C99に対応した標準Cライブラリの実装レポートを行っていきます。

プロフィール 

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

ホーム 全記事一覧 << 前の記事 次の記事 >>

 

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:0CM:0

コメント
コメントの投稿

管理者にだけ表示を許可する


トラックバック
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/20-2c49e44a

ホーム 全記事一覧 << 前の記事 次の記事 >>

ブログ内検索 

お勧め書籍 

RSSフィード 

リンク 

このブログをリンクに追加する

Powered By FC2ブログ 

Powered By FC2ブログ
ブログやるならFC2ブログ

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. 無料ホームページ アフィリエイト レンタルサーバー FC2ブログ 一戸建て template designed by 遥かなるわらしべ長者への挑戦.