|
|
|
ホーム
全記事一覧
<< 前の記事
次の記事 >>
|
|
|
| |
| | 2008/10/07 11:40||▲
|
|
| 今回はlocaleconv関数の実装に関するお話です。localeconvは、現在のロケールに応じた、数値や金額の変換方法に関する情報を取得するための関数です。
今回、とりあえずは"C"ロケールにのみ対応することにしましたが、他のロケールに対応する余地を残すために、現在のロケールに応じたlconv構造体へのポインタを、いったん大域変数__lconvに格納することにします。そして、__lconvは、"C"ロケール用のlconv構造体__lconv_Cを指すように初期化します。
/* __lconv_C.c */ const struct lconv __lconv_C = { ".", "", "", "", "", "", "", "", "", "", CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, };
const struct lconv *__lconv = &__lconv_C;
そして、効率化のため、__lconvおよび__lconv_Cは<locale.h>の中で宣言し、localeconvはインライン関数として実装することにします。
#ifdef __cplusplus extern "C" { #endif extern const struct lconv __lconv_C; extern const struct lconv *__lconv; #ifdef __cplusplus } #endif
static __inline__ struct lconv *localeconv(void) { return (struct lconv*)__lconv; }
ここで、"C"ロケールしか扱わない場合は、いったん__lconvを介して間接参照するのは無駄ですので、
#ifdef __ONLY_C_LOCALE #define __lconv (&__lconv_C) #endif
として、"C"ロケール限定の場合は、__lconv_Cを直接アクセスするようにします。
ここで一つ大きな問題が発生します。それは、__lconv_Cの初期化に使用しているCHAR_MAXです。これは規格上、値がCHAR_MAXに定められているためにそのようにしているのですが、CHAR_MAXの値はコンパイルオプションによって、すなわち、char型の符合の有無によって異なってくるのです。
仕方がないので、上記の定義はデフォルト(=符号なし)の場合のものとし、符号付の場合は、__lconv_Cの代わりに__lconv_C_sを、__lconvの代わりに__lconv_sを使用するようにせざるを得ないようです。結局のところ、
#ifndef __CHAR_UNSIGNED__ #define __lconv_C __lconv_C_s #define __lconv __lconv_s #endif
#ifdef __cplusplus extern "C" { #endif extern const struct lconv __lconv_C; extern const struct lconv *__lconv; #ifdef __cplusplus } #endif
#ifdef __ONLY_C_LOCALE #define __lconv (&__lconv_C) #endif
static __inline__ struct lconv *localeconv(void) { return (struct lconv*)__lconv; }
のように、条件付きコンパイルが必要になりそうです。
ところで、規格上は<locale.h>をインクルードせず、ユーザーが自分でlconv構造体の定義と、localeconvの関数原型を記述して使用してもよいことになっていますが、さすがにその場合は対処の方法がありません。
今回は、厳密には規格に反するものの、<locale.h>ヘッダを必須とした方が有益であると判断し、localeconvの外部定義は行わないことにします。
なお、他の標準ライブラリ関数は、見かけ上、localeconvを呼び出さないかのような実装を行うことが要求されています。通常、localeconvを用いて取得する情報(小数点文字など)には、__lconvを使用することにします。
"C"ロケール以外に対応させるには、setlocale関数を用いて__lconvに異なるlconv構造体を参照させるようにするか、あるいは、"C"ロケール以外の単一のロケールに固定するのであれば、__lconv_C.cを必要なロケールに対応したファイルに置き換えてしまうか、どちらかの方法で対応することになるでしょう。後者の方法(__lconv_C.c)は正当な方法ではありませんが、メモリの少ない環境では有効です。
| | 2006/01/30 20:35|文化圏固有動作|TB:0|CM:0|▲
|
| |
コメント
| |
コメントの投稿
| |
|
| |
トラックバック
|
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/20-2c49e44a
|
| |
|
|
ホーム
全記事一覧
<< 前の記事
次の記事 >>
|
|
|