2023-05-17
mgl-msgconv - CSV to メッセージデータコンバータ
mgl-msgconv csv-filename [options]
mgl-msgconvは多言語に対応したメッセージデータをバイナリデータまたは C/C++のソースコードで出力するためのツールです.
メッセージデータの入力にはCSV形式のファイルを用います.書式の詳細に ついては後述のCSV FORMATを参照してください.
変換元となるCSVファイルはRFC 4180に準拠したUTF-8エンコーディングである 必要があります.多くのソフトウェアでは,区切り文字に','を,改行コードに CR+LFを指定することでRFC 4180に準拠したCSVファイルを出力します.
最初のレコードには言語名を記述します.フィールドの最初に"id"と記述し, 以降のフィールドに対応する言語名を記述してください.最初に記述した言語 はデフォルトの言語となります.
例: id, en_US, ja_JP
2行目以降のレコードには最初にメッセージIDを記述し,以降に対応した言語の メッセージを入力してください.メッセージを空欄にした場合,デフォルトの 言語のメッセージが使用されます.
例: HelloWorld, "hello, world", "こんにちは,世界"
言語名とメッセージIDはC/C++の変数名の命名規則に基づいた名前を推奨します.
--hash-seed
バイナリ出力時に使用するハッシュ生成関数のシード値を指定します. 指定しなかった場合は0xA3F6C23Eが使用されます.ハッシュ値が衝突を 起こす場合はこのオプションを使用してシード値を変更してください.
--help
簡易ヘルプを表示して終了します.
--indexing, --indexing-all
メッセージデータの文字をインデックスに変換して出力し,同時に
使用文字リストをJSON形式で出力します.使用文字リストはUnicode
との関連付けを解決するために用いられる他,mgl-font2texに指定
してテクスチャ生成にも利用できます.--indexing
を指定した場合は
言語ごとにインデックス化を行い,--indexing-all
を指定した場合は
全ての言語をまとめてインデックス化します.--source
オプションが
指定されている場合,このオプションは無視されます.
--output, -o
出力ディレクトリを指定します.指定しなかった場合はカレント ディレクトリに出力します.
--prefix, -p
出力ファイルのプリフィックスを指定します.指定しなかった場合は "msg"が使用されます.
--replace
既存のファイルの一部をコンバート結果で置換して出力します.置換元 ファイル内に置換コマンドを記述することで,その部分が変換結果に 置き換えられます.置換コマンドの詳細については TEXT REPLACEの セクションを参照してください.
--source, -s
変換結果をCまたはC++で利用可能な文字列で出力します.このオプション
を使用した場合,バイナリデータとその関連ファイルは出力されません.
出力ファイルは言語ごとの文字列テーブルをプリフィックス+言語名+
".inc"の名前で,メッセージIDをプリフィックス+"_id.inc"の名前で
出力します.--replace
オプションを使用する場合,これらのファイル
は出力されません.
--version, -v
バージョン情報を表示して終了します.
0
成功
それ以外
失敗
置換元のテキストに'$'で囲まれた文字列を記述することで,mgl-msgconvは その文字列を置換コマンドとして認識します.
Example: $REPLAC_COMMAND$
置換コマンドを':'で区切ることによって,それ以降の文字列はコマンドの 引数として扱われます.
Example: $REPLAC_COMMAND:argument$
置換コマンドは行の先頭に書かなければならず,スペースとタブ以外の文字が 先に記述されている場合は置換コマンドとして認識されません.コマンド前の インデントは結果に反映されます.置換は行単位で行われるため,その置換 コマンド以降から改行までの文字列は全て無視されます.
ID_LIST
その行にメッセージIDのリストを出力します.ソースコード出力の場合 はMESSAGE_LISTによる出力と同じ順で,バイナリ出力の場合はバイナリ ファイルが保持するハッシュ値の定義として出力します.
LANGUAGE_LIST
その行に言語名のリストを出力します.出力順はCSVの最初のレコード に記述したフィールドの順です.
MESSAGE_LIST:language
引数で指定した言語のメッセージリストをその行に出力します.この コマンドはソースコード出力でのみ使用可能です.出力順はCSVに 記述した順です.
IF:condition
その行にCプリプロセッサの#ifディレクティブを出力します.引数には 条件を指定し,出力時に0または1に置き換えられます.有効な引数は 後述の条件の節を参照してください.
ELIF:condition
その行にCプリプロセッサの#elifディレクティブを出力します.引数 には条件を指定し,出力時に0または1に置き換えられます.有効な引数 は後述の条件の節を参照してください.
ELSE
その行にCプリプロセッサの#elseディレクティブを出力します.
ENDIF
その行にCプリプロセッサの#endifディレクティブを出力します.
OUTPUT_NAME:name
置換後のファイルの名前を指定します.nameに相対パスを指定した
場合,--output
オプションに指定したパスを起点とします.この
コマンドを使用しなかった場合は入力ファイル名と同じ名前が使用
されます.入力ファイルと出力ファイルが等価である場合,名前の
末尾に".replaced"を付与して上書きを防ぎます.
SOURCE
ソースコード出力の場合に1を,そうでなければ0を出力します.
BINARY
バイナリ出力の場合に1を,そうでなければ0を出力します.
INDEXED
--indexing
または--indexing-all
を使用してインデックス文字列を
出力する場合に1を,そうでなければ0を出力します.
TRUE
常に1を出力します.
FALSE
常に0を出力します.
コンバータが出力するバイナリデータには,次の順で内容が格納されています.
全ての値のバイトオーダーはリトルエンディアンです.
ヘッダは合計24バイトで,次のパラメータが格納されています.
+0 hashSeed (4バイト)
このファイルが使用するハッシュ計算のシード値です.--hash-seed
オプションで指定した値がこの領域に格納されます.mgl-msgconvが
使用するハッシュ生成アルゴリズムについてはHASH ALGORITHMの節を
参照してください.
+4 identify (4バイト)
このファイルがメッセージデータである事を確認するための識別子で, hashSeedを用いて文字列"MessageData"をハッシュ化した値が格納 されています.この領域はこのファイルがメッセージデータであること を確認すると同時に,ハッシュ生成アルゴリズムが意図した値を算出 するかのチェックも兼ねています.
+8 revision (4バイト)
このバイナリフォーマットのリビジョン情報です.現在は常に0であり, 将来フォーマットの変更が行われた場合に加算される予定です.
+12 languageCount (4バイト)
メッセージデータに収録されている言語数です.
+16 identifyCount (4バイト)
メッセージデータに収録されているメッセージIDの数です.
+20 flags (4バイト)
メッセージデータの属性を表すビットフラグです.内容は後述する ヘッダのビットフラグを参照してください.
0ビット: インデックス文字列フラグ
メッセージプールに格納されている文字列がインデックス文字列である かを表すフラグです.このフラグが0である場合,メッセージデータは UTF-8でエンコーディングされています.
1ビットから31ビット: 未使用
この領域は現在使用されていません.
言語テーブルにはCSVで指定した言語名の32ビットハッシュ値が格納されていま す. 合計サイズは言語数x4バイトです.
このテーブルは与えられた言語からインデックスを導出する際に使用します.
メッセージIDのハッシュテーブルには,CSVで指定した各IDの名前を32ビットの ハッシュ値に変換した値が格納されています. 合計サイズはメッセージIDの数x4バイトです.
このテーブルは与えられたメッセージIDからインデックスを導出する際に使用 します.
オフセットプールは言語とメッセージIDからメッセージの格納先を導出する ための値が格納されています.最初の4バイトにプールサイズがバイト数で 格納されており,その次からプールサイズ分の領域がオフセットプールと なります.
オフセットプールはメッセージプール上のオフセット値が4バイト単位で格納 された配列です.言語とメッセージIDからオフセット値を得るためには,次の 方法で算出されたインデックスの要素を読み取ります.
メッセージIDのインデックス * 言語数 + 言語のインデックス
このインデックスから読み取った要素はメッセージプールのインデックスとして 使用します.
メッセージプールはメッセージデータを格納している領域です.最初の4バイト にプールサイズがバイト数で格納されており,その次からプールサイズ分の 領域がメッセージプールとなります.
オフセットプールから読み取った要素をインデックスとしてアクセスすること によって,言語とメッセージIDに対応したメッセージデータの先頭が取得でき ます.
メッセージプールの要素1つあたりのサイズはエンコーディングによって異なり ます.メッセージがUTF-8で格納されている場合は1バイトであり,インデックス 文字列の場合は2バイトです.
各メッセージは終端記号によって終端されています.終端記号はUTF-8の場合は 0x00であり,インデックス文字列の場合は0xFFFFです.
フッタは4バイトで,文字列"EndOfRecord"をハッシュ化した32ビット値が格納 されています.全ての要素を読み込んだ後にこの値が読み取れない場合, メッセージデータのパースに失敗している可能性があります.
mgl-msgconvはハッシュ生成にFNV1aアルゴリズムを使用します.この アルゴリズムをC++で実装する例を次に示します.
constexpr uint32_t kFNV1aPrime32 = 0x1000193;
constexpr uint32_t FNV1a(
const char *str,
const uint32_t seed) noexcept
{
if (str[0] == '\0')
{
return seed;
}
return FNV1a(
&str[1],
(seed ^ uint32_t(str[0])) * kFNV1aPrime32);
}
mgl-font2tex(1)