Webcore中文本資源編解碼

Webcore中文本資源編解碼

 

dlmu2001

 

本文描述的文本資源編解碼,針對的是字符串編解碼,如 UTF-8,GB2312 ,而非傳輸編解碼(如 gzip )。

    關於字符串編碼的理論知識,如果你還不瞭解,可以參考 http://baike.baidu.com/view/1204863.htm

    我們以一個最簡單的網頁爲例,假設服務器上有一個純鏈接的頁面,沒有任何派生資源( image css sound subframe javascript 等)。服務器傳送給我們的頁面,他們字符串編碼是各種各樣的,常見的有 utf8 gb2312 。如果我們用 utf8 的解碼方式去解 gb2312 的網頁,那麼網頁顯示出來的就是亂碼。所以, webcore 裏面,需要首先找出服務器提供的網頁的字符串編碼格式,然後調用對應的解碼接口進行解碼,輸出 webcore 的其它模塊接受的 unicode 方式的文本( String 類)。

    那如何來確定網頁的字符串編碼呢,一般有如下幾種方式

1 )父親節點繼承過來的 charset 屬性,比如 Iframe 裏面的 charset ,如果不指定,則一般繼承自原生頁面(當然,前提是 subframe 和原生頁面的 domain 是一樣的)

2 HTTP 響應頭部中包含了 charset 字段

3 )如果有外部的 css ,也可能由外部 css 來指定 charset

4 HTML head 元素裏面的 meta 標籤指定了字符串編碼,如
<head><meta http-equiv="Content-Type" content="text/html;charset=gb2312">

5 )如果是 XML 頁面, XML 頭部中指定了 charset ,如
      <?xml version="1.0" encoding="UTF-8"?>

對一個瀏覽器來說,可能還會支持用戶直接指定字符串編碼方式,自動識別。

 

   WebCore 中同字符串解碼處理相關的文件主要是   TextResourceDecoder.h/TextResourceDecoder.cpp ,TextCodec.h/TextCodec.cpp,  以及不同平臺的字符串解碼的 porting (如 TextCodecICU.cpp,TextCodecQt   .cpp,TextCodecUTF16.cpp 等),這裏以 TextCodecICU porting 爲例來理解。

  

   WebCore 中通過 DocumentWriter 類維護了一個 TextResourceDecoder 類的指針 m_decoder ,以此來實現對文本資源的解碼功能的調用和控制。  

   當網絡有數據到來的時候,會調用 DocumentWriter.cpp createDecoderIfNeeded 函數,這裏可以看到一個 TextResourceDecoder 的創建,首先考慮的是設置中是否允許自動識別,其後是 HTTP  響應的 header 中是否有 charset 頭部( m_decoding ),如果此處調用了 TextResourceDecoder 類的 setEncoding 方法設置了編碼方式,則之後就不需要再去檢查 HTML 中的 meta 標籤等。

   在創建了 decoder 以後,就可以對數據進行解碼了, DecodedDataDocumentParser 類的 appendBytes 函數調用了 TextResourceDecoder decode 方法,對到來的數據進行解碼,由於數據是分段到了,所以分段解碼。如果數據來齊了,或者中斷了,則調用 TextResourceDecoder flush 函數來結束解碼流程。

 

TextResourceDecoder 類主要實現兩個功能,一個是 charset 的獲取,包括 meta charset 的獲取, xml charset 的獲取, charset 的自動識別( KanjiCode 類)。另外一個是解碼組件的調用和維護。

解碼組件的維護是通過成員變量 m_codec 來完成的。在開始 decode 的時候,調用 newTextCodec 接口,根據 charset 類型,來創建一個解碼組件,然後調用解碼組件的 decode 方法完成解碼(該方法通過 TextCodec 類進行了封裝,通過 TextCodecICU 等類進行了實現)。解碼完成以後,則將 m_codec 釋放( clear )。需要注意的是,在 TextResourceDecoder 類的 flush 接口中,需要先進行 decode ,才進行 clear ,以免丟失數據。

 

最後說一下 TextEncodingRegistry.cpp 這個文件,從名字也可以看出來,它用來負責解碼控件的註冊和管理,相當於一個容器,來匹配編碼方式和對應的解碼組件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章