MFC CArchive實現機制

2021-06-16 00:32:04 字數 4005 閱讀 6496

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...