2012年5月29日 星期二

OSSP 的 uuid 函式庫內有精簡的 md5/sha1 hash 實作

手邊 C++ 專案需要實現 SHA1 hash 的功能, 原本想到的是透過 OpenSSL / Botan 這類的現有函式庫來達到, 但轉念想想沒道理為了加扇窗就把整棟大樓的材料都堆進來. 就一直在網上尋找精簡的 md5/sha1 hash 實現. 不知道是鬼打牆還是怎地一直沒找到. 而事情就這麼巧, 接著在找 uuid 開源替代方案時找到 OSSPuuid 專案, 裡面竟然帶有一套不依賴任何第三方函式庫的 md5/sha1 實現. 整個專案還是用 MIT 授權, 真是踏破鐵鞋無覓處...

有個小問題是 uuid 目前的 build process 不支援 Windows 平台 (以 OSSP 的宗旨來看也很合理) , 它是基於 autogen/configure 那一套 unix 標準程序的, 引用的 header 中也有包含 unistd.h 這類在 Windows 缺乏對應的文件. 不過評估了一下 porting 的功夫不會很大, 小改了一下目前在 MSVC 環境中已可建置它的 md5/sha1 hash 模組. 有時間會嘗試整個 porting. 想要導入 cmake 代替原有的 autogen, porting 完之後可以一次搞定 msvc, mingw, cygwin 三個環境.

Sourceforge: http://sourceforge.net/projects/osspuuidwin32/

2012年5月22日 星期二

跨網路資料交換

最近這一個月都在反覆實作與檢示 Client Server 之間的資料交換架構. 一般最直觀的資料交換, 就是任何一方發送資料時先經過制式的序列化 (serialization, 或稱 deflating, marshalling) 程序, 把運行時結構化的數據資料成員重新排列成平面且緊密的純二進位資料流 (binary data stream), 然後將資料流送出, 接收方再透過相對應的反序列化程序 (deserialization, 或稱 inflating, unmarshalling) 把收到的資料流重組回結構化的數據.

這樣直觀的流程套用在開發專案時會遇到一個問題: 每種需要進行資料交換的結構化數據類型都必需要撰寫其專有的序列化/反序列化程序. 這樣的需求在結構化數據類型會隨專案開發的進度而大量增加時就會變得很繁瑣. 為了解決這種窘境, 我們會希望在序列化時盡量讓輸出的資料流保有某種程度上的自述性. 也就是說不管面對何種類型的數據類型, 序列化/反序列化的做法都要能是同一套, 序列化時除了資料本身之外, 還夾帶了這些資料的型態, 彼此的結構關系這類資訊, 提供反序列化程序檢示, 賴以重組回結構化的數據. 舉一個極端的例子: 進行序列化時, 將結構數據輸出為用 JSONYAML 這類資料描述語言的描述語句, 反序列化時解析這些語句重組回結構化數據. 通常這些描述語言都已有很好的各類程序語言函式庫, 可提供現成的輸出描述語句和解析語句的功能.

輸出具有自述性的資料流會有個不良影響是會導致資料流的膨脹. 原本只要夾帶資料本身, 現在要多附加資料型態和結構關係, 所以因資料膨脹導致交換效能降低是必然的結果. 那麼在效能跟繁瑣之間有沒有妥協方案呢? Google 提倡的 protobuf 就是一例. 它的運作原理是, 把資料型態和結構化關係這類額外的資訊另外寫成 .proto 的文件 (protobuf 本身的資料描述語法), 透過 protobuf 提供的編譯功能編譯這些 .proto 文件產生專有的序列化/反序列化模組, 程式運行時再透過這些模組對於該資料類型進行序列化工作. 輸出的二進位資料流的緊密度和效能就由 protobuf 來背書, 理論上會比自述性資料流來得好, 因為要傳輸的資料較密(量較少)且序列化過程中做的事較少.

目前已實現基於 JSON 自述的序列化程序, 正朝 protobuf 前進. 由於需要交換的結構化數據都是用 XML Schema 定義, 所以要做 protobuf 的實現必需先克服由 XML Schema 自動生成 .proto 文件的這一步.

2012年5月11日 星期五

如何查看編譯器預先定義的巨集 (Predefined Macro) 有哪些?

建立跨平台且能兼容各家編譯器的 C/C++ 軟體專案時會需要知道各家 Compiler 在不同平台上分別會設定哪些 Predefined Macro, 以便後續於程式碼中利用.

目前 GNU 和 LLVM-Clang 的 Compiler 不管是 Unix 上或是 Windows 上的 cygwin/mingw 環境中, 都可透過同樣的方式去取得 Predefined Macro 列表:
    <gcc|g++|clang> -dM -E -x <c|c++> <input file>    

例如:
    clang -dM -E -x c /dev/null    
    g++ -dM -E -x c++ /dev/null    

而微軟的 cl 所定義的巨集可以直接查看 msdn 文件.