summaryrefslogtreecommitdiff
path: root/cpan/dist/Unicode-Japanese/getcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpan/dist/Unicode-Japanese/getcode.c')
-rw-r--r--cpan/dist/Unicode-Japanese/getcode.c454
1 files changed, 454 insertions, 0 deletions
diff --git a/cpan/dist/Unicode-Japanese/getcode.c b/cpan/dist/Unicode-Japanese/getcode.c
new file mode 100644
index 00000000..c25794c8
--- /dev/null
+++ b/cpan/dist/Unicode-Japanese/getcode.c
@@ -0,0 +1,454 @@
+
+/* $Id$ */
+
+#include "Japanese.h"
+#include "getcode.h"
+
+#include <string.h>
+
+#ifndef dAX
+/* 5.6.x? */
+#define dAX I32 ax = MARK - PL_stack_base + 1
+#endif
+
+#define PERL_PATCHLEVEL_H_IMPLICIT
+#include "patchlevel.h"
+
+#if !defined(PERL_VERSION) && defined(PATCHLEVEL)
+/* 5.005_xx and prior */
+#define PERL_REVISION 5
+#define PERL_VERSION PATCHLEVEL
+#define PERL_SUBVERSION SUBVERSION
+#endif
+
+#if PERL_VERSION <= 4 && !defined(PL_stack_base)
+/* 5.004 */
+extern SV ** Perl_stack_base;
+#define PL_stack_base Perl_stack_base
+#endif
+
+#define GC_DISP 0
+
+#ifndef __cplusplus
+#undef bool
+#undef true
+#undef false
+typedef enum bool { false, true, } bool;
+#endif
+
+/* 文字コード定数 */
+enum charcode_t
+{
+ cc_unknown,
+ cc_ascii,
+ cc_sjis,
+ cc_eucjp,
+ cc_jis_au,
+ cc_jis_jsky,
+ cc_jis,
+ cc_utf8,
+ cc_utf16,
+ cc_utf32,
+ cc_utf32_be,
+ cc_utf32_le,
+ cc_sjis_jsky,
+ cc_sjis_au,
+ cc_sjis_imode,
+ cc_sjis_doti,
+ cc_last,
+};
+typedef enum charcode_t charcode_t;
+
+/* 文字コード名文字列(SV*) */
+#define new_CC_UNKNOWN() newSVpvn("unknown", 7)
+#define new_CC_ASCII() newSVpvn("ascii", 5)
+#define new_CC_SJIS() newSVpvn("sjis", 4)
+#define new_CC_JIS_AU() newSVpvn("jis-au", 6)
+#define new_CC_JIS_JSKY() newSVpvn("jis-jsky",8)
+#define new_CC_JIS() newSVpvn("jis", 3)
+#define new_CC_EUCJP() newSVpvn("euc", 3)
+#define new_CC_UTF8() newSVpvn("utf8", 4)
+#define new_CC_UTF16() newSVpvn("utf16", 5)
+#define new_CC_UTF32() newSVpvn("utf32", 5)
+#define new_CC_UTF32_BE() newSVpvn("utf32-be",8)
+#define new_CC_UTF32_LE() newSVpvn("utf32-le",8)
+#define new_CC_SJIS_JSKY() newSVpvn("sjis-jsky",9)
+#define new_CC_SJIS_IMODE() newSVpvn("sjis-imode",10)
+#define new_CC_SJIS_DOTI() newSVpvn("sjis-doti",9)
+#define new_CC_SJIS_AU() newSVpvn("sjis-au",7)
+
+/* */
+#define RE_BOM2_BE "\xfe\xff"
+#define RE_BOM2_LE "\xff\xfe"
+#define RE_BOM4_BE "\x00\x00\xfe\xff"
+#define RE_BOM4_LE "\xff\xfe\x00\x00"
+
+#if defined(TEST) && GC_DISP
+/* 文字コード定数を文字コード名に. */
+static const char* charcodeToStr(charcode_t code)
+{
+ switch(code)
+ {
+ case cc_unknown: return "unknown";
+ case cc_ascii: return "ascii";
+ case cc_sjis: return "sjis";
+ case cc_eucjp: return "eucjp";
+ case cc_jis_au: return "jis-au";
+ case cc_jis_jsky: return "jis-jsky";
+ case cc_jis: return "jis";
+ case cc_utf8: return "utf8";
+ case cc_utf32: return "utf32";
+ case cc_utf32_be: return "utf32-be";
+ case cc_utf32_le: return "utf32-le";
+ case cc_sjis_jsky: return "sjis-jsky";
+ case cc_sjis_imode: return "sjis-imode";
+ case cc_sjis_doti: return "sjis-doti";
+ case cc_sjis_au: return "sjis-au";
+ default: return NULL;
+ }
+}
+#endif
+#ifdef TEST
+DECL_MAP_MODE(ascii,1) = { "ascii", };
+DECL_MAP_MODE(eucjp,5) =
+{ "eucjp", "0212:3.1","0212:3.2","c:2.1","kana:2.1",};
+DECL_MAP_MODE(sjis,2) = { "sjis","c:2.1", };
+DECL_MAP_MODE(jis,11) =
+{
+ "jis","jis#1","jis#2","jis#3","jis#4","jis#5","jis#6",
+ "jis#7","jis#loop1","jis#loop2","jis#kana",
+};
+DECL_MAP_MODE(jis_au,12) =
+{
+ "jis","jis#1","jis#2","jis#3","jis#4","jis#5","jis#6",
+ "jis#7","jis#loop1","jis#loop2","jis#kana","jis#au",
+};
+DECL_MAP_MODE(jis_jsky,13) =
+{
+ "jis","jis#1","jis#2","jis#3","jis#4","jis#5","jis#6",
+ "jis#7","jis#loop1","jis#loop2","jis#kana","jis#j2","jis#jend",
+};
+DECL_MAP_MODE(utf8,6) =
+{
+ "utf8",
+ "u8:6.1","u8:6.2","u8:6.3","u8:6.4","u8:6.5",
+};
+DECL_MAP_MODE(utf32_be,4) =
+{
+ "utf32-be","utf32-be:4:1","utf32-be:4:2","utf32-be:4:3",
+};
+DECL_MAP_MODE(utf32_le,4) =
+{
+ "utf32-le","utf32-le:4:1","utf32-le:4:2","utf32-le:4:3",
+};
+DECL_MAP_MODE(sjis_jsky,5) =
+{
+ "sjis","c:2.1",
+ "jsky:start:1","jsky:start:2","jsky:code1",
+};
+DECL_MAP_MODE(sjis_imode,4) =
+{
+ "sjis","c:2.1",
+ "imode1:1","imode2:1",
+};
+DECL_MAP_MODE(sjis_doti,7) =
+{
+ "sjis","c:2.1",
+ "doti1:1", "doti2:1", "doti3:1", "doti4:1", "doti5:1",
+};
+DECL_MAP_MODE(sjis_au,3) =
+{
+ "sjis","c:2.1",
+ "au:1",
+};
+#endif
+
+/* 文字コード判定時に使用する構造体. */
+struct CodeCheck
+{
+ charcode_t code;
+ const unsigned char* base;
+ const unsigned char* table;
+#ifdef TEST
+ const char** msg;
+#endif
+};
+typedef struct CodeCheck CodeCheck;
+
+/* 文字コード判定の初期状態. */
+#ifndef TEST
+#define GEN_CODE(name) \
+ { cc_##name, (const unsigned char*)map_##name, (const unsigned char*)map_##name, }
+#else
+#define GEN_CODE(name) \
+ { cc_##name, (const unsigned char*)map_##name, (const unsigned char*)map_##name, mode_##name, }
+#endif
+#define cc_tmpl_max 13
+const CodeCheck cc_tmpl[cc_tmpl_max] =
+{
+ GEN_CODE(utf32_be),
+ GEN_CODE(utf32_le),
+ GEN_CODE(ascii),
+ GEN_CODE(jis),
+ GEN_CODE(jis_au),
+ GEN_CODE(jis_jsky),
+ GEN_CODE(eucjp),
+ GEN_CODE(sjis),
+ GEN_CODE(sjis_jsky),
+ GEN_CODE(sjis_imode),
+ GEN_CODE(sjis_au),
+ GEN_CODE(sjis_doti),
+ GEN_CODE(utf8),
+};
+
+/* 判定結果の構造体. */
+struct CodeResult
+{
+ charcode_t code;
+ int begin;
+ int len;
+};
+typedef struct CodeResult CodeResult;
+
+static bool _is_acceptable_state(const CodeCheck* check)
+{
+ /* special cases. */
+ if( check->table==map_jis_jsky[11] )
+ { /* jis-jsky, jis#j2 */
+ return true;
+ }
+ if( check->table==map_sjis_jsky[4] )
+ { /* sjis-jsky, sjis#j2 */
+ return true;
+ }
+ return false;
+}
+
+static int getcode_list(SV* sv_str, CodeCheck* check)
+{
+ unsigned char* src;
+ int len;
+ const unsigned char* src_end;
+ int cc_max;
+
+ if( sv_str==&PL_sv_undef )
+ {
+ return 0;
+ }
+
+ src = (unsigned char*)SvPV(sv_str,PL_na);
+ len = sv_len(sv_str);
+ src_end = src+len;
+
+ /* empty string */
+ /* (jp:) 空文字列は unknown */
+ if( len==0 )
+ {
+ return 0;
+ }
+
+ /* BOM of UTF32 */
+ if( (len%4)==0 && len>=4 &&
+ ( memcmp(src,RE_BOM4_BE,4)==0 || memcmp(src,RE_BOM4_LE,4)==0 ) )
+ {
+ check[0].code = cc_utf32;
+ return 1;
+ }
+
+ /* BOM of UTF16 */
+ if( (len%2)==0 && len>=2 &&
+ ( memcmp(src,RE_BOM2_BE,2)==0 || memcmp(src,RE_BOM2_LE,2)==0 ) )
+ {
+ check[0].code = cc_utf16;
+ return 1;
+ }
+
+ /* fprintf(stderr,"Unicode::Japanese::(xs)getcode[%d]\n",len); */
+ /* fprintf(stderr,">>%s<<\n",src); */
+ /* bin_dump("in ",src,len); */
+
+ memcpy(check,cc_tmpl,sizeof(cc_tmpl));
+ cc_max = cc_tmpl_max;
+
+ for( ; src<src_end; ++src )
+ {
+ int invalids;
+ int i;
+#if TEST && GC_DISP
+ fprintf(stderr,"[%d] '%c' 0x%02x (%d)\n",len-(src_end-src),(0x20<=*src&&*src<=0x7f?*src:'.'),*src,*src);
+#endif
+ /* 遷移を1つ進める〜 */
+ invalids = 0;
+ for( i=0; i<cc_max; ++i )
+ {
+ int nxt = check[i].table[*src];
+#if TEST && GC_DISP
+ fprintf(stderr," %s : %d (%s)\n",charcodeToStr(check[i].code),nxt,nxt!=map_invalid?check[i].msg[nxt]:"invalid");
+#endif
+ if( nxt!=map_invalid )
+ {
+ check[i].table = check[i].base+nxt*256;
+ }else
+ {
+ ++invalids;
+ check[i].table = NULL;
+ }
+ }
+ if( invalids==0 )
+ { /* 全部継続 */
+ continue;
+ }else if( cc_max-invalids>0 )
+ { /* まだあり〜 */
+ int rd = 0;
+ int wr = 0;
+ for( ;rd<cc_max; ++rd )
+ {
+ if( check[rd].table )
+ {
+ if( rd!=wr )
+ {
+ check[wr] = check[rd];
+ }
+ ++wr;
+ }
+ }
+ cc_max = wr;
+ }else
+ { /* 全部だめ〜 */
+ return 0;
+ }
+ }
+
+ /* check if we have stopped at a valid (final?) state */
+ {
+ int wr = 0;
+ int i;
+ for( i=0; i<cc_max; ++i )
+ {
+ if( check[i].table == check[i].base || _is_acceptable_state(&check[i]) )
+ {
+ if( wr!=i )
+ {
+ check[wr] = check[i];
+ }
+ ++wr;
+ }
+ }
+ cc_max = wr;
+ }
+
+#if TEST && GC_DISP
+ fprintf(stderr,"<availables>\n");
+ {
+ int i;
+ for( i=0; i<cc_max; ++i )
+ {
+ fprintf(stderr," %s\n",charcodeToStr(check[i].code));
+ }
+ }
+#endif
+
+ return cc_max;
+}
+
+#ifndef NO_XSUBS
+
+/* getcode関数 */
+SV* xs_getcode(SV* sv_str)
+{
+ int matches;
+ CodeCheck check[cc_tmpl_max];
+
+ if( sv_str==&PL_sv_undef )
+ {
+ return new_SV_UNDEF();
+ }
+ matches = getcode_list(sv_str, check);
+ if( matches>0 )
+ {
+ int index = 0;
+#if TEST && GC_DISP
+ fprintf(stderr,"<selected>\n");
+ fprintf(stderr," %d of 0..%d\n",index,matches-1);
+ fprintf(stderr," %s\n",charcodeToStr(check[index].code));
+#endif
+ switch(check[index].code)
+ {
+ case cc_unknown: return new_CC_UNKNOWN();
+ case cc_ascii: return new_CC_ASCII();
+ case cc_sjis: return new_CC_SJIS();
+ case cc_eucjp: return new_CC_EUCJP();
+ case cc_jis: return new_CC_JIS();
+ case cc_jis_au: return new_CC_JIS_AU();
+ case cc_jis_jsky: return new_CC_JIS_JSKY();
+ case cc_utf8: return new_CC_UTF8();
+ case cc_utf16: return new_CC_UTF16();
+ case cc_utf32: return new_CC_UTF32();
+ case cc_utf32_be: return new_CC_UTF32_BE();
+ case cc_utf32_le: return new_CC_UTF32_LE();
+ case cc_sjis_jsky: return new_CC_SJIS_JSKY();
+ case cc_sjis_imode: return new_CC_SJIS_IMODE();
+ case cc_sjis_doti: return new_CC_SJIS_DOTI();
+ case cc_sjis_au: return new_CC_SJIS_AU();
+
+ default:
+#ifdef TEST
+ return NULL;
+#else
+ return new_CC_UNKNOWN();
+#endif
+ }
+ }else
+ {
+ return new_CC_UNKNOWN();
+ }
+}
+
+/* getcode_list関数 */
+int xs_getcode_list(SV* sv_str)
+{
+ int matches;
+ CodeCheck check[cc_tmpl_max];
+ int i;
+ dSP; dMARK; dAX; /* XSARGS; - items */
+
+ if( sv_str==&PL_sv_undef )
+ {
+ return 0;
+ }
+ matches = getcode_list(sv_str, check);
+ if( matches<=0 )
+ {
+ return 0;
+ }
+ EXTEND(SP, matches);
+ for( i=0; i<matches; ++i )
+ {
+ switch(check[i].code)
+ {
+ case cc_unknown: ST(i) = sv_2mortal( new_CC_UNKNOWN() ); break;
+ case cc_ascii: ST(i) = sv_2mortal( new_CC_ASCII() ); break;
+ case cc_sjis: ST(i) = sv_2mortal( new_CC_SJIS() ); break;
+ case cc_eucjp: ST(i) = sv_2mortal( new_CC_EUCJP() ); break;
+ case cc_jis: ST(i) = sv_2mortal( new_CC_JIS() ); break;
+ case cc_jis_au: ST(i) = sv_2mortal( new_CC_JIS_AU() ); break;
+ case cc_jis_jsky: ST(i) = sv_2mortal( new_CC_JIS_JSKY() ); break;
+ case cc_utf8: ST(i) = sv_2mortal( new_CC_UTF8() ); break;
+ case cc_utf16: ST(i) = sv_2mortal( new_CC_UTF16() ); break;
+ case cc_utf32: ST(i) = sv_2mortal( new_CC_UTF32() ); break;
+ case cc_utf32_be: ST(i) = sv_2mortal( new_CC_UTF32_BE() ); break;
+ case cc_utf32_le: ST(i) = sv_2mortal( new_CC_UTF32_LE() ); break;
+ case cc_sjis_jsky: ST(i) = sv_2mortal( new_CC_SJIS_JSKY() ); break;
+ case cc_sjis_imode: ST(i) = sv_2mortal( new_CC_SJIS_IMODE() ); break;
+ case cc_sjis_doti: ST(i) = sv_2mortal( new_CC_SJIS_DOTI() ); break;
+ default: ST(i) = sv_2mortal( new_CC_UNKNOWN() ); break;
+ }
+ }
+ return matches;
+}
+
+#endif
+
+/* ----------------------------------------------------------------------------
+ * End of File.
+ * ------------------------------------------------------------------------- */