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

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: 
1.1.1.2 ! misho      37: int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter);
1.1       misho      38: 
1.1.1.2 ! misho      39: 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:        1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1.1       misho      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: {
1.1.1.2 ! misho     101:        int s, c1, w = 0, flag = 0;
1.1       misho     102: 
                    103:        if (c < 0x80) {
1.1.1.2 ! misho     104:                if (filter->status != 0)  {
        !           105:                        w = (filter->cache & MBFL_WCSGROUP_MASK) | MBFL_WCSGROUP_THROUGH;
        !           106:                        CK((*filter->output_function)(w, filter->data));
        !           107:                        filter->status = 0;
        !           108:                        filter->cache = 0;
        !           109:                }
1.1       misho     110:                if (c >= 0) {
                    111:                        CK((*filter->output_function)(c, filter->data));
                    112:                }
                    113:        } else if (c < 0xc0) {
                    114:                int status = filter->status & 0xff;
                    115:                switch (status) {
1.1.1.2 ! misho     116:                case 0x10: /* 2byte code 2nd char: 0x80-0xbf */
        !           117:                case 0x21: /* 3byte code 3rd char: 0x80-0xbf */
        !           118:                case 0x32: /* 4byte code 4th char: 0x80-0xbf */
1.1       misho     119:                        filter->status = 0;
                    120:                        s = filter->cache | (c & 0x3f);
1.1.1.2 ! misho     121:                        filter->cache = 0;
1.1       misho     122:                        if ((status == 0x10 && s >= 0x80) ||
                    123:                            (status == 0x21 && s >= 0x800 && (s < 0xd800 || s > 0xdfff)) ||
1.1.1.2 ! misho     124:                            (status == 0x32 && s >= 0x10000 && s < 0x110000)) {
1.1       misho     125:                                CK((*filter->output_function)(s, filter->data));
1.1.1.2 ! misho     126:                        } else {
        !           127:                                w = s & MBFL_WCSGROUP_MASK;
        !           128:                                flag = 1;
1.1       misho     129:                        }
                    130:                        break;
1.1.1.2 ! misho     131:                case 0x20: /* 3byte code 2nd char: 0:0xa0-0xbf,D:0x80-9F,1-C,E-F:0x80-0x9f */
        !           132:                        s = filter->cache | ((c & 0x3f) << 6);
        !           133:                        c1 = (s >> 12) & 0xf;
        !           134:                        if ((c1 == 0x0 && c >= 0xa0) || 
        !           135:                                (c1 == 0xd && c < 0xa0) || 
        !           136:                                (c1 > 0x0 && c1 != 0xd)) {
        !           137:                                filter->cache = s;
        !           138:                                filter->status++;
        !           139:                        } else {
        !           140:                                w = s & MBFL_WCSGROUP_MASK;
        !           141:                                flag = 1;
        !           142:                        }
1.1       misho     143:                        break;
1.1.1.2 ! misho     144:                case 0x31: /* 4byte code 3rd char: 0x80-0xbf */
        !           145:                        filter->cache |= ((c & 0x3f) << 6);
1.1       misho     146:                        filter->status++;
                    147:                        break;
1.1.1.2 ! misho     148:                case 0x30: /* 4byte code 2nd char: 0:0x90-0xbf,1-3:0x80-0xbf,4:0x80-0x8f */
        !           149:                        s = filter->cache | ((c & 0x3f) << 12);
        !           150:                        c1 = (s >> 18) & 0x7;
        !           151:                        if ((c1 == 0x0 && c >= 0x90) ||
        !           152:                                (c1 > 0x0 && c1 < 0x4) ||
        !           153:                                (c1 == 0x4 && c < 0x90)) {
        !           154:                                filter->cache = s;
        !           155:                                filter->status++;
        !           156:                        } else {
        !           157:                                w = s & MBFL_WCSGROUP_MASK;
        !           158:                                flag = 1;
        !           159:                        }
1.1       misho     160:                        break;
                    161:                default:
1.1.1.2 ! misho     162:                        w = c & MBFL_WCSGROUP_MASK;
        !           163:                        flag = 1;
1.1       misho     164:                        break;
                    165:                }
1.1.1.2 ! misho     166:        } else if (c < 0xc2) { /* invalid: 0xc0,0xc1 */
        !           167:                w = c & MBFL_WCSGROUP_MASK;
        !           168:                flag = 1;
        !           169:        } else if (c < 0xe0) { /* 2byte code first char: 0xc2-0xdf */
        !           170:                if (filter->status == 0x0) {
        !           171:                        filter->status = 0x10;
        !           172:                        filter->cache = (c & 0x1f) << 6;
        !           173:                } else {
        !           174:                        w = c & MBFL_WCSGROUP_MASK;
        !           175:                        flag = 1;
        !           176:                }
        !           177:        } else if (c < 0xf0) { /* 3byte code first char: 0xe0-0xef */
        !           178:                if (filter->status == 0x0) {
        !           179:                        filter->status = 0x20;
        !           180:                        filter->cache = (c & 0xf) << 12;
        !           181:                } else {
        !           182:                        w = c & MBFL_WCSGROUP_MASK;
        !           183:                        flag = 1;
        !           184:                }
        !           185:        } else if (c < 0xf5) { /* 4byte code first char: 0xf0-0xf4 */
        !           186:                if (filter->status == 0x0) {
        !           187:                        filter->status = 0x30;
        !           188:                        filter->cache = (c & 0x7) << 18;
        !           189:                } else {
        !           190:                        w = c & MBFL_WCSGROUP_MASK;
        !           191:                        flag = 1;
        !           192:                }
1.1       misho     193:        } else {
1.1.1.2 ! misho     194:                w = c & MBFL_WCSGROUP_MASK;
        !           195:                flag = 1;
        !           196:        }
        !           197: 
        !           198:        if (flag) {
        !           199:                w |= MBFL_WCSGROUP_THROUGH;
        !           200:                CK((*filter->output_function)(w, filter->data));
1.1       misho     201:                filter->status = 0;
                    202:                filter->cache = 0;
                    203:        }
                    204: 
                    205:        return c;
                    206: }
                    207: 
                    208: /*
                    209:  * wchar => UTF-8
                    210:  */
                    211: int mbfl_filt_conv_wchar_utf8(int c, mbfl_convert_filter *filter)
                    212: {
1.1.1.2 ! misho     213:        if (c >= 0 && c < 0x110000) {
1.1       misho     214:                if (c < 0x80) {
                    215:                        CK((*filter->output_function)(c, filter->data));
                    216:                } else if (c < 0x800) {
                    217:                        CK((*filter->output_function)(((c >> 6) & 0x1f) | 0xc0, filter->data));
                    218:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
                    219:                } else if (c < 0x10000) {
                    220:                        CK((*filter->output_function)(((c >> 12) & 0x0f) | 0xe0, filter->data));
                    221:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
                    222:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
                    223:                } else {
1.1.1.2 ! misho     224:                        CK((*filter->output_function)(((c >> 18) & 0x07) | 0xf0, filter->data));
1.1       misho     225:                        CK((*filter->output_function)(((c >> 12) & 0x3f) | 0x80, filter->data));
                    226:                        CK((*filter->output_function)(((c >> 6) & 0x3f) | 0x80, filter->data));
                    227:                        CK((*filter->output_function)((c & 0x3f) | 0x80, filter->data));
                    228:                }
                    229:        } else {
                    230:                if (filter->illegal_mode != MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
                    231:                        CK(mbfl_filt_conv_illegal_output(c, filter));
                    232:                }
                    233:        }
                    234: 
                    235:        return c;
                    236: }
                    237: 
