読者です 読者をやめる 読者になる 読者になる

auとSoftBankのShift_JISからUnicodeへの変換規則

au SoftBank

共にEncode::JP::Mobileのdat/*-table.yamlのデータで検証。

SoftBankShift_JISからUnicode

規則が分かったのでスッキリした。これでShift_JIS(cp932)⇔UnicodeUTF-8を機械的に変換できる。

def softbank_sjis_to_unicode(sjis):
    high = sjis >> 8
    low  = sjis & 0xff

    if high == 0xf7:
        if low < 0xa0:
            base = 0xe100
        else:
            base = 0xe200
    elif high == 0xf9:
        if low < 0xa0:
            base = 0xe000
        else:
            base = 0xe300
    elif high == 0xfb:
        if low < 0xa0:
            base = 0xe400
        else:
            base = 0xe500
    else:
        raise ValueError("not softbank emoji")

    if low < 0x80:
        code = base + (low - 0x40)
    elif low > 0xa0:
        code = base + (low - 0xa0)
    else:
        code = base + (low - 0x41)

    return code

if __name__ == '__main__':
    import yaml
    for x in yaml.load(file('softbank-table.yaml')):
        if x['sjis_auto']:
            assert softbank_sjis_to_unicode(int(x['sjis_auto'], 16)) == int(x['unicode'], 16)

auのShift_JISからUnicode

Shift_JISからauの技術情報のページに載っているUnicode(0x700引く方ではないやつ)に変換する。

# -*- coding: utf-8 -*-

def kddi_sjis_to_unicode(sjis):
    if sjis >= 0xf340 and sjis <= 0xf352:
        # 358-376番
        diff = 921

    elif sjis >= 0xf353 and sjis <= 0xf3ce:
        # 377-499番台
        diff = 2105

    elif sjis >= 0xf3cf and sjis <= 0xf48d:
        # 700番台以降
        diff = 2124

    elif sjis >= 0xf640 and sjis <= 0xf7d1:
        # 1-333番
        diff = 0

    elif sjis >= 0xf7d2 and sjis <= 0xf7e4:
        # 500番台
        diff = 1350

    elif sjis >= 0xf7e5 and sjis <= 0xf7fc:
        # 334-357番台
        diff = -19

    else:
        raise ValueError("not kddi emoji")

    high = sjis >> 8
    low  = sjis & 0xff
    if low < 0x80:
        return 0xe000 + (188 * (high - 0xf0)) + low - 0x40 + diff
    else:
        return 0xe000 + (188 * (high - 0xf0)) + low - 0x41 + diff

if __name__ == '__main__':
    import yaml
    for x in yaml.load(file('kddi-table.yaml')):
        sjis = int(x['sjis'], 16)
        assert kddi_sjis_to_unicode(sjis) == int(x['unicode'], 16)
        assert (sjis - 0x700) == int(x['unicode_auto'], 16)

1-333番台に関しては問題がない。334-357番台は、間に500番台の文字が割り込んでいるためずれているということは推測できるが、(1)なぜ500番台がここに割り込んでいるのか、(2)358番以降の規則性、が分からない。

でもこれだけでも、KDDI JIS⇔Eメール用Shift_JISShift_JIS(cp932)⇔UnicodeUTF-8の変換ができるはず。