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

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

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