Last Update: Jul.16,2004

C Source Library

「LSI C-86 Ver.3.30c 試食版」、「Borland C++ 5.5」でコンパイル出来ます。

■ Unicode/UTF-8 相互変換

/*
 *  utf8.c : Unicode <-> UTF-8 相互変換
 *
 *      Copyright (c) 2004 AOK. 
 *  
 *      2004.07.14 - 初版
 *
 *      UCS-2       UTF-8
 *      0000-007F   0xxxxxxx
 *      0080-07FF   110xxxxx 10xxxxxx
 *      0800-FFFF   1110xxxx 10xxxxxx 10xxxxxx
 *
 */

#include <stdio.h>
#include <stdlib.h>

unsigned long _to_utf8(const unsigned short *s, unsigned char *d)
{
    long c = 0;
    while (*s != 0) {
        if (*s <= 0x7f) {
            if (d != NULL) *d++ = *s;
            c++;
        } else if (*s >= 0x80 && *s <= 0x7ff) {
            if (d != NULL) {
                *d++ = ((*s >> 6) & 0x1f) | 0xc0;
                *d++ = (*s & 0x3f) | 0x80;
            }
            c += 2;
        } else {
            if (d != NULL) {
                *d++ = (*s >> 12) | 0xe0;
                *d++ = ((*s >> 6) & 0x3f) | 0x80;
                *d++ = (*s & 0x3f) | 0x80;
            }
            c += 3;
        }
        s++;
    }
    if (d != NULL) *d = 0;
    return c;
}

unsigned long _from_utf8(const unsigned char *s, unsigned short *d)
{
    long c = 0;
    int flag = 0;
    unsigned short tmp;
    while (*s != 0) {
        if (flag == 0) {
            if ((*s & 0xe0) == 0xe0) {
                flag = 2;
                tmp = (*s & 0x0f) << 12;
            } else if ((*s & 0xc0) == 0xc0) {
                flag = 1;
                tmp = (*s & 0x1f) << 6;
            } else if ((*s & 0x80) == 0) {
                if (d != NULL) *d++ = *s;
                c++;
            } else {
                flag = 0;
            }
        } else if (flag == 1) {
            flag = 0;
            if (d != NULL) *d++ = tmp | (*s & 0x3f);
            c++;
        } else if (flag == 2) {
            flag = 3;
            tmp |= (*s & 0x3f) << 6;
        } else if (flag == 3) {
            flag = 0;
            if (d != NULL) *d++ = tmp | (*s & 0x3f);
            c++;
        } else {
            flag = 0;
        }
        s++;
    }
    if (d != NULL) *d = 0;
    return c;
}

/* メイン */
int main()
{
    unsigned short s[] = {
        0x30AB, 0x30CA, 0x30C0, 0x304B, 0x3089, 
        0x306E, 0x0032, 0x901A, 0x306E, 0x624B,
        0x7D19, 0,
    };
    unsigned char *d;
    unsigned long i, c;
    c = _to_utf8(s, NULL);
    d = (unsigned char *)malloc(sizeof(unsigned char)*(c+1));
    _to_utf8(s, d);
    printf("UTF-8:  ");
    for (i = 0; i <= c; i++) printf("%02X ", *(d+i));
    putchar('\n');
    printf("UTF-16: ");
    c = _from_utf8(d, s);
    for (i = 0; i <= c; i++) printf("%04X ", s[i]); 
    putchar('\n');
    free(d);
    return 0;
}