classABI_EXPORTUT_GenericStringMap{//嵌套類UT_Cursor{…}//代表實際存儲的容器ha" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

abiWord中數據的存儲

系統 1875 0

abiWord中數據的存儲

第一部分:abiWord中數據的存儲
一、哈希表是根據一定的算法在表中的相應位置存儲數據的一種容器,在abiWord程序中這個表相當于一個數組。下面列出了ABIWORD哈希表的構成.在列舉出表的構成之后,對于構成哈希表的各個組成部分分別進行說明.
1、abiWord中的哈希表
template <class T>
class ABI_EXPORT??? UT_GenericStringMap
{
//嵌套類
UT_Cursor
{
?????? …
}
//代表實際存儲的容器
hash_slot<T> * m_pMapping;
};
?
//哈希表中鍵的封裝類
class key_wrapper
{
private:
?????? UT_String???? m_val;????????????????? //鍵
?????? UINT??????????? m_hashval;?????????? //鍵的哈希值
};
?
// 數據的槽
template<class T>
class hash_slot
{
…………
?????? T???? m_value;
?????? key_wrapper m_key;
};
?
以上就是一上哈希表的構成我們可以看出從大的結構上看,有四個部分:
1、主要類UT_GenericStringMap<class T>:這個類主要實現了基本的哈希表的算法如查找,插入、刪除等。
2、UT_Cursor:這個類主要是用來遍歷哈希表的,我們可以把它理解為一個迭代器.
3、Key_wrapper:這個類是哈希表中鍵的封閉類,相當于一個字符串,它內部包含一個相應于該鍵值(字符串)的哈希值。
4、Hash_slot<class T>這個類用來表示哈希表中存儲的鍵 / 值對,可以理解為哈希表中所存儲的元素類型(類型是鍵 / 值對).
注:對于上面的這個數據模型,其實是哈希表與映射表的結合.對于這個類更具體的說明請參考UT_GenericStringMap<T>類

UT_GenericStringMap<T>類是一個映射表類
數據成員
private:???
hash_slot<T> * m_pMapping;
??? size_t???? n_keys;
??? size_t???? n_deleted;
??? size_t???? m_nSlots;
??? size_t???? reorg_threshold;
??? size_t???? flags;
?
??? char?? ** m_list;
這個類的友元類??? hash_slot<T>,顧名思義,hash_slot<T>是一個(哈希槽)模板類,是UT_GenericStringMap<T>的一個成員,所以類型參數T由傳給UT_GenericStringMap<T>的T類型參數決定。
hash_slot<T>的成員
public:
T?? m_value;
??? key_wrapper?? m_key;
?
1、UT_Cursor類(游標)
這個類是UT_GenericStringMap<T> 的內嵌友元類,它只有一個成員即
private:
const UT_GenericStringMap<T> * m_d;
int?????????? m_index;??????????????
這個函數成員函數:
inline?????? const UT_String & key()
{
return m_d->_key(*this);
}
?
inline?????? void make_deleted()
{
m_d->_make_deleted(*this);
}
inline?????? const T first()
{
return m_d->_first(*this);
}
?
inline?????? const T next()
{
return m_d->_next(*this);
}
inline?????? const T prev()
{
return m_d->_prev(this);
}
inline?????? bool is_valid()
{
return (m_index != -1);
}
???????
private:
inline?????? void _set_index(int i )
??? {
m_index = i;
??? }
inline?? int _get_index()
??? {
return m_index;
??? }
可以看出這個類的公有成員函數:
const UT_String & key()調用其成員UT_GenericStringMap<T> m_d的相應成員函數 _key(*this);并以其自身this指針為參數.
void make_deleted()調用其成員UT_GenericStringMap<T> m_d的相應成員函數m_d->_make_deleted(*this);并以其自身this指針為參數.
const T first();調用其成員UT_GenericStringMap<T> m_d的相應成員函數m_d->_first(*this);并以其自身this指針為參數.
const T next();調用其成員UT_GenericStringMap<T> m_d的相應成員函數m_d->_next(*this);并以其自身this指針為參數.
const T prev();調用其成員UT_GenericStringMap<T> m_d的相應成員函數m_d->_prev(*this);并以其自身this指針為參數.
bool?? is_valid();只是判斷m_index成員是否等于-1,如果等于-1則是無效的,否則是有效的。
_set_index(int i )和_get_index()分別是設置和獲取m_index成員的值。
?
2、key_wrapper
這個類封閉了一個字符串類UT_String ;其成員包括:
private:
??? UT_String m_val;??????? //一個字符串類
??? UINT?????? m_hashval;??? //該字符串的散列值
成員函數:
Public:
void?? die()?
??? {
?????? m_val.clear();
??? }
????
??? bool?? eq(const?? char * key)
??? {
return (m_val == key);
??? }
?
bool?? eq(const UT_String & key)const
??? {
return (m_val == key);
??? }
?
void??? operator=(const UT_String & k)
??? {
m_val = k;
??? }
UINT hashval()const
??? {
return m_hashval;
??? }
????
void??? set_hashval(UINT?????? h)
??? {
m_hashval = h;
??? }
?
UT_String & value()
??? {
return m_val;
??? }
?
void??? operator=(const key_wrapper & rhs)
??? {
m_val = rhs.m_val;
m_hashval = rhs.m_hashval;
??? }
?
static UINT???? computer_hash(const UT_String & key)
??? {
return??? hashcode(key);
??? }
static UINT???? compute_hash(const char * key)
??? {
return hashcode(key);
??? }
可以看出基本操作都是針對UT_String類型進行操作。
Void?? die();調用UT_String::Clear()清空緩沖區。
?
Bool?? eq(const?? char * key);調用UT_String::operator==(char * key);判斷UT_String成員m_val是否和參數相等。
?
bool?? eq(const UT_String & key)const重載版本參數為UT_String類型的常量引用。
?
void?? operator=(const UT_String & k);以參數對成員m_val賦值.
?
UINT?? hashval()const; 返回成員m_hashval的值.
?
void?? set_hashval(UINT h);設置成員m_hashval的值.
?
UT_String & value();返回成員m_val的值。
void?? operator=(const key_wrapper & rhs);以參數對兩個成員賦值.
?
static UINT?? computer_hash(const UT_String & key);
static UINT?? compute_hash(const char * key);
?
兩個重載函數,都是調用全局函數hashcode();
3、hash_slot<T>
哈希槽:
成員變量:
T?? m_value;
key_wrapper?? m_key;
?
成員函數:
void make_deleted()
{
m_value = reinterpret_cast<T>(this);
m_key.die();
}
????
void make_empty()
{
m_value = 0;
}
const T?? value() const {return m_value;}
void?? insert(const T v , const UT_String & k ,UINT h)
{
m_value = v;
m_key = k;
m_key.set_hashval(h);
}
void assign(hash_slot<T> * s)
{
m_value = s->value();
m_key = s->m_key;
}
bool empty()const
{
return (m_value == 0);
}
bool deleted()const
{
return static_cast<const void *>(this) == m_value;
}
?
?
成員T m_value和key_wrapper m_key,就代表了在UT_GenericStringMap<T> 中存儲的兩個東西,一個是實值m_value,另一個是鍵值m_key;
?
bool?? key_eq(const UT_String & test , size_t)const
{
return m_key.eq(test);
}
bool key_eq(const char * test , size_t h)const
{
return m_key.eq(test);
}
?
4、UT_GenericStringMap<T>類的說明:
UT_GenericStringMap<T>類代表了一個映射表類,它內嵌一個UT_Cursor類,同時以一個hash_slot<T> 類型作為它的一個成員。
template <class T> hash_slot<T>*
UT_GenericStringMap<T>::find_slot(const char *k,
????????????????? SM_search_type??? search_type,
????????????????? size_t&?????????? slot,
????????????????? bool&???????? key_found,
????????????????? size_t&?????????? hashval,
????????????????? const void*?????? v,
????????????????? bool*???????? v_found,
????????????????? void*???????? vi,
????????????????? size_t???? hashval_in) const
{
這個函數參數的說明
SM_search_type?????????? search_type //一個枚舉類型的值,可以是SM_LOOLUP,SM_INSERT,SM_REORG.
Size_t & slot,哈希槽,即位置
Bool?? &?? key_found, 輸出參數,是否發現了這個鍵
Size_t &?? hashval, 哈希值
Const void * v,實值
Bool?? v_found,實值是否被發現。
Void?? * vi,
Size_t hashval_in, 輸入的哈希值。
?
二、用來存儲屬性/樣式的類PP_AttrProp PP_AttrProp的基本定義如下:
class ABI_EXPORT PP_AttrProp
{
public:
//char ** 像main()函數中的argv ,它包含了名子/值對的多重設置,
//名字是在偶數單元 ; 值是在體奇數單元 , 列表是通過一個null名字終止
……
?????? bool?????? setAttributes(const?????? char ** attributes);???????
?????? bool??? setAttributes(const UT_GenericVector<char*> * pVector);
?
?????? bool?????? setProperties(const char ** properties);
?????? bool?????? setProperties(const UT_GenericVector<char*> * pVector);
?????? ……??????
?
//主要的數據定義
typedef UT_Pair<const char*,const PP_PropertyType *> PropertyPair;
UT_GenericStringMap<char*> * m_pAttributes; // of char*
UT_GenericStringMap<PropertyPair*> * m_pProperties; // of PropertyPair
?????? bool??????????????????????????? m_bIsReadOnly;
?????? UT_uint32?????????????????? m_checkSum;
?????? UT_uint32?????????????????? m_index;?????? //$HACK??????
};
從這個類的定義中我們可以找出幾個關鍵的數據類型:
1、typedef??? UT_Pair<const???? char *???? , PP_PropertyType *> PropertyPair;
這個typedef語句的作用也就是以類型參數 const???????????? char *和PP_PropertyType*實例化一個類模板.之后PropertyPair就代表了UT_Pair<const?? char * ,PP_PropertyType *>這種類型.
2、UT_GenericStringMap<PropertyPair *>????????? m_pProperties;聲明了一個對象,這個對象是一個哈希表,并且這個這個哈希表中所存儲的元素類型為PropertyPair類型的指針.

?
UT_GenericStringMap<PropertyPair*>*m_pProperties;(哈希表)
內部有hash_slot類型的指針用來存儲鍵/值對?
以字節為單位的文本數據?


template <class T, class U>
class?????? UT_Pair
{
?????? …

private:
const????? T m_first;
const????? U m_second;
}
這是一個模板類.
PP_AttrProp中又有這樣的聲明:
typedef UT_Pair<const char*,const PP_PropertyType *> PropertyPair;
這個類型定義語句,定義了一個新的類型即把UT_Pair類模板的模板參數設置為const char * ,和const PP_PropertyType *;


3、UT_GenericStringMap<char *> m_pAttributes. 聲明了一個對象,這個對象是一個哈希表,并且這個哈希表中所存儲的元素類型為char *.再看template<class T> class hash_slot類模板,它里面有一個模板參數 T m_value.這時我們就更加能夠看明白,在哈希表中所存儲的內容了.
OK,至此我們可以看出,PP_AttrProp類中有個哈希表的數據成員,而這個哈希表就是解析出關鍵字的以及關鍵字所對應的值的存儲地。而PP_AttrProp中所有的方法即成員函數無非是對這個哈希表進行操作如設置一個PP_AttrProp類型對象的值即填充內容。對哈希表中值進行查找等等。在這里先說明一下,其實一個PP_AttrProp就代表了一個相同類型的屬性集合,也就是說,同一個事物的各種屬性的一個集合,針對RTF文件,我們知道,文本是構成RTF文件的一種數據元素,而針對一段文本,它必定要有字體屬性,字體屬性包括如字號,字體顏色,字體字符集等不同特征,而這一個PP_AttrProp即是這個字體的所有特征的一個集合。對于Word中的RTF文件它有section(節),我們也可以把考慮為一種數據類型。
那么這個PP_AttrProp既然是構成RTF文件的同種類型數據(在這里數據指的是實際的文件內容比如”文本”,RTF中的”圖像數據”,以及”表格”、”頁?”、”頁腳”等等)的各種屬性的集合,它本身在abiWord這個項目中充當何種角色呢?繼續往上走我們看到了pp_TableAttrProp這個類。
二、pp_TableAttrProp:
首先給出類的基本定義。
class ABI_EXPORT pp_TableAttrProp
{
public:
……
……
?????? bool?????????????????????????????????? addAP(PP_AttrProp * pAP,
???????????????????????????????????????????????????????? UINT * pSubscript);
?????? bool?????????????????????????????????? createAP(UINT * pSubscript);
?
?????? bool?????????????????????????????????? createAP(const char ** attributes,
??????????????????????????????????????????????????????????????? const char ** properties,
??????????????????????????????????????????????????????????????? UINT * pSubscript);
?
?????? bool?????????????????????????????????? createAP(const UT_GenericVector<char*>* pVector,
??????????????????????????????????????????????????????????????? UINT * pSubscript);
?
?????? bool?????????????????????????????????? findMatch(const PP_AttrProp * pMatch,
??????????????????????????????????????????????????????????????? UINT * pSubscript) const;
???????
?????? const PP_AttrProp *????????? getAP(UINT subscript) const;
?????? void???????????????????????????? ReleaseVec();
?
protected:
UT_GenericVector<PP_AttrProp *> m_vecTable;
UT_GenericVector<PP_AttrProp *>???? m_vecTableSorted;
};
先看數據成員,只有兩個:
1、UT_GenericVector<PP_AttrProp *> m_vecTable;
2、UT_GenericVector<PP_AttrProp *> m_vecTableSorted;
很明顯是兩個向量即vector,在這里我們可以把它看成數組,數組的元素類型是PP_AttrProp對象的指針。
由此我們可以抽象出:
pp_TableAttrProp代表一個數組,(盡管它內部有兩個vector,我們先不考慮m_vecTableSorted)數組中的元素類型是PP_AttrProp對象的指針。根據組成RTF文件的結構,我們知道,一個PP_AttrProp可能是一段文本字體的特征集合(以后統稱屬性),也可以是section(節)的屬性,或者是paragraph(段落)的屬性,當然還有其它的屬性。總之不管是什么東西的屬性,我們就以一個PP_AttrProp來表示一個事物(以后統稱數據元素)的所有屬性的集合。PP_AttrProp本身可以看成是一個哈希表。至此我們知道PP_AttrProp是一個哈希表,一個哈希表中存放的是RTF文件中某種具有相同屬性的數據元素塊的屬性集合。比如一段具有相同屬性的文本。它的所有屬性就用一個PP_AttrProp來描述。而pp_TableAttrProp則是元素類型為PP_AttrProp對象指針的一個數組。自然數組中的元素可以描述一段文本的屬性、一個段落的屬性或者是一個section的屬性。簡而言之,pp_TableAttrprop是一個數組,數組中的元素類型是一個哈希表。
備注:(引自abiWord程序代碼的注釋)pp_TableAttrProp實現了一個無限大的pp_AttrProp對象的表,每一個PP_AttrProp代表了文檔的一個或多個片斷的完整的Attribute/Property狀態
通過程序代碼我們會發現這個pp_Attrprop本身又被包含在一個pt_VarSet的類中,下面我們來看看這個類。
三、pt_VarSet類的說明:
class ABI_EXPORT pt_VarSet
{
public:
……??????
……
//如果pts == PTS_Editing m_currentVarSet = 1;
void???????????????????????????? setPieceTableState(PTState pts);
//將pBuf到緩沖區bool?? appendBuf(const UINT *pBuf , UINT length , UINT * pbi);
?????? //
?????? bool?????????????????????????????????? storeAP(const char ** attributes, UINT * papi);
?????? bool?????????????????????????????????? storeAP(const UT_GenericVector<XML_Char*>* pVecAttributes, PT_AttrPropIndex * papi);
?
?????? //
?????? const UT_UCSChar *??????? getPointer(PT_BufIndex bi) const ;
???????
?????? PT_BufIndex????????????????????? getBufIndex(PT_BufIndex bi, UT_uint32 offset) const;
?
??????????????
?????? const PP_AttrProp *????????? getAP(PT_AttrPropIndex api) const;
private:
UINT _subscriptFromBufIndex(PT_BufIndex bi) const;
UT_uint32 _subscriptFromAPIndex(PT_AttrPropIndex api) const;
UT_uint32 _varsetFromBufIndex(PT_BufIndex bi) const;
inline UT_uint32 _varsetFromAPIndex(PT_AttrPropIndex api) const; inline PT_AttrPropIndex _makeAPIndex(UT_uint32 varset, UT_uint32 subscript) const;
?????? bool?????????????????????????????????? _finishConstruction(void);
?
?????? bool?????????????????????????????????? m_bInitialized;
?????? UT_uint32????????????????????????? m_currentVarSet;
?
//下面這兩個數組變量的類型是兩個對象,每個數組的大小為2,那么下標0代表裝入文檔的
//文本數據,下標1代表編輯時插入的數據.
?????? UT_GrowBuf??????????????????????????? m_buffer[2];
?????? pp_TableAttrProp????????????? m_tableAttrProp[2];
};
先看數據成員:
UT_GrowBuf???????????????????? m_buffer[2];
pp_TableAttrProp????????????? m_tableAttrProp[2];
結合程序代碼的分析。我們可以這樣理解。在pt_VarSet這個類中m_buffer用來存儲RTF文件中的文本即字符,m_tableAttrProp用來存儲RTF文件中不同屬性的數據元素的屬性表即哈希表。在這里數據元素代表文本、段落或者是section等等。至此我們可以看出如果對于一個RTF文件來說,其主要的數據存儲位置我們基本上已經可以確定了。
備注:對于圖像文件來說,它的圖像數據存儲是否也在這個m_buffer中,還有待進一步考證。當然如果是在這個m_buffer中,也可以實現。

m_buffer[0]即UT_GrowBuf?
說明:至于m_buffer和m_tableAttrprop數組的大小均為2,原因是0代表讀取的數據,1代表編輯時插入的數據。具體到這兩個數據成員上m_buffer[0]中存儲的是從RTF文件中讀取的數據,m_buffer[1]中存儲的是用戶在編輯階段插入到文件中的數據。m_tableAttrprop[0]存儲的是從文件中讀取的數據元素的屬性。m_tableAttrProp[1]中存儲的是用戶在編輯階段插入的數據元素的屬性。

?

m_tableAttrProp[0]中所存儲的內容pp_TableAttrProp?
m_vecTable[0]類型為UT_GenericVector,相當于數組
?
0號元素:PP_AttrProp *(某個section屬性)
?
? 1號元素段落屬性
?
?
…………
省略 2號元素文本屬性
?
?
…………
省略

?
第二部分:abiWord中數據的關聯.
對這一部分的說明,采取主要以數據類型為”文本”的特例來說明.
一、pf_Frag類的說明
******************************************************************************ppf_Frag代表了一個文檔片斷, 這可以是文本 (pf_Frag_Text),
一個內置對象如一個圖像(pf_Frag_object) ,或者結構信息例如
一個段落或章節(pf_Frag_Strux_Block , pf_Frag_Strux_Section)
pf_Frag是一個抽象基類,我們使用一個枚舉成員類型,勝于使用
任何運行時原料
*******************************************************************************class ABI_EXPORT pf_Frag
{
public:
typedef enum _PFType {PFT_Text = 0 , PFT_Object , PFT_Strux , PFT_EndOfDoc , PFT_FmtMark}PFType;
pf_Frag(pt_PieceTable * pPT , PFType type , UINT?? length); virtual ~pf_Frag();
//返回pf_Frag所代表的類型,正如上面的結構體所描述的類型.
inline?????? PFType????????? getType(void)const {return??? m_type;}
//從下面這個函數的功能(返回自身類型的指針,可以看出,這個對象可能被用于鏈表等數據存儲方式)
//這個功能有助于類似鏈表的數據結構進行查找和遍歷.
?????? inline?????? pf_Frag *???? getNext(void)const????? {return m_next;}
?????? inline?????? pf_Frag *???? getPrev(void)const {return m_prev;}
?
?????? pf_Frag *??????????????????? setNext(pf_Frag * pNext);
?????? pf_Frag *??????????????????? setPrev(pf_Frag * pPrev);
?
?????? inline?????? UINT???? getLength(void)const {return m_length;}
?????? pt_PieceTable *??? getPieceTable() {return m_pPieceTable;}
?
?????? fd_Field *???? getField();
?????? PT_DocPosition?? getPos(void) const?????? {return m_docPos;}
?????? void?????????????? setPos(PT_DocPosition????? pos)const{m_docPos = pos;}
?
//這個序號是代表Attr/Prop的序號,Attr/Prop存儲在一個vector中
?????? inline????????????? PT_AttrPropIndex?????? getIndexAP(void) const {return m_indexAP;}
?????? virtual??????????? void setIndexAP(PT_AttrPropIndex indexNewAP){m_indexAP = indexNewAP;}
?
//比較兩個fragments的內容,忽略格式
?????? bool????????????? isContentEqual(const pf_Frag & f2)const;
???????
?????? UINT??????????? getXID()const {return m_iXID;}
?????? void??????? setXID(UINT?????? xid){m_iXID = xid;}
?
// I would much prefer if this was a pure vitual, but we do not have Eod frag
virtual bool??????????? usesXID() const {return false;}
// compare contents and format of two fragments
bool operator == (const pf_Frag & f2) const;
?
protected:
?????? virtual???? bool????????????? _isContentEqual(const pf_Frag & f2)const {return true;}
?
?????? PFType????????????????????????????? m_type;???????? //該fragment所代表的類型
?????? UINT???????????????????????????????? m_length;?????? //大小
?
?????? pf_Frag *????????????????????????? m_next;???????? //下一個
?????? pf_Frag *????????????????????????? m_prev;???????? //上一個
?
?????? fd_Field *????????????????????????? m_pField;
?????? pt_PieceTable *????????????????? m_pPieceTable;
?????? PT_AttrPropIndex???????????????????? m_indexAP;
?
private:
?????? mutable PT_DocPosition?? m_docPos;
?????? UINT???????????????????????????????? m_iXID;?
};
這個類是所有pf_Frag_xxxx派生類的基類,從它內部的數據成員我們可以看出它存儲于一個鏈表類型的數據結構中,這個類代表代表了一個文檔片斷, 這個片斷可以是文本 (pf_Frag_Text)、一個內置對象如一個圖像(pf_Frag_object) ,或者結構信息例如一個段落或章節(pf_Frag_Strux_Block , pf_Frag_Strux_Section)。那么它是如何把一個數據片斷與這個數據片斷所對應的屬性相對應起來的呢 ? 我們從它內部的數據成員PT_AttrPropIndex m_indexAP和 PT_DocPosition??????????? m_docPos;這兩個變量身上似乎可以找到答案。第一個代表屬性表在緩沖區的索引,第二個是它在文檔中的位置。因為這個類是所有pf_Frag_XXX類的基類,所以如果針對一個文本,我們并不能從中看出它的對應關系。因為不管哪個派生類,只要你是RTF文件的數據元素,那么你都有屬性,所以屬性序號即PT_AttrPropIndex是所有派生類必須有的。所以把這個定義在了基類。至于PT_DocPosition,我們可以看出它為私有成員,那么派生類是無法訪問到的。這個變量代表文檔的絕對位置。可以猜想是用來為寫文件準備的的。暫時不關心。接下來我們看它的一個派生類:代表文本片斷的pf_Frag_Text.
二、pf_Frag_Text類的說明:
/******************************************************************************
pf_Frag_text代表了文檔的文本片斷,
注意它沒有包含一個PT_DocPostion,文本片斷不知道這是在文檔中;
它只知道它的緩沖區位置
class?????? ABI_EXPORT pf_Frag_Text : public???? pf_Frag
{
public:
?????? pf_Frag_Text(pt_PieceTable??????????????????? * pPT,
?????????????????????????????????????????? UINT???????????????? bufIndex,
?????????????????????????????????????????? UINT???????????????? length,
?????????????????????????????????????????? UINT???????????????? indexAP,
?????????????????????????????????????????? fd_Field????????????? * m_pField);
?
?????? virtual??????????? ~pf_Frag_Text();
???????
endFragOffset}const;
inline PT_BufIndex getBufIndex(void) const
?????? {
return m_bufIndex;
?????? }
???????
?????? void?????????????? changeLength(UINT??? newLength);?
?????? void?????????????? adjustOffsetLength(PT_BufIndex????? bi , UINT????? newLength);
?????? void?????????????? setField(fd_Field?? * pField);
?
?????? virtual??????????? bool?????? usesXID() const {return false;}
protected:
?????? virtual??????????? bool?????? _isContentEqual(const pf_Frag & f2)const;
?????? UINT??????????? m_bufIndex;
};
?
一眼就能看出最后一個數據成員的定義UINT???????? m_bufIndex;顧名思義,緩沖區的索引。這就是在pt_VarSet中m_buffer[0]中的索引,聯系到這個類的基類pf_Frag中的PT_AttrPropIndex?????????????????? m_indexAP;定義,我們已經找到了文本數據與它的屬性的聯系方式,通過一個pf_Frag對象來保存。
下面對pf_Frag的其它派生類進行簡要說明:
在pf_Frag中定義了一個枚舉類型的數據類型:
typedef enum _PFType {PFT_Text = 0 , PFT_Object , PFT_Strux , PFT_EndOfDoc , PFT_FmtMark}PFType;
PFT_Test:文本
PFT_Object:對象如圖片
PFT_Strux:Strux類型,所有從pf_Frag_Strux派生的類.
PFT_EndOfDoc:暫時不予討論.
PFT_FmtMark:暫時不予討論.
?
我們主要討論pf_Frag_Strux這個類
三、pf_Frag_Strux類的說明:
pf_Frag_Strux代表了文檔中的結構信息(例如一個段落或章節).
pf_Frag_Strux從pf_Frag派生,但它也是一個基類,
pf_Frag_strux_Block和pf_Frag_Strux_Section從它派生.
我們使用一枚舉以記住Strux的類型。
?
class ABI_EXPORT?????? pf_Frag_Strux : public pf_Frag
{
public :
pf_Frag_Strux(pt_PieceTable * pPT,
???????????????????????????? PTStruxType??? struxType,
???????????????????????????? UINT length,
???????????????????????????? PT_AttrPropIndex?? indexAP);
?
?????? virtual????????????????????????? ~pf_Frag_Strux();
?????? PTStruxType??????? getStruxType(void) const;
?????? const????? void *??????????? getFmtHandle(UINT lid)const;
?????? bool??????????????????????????? setFmtHandle(UINT??? lid , const void * sfh);
?
?????? virtual??????????? bool?????? usesXID()const;
?????? bool??????????????????????????? isMatchingType(PTStruxType e)const;
?????? bool??????????????????????????? isMatchingType(const pf_Frag * p)const;
?
protected:
?????? virtual???? bool??????????? _isContentEqual(const pf_Frag & f2)const;
?????? PTStruxType??????? m_struxType;
?????? UT_Vector????????????????? m_vecFmtHandle;
};
?
PTStruxType???????? m_struxType;這個定義了一種類型,即該Strux對象所代表的類型它的定義如下:
//PTStruxType標識了FragStrux的子類型
typedef enum _PTStruxType
{
?????? PTX_Section = 0,????????????? // 0???????? section(節)
?????? PTX_Block,?????????? // 1???????? paragraph(段落)
?????? PTX_SectionHdrFtr,????????????? // 2???????? (頁眉頁腳)
?????? PTX_SectionEndnote,??????????? // 3???????? (腳注)
?????? PTX_SectionTable,?????????????? // 4
?????? PTX_SectionCell,???????????????? // 5
?????? PTX_SectionFootnote,???????????? // 6
?????? PTX_SectionMarginnote, // 7
?????? PTX_SectionFrame,??????????? // 8
?????? PTX_SectionTOC,??????????????????? // 9
?????? PTX_EndCell,???????????????? // 10
PTX_EndTable,
PTX_EndFootnote,
PTX_EndMarginnote,
PTX_EndEndnote,
PTX_EndFrame,
PTX_EndTOC,
PTX_StruxDummy
} PTStruxType;
那么所有的pf_Frag_Strux的派生類所代表的類型均以在這個枚舉型的數據中列出. 下面列出了pf_Frag_Strux_Section類的定義:
一個pf_Frag_Strux_Section代表文檔中一個節(區域)的結構信息。
?
class ABI_EXPORT pf_Frag_Strux_Section : public pf_Frag_Strux
{
public:
pf_Frag_Strux_Section(pt_PieceTable * pPT , PT_AttrPropIndex indexAP);
virtual ~pf_Frag_Strux_Section();
};
由這個類的定義可以看出,是非常簡單的。它只是簡單的繼承了基類的數據成員和方法,自己本身并沒有新的數據成員和方法。也就是說父類的數據成員足以描述一個文檔中的節(區域)。
?
同樣,其它由pf_Frag_Strux派生的類,分別代表組成文檔的不同數據元素。在這里就不一一列出了。
既然pf_Frag類的派生類是鏈表的一個節點,那么它肯定要有一個鏈表類來管理這些節點,實現對這些節點一些操作如排序、插入、刪除、查找等等。在abiWord中的這個鏈表類是pf_Fragments類,下面我們了解一下這個類的定義:
首先給出定義:
四、pf_Fragments類的說明:
class?????? ABI_EXPORT???? pf_Fragments
{
public:
?????? pf_Fragments();
?????? ~pf_Fragments();
?
?????? void????????????????????? appendFrag(pf_Frag * pf);
?????? void????????????????????? insertFrag(pf_Frag?????? * pfPlace , pf_Frag????? * pfNew);
?????? void????????????????????? insertFragBefore(pf_Frag * pfPlace , pf_Frag * pfNew);
?????? void????????????????????? unlinkFrag(pf_Frag * pf);
?????? void????????????????????? cleanFrags(void) const;
?
?????? pf_Frag?????????????????????? * getNthFrag(UINT??? nthFrag)const;
?????? pf_Frag?????????????????????? * findFirstFragBeforePos(PT_DocPosition)const;
?
?????? UINT????????????????????????? getNumberOfFrags()const;
?????? UINT????????????????????????? getFragNumber(const pf_Frag * pf)const;
?
?????? pf_Frag?????????????????????? * getFirst()const;
?????? pf_Frag?????????????????????? * getLast()const;
?
?????? void????????????????????? setFragsDirty(void){ m_bAreFragsClean = false;}
?????? bool??????????????????????????? areFragsDirty () const {return !m_bAreFragsClean;}
?
#ifdef????? PT_TEST
?????? void????????????????????? __dump(FILE????? * fp)const;
#endif
?
private:
?????? inline?????? pf_Frag *????? getCache() const {return m_pCache;}
?????? inline?????? void??????? setCache(pf_Frag * pf) const {m_pCache = pf;}
?
?????? pf_Frag?????????????????????? * m_pFirst;
?????? pf_Frag?????????????????????? * m_pLast;
?
?????? mutable UT_Vector m_vecFrags;
?????? mutable bool??????????? m_bAreFragsClean;
?????? mutable pf_Frag???????? * m_pCache;
};
通過分析pf_Fragments類的定義,我們可以看出,pf_Fragmenst只是實現了鏈表的基本操作,但需要注意的是由于pf_Fragments中的節點類型是pf_Frag類型的指針,而在pf_Frag的類定義中有一個 PT_DocPosition?????????? m_docPos;變量的定義,這個變量是文檔位置,所以它實現了對于文檔位置的查找,比如說給出一個文檔位置,要找到包含這個文檔位置的片斷即pf_Frag。pf_Frag * pf_Fragments::findFirstFragBeforePos(PT_DocPosition pos) const;這個函數就是為此目的而實現的,但這個函數寫的不是很好。
?????? 同時我們可以看出,在pf_Fragments鏈表類中有一個 UT_Vector??????? m_vecFrags;數據成員的定義,估計是專門用來為輸出到文件準備的,pf_Fragments對這個成員的操作主要包括排序、查找某個pf_Frag 類型的指針在m_vecFrags中的索引等等。并且pf_Fragments有一個專門的CleanFrags( )函數,用來對把在pf_Fragments中按一定順序(文檔順序)鏈接的節點順序添加到m_vecFrags中,CleanFrags( )這個函數的作用就是使m_vecFrags中的節點的順序和pf_Fragments中節點的鏈接順序相一致,我們可以想象這可能會在編輯文檔時使用,因為用戶編輯文檔時,它在文檔中插入數據的位置是隨機的,并不是只在尾部或其它固定位置插入數據,這就導致了在pf_Fragments中插入節點時要以文檔的排版順序來插入,那么m_vecFrags中節點的存放順序也必須和鏈表的鏈接順序相一致,CleanFrags( )函數的作用就是為此目的的。
?
?????? 在abiWord中用來遍歷pf_Fragments鏈表時用一個專門的迭代器來實現,這個迭代器以一個類來表示,類名為PD_DocIterator:下面給出這個類的定義和說明:
?
五、PD_DocIterator類的說明:
class ABI_EXPORT PD_DocIterator : public UT_TextIterator
{
public:
???????????????? //兩個參數分別是文檔類的引用和文檔位置
?????? PD_DocIterator(const CTestRTFDoc & doc, PT_DocPosition dpos = 0);
?
?????? //返回當前位置的字符
?????? virtual UT_UCS4Char getChar();
?
?????? //返回當前文檔位置
?????? virtual UINT getPosition() const {return m_pos;}
?
?????? //設置文檔對象成員m_pos;
?????? virtual void setPosition(UINT pos);
?
?????? ……
?
private:
?????? PD_DocIterator(pt_PieceTable & pt):m_pt(pt){};
?
?????? bool?????? _findFrag();
?
?????? pt_PieceTable?????? & m_pt;
?????? PT_DocPosition?? m_pos;
?????? PT_DocPosition?? m_max_pos;
?
?????? const pf_Frag * m_frag;
?
?????? UTIterStatus??? m_status;
};
?
先對數據成員進行說明:
1、pt_PieceTable?????????????? & m_pt;?????????????? //pt_PieceTable的引用
2、PT_DocPosition????????????????? m_pos;???????????????? //本迭代器當前的文檔位置
3、PT_DocPOsition???????????????? m_max_pos;???????? //本迭代器所能迭代的緩沖區上限即索引
4、const?????? pf_Frag *???????????? m_frag;???????????????? //本迭代器所對應的m_frag。
5、UTIterStatus??????????????????????? m_status;????????????? //一個枚舉類型的值用來代表當前迭代器的狀態。
?
這個類的目的主要是用來迭代一個m_frag所標識的數據段,對m_frag所標識的緩沖區的數據進行遍歷。
?
六、PD_StruxIterator類的說明
PD_StruxIterator 從一個給定的strux正向跨越迭代文檔內容;和上面的
PD_DocIterator形成對比,它不依賴于PT_Fragments是干凈的,但從起始的fragments
計算偏移量,這個偏移量是單個fragments的長度.
?
class ABI_EXPORT??? PD_StruxIterator : public UT_TextIterator
{
public:
?????? PD_StruxIterator(PL_StruxDocHandle sdh , UINT offset = 0 , UINT maxoffset = 0xffffffff);
?
?????? ……
?
private:
?????? PD_StruxIterator(){};
?????? bool??????????????????????????? _findFrag();
?????? bool??????????????????????????? _incrementPos(UINT d);
?
?????? pt_PieceTable????????????? * m_pPT;
???????
?????? //當前位置
?????? UINT????????????????????????? m_offset;
?
?????? //這個對象所代表的pf_Frag的偏移量,pf_Frag標識一個section
?????? //那么這個偏移量就是起始的位置
?????? UINT????????????????????????? m_frag_offset;?????????????
?????? PL_StruxDocHandle?? m_sdh;
?
?????? const pf_Frag????????????? * m_frag;
?????? UTIterStatus??????????????? m_status;
?????? UINT????????????????????????? m_max_offset;
?????? UINT????????????????????????? m_strux_len;
?
};
在這里對一些數據成員的作用進行探討,const??? pf_Frag???????? * m_frag 是一個指針,它指向了要迭代的那個pf_Frag,在這個類的構造函數中會調用 _findFrag()這個函數,這個函數的作用是定位這個迭代器的 pf_Frag,以使同m_offset 在某一個 pf_Frag的范圍內,即定位m_frag的值。同時_findFrag()會對m_frag_offset這個成員賦值,這個值代表該迭代器對應的pf_Frag的起始值。我們知道,pf_Frag代表一個文檔的片斷,當然至于pf_Frag_Strux類型也可以看成是一個片斷,那么這個片斷就是文檔中的一段數據的范圍,此類的pf_frag_offset成員就代表了數據的起始位置。m_strux_len數據成員代表了本pf_Frag_Strux的跨度即所代表的數據范圍的長度。m_offset成員可以理解為一個當前位置。
?????? 到這里已經總結出了abiWord中數據存放的位置以及數據的關聯方法,也看到了鏈表的一些相關操作,如上面的迭代器。在abiWord中,所有這些類的容器是一個名稱為pt_PieceTable的類。這個類容納了所有的文檔數據,以及它們之間的聯系。下面我們分析這個類的作用。
?
七、pt_PieceTable類的說明:
?
class pt_PieceTable?
{
public:
?????? bool?????????????????????????????????? appendFmt(const char ** attributes);
public:
?????? struct?
?????? {
????????????? UINT???? m_indexCurrentInlineAP;
?????? } loading;??????????????????????????????????????????????? /* stuff only valid while m_pts==PTS_Loading */
?
?
?????? pt_VarSet??????????????????????????????????????????????? m_varset;??????????????????? //容器
?????? pf_Fragments????????????????????????????????????????? m_fragments;??????? //鏈表
???????
???????
public:
?????? bool?????????????????????????????????? appendSpan(const UT_UCSChar * pbuf, UT_uint32 length);
?????? bool?????????????????????????????????? getAttrProp(PT_AttrPropIndex indexAP,
????????????????????????????????????????????????????????????????????? const PP_AttrProp ** ppAP) const;
?????? pt_VarSet &???????????? getVarSet(void) {return m_varset;}
?????? pf_Fragments &????????? getFragments(void) {return m_fragments;}
bool?????? appendStrux(PTStruxType pts, const char ** attributes, pf_Frag_Strux ** ppfs_ret = 0);
???????
???????
?????? inline const UT_UCSChar *getPointer(PT_BufIndex bi) const
?????? {
???????????????????? // the pointer that we return is NOT a zero-terminated
???????????????????? // string. the caller is responsible for knowing how
???????????????????? // long the data is within the span/fragment.
?
???????????????????? return m_varset.getPointer(bi);
?????? }
?????? CTestRTFDoc???????????? *getDocument();
};
?
上面簡要的列出了這個類的一部分聲明:下面對這個類的功能進行簡要的描述:
1、對于section(節)、paragraph(段落),我們都認為它們是一個strux類型,即保存它們相關的信息的pf_Frag派生類為pf_Frag_Strux_xxx , 比如 section相對應的pf_Frag類型為pf_Frag_Strux_Section,與段落相對應的pf_Frag為pf_Frag_Strux_Block。在pt_PieceTable這個類中如果要保存類似這些Strux的屬性則調用其成員函數appendStrux();下面畫出調用流程:

這是文本與其屬性的存儲方式分三步:
1、 存儲AP并獲得AP的索引;
2、 存儲文本并獲得文本在緩沖區中的偏移量
3、 存儲關聯文本和它的AP的pf_Frag_Text對象?
appendStrux( )
在調用了_makeStrux()之后,此函數會調用m_fragments.appendFrag(pfs); //將pf_Frag加入到鏈表中?
_makeStrux():
1、?? 這個函數會調用pt_VarSet的成員函數storeAP()以存儲屬性。
2、?? 調用_createStrux(pts,indexAP,&pfs),參數分別為Strux的類型、AP在vector中的索引,以及一個輸出參數pf_Frag_Strux & pfs.這個調用執行后會依據pts的類型創建一個pf_Frag_Strux.?
這是Strux的存儲方式


?
下面看文本以及其屬性的存儲方式

pt_PieceTable::appendFmt( )?
我們知道pt_PieceTable中有一個pt_VarSet類型的對象變量,調用這個對象的storeAP( )方法以存儲(AP)屬性。注意參數:1、屬性字符串;2、一個輸出參數會返回AP在vector中的索引。
m_varset.storeAP(attributes,&loading.m_indexCurrentInlineAP)?
bool pt_PieceTable::appendSpan( )?
?????? UINT bi;
?????? m_varset.appendBuf(pbuf,length,&bi)
上面這條語句是調用pt_VarSet::appendBuf();
參數說明:1、數據緩沖區指針.2、輸出參數會返回中到pv_VarSet的m_buffer[0]中的之后的偏移量.?
pt_PieceTable::appendSpan( )?
pf_Frag_Text * pft = new f_Frag_Text(this,bi,length,loading.m_indexCurrentInlineAP,NULL);
?????? 把這個fragment添加到鏈表末尾.
?????? m_fragments.appendFrag(pft);
生成一個pf_Frag并把它添加到鏈表末尾.
參數說明:1、pt_PieceTable的this指針;2、數據緩沖區的索引;3、AP在vector中的索引;4、暫時不解釋

至此,我們已經看到了存儲Strux與存儲文本的方式。

abiWord中數據的存儲


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产成人综合自拍 | 亚洲欧美一区二区三区久久 | 欧美一级在线免费观看 | 国产亚洲福利精品一区 | 国产91小视频 | 久青草视频在线播放 | 国产在视频线精品www666 | 中文字幕欧美在线观看 | 国产高清视频在线播放 | 天天做天天爱天天一爽一毛片 | 最新亚洲情黄在线网站 | 久久91精品久久久久久水蜜桃 | 亚洲高清国产一线久久 | 欧美综合视频在线 | 奇米影视第七色 | 国产精品免费观看网站 | 不卡中文字幕 | 想看一级毛片 | 伊人网址 | 亚洲精品动漫一区二区三区在线 | 久久6精品 | 二级片免费看 | 97视频在线看| 久久香蕉国产线看观看8青草 | 欧美丰满大乳大屁股毛片 | 四虎最新紧急入口 | 久久香蕉国产精品一区二区三 | 九九热最新视频 | 日韩国产欧美一区二区三区 | 亚洲国产精品婷婷久久久久 | 久久久精品日本一区二区三区 | 豆国产93在线 | 亚洲 | 亚洲欧美日韩综合精品网 | www夜夜操 | 国产精品久久新婚兰兰 | 国产精品热久久 | 亚洲精品久久久午夜伊人 | 人人爱天天做夜夜爽毛片 | 手机看片福利永久国产日韩 | 久草视频官网 | 人人夜|