ShiftJIS-String

 view release on metacpan or  search on metacpan

String.xsX  view on Meta::CPAN

	*d++ = (U8)( c       & 0xFF);
    }
    return d;
}

/********
 *
 * for mktrans.
 *
 * the first 256bytes: index[256];
 * the next 2 bytes:   tolast[2]
 * the following: tochar[2] in 400 bytes per 1 fromchar row.
 *
 ********/

/* 256 + 2 */
#define SJIS_TransIndexPad    (258)

/* at least,
 * for single-byte 0x00..0x7F and 0xA1..0xDF (191 chars) => 382 bytes
 * for double-byte 0x40..0x7E and 0x80..0xFC (188 chars) => 376 bytes
 */
#define SJIS_TransBytesPerRow (400)

#define SJIS_TransUndefByte (0xFF)
#define SJIS_TransDelByte   (0xFE)

static U8*
trans_toptr(U8 *tr, STRLEN trbyte, U8 row, U8 cell)
{
    U8 idx; STRLEN offset;

    idx = tr[row];
    if (idx == SJIS_TransUndefByte)
	return NULL;
    offset = SJIS_TransIndexPad + (idx * SJIS_TransBytesPerRow);

    if (row) {
	if (!Is_SJ2ND(cell))
	    return NULL;
	offset += 2 * (cell - 0x40 - (0x80 <= cell));
    } else {
	if (!Is_SJ1BT(cell))
	    return NULL;
	offset += 2 * (cell - 0x21 * (0xA1 <= cell));
    }
    if (offset >= trbyte)
	croak(PkgName " Panic offset >= transbyte in trans_toptr");
    return(tr + offset);
}


MODULE = ShiftJIS::String	PACKAGE = ShiftJIS::String

void
issjis(...)
  PREINIT:
    I32 i;
    U8 *s;
    STRLEN byte;
  PPCODE:
    for (i = 0; i < items; i++) {
	s = (U8*)SvPV(ST(i), byte);
	if (!issjis(s, byte))
	    XSRETURN_NO;
    }
    XSRETURN_YES;


SV*
length(src)
    SV *src
  PROTOTYPE: $
  PREINIT:
    U8 *s;
    STRLEN byte;
  CODE:
    s = (U8*)SvPV(src,byte);
    RETVAL = newSViv(length(s,byte));
  OUTPUT:
    RETVAL


SV*
strrev(src)
    SV *src
  PROTOTYPE: $
  PREINIT:
    U8 *s, *p, *q, *e;
    STRLEN byte;
    SV *dst;
  CODE:
    s = (U8*)SvPV(src,byte);
    dst = newSVpvn("",0);
    (void)SvPOK_only(dst);
    SvGROW(dst,byte+1);
    SvCUR_set(dst, byte);
    q = (U8*)SvEND(dst);
    *q = '\0';
    p = s;
    e = s + byte;
    while (p < e) {
	if (Is_SJ2BTp(p,e)) {
	    q -= 2;
	    q[0] = *p++;
	    q[1] = *p++;
	}
	else
	    *--q = *p++;
    }
    RETVAL = dst;
  OUTPUT:
    RETVAL


SV*
strspn(src, search)
    SV *src
    SV *search
  PROTOTYPE: $$
  ALIAS:

String.xsX  view on Meta::CPAN

    SV *sub
    I32 pos
  PROTOTYPE: $$;$
  ALIAS:
    rindex = 1
  PREINIT:
    U8 *s, *e, *b, *p;
    STRLEN sbyte, bbyte;
    I32 slen, cnt, ret_iv;
  CODE:
    s = (U8*)SvPV(src,sbyte);
    b = (U8*)SvPV(sub,bbyte);
    slen = length(s,sbyte);

    if (!ix) {
	if (items == 2)
	    pos = 0;
	if (bbyte == 0)
	    XSRETURN_IV(pos <= 0 ? 0 : slen <= pos ? slen : pos);
	if (slen < pos)
	    XSRETURN_IV(-1);
    }
    else {
	if (items == 2)
	    pos = slen;
	if (bbyte == 0)
	    XSRETURN_IV(pos <= 0 ? 0 : slen <= pos ? slen : pos);
	if (pos  <   0)
	    XSRETURN_IV(-1);
    }

    ret_iv = -1;
    e = s + sbyte - (bbyte - 1); /* p must be followed by bbyte */
    for (p = s, cnt = 0; p < e; ++cnt) {
	if (ix ? cnt <= pos : pos <= cnt) {
	    if (*p == *b && (bbyte == 1 || memEQ(p,b,bbyte))) {
		ret_iv = cnt;
		if (!ix)
		    break;
	    }
	}
	p += Is_SJ2BTp(p,e) ? 2 : 1;
    }
    RETVAL = newSViv(ret_iv);
  OUTPUT:
    RETVAL


