SJISの扱い方
そんなわけで、フォント表示を作っていたときに、SJISコードについて調べたので、作業記録を残しておきます。
SJISコードでは、文字列を先頭から読み込んだ時の1byte目には[0x81,0x9f]の範囲と、[0xe0,0xef]の範囲の値が入ります。
そして、続く2byte目には、[0x40,0xfc]の範囲の値が入ります。
ただし、2byte目の範囲には、0x7fは含まれません。
また、asciiコードの範囲は[0x20,0x7e]、半角カナコードの範囲は[0xa1,0xdf]となります。
(ここで、[x,y] の表記は、x以上、y以下の範囲(x,yどちらも含める)としました)
まとめますと、
asciiコードの範囲 [0x20,0x7e]
半角カナコードの範囲 [0xa1,0xdf]
SJISコードの1byte目 [0x81,0x9f] もしくは [0xe0,0xef]
SJISコードの2byte目 [0x40,0xfc]
となります。
さて、SJISで表現されたchar配列から、文字入力ストリームを作ることを考えて見ることにします。
char配列を読み込みながら、一文字分の文字を返してくれるようなストリームです。
例えば、こんな感じ...
char a_str[] = "あいうえおacdeカキクケコ"; CharStream a_cs( a_str, strlen( a_str ) ); char a_buf[3]; while( a_cs.ReadNext( a_buf ) ){ printf( "%s\n", a_buf ); }
出力結果
あ い う え お a b c d カ キ ク ケ コ
重要な部分だけの、擬似コードを書いてみると
bool IsSJISReaderByte( char i_c ) { int code = i_c; if( (0x81 <= code) && (code <= 0x9f) || (0xe0 <= code) && (code <= 0xef) ){ return true; } return false; } bool CharStream::ReadNext( char* i_output ) { if( IsFail() ){ return false; } char a_c = readByte(); if( IsSJISReaderByte( a_c ) ){ i_output[ 0 ] = a_c; i_output[ 1 ] = readByte(); i_output[ 2 ] = '\0'; }else{ i_output[ 0 ] = a_c; i_output[ 1 ] = '\0'; } return true; }
こんな感じになります
逆に、SJISコードを全部出力したい場合には、
void printSJISChar() { char a_buf[3]; for( u16 a_hi = 0x81; a_hi <= 0x9f; a_hi++ ){ for( u16 a_low = 0x40; a_low <= 0xfc; a_low++ ){ if( a_low != 0x007f ){ a_buf[0] = a_hi; a_buf[1] = a_low; a_buf[2] = '\0'; printf( "%s", a_buf ); } } } }
こんな感じにダンプすれば良いでしょう。
ま、文字コードの範囲さえわかっちゃえば、やることは簡単ですよね