ProtoBuf 源碼簡析


 
         
ProtoBuf項目描述:
  Google Protocol Buffer簡稱protobuf,為高效的二進制序列化/反序列化協議(一般為google內部使用),不同於xml、json等,其更小巧、高效;avro、thrift等; 其可用於網絡協議、數據存儲等語言無關、平台無關、可擴展的序列化結構數據格式。只要按照特定條件可支持向前、向后兼容;目前提供了C++、Java、Python 三種語言的 API,這樣各語言可以相互序列化和反序列化數據信息(事實上也可以自定義實現其他語言的API接口)。 在使用中,用戶可根據自定義或引入數據結構(Message)文件*.proto;此后通過編譯器protoc.exe編譯該描述文件為指定語言的操作接口,而后將產生的操作接口文件 和libprotobuf.lib添加入項目中進行數據序列化和反序列化操作即可,產生的序列化后的信息可讀性很差,此外反序列化也必須知道對應的數據結構描述文件*.proto, 否則無法正確地反序列化,也不再有意義,相對xml,json無法直接插入或修改數據信息內容; 以下僅對C++相關進行分析; 項目工程: gtest:google 白盒測試開源項目,主要用於單元測試,后面的gtest_main、tests項目; gtest_main:簡單的對main函數以及testing::InitGoogleTest(&argc, argv);RUN_ALL_TESTS();封裝的lib,這樣其他測試工程只需要包含引入該庫並集中精力在 測試用例上; libprotobuf:protobuf基礎工程庫,主要實現; libprotobuf-lite: libprotobufc:對應protobuf的編譯器封裝為庫,以支持c++、java、python語言對*.proto文件的編譯為相應的接口API; lite-test: protoc:簡單的控制台實現的protoc編譯器,該編譯器通過命令行參數傳遞對應的*.proto文件和編譯輸出接口API選項;依賴於libprotobuf、libprotobufc; test_plugin: tests: *.proto數據描述文件說明: protoc編譯器命令行參數說明和生成文件API文件名說明: *.proto 文件編譯后為*.pb.h以及*.pb.cc;
項目內容簡析:

  libprotobuf:protobuf基礎工程庫,內部主要實現編碼和解碼等相關操作。 config.h:配置相關,事實上為聲明宏hash_map、hash_set頭文件以及編譯宏HAVE_HASH_SET、HAVE_HASH_MAP; template_util.h :模板元編程相關的工具,模板、函數;主要包括: integral_constant、if_、type_equals_、and_、or_、true_、false_; type_traits.h :在template_util.h的基礎上,定義了一系列類型特征萃取相關的模板類或函數如:is_xxx,has_xxx,remove_xxx; common.h:內部使用公共函數、基本類型,全局常量、用於當前庫的工具模板輔助函數; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS:不允許賦值拷貝宏; LIBPROTOBUF_EXPORT