1.1.1.2 ! misho     238: int mbfl_filt_ident_utf8(int c, mbfl_identify_filter *filter)
1.1       misho     239: {
1.1.1.2 ! misho     240:        int c1;
        !           241: 
        !           242:        c1 = (filter->status >> 8) & 0xff;
        !           243:        filter->status &= 0xff;
        !           244: 
1.1       misho     245:        if (c < 0x80) {
                    246:                if (c < 0) { 
                    247:                        filter->flag = 1;       /* bad */
                    248:                } else if (filter->status) {
                    249:                        filter->flag = 1;       /* bad */
                    250:                }
                    251:                filter->status = 0;
                    252:        } else if (c < 0xc0) {
                    253:                switch (filter->status) {
                    254:                case 0x20: /* 3 byte code 2nd char */
1.1.1.2 ! misho     255:                        if ((c1 == 0x0 && c >= 0xa0) || 
        !           256:                                (c1 == 0xd && c < 0xa0) || 
        !           257:                                (c1 > 0x0 && c1 != 0xd)) {
        !           258:                                filter->status++;
        !           259:                        } else {
        !           260:                                filter->flag = 1;       /* bad */
        !           261:                                filter->status = 0;                             
        !           262:                        }
        !           263:                        break;
1.1       misho     264:                case 0x30: /* 4 byte code 2nd char */
1.1.1.2 ! misho     265:                        if ((c1 == 0x0 && c >= 0x90) || 
        !           266:                                (c1 > 0x0 && c1 < 0x4) || 
        !           267:                                (c1 == 0x4 && c < 0x90)) {
        !           268:                                filter->status++;
        !           269:                        } else {
        !           270:                                filter->flag = 1;       /* bad */
        !           271:                                filter->status = 0;                             
        !           272:                        }
        !           273:                        break;
1.1       misho     274:                case 0x31: /* 4 byte code 3rd char */
                    275:                        filter->status++;
                    276:                        break;
                    277:                case 0x10: /* 2 byte code 2nd char */
                    278:                case 0x21: /* 3 byte code 3rd char */
                    279:                case 0x32: /* 4 byte code 4th char */
                    280:                        filter->status = 0;
                    281:                        break;
                    282:                default:
                    283:                        filter->flag = 1;       /* bad */
                    284:                        filter->status = 0;
                    285:                        break;
                    286:                }
1.1.1.2 ! misho     287:        } else if (c < 0xc2) { /* 0xc0,0xc1 */
        !           288:                filter->flag = 1;       /* bad */
        !           289:                filter->status = 0;
1.1       misho     290:        } else {
                    291:                if (filter->status) {
                    292:                        filter->flag = 1;       /* bad */
                    293:                }
                    294:                filter->status = 0;
                    295:                if (c < 0xe0) {                         /* 2 byte code first char */
                    296:                        filter->status = 0x10;
                    297:                } else if (c < 0xf0) {          /* 3 byte code 1st char */
                    298:                        filter->status = 0x20;
1.1.1.2 ! misho     299:                        filter->status |= (c & 0xf) << 8;
        !           300:                } else if (c < 0xf5) {          /* 4 byte code 1st char */
1.1       misho     301:                        filter->status = 0x30;
1.1.1.2 ! misho     302:                        filter->status |= (c & 0x7) << 8;
1.1       misho     303:                } else {
                    304:                        filter->flag = 1;       /* bad */
                    305:                }
                    306:        }
                    307: 
                    308:        return c;
                    309: }

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