mfc 提供carchive類實現資料的緩衝區讀寫,同時定義了類物件的儲存與讀取方案。 以下對carchvie 的內部實現作分析。
1.概述
2.內部資料
3.基本資料讀寫
4.緩衝區的更新
5.指定長度資料段落的讀寫
6.字串的讀寫
7.cobject派生物件的讀寫
一.概述
carchive使用了緩衝區,即一段記憶體空間作為臨時資料儲存地,對carchive的讀寫都先依次排列到此緩衝區,當緩衝區滿或使用者要求時,將此段整理後的資料讀寫到指定的儲存煤質。
當建立carchive物件時,應指定其模式是用於緩衝區讀,還是用於緩衝區寫。
可以這樣理解,carchive物件相當於鐵路的貨運練排程站,零散的貨物被收集,當總量到達火車運量的時候,由火車裝運走。
當接到火車的貨物時,則貨物由被分散到各自的貨主。與貨運不同的是,交貨、取貨是按時間循序執行的,而不是憑票據。因此必須保證送貨的和取貨的貨主按同樣的循序去存或取。
對於大型的貨物,則是拆散成火車單位,運走,取貨時,依次取各部分,組裝成原物。
二.內部資料
緩衝區指標 byte* m_lpbufstart,指向緩衝區,這個緩衝區有可能是底層cfile(如派生類cmemfile)物件提供的,但一般是carchive自己建立的。
緩衝區尾部指標 byte* m_lpbufmax;
緩衝區當前位置指標 byte* m_lpbufcur;
初始化時,如果是讀模式,當前位置在尾部,如果是寫模式,當前位置在頭部:
m_lpbufcur = (isloading()) ? m_lpbufmax : m_lpbufstart;
三.基本資料讀寫
對於基本的資料型別,例如位元組、雙字等,可以直接使用">>"、"<<"符號進行讀出、寫入。
//操作符定義捕:
//插入操作
carchive& operator<<(byte by);
carchive& operator<<(word w);
carchive& operator<<(long l);
carchive& operator<<(dword dw);
carchive& operator<<(float f);
carchive& operator<<(double d);
carchive& operator<<(int i);
carchive& operator<<(short w);
carchive& operator<<(char ch);
carchive& operator<<(unsigned u);
//提取操作
carchive& operator>>(byte& by);
carchive& operator>>(word& w);
carchive& operator>>(dword& dw);
carchive& operator>>(long& l);
carchive& operator>>(float& f);
carchive& operator>>(double& d);
carchive& operator>>(int& i);
carchive& operator>>(short& w);
carchive& operator>>(char& ch);
carchive& operator>>(unsigned& u);
下面以雙字為例,分析原碼
雙字的插入(寫)
carchive& carchive::operator<<(dword dw)
雙字的提取(讀) carchive& carchive::operator>>(dword& dw)
四.緩衝區的更新
以上操作中,當緩衝區將插入滿或緩衝區將提取空時,都將對緩衝區進行更新處理。
緩衝區將插入滿時呼叫flush(); void carchive::flush()
else //寫模式
else
m_lpbufcur = m_lpbufstart; //指向緩衝區首
} }
緩衝區將提取空,會呼叫fillbuffer。 nbytesneeded為當前剩餘部分上尚有用的位元組void carchive::fillbuffer(uint nbytesneeded)
// read to satisfy nbytesneeded or nleft if possible
uint nread = nunused;
uint nleft = m_nbufsize-nunused;
uint nbytes;
byte* lptemp = m_lpbufstart + nunused;
do
while (nbytes > 0 && nleft > 0 && nread < nbytesneeded);
m_lpbufcur = m_lpbufstart;
m_lpbufmax = m_lpbufstart + nread;
} }
else
// not enough data to fill request?
if ((ulong)(m_lpbufmax - m_lpbufcur) < ntotalneeded)
afxthrowarchiveexception(carchiveexception::endoffile);
} 五.指定長度資料段落的讀寫
以下分析
uint read(void* lpbuf, uint nmax); 讀取長度為nmax的資料
void write(const void* lpbuf, uint nmax); 寫入指定長度nmax的資料
對於大段資料的讀寫,先使用當前緩衝區中的內容或空間讀取或寫入,若這些空間夠用了,則結束。
否則,從剩餘的資料中找出最大的緩衝區整數倍大小的一塊資料,直接讀寫到儲存煤質(不反覆使用緩衝區)。
剩餘的餘數部分,再使用緩衝區讀寫。
(說明:緩衝區讀寫的主要目的是將零散的資料以緩衝區大小為尺度來處理。對於大型資料,其中間的部分,不是零散的資料,使用緩衝區已經沒有意思,故直接讀寫)
①讀取
uint carchive::read(void* lpbuf, uint nmax)
while ((nbytes > 0) && (nleft > 0)); 知道讀入了預定大小,或到達檔案尾
nmaxtemp -= nread;
if (nread == ntemp) //讀入的位元組等於讀入的整數倍部分 該讀最後的餘數部分了
while ((nbytes > 0) && (nleft > 0) && nread < nmaxtemp);
m_lpbufcur = m_lpbufstart;
m_lpbufmax = m_lpbufstart + nread;
} else
//讀出此剩餘部分到輸出
ntemp = min(nmaxtemp, (uint)(m_lpbufmax - m_lpbufcur));
memcpy(lpbuf, m_lpbufcur, ntemp);
m_lpbufcur += ntemp;
nmaxtemp -= ntemp;
} }
return nmax - nmaxtemp;
} ②儲存,寫入 void carchive::write(const void* lpbuf, uint nmax)
// copy remaining to active buffer
assert(nmax < (uint)m_nbufsize);
assert(m_lpbufcur == m_lpbufstart);
memcpy(m_lpbufcur, lpbuf, nmax);
m_lpbufcur += nmax;
} }
hashmap實現機制
int uint key.gethashcode 0x8ffffff 具體多少忘記了,總之就是把它弄成正數 int index uint map.length 把value放到那個 index位置。下次訪問時再通過 key的hashcode 0x8fffff 再 map.length 就知道valu...
KVM 實現機制
kvm管理介面 qemu和 kvm關係很深,甚至可以認為雙方本來是乙個軟體,qemu 是應用層的控制部分,而 kvm是核心執行部分。軟體復用能達到如此天衣無縫的地步,是一件很神奇的事情,也說明 kvm設計時候的思路之巧。所以分析kvm 必須首先從 qemu 的 分析入手。為了避免繁瑣,引入太多知識點...
const實現機制
c語言以及c 語言中的const究竟表示什麼?其具體的實現機制又是如何實現的呢?本文將對這兩個問題進行一些分析,簡單解釋const的含義以及實現機制。簡單的說const在c語言中表示唯讀的變數,而在c 語言中表示常量。關於const在c與c 語言中的使用以及更多的區別,以後有時間另開一貼說明。那麼c...