從「萬碼奔騰」到「五碼諧和」
在工作上,經常會碰到萬碼奔騰的狀況,常搞的我一個頭兩個大,還好經過一年多的努力,處理 i18n 的程式庫大致有了個基礎,雖不完整,但也堪用。我有試著讓這堆 i18n 的程式儘可能地一致有條理,但邊造槍邊上戰場,還是有很多地方雜草叢生,旁枝錯節,無法達到完美和諧。所以我也只能盡量,將「萬碼奔騰」化約為「五碼諧和」,便是其中的一個嘗試。
世界上的語言千萬種,應用在電腦上,各家都要有自己的一套,因而造成了「萬碼奔騰」的現況。雖然 Unicode 包容萬碼的理想極其崇高偉大,但是革命尚未成功,同志仍須努力。一天這個世界還不能大一統,身為師程工的我們,就必須要身先士卒,代替普羅大眾,面對萬碼侵襲。
還好,我們有「化約」這個武器,可以化繁為簡,萬宗歸五,將「萬碼」化約成「五碼」,挑出重點,各個擊破。哪五碼?RAW、MBCS、WCCS、U8CS 以及 CLCS 這五碼,各有各的花名,招式相同的,大家一條褲子一起穿,招式不同的,那就各顯本事,各展奇才。口說無憑,有表有真相。
| 編碼 | 字元 | 字串 | 說明 | ||
|---|---|---|---|---|---|
| 花名 | 型別 | 花名 | 型別 | ||
| RAW | - | char |
str | char* |
無招勝有招,赤裸裸的 bytes 專門演出無碼劇。本應使用 byte_t 為其型別,但為與大多數的舊有 C 程式介面相容,故仍沿用 char。 |
| MBCS | mbc | char* |
mbs | char* |
用多個 bytes 表達一個 character 的編碼形式。某些 MBCS 需要 shift-state 的支援。對 C/C++ 來說,MBCS 對應到目前唯一的 global locale。 |
| WCCS | wcc | wchar_t |
wcs | wchar_t* |
由 OS/Compiler 廠商決定的固定長度 Unicode 編碼,無法跨平台,兼有包容與速度的優勢。 |
| U8CS | u8c | char* |
u8s | char* |
即 UTF-8,為近年流行的跨平台之不固定長度 Unicode 編碼,未來的烏托邦,便是只剩下 WCCS 與 U8CS 這兩種碼的大一統世界。雖然現在還不是,但我們必須向著這個方向走。 |
| CLCS | lcc | byte_t* |
lcs | byte_t* |
CLCS 為 Custom Locale Character Set 的縮寫,即指定 locale 的編碼方式。當其他四碼都不行時,就只有靠他了。 |
為了分辨彼此,各招的名稱,必須內含各碼的花名。舉例來說,光就「長度」這一項,就可以分化成三個變化:有多少個 bytes、有多少個 characters 以及畫在終端機螢幕上時,佔用多少個基本寬度。將上表套用這三個變化,就成了以下各招的招型:
- 有多少個 bytes:除了 RAW 字元以外,不論字元或字串,都有佔用 bytes 數的問題。其中,WCCS 字元佔用的 bytes 數為常數,其值各平台不一定相同。
size_t adk_str_nbytes(const char* str); size_t adk_mbc_nbytes(const char* mbc); size_t adk_mbs_nbytes(const char* mbs); #define ADK_WCC_NBYTES sizeof(wchar_t) size_t adk_wcc_nbytes(); size_t adk_wcs_nbytes(const wchar_t* wcs); size_t adk_u8c_nbytes(const char* u8c); size_t adk_u8s_nbytes(const char* u8s); size_t adk_lcc_nbytes(const char* loc, const byte_t* lcc); size_t adk_lcs_nbytes(const char* loc, const byte_t* lcs);
- 有多少個 characters:對 RAW 編碼方式無意義。
size_t adk_mbs_nchars(const char* mbs); size_t adk_wcs_nchars(const wchar_t* wcs); size_t adk_u8s_nchars(const char* u8s); size_t adk_lcs_nchars(const char* loc, const byte_t* lcs);
- 畫在終端機螢幕上時,佔用多少個基本寬度:對 RAW 編碼方式無意義。對於傳統 CJK 來說,有所謂「寬字元」的存在,印在終端機螢幕上時,佔用普通字元的兩倍寬。
size_t adk_mbc_width(const char* mbc); size_t adk_mbs_width(const char* mbs); size_t adk_wcc_width(wchar_t wcc); size_t adk_wcs_width(const wchar_t* wcs); size_t adk_u8c_width(const char* u8c); size_t adk_u8s_width(const char* u8s); size_t adk_lcc_width(const char* loc, const byte_t* lcc); size_t adk_lcs_width(const char* loc, const byte_t* lcs);
而例外狀況,就交由特殊的招式處理。好比說應付 C++ template parameter 於 coding-time 仍未知的字元、字串型別,我們可以有 TPCS,使用 tcc 與 tcs 的花名,自動於 compile-time 的 template parameter resolution 時,轉換為對應的 MBCS 或 WCCS 型別。或者,為了處理與大五碼 (big5) 相容的特殊需求,我們可以有 B5CS,使用 b5c 與 b5s 的花名,針對 wcc/u8c/lcc/wcs/u8s/lcs 與 b5c/b5s 的可轉換性,進行處理。
如此,透過「萬碼化五碼」及「花名制」,就算與字元處理的招式再多,面對萬碼,仍然還是只有這五碼,簡單易懂,方便使用。
2 Comments
這篇文章用字不像之前樸素的Jeff,反而比較像對岸的同胞? XD
平時坐車慣了看對岸的 YY 小說,一不小心模式切了過去,就變這樣了。
不過,練練口花花也好,我就欠這個。:-p
(也可能是最近看了天龍進的簡體電腦雜誌的緣故。)
Post a Comment