cmarkup定位解釋
三年前,我寫過一篇關於
cmarkup
定位的解釋,現在我用這篇文章代替那篇。
int nstart;
int nlength;
int ntaglengths;
int nflags;
int ielemparent;
int ielemchild;
int ielemnext;
int ielemprev;
前三個整數告訴我們了在文件中,元素的起始位置,它的長度以及開始和結束標籤的長度,因為
nstart
是乙個32bit
的整數,所以文件
的最大尺寸可以有
2g,並且同樣,最大元素的長度是一樣的。整數
ntaglengths
被分成兩部分,
22bit(4m)
用於開始標籤(開始標籤可以包含屬性),另外
10bit(1k
)用於結束標籤。在下列元素中,開始標籤的長度是
14,結束標籤是
8.,整個元素的長度是29.
<
topic id
="5">triumph
topic
>
整數nflags
的低16
位實際儲存的是元素的深度或層次,高
16位是特殊標識。根元素是
0層,根元素的孩子是
1層等等
,特殊標識告訴我們元素是第乙個兄弟或最後乙個兄弟、或空元素、以及如果這個元素已經被刪除了(這樣的結構能夠被恢復) 四個
ielem
ielemparent
指向父元素,
ielemchild
指向第乙個子元素,
ielemnext
指向下乙個元素,當這個元素是最後乙個兄弟時,
ielemnext是0
,當元素不是第乙個兄弟元素時,
ielemprev
指向其前乙個兄弟元素,如果元素是第乙個兄弟元素,
ielemprev
指向最後乙個兄弟元素。因此,順著
ielemchild
的鏈結以及從那裡沿著
ielemprev
的鏈結,可以得到父元素的最後乙個子元素。
如果你熟悉像這樣用樹結點鏈結在一起的工作方式,你將明白這個地圖的效果。這個設計對於樹層次的回來操作是有效的,再通過兄弟元素形成乙個環,但是,對於隨機訪問第
n個子元素將需要先迴圈這個元素之前的所有兄弟元素。一旦被建立起來,在文件中隨意的導航將不再需要費時的分析。
當乙個文件被分析時,就產生了這些資訊,因此當文件被修改時,這些資訊也修改。例如,增加乙個屬性,開始標籤的長度改變了,元素的長度改變了,以及所有後面的和包含的元素都要被調整。如果刪除乙個元素,領銜值改變了,還有其前乙個元素的
ielemnext
也被修改以繞過刪除的元素等等。
深入markup分析器
雖然markup
經常被叫做是「分析器」,但是分析保是
cmarkup
功能中的一部分,另外
cmarkup
還支援文件的導航、建立和修改,還有其它如檔案
i/o、字符集及
64位編碼轉換等功能。然而分析器是
cmarkup
乙個最重要的功能,因為這樣可以匯入和訪問現有
xml檔案。
分析器在
setdoc
和load
方法中分析文件,並建立定位陣列,這是乙個非驗證的分析器,這表明它不會依照著
dtd和
schema
來檢查文件的正確性。它只會檢查格式的好壞,如果結束標籤不匹配開始標籤它會產生乙個錯誤,如果沒有根元素存在會產生乙個錯誤,或者其它一些不正確的結點樣式它也會產生乙個錯誤。 在
7.0版 本中,分析器使用了新的分析方法,不再使用遞迴實現。在以前的版本中,使用遞迴方法實現時,每次在另乙個元素中發現乙個元素就呼叫自己,當它到達父結點的 結束標籤時返回。因為每次巢狀呼叫都要增加區域性變數和引數到堆疊中,但是在堆疊的尺寸是有限的任何平台上,例如掌上作業系統,這時,遞迴就成為乙個問題 了。雖然大多數的檔案不會大於
10個元素的深度(巢狀),也許在棧中只需要
500bytes
,然而,這仍是乙個潛在的危險。新的分析器使用了乙個叫
nodestack
的小陣列,它就像乙個棧,但是它在堆裡的。
它保持著一直到當前深度的所有被巢狀的元素的標籤名。
分析函式x_parseelem實際上相當簡單,它通過呼叫
x_parsenode
查詢和檢查下乙個結點來迴圈所有的結點,直到文件的結束。關於結點型別的討論可以看在nodes的文章。元素的結束標籤被表示成0的結點型別,因為它是元素結點的結束。
nodestack 用來記錄被巢狀的元素,當乙個起始標籤被遇到時,它將呆在nodestack中,直到相對應的結束標籤被發現。如果乙個元素a包含其它一些元素,那麼這些 元素將會放到nodestack中,並且置於元素a的上面,在恢復父元素(元素a)之前,需要匹配它們的結束標籤然後從nodestack中刪除。
x_parsenode
函式是根據在文件中給定結點起始字元的偏移量來識別乙個結點。出於對速度和簡單考慮,結點被分析只是從第乙個字元前進做乙個簡單的迴圈,在結點的型別被確定前,保持乙個位元標誌狀態。
如果第一字元是小於號「
<」,
它就是乙個標籤「
<..>」(
對於文字和空格
),如果是標籤,檢查第二個字元,它可能是元素標籤名的起始、或者乙個斜線(結束標籤)、或者是乙個感嘆號(是注釋、
cdata
段或doctype
)或是問號(
pi),如果是感嘆號,你必須要得到下乙個字元來判斷結點的型別。一旦知道了結點型別,分析器就可以正確掃瞄這種結點型別相應的結束字串。
如果第乙個字元不是小於號「
<
」,同時也不空格,那麼它是乙個文字結點,並且這個結點一直要到乙個小於號
」<」
或者到文件的結束。如果第乙個字元是乙個空格,那麼它也要一直到小於號
」<」
或文件結束,但是當看到第乙個非空格就表明它是乙個文字結點。如果到結點的結束都沒有遇到非空格,那麼,它就是乙個空格結點。
現在,讓我們這樣的步驟來處理下面的簡單
xml文件。
<?
xml version
="1.0"?><
test
>hello world
test
>
首先呼叫
x_parsenode
,開始字元是文件的第乙個字元,如果是小於號,表明是標籤,所以
opentag
位被設定,下乙個字元是乙個問號,那麼在
opentag
狀態中,表明這是乙個處理指令(
pi),現在知道了結點型別,不需要設定
opentag
位了。它會掃瞄
pi的結束字串
?>,
再返回。
第二步,呼叫
x_parsenode
,開始字元是測試元素的第乙個字元,是小於號,表明這是乙個標籤,所以設定
opentag
位,下乙個字元是乙個有效字元,是元素標籤名的第乙個字元,那麼在
opentag
狀態中,意味著這是乙個文字結點。現在知道了結點型別,就不需要再設定
opentag
位了。它會掃瞄到元素標籤的結束字元
」>」,
接著返回。
第三步,呼叫
x_parsenode
,起始字元是「
hello world
」的第乙個字元,這不是小於號了,它是乙個空格,所以
textorws
(文字或空格
)位要被設定。下乙個字元是文字字元,所以在
extorws
狀態中,就意味著這是乙個文字結點,現在,解析器知道了結點型別,就不用再設定
textorws
位了,它會掃瞄小於號或文件的結束,然後返回。
第四步,呼叫
x_parsenode
,,開始字元是測試元素結束標籤的第乙個字元,這是乙個小於號,表明它是標籤,所以要設定
opentag
位,下乙個字元是斜線,在
opentag
狀態中,這意味著它是乙個結束標籤,現在知道標籤的型別了,不用設定
opentag
位了,它會掃瞄結束標籤的結束字元「>」,然後返回。
select COUNT 語句深入解釋
select count 只統計不是null的列數,所以count 列名 count 常量 count 的區別就是 count 列名 中的列可能是null,於是不被統計入內 其餘兩個倒是統計所有符合條件的行數,且是標準的統計行數的方法,mysql已經做了一些優化,所以推薦 區分為myisam和inn...
漏洞可解釋性定位
利用可解釋性做定位,用可解釋的方法來做定位。首先在建模的時候要包括能體現漏洞的特徵,結合汙點分析的原理,可以這樣說,如果在source和sink中間沒有sanitizer操作,這才可能會導致漏洞發生,資料完整性或資料私密性被破壞。都說借助自然語言的處理方法來對程式處理,是為了程式的語義資訊。可是,程...
深入理解浮動定位 float
css網頁布局有兩種方式 一種是浮動式布局 另外一種是定位布局。這兩種方式的核心都脫離於文件流的控制。前提 文件流 document flow 對於乙個xhtml網頁,body元素下的任意元素,根據其前後順序,組成了乙個個上下關係,簡單說這就是文件流。瀏覽器根據這些元素的順序去顯示它們在網頁中的位置...