/* ---------------------------------------------------------------------------- * ucs4.c * ---------------------------------------------------------------------------- * Mastering programed by YAMASHINA Hio * ---------------------------------------------------------------------------- * $Id$ * ------------------------------------------------------------------------- */ #include "Japanese.h" /* ---------------------------------------------------------------------------- * convert ucs4 into utf-8 * ------------------------------------------------------------------------- */ EXTERN_C SV* xs_ucs4_utf8(SV* sv_str) { UJ_UINT8* src; int len; SV_Buf result; const UJ_UINT8* src_end; UJ_UINT8 buf[4]; if( sv_str==&PL_sv_undef ) { return newSVpvn("",0); } src = (UJ_UINT8*)SvPV(sv_str,PL_na); len = sv_len(sv_str); src_end = src+(len&~1); /*fprintf(stderr,"Unicode::Japanese::(xs)ucs4_utf8\n",len);*/ /*bin_dump("in ",src,len);*/ SV_Buf_init(&result,len*3/2+4); if( len&3 ) { Perl_croak(aTHX_ "Unicode::Japanese::ucs4_utf8, invalid length (not 4*n)"); } for(; src> 6); buf[1] = 0x80 | (ucs4 & 0x3F); SV_Buf_append_mem(&result, buf, 2); }else if( ucs4 < 0x10000 ) { buf[0] = 0xE0 | (ucs4 >> 12); buf[1] = 0x80 | ((ucs4 >> 6) & 0x3F); buf[2] = 0x80 | (ucs4 & 0x3F); SV_Buf_append_mem(&result, buf, 3); }else if( ucs4 <= 0x0010FFFF ) { buf[0] = 0xF0 | (ucs4 >> 18); buf[1] = 0x80 | ((ucs4 >> 12) & 0x3F); buf[2] = 0x80 | ((ucs4 >> 6) & 0x3F); buf[3] = 0x80 | ( ucs4 & 0x3F); SV_Buf_append_mem(&result, buf, 4); }else { SV_Buf_append_ch(&result,'?'); } } /*bin_dump("out",result.getBegin(),result.getLength()); */ SV_Buf_setLength(&result); return SV_Buf_getSv(&result); } /* ---------------------------------------------------------------------------- * convert utf-8 into ucs4 * ------------------------------------------------------------------------- */ EXTERN_C SV* xs_utf8_ucs4(SV* sv_str) { UJ_UINT8* src; int len; SV_Buf result; const UJ_UINT8* src_end; const UJ_UINT8 buf_failed[4] = { 0, 0, 0, '?' }; if( sv_str==&PL_sv_undef ) { return newSVpvn("",0); } src = (UJ_UINT8*)SvPV(sv_str,PL_na); len = sv_len(sv_str); src_end = src+len; /*fprintf(stderr,"Unicode::Japanese::(xs)utf8_ucs4\n",len); */ /*bin_dump("in ",src,len); */ SV_Buf_init(&result,len*4); while( src=src_end || src[1]<0x80 || 0xbf=src_end || src[1]<0x80 || 0xbf0xDBFF ) { /* normal char, noop */ }else { /* delete surrogate pair range */ SV_Buf_append_ch4(&result, *(UJ_UINT32*)buf_failed); continue; } /* ok. */ }else if( 0xf0<=*src && *src<=0xf7 ) { /* length [4] */ const int utf8_len = 4; const UJ_UINT32 ucs_min = 0x010000; const UJ_UINT32 ucs_max = 0x10ffff; if( src+3>=src_end || src[1]<0x80 || 0xbf