void
possubstr (src, off, len=-0, rep=&PL_sv_undef)
    SV *src
    I32 off
    I32 len
    SV *rep
  PROTOTYPE: $$;$$
  PREINIT:
    U8 *s, *e, *p, *p_ini, *p_fin;
    STRLEN sbyte;
    I32 slen, ini, fin, cnt;
    int except;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), sbyte)
	: (U8*)SvPV(src, sbyte);

    slen = length(s,sbyte);
    except = FALSE;

    if (slen < off)
	except = TRUE;

    if (items == 2)
	len = slen - off;
    else
	if (off + slen < 0 && len + slen < 0)
	    except = TRUE;
        else if (0 <= len && off + len + slen < 0)
	    except = TRUE;

    if (except)
	if (items > 3)
	    croak(PkgName " outside of string in substr");
	else
	    XSRETURN_UNDEF;

    ini = off < 0 ? slen + off : off;
    fin = len < 0 ? slen + len : ini + len;

    if (ini < 0)
	ini = 0;
    if (ini > fin)
	fin = ini;
    if (slen < ini)
	ini = slen;
    if (slen < fin)
	fin = slen;

    p_ini = (!ini) ? s : NULL;
    p_fin = (!fin) ? s : NULL;

    for (p = s, e = s + sbyte, cnt = 0; p < e; ) {
	if (fin <= cnt)
	    break;
	p += Is_SJ2BTp(p,e) ? 2 : 1;
	++cnt;

	if (cnt == ini)
	    p_ini = p;
	if (cnt == fin)
	    p_fin = p;
    }
    XPUSHs(sv_2mortal(newSViv(p_ini - s)));
    XPUSHs(sv_2mortal(newSViv(p_fin - p_ini)));


