やんちのプログラミングメモこんにちは、こちらはやんちのウェブページです。 |
||
リンク
|
ISO-2022-JP to UTF-16 への文字コード変換のサンプル実装。
MinGW + gcc 3.4.2 環境において動作確認してあります。 以下の例は、Iso2022jpToUtf16()の実装の例です。 [iso2022jp_to_utf16_c.zip]
/*
* iso2022jp_to_utf16.c * * Created on: 2008/10/24 * Author: yanch */ /** @file * @brief ISO-2022-JP → UTF-16 への変換実装サンプルプログラム。 * */ /* * 1B 24 40 ESC $ @ JIS C 6226-1978(旧JIS漢字) * 範囲{firstByte(0x21~0x7e), secondByte(0x21~0x7e)} * 1B 24 42 ESC $ B JIS X 0208-1983 または JIS X 0208:1990(新JIS漢字) * 範囲{firstByte(0x21~0x7e), secondByte(0x21~0x7e)} * 1B 28 42 ESC ( B ASCII * 範囲{0x00~0x7f} * 1B 28 49 ESC ( I JIS X 0201(半角カナ) * 範囲{0x21~0x5f} * 1B 28 4A ESC ( J JIS X 0201-1976のラテン文字集合 (ISO/IEC 646の日本版) * 範囲{0x20~0x7e} */ #define STRICT #include <locale.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wchar.h> #include "iso2022jp_to_utf16_share.h" #include "iso2022jp_to_utf16_table_1B2440.h" #include "iso2022jp_to_utf16_table_1B2442.h" #include "iso2022jp_to_utf16_table_1B284A.h" /********************************************************************/ #define CODE_TYPE_OLD_JIS (1) #define CODE_TYPE_NEW_JIS (2) #define CODE_TYPE_ASCII (3) #define CODE_TYPE_HANKAKU_KANA (4) #define CODE_TYPE_RATEN (5) #define CODE_TYPE_BYTE_SIZE1 (6) #define CODE_TYPE_BYTE_SIZE2 (7) #define CODE_TYPE_UNKNOWN (-1) /********************************************************************/ /** * バッファ長。 * 一行毎の文字列を処理するのに必要なバイト数 */ #define DEFAULT_BUFF_LEN 4096 #define DUMMY_CODE (0xff1f) /********************************************************************/ /** * _OPTIONS 構造体 * プログラム起動オプションを格納する構造体 */ struct _OPTIONS { char i[DEFAULT_BUFF_LEN]; char o[DEFAULT_BUFF_LEN]; }; typedef struct _OPTIONS T_OPTIONS; /********************************************************************/ size_t bytelen(const char *string, size_t max_length); char *fgets_for_iso2022jp(char *string, int n, FILE *stream); int getCodeType(char src[], int currenMode); int Iso2022jpToUtf16(wchar_t *dest, size_t dest_size, char *src , size_t src_size); int printUsage(); wchar_t selectUnicodeFromNewJisTable(unsigned long iso2022jpCode); wchar_t selectUnicodeFromOldJisTable(unsigned long iso2022jpCode); /********************************************************************/ /** * メイン関数。 * ここからプログラムの実行を開始します。 * * @param[in] argc 引数の数 * @param[in] argv 引数へのポインタ * @return 戻り値(正常終了時は0を戻す) */ int main(int argc, char *argv[]) { wchar_t bom = 0; int convertCharCount = 0; wchar_t dest[DEFAULT_BUFF_LEN]; size_t dest_size = 0; int i = 0; int iResult = 0; char key[DEFAULT_BUFF_LEN]; int n = 0; T_OPTIONS options; FILE *pInputFile = NULL; FILE *pOutputFile = NULL; char src[DEFAULT_BUFF_LEN]; size_t src_size = 0; /* * ●ロケールを設定 */ _wsetlocale(LC_ALL, L"japanese"); /* * ●入力パラメタチェック */ if (argc < 5) { printUsage(); return 0; } else { memset(&options, 0, sizeof(options)); memset(key, 0, DEFAULT_BUFF_LEN); for (i = 1; i < argc; i++) { if (*argv[i] == '-') { strcpy(key, argv[i]); } else { if (strcmp(key, "-i") == 0) { strcpy(options.i, argv[i]); } else if (strcmp(key, "-o") == 0) { strcpy(options.o, argv[i]); } strcpy(key, ""); } } } if (*(options.i) == '\0' || *(options.o) == '\0') { printUsage(); return 0; } /* * ●ファイルを開く */ pInputFile = fopen(options.i, "rb"); if (pInputFile == NULL) { fwprintf(stderr, L"ファイルが開けません: %s\n", options.i); } pOutputFile = fopen(options.o, "wb"); if (pOutputFile == NULL) { fwprintf(stderr, L"ファイルが開けません: %s\n", options.o); } if ((pInputFile != NULL) && (pOutputFile != NULL)) { bom = 0xfeff; fwrite((char *)&bom, sizeof(wchar_t), 1, pOutputFile); while (feof(pInputFile) == 0) { /* * ●ファイル読込 */ memset(src, 0, sizeof(char) * DEFAULT_BUFF_LEN); n = DEFAULT_BUFF_LEN - 1; if (NULL == fgets_for_iso2022jp(src, n, pInputFile)) { src[0] = '\0'; break; } /* * ●文字コード変換 * ISO-2022-JP:src -> UTF-16:dest 変換 */ memset(dest, 0, sizeof(wchar_t) * DEFAULT_BUFF_LEN); dest_size = DEFAULT_BUFF_LEN - 1; src_size = bytelen(src, sizeof(src)); iResult = Iso2022jpToUtf16(dest, dest_size, src, src_size); if (iResult == (-1)) { fwprintf(stderr, L"Iso2022jpToUtf16() Failed.\n"); if (pInputFile != NULL) { fclose(pInputFile); pInputFile = NULL; } if (pOutputFile != NULL) { fclose(pOutputFile); pOutputFile = NULL; } return 1; } convertCharCount += iResult; /* * ●ファイル書込 */ fputws(dest, pOutputFile); } } /* * ●ファイルを閉じる */ if (pInputFile != NULL) { fclose(pInputFile); pInputFile = NULL; } if (pOutputFile != NULL) { fclose(pOutputFile); pOutputFile = NULL; } wprintf(L"%d 文字変換しました。\n", convertCharCount); return 0; } /********************************************************************/ /** * ゼロ終端バイト列の長さを調べます。 * バイト列がmax_lengthよりも大きい場合は、max_lengthを戻します。 * * @param[in] sting 入力バイト列 * @param[in] max_length バイト列を調べる最大長 * @return 長さ(byte数) */ size_t bytelen(const char *string, size_t max_length) { size_t i = 0; if (string == NULL) { return 0; } for (i = 0; i < max_length; i++) { if (*(string + i) == '\0') { break; } } return i; } /********************************************************************/ /** * ストリームから文字列を読み込みます。 * * @param[out] string データの格納場所 * @param[in] b 格納するバイト数 * @param[in] stream FILE構造体へのポインタ * * @return 成功するとstringを返します。エラーが発生するか、ファイルの終端に達するとNULLを返します。 */ char *fgets_for_iso2022jp(char *string, int n, FILE *stream) { char *buffer; size_t count = 0; size_t size = 0; buffer = string; size = 1; count = 1; while (n) { if (fread(buffer, size, count, stream) != count) { return NULL; } if (*buffer == 0x0a) { return string; } buffer++; n--; } return string; } /********************************************************************/ /** * 入力コードの種類を調べます。 * コードの種類 * CODE_TYPE_OLD_JIS:コードタイプは旧JIS * CODE_TYPE_NEW_JIS:コードタイプは新JIS * CODE_TYPE_ASCII:コードタイプはASCII * CODE_TYPE_HANKAKU_KANA:コードタイプは半角カナ * CODE_TYPE_RATEN:コードタイプはラテン * CODE_TYPE_BYTE_SIZE1:コードタイプはバイトサイズ1 * CODE_TYPE_BYTE_SIZE2:コードタイプはバイトサイズ2 * CODE_TYPE_UNKNOWN:コードタイプは不明 * * @param[in] src 入力ISO-2022-JP文字列 * @param[in] currentMode カレントの文字集合 * @return コードの種類 */ int getCodeType(char src[], int currenMode) { if (src == NULL) { return CODE_TYPE_UNKNOWN; } switch (src[0]) { case 0x1b: switch (src[1]) { case 0x24: switch (src[2]) { case 0x40: /* 1B 24 40 */ return CODE_TYPE_OLD_JIS; case 0x42: /* 1B 24 42 */ return CODE_TYPE_NEW_JIS; default: break; } break; case 0x28: switch (src[2]) { case 0x42: /* 1B 28 42 */ return CODE_TYPE_ASCII; case 0x49: /* 1B 28 49 */ return CODE_TYPE_HANKAKU_KANA; case 0x4a: /* 1B 28 4A */ return CODE_TYPE_RATEN; default: break; } break; default: break; } break; default: switch (currenMode) { case CODE_TYPE_ASCII: case CODE_TYPE_HANKAKU_KANA: case CODE_TYPE_RATEN: return CODE_TYPE_BYTE_SIZE1; case CODE_TYPE_OLD_JIS: case CODE_TYPE_NEW_JIS: return CODE_TYPE_BYTE_SIZE2; default: return CODE_TYPE_UNKNOWN; } } return CODE_TYPE_UNKNOWN; } /********************************************************************/ /** * 文字コードを ISO-2022-JP より UTF-16 へと変換。 * * @param[out] dest 出力文字列 UTF-16 * @param[in] dest_size destの文字数 * @param[in] src 入力文字列 ISO-2022-JP * @param[in] src_size 入力文字列のバイト数 * * @return 成功時には出力文字列の文字数を戻します。 * dest_size に0を指定し、こちらの関数を呼び出すと、変換された * 文字列を格納するのに必要なdestの文字数を戻します。 * 関数が失敗した場合には、(-1)を戻します。 */ int Iso2022jpToUtf16(wchar_t *dest, size_t dest_size, char *src , size_t src_size) { char buffer[4]; int codeType = CODE_TYPE_UNKNOWN; int countNeedsWords = 0; int currentMode = CODE_TYPE_ASCII; int cursor = 0; unsigned long iso2022jpCode = 0; const int nMaxReadSize = 3; int nReadDataSize = 0; int sizeBytes = 0; wchar_t unicode = 0; /* * 入力パラメータをチェック */ if (dest_size) { /* dest_size != 0 */ if (dest == NULL) { /* Error -- Null Pointer Exception : dest */ return (-1); } if (dest_size < 0) { /* Error -- dest_size < 0 */ return (-1); } } if (src == NULL) { /* Error -- Null Pointer Exception : src */ return (-1); } if (src_size < 1) { /* Error -- src_size < 1 */ return (-1); } countNeedsWords = 0; for (cursor = 0; cursor < src_size;) { /* src より3バイトのデータを読み出し */ nReadDataSize = (nMaxReadSize < (src_size - cursor))?(nMaxReadSize) :(src_size - cursor); memcpy(buffer, (src + cursor), nReadDataSize); memset(buffer + nReadDataSize, 0, sizeof(buffer) - nReadDataSize); /* data size の調べる */ codeType = getCodeType(buffer, currentMode); switch (codeType) { case CODE_TYPE_OLD_JIS: sizeBytes = 3; break; case CODE_TYPE_NEW_JIS: sizeBytes = 3; break; case CODE_TYPE_ASCII: sizeBytes = 3; break; case CODE_TYPE_HANKAKU_KANA: sizeBytes = 3; break; case CODE_TYPE_RATEN: sizeBytes = 3; break; case CODE_TYPE_BYTE_SIZE1: sizeBytes = 1; break; case CODE_TYPE_BYTE_SIZE2: sizeBytes = 2; break; default: sizeBytes = 1; break; } /* * dest_size をチェック */ if (dest_size && (dest_size < (countNeedsWords + 1))) { /* Error : memory is not enough for dest */ return countNeedsWords; } /* sizeBytes毎に処理を分岐 */ if (dest_size) { unicode = DUMMY_CODE; switch (codeType) { case CODE_TYPE_OLD_JIS: currentMode = CODE_TYPE_OLD_JIS; break; case CODE_TYPE_NEW_JIS: currentMode = CODE_TYPE_NEW_JIS; break; case CODE_TYPE_ASCII: currentMode = CODE_TYPE_ASCII; break; case CODE_TYPE_HANKAKU_KANA: currentMode = CODE_TYPE_HANKAKU_KANA; break; case CODE_TYPE_RATEN: currentMode = CODE_TYPE_RATEN; break; case CODE_TYPE_BYTE_SIZE1: switch (currentMode) { case CODE_TYPE_ASCII: unicode = ((wchar_t)buffer[0]) & 0x007f; break; case CODE_TYPE_HANKAKU_KANA: iso2022jpCode = ((wchar_t)buffer[0]) & 0x007f; if (iso2022jpCode <= 0x20 || iso2022jpCode == 0x7f) { /* * 規格外のデータだけど、対応。 */ unicode = iso2022jpCode; } else { unicode = iso2022jpCode -0x21 + 0xFF61; } break; case CODE_TYPE_RATEN: iso2022jpCode = ((unsigned long)buffer[0]) & 0x007f; if (iso2022jpCode <= 0x20 || iso2022jpCode == 0x7f) { /* * 規格外のデータだけど、対応。 */ unicode = iso2022jpCode; } else { unicode = iso2022jp_to_utf16_table_1B284A[iso2022jpCode]; } break; default: break; } *dest = unicode; dest++; break; case CODE_TYPE_BYTE_SIZE2: iso2022jpCode = ((unsigned long)buffer[0] << 8) & 0x7f00; iso2022jpCode |= ((unsigned long)buffer[1]) & 0x007f; switch (currentMode) { case CODE_TYPE_OLD_JIS: unicode = selectUnicodeFromOldJisTable(iso2022jpCode); break; case CODE_TYPE_NEW_JIS: unicode = selectUnicodeFromNewJisTable(iso2022jpCode); break; default: break; } *dest = unicode; dest++; break; default: break; } } switch (codeType) { case CODE_TYPE_BYTE_SIZE1: case CODE_TYPE_BYTE_SIZE2: countNeedsWords++; } cursor += sizeBytes; } return countNeedsWords; } /********************************************************************/ /** * printUsage() 関数。 * 使用方法をコンソールに出力します。 */ int printUsage() { wprintf(L"iso2022jp_to_utf16.exe\n"); wprintf(L"ISO-2022-JP から UTF-16 へ文字コードを変換します。\n"); wprintf(L"使用法\n"); wprintf(L"> iso2022jp_to_utf16 -i 入力ファイル -o 出力ファイル[Enter]\n"); return 0; } /********************************************************************/ /** * 新JISテーブルよりUnicodeをセレクトします。 * * @param[in] iso2022jpCode ISO-2022-JPコード * @return Unicode。対応するコードが見つからない場合は DUMMY_CODE を戻す。 */ wchar_t selectUnicodeFromNewJisTable(unsigned long iso2022jpCode) { unsigned char firstByte = 0; unsigned char secondByte = 0; unsigned long firstIndex = 0; unsigned long secondIndex = 0; wchar_t unicode = DUMMY_CODE; firstByte = (unsigned char)((iso2022jpCode >> 8) & 0x7f); secondByte = (unsigned char)((iso2022jpCode) & 0x7f); firstIndex = firstByte; /* 1:isEmpty 2:BitmapIndex 3:index */ if (iso2022jp_to_utf16_index_table_1B2442[firstIndex].byType != BITYPE_BITMAP_INDEX) { return DUMMY_CODE; } secondIndex = iso2022jp_to_utf16_index_table_1B2442[firstIndex].dwIndex + secondByte; if (iso2022jp_to_utf16_index_table_1B2442[secondIndex].byType != BITYPE_INDEX) { return DUMMY_CODE; } unicode = iso2022jp_to_utf16_table_1B2442[ iso2022jp_to_utf16_index_table_1B2442[secondIndex].dwIndex]; if (unicode == 0x0000) { unicode = DUMMY_CODE; } return unicode; } /********************************************************************/ /** * 旧JISテーブルよりUnicodeをセレクトします。 * * @param[in] iso2022jpCode ISO-2022-JPコード * @return Unicode。対応するコードが見つからない場合は DUMMY_CODE を戻す。 */ wchar_t selectUnicodeFromOldJisTable(unsigned long iso2022jpCode) { unsigned char firstByte = 0; unsigned char secondByte = 0; unsigned long firstIndex = 0; unsigned long secondIndex = 0; wchar_t unicode = DUMMY_CODE; firstByte = (unsigned char)((iso2022jpCode >> 8) & 0x7f); secondByte = (unsigned char)((iso2022jpCode) & 0x7f); firstIndex = firstByte; /* 1:isEmpty 2:BitmapIndex 3:index */ if (iso2022jp_to_utf16_index_table_1B2440[firstIndex].byType != BITYPE_BITMAP_INDEX) { return DUMMY_CODE; } secondIndex = iso2022jp_to_utf16_index_table_1B2440[firstIndex].dwIndex + secondByte; if (iso2022jp_to_utf16_index_table_1B2440[secondIndex].byType != BITYPE_INDEX) { return DUMMY_CODE; } unicode = iso2022jp_to_utf16_table_1B2440[ iso2022jp_to_utf16_index_table_1B2440[secondIndex].dwIndex]; if (unicode == 0x0000) { unicode = DUMMY_CODE; } return unicode; } ・2009-01-07
|
右サイドメニュー
|