Changeset 15091

Show
Ignore:
Timestamp:
07/03/08 15:01:57 (5 months ago)
Author:
dankogai
Message:

Unicode/Unicode.xs Refactored by Alex Davies

Location:
lang/perl/Encode/trunk
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • lang/perl/Encode/trunk/AUTHORS

    r1747 r15091  
    1010# This list is in alphabetical order. 
    1111-- 
    12 Andreas J. Koenig               <andreas.koenig@anima.de> 
     12Alex Davies                     <alex.davies@talktalk.net> 
     13Andreas J. Koenig               <andreas.koenig@anima.de> 
    1314Anton Tagunov                   <tagunov@motor.ru> 
    1415Autrijus Tang                   <autrijus@autrijus.org> 
  • lang/perl/Encode/trunk/Changes

    r15030 r15091  
    44# 
    55$Revision: 2.26 $ $Date: 2008/07/01 20:56:17 $ 
     6! Unicode/Unicode.xs 
     7  Refactored by Alex Davies 
     8  http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2007-10/msg00745.html 
     9  Message-Id: <7637669B2E3D46B187591747DA27F4C8@Amelie> 
     10 
     112.26 2008/07/01 20:56:17 
    612! Encode.pm 
    713  Absense of Encode::ConfigLocal no longer carps no matter what. 
    8   https://bugzilla.redhat.com/show_bug.cgi?id=435505#c2 
    9   https://rt.cpan.org/Ticket/Display.html?id=28638 
    10   https://rt.cpan.org/Ticket/Display.html?id=11511 
     14  http://bugzilla.redhat.com/show_bug.cgi?id=435505#c2 
     15  http://rt.cpan.org/Ticket/Display.html?id=28638 
     16  http://rt.cpan.org/Ticket/Display.html?id=11511 
    1117! lib/Encode/JIS7.pm 
    1218  use encoding 'utf8' and 'iso-2022-jp' glitches on perl 5.10 
  • lang/perl/Encode/trunk/Encode.xs

    r7855 r15091  
    11/* 
    2  $Id: Encode.xs,v 2.14 2007/05/29 18:15:32 dankogai Exp $ 
     2 $Id: Encode.xs,v 2.14 2007/05/29 18:15:32 dankogai Exp dankogai $ 
    33 */ 
    44 
  • lang/perl/Encode/trunk/Unicode/Unicode.xs

    r1747 r15091  
    1919#define invalid_ucs2(x)         ( issurrogate(x) || 0xFFFF < (x) ) 
    2020 
     21#define PERLIO_BUFSIZ 1024 /* XXX value comes from PerlIOEncode_get_base */ 
     22 
     23/* Avoid wasting too much space in the result buffer */ 
     24static void 
     25shrink_buffer(SV *result) 
     26{ 
     27    if (SvLEN(result) > 42 + SvCUR(result)) { 
     28        char *buf; 
     29        STRLEN datalen = 1 + SvCUR(result); /* include the NUL byte */ 
     30        STRLEN buflen = PERL_STRLEN_ROUNDUP(datalen); 
     31        Newx(buf, buflen, char); 
     32        Copy(SvPVX(result), buf, datalen, char); 
     33        Safefree(SvPVX(result)); 
     34        SvPV_set(result, buf); 
     35        SvLEN_set(result, buflen); 
     36    } 
     37} 
     38 
    2139static UV 
    22 enc_unpack(pTHX_ U8 **sp,U8 *e,STRLEN size,U8 endian) 
     40enc_unpack(pTHX_ U8 **sp, U8 *e, STRLEN size, U8 endian) 
    2341{ 
    2442    U8 *s = *sp; 
    2543    UV v = 0; 
    2644    if (s+size > e) { 
    27     croak("Partial character %c",(char) endian); 
     45        croak("Partial character %c",(char) endian); 
    2846    } 
    2947    switch(endian) { 
    3048    case 'N': 
    31     v = *s++; 
    32     v = (v << 8) | *s++; 
     49        v = *s++; 
     50        v = (v << 8) | *s++; 
    3351    case 'n': 
    34     v = (v << 8) | *s++; 
    35     v = (v << 8) | *s++; 
    36     break; 
     52        v = (v << 8) | *s++; 
     53        v = (v << 8) | *s++; 
     54        break; 
    3755    case 'V': 
    3856    case 'v': 
    39     v |= *s++; 
    40     v |= (*s++ << 8); 
    41     if (endian == 'v') 
    42         break; 
    43     v |= (*s++ << 16); 
    44     v |= (*s++ << 24); 
    45     break; 
     57        v |= *s++; 
     58        v |= (*s++ << 8); 
     59        if (endian == 'v') 
     60            break; 
     61        v |= (*s++ << 16); 
     62        v |= (*s++ << 24); 
     63        break; 
    4664    default: 
    47     croak("Unknown endian %c",(char) endian); 
    48     break; 
     65        croak("Unknown endian %c",(char) endian); 
     66        break; 
    4967    } 
    5068    *sp = s; 
     
    5371 
    5472void 
    55 enc_pack(pTHX_ SV *result,STRLEN size,U8 endian,UV value) 
    56 { 
    57     U8 *d = (U8 *)SvGROW(result,SvCUR(result)+size+1); 
     73enc_pack(pTHX_ SV *result, STRLEN size, U8 endian, UV value) 
     74{ 
     75    U8 *d = (U8 *) SvPV_nolen(result); 
     76 
    5877    switch(endian) { 
    5978    case 'v': 
    6079    case 'V': 
    61     d += SvCUR(result); 
    62     SvCUR_set(result,SvCUR(result)+size); 
    63     while (size--) { 
    64         *d++ = (U8)(value & 0xFF); 
    65         value >>= 8; 
    66     } 
    67     break; 
     80        d += SvCUR(result); 
     81        SvCUR_set(result,SvCUR(result)+size); 
     82        while (size--) { 
     83            *d++ = (U8)(value & 0xFF); 
     84            value >>= 8; 
     85        } 
     86        break; 
    6887    case 'n': 
    6988    case 'N': 
    70     SvCUR_set(result,SvCUR(result)+size); 
    71     d += SvCUR(result); 
    72     while (size--) { 
    73         *--d = (U8)(value & 0xFF); 
    74         value >>= 8; 
    75     } 
    76     break; 
     89        SvCUR_set(result,SvCUR(result)+size); 
     90        d += SvCUR(result); 
     91        while (size--) { 
     92            *--d = (U8)(value & 0xFF); 
     93            value >>= 8; 
     94        } 
     95        break; 
    7796    default: 
    78     croak("Unknown endian %c",(char) endian); 
    79     break; 
     97        croak("Unknown endian %c",(char) endian); 
     98        break; 
    8099    } 
    81100} 
     
    95114CODE: 
    96115{ 
    97     U8 endian   = *((U8 *)SvPV_nolen(attr("endian", 6))); 
    98     int size    =   SvIV(attr("size",  4)); 
    99     int ucs2    = SvTRUE(attr("ucs2",   4)); 
    100     int renewed = SvTRUE(attr("renewed",  7)); 
    101     SV *result  = newSVpvn("",0); 
     116    U8 endian    = *((U8 *)SvPV_nolen(attr("endian", 6))); 
     117    int size     = SvIV(attr("size", 4)); 
     118    int ucs2     = -1; /* only needed in the event of surrogate pairs */ 
     119    SV *result   = newSVpvn("",0); 
     120    STRLEN usize = (size > 0 ? size : 1); /* protect against rogue size<=0 */ 
    102121    STRLEN ulen; 
     122    STRLEN resultbuflen; 
     123    U8 *resultbuf; 
    103124    U8 *s = (U8 *)SvPVbyte(str,ulen); 
    104125    U8 *e = (U8 *)SvEND(str); 
     126    /* Optimise for the common case of being called from PerlIOEncode_fill() 
     127       with a standard length buffer. In this case the result SV's buffer is 
     128       only used temporarily, so we can afford to allocate the maximum needed 
     129       and not care about unused space. */ 
     130    const bool temp_result = (ulen == PERLIO_BUFSIZ); 
     131 
    105132    ST(0) = sv_2mortal(result); 
    106133    SvUTF8_on(result); 
    107134 
    108135    if (!endian && s+size <= e) { 
    109     UV bom; 
    110     endian = (size == 4) ? 'N' : 'n'; 
    111     bom = enc_unpack(aTHX_ &s,e,size,endian); 
    112         if (bom != BOM_BE) { 
    113         if (bom == BOM16LE) { 
    114         endian = 'v'; 
    115         } 
    116         else if (bom == BOM32LE) { 
    117         endian = 'V'; 
    118         } 
    119         else { 
    120         croak("%"SVf":Unrecognised BOM %"UVxf, 
    121                       *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
    122               bom); 
    123         } 
    124     } 
     136        UV bom; 
     137        endian = (size == 4) ? 'N' : 'n'; 
     138        bom = enc_unpack(aTHX_ &s,e,size,endian); 
     139        if (bom != BOM_BE) { 
     140            if (bom == BOM16LE) { 
     141                endian = 'v'; 
     142            } 
     143            else if (bom == BOM32LE) { 
     144                endian = 'V'; 
     145            } 
     146            else { 
     147                croak("%"SVf":Unrecognised BOM %"UVxf, 
     148                      *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
     149                      bom); 
     150            } 
     151        } 
    125152#if 1 
    126     /* Update endian for next sequence */ 
    127     if (renewed) { 
    128         hv_store((HV *)SvRV(obj),"endian",6,newSVpv((char *)&endian,1),0); 
    129     } 
     153        /* Update endian for next sequence */ 
     154        if (SvTRUE(attr("renewed", 7))) { 
     155            hv_store((HV *)SvRV(obj),"endian",6,newSVpv((char *)&endian,1),0); 
     156        } 
    130157#endif 
    131158    } 
     159 
     160    if (temp_result) { 
     161        resultbuflen = 1 + ulen/usize * UTF8_MAXLEN; 
     162    } else { 
     163        /* Preallocate the buffer to the minimum possible space required. */ 
     164        resultbuflen = ulen/usize + UTF8_MAXLEN + 1; 
     165    } 
     166    resultbuf = (U8 *) SvGROW(result, resultbuflen); 
     167 
    132168    while (s < e && s+size <= e) { 
    133     UV ord = enc_unpack(aTHX_ &s,e,size,endian); 
    134     U8 *d; 
    135     if (issurrogate(ord)) { 
    136         if (ucs2 || size == 4) { 
    137         if (check) { 
    138             croak("%"SVf":no surrogates allowed %"UVxf, 
    139               *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
    140               ord); 
    141         } 
    142         if (s+size <= e) { 
    143                     /* skip the next one as well */ 
    144             enc_unpack(aTHX_ &s,e,size,endian); 
    145         } 
    146         ord = FBCHAR; 
    147         } 
    148         else { 
    149         UV lo; 
    150         if (!isHiSurrogate(ord)) { 
    151             if (check) { 
    152             croak("%"SVf":Malformed HI surrogate %"UVxf, 
    153                   *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
    154                   ord); 
    155             } 
    156             else { 
    157             ord = FBCHAR; 
    158             } 
    159         } 
    160             else { 
    161             if (s+size > e) { 
    162             /* Partial character */ 
    163             s -= size;   /* back up to 1st half */ 
    164             break;       /* And exit loop */ 
    165             } 
    166             lo = enc_unpack(aTHX_ &s,e,size,endian); 
    167             if (!isLoSurrogate(lo)){ 
    168             if (check) { 
    169                 croak("%"SVf":Malformed LO surrogate %"UVxf, 
    170                   *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
    171                   ord); 
    172             } 
    173             else { 
    174                 ord = FBCHAR; 
    175             } 
    176             } 
    177             else { 
    178             ord = 0x10000 + ((ord - 0xD800) << 10) + (lo - 0xDC00); 
    179             } 
    180         } 
    181         } 
    182     } 
    183  
    184     if ((ord & 0xFFFE) == 0xFFFE || (ord >= 0xFDD0 && ord <= 0xFDEF)) { 
    185         if (check) { 
    186         croak("%"SVf":Unicode character %"UVxf" is illegal", 
    187               *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
    188               ord); 
    189         } else { 
    190         ord = FBCHAR; 
    191         } 
    192     } 
    193  
    194     d = (U8 *) SvGROW(result,SvCUR(result)+UTF8_MAXLEN+1); 
    195     d = uvuni_to_utf8_flags(d+SvCUR(result), ord, 0); 
    196     SvCUR_set(result,d - (U8 *)SvPVX(result)); 
    197     } 
     169        UV ord = enc_unpack(aTHX_ &s,e,size,endian); 
     170        U8 *d; 
     171        if (issurrogate(ord)) { 
     172            if (ucs2 == -1) { 
     173                ucs2 = SvTRUE(attr("ucs2", 4)); 
     174            } 
     175            if (ucs2 || size == 4) { 
     176                if (check) { 
     177                    croak("%"SVf":no surrogates allowed %"UVxf, 
     178                          *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
     179                          ord); 
     180                } 
     181                if (s+size <= e) { 
     182                    /* skip the next one as well */ 
     183                    enc_unpack(aTHX_ &s,e,size,endian); 
     184                } 
     185                ord = FBCHAR; 
     186            } 
     187            else { 
     188                UV lo; 
     189                if (!isHiSurrogate(ord)) { 
     190                    if (check) { 
     191                        croak("%"SVf":Malformed HI surrogate %"UVxf, 
     192                              *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
     193                              ord); 
     194                    } 
     195                    else { 
     196                        ord = FBCHAR; 
     197                    } 
     198                } 
     199                else { 
     200                    if (s+size > e) { 
     201                        /* Partial character */ 
     202                        s -= size;   /* back up to 1st half */ 
     203                        break;       /* And exit loop */ 
     204                    } 
     205                    lo = enc_unpack(aTHX_ &s,e,size,endian); 
     206                    if (!isLoSurrogate(lo)) { 
     207                        if (check) { 
     208                            croak("%"SVf":Malformed LO surrogate %"UVxf, 
     209                                  *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
     210                                  ord); 
     211                        } 
     212                        else { 
     213                            ord = FBCHAR; 
     214                        } 
     215                    } 
     216                    else { 
     217                        ord = 0x10000 + ((ord - 0xD800) << 10) + (lo - 0xDC00); 
     218                    } 
     219                } 
     220            } 
     221        } 
     222 
     223        if ((ord & 0xFFFE) == 0xFFFE || (ord >= 0xFDD0 && ord <= 0xFDEF)) { 
     224            if (check) { 
     225                croak("%"SVf":Unicode character %"UVxf" is illegal", 
     226                      *hv_fetch((HV *)SvRV(obj),"Name",4,0), 
     227                      ord); 
     228            } else { 
     229                ord = FBCHAR; 
     230            } 
     231        } 
     232 
     233        if (resultbuflen < SvCUR(result) + UTF8_MAXLEN + 1) { 
     234            /* Do not allocate >8Mb more than the minimum needed. 
     235               This prevents allocating too much in the rogue case of a large 
     236               input consisting initially of long sequence uft8-byte unicode 
     237               chars followed by single utf8-byte chars. */ 
     238            STRLEN remaining = (e - s)/usize; 
     239            STRLEN max_alloc = remaining + (8*1024*1024); 
     240            STRLEN est_alloc = remaining * UTF8_MAXLEN; 
     241            STRLEN newlen = SvLEN(result) + /* min(max_alloc, est_alloc) */ 
     242                (est_alloc > max_alloc ? max_alloc : est_alloc); 
     243            resultbuf = (U8 *) SvGROW(result, newlen); 
     244            resultbuflen = SvLEN(result); 
     245        } 
     246 
     247        d = uvuni_to_utf8_flags(resultbuf+SvCUR(result), ord, 0); 
     248        SvCUR_set(result, d - (U8 *)SvPVX(result)); 
     249    } 
     250 
    198251    if (s < e) { 
    199     /* unlikely to happen because it's fixed-length -- dankogai */ 
    200     if (check & ENCODE_WARN_ON_ERR){ 
    201         Perl_warner(aTHX_ packWARN(WARN_UTF8),"%"SVf":Partial character", 
    202             *hv_fetch((HV *)SvRV(obj),"Name",4,0)); 
    203     } 
    204     } 
    205     if (check && !(check & ENCODE_LEAVE_SRC)){ 
    206     if (s < e) { 
    207         Move(s,SvPVX(str),e-s,U8); 
    208         SvCUR_set(str,(e-s)); 
    209     } 
    210     else { 
    211         SvCUR_set(str,0); 
    212     } 
    213     *SvEND(str) = '\0'; 
    214     } 
     252        /* unlikely to happen because it's fixed-length -- dankogai */ 
     253        if (check & ENCODE_WARN_ON_ERR) { 
     254            Perl_warner(aTHX_ packWARN(WARN_UTF8),"%"SVf":Partial character", 
     255                        *hv_fetch((HV *)SvRV(obj),"Name",4,0)); 
     256        } 
     257    } 
     258    if (check && !(check & ENCODE_LEAVE_SRC)) { 
     259        if (s < e) { 
     260            Move(s,SvPVX(str),e-s,U8); 
     261            SvCUR_set(str,(e-s)); 
     262        } 
     263        else { 
     264            SvCUR_set(str,0); 
     265        } 
     266        *SvEND(str) = '\0'; 
     267    } 
     268 
     269    if (!temp_result) 
     270        shrink_buffer(result); 
     271 
    215272    XSRETURN(1); 
    216273} 
     
    223280CODE: 
    224281{ 
    225     U8 endian   = *((U8 *)SvPV_nolen(attr("endian", 6))); 
    226     int size    =   SvIV(attr("size",  4)); 
    227     int ucs2    = SvTRUE(attr("ucs2",   4)); 
    228     int renewed = SvTRUE(attr("renewed",  7)); 
    229     SV *result  = newSVpvn("",0); 
     282    U8 endian = *((U8 *)SvPV_nolen(attr("endian", 6))); 
     283    const int size = SvIV(attr("size", 4)); 
     284    int ucs2 = -1; /* only needed if there is invalid_ucs2 input */ 
     285    const STRLEN usize = (size > 0 ? size : 1); 
     286    SV *result = newSVpvn("", 0); 
    230287    STRLEN ulen; 
    231     U8 *s = (U8 *)SvPVutf8(utf8,ulen); 
    232     U8 *e = (U8 *)SvEND(utf8); 
     288    U8 *s = (U8 *) SvPVutf8(utf8, ulen); 
     289    const U8 *e = (U8 *) SvEND(utf8); 
     290    /* Optimise for the common case of being called from PerlIOEncode_flush() 
     291       with a standard length buffer. In this case the result SV's buffer is 
     292       only used temporarily, so we can afford to allocate the maximum needed 
     293       and not care about unused space. */ 
     294    const bool temp_result = (ulen == PERLIO_BUFSIZ); 
     295 
    233296    ST(0) = sv_2mortal(result); 
     297 
     298    /* Preallocate the result buffer to the maximum possible size. 
     299       ie. assume each UTF8 byte is 1 character. 
     300       Then shrink the result's buffer if necesary at the end. */ 
     301    SvGROW(result, ((ulen+1) * usize)); 
     302 
    234303    if (!endian) { 
    235     endian = (size == 4) ? 'N' : 'n'; 
    236     enc_pack(aTHX_ result,size,endian,BOM_BE); 
     304        endian = (size == 4) ? 'N' : 'n'; 
     305        enc_pack(aTHX_ result,size,endian,BOM_BE); 
    237306#if 1 
    238     /* Update endian for next sequence */ 
    239     if (renewed){ 
    240         hv_store((HV *)SvRV(obj),"endian",6,newSVpv((char *)&endian,1),0); 
    241     } 
     307        /* Update endian for next sequence */ 
     308        if (SvTRUE(attr("renewed", 7))) { 
     309            hv_store((HV *)SvRV(obj),"endian",6,newSVpv((char *)&endian,1),0); 
     310        } 
    242311#endif 
    243312    } 
    244313    while (s < e && s+UTF8SKIP(s) <= e) { 
    245     STRLEN len; 
    246     UV ord = utf8n_to_uvuni(s, e-s, &len, 0); 
    247         s += len; 
    248     if (size != 4 && invalid_ucs2(ord)) { 
    249         if (!issurrogate(ord)){ 
    250         if (ucs2) { 
    251             if (check) { 
    252             croak("%"SVf":code point \"\\x{%"UVxf"}\" too high", 
    253                   *hv_fetch((HV *)SvRV(obj),"Name",4,0),ord); 
    254             } 
    255             enc_pack(aTHX_ result,size,endian,FBCHAR); 
    256         }else{ 
    257             UV hi = ((ord - 0x10000) >> 10)   + 0xD800; 
    258             UV lo = ((ord - 0x10000) & 0x3FF) + 0xDC00; 
    259             enc_pack(aTHX_ result,size,endian,hi); 
    260             enc_pack(aTHX_ result,size,endian,lo); 
    261         } 
    262         } 
    263         else { 
    264         /* not supposed to happen */ 
    265         enc_pack(aTHX_ result,size,endian,FBCHAR); 
    266         } 
    267     } 
    268     else { 
    269         enc_pack(aTHX_ result,size,endian,ord); 
    270     } 
     314        STRLEN len; 
     315        UV ord = utf8n_to_uvuni(s, e-s, &len, 0); 
     316        s += len; 
     317        if (size != 4 && invalid_ucs2(ord)) { 
     318            if (!issurrogate(ord)) { 
     319                if (ucs2 == -1) { 
     320                    ucs2 = SvTRUE(attr("ucs2", 4)); 
     321                } 
     322                if (ucs2) { 
     323                    if (check) { 
     324                        croak("%"SVf":code point \"\\x{%"UVxf"}\" too high", 
     325                                  *hv_fetch((HV *)SvRV(obj),"Name",4,0),ord); 
     326                    } 
     327                    enc_pack(aTHX_ result,size,endian,FBCHAR); 
     328                } else { 
     329                    UV hi = ((ord - 0x10000) >> 10)   + 0xD800; 
     330                    UV lo = ((ord - 0x10000) & 0x3FF) + 0xDC00; 
     331                    enc_pack(aTHX_ result,size,endian,hi); 
     332                    enc_pack(aTHX_ result,size,endian,lo); 
     333                } 
     334            } 
     335            else { 
     336                /* not supposed to happen */ 
     337                enc_pack(aTHX_ result,size,endian,FBCHAR); 
     338            } 
     339        } 
     340        else { 
     341            enc_pack(aTHX_ result,size,endian,ord); 
     342        } 
    271343    } 
    272344    if (s < e) { 
    273     /* UTF-8 partial char happens often on PerlIO. 
    274        Since this is okay and normal, we do not warn. 
    275        But this is critical when you choose to LEAVE_SRC 
    276        in which case we die */ 
    277     if (check & (ENCODE_DIE_ON_ERR|ENCODE_LEAVE_SRC)){ 
    278         Perl_croak(aTHX_ "%"SVf":partial character is not allowed " 
    279                "when CHECK = 0x%" UVuf, 
    280                *hv_fetch((HV *)SvRV(obj),"Name",4,0), check); 
    281     } 
    282      
    283     } 
    284     if (check && !(check & ENCODE_LEAVE_SRC)){ 
    285     if (s < e) { 
    286         Move(s,SvPVX(utf8),e-s,U8); 
    287         SvCUR_set(utf8,(e-s)); 
    288     } 
    289     else { 
    290         SvCUR_set(utf8,0); 
    291     } 
    292     *SvEND(utf8) = '\0'; 
    293     }  
     345        /* UTF-8 partial char happens often on PerlIO. 
     346           Since this is okay and normal, we do not warn. 
     347           But this is critical when you choose to LEAVE_SRC 
     348           in which case we die */ 
     349        if (check & (ENCODE_DIE_ON_ERR|ENCODE_LEAVE_SRC)) { 
     350            Perl_croak(aTHX_ "%"SVf":partial character is not allowed " 
     351                       "when CHECK = 0x%" UVuf, 
     352                       *hv_fetch((HV *)SvRV(obj),"Name",4,0), check); 
     353        } 
     354    } 
     355    if (check && !(check & ENCODE_LEAVE_SRC)) { 
     356        if (s < e) { 
     357            Move(s,SvPVX(utf8),e-s,U8); 
     358            SvCUR_set(utf8,(e-s)); 
     359        } 
     360        else { 
     361            SvCUR_set(utf8,0); 
     362        } 
     363        *SvEND(utf8) = '\0'; 
     364    } 
     365 
     366    if (!temp_result) 
     367        shrink_buffer(result); 
     368 
    294369    XSRETURN(1); 
    295370} 
    296