/LIBPROTOC_EXPORT:導入導出宏; 一系列標識庫版本的宏、常量,格式:major * 10^6 + minor * 10^3 + micro,如:2005000; VersionString:整形轉化為版本字符串;格式:major.minor.micro,如:2.5.0 VerifyVersion:版本兼容性檢定函數; 重聲明基本類型,便於統一處理以及定義了幾種類型靜態變量最大最小值; GOOGLE_ARRAYSIZE:安全的獲取數組元素個數(若未對齊,則會提示除0警告); implicit_cast:隱式轉換模板;類似於static_cast、const_cast的安全版本; down_cast:向下轉換,由父類指針對象轉型為某個子類,內部使用static_cast轉型,在調試模式下時使用dynamic_cast進行驗證; CompileAssert:編譯時斷言,結合GOOGLE_COMPILE_ASSERT宏,內部通過msg[-1或1]確定是否可通過編譯,可能對浮點數0.0之類的存在歧義; scoped_ptr/scoped_array:指針包裝,智能指針; LogLevel:日志級別,提供INFO、WARN、ERROR、FATAL幾種嚴重級別; LogMessage:消息日志,記錄、操作消息; LogMessage:構造函數傳參為日志級別、文件名稱、所在行; 重載多個版本operator<<; Finish:完成操作,內部若為非FATAL日志,則將調用InitLogSilencerCountOnce,此外若無靜默者·則調用log_handler_處理該日志, 默認調用接口為DefaultLogHandler(默認向stderr輸出,格式“[libprotobuf level filename:line] message ”),此外若為FATAL日志, 則根據是否使用異常拋出FatalException類型對象異常或調用abort終止進程; level_:日志級別; filename_:文件名稱; line_:所在行; message_:消息內容; LogFinisher:log日志完成者,實現了operator=,內部調用LogMessage的Finish函數; GOOGLE_LOG:log宏,封裝LogFinisher作為工具封裝; GOOGLE_LOG_IF:條件log宏; GOOGLE_CHECK_XXX:一系列檢測宏,內部調用GOOGLE_LOG_IF(FATAL,...); CheckNotNull:非NULL檢測以及宏GOOGLE_CHECK_NOTNULL; debug模式下的GOOGLE_DCHECK_XXX調試宏; SetLogHandler:設置日志控制器log_handler_,若參數為NULL則設置為NullLogHandler,其不處理日志信息, LogSilencer:日志靜默者,跳過非FATAL日志,使得log_handler_控制器不處理日志;使用時可直接在某個函數點創建臨時對象即可,在作用 域內,產生的日志信息將會被“吸收”;作用域外則恢復到正常的日志處理; Closure:稱為關閉、終止的基類,內部只提供了純虛函數Run; FunctionClosureXXX/MethodClosureXXX:繼承於Closure類,實現Run內部調用傳入的函數並根據參數刪除釋放當前本類對象;前者主要傳入普通 或類的靜態成員函數,后者主要處理類對象以及相應類的成員函數;目前僅實現了支持0,1,2個參數的繼承類; NewCallback/NewPermanentCallback:分別重載了對應不同參數類型的模板幫助函數,內部通過new創建FunctionClosureXXX/MethodClosureXXX; 前者創建了調用Run會自動刪除對象;后者為永久對象,用戶可根據需要某個時刻delete該對象; DoNothing:空函數操作; Mutex:鎖,通過IMPL技巧實現,內部利用臨界區實現鎖機制,此外AssertHeld函數用以在調試模式下檢測當前線程下是否為獲取到鎖的線程; MutexLock:自動鎖,對Mutex的封裝,此外重聲明鎖ReaderMutexLock、WriterMutexLock; MutexLockMaybe:同MutexLock,但更安全; IsStructurallyValidUTF8:檢測是否包含UTF-8的字符編碼; ghtonl:主機字節序轉化為網絡字節序,同htonl; ShutdownProtobufLibrary:關閉protobuf庫,主要為執行關閉操作函數集vector<void (*)()>的shutdown_functions內容,釋放shutdown_functions、 shutdown_functions_mutex鎖對象; OnShutdown:注冊關閉庫時被調用的函數,添加至shutdown_functions; FatalException:繼承於std::exception,構造函數提供文件名稱、所在行、消息內容,並添加filename、line、message操作方便獲取相應成員變量值; platform_macros.h:跨平台相關的宏定義; atomicops.h:提供跨平台的原子操作,內部實現根據相應平台編譯相應接口的實現,以下以X86 msvc編譯器為例,將采用atomicops_internals_x86_msvc的實現; Atomic32/AtomicWord:原子類型重聲明; NoBarrier_CompareAndSwap:內部調用InterlockedCompareExchange,實現原子的比較交換操作; NoBarrier_AtomicExchange:內部調用InterlockedExchange,實現原子指定值操作; NoBarrier_AtomicIncrement:內部調用InterlockedExchangeAdd,實現原子加操作,累加的數值為參數的2倍值; Barrier_AtomicIncrement:同NoBarrier_AtomicIncrement;、 Acquire_CompareAndSwap:事實上內部調用NoBarrier_CompareAndSwap; Release_CompareAndSwap:事實上內部調用NoBarrier_CompareAndSwap; MemoryBarrier:內部調用MemoryBarrier,實現硬件防護,以防止CPU或編譯器亂序執行; NoBarrier_Store:非防護設置,參數指針對象ptr設置值為value; Acquire_Store:內部調用NoBarrier_AtomicExchange; Release_Store:同NoBarrier_Store; NoBarrier_Load:獲取當前參數值; Acquire_Load:獲取臨時參數值; Release_Load:獲取MemoryBarrier防護后的當前參數值; once.h:主要封裝初始化一次的操作; 通過定義GOOGLE_PROTOBUF_DECLARE_ONCE宏原子變量以及初始化函數,當調用GoogleOnceInit時實現執行一次初始化函數; 示例:void Init();GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);void InitOnce(){GoogleOnceInit(&once_init,&Init);};任何多次調用InitOnce函數只會最終 調用Init初始化函數一次; 內部定義了三種原子狀態:未初始化ONCE_STATE_UNINITIALIZED、正在執行初始化ONCE_STATE_EXECUTING_CLOSURE、已完成初始化ONCE_STATE_DONE; GoogleOnceInit:初始化一次函數,參數分別為原子、初始化函數;提供無參版本和重載模板一個參數的版本;函數內部調用Acquire_Load獲取原子狀態,此后根據 狀態處理創建FunctionClosure0執行GoogleOnceInitImpl; GoogleOnceInitImpl:內部處理原子狀態並處理多線程下執行流程;若未初始化則設置原子為正在初始化並執行FunctionClosure0的Run函數,執行完成后設置原子 為已完成初始化狀態;若其他線程進入時,若此時仍為正在執行初始化,則循環查詢原子狀態並調用SchedYield放棄CPU時間片; strutil.h:字符、字符串工具函數; ascii_isalnum:ASCII碼是否為a~z或A~Z或0~9的字符; ascii_isdigit:ASCII碼是否為數字字符; HasPrefixString:原始字符串是否有指定的前綴字符串; StripPrefixString:獲取剝去原始字符串中的指定前綴的字符串,否則為原始字符串; HasSuffixString:原始字符串是否有指定的后綴字符串; StripSuffixString:獲取剝去原始字符串中的指定后綴的字符串,否則為原始字符串; StripString:查找指定字符串s中被匹配的模式字符串remove中出現的位置,並替換為字符replacewith;內部調用strpbrk實現查找匹配; LowerString:字符串小寫化; UpperString:字符串大寫化; StringReplace:相對StripString,其實現字符串分片替換為新的字符串,若參數replace_all為true,則全部替換,否則只替換第一次出現的; SplitStringUsing:對給定的模式字符串delim,匹配原始字符串full,並拆分至vector<string>* res中; SplitStringAllowEmpty:相對SplitStringUsing,其允許空原始字符串和傳回空字符串; JoinStrings:提供兩個版本,合並字符串和分隔符字符串合並,字符串間為分隔符字符串組合為返回字符串; UnescapeCEscapeSequences:轉化字符串各字符為相應的ASCII碼; UnescapeCEscapeString:同UnescapeCEscapeSequences; CEscapeString/CEscape:轉化字符串,保存部分標識(目前\n, \r, \t, ", ', \以及不可打印的字符將被隱藏(保護)); 字符串與數值間的相互轉化; strto32/strtou32/strto64/strtou64:字符串轉數值(內部調用strtoXXX系列函數); FastXXXToBuffer:系列函數,數值轉化為字符串,字符串右對齊; FastXXXToBufferLeft:系列函數,數值轉化為字符串,字符串左對齊; SimpleItoa:重載版本,整型數值轉字符串,參數為有符號時內部調用FastXXXToBuffer,無符號時調用FastXXXToBufferLeft; SimpleDtoa/SimpleFtoa:分別為雙精度、單精度浮點轉字符串; DoubleToBuffer/FloatToBuffer:雙精度、單精度浮點轉字符串; 目前控制字符串轉化最大長度為kDoubleToBufferSize(32位),kFloatToBufferSize(24位); NoLocaleStrtod:無區域化字符串轉雙精度浮點數;類似於strtod; stl_util.h:STL相關的部分輔助工具、函數; STLDeleteContainerPointers:模板實現,刪除釋放容器內指針對象資源,參數為容器收尾迭代器對象; STLStringResizeUninitialized:重置容器大小,針對string容器,內部調用resize; string_as_array:string字符串當前array使用,內部取string的begin地址位置;使用時示例;string str;string_as_array(&str)[i]; 個人認為與string的operator[]等價; STLDeleteElements:模板實現,內部調用STLDeleteContainerPointers,且調用容器對象的clear接口;釋放容器內對象資源且清空容器; STLDeleteValues:模板實現,一般用在map或pair對的容器參數,以釋放容器value值對應的對象內容,並調用clear清空容器; hash.h:封裝實現內部使用的hash_map和hash_set; hash<key>:模板類,繼承於std::hash_compare<key>; CstringLess:函數對象(仿函數),作為hash_compare<const char*, CstringLess>的operator<比較操作模板參數,其僅支持const char*參數(內部通過strcmp比較); hash<const char*>:hash模板特化版本,繼承於std::hash_compare<const char*, CstringLess>; hash_map/hash_set:分別繼承與hash_map/hash_set;對於非MSVC編譯器,則采用的自己的實現,此外對hash<const char*>則使用result = 5 * result + *str; 循環疊加的方式處理; hash<string>:hash模板特化版本; hash<pair<First, Second> >:針對pair的版本; streq:仿函數,實現比較const char*字符串相等操作,內部調用strcmp; maputil.h:map或hash_map輔助工具、函數,以下的map代表map或hash_map; FindWithDefault:查找map容器中指定key的value值,否則返回提供的默認值value; FindOrNull:查找map容器中指定key的value值地址,否則返回NULL; FindOrDie:查找map容器中指定key的value值地址,否則拋出FatalException異常或終止進程; FindPtrOrNull:查找map容器中指定key的value值,否則返回0; InsertOrUpdate:若map容器存在對應的key則更新,否則插入元素,返回值false表示更新,true為插入; InsertIfNotPresent:同InsertOrUpdate,不過存在對應的key時不再更新,返回值false為插入失敗,true插入成功; stringprintf.h:字符串格式化輸出、打印; StringPrintf:格式化輸出字符串(內部通過調用StringAppendV實現); SStringPrintf:同StringPrintf,但是傳入的參數dst會被清空; StringAppendV:格式化字符串,內部vsnprintf與va結合進行格式化,並采取基於堆和棧的方式實現長短字符串的格式化(棧最大大小kSpaceLength(1024字節)); StringAppendF:同StringAppendV,內部不會清空參數dst,會追加格式化后的字符串; StringPrintfVector:打印格式化vector<string>數據容器,內部調用StringPrintf進行格式化; kStringPrintfVectorMaxArgs:StringPrintfVector中vector容器的最大參數(最大32個,若v容器大小大於該值將調用LOG(FATAL)); string_printf_empty_block:保護StringPrintfVector打印,為空塊; substitute.h:類似於stringprintf.h的字符串格式化,但是比stringprintf.h更加高效且使用方式上有所不同; SubstituteArg:格式化參數類,提供了多個支持基本數據類型的構造函數,此外提供提取轉化后字符串data和字符串數據長度size接口,對於基本數據轉換利用 strutil.h中提供的快速轉換,如FastInt32ToBuffer、FloatToBuffer等; Substitute:提供了支持至多9個參數的格式化字符串,參數為SubstituteArg類型或可轉化為SubstituteArg類型的;此外格式化使用“$”后跟一個數字, 該數字值為對應SubstituteArg參數,使用示例: string str; strings::SubstituteAndAppend(&str,"My name is $0 $1 and I am $2 years old.",first_name,last_name,age);事實上$后的數字可以一樣; SubstituteAndAppend:同Substitute,但是會對格式化后的字符串數據對應參數output進行追加; zero_copy_stream.h:提供最小化數據流拷貝操作,主要提供ZeroCopyInputStream和ZeroCopyOutputStream抽象基類操作的接口,具體實現類位於 zero_copy_stream_impl.h和zero_copy_stream_impl_lite.h中; 此兩個抽象基類操作接口如下(ZeroCopyOutputStream沒有提供Skip接口): Next:獲取數據流中的一塊數據,參數data為指向的數據指針,size為獲取的數據長度,返回值為false表示沒有可讀的數據或出現異常; BackUp:在調用Next后,可以回退內部數據指針索引位置,這樣下一次調用Next時可以重新獲取前一段數據;參數值不可大於早期Next得到的size長度; Skip:跳過部分數據流,返回false則表示已到數據流末尾或發生異常,為防止異常,可結合ByteCount和早期的Next確定是否會達到數據流末尾; ByteCount:獲取當前數據流位置; zero_copy_stream_impl_lite.h:對zero_copy_stream.h中的抽象基類的實現,主要提供基於array、string的輸入和輸出流實現; ArrayInputStream:類array的輸入流,繼承於ZeroCopyInputStream; 數據成員: data_:指向uint8類型的array的數據指針; size_:array數據的有效長度; block_size_:每次調用獲取Next獲取的數據最大長度; position_:當前數據的索引位置; last_returned_size_:最后一次調用Next返回的數據長度; 構造函數:參數data為指向數據array的指針(該數據array應在ArrayInputStream生命周期內是有效的),size為數據長度,block_size為Next獲取的最大長度; ArrayOutputStream:類array的輸出流,繼承於ZeroCopyInputStream,操作大體同ArrayInputStream; StringOutputStream:支持string類型的輸出流,繼承於ZeroCopyInputStream; kMinimumSize:最小的new size大小,在處理Next操作中,調整目標string大小為kMinimumSize或2 * old_size或capacity()大小; CopyingInputStream:拷貝輸入流;僅提供Read、Skip操作接口; Read:讀取流中指定數據;參數buffer指向流數據針對,size數據流大小,返回值為讀取到的字節數,返回0為讀取到數據流尾,返回-1表示異常; Skip:跳過指定長度的數據流;返回值為跳過的實際長度; CopyingOutputStream:拷貝輸出流,僅提供Write操作接口; Write:從給定buffer中讀取size字節的數據至輸出流;返回值true表示成功,false表示寫入異常; CopyingInputStreamAdaptor:拷貝輸入流適配器(事實上內部並非為zero-copy),繼承於ZeroCopyInputStream,其以CopyingInputStream作為輸入流對象; 數據成員: copying_stream_:CopyingInputStream類型的流對象指針; owns_copying_stream_:是否是copying_stream_對象的擁有者,便以在釋放的時候釋放copying_stream_對象資源; failed_:是否出現操作異常; position_:當前數據流位置索引; buffer_:讀取到的數據流對象緩沖區; buffer_size_:讀取到的數據流對象緩沖區大小; buffer_used_:調用Next最近一次的大小; backup_bytes_:調用BackUp的回退字節數; 成員函數: 構造函數,參數copying_stream為CopyingInputStream類型的流對象指針,block_size為數據緩沖區大小以初始化 buffer_size_(若為<0則為默認大小kDefaultBlockSize(8192)); SetOwnsCopyingStream:設置是否為copying_stream_對象的擁有者; AllocateBufferIfNeeded:分配為buffer_size_大小的buffer_緩沖區; FreeBuffer:釋放buffer_緩沖區資源; 此外Next、BackUp、Skip、ByteCount為ZeroCopyInputStream的接口實現; CopyingOutputStreamAdaptor:拷貝輸出流適配器(事實上內部並非為zero-copy),繼承於ZeroCopyInputStream,其以CopyingOutputStream作為輸出流對象; 數據成員: copying_stream_:CopyingOutputStream類型的流對象指針; owns_copying_stream_:是否是copying_stream_對象的擁有者,便以在釋放的時候釋放copying_stream_對象資源; failed_:是否出現操作異常; position_:當前數據流位置索引; buffer_:讀取到的數據流對象緩沖區; buffer_size_:讀取到的數據流對象緩沖區大小; buffer_used_:調用Next最近一次的大小; 成員函數: 構造函數,參數copying_stream為CopyingOutputStream類型的流對象指針,block_size為數據緩沖區大小以初始化 buffer_size_(若為<0則為默認大小kDefaultBlockSize(8192)); SetOwnsCopyingStream:設置是否為copying_stream_對象的擁有者; Flush:調用底層刷新寫入數據至輸出流; AllocateBufferIfNeeded:分配為buffer_size_大小的buffer_緩沖區; FreeBuffer:釋放buffer_緩沖區資源; WriteBuffer:寫入當前buffer_used_大小的數據至輸出緩沖區數據; zero_copy_stream_impl.h:對zero_copy_stream.h中的抽象基類的實現,主要實現File、stream、Concatenating、Limiting等幾種流實現; FileInputStream:文件描述的讀操作類,繼承於ZeroCopyInputStream; 先介紹CopyingFileInputStream:文件輸入流類,繼承於CopyingInputStream,實現讀取文件數據; 數據成員: file_:文件描述符或文件句柄; close_on_delete_:關閉時,是否釋放、刪除文件描述對象; is_closed_:是否已關閉; errno_:IO操作錯誤碼; previous_seek_failed_:最近一次seek是否失敗; 成員函數: 構造函數參數為文件描述符或文件句柄 Close:關閉文件描述符或文件句柄; SetCloseOnDelete:設置關閉操作時,自動釋放、文件描述對象; GetErrno:獲取IO操作錯誤碼; 此外Read、Skip為CopyingInputStream類的實現接口,實現文件的讀取和跳過指定字節數的操作; 數據成員: copying_input_:CopyingFileInputStream類型的輸入流對象; impl_:CopyingInputStreamAdaptor類型的輸入流對象適配器,作為流輸入對象的實現類; 成員函數: 構造函數參數file_descriptor文件描述初始化copying_output_,其與block_size輸入流塊大小初始化impl_; Close:關閉文件描述並刷新緩沖區,內部調用copying_input_的Close函數; SetCloseOnDelete:設置關閉操作時,自動釋放、文件描述對象,內部調用copying_input_的SetCloseOnDelete函數; GetErrno:獲取IO操作錯誤碼,內部調用copying_input_的GetErrno函數; 此外Next、BackUp、Skip、ByteCount均內部調用impl_相應接口實現; FileOutputStream:文件描述的寫操作類,繼承於ZeroCopyOutputStream,接口實現與FileInputStream相似; 增加了Flush接口以刷新輸出流,無Skip接口; IstreamInputStream:用以對C++輸入流操作,繼承於ZeroCopyInputStream;同FileInputStream,只是操作構造函數為istream的對象; 其內部讀輸入,使用istream的read、gcount、fail、eof接口操作; OstreamOutputStream:用以對C++輸出流操作,繼承於ZeroCopyOutputStream,同FileOutputStream,只是操作構造函數為ostream的對象; 其內部寫輸出,使用ostream的write、good接口操作; ConcatenatingInputStream:處理多個ZeroCopyInputStream輸入流的stream對象操作,繼承於ZeroCopyInputStream; 構造函數streams為ZeroCopyInputStream類型的指針數組,count為數組大小; LimitingInputStream:處理受限字節的輸入流,,繼承於ZeroCopyInputStream; 構造函數input為ZeroCopyInputStream類型的指針對象,limit為字節上限; ConcatenatingInputStream與LimitingInputStream僅為其他stream對象的包裝而已;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM