ja_JP ロケールにおける wctype(3)/iswctype(3), wctrans(3)/towctrans(3)

wctype(3) は引数として渡された名前に対応した property を返し,これを利用して iswctype(3) である文字がその property を持っているかどうか判定する.どんな property があるかはロケールに依存しているが,alnum, alpha, blank 等の全てのロケールで使えるものもある.これらの property による判定はそれぞれよく知られている isalnum(3), isalpha(3), isblank(3) 等と同じ.

wctrans(3)/towctrans(3) は似たようなインターフェイスで文字の変換を行う.全てのロケールで使えるものは tolower, toupper で,それぞれ tolower(3), toupper(3) にあたる.

で,日本の ja_JP ロケールにおいては /usr/share/i18n/locales/ja_JP を見てみると wctype(3) に渡せる名前として

  • jspace
  • jhira
  • jkata
  • jkanji
  • jdigit

が使え,wctrans(3) には

  • tojhira
  • tojkata

が使えるみたい.

とりあえず手元の Linux 環境と ideone で以下のコードが意図した通りに動いたけど,どれくらい広く利用可能なのか,*BSD 系でも同様に動作するのかは知らない.
http://ideone.com/7kWcM

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>

static void sample_wctype(const wchar_t *str, const char *name)
{
  const wctype_t wc = wctype(name);
  if (wc == (wctype_t)0) {
    fprintf(stderr, "wctype(%s) is not supported in this locale\n", name);
    return;
  }

  const size_t len = wcslen(str);
  size_t i;
  for (i = 0; i < len; i++) {
    wprintf(L"is%s? %lc => %d\n", name, str[i], iswctype(str[i], wc));
  }
}

static void sample_wctrans(const wchar_t *str, const char *name)
{
  const wctrans_t wct = wctrans(name);
  if (wct == (wctrans_t)0) {
    fprintf(stderr, "wctrans(%s) is not supported in this locale\n", name);
    return;
  }

  const size_t len = wcslen(str);
  size_t i;
  for (i = 0; i < len; i++) {
    wprintf(L"%s %lc => %lc\n", name, str[i], towctrans(str[i], wct));
  }
}

int main(void)
{
  if (setlocale(LC_ALL, "ja_JP.UTF-8") == NULL) {
    fputs("setlocale failed\n", stderr);
    return 1;
  }

  const wchar_t str[] = L"廾ゃヵ";

  sample_wctype(str, "jkata");
  sample_wctype(str, "jkanji");
  sample_wctrans(str, "tojkata");

  return 0;
}