本来ならJISとShift-JISの約束をコードにすると、次のようになります。JISもSJISも2Byteコードなので、引数も戻り値も1文字分のWord(2Byte)です。
function
JisToSJis(jis: Word): Word; var hib, lob: Word; begin hib:= (jis shr 8) and $FF; lob:= jis and $FF; if Boolean(hib and 1) then lob:= lob + $1F else lob:= lob + $7D; if lob >= $7F then Inc(lob); hib:= ((hib - $21) shr 1) + $81; if hib > $9F then hib:= hib + $40; Result:= (hib shl 8) or lob; end; |
インラインアセンブラで書くと次の通り。
function
JisToSJis(jis: Word): Word; assembler; asm add ax,0a17eh ; shr ah,1 ; jb @1 cmp al,0deh ; sbb al,5eh @1: xor ah,0e0h end; |
後者の方が若干高速なのかしら。大して違わないか。
上の逆の処理ですな。
function
SJisToJis(sjis: Word): Word; var hib, lob: Byte; begin hib:= (sjis shr 8) and $FF; lob:= sjis and $FF; if hib <= $9F then hib:= hib - $71 else hib:= hib - $B1; hib:= (hib shl 1) + 1; if lob > $7F then Dec(lob); if lob >= $9E then begin lob:= lob - $7D; Inc(hib); end else lob:= lob - $1F; Result:= (hib shl 8) or lob; end; |
で、下がそのアセンブラ版。
function
SJisToJis(sjis: Word): Word; assembler; asm shl ah,1 ; sub al,1fh ; js @1 cmp al,61h ; adc al,0deh @1: add ax,1fa1h ; and ax,7f7fh end; |
若干面倒ですが、次のようにすればいけると思います。
function
SJisToEuc(sjis: Word): Word; var hib, lob: Byte; begin hib:= (sjis shr 8) and $ff; lob:= sjis and $ff; if hib <= $9f then hib:= hib - $71 else hib:= hib - $b1; hib:= (hib shl 1) + 1; if lob >= $9e then begin lob := lob - $7e; Inc(hib); end else if lob > $7f then lob := lob - $20 else lob := lob - $1f; hib:= hib or $80; lob:= lob or $80; Result:= (hib shl 8) or lob; end; |
実は、EUCコードというのは、JISコードと8080hとの論理和をとったものになります。なので、SJisToJis の結果を使って次のように書くとスッキリします。
function
SJisToEuc(sjis: Word): Word; begin Result:= SJisToJis(sjis) or $8080; end; |
とりあえず、まともにやると次の通りです。
function
HankToZenk(wrd: Word): Word; const z : Array [1..64] of Word = ($2121,$2123,$2156,$2157,$2122,$2126,$2572,$2521, $2523,$2525,$2527,$2529,$2563,$2565,$2567,$2543, $213c,$2522,$2524,$2526,$2528,$252a,$252b,$252d, $252f,$2531,$2533,$2535,$2537,$2539,$253b,$253d, $253f,$2541,$2544,$2546,$2548,$254a,$254b,$254c, $254d,$254e,$254f,$2552,$2555,$2558,$255b,$255e, $255f,$2560,$2561,$2562,$2564,$2566,$2568,$2569, $256a,$256b,$256c,$256d,$256f,$2573,$212b,$212c); begin if (wrd < $A0) or (wrd > $DF) then Result:= 0 else Result:= z[wrd - $A0]; end; function EucToSJis(euc: Word): Word; var jis: Word; hib, lob: Byte; begin if (euc and $ff00) = $8e00 then jis:= HankToZenk(euc and $ff) else jis:= euc and (not $8080); hib:= (jis shr 8) and $ff; lob:= jis and $ff; if (hib and 1) <> 0 then lob:= lob + $1f else lob:= lob + $7d; if lob >= $7f then Inc(lob); hib:= ((hib - $21) shr 1) + $81; if hib > $9f then hib:= hib + $40; Result:= (hib shl 8) or lob; end; |
HankToZenk というのは半角カナを全角カナに変換する関数です。
で、EUCコードと7F7Fhとの論理積はJISコードになるので、JisToSJis を使えば次のように簡略することもできます。
function EUCToSJis(euc: Word): Word; begin Result:= JisToSJis(euc and $7F7F); end; |
びゅーちふる。
Windowsではあまり使わないと思うんですが、とりあえず次の通りです。JISコードと8080hとの論理和をとれば、それがEUCコードです。
function
JisToEuc(jis: Word): Word; begin Result:= jis or $8080; end; |
アセンブラで決めたければ次の通り。
function
JisToEuc(jis: Word): Word; asm or ax,8080h end; |
EUCコードと7F7Fhとの論理積がJISコードです。なので、次の通り。
function EucToJis(euc: Word): Word; begin Result:= euc and $7F7F; end; |
そのアセンブラ版。
function EucToJis(euc: Word): Word; asm and ax,7F7Fh end; |
EBCDICとASCIIの間には変換の法則性はありません。ですので、テーブルをゴリゴリ作って、それで対照して戻してやるしかないです。やるとすれば次のような感じになります。
const { EBCDIC→ASCII変換用テーブル } tblEToA: Array [0..255] of Byte = ($00, $01, $02, $03, $9c, $09, $86, $7f, //00-07 $97, $8d, $8e, $0b, $0c, $0d, $0e, $0f, //08-0F $10, $11, $12, $13, $9d, $85, $08, $87, //10-17 $18, $19, $92, $8f, $1c, $1d, $1e, $1f, //18-1F $80, $81, $82, $83, $84, $0a, $17, $1b, //20-27 $88, $89, $8a, $8b, $8c, $05, $06, $07, //28-2F $90, $91, $16, $93, $94, $95, $96, $04, //30-37 $98, $99, $9a, $9b, $14, $15, $9e, $1a, //38-3F $20, $a0, $a1, $a2, $a3, $a4, $a5, $a6, //40-47 $a7, $a8, $5b, $2e, $3c, $28, $2b, $21, //48-4F $26, $a9, $aa, $ab, $ac, $ad, $ae, $af, //50-57 $b0, $b1, $5d, $24, $2a, $29, $3b, $5e, //58-5F $2d, $2f, $b2, $b3, $b4, $b5, $b6, $b7, //60-6F $b8, $b9, $7c, $2c, $25, $5f, $3e, $3f, //68-6F $ba, $bb, $bc, $bd, $be, $bf, $c0, $c1, //70-77 $c2, $60, $3a, $23, $40, $27, $3d, $22, //78-7F $c3, $61, $62, $63, $64, $65, $66, $67, //80-87 $68, $69, $c4, $c5, $c6, $c7, $c8, $c9, //88-8F $ca, $6a, $6b, $6c, $6d, $6e, $6f, $70, //90-97 $71, $72, $cb, $cc, $cd, $ce, $cf, $d0, //98-9F $d1, $7e, $73, $74, $75, $76, $77, $78, //A0-A7 $79, $7a, $d2, $d3, $d4, $d5, $d6, $d7, //A8-AF $d8, $d9, $da, $db, $dc, $dd, $de, $df, //B0-B7 $e0, $e1, $e2, $e3, $e4, $e5, $e6, $e7, //B8-BF $7b, $41, $42, $43, $44, $45, $46, $47, //C0-C7 $48, $49, $e8, $e9, $ea, $eb, $ec, $ed, //C8-CF $7d, $4a, $4b, $4c, $4d, $4e, $4f, $50, //D0-D7 $51, $52, $ee, $ef, $f0, $f1, $f2, $f3, //D8-DF $5c, $9f, $53, $54, $55, $56, $57, $58, //E0-E7 $59, $5a, $f4, $f5, $f6, $f7, $f8, $f9, //E8-EF $30, $31, $32, $33, $34, $35, $36, $37, //F0-F7 $38, $39, $fa, $fb, $fc, $fd, $fe, $ff);//F8-FF function EbcdicToAscii(e: Char): Char; begin Result:= Chr(tblEToA[Ord(e)]); end; |
EBCDICの仕様はNEC系とか日立系などベンダーによって微妙に変更されていたりするので、上のテーブルもそれにあわせてカスタマイズが必要になるかもしれません。この例のテーブルは一般的なものです。
ASCIIとEBCDICの間には変換の法則はないので、やはりテーブルを作るしかないです。
const { ASCII→EBCDIC(K)変換用テーブル } tblAToE: Array [0..255] of Byte = ($00, $01, $02, $03, $37, $2d, $2e, $2f, //00-07 $16, $05, $25, $0b, $0c, $0d, $0e, $0f, //08-0F $10, $11, $12, $13, $3c, $3d, $32, $26, //10-17 $18, $19, $3f, $27, $1c, $1d, $1e, $1f, //18-1F $40, $4f, $7f, $7b, $5b, $6c, $50, $7d, //20-27 $4d, $5d, $5c, $4e, $6b, $60, $4b, $61, //28-2F $f0, $f1, $f2, $f3, $f4, $f5, $f6, $f7, //30-37 $f8, $f9, $7a, $5e, $4c, $7e, $6e, $6f, //38-3F $7c, $c1, $c2, $c3, $c4, $c5, $c6, $c7, //40-47 $c8, $c9, $d1, $d2, $d3, $d4, $d5, $d6, //48-4F $d7, $d8, $d9, $e2, $e3, $e4, $e5, $e6, //50-57 $e7, $e8, $e9, $4a, $e0, $5a, $5f, $6d, //58-5F $79, $81, $82, $83, $84, $85, $86, $87, //60-67 $88, $89, $91, $92, $93, $94, $95, $96, //68-6F $97, $98, $99, $a2, $a3, $a4, $a5, $a6, //70-77 $a7, $a8, $a9, $c0, $6a, $d0, $a1, $07, //78-7F $20, $21, $22, $23, $24, $15, $06, $17, //80-87 $28, $29, $2a, $2b, $2c, $09, $0a, $1b, //88-8F $30, $31, $1a, $33, $34, $35, $36, $08, //90-97 $38, $39, $3a, $3b, $04, $14, $3e, $e1, //98-9F $41, $42, $43, $44, $45, $46, $47, $48, //A0-A7 $49, $51, $52, $53, $54, $55, $56, $57, //A8-AF $58, $59, $62, $63, $64, $65, $66, $67, //B0-B7 $68, $69, $70, $71, $72, $73, $74, $75, //B8-BF $76, $77, $78, $80, $8a, $8b, $8c, $8d, //C0-C7 $8e, $8f, $90, $9a, $9b, $9c, $9d, $9e, //C8-CF $9f, $a0, $aa, $ab, $ac, $ad, $ae, $af, //D0-D7 $b0, $b1, $b2, $b3, $b4, $b5, $b6, $b7, //D8-DF $b8, $b9, $ba, $bb, $bc, $bd, $be, $bf, //E0-E7 $ca, $cb, $cc, $cd, $ce, $cf, $da, $db, //E8-EF $dc, $dd, $de, $df, $ea, $eb, $ec, $ed, //F0-F7 $ee, $ef, $fa, $fb, $fc, $fd, $fe, $ff);//F8-FF function AsciiToEbcdic(a: Char): Char; begin Result:= Chr(tblAToE[Ord(a)]); end; |
力技ですな。
[ Delphi へ戻る ]