     1			/*
     2			 * This file was generated automatically by ExtUtils::ParseXS version 2.10 from the
     3			 * contents of Normalize.xs. Do not edit this file, edit Normalize.xs instead.
     4			 *
     5			 *	ANY CHANGES MADE HERE WILL BE LOST! 
     6			 *
     7			 */
     8			
     9			#line 1 "Normalize.xs"
    10			
    11			#include "EXTERN.h"
    12			#include "perl.h"
    13			#include "XSUB.h"
    14			
    15			/* These 5 files are prepared by mkheader */
    16			#include "unfcmb.h"
    17			#include "unfcan.h"
    18			#include "unfcpt.h"
    19			#include "unfcmp.h"
    20			#include "unfexc.h"
    21			
    22			/* Perl 5.6.1 ? */
    23			#ifndef uvuni_to_utf8
    24			#define uvuni_to_utf8   uv_to_utf8
    25			#endif /* uvuni_to_utf8 */
    26			
    27			/* Perl 5.6.1 ? */
    28			#ifndef utf8n_to_uvuni
    29			#define utf8n_to_uvuni  utf8_to_uv
    30			#endif /* utf8n_to_uvuni */
    31			
    32			/* UTF8_ALLOW_BOM is used before Perl 5.8.0 */
    33			#ifdef UTF8_ALLOW_BOM
    34			#define AllowAnyUTF (UTF8_ALLOW_SURROGATE|UTF8_ALLOW_BOM|UTF8_ALLOW_FFFF)
    35			#else
    36			#define AllowAnyUTF (UTF8_ALLOW_SURROGATE|UTF8_ALLOW_FFFF)
    37			#endif
    38			
    39			/* if utf8n_to_uvuni() sets retlen to 0 (?) */
    40			#define ErrRetlenIsZero "panic (Unicode::Normalize): zero-length character"
    41			
    42			/* utf8_hop() hops back before start. Maybe broken UTF-8 */
    43			#define ErrHopBeforeStart "panic (Unicode::Normalize): hopping before start"
    44			
    45			/* At present, char > 0x10ffff are unaffected without complaint, right? */
    46			#define VALID_UTF_MAX    (0x10ffff)
    47			#define OVER_UTF_MAX(uv) (VALID_UTF_MAX < (uv))
    48			
    49			/* HANGUL_H */
    50			#define Hangul_SBase  0xAC00
    51			#define Hangul_SFinal 0xD7A3
    52			#define Hangul_SCount  11172
    53			
    54			#define Hangul_NCount    588
    55			
    56			#define Hangul_LBase  0x1100
    57			#define Hangul_LFinal 0x1112
    58			#define Hangul_LCount     19
    59			
    60			#define Hangul_VBase  0x1161
    61			#define Hangul_VFinal 0x1175
    62			#define Hangul_VCount     21
    63			
    64			#define Hangul_TBase  0x11A7
    65			#define Hangul_TFinal 0x11C2
    66			#define Hangul_TCount     28
    67			
    68			#define Hangul_IsS(u)  ((Hangul_SBase <= (u)) && ((u) <= Hangul_SFinal))
    69			#define Hangul_IsN(u)  (((u) - Hangul_SBase) % Hangul_TCount == 0)
    70			#define Hangul_IsLV(u) (Hangul_IsS(u) && Hangul_IsN(u))
    71			#define Hangul_IsL(u)  ((Hangul_LBase <= (u)) && ((u) <= Hangul_LFinal))
    72			#define Hangul_IsV(u)  ((Hangul_VBase <= (u)) && ((u) <= Hangul_VFinal))
    73			#define Hangul_IsT(u)  ((Hangul_TBase  < (u)) && ((u) <= Hangul_TFinal))
    74			/* HANGUL_H */
    75			
    76			/* this is used for canonical ordering of combining characters (c.c.). */
    77			typedef struct {
    78			    U8 cc;	/* combining class */
    79			    UV uv;	/* codepoint */
    80			    STRLEN pos; /* position */
    81			} UNF_cc;
    82			
    83			static int compare_cc (const void *a, const void *b)
    84			{
    85			    int ret_cc;
    86			    ret_cc = ((UNF_cc*) a)->cc - ((UNF_cc*) b)->cc;
    87			    if (ret_cc)
    88				return ret_cc;
    89			
    90			    return ( ((UNF_cc*) a)->pos > ((UNF_cc*) b)->pos )
    91				 - ( ((UNF_cc*) a)->pos < ((UNF_cc*) b)->pos );
    92			}
    93			
    94			static U8* dec_canonical (UV uv)
    95			{
    96			    U8 ***plane, **row;
    97			    if (OVER_UTF_MAX(uv))
    98				return NULL;
    99			    plane = (U8***)UNF_canon[uv >> 16];
   100			    if (! plane)
   101				return NULL;
   102			    row = plane[(uv >> 8) & 0xff];
   103			    return row ? row[uv & 0xff] : NULL;
   104			}
   105			
   106			static U8* dec_compat (UV uv)
   107			{
   108			    U8 ***plane, **row;
   109			    if (OVER_UTF_MAX(uv))
   110				return NULL;
   111			    plane = (U8***)UNF_compat[uv >> 16];
   112			    if (! plane)
   113				return NULL;
   114			    row = plane[(uv >> 8) & 0xff];
   115			    return row ? row[uv & 0xff] : NULL;
   116			}
   117			
   118			static UV composite_uv (UV uv, UV uv2)
   119			{
   120			    UNF_complist ***plane, **row, *cell, *i;
   121			
   122			    if (! uv2 || OVER_UTF_MAX(uv) || OVER_UTF_MAX(uv2))
   123				return 0;
   124			
   125			    if (Hangul_IsL(uv) && Hangul_IsV(uv2)) {
   126				uv  -= Hangul_LBase; /* lindex */
   127				uv2 -= Hangul_VBase; /* vindex */
   128				return(Hangul_SBase + (uv * Hangul_VCount + uv2) * Hangul_TCount);
   129			    }
   130			    if (Hangul_IsLV(uv) && Hangul_IsT(uv2)) {
   131				uv2 -= Hangul_TBase; /* tindex */
   132				return(uv + uv2);
   133			    }
   134			    plane = UNF_compos[uv >> 16];
   135			    if (! plane)
   136				return 0;
   137			    row = plane[(uv >> 8) & 0xff];
   138			    if (! row)
   139				return 0;
   140			    cell = row[uv & 0xff];
   141			    if (! cell)
   142				return 0;
   143			    for (i = cell; i->nextchar; i++) {
   144				if (uv2 == i->nextchar)
   145				    return i->composite;
   146			    }
   147			    return 0;
   148			}
   149			
   150			static U8 getCombinClass (UV uv)
   151			{
   152			    U8 **plane, *row;
   153			    if (OVER_UTF_MAX(uv))
   154				return 0;
   155			    plane = (U8**)UNF_combin[uv >> 16];
   156			    if (! plane)
   157				return 0;
   158			    row = plane[(uv >> 8) & 0xff];
   159			    return row ? row[uv & 0xff] : 0;
   160			}
   161			
   162			static void sv_cat_decompHangul (SV* sv, UV uv)
   163			{
   164			    UV sindex, lindex, vindex, tindex;
   165			    U8 *t, tmp[3 * UTF8_MAXLEN + 1];
   166			
   167			    if (! Hangul_IsS(uv))
   168				return;
   169			
   170			    sindex =  uv - Hangul_SBase;
   171			    lindex =  sindex / Hangul_NCount;
   172			    vindex = (sindex % Hangul_NCount) / Hangul_TCount;
   173			    tindex =  sindex % Hangul_TCount;
   174			
   175			    t = tmp;
   176			    t = uvuni_to_utf8(t, (lindex + Hangul_LBase));
   177			    t = uvuni_to_utf8(t, (vindex + Hangul_VBase));
   178			    if (tindex)
   179				t = uvuni_to_utf8(t, (tindex + Hangul_TBase));
   180			    *t = '\0';
   181			    sv_catpvn(sv, (char *)tmp, t - tmp);
   182			}
   183			
   184			static void sv_cat_uvuni (SV* sv, UV uv)
   185			{
   186			    U8 *t, tmp[UTF8_MAXLEN + 1];
   187			
   188			    t = tmp;
   189			    t = uvuni_to_utf8(t, uv);
   190			    *t = '\0';
   191			    sv_catpvn(sv, (char *)tmp, t - tmp);
   192			}
   193			
   194			static char * sv_2pvunicode(SV *sv, STRLEN *lp)
   195			{
   196			    char *s;
   197			    STRLEN len;
   198			    s = (char*)SvPV(sv,len);
   199			    if (!SvUTF8(sv)) {
   200				SV* tmpsv = sv_mortalcopy(sv);
   201				if (!SvPOK(tmpsv))
   202				    (void)sv_pvn_force(tmpsv,&len);
   203				sv_utf8_upgrade(tmpsv);
   204				s = (char*)SvPV(tmpsv,len);
   205			    }
   206			    *lp = len;
   207			    return s;
   208			}
   209			
   210			#ifndef PERL_UNUSED_VAR
   211			#  define PERL_UNUSED_VAR(var) if (0) var = var
   212			#endif
   213			
   214			#line 215 "Normalize.c"
   215	         611    
   216	         370    XS(XS_Unicode__Normalize_decompose); /* prototype to pass -Wmissing-prototypes */
   217	         370    XS(XS_Unicode__Normalize_decompose)
   218	         370    {
   219	         740        dXSARGS;
   220	         740        if (items < 1 || items > 2)
   221	         370    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::decompose(src, compat = &PL_sv_no)");
   222	         370        PERL_UNUSED_VAR(cv); /* -W */
   223	        1011        {
   224	        1011    	SV *	src = ST(0);
   225	        1011    	SV *	compat;
   226	      ######    #line 209 "Normalize.xs"
   227			    SV *dst;
   228	         641        STRLEN srclen, retlen;
   229	          13        U8 *s, *e, *p, *r;
   230			    UV uv;
   231	         628        bool iscompat;
   232	         628    #line 233 "Normalize.c"
   233	         478    	SV *	RETVAL;
   234			
   235	         890    	if (items < 2)
   236	         241    	    compat = &PL_sv_no;
   237				else {
   238	         499    	    compat = ST(1);
   239				}
   240			#line 215 "Normalize.xs"
   241			    iscompat = SvTRUE(compat);
   242			    s = (U8*)sv_2pvunicode(src,&srclen);
   243			    e = s + srclen;
   244			
   245			    dst = newSV(1);
   246			    (void)SvPOK_only(dst);
   247			    SvUTF8_on(dst);
   248			
   249			    for (p = s; p < e; p += retlen) {
   250				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   251				if (!retlen)
   252				    croak(ErrRetlenIsZero);
   253			
   254				if (Hangul_IsS(uv))
   255				    sv_cat_decompHangul(dst, uv);
   256				else {
   257				    r = iscompat ? dec_compat(uv) : dec_canonical(uv);
   258				    if (r)
   259					sv_catpv(dst, (char *)r);
   260				    else
   261					sv_cat_uvuni(dst, uv);
   262				}
   263			    }
   264			    RETVAL = dst;
   265			#line 266 "Normalize.c"
   266	         370    	ST(0) = RETVAL;
   267	         370    	sv_2mortal(ST(0));
   268			    }
   269	         370        XSRETURN(1);
   270			}
   271			
   272			
   273			XS(XS_Unicode__Normalize_reorder); /* prototype to pass -Wmissing-prototypes */
   274			XS(XS_Unicode__Normalize_reorder)
   275	         363    {
   276	         363        dXSARGS;
   277	         363        if (items != 1)
   278	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::reorder(src)");
   279	         363        PERL_UNUSED_VAR(cv); /* -W */
   280			    {
   281	         363    	SV *	src = ST(0);
   282			#line 249 "Normalize.xs"
   283			    SV *dst;
   284			    STRLEN srclen, dstlen, retlen, stk_cc_max;
   285			    U8 *s, *e, *p, *d, curCC;
   286			    UV uv, uvlast;
   287			    UNF_cc * stk_cc;
   288			    STRLEN i, cc_pos;
   289			    bool valid_uvlast;
   290			#line 291 "Normalize.c"
   291	         363    	SV *	RETVAL;
   292			#line 257 "Normalize.xs"
   293			    s = (U8*)sv_2pvunicode(src,&srclen);
   294			    e = s + srclen;
   295			
   296			    dstlen = srclen + 1;
   297			    dst = newSV(dstlen);
   298			    (void)SvPOK_only(dst);
   299			    SvUTF8_on(dst);
   300			    d = (U8*)SvPVX(dst);
   301			
   302			    stk_cc_max = 10; /* enough as an initial value? */
   303			    New(0, stk_cc, stk_cc_max, UNF_cc);
   304			
   305			    for (p = s; p < e;) {
   306				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   307				if (!retlen)
   308				    croak(ErrRetlenIsZero);
   309				p += retlen;
   310			
   311				curCC = getCombinClass(uv);
   312				if (curCC == 0) {
   313				    d = uvuni_to_utf8(d, uv);
   314				    continue;
   315				}
   316			
   317				cc_pos = 0;
   318				stk_cc[cc_pos].cc  = curCC;
   319				stk_cc[cc_pos].uv  = uv;
   320				stk_cc[cc_pos].pos = cc_pos;
   321			
   322				valid_uvlast = FALSE;
   323				while (p < e) {
   324				    uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   325				    if (!retlen)
   326					croak(ErrRetlenIsZero);
   327				    p += retlen;
   328			
   329				    curCC = getCombinClass(uv);
   330				    if (curCC == 0) {
   331					uvlast = uv;
   332					valid_uvlast = TRUE;
   333					break;
   334				    }
   335			
   336				    cc_pos++;
   337				    if (stk_cc_max <= cc_pos) { /* extend if need */
   338					stk_cc_max = cc_pos + 1;
   339					Renew(stk_cc, stk_cc_max, UNF_cc);
   340				    }
   341				    stk_cc[cc_pos].cc  = curCC;
   342				    stk_cc[cc_pos].uv  = uv;
   343				    stk_cc[cc_pos].pos = cc_pos;
   344				}
   345			
   346				/* reordered if there are two c.c.'s */
   347				if (cc_pos) {
   348				    qsort((void*)stk_cc, cc_pos + 1, sizeof(UNF_cc), compare_cc);
   349				}
   350			
   351				for (i = 0; i <= cc_pos; i++) {
   352				    d = uvuni_to_utf8(d, stk_cc[i].uv);
   353				}
   354				if (valid_uvlast)
   355				{
   356				    d = uvuni_to_utf8(d, uvlast);
   357				}
   358			    }
   359			    *d = '\0';
   360			    SvCUR_set(dst, d - (U8*)SvPVX(dst));
   361			    Safefree(stk_cc);
   362			    RETVAL = dst;
   363			#line 364 "Normalize.c"
   364	         363    	ST(0) = RETVAL;
   365	         363    	sv_2mortal(ST(0));
   366			    }
   367	         363        XSRETURN(1);
   368			}
   369			
   370			
   371			XS(XS_Unicode__Normalize_compose); /* prototype to pass -Wmissing-prototypes */
   372			XS(XS_Unicode__Normalize_compose)
   373	         201    {
   374	         201        dXSARGS;
   375	         201        dXSI32;
   376	         201        if (items != 1)
   377	      ######           Perl_croak(aTHX_ "Usage: %s(src)", GvNAME(CvGV(cv)));
   378	         201        PERL_UNUSED_VAR(cv); /* -W */
   379			    {
   380	         201    	SV *	src = ST(0);
   381			#line 339 "Normalize.xs"
   382			    SV  *dst, *tmp;
   383			    U8  *s, *p, *e, *d, *t, *tmp_start, curCC, preCC;
   384			    UV uv, uvS, uvComp;
   385			    STRLEN srclen, dstlen, tmplen, retlen;
   386			    bool beginning = TRUE;
   387			#line 388 "Normalize.c"
   388	         201    	SV *	RETVAL;
   389			#line 345 "Normalize.xs"
   390			    s = (U8*)sv_2pvunicode(src,&srclen);
   391			    e = s + srclen;
   392			
   393			    dstlen = srclen + 1;
   394			    dst = newSV(dstlen);
   395			    (void)SvPOK_only(dst);
   396			    SvUTF8_on(dst);
   397			    d = (U8*)SvPVX(dst);
   398			
   399			  /* for uncomposed combining char */
   400			    tmp = sv_2mortal(newSV(dstlen));
   401			    (void)SvPOK_only(tmp);
   402			    SvUTF8_on(tmp);
   403			
   404			    for (p = s; p < e;) {
   405				if (beginning) {
   406				    uvS = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   407				    if (!retlen)
   408					croak(ErrRetlenIsZero);
   409				    p += retlen;
   410			
   411			            if (getCombinClass(uvS)) { /* no Starter found yet */
   412					d = uvuni_to_utf8(d, uvS);
   413					continue;
   414				    }
   415			            beginning = FALSE;
   416				}
   417			
   418			    /* Starter */
   419				t = tmp_start = (U8*)SvPVX(tmp);
   420				preCC = 0;
   421			
   422			    /* to the next Starter */
   423				while (p < e) {
   424				    uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   425				    if (!retlen)
   426					croak(ErrRetlenIsZero);
   427				    p += retlen;
   428			
   429				    curCC = getCombinClass(uv);
   430			
   431				    if (preCC && preCC == curCC) {
   432					preCC = curCC;
   433					t = uvuni_to_utf8(t, uv);
   434				    } else {
   435					uvComp = composite_uv(uvS, uv);
   436			
   437					if (uvComp && ! isExclusion(uvComp) &&
   438						(ix ? (t == tmp_start) : (preCC <= curCC))) {
   439					    STRLEN leftcur, rightcur, dstcur;
   440					    leftcur  = UNISKIP(uvComp);
   441					    rightcur = UNISKIP(uvS) + UNISKIP(uv);
   442			
   443					    if (leftcur > rightcur) {
   444						dstcur = d - (U8*)SvPVX(dst);
   445						dstlen += leftcur - rightcur;
   446						d = (U8*)SvGROW(dst,dstlen) + dstcur;
   447					    }
   448					    /* preCC not changed to curCC */
   449					    uvS = uvComp;
   450					} else if (! curCC && p < e) { /* blocked */
   451					    break;
   452					} else {
   453					    preCC = curCC;
   454					    t = uvuni_to_utf8(t, uv);
   455					}
   456				    }
   457				}
   458				d = uvuni_to_utf8(d, uvS); /* starter (composed or not) */
   459				tmplen = t - tmp_start;
   460				if (tmplen) { /* uncomposed combining char */
   461				    t = (U8*)SvPVX(tmp);
   462				    while (tmplen--)
   463					*d++ = *t++;
   464				}
   465				uvS = uv;
   466			    } /* for */
   467			    *d = '\0';
   468			    SvCUR_set(dst, d - (U8*)SvPVX(dst));
   469			    RETVAL = dst;
   470			#line 471 "Normalize.c"
   471	         201    	ST(0) = RETVAL;
   472	         201    	sv_2mortal(ST(0));
   473			    }
   474	         201        XSRETURN(1);
   475			}
   476			
   477			
   478			XS(XS_Unicode__Normalize_checkNFD); /* prototype to pass -Wmissing-prototypes */
   479			XS(XS_Unicode__Normalize_checkNFD)
   480	          23    {
   481	          23        dXSARGS;
   482	          23        dXSI32;
   483	          23        if (items != 1)
   484	      ######           Perl_croak(aTHX_ "Usage: %s(src)", GvNAME(CvGV(cv)));
   485	          23        PERL_UNUSED_VAR(cv); /* -W */
   486			    {
   487	          23    	SV *	src = ST(0);
   488			#line 436 "Normalize.xs"
   489			    STRLEN srclen, retlen;
   490			    U8 *s, *e, *p, curCC, preCC;
   491			    UV uv;
   492			#line 493 "Normalize.c"
   493			#line 440 "Normalize.xs"
   494			    s = (U8*)sv_2pvunicode(src,&srclen);
   495			    e = s + srclen;
   496			
   497			    preCC = 0;
   498			    for (p = s; p < e; p += retlen) {
   499				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   500				if (!retlen)
   501				    croak(ErrRetlenIsZero);
   502			
   503				curCC = getCombinClass(uv);
   504				if (preCC > curCC && curCC != 0) /* canonical ordering violated */
   505				    XSRETURN_NO;
   506				if (Hangul_IsS(uv) || (ix ? dec_compat(uv) : dec_canonical(uv)))
   507				    XSRETURN_NO;
   508				preCC = curCC;
   509			    }
   510			    XSRETURN_YES;
   511			#line 512 "Normalize.c"
   512			    }
   513	          23        XSRETURN_EMPTY;
   514			}
   515			
   516			
   517			XS(XS_Unicode__Normalize_checkNFC); /* prototype to pass -Wmissing-prototypes */
   518			XS(XS_Unicode__Normalize_checkNFC)
   519	          28    {
   520	          28        dXSARGS;
   521	          28        dXSI32;
   522	          28        if (items != 1)
   523	      ######           Perl_croak(aTHX_ "Usage: %s(src)", GvNAME(CvGV(cv)));
   524	          28        PERL_UNUSED_VAR(cv); /* -W */
   525			    {
   526	          28    	SV *	src = ST(0);
   527			#line 467 "Normalize.xs"
   528			    STRLEN srclen, retlen;
   529			    U8 *s, *e, *p, curCC, preCC;
   530			    UV uv;
   531			    bool isMAYBE;
   532			#line 533 "Normalize.c"
   533			#line 472 "Normalize.xs"
   534			    s = (U8*)sv_2pvunicode(src,&srclen);
   535			    e = s + srclen;
   536			
   537			    preCC = 0;
   538			    isMAYBE = FALSE;
   539			    for (p = s; p < e; p += retlen) {
   540				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   541				if (!retlen)
   542				    croak(ErrRetlenIsZero);
   543			
   544				curCC = getCombinClass(uv);
   545			
   546				if (preCC > curCC && curCC != 0) /* canonical ordering violated */
   547				    XSRETURN_NO;
   548			
   549				/* get NFC/NFKC property */
   550				if (Hangul_IsS(uv)) /* Hangul syllables are canonical composites */
   551				    ; /* YES */
   552				else if (isExclusion(uv) || isSingleton(uv) || isNonStDecomp(uv))
   553				    XSRETURN_NO;
   554				else if (isComp2nd(uv))
   555				    isMAYBE = TRUE;
   556				else if (ix) {
   557				    char *canon, *compat;
   558				  /* NFKC_NO when having compatibility mapping. */
   559				    canon  = (char *) dec_canonical(uv);
   560				    compat = (char *) dec_compat(uv);
   561				    if (compat && !(canon && strEQ(canon, compat)))
   562					XSRETURN_NO;
   563				} /* end of get NFC/NFKC property */
   564			
   565				preCC = curCC;
   566			    }
   567			    if (isMAYBE)
   568				XSRETURN_UNDEF;
   569			    else
   570				XSRETURN_YES;
   571			#line 572 "Normalize.c"
   572			    }
   573	          28        XSRETURN_EMPTY;
   574			}
   575			
   576			
   577			XS(XS_Unicode__Normalize_checkFCD); /* prototype to pass -Wmissing-prototypes */
   578			XS(XS_Unicode__Normalize_checkFCD)
   579	          39    {
   580	          39        dXSARGS;
   581	          39        dXSI32;
   582	          39        if (items != 1)
   583	      ######           Perl_croak(aTHX_ "Usage: %s(src)", GvNAME(CvGV(cv)));
   584	          39        PERL_UNUSED_VAR(cv); /* -W */
   585			    {
   586	          39    	SV *	src = ST(0);
   587			#line 519 "Normalize.xs"
   588			    STRLEN srclen, retlen, canlen, canret;
   589			    U8 *s, *e, *p, curCC, preCC;
   590			    UV uv, uvLead, uvTrail;
   591			    U8 *sCan, *pCan, *eCan;
   592			    bool isMAYBE;
   593			#line 594 "Normalize.c"
   594			#line 525 "Normalize.xs"
   595			    s = (U8*)sv_2pvunicode(src,&srclen);
   596			    e = s + srclen;
   597			
   598			    preCC = 0;
   599			    isMAYBE = FALSE;
   600			    for (p = s; p < e; p += retlen) {
   601				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   602				if (!retlen)
   603				    croak(ErrRetlenIsZero);
   604			
   605				sCan = (U8*) dec_canonical(uv);
   606			
   607				if (sCan) {
   608				    canlen = (STRLEN)strlen((char *) sCan);
   609				    uvLead = utf8n_to_uvuni(sCan, canlen, &canret, AllowAnyUTF);
   610				}
   611				else {
   612				    uvLead = uv;
   613				}
   614			
   615				curCC = getCombinClass(uvLead);
   616			
   617				if (curCC != 0 && curCC < preCC) /* canonical ordering violated */
   618				    XSRETURN_NO;
   619			
   620				if (ix) {
   621				    if (isExclusion(uv) || isSingleton(uv) || isNonStDecomp(uv))
   622					XSRETURN_NO;
   623				    else if (isComp2nd(uv))
   624					isMAYBE = TRUE;
   625				}
   626			
   627				if (sCan) {
   628				    eCan = sCan + canlen;
   629				    pCan = utf8_hop(eCan, -1);
   630				    if (pCan < sCan)
   631					croak(ErrHopBeforeStart);
   632				    uvTrail = utf8n_to_uvuni(pCan, eCan - pCan, &canret, AllowAnyUTF);
   633				    preCC = getCombinClass(uvTrail);
   634				}
   635				else {
   636				    preCC = curCC;
   637				}
   638			    }
   639			    if (isMAYBE)
   640				XSRETURN_UNDEF;
   641			    else
   642				XSRETURN_YES;
   643			#line 644 "Normalize.c"
   644			    }
   645	          39        XSRETURN_EMPTY;
   646			}
   647			
   648			
   649			XS(XS_Unicode__Normalize_getCombinClass); /* prototype to pass -Wmissing-prototypes */
   650			XS(XS_Unicode__Normalize_getCombinClass)
   651	          36    {
   652	          36        dXSARGS;
   653	          36        if (items != 1)
   654	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::getCombinClass(uv)");
   655	          36        PERL_UNUSED_VAR(cv); /* -W */
   656			    {
   657	          36    	UV	uv = (UV)SvUV(ST(0));
   658	          36    	U8	RETVAL;
   659	          36    	dXSTARG;
   660			
   661	          36    	RETVAL = getCombinClass(uv);
   662	          36    	XSprePUSH; PUSHu((UV)RETVAL);
   663			    }
   664	          36        XSRETURN(1);
   665			}
   666			
   667			
   668			XS(XS_Unicode__Normalize_isExclusion); /* prototype to pass -Wmissing-prototypes */
   669			XS(XS_Unicode__Normalize_isExclusion)
   670	           5    {
   671	           5        dXSARGS;
   672	           5        if (items != 1)
   673	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::isExclusion(uv)");
   674	           5        PERL_UNUSED_VAR(cv); /* -W */
   675			    {
   676	           5    	UV	uv = (UV)SvUV(ST(0));
   677	           5    	bool	RETVAL;
   678			
   679	           5    	RETVAL = isExclusion(uv);
   680	           5    	ST(0) = boolSV(RETVAL);
   681	           5    	sv_2mortal(ST(0));
   682			    }
   683	           5        XSRETURN(1);
   684			}
   685			
   686			
   687			XS(XS_Unicode__Normalize_isSingleton); /* prototype to pass -Wmissing-prototypes */
   688			XS(XS_Unicode__Normalize_isSingleton)
   689	           2    {
   690	           2        dXSARGS;
   691	           2        if (items != 1)
   692	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::isSingleton(uv)");
   693	           2        PERL_UNUSED_VAR(cv); /* -W */
   694			    {
   695	           2    	UV	uv = (UV)SvUV(ST(0));
   696	           2    	bool	RETVAL;
   697			
   698	           2    	RETVAL = isSingleton(uv);
   699	           2    	ST(0) = boolSV(RETVAL);
   700	           2    	sv_2mortal(ST(0));
   701			    }
   702	           2        XSRETURN(1);
   703			}
   704			
   705			
   706			XS(XS_Unicode__Normalize_isNonStDecomp); /* prototype to pass -Wmissing-prototypes */
   707			XS(XS_Unicode__Normalize_isNonStDecomp)
   708	      ######    {
   709	      ######        dXSARGS;
   710	      ######        if (items != 1)
   711	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::isNonStDecomp(uv)");
   712	      ######        PERL_UNUSED_VAR(cv); /* -W */
   713			    {
   714	      ######    	UV	uv = (UV)SvUV(ST(0));
   715	      ######    	bool	RETVAL;
   716			
   717	      ######    	RETVAL = isNonStDecomp(uv);
   718	      ######    	ST(0) = boolSV(RETVAL);
   719	      ######    	sv_2mortal(ST(0));
   720			    }
   721	      ######        XSRETURN(1);
   722			}
   723			
   724			
   725			XS(XS_Unicode__Normalize_isComp2nd); /* prototype to pass -Wmissing-prototypes */
   726			XS(XS_Unicode__Normalize_isComp2nd)
   727	      ######    {
   728	      ######        dXSARGS;
   729	      ######        dXSI32;
   730	      ######        if (items != 1)
   731	      ######           Perl_croak(aTHX_ "Usage: %s(uv)", GvNAME(CvGV(cv)));
   732	      ######        PERL_UNUSED_VAR(cv); /* -W */
   733			    {
   734	      ######    	UV	uv = (UV)SvUV(ST(0));
   735	      ######    	bool	RETVAL;
   736			
   737	      ######    	RETVAL = isComp2nd(uv);
   738	      ######    	ST(0) = boolSV(RETVAL);
   739	      ######    	sv_2mortal(ST(0));
   740			    }
   741	      ######        XSRETURN(1);
   742			}
   743			
   744			
   745			XS(XS_Unicode__Normalize_isNFD_NO); /* prototype to pass -Wmissing-prototypes */
   746			XS(XS_Unicode__Normalize_isNFD_NO)
   747	      ######    {
   748	      ######        dXSARGS;
   749	      ######        dXSI32;
   750	      ######        if (items != 1)
   751	      ######           Perl_croak(aTHX_ "Usage: %s(uv)", GvNAME(CvGV(cv)));
   752	      ######        PERL_UNUSED_VAR(cv); /* -W */
   753			    {
   754	      ######    	UV	uv = (UV)SvUV(ST(0));
   755			#line 613 "Normalize.xs"
   756			    if (Hangul_IsS(uv) || (ix ? dec_compat(uv) : dec_canonical(uv)))
   757				XSRETURN_YES; /* NFD_NO or NFKD_NO */
   758			    else
   759				XSRETURN_NO;
   760			#line 761 "Normalize.c"
   761			    }
   762	      ######        XSRETURN_EMPTY;
   763			}
   764			
   765			
   766			XS(XS_Unicode__Normalize_isComp_Ex); /* prototype to pass -Wmissing-prototypes */
   767			XS(XS_Unicode__Normalize_isComp_Ex)
   768	      ######    {
   769	      ######        dXSARGS;
   770	      ######        dXSI32;
   771	      ######        if (items != 1)
   772	      ######           Perl_croak(aTHX_ "Usage: %s(uv)", GvNAME(CvGV(cv)));
   773	      ######        PERL_UNUSED_VAR(cv); /* -W */
   774			    {
   775	      ######    	UV	uv = (UV)SvUV(ST(0));
   776			#line 628 "Normalize.xs"
   777			    if (isExclusion(uv) || isSingleton(uv) || isNonStDecomp(uv))
   778				XSRETURN_YES; /* NFC_NO or NFKC_NO */
   779			    else if (ix) {
   780				char *canon, *compat;
   781				canon  = (char *) dec_canonical(uv);
   782				compat = (char *) dec_compat(uv);
   783				if (compat && (!canon || strNE(canon, compat)))
   784				    XSRETURN_YES; /* NFC_NO or NFKC_NO */
   785				else
   786				    XSRETURN_NO;
   787			    }
   788			    else
   789				XSRETURN_NO;
   790			#line 791 "Normalize.c"
   791			    }
   792	      ######        XSRETURN_EMPTY;
   793			}
   794			
   795			
   796			XS(XS_Unicode__Normalize_getComposite); /* prototype to pass -Wmissing-prototypes */
   797			XS(XS_Unicode__Normalize_getComposite)
   798	          16    {
   799	          16        dXSARGS;
   800	          16        if (items != 2)
   801	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::getComposite(uv, uv2)");
   802	          16        PERL_UNUSED_VAR(cv); /* -W */
   803			    {
   804	          16    	UV	uv = (UV)SvUV(ST(0));
   805	          16    	UV	uv2 = (UV)SvUV(ST(1));
   806			#line 650 "Normalize.xs"
   807			    UV composite;
   808			#line 809 "Normalize.c"
   809	          16    	SV *	RETVAL;
   810			#line 652 "Normalize.xs"
   811			    composite = composite_uv(uv, uv2);
   812			    RETVAL = composite ? newSVuv(composite) : &PL_sv_undef;
   813			#line 814 "Normalize.c"
   814	          16    	ST(0) = RETVAL;
   815	          16    	sv_2mortal(ST(0));
   816			    }
   817	          16        XSRETURN(1);
   818			}
   819			
   820			
   821			XS(XS_Unicode__Normalize_getCanon); /* prototype to pass -Wmissing-prototypes */
   822			XS(XS_Unicode__Normalize_getCanon)
   823	          26    {
   824	          26        dXSARGS;
   825	          26        dXSI32;
   826	          26        if (items != 1)
   827	      ######           Perl_croak(aTHX_ "Usage: %s(uv)", GvNAME(CvGV(cv)));
   828	          26        PERL_UNUSED_VAR(cv); /* -W */
   829			    {
   830	          26    	UV	uv = (UV)SvUV(ST(0));
   831			#line 666 "Normalize.xs"
   832			    U8 * rstr;
   833			#line 834 "Normalize.c"
   834	          26    	SV *	RETVAL;
   835			#line 668 "Normalize.xs"
   836			    if (Hangul_IsS(uv)) {
   837				SV * dst;
   838				dst = newSV(1);
   839				(void)SvPOK_only(dst);
   840				sv_cat_decompHangul(dst, uv);
   841				RETVAL = dst;
   842			    } else {
   843				rstr = ix ? dec_compat(uv) : dec_canonical(uv);
   844				if (!rstr)
   845				    XSRETURN_UNDEF;
   846				RETVAL = newSVpvn((char *)rstr, strlen((char *)rstr));
   847			    }
   848			    SvUTF8_on(RETVAL);
   849			#line 850 "Normalize.c"
   850	          20    	ST(0) = RETVAL;
   851	          20    	sv_2mortal(ST(0));
   852			    }
   853	          20        XSRETURN(1);
   854			}
   855			
   856			
   857			XS(XS_Unicode__Normalize_splitOnLastStarter); /* prototype to pass -Wmissing-prototypes */
   858			XS(XS_Unicode__Normalize_splitOnLastStarter)
   859	           7    {
   860	           7        dXSARGS;
   861	           7        if (items != 1)
   862	      ######    	Perl_croak(aTHX_ "Usage: Unicode::Normalize::splitOnLastStarter(src)");
   863	           7        PERL_UNUSED_VAR(cv); /* -W */
   864	           7        PERL_UNUSED_VAR(ax); /* -Wall */
   865	           7        SP -= items;
   866			    {
   867	           7    	SV *	src = ST(0);
   868			#line 689 "Normalize.xs"
   869			    SV *svp;
   870			    STRLEN srclen, retlen;
   871			    U8 *s, *e, *p;
   872			    UV uv;
   873			#line 874 "Normalize.c"
   874			#line 694 "Normalize.xs"
   875			    s = (U8*)sv_2pvunicode(src,&srclen);
   876			    e = s + srclen;
   877			
   878			    for (p = e; s < p; ) {
   879				p = utf8_hop(p, -1);
   880				if (p < s)
   881				    croak(ErrHopBeforeStart);
   882				uv = utf8n_to_uvuni(p, e - p, &retlen, AllowAnyUTF);
   883				if (getCombinClass(uv) == 0) /* Last Starter found */
   884				    break;
   885			    }
   886			
   887			    svp = sv_2mortal(newSVpvn((char*)s, p - s));
   888			    SvUTF8_on(svp);
   889			    XPUSHs(svp);
   890			
   891			    svp = sv_2mortal(newSVpvn((char*)p, e - p));
   892			    SvUTF8_on(svp);
   893			    XPUSHs(svp);
   894			#line 895 "Normalize.c"
   895	           7    	PUTBACK;
   896				return;
   897			    }
   898			}
   899			
   900			#ifdef __cplusplus
   901			extern "C"
   902			#endif
   903			XS(boot_Unicode__Normalize); /* prototype to pass -Wmissing-prototypes */
   904			XS(boot_Unicode__Normalize)
   905	          12    {
   906	          12        dXSARGS;
   907	          12        char* file = __FILE__;
   908			
   909	          12        PERL_UNUSED_VAR(cv); /* -W */
   910	          12        PERL_UNUSED_VAR(items); /* -W */
   911	          12        XS_VERSION_BOOTCHECK ;
   912			
   913			    {
   914	          12            CV * cv ;
   915			
   916	          12            newXSproto("Unicode::Normalize::decompose", XS_Unicode__Normalize_decompose, file, "$;$");
   917	          12            newXSproto("Unicode::Normalize::reorder", XS_Unicode__Normalize_reorder, file, "$");
   918	          12            cv = newXS("Unicode::Normalize::composeContiguous", XS_Unicode__Normalize_compose, file);
   919	          12            XSANY.any_i32 = 1 ;
   920	          12            sv_setpv((SV*)cv, "$") ;
   921	          12            cv = newXS("Unicode::Normalize::compose", XS_Unicode__Normalize_compose, file);
   922	          12            XSANY.any_i32 = 0 ;
   923	          12            sv_setpv((SV*)cv, "$") ;
   924	          12            cv = newXS("Unicode::Normalize::checkNFD", XS_Unicode__Normalize_checkNFD, file);
   925	          12            XSANY.any_i32 = 0 ;
   926	          12            sv_setpv((SV*)cv, "$") ;
   927	          12            cv = newXS("Unicode::Normalize::checkNFKD", XS_Unicode__Normalize_checkNFD, file);
   928	          12            XSANY.any_i32 = 1 ;
   929	          12            sv_setpv((SV*)cv, "$") ;
   930	          12            cv = newXS("Unicode::Normalize::checkNFC", XS_Unicode__Normalize_checkNFC, file);
   931	          12            XSANY.any_i32 = 0 ;
   932	          12            sv_setpv((SV*)cv, "$") ;
   933	          12            cv = newXS("Unicode::Normalize::checkNFKC", XS_Unicode__Normalize_checkNFC, file);
   934	          12            XSANY.any_i32 = 1 ;
   935	          12            sv_setpv((SV*)cv, "$") ;
   936	          12            cv = newXS("Unicode::Normalize::checkFCD", XS_Unicode__Normalize_checkFCD, file);
   937	          12            XSANY.any_i32 = 0 ;
   938	          12            sv_setpv((SV*)cv, "$") ;
   939	          12            cv = newXS("Unicode::Normalize::checkFCC", XS_Unicode__Normalize_checkFCD, file);
   940	          12            XSANY.any_i32 = 1 ;
   941	          12            sv_setpv((SV*)cv, "$") ;
   942	          12            newXSproto("Unicode::Normalize::getCombinClass", XS_Unicode__Normalize_getCombinClass, file, "$");
   943	          12            newXSproto("Unicode::Normalize::isExclusion", XS_Unicode__Normalize_isExclusion, file, "$");
   944	          12            newXSproto("Unicode::Normalize::isSingleton", XS_Unicode__Normalize_isSingleton, file, "$");
   945	          12            newXSproto("Unicode::Normalize::isNonStDecomp", XS_Unicode__Normalize_isNonStDecomp, file, "$");
   946	          12            cv = newXS("Unicode::Normalize::isNFKC_MAYBE", XS_Unicode__Normalize_isComp2nd, file);
   947	          12            XSANY.any_i32 = 2 ;
   948	          12            sv_setpv((SV*)cv, "$") ;
   949	          12            cv = newXS("Unicode::Normalize::isComp2nd", XS_Unicode__Normalize_isComp2nd, file);
   950	          12            XSANY.any_i32 = 0 ;
   951	          12            sv_setpv((SV*)cv, "$") ;
   952	          12            cv = newXS("Unicode::Normalize::isNFC_MAYBE", XS_Unicode__Normalize_isComp2nd, file);
   953	          12            XSANY.any_i32 = 1 ;
   954	          12            sv_setpv((SV*)cv, "$") ;
   955	          12            cv = newXS("Unicode::Normalize::isNFKD_NO", XS_Unicode__Normalize_isNFD_NO, file);
   956	          12            XSANY.any_i32 = 1 ;
   957	          12            sv_setpv((SV*)cv, "$") ;
   958	          12            cv = newXS("Unicode::Normalize::isNFD_NO", XS_Unicode__Normalize_isNFD_NO, file);
   959	          12            XSANY.any_i32 = 0 ;
   960	          12            sv_setpv((SV*)cv, "$") ;
   961	          12            cv = newXS("Unicode::Normalize::isNFKC_NO", XS_Unicode__Normalize_isComp_Ex, file);
   962	          12            XSANY.any_i32 = 1 ;
   963	          12            sv_setpv((SV*)cv, "$") ;
   964	          12            cv = newXS("Unicode::Normalize::isComp_Ex", XS_Unicode__Normalize_isComp_Ex, file);
   965	          12            XSANY.any_i32 = 0 ;
   966	          12            sv_setpv((SV*)cv, "$") ;
   967	          12            cv = newXS("Unicode::Normalize::isNFC_NO", XS_Unicode__Normalize_isComp_Ex, file);
   968	          12            XSANY.any_i32 = 0 ;
   969	          12            sv_setpv((SV*)cv, "$") ;
   970	          12            newXSproto("Unicode::Normalize::getComposite", XS_Unicode__Normalize_getComposite, file, "$$");
   971	          12            cv = newXS("Unicode::Normalize::getCanon", XS_Unicode__Normalize_getCanon, file);
   972	          12            XSANY.any_i32 = 0 ;
   973	          12            sv_setpv((SV*)cv, "$") ;
   974	          12            cv = newXS("Unicode::Normalize::getCompat", XS_Unicode__Normalize_getCanon, file);
   975	          12            XSANY.any_i32 = 1 ;
   976	          12            sv_setpv((SV*)cv, "$") ;
   977	          12            newXS("Unicode::Normalize::splitOnLastStarter", XS_Unicode__Normalize_splitOnLastStarter, file);
   978			    }
   979	          12        XSRETURN_YES;
   980			}
   981			
