Annotation of embedaddon/php/ext/mbstring/libmbfl/filters/mbfilter_utf8.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * "streamable kanji code filter and converter"
        !             3:  * Copyright (c) 1998-2002 HappySize, Inc. All rights reserved.
        !             4:  *
        !             5:  * LICENSE NOTICES
        !             6:  *
        !             7:  * This file is part of "streamable kanji code filter and converter",
        !             8:  * which is distributed under the terms of GNU Lesser General Public 
        !             9:  * License (version 2) as published by the Free Software Foundation.
        !            10:  *
        !            11:  * This software is distributed in the hope that it will be useful,
        !            12:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14:  * GNU Lesser General Public License for more details.
        !            15:  *
        !            16:  * You should have received a copy of the GNU Lesser General Public
        !            17:  * License along with "streamable kanji code filter and converter";
        !            18:  * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
        !            19:  * Suite 330, Boston, MA  02111-1307  USA
        !            20:  *
        !            21:  * The author of this file:
        !            22:  *
        !            23:  */
        !            24: /*
        !            25:  * The source code included in this files was separated from mbfilter.c
        !            26:  * by moriyoshi koizumi <moriyoshi@php.net> on 4 dec 2002.
        !            27:  * 
        !            28:  */
        !            29: 
        !            30: #ifdef HAVE_CONFIG_H
        !            31: #include "config.h"
        !            32: #endif
        !            33: 
        !            34: #include "mbfilter.h"
        !            35: #include "mbfilter_utf8.h"
        !            36: 
        !            37: static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
        !            38: 
        !            39: static const unsigned char mblen_table_utf8[] = {
        !            40:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            41:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            42:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            43:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            44:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            45:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            46:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            47:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            48:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            49:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            50:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            51:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !            52:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !            53:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !            54:   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
        !            55:   4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1
        !            56: };
        !            57: 
        !            58: static const char *mbfl_encoding_utf8_aliases[] = {"utf8", NULL};
        !            59: 
        !            60: const mbfl_encoding mbfl_encoding_utf8 = {
        !            61:        mbfl_no_encoding_utf8,
        !            62:        "UTF-8",
        !            63:        "UTF-8",
        !            64:        (const char *(*)[])&mbfl_encoding_utf8_aliases,
        !            65:        mblen_table_utf8,
        !            66:        MBFL_ENCTYPE_MBCS
        !            67: };
        !            68: 
        !            69: const struct mbfl_identify_vtbl vtbl_identify_utf8 = {
        !            70:        mbfl_no_encoding_utf8,
        !            71:        mbfl_filt_ident_common_ctor,
        !            72:        mbfl_filt_ident_common_dtor,
        !            73:        mbfl_filt_ident_utf8
        !            74: };
        !            75: 
        !            76: const struct mbfl_convert_vtbl vtbl_utf8_wchar = {
        !            77:        mbfl_no_encoding_utf8,
        !            78:        mbfl_no_encoding_wchar,
        !            79:        mbfl_filt_conv_common_ctor,
        !            80:        mbfl_filt_conv_common_dtor,
        !            81:        mbfl_filt_conv_utf8_wchar,
        !            82:        mbfl_filt_conv_common_flush
        !            83: };
        !            84: 
        !            85: const struct mbfl_convert_vtbl vtbl_wchar_utf8 = {
        !            86:        mbfl_no_encoding_wchar,
        !            87:        mbfl_no_encoding_utf8,
        !            88:        mbfl_filt_conv_common_ctor,
        !            89:        mbfl_filt_conv_common_dtor,
        !            90:        mbfl_filt_conv_wchar_utf8,
        !            91:        mbfl_filt_conv_common_flush
        !            92: };
        !            93: 
        !            94: #define CK(statement)  do { if ((statement) < 0) return (-1); } while (0)
        !            95: 
        !            96: /*
        !            97:  * UTF-8 => wchar
        !            98:  */
        !            99: int mbfl_filt_conv_utf8_wchar(int c, mbfl_convert_filter *filter)
        !           100: {
        !           101:        int s;
        !           102: 
        !           103:        if (c < 0x80) {
        !           104:                if (c >= 0) {
        !           105:                        CK((*filter->output_function)(c, filter->data));
        !           106:                }
        !           107:                filter->status = 0;
        !           108:        } else if (c < 0xc0) {
        !           109:                int status = filter->status & 0xff;
        !           110:                switch (status) {
        !           111:                case 0x10: /* 2byte code 2nd char */
        !           112:                case 0x21: /* 3byte code 3rd char */
        !           113:                case 0x32: /* 4byte code 4th char */
        !           114:                case 0x43: /* 5byte code 5th char */
        !           115:                case 0x54: /* 6byte code 6th char */
        !           116:                        filter->status = 0;
        !           117:                        s = filter->cache | (c & 0x3f);
        !           118:                        if ((status == 0x10 && s >= 0x80) ||
        !           119:                            (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
        !           120:                            (status == 0x32 && s >= 0x10000) ||
        !           121:                            (status == 0x43 && s >= 0x200000) ||
        !           122:                            (status == 0x54 && s >= 0x4000000 && s < MBFL_WCSGROUP_UCS4MAX)) {
        !           123:                                CK((*filter->output_function)(s, filter->data));
        !           124:                        }
        !           125:                        break;
        !           126:                case 0x20: /* 3byte code 2nd char */
        !           127:                case 0x31: /* 4byte code 3rd char */
        !           128:                case 0x42: /* 5byte code 4th char */
        !           129:                case 0x53: /* 6byte code 5th char */
        !           130:                        filter->cache |= ((c & 0x3f) << 6);
        !           131:                        filter->status++;
        !           132:                        break;
        !           133:                case 0x30: /* 4byte code 2nd char */
        !           134:                case 0x41: /* 5byte code 3rd char */
        !           135:                case 0x52: /* 6byte code 4th char */
        !           136:                        filter->cache |= ((c & 0x3f) << 12);
        !           137:                        filter->status++;
        !           138:                        break;
        !           139:                case 0x40: /* 5byte code 2nd char */
        !           140:                case 0x51: /* 6byte code 3rd char */
        !           141:                        filter->cache |= ((c & 0x3f) << 18);
        !           142:                        filter->status++;
        !           143:                        break;
        !           144:                case 0x50: /* 6byte code 2nd char */
        !           145:                        filter->cache |= ((c & 0x3f) << 24);
        !           146:                        filter->status++;
        !           147:                        break;
        !           148:                default:
        !           149:                        filter->status = 0;
        !           150:                        break;
        !           151:                }
        !           152:        } else if (c < 0xe0) { /* 2byte code first char */
        !           153:                filter->status = 0x10;
        !           154:                filter->cache = (c & 0x1f) << 6;
        !           155:        } else if (c < 0xf0) { /* 3byte code first char */
        !           156:                filter->status = 0x20;
        !           157:                filter->cache = (c & 0xf) << 12;
        !           158:        } else if (c < 0xf8) { /* 4byte code first char */
        !           159:                filter->status = 0x30;
        !           160:                filter->cache = (c & 0x7) << 18;
        !           161:        } else if (c < 0xfc) { /* 5byte code first char */
        !           162:                filter->status = 0x40;
        !           163:                filter->cache = (c & 0x3) << 24;
        !           164:        } else if (c < 0xfe)  { /* 6 byte code first char */
        !           165:                filter->status = 0x50;
        !           166:                filter->cache = (c & 0x1) << 30;
        !           167:        } else {
        !           168:                filter->status = 0;
        !           169:                filter->cache = 0;
        !           170:        }
        !           171: 
        !           172:        return c;
        !           173: }
        !           174: 
        !           175: /*
        !           176:  * wchar => UTF-8
        !           177:  */
        !           178: int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter)
        !           179: {
        !           180:        if (c >= 0 && c < MBFL_WCSGROUP_UCS4MAX) {
        !           181:                if (c < 0x80) {
        !           182:                        CK((*filter->output_function)(c, filter->data));
        !           183:                } else if (c < 0x800) {
        !           184:                        CK((*filter->output_function)(((c >> 6) & 0x1f) | 0xc0, filter->data));
        !           185:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
        !           186:                } else if (c < 0x10000) {
        !           187:                        CK((*filter->output_function)(((c >> 12) & 0x0f) | 0xe0, filter->data));
        !           188:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
        !           189:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
        !           190:                } else if (c < 0x200000) {
        !           191:                        CK((*filter->output_function)(((c >> 18) & 0x07) | 0xf0, filter->data));
        !           192:                        CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
        !           193:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
        !           194:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
        !           195:                } else if (c < 0x4000000) {
        !           196:                        CK((*filter->output_function)(((c >> 24) & 0x03) | 0xf8, filter->data));
        !           197:                        CK((*filter->output_function)(((c >> 18) & 0x3f) | 0x80, filter->data));
        !           198:                        CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
        !           199:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
        !           200:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
        !           201:                } else {
        !           202:                        CK((*filter->output_function)(((c >> 30) & 0x01) | 0xfc, filter->data));
        !           203:                        CK((*filter->output_function)(((c >> 24) & 0x3f) | 0x80, filter->data));
        !           204:                        CK((*filter->output_function)(((c >> 18) & 0x3f) | 0x80, filter->data));
        !           205:                        CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
        !           206:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
        !           207:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
        !           208:                }
        !           209:        } else {
        !           210:                if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
        !           211:                        CK(mbfl_filt_conv_illegal_output(c, filter));
        !           212:                }
        !           213:        }
        !           214: 
        !           215:        return c;
        !           216: }
        !           217: 
        !           218: static int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
        !           219: {
        !           220:        if (c < 0x80) {
        !           221:                if (c < 0) { 
        !           222:                        filter->flag = 1;       /* bad */
        !           223:                } else if (filter->status) {
        !           224:                        filter->flag = 1;       /* bad */
        !           225:                }
        !           226:                filter->status = 0;
        !           227:        } else if (c < 0xc0) {
        !           228:                switch (filter->status) {
        !           229:                case 0x20: /* 3 byte code 2nd char */
        !           230:                case 0x30: /* 4 byte code 2nd char */
        !           231:                case 0x31: /* 4 byte code 3rd char */
        !           232:                case 0x40: /* 5 byte code 2nd char */
        !           233:                case 0x41: /* 5 byte code 3rd char */
        !           234:                case 0x42: /* 5 byte code 4th char */
        !           235:                case 0x50: /* 6 byte code 2nd char */
        !           236:                case 0x51: /* 6 byte code 3rd char */
        !           237:                case 0x52: /* 6 byte code 4th char */
        !           238:                case 0x53: /* 6 byte code 5th char */
        !           239:                        filter->status++;
        !           240:                        break;
        !           241:                case 0x10: /* 2 byte code 2nd char */
        !           242:                case 0x21: /* 3 byte code 3rd char */
        !           243:                case 0x32: /* 4 byte code 4th char */
        !           244:                case 0x43: /* 5 byte code 5th char */
        !           245:                case 0x54: /* 6 byte code 6th char */
        !           246:                        filter->status = 0;
        !           247:                        break;
        !           248:                default:
        !           249:                        filter->flag = 1;       /* bad */
        !           250:                        filter->status = 0;
        !           251:                        break;
        !           252:                }
        !           253:        } else {
        !           254:                if (filter->status) {
        !           255:                        filter->flag = 1;       /* bad */
        !           256:                }
        !           257:                filter->status = 0;
        !           258:                if (c < 0xe0) {                         /* 2 byte code first char */
        !           259:                        filter->status = 0x10;
        !           260:                } else if (c < 0xf0) {          /* 3 byte code 1st char */
        !           261:                        filter->status = 0x20;
        !           262:                } else if (c < 0xf8) {          /* 4 byte code 1st char */
        !           263:                        filter->status = 0x30;
        !           264:                } else if (c < 0xfc) {          /* 5 byte code 1st char */
        !           265:                        filter->status = 0x40;
        !           266:                } else if (c < 0xfe) {          /* 6 byte code 1st char */
        !           267:                        filter->status = 0x50;
        !           268:                } else {
        !           269:                        filter->flag = 1;       /* bad */
        !           270:                }
        !           271:        }
        !           272: 
        !           273:        return c;
        !           274: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>