void
hiXka(src)
    SV *src
  PROTOTYPE: $
  ALIAS:
    hi2ka = 1
    ka2hi = 2
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    I32 cnt = 0;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV((ix == 1) ? byte : 2 * byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    for (p = s, e = s + byte; p < e;) {
	if (Is_SJ2BTp(p,e)) {
	    if (ix != 2) {
		if (Is_SJ_HI_VUp(p)) {
		    *d++ = *p++ + 1;
		    *d++ = 0x94;
		    p += 3; ++cnt;
		    continue;
		}
		else if (Is_SJ_HI1ST(*p) && Is_SJ_HI2ND(p[1])) {
		    *d++ = *p++ + 1;
		    *d++ = *p - (SJIS_DIFF_HIRA_KATA + Is_SJ_HI2ND1(*p));
		    ++p; ++cnt;
		    continue;
		}
		else if (Is_SJ_HI_ITERp(p)) {
		    *d++ = *p++;
		    *d++ = *p - SJIS_DIFF_HIRA_KATA_ITER;
		    ++p; ++cnt;
		    continue;
		}
	    }
	    if (ix != 1) {
		if (Is_SJ_KA1ST(*p)) {
		    if (Is_SJ_KA2ND(p[1])) {
			*d++ = *p++ - 1;
			*d++ = *p + (SJIS_DIFF_HIRA_KATA + Is_SJ_KA2ND1(*p));
			++p; ++cnt;
			continue;
		    }
		    else if (Is_SJ_KA2ND_VU(p[1])) {
			*d++ = *p++ - 1;
			*d++ = 0xA4;
			*d++ = 0x81;
			*d++ = 0x4A;
			++p; ++cnt;
			continue;
		    }
		    else if (Is_SJ_KA2ND_KA(p[1])) {
			*d++ = *p++ - 1;
			*d++ = 0xA9;
			++p; ++cnt;
			continue;
		    }
		    else if (Is_SJ_KA2ND_KE(p[1])) {
			*d++ = *p++ - 1;
			*d++ = 0xAF;
			++p; ++cnt;
			continue;
		    }
		}
		else if (Is_SJ_KA_ITERp(p)) {
		    *d++ = *p++;
		    *d++ = *p + SJIS_DIFF_HIRA_KATA_ITER;
		    ++p; ++cnt;
		    continue;
		}
	    }
	    *d++ = *p++;
	    *d++ = *p++;
	} else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
kanaH2Z(src)
    SV *src
  PROTOTYPE: $
  ALIAS:
    kataH2Z = 1
    hiraH2Z = 2
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    I32 cnt = 0;
    U8* trail;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV(2 * byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    trail = (ix == 2) ? (U8*)SJIS_HHIRA_TRAIL : (U8*)SJIS_HKANA_TRAIL;

    for (p = s, e = s + byte; p < e; ) {
	if (Is_SJ2BTp(p,e)) {
	    *d++ = *p++;
	    *d++ = *p++;
	}
	else if (Is_SJ_HKPCT(*p)) {
	    *d++ = 0x81;
	    *d++ = trail[ *p++ - 0xA0 ];
	    ++cnt;
	}
	else if (Is_SJ_HKANA(*p)) {
	    *d++ = (ix == 2) ? 0x82 : 0x83;
	    *d   = trail[ *p - 0xA0 ];

	    if (Is_SJ_HKATO(*p) && Is_SJ_HTEN2(p[1])) {
		++*d;
		++p;
	    }
	    else if (Is_SJ_H_VUp(p)) {
		++p;
		if (ix == 2) {
		    *++d = 0x81;
		    *++d = 0x4A;
		}
		else
		    *d = 0x94;
	    }
	    else if (Is_SJ_HHAHO(*p)) {
		if (Is_SJ_HTEN2(p[1])) {
		    ++*d;
		    ++p;
		}
		else if (Is_SJ_HMARU(p[1])) {
		    *d += 2;
		    ++p;
		}
	    }
	    ++d; ++p; ++cnt;
	} else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
kanaZ2H(src)
    SV *src
  PROTOTYPE: $
  ALIAS:
    kataZ2H = 1
    hiraZ2H = 2
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    U16 uv;
    I32 cnt = 0;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV(byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    for (p = s, e = s + byte; p < e; ) {
	if (Is_SJ2BTp(p,e)) {
	    if (Is_SJ_HI_VUp(p)) {
		if (ix == 1) { /* kataZ2H:  not replaced */
		    *d++ = *p++;
		    *d++ = *p++;
		    *d++ = *p++;
		    *d++ = *p++;
		}
		else {
		    *d++ = 0xB3;
		    *d++ = 0xDE;
		    p += 4; ++cnt;
		}
	    }
	    else if (ix != 1 && Is_SJ_HI1ST(*p) && Is_SJ_HI2ND(p[1])) {
		uv = SJIS_ZHIRA_TRAIL[ *++p - 0x9F ];
		if (0xFF < uv)
		    *d++ = (U8)(uv >> 8);
		if (uv)
		    *d++ = (U8)(uv & 0xFF);
		++p; ++cnt;
	    }
	    else if (ix != 2 && Is_SJ_KA1ST(*p) && Is_SJ_KA2ND_X(p[1])) {
		uv = SJIS_ZKATA_TRAIL[ *++p - 0x40 ];
		if (0xFF < uv)
		    *d++ = (U8)(uv >> 8);
		if (uv)
		    *d++ = (U8)(uv & 0xFF);
		++p; ++cnt;
	    }
	    else if (*p == 0x81 && Is_SJ_ZKPCT2ND(p[1])) {
		switch (*++p) {
		case 0x41:
		    *d++ = 0xA4; break;
		case 0x42:
		    *d++ = 0xA1; break;
		case 0x45:
		    *d++ = 0xA5; break;
		case 0x4A:
		    *d++ = 0xDE; break;
		case 0x4B:
		    *d++ = 0xDF; break;
		case 0x5B:
		    *d++ = 0xB0; break;
		case 0x75:
		    *d++ = 0xA2; break;
		case 0x76:
		    *d++ = 0xA3; break;
		}
		++p; ++cnt;
	    }
	    else {
		*d++ = *p++;
		*d++ = *p++;
	    }
	}
	else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
spaceH2Z(src)
    SV *src
  PROTOTYPE: $
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    I32 cnt = 0;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV(2 * byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    for (p = s, e = s + byte; p < e;) {
	if (Is_SJ2BTp(p,e)) {
	    *d++ = *p++;
	    *d++ = *p++;
	}
	else if (Is_SJ_SPACE(*p)) {
	    *d++ = 0x81;
	    *d++ = 0x40;
	    ++p; ++cnt;
	}
	else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
spaceZ2H(src)
    SV *src
  PROTOTYPE: $
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    I32 cnt = 0;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV(byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    for (p = s, e = s + byte; p < e; ) {
	if (Is_SJ2BTp(p,e)) {
	    if (Is_SJ_ZSPACEp(p)) {
		*d++ = 0x20;
		p += 2;
		++cnt;
	    }
	    else {
		*d++ = *p++;
		*d++ = *p++;
	    }
	}
	else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
toupper(src)
    SV * src
  PROTOTYPE: $
  ALIAS:
    tolower = 1
  PREINIT:
    U8 *s, *p, *e, *d;
    STRLEN byte;
    SV *dst;
    I32 cnt = 0;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    dst = byte ? newSV(byte) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    for (p = s, e = s + byte; p < e; ) {
	if (Is_SJ2BTp(p,e)) {
	    *d++ = *p++;
	    *d++ = *p++;
	}
	else if (ix == 0 && Is_SJ_LOWER(*p))
	    *d++ = *p++ - 0x20, ++cnt;
	else if (ix == 1 && Is_SJ_UPPER(*p))
	    *d++ = *p++ + 0x20, ++cnt;
	else
	    *d++ = *p++;
    }
    *d = '\0';
    SvCUR_set(dst, d - (U8*)SvPVX(dst));

    if (SvROK(src)) {
	sv_setsv(SvRV(src), dst);
	XPUSHs(sv_2mortal(newSViv(cnt)));
    }
    else
	XPUSHs(dst);


void
mkrange(src, rev = &PL_sv_undef)
    SV *src
    SV *rev
  PROTOTYPE: $;$
  PREINIT:
    U8 *s, *p, *e, *d;
    U8 lastL = 0, iniL, iniT, finL, finT;
    STRLEN sbyte, dbyte, dstcur;
    SV *dst;
    U16 fr, to;
    int isReverse, doReverse, isrange;
  PPCODE:
    isReverse = SvTRUE(rev);

    s = (U8*)SvPV(src, sbyte);

    dbyte = sbyte + 1;
    dst = sv_2mortal(newSV(dbyte));
    (void)SvPOK_only(dst);
    d = (U8*)SvPVX(dst);

    p = s;
    if (sbyte && *p == '-')
	*d++ = *p++;

    for (e = s + sbyte, isrange = FALSE; p < e; ) {
	if (isrange) {
	    iniL = lastL;
	    iniT = *(d-1);
	    doReverse = FALSE;

	    if (Is_SJ_BACKp(p))
		++p; /* skip \ in <\\> or <\-> */
	    finL = Is_SJ2BTp(p,e) ? *p++ : 0;
	    finT = *p++;

	    fr = (iniL << 8) | iniT;
	    to = (finL << 8) | finT;

	    if (fr > to) {
		if (isReverse)
		    doReverse = TRUE;
		else {
		    char *m;
		    char msg[SJIS_DISPLAY_MAX_BYTES * 2 + 2];

		    m = msg;
		    m = (char*)sjis_display((U8*)m, fr);
		    *m++ = '-';
		    m = (char*)sjis_display((U8*)m, to);
		    *m++ = '\0';
		    croak(PkgName " Invalid character range %s", msg);
		}
	    }
	    dbyte += diff_by_lead(iniL, finL);
	    dstcur = d - (U8*)SvPVX(dst);
	    d = (U8*)SvGROW(dst,dbyte + 1) + dstcur;

	    if (doReverse) /* fr-1 or +1: skip the first */
		d = range_expand_rev(d, (U16)(fr - 1), to);
	    else
		d = range_expand(d, (U16)(fr + 1), to);

	    isrange = FALSE;
	}
	else {
	    if (Is_SJ_BACKp(p)) {
		lastL = 0;
		++p;
		*d++ = *p++;
	    }
	    else if (Is_SJ2BTp(p,e)) {
		lastL = *p;
		*d++ = *p++;
		*d++ = *p++;
	    }
	    else if (Is_SJ_RANGEp(p)) {
		++p;
		if (p < e)
		    isrange = TRUE;
		else
		    *d++ = '-';
	    } else {
		lastL = 0;
		*d++ = *p++;
	    }
	}
    }
    *d = '\0';
    dstcur = d - (U8*)SvPVX(dst);
    SvCUR_set(dst, dstcur);

    if (GIMME_V != G_ARRAY)
	XPUSHs(dst);
    else {
	I32 dlen;
        STRLEN ch = 0;
	d = (U8*)SvPV(dst,dbyte);
	e = d + dbyte;
	dlen = length(d, dbyte);
        EXTEND(SP, dlen);
	for (p = d; p < e; p += ch) {
	    ch = Is_SJ2BTp(p,e) ? 2 : 1;
	    PUSHs(sv_2mortal(newSVpvn((char*)p,ch)));
	}
    }


void
strtr_light (src, trans, mod = &PL_sv_no)
    SV *src;
    SV *trans;
    SV *mod;
  PROTOTYPE: $$;$
  PREINIT:
    SV *dst;
    int mod_c, mod_d, mod_s, found;
    int modes, tlen, cnt;
    U8 *p, *e, *s, *d, *tr, *m;
    STRLEN idx;
    STRLEN byte, trbyte, modbyte;
    U8 fr[2], *to, tolast[2], pre[2], tmp[2];
    STRLEN fbyte, tbyte, lbyte, prebyte, tmpbyte;
  PPCODE:
    s = SvROK(src)
	? (U8*)SvPV_force(SvRV(src), byte)
	: (U8*)SvPV(src, byte);

    tr = (U8*)SvPV(trans, trbyte);

    if (trbyte < SJIS_TransIndexPad)
	croak(PkgName " Panic! too short trans string in strtr_light");
    idx = (trbyte - SJIS_TransIndexPad) / SJIS_TransBytesPerRow;

    for (p = tr, e = tr + 0x100; p < e; p++)
	if (*p != SJIS_TransUndefByte && idx <= *p)
	    croak(PkgName " Panic! index is broken in strtr_light");

    tolast[0] = tr[SJIS_TransIndexPad - 2];
    tolast[1] = tr[SJIS_TransIndexPad - 1];
    lbyte = (*tolast == SJIS_TransUndefByte) ? 0 : (*tolast) ? 2 : 1;

    /* now only bool, not a string-length */
    tlen = (*tolast != SJIS_TransUndefByte);

    m = (U8*)SvPV(mod, modbyte);
    mod_c = memchr((void*)m, 'c', modbyte) != NULL;
    mod_d = memchr((void*)m, 'd', modbyte) != NULL;
    mod_s = memchr((void*)m, 's', modbyte) != NULL;
    modes = (mod_s << 2) | (mod_d << 1) | mod_c;

    dst = byte ? newSV(2 * byte + 1) : newSVpvn("",0);
    (void)SvPOK_only(dst);
    (void)sv_2mortal(dst);
    d = (U8*)SvPVX(dst);

    prebyte = pre[0] = pre[1] = 0;
    tmpbyte = tmp[0] = tmp[1] = 0;

    for (p = s, e = s + byte, cnt = 0; p < e; ) {
	fr[0] = Is_SJ2BTp(p,e) ? *p++ : 0;
	fr[1] = *p++;

	fbyte = (*fr) ? 2 : 1;
	tbyte = 0;
	to = trans_toptr(tr, trbyte, fr[0], fr[1]);

	found = FALSE;
	if (to != NULL && *to != SJIS_TransUndefByte) {
	    found = TRUE;
	    tbyte = (*to == SJIS_TransDelByte) ? 0 : (*to) ? 2 : 1;
	}

	if (mod_c ^ found)
	    cnt++;

	switch (modes) {
	case 0: /* c: false, d: false, s: false */
	case 2: /* c: false, d: true,  s: false */

	    if (found) {
		if (tbyte > 1)
		    *d++ = to[0];
		if (tbyte > 0)

String.xsX  view on Meta::CPAN


	if (t && t < tend) {
	    to[0] = Is_SJ2BTp(t,tend) ? *t++ : 0;
	    to[1] = *t++;
	}

	here = trans_toptr(d, dbyte, fr[0], fr[1]);

	if (here && *here == SJIS_TransUndefByte) {
	    if (tbyte) {
		if (t) {
		    here[0] = to[0];
		    here[1] = to[1];
		}
		else if (!mod_d) {
		    here[0] = tolast[0];
		    here[1] = tolast[1];
		}
		else
		    here[0] = here[1] = SJIS_TransDelByte;
	    } else {
		if (!mod_d || mod_c) {
		    here[0] = fr[0];
		    here[1] = fr[1];
		}
		else
		    here[0] = here[1] = SJIS_TransDelByte;
	    }
	}

	if (t && t >= tend) {
	    t = NULL;
	    tolast[0] = to[0];
	    tolast[1] = to[1];
	}
    }
    if (t) {
	while (t < tend) {
	    tolast[0] = Is_SJ2BTp(t,tend) ? *t++ : 0;
	    tolast[1] = *t++;
        }
    }
    d[SJIS_TransIndexPad - 2] = tolast[0];
    d[SJIS_TransIndexPad - 1] = tolast[1];
    RETVAL = dst;
  OUTPUT:
    RETVAL


void
strsplit (separator, src, lim = 0)
    SV *separator;
    SV *src;
    I32 lim;
  PROTOTYPE: $$;$
  PREINIT:
    U8 *s, *e, *p, *sep, *anc, *last;
    STRLEN byte, sepbyte, ch;
    int wantarray;
    I32 cnt = 0;
  PPCODE:
    wantarray = (GIMME_V == G_ARRAY);

    s = (U8*)SvPV(src, byte);

    if (!byte)
	if (wantarray)
	    XSRETURN_EMPTY;
	else
	    XSRETURN_IV(0);

    if (!separator || !SvOK(separator)) { /* splitspace */
	e = s + byte;

        for (p = s; p < e; p += ch) {
	    ch = Is_SJ2BTp(p,e) ? 2 : 1;
	    if (!Is_SJ_SPACEpc(p,ch))
		break;
	}

	for (anc = p; (lim <= 0 || cnt < lim - 1) && p < e; p += ch) {
	    ch = Is_SJ2BTp(p,e) ? 2 : 1;
	    if (Is_SJ_SPACEpc(p,ch)) {
		if (anc != p) {
		    ++cnt;
		    if (wantarray)
			XPUSHs(sv_2mortal(newSVpvn((char*)anc, p - anc)));
		}
		anc = p + ch;
	    }
	}

        for (; p < e; p += ch) {
	    ch = Is_SJ2BTp(p,e) ? 2 : 1;
	    if (!Is_SJ_SPACEpc(p,ch))
		break;
	    anc = p + ch;
	}

	if (!(lim == 0 && e == anc)) {
	    ++cnt;
	    if (wantarray)
		XPUSHs(sv_2mortal(newSVpvn((char*)anc, e - anc)));
	}

	if (!wantarray)
	     XPUSHs(sv_2mortal(newSViv(cnt)));
    } /* end-splitspace */

    else { /* other than splitspace */
	sep = (U8*)SvPV(separator, sepbyte);

	if (!sepbyte) { /* splitchar */
	    if (wantarray)
		EXTEND(SP, lim <= 0 ? length(s,byte) : lim);

	    for (p = s, e = s + byte, cnt = 0;
	         (lim <= 0 || cnt < lim - 1) && p < e; cnt++)
	    {
		ch = Is_SJ2BTp(p,e) ? 2 : 1;
		if (wantarray)



( run in 0.937 second using v1.01-cache-2.11-cpan-5511b514fd6 )