Ticket #1456: string-iter-v4.diff

File string-iter-v4.diff, 71.6 KB (added by nwellnhof, 5 years ago)

Proposed patch

  • include/parrot/encoding.h

    diff --git a/include/parrot/encoding.h b/include/parrot/encoding.h
    index b9a5853..391f454 100644
    a b  
    3737 
    3838typedef void (*encoding_iter_init_t)(PARROT_INTERP, const STRING *src, 
    3939        struct string_iterator_t *); 
     40typedef UINTVAL (*encoding_iter_get_t)( 
     41    PARROT_INTERP, const STRING *str, const String_iter *i, INTVAL  offset); 
     42typedef void    (*encoding_iter_skip_t)( 
     43    PARROT_INTERP, const STRING *str,       String_iter *i, INTVAL  skip); 
     44typedef UINTVAL (*encoding_iter_get_and_advance_t)( 
     45    PARROT_INTERP, const STRING *str,       String_iter *i); 
     46typedef void    (*encoding_iter_set_and_advance_t)( 
     47    PARROT_INTERP,       STRING *str,       String_iter *i, UINTVAL c); 
     48typedef void    (*encoding_iter_set_position_t)( 
     49    PARROT_INTERP, const STRING *str,       String_iter *i, UINTVAL pos); 
    4050 
    4151struct _encoding { 
    4252    ARGIN(const char *name); 
     
    5767    encoding_bytes_t                    bytes; 
    5868    encoding_iter_init_t                iter_init; 
    5969    encoding_find_cclass_t              find_cclass; 
     70    encoding_iter_get_t                 iter_get; 
     71    encoding_iter_skip_t                iter_skip; 
     72    encoding_iter_get_and_advance_t     iter_get_and_advance; 
     73    encoding_iter_set_and_advance_t     iter_set_and_advance; 
     74    encoding_iter_set_position_t        iter_set_position; 
    6075}; 
    6176 
    6277typedef struct _encoding ENCODING; 
  • include/parrot/string.h

    diff --git a/include/parrot/string.h b/include/parrot/string.h
    index fb6a3be..7d87f8e 100644
    a b  
    3737    void (*set_position)(PARROT_INTERP, struct string_iterator_t *i, UINTVAL pos); 
    3838} String_iter; 
    3939 
     40#define STRING_ITER_INIT(i, iter) \ 
     41    (iter)->charpos = (iter)->bytepos = 0 
     42#define STRING_ITER_GET(i, str, iter, offset) \ 
     43    ((str)->encoding)->iter_get((i), (str), (iter), (offset)) 
     44#define STRING_ITER_SKIP(i, str, iter, skip) \ 
     45    ((str)->encoding)->iter_skip((i), (str), (iter), (skip)) 
     46#define STRING_ITER_GET_AND_ADVANCE(i, str, iter) \ 
     47    ((str)->encoding)->iter_get_and_advance((i), (str), (iter)) 
     48#define STRING_ITER_SET_AND_ADVANCE(i, str, iter, c) \ 
     49    ((str)->encoding)->iter_set_and_advance((i), (str), (iter), (c)) 
     50#define STRING_ITER_SET_POSITION(i, str, iter, pos) \ 
     51    ((str)->encoding)->iter_set_position((i), (str), (iter), (pos)) 
     52 
    4053#define STREQ(x, y)  (strcmp((x), (y))==0) 
    4154#define STRNEQ(x, y) (strcmp((x), (y))!=0) 
    4255 
  • include/parrot/string_funcs.h

    diff --git a/include/parrot/string_funcs.h b/include/parrot/string_funcs.h
    index b4bcd34..8087b8f 100644
    a b  
    249249        __attribute__nonnull__(3); 
    250250 
    251251PARROT_EXPORT 
     252PARROT_CANNOT_RETURN_NULL 
     253PARROT_WARN_UNUSED_RESULT 
     254STRING * Parrot_str_iter_substr(PARROT_INTERP, 
     255    ARGMOD(STRING *str), 
     256    ARGIN(const String_iter *l), 
     257    ARGIN(const String_iter *r)) 
     258        __attribute__nonnull__(1) 
     259        __attribute__nonnull__(2) 
     260        __attribute__nonnull__(3) 
     261        __attribute__nonnull__(4) 
     262        FUNC_MODIFIES(*str); 
     263 
     264PARROT_EXPORT 
    252265PARROT_WARN_UNUSED_RESULT 
    253266PARROT_CANNOT_RETURN_NULL 
    254267STRING* Parrot_str_join(PARROT_INTERP, 
     
    626639#define ASSERT_ARGS_Parrot_str_is_cclass __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    627640       PARROT_ASSERT_ARG(interp) \ 
    628641    , PARROT_ASSERT_ARG(s)) 
     642#define ASSERT_ARGS_Parrot_str_iter_substr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     643       PARROT_ASSERT_ARG(interp) \ 
     644    , PARROT_ASSERT_ARG(str) \ 
     645    , PARROT_ASSERT_ARG(l) \ 
     646    , PARROT_ASSERT_ARG(r)) 
    629647#define ASSERT_ARGS_Parrot_str_join __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    630648       PARROT_ASSERT_ARG(interp) \ 
    631649    , PARROT_ASSERT_ARG(ar)) 
  • src/io/utf8.c

    diff --git a/src/io/utf8.c b/src/io/utf8.c
    index 0df3d22..f2b3b5d 100644
    a b  
    5757    s->encoding = Parrot_utf8_encoding_ptr; 
    5858 
    5959    /* count chars, verify utf8 */ 
    60     Parrot_utf8_encoding_ptr->iter_init(interp, s, &iter); 
     60    STRING_ITER_INIT(interp, &iter); 
    6161 
    6262    while (iter.bytepos < s->bufused) { 
    6363        if (iter.bytepos + 4 > s->bufused) { 
     
    9292            } 
    9393        } 
    9494ok: 
    95         iter.get_and_advance(interp, &iter); 
     95        Parrot_utf8_encoding_ptr->iter_get_and_advance(interp, *buf, &iter); 
    9696    } 
    9797    s->strlen = iter.charpos; 
    9898    return len; 
  • src/pmc/stringiterator.pmc

    diff --git a/src/pmc/stringiterator.pmc b/src/pmc/stringiterator.pmc
    index 3e0cefc..aa3086b 100644
    a b  
    2323 
    2424 
    2525pmclass StringIterator auto_attrs extends Iterator { 
    26     ATTR PMC    *string;    /* String to iterate over */ 
    27     ATTR INTVAL  pos;       /* Current position of iterator for forward iterator */ 
    28                             /* Previous position of iterator for reverse iterator */ 
    29     ATTR INTVAL  length;    /* Length of C<string> */ 
    30     ATTR INTVAL  reverse;   /* Direction of iteration. 1 - for reverse iteration */ 
     26    ATTR PMC         *string;    /* String PMC to iterate over */ 
     27    ATTR STRING      *str_val;   /* The actual string */ 
     28    ATTR String_iter  iter;      /* String iterator */ 
     29    ATTR INTVAL       reverse;   /* Direction of iteration. 1 - for reverse iteration */ 
    3130 
    3231/* 
    3332 
     
    3938 
    4039*/ 
    4140    VTABLE void init_pmc(PMC *string) { 
     41        Parrot_StringIterator_attributes * const attrs = 
     42                PARROT_STRINGITERATOR(SELF); 
     43        STRING * const str_val = VTABLE_get_string(INTERP, string); 
     44 
    4245        SET_ATTR_string(INTERP, SELF, string); 
     46        SET_ATTR_str_val(INTERP, SELF, str_val); 
     47        STRING_ITER_INIT(INTERP, &attrs->iter); 
    4348 
    4449        /* by default, iterate from start */ 
    4550        SELF.set_integer_native(ITERATE_FROM_START); 
     
    5863 
    5964    VTABLE void mark() { 
    6065        PMC *string; 
     66        STRING *str_val; 
     67 
    6168        GET_ATTR_string(INTERP, SELF, string); 
    6269        Parrot_gc_mark_PMC_alive(INTERP, string); 
     70        GET_ATTR_str_val(INTERP, SELF, str_val); 
     71        Parrot_gc_mark_STRING_alive(INTERP, str_val); 
    6372    } 
    6473 
    6574/* 
     
    7786        Parrot_StringIterator_attributes * const clone_attrs = 
    7887                PARROT_STRINGITERATOR(clone); 
    7988 
    80         clone_attrs->pos     = attrs->pos; 
     89        /* TODO: this isn't safe if the string PMC has changed */ 
     90        clone_attrs->iter    = attrs->iter; 
    8191        clone_attrs->reverse = attrs->reverse; 
    8292        return clone; 
    8393    } 
     
    110120        Parrot_StringIterator_attributes * const attrs = 
    111121                PARROT_STRINGITERATOR(SELF); 
    112122        if (attrs->reverse) 
    113             return attrs->pos; 
     123            return attrs->iter.charpos; 
    114124        else 
    115             return attrs->length - attrs->pos; 
     125            return attrs->str_val->strlen - attrs->iter.charpos; 
    116126    } 
    117127 
    118128    VTABLE INTVAL get_integer() { 
     
    137147                PARROT_STRINGITERATOR(SELF); 
    138148        if (value == ITERATE_FROM_START) { 
    139149            attrs->reverse   = 0; 
    140             attrs->pos       = 0; 
    141             attrs->length    = VTABLE_elements(INTERP, attrs->string); 
     150            STRING_ITER_SET_POSITION(INTERP, attrs->str_val, &attrs->iter, 0); 
    142151        } 
    143152        else if (value == ITERATE_FROM_END) { 
    144153            attrs->reverse   = 1; 
    145             attrs->pos       = attrs->length 
    146                              = VTABLE_elements(INTERP, attrs->string); 
     154            STRING_ITER_SET_POSITION(INTERP, attrs->str_val, &attrs->iter, attrs->str_val->strlen); 
    147155        } 
    148156        else 
    149157            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, 
     
    179187        Parrot_StringIterator_attributes * const attrs = 
    180188                PARROT_STRINGITERATOR(SELF); 
    181189        PMC *ret; 
     190        STRING *str; 
     191        const String_iter old_iter = attrs->iter; 
    182192 
    183         if (attrs->pos >= attrs->length) 
     193        if (attrs->iter.charpos >= attrs->str_val->strlen) 
    184194            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    185195                "StopIteration"); 
    186196 
    187         ret = pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp, enum_class_String)); 
    188         VTABLE_set_string_native(INTERP, ret, 
    189                 VTABLE_get_string_keyed_int(INTERP, attrs->string, attrs->pos++)); 
     197        ret = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_String)); 
     198        STRING_ITER_SKIP(INTERP, attrs->str_val, &attrs->iter, 1); 
     199        str = Parrot_str_iter_substr(INTERP, attrs->str_val, &old_iter, &attrs->iter); 
     200        VTABLE_set_string_native(INTERP, ret, str); 
    190201        return ret; 
    191202    } 
    192203 
     
    202213    VTABLE STRING *shift_string() { 
    203214        Parrot_StringIterator_attributes * const attrs = 
    204215                PARROT_STRINGITERATOR(SELF); 
     216        const String_iter old_iter = attrs->iter; 
    205217 
    206         if (attrs->pos >= attrs->length) 
     218        if (attrs->iter.charpos >= attrs->str_val->strlen) 
    207219            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    208220                "StopIteration"); 
    209221 
    210         return VTABLE_get_string_keyed_int(INTERP, attrs->string, attrs->pos++); 
     222        STRING_ITER_SKIP(INTERP, attrs->str_val, &attrs->iter, 1); 
     223        return Parrot_str_iter_substr(INTERP, attrs->str_val, &old_iter, &attrs->iter); 
    211224    } 
    212225 
    213226/* 
     
    223236        Parrot_StringIterator_attributes * const attrs = 
    224237                PARROT_STRINGITERATOR(SELF); 
    225238 
    226         if (attrs->pos >= attrs->length) 
     239        if (attrs->iter.charpos >= attrs->str_val->strlen) 
    227240            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    228241                "StopIteration"); 
    229242 
    230         return VTABLE_get_integer_keyed_int(INTERP, attrs->string, attrs->pos++); 
     243        return STRING_ITER_GET_AND_ADVANCE(INTERP, attrs->str_val, &attrs->iter); 
    231244    } 
    232245 
    233246/* 
     
    243256        Parrot_StringIterator_attributes * const attrs = 
    244257                PARROT_STRINGITERATOR(SELF); 
    245258        PMC *ret; 
     259        STRING * str; 
     260        const String_iter old_iter = attrs->iter; 
    246261 
    247         if (!STATICSELF.get_bool()) 
     262        if (attrs->iter.charpos <= 0) 
    248263            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    249264                "StopIteration"); 
    250265 
    251         ret = pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp, enum_class_String)); 
    252         VTABLE_set_string_native(INTERP, ret, 
    253                 VTABLE_get_string_keyed_int(INTERP, attrs->string, --attrs->pos)); 
     266        ret = pmc_new(INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_String)); 
     267        STRING_ITER_SKIP(INTERP, attrs->str_val, &attrs->iter, -1); 
     268        str = Parrot_str_iter_substr(INTERP, attrs->str_val, &attrs->iter, &old_iter); 
     269        VTABLE_set_string_native(INTERP, ret, str); 
    254270        return ret; 
    255271    } 
    256272 
     
    266282    VTABLE STRING *pop_string() { 
    267283        Parrot_StringIterator_attributes * const attrs = 
    268284                PARROT_STRINGITERATOR(SELF); 
     285        const String_iter old_iter = attrs->iter; 
    269286 
    270         if (!STATICSELF.get_bool()) 
     287        if (attrs->iter.charpos <= 0) 
    271288            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    272289                "StopIteration"); 
    273290 
    274         return VTABLE_get_string_keyed_int(INTERP, attrs->string, --attrs->pos); 
     291        STRING_ITER_SKIP(INTERP, attrs->str_val, &attrs->iter, -1); 
     292        return Parrot_str_iter_substr(INTERP, attrs->str_val, &attrs->iter, &old_iter); 
    275293    } 
    276294 
    277295/* 
     
    287305        Parrot_StringIterator_attributes * const attrs = 
    288306                PARROT_STRINGITERATOR(SELF); 
    289307 
    290         if (!STATICSELF.get_bool()) 
     308        if (attrs->iter.charpos <= 0) 
    291309            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    292310                "StopIteration"); 
    293311 
    294         return VTABLE_get_integer_keyed_int(INTERP, attrs->string, --attrs->pos); 
     312        STRING_ITER_SKIP(INTERP, attrs->str_val, &attrs->iter, -1); 
     313        return STRING_ITER_GET(INTERP, attrs->str_val, &attrs->iter, 0); 
    295314    } 
    296315 
    297316/* 
     
    305324*/ 
    306325 
    307326    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) { 
    308         return VTABLE_get_integer_keyed_int(INTERP, STATICSELF.get_pmc(), 
    309                 PARROT_STRINGITERATOR(SELF)->pos + idx); 
     327        Parrot_StringIterator_attributes * const attrs = 
     328                PARROT_STRINGITERATOR(SELF); 
     329        const UINTVAL offset = attrs->iter.charpos + idx; 
     330 
     331        if (offset >= attrs->str_val->strlen) 
     332            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
     333                "StopIteration"); 
     334 
     335        return STRING_ITER_GET(INTERP, attrs->str_val, &attrs->iter, idx); 
    310336    } 
    311337 
    312338/* 
     
    320346*/ 
    321347 
    322348    VTABLE STRING *get_string_keyed_int(INTVAL idx) { 
    323         return VTABLE_get_string_keyed_int(INTERP, STATICSELF.get_pmc(), 
    324                 PARROT_STRINGITERATOR(SELF)->pos + idx); 
     349        Parrot_StringIterator_attributes * const attrs = 
     350                PARROT_STRINGITERATOR(SELF); 
     351        const UINTVAL offset = attrs->iter.charpos + idx; 
     352        String_iter iter, next_iter; 
     353 
     354        if (offset >= attrs->str_val->strlen) 
     355            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
     356                "StopIteration"); 
     357 
     358        iter = attrs->iter; 
     359        if (idx != 0) 
     360            STRING_ITER_SKIP(INTERP, attrs->str_val, &iter, idx); 
     361        next_iter = iter; 
     362        STRING_ITER_SKIP(INTERP, attrs->str_val, &next_iter, 1); 
     363 
     364        return Parrot_str_iter_substr(INTERP, attrs->str_val, &iter, &next_iter); 
    325365    } 
    326366} 
    327367 
  • src/string/api.c

    diff --git a/src/string/api.c b/src/string/api.c
    index 3c4e618..042beda 100644
    a b  
    12701270    } 
    12711271} 
    12721272 
     1273/* 
     1274 
     1275=item C<STRING * Parrot_str_iter_substr(PARROT_INTERP, STRING *str, const 
     1276String_iter *l, const String_iter *r)> 
     1277 
     1278Returns the substring between iterators C<l> and C<r>. 
     1279 
     1280=cut 
     1281 
     1282*/ 
     1283 
     1284PARROT_EXPORT 
     1285PARROT_CANNOT_RETURN_NULL 
     1286PARROT_WARN_UNUSED_RESULT 
     1287STRING * 
     1288Parrot_str_iter_substr(PARROT_INTERP, 
     1289    ARGMOD(STRING *str), 
     1290    ARGIN(const String_iter *l), ARGIN(const String_iter *r)) 
     1291{ 
     1292    ASSERT_ARGS(Parrot_str_iter_substr) 
     1293    STRING *dest = Parrot_str_new_COW(interp, str); 
     1294 
     1295    dest->strstart = (char *)dest->strstart + l->bytepos; 
     1296    dest->bufused  = r->bytepos - l->bytepos; 
     1297    dest->strlen   = r->charpos - l->charpos; 
     1298    dest->hashval  = 0; 
     1299 
     1300    return dest; 
     1301} 
     1302 
    12731303 
    12741304/* 
    12751305 
     
    13641394    } 
    13651395 
    13661396    /* get byte position of the part that will be replaced */ 
    1367     ENCODING_ITER_INIT(interp, src, &iter); 
     1397    STRING_ITER_INIT(interp, &iter); 
    13681398 
    1369     iter.set_position(interp, &iter, true_offset); 
     1399    STRING_ITER_SET_POSITION(interp, src, &iter, true_offset); 
    13701400    start_byte = iter.bytepos; 
    13711401 
    1372     iter.set_position(interp, &iter, true_offset + true_length); 
     1402    STRING_ITER_SET_POSITION(interp, src, &iter, true_offset + true_length); 
    13731403    end_byte   = iter.bytepos; 
    13741404 
    13751405    /* not possible.... */ 
     
    14671497Parrot_str_chopn_inplace(PARROT_INTERP, ARGMOD(STRING *s), INTVAL n) 
    14681498{ 
    14691499    ASSERT_ARGS(Parrot_str_chopn_inplace) 
    1470     UINTVAL new_length, uchar_size; 
     1500    UINTVAL new_length; 
    14711501 
    14721502    if (n < 0) { 
    14731503        new_length = -n; 
     
    14881518        return; 
    14891519    } 
    14901520 
    1491     uchar_size = s->bufused / s->strlen; 
    1492     s->strlen  = new_length; 
    1493  
    14941521    if (s->encoding == Parrot_fixed_8_encoding_ptr) { 
    14951522        s->bufused = new_length; 
    14961523    } 
    14971524    else if (s->encoding == Parrot_ucs2_encoding_ptr) { 
     1525        const UINTVAL uchar_size = s->bufused / s->strlen; 
    14981526        s->bufused = new_length * uchar_size; 
    14991527    } 
    15001528    else { 
    15011529        String_iter iter; 
    15021530 
    1503         ENCODING_ITER_INIT(interp, s, &iter); 
    1504         iter.set_position(interp, &iter, new_length); 
     1531        STRING_ITER_INIT(interp, &iter); 
     1532        STRING_ITER_SET_POSITION(interp, s, &iter, new_length); 
    15051533        s->bufused = iter.bytepos; 
    15061534    } 
    15071535 
     1536    s->strlen  = new_length; 
     1537 
    15081538    return; 
    15091539} 
    15101540 
     
    21402170        int                 sign      = 1; 
    21412171        INTVAL              i         = 0; 
    21422172        String_iter         iter; 
    2143         UINTVAL             offs; 
    21442173        number_parse_state  state = parse_start; 
    21452174 
    2146         ENCODING_ITER_INIT(interp, s, &iter); 
     2175        STRING_ITER_INIT(interp, &iter); 
    21472176 
    2148         for (offs = 0; (state != parse_end) && (offs < s->strlen); ++offs) { 
    2149             const UINTVAL c = iter.get_and_advance(interp, &iter); 
     2177        while (state != parse_end && iter.charpos < s->strlen) { 
     2178            const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, s, &iter); 
    21502179            /* Check for overflow */ 
    21512180            if (c > 255) 
    21522181                break; 
     
    22312260    int           d_length  = 0; 
    22322261    int           check_nan = 0;    /* Check for NaN and Inf after main loop */ 
    22332262    String_iter iter; 
    2234     UINTVAL     offs; 
    22352263    number_parse_state state = parse_start; 
    22362264 
    22372265    if (!s) 
    22382266        return 0.0; 
    22392267 
    2240     ENCODING_ITER_INIT(interp, s, &iter); 
     2268    STRING_ITER_INIT(interp, &iter); 
    22412269 
    22422270    /* Handcrafter FSM to read float value */ 
    2243     for (offs = 0; (state != parse_end) && (offs < s->strlen); ++offs) { 
    2244         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     2271    while (state != parse_end && iter.charpos < s->strlen) { 
     2272        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, s, &iter); 
    22452273        /* Check for overflow */ 
    22462274        if (c > 255) 
    22472275            break; 
     
    26162644{ 
    26172645    ASSERT_ARGS(Parrot_str_to_hashval) 
    26182646    String_iter iter; 
    2619     UINTVAL     offs; 
    26202647    size_t      hashval = interp->hash_seed; 
    26212648 
    26222649    if (!s) 
     
    26252652    /* ZZZZZ workaround for something not setting up encodings right */ 
    26262653    saneify_string(s); 
    26272654 
    2628     ENCODING_ITER_INIT(interp, s, &iter); 
     2655    STRING_ITER_INIT(interp, &iter); 
    26292656 
    2630     for (offs = 0; offs < s->strlen; ++offs) { 
    2631         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     2657    while (iter.charpos < s->strlen) { 
     2658        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, s, &iter); 
    26322659        hashval += hashval << 5; 
    26332660        hashval += c; 
    26342661    } 
     
    27062733            Parrot_fixed_8_encoding_ptr, Parrot_ascii_charset_ptr, 0); 
    27072734 
    27082735    /* more work TODO */ 
    2709     ENCODING_ITER_INIT(interp, src, &iter); 
     2736    STRING_ITER_INIT(interp, &iter); 
    27102737    dp = (unsigned char *)result->strstart; 
    27112738 
    27122739    for (i = 0; len > 0; --len) { 
    2713         UINTVAL c = iter.get_and_advance(interp, &iter); 
     2740        UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    27142741        if (c < 0x7f) { 
    27152742            /* process ASCII chars */ 
    27162743            if (i >= charlen - 2) { 
     
    28672894        encoding = result->encoding; 
    28682895    } 
    28692896 
    2870     encoding->iter_init(interp, result, &iter); 
     2897    STRING_ITER_INIT(interp, &iter); 
    28712898 
    28722899    for (offs = d = 0; offs < clength; ++offs) { 
    28732900        r = (Parrot_UInt4)((unsigned char *)result->strstart)[offs]; 
     
    28902917        } 
    28912918 
    28922919        PARROT_ASSERT(d < offs); 
    2893         iter.set_and_advance(interp, &iter, r); 
     2920        encoding->iter_set_and_advance(interp, result, &iter, r); 
    28942921        ++d; 
    28952922    } 
    28962923 
     
    34253452    ARGIN_NULLOK(STRING *delim), ARGIN_NULLOK(STRING *str)) 
    34263453{ 
    34273454    ASSERT_ARGS(Parrot_str_split) 
    3428     PMC    *res; 
    3429     INTVAL  slen, dlen, ps, pe; 
     3455    PMC     *res; 
     3456    STRING  *tstr; 
     3457    UINTVAL  slen, dlen, start, len; 
     3458    String_iter iter; 
    34303459 
    34313460    if (STRING_IS_NULL(delim) || STRING_IS_NULL(str)) 
    34323461        return PMCNULL; 
     
    34373466    if (!slen) 
    34383467        return res; 
    34393468 
     3469    STRING_ITER_INIT(interp, &iter); 
    34403470    dlen = Parrot_str_byte_length(interp, delim); 
    34413471 
    34423472    if (dlen == 0) { 
    3443         int i; 
    34443473        VTABLE_set_integer_native(interp, res, slen); 
    34453474 
    3446         for (i = 0; i < slen; ++i) { 
    3447             STRING * const p = Parrot_str_substr(interp, str, i, 1, NULL, 0); 
    3448             VTABLE_set_string_keyed_int(interp, res, i, p); 
    3449         } 
     3475        do { 
     3476            const String_iter old_iter = iter; 
    34503477 
    3451         return res; 
    3452     } 
     3478            STRING_ITER_SKIP(interp, str, &iter, 1); 
     3479            tstr = Parrot_str_iter_substr(interp, str, &old_iter, &iter); 
     3480            VTABLE_set_string_keyed_int(interp, res, old_iter.charpos, tstr); 
     3481        } while (iter.charpos < slen); 
    34533482 
    3454     pe = Parrot_str_find_index(interp, str, delim, 0); 
    3455  
    3456     if (pe < 0) { 
    3457         VTABLE_push_string(interp, res, str); 
    34583483        return res; 
    34593484    } 
    34603485 
    3461     ps = 0; 
    3462  
    3463     while (ps <= slen) { 
    3464         const int      pl   = pe - ps; 
    3465         STRING * const tstr = Parrot_str_substr(interp, str, ps, pl, NULL, 0); 
     3486    start = iter.bytepos; 
     3487    len   = 0; 
    34663488 
    3467         VTABLE_push_string(interp, res, tstr); 
    3468         ps = pe + Parrot_str_byte_length(interp, delim); 
    3469  
    3470         if (ps > slen) 
    3471             break; 
     3489    do { 
     3490        UINTVAL end = start; 
     3491        String_iter delim_iter; 
     3492 
     3493        STRING_ITER_INIT(interp, &delim_iter); 
     3494 
     3495        while (delim_iter.charpos < dlen && iter.charpos < slen) { 
     3496            const UINTVAL c1 = STRING_ITER_GET_AND_ADVANCE(interp, str, &iter); 
     3497            const UINTVAL c2 = STRING_ITER_GET_AND_ADVANCE(interp, delim, &delim_iter); 
     3498            if (c1 != c2) { 
     3499                len += delim_iter.charpos; 
     3500                end = iter.bytepos; 
     3501                STRING_ITER_INIT(interp, &delim_iter); 
     3502            } 
     3503        } 
    34723504 
    3473         pe = Parrot_str_find_index(interp, str, delim, ps); 
     3505        if (delim_iter.charpos >= dlen) { 
     3506            tstr = Parrot_str_new_COW(interp, str); 
     3507            tstr->strstart = (char *)tstr->strstart + start; 
     3508            tstr->bufused  = end - start; 
     3509            tstr->strlen   = len; 
     3510            tstr->hashval  = 0; 
     3511            VTABLE_push_string(interp, res, tstr); 
    34743512 
    3475         if (pe < 0) 
    3476             pe = slen; 
    3477     } 
     3513            start = iter.bytepos; 
     3514            len   = 0; 
     3515        } 
     3516        else { 
     3517            len += delim_iter.charpos; 
     3518        } 
     3519    } while (iter.charpos < slen); 
     3520 
     3521    tstr = Parrot_str_new_COW(interp, str); 
     3522    tstr->strstart = (char *)tstr->strstart + start; 
     3523    tstr->bufused  = iter.bytepos - start; 
     3524    tstr->strlen   = len; 
     3525    tstr->hashval  = 0; 
     3526    VTABLE_push_string(interp, res, tstr); 
    34783527 
    34793528    return res; 
    34803529} 
  • src/string/charset/ascii.c

    diff --git a/src/string/charset/ascii.c b/src/string/charset/ascii.c
    index 6618096..90d1eab 100644
    a b  
    263263{ 
    264264    ASSERT_ARGS(to_ascii) 
    265265    String_iter iter; 
    266     UINTVAL offs; 
    267266    unsigned char *p; 
    268267    const UINTVAL len = src->strlen; 
    269268 
     
    275274        dest = src; 
    276275    } 
    277276    p = (unsigned char *)dest->strstart; 
    278     ENCODING_ITER_INIT(interp, src, &iter); 
    279     for (offs = 0; offs < len; ++offs) { 
    280         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     277    STRING_ITER_INIT(interp, &iter); 
     278    while (iter.charpos < len) { 
     279        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    281280        if (c >= 128) 
    282281            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LOSSY_CONVERSION, 
    283282                    "can't convert unicode string to ascii"); 
     
    557556            return ret_val < 0 ? -1 : 1; 
    558557    } 
    559558    else { 
    560         UINTVAL offs; 
    561         ENCODING_ITER_INIT(interp, rhs, &iter); 
    562         for (offs = 0; offs < min_len; ++offs) { 
    563             const UINTVAL cl = ENCODING_GET_BYTE(interp, lhs, offs); 
    564             const UINTVAL cr = iter.get_and_advance(interp, &iter); 
     559        STRING_ITER_INIT(interp, &iter); 
     560        while (iter.charpos < min_len) { 
     561            const UINTVAL cl = ENCODING_GET_BYTE(interp, lhs, iter.charpos); 
     562            const UINTVAL cr = STRING_ITER_GET_AND_ADVANCE(interp, rhs, &iter); 
    565563            if (cl != cr) 
    566564                return cl < cr ? -1 : 1; 
    567565        } 
     
    596594{ 
    597595    ASSERT_ARGS(mixed_cs_index) 
    598596    String_iter src_iter, search_iter; 
    599     UINTVAL len; 
    600     INTVAL start; 
    601  
    602     ENCODING_ITER_INIT(interp, src, &src_iter); 
    603     src_iter.set_position(interp, &src_iter, offs); 
    604     ENCODING_ITER_INIT(interp, search, &search_iter); 
    605     len = search->strlen; 
    606  
    607     start = -1; 
    608     for (; len && offs < src->strlen; ++offs) { 
    609         const UINTVAL c1 = src_iter.get_and_advance(interp, &src_iter); 
    610         const UINTVAL c2 = search_iter.get_and_advance(interp, &search_iter); 
    611         if (c1 == c2) { 
    612             --len; 
    613             if (start == -1) 
    614                 start = offs; 
    615         } 
    616         else { 
    617             len = search->strlen; 
    618             start = -1; 
    619             search_iter.set_position(interp, &search_iter, 0); 
     597    const UINTVAL len = search->strlen; 
     598    UINTVAL start; 
     599 
     600    STRING_ITER_INIT(interp, &src_iter); 
     601    STRING_ITER_SET_POSITION(interp, src, &src_iter, offs); 
     602    STRING_ITER_INIT(interp, &search_iter); 
     603 
     604    start = src_iter.charpos; 
     605    while (search_iter.charpos < len && src_iter.charpos < src->strlen) { 
     606        const UINTVAL c1 = STRING_ITER_GET_AND_ADVANCE(interp, src, &src_iter); 
     607        const UINTVAL c2 = STRING_ITER_GET_AND_ADVANCE(interp, search, &search_iter); 
     608        if (c1 != c2) { 
     609            start = src_iter.charpos; 
     610            STRING_ITER_INIT(interp, &search_iter); 
    620611        } 
    621612    } 
    622     if (len == 0) 
     613    if (search_iter.charpos >= len) 
    623614        return start; 
    624615    return -1; 
    625616} 
     
    700691validate(PARROT_INTERP, ARGIN(STRING *src)) 
    701692{ 
    702693    ASSERT_ARGS(validate) 
    703     UINTVAL offset; 
     694    const UINTVAL len = Parrot_str_byte_length(interp, src); 
    704695    String_iter iter; 
    705696 
    706     ENCODING_ITER_INIT(interp, src, &iter); 
    707     for (offset = 0; offset < Parrot_str_byte_length(interp, src); ++offset) { 
    708         const UINTVAL codepoint = iter.get_and_advance(interp, &iter); 
     697    STRING_ITER_INIT(interp, &iter); 
     698    while (iter.charpos < len) { 
     699        const UINTVAL codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    709700        if (codepoint >= 0x80) 
    710701            return 0; 
    711702    } 
  • src/string/charset/iso-8859-1.c

    diff --git a/src/string/charset/iso-8859-1.c b/src/string/charset/iso-8859-1.c
    index b88c11d..65c663a 100644
    a b  
    215215to_iso_8859_1(PARROT_INTERP, ARGIN(STRING *src), ARGMOD_NULLOK(STRING *dest)) 
    216216{ 
    217217    ASSERT_ARGS(to_iso_8859_1) 
    218     UINTVAL offs, src_len; 
     218    UINTVAL src_len; 
    219219    String_iter iter; 
    220220 
    221     ENCODING_ITER_INIT(interp, src, &iter); 
     221    STRING_ITER_INIT(interp, &iter); 
    222222    src_len = src->strlen; 
    223223    if (dest) { 
    224224        Parrot_gc_reallocate_string_storage(interp, dest, src_len); 
     
    229229        dest = src; 
    230230    } 
    231231    dest->bufused = src_len; 
    232     dest->charset = Parrot_iso_8859_1_charset_ptr; 
    233     dest->encoding = Parrot_fixed_8_encoding_ptr; 
    234     for (offs = 0; offs < src_len; ++offs) { 
    235         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     232    while (iter.charpos < src_len) { 
     233        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    236234        if (c >= 0x100) 
    237235            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LOSSY_CONVERSION, 
    238236                "lossy conversion to iso-8559-1"); 
    239237 
    240         ENCODING_SET_BYTE(interp, dest, offs, c); 
     238        Parrot_fixed_8_encoding_ptr->set_byte(interp, dest, iter.charpos - 1, c); 
    241239    } 
     240    dest->charset = Parrot_iso_8859_1_charset_ptr; 
     241    dest->encoding = Parrot_fixed_8_encoding_ptr; 
    242242    return dest; 
    243243} 
    244244 
     
    258258{ 
    259259    ASSERT_ARGS(to_unicode) 
    260260    if (dest) { 
    261         UINTVAL offs; 
    262261        String_iter iter; 
    263262 
    264263        dest->charset = Parrot_unicode_charset_ptr; 
    265264        dest->encoding = CHARSET_GET_PREFERRED_ENCODING(interp, dest); 
    266265        Parrot_gc_reallocate_string_storage(interp, dest, src->strlen); 
    267         ENCODING_ITER_INIT(interp, dest, &iter); 
    268         for (offs = 0; offs < src->strlen; ++offs) { 
    269             const UINTVAL c = ENCODING_GET_BYTE(interp, src, offs); 
     266        STRING_ITER_INIT(interp, &iter); 
     267        while (iter.charpos < src->strlen) { 
     268            const UINTVAL c = ENCODING_GET_BYTE(interp, src, iter.charpos); 
    270269 
    271270            if (iter.bytepos >= Buffer_buflen(dest) - 4) { 
    272                 UINTVAL need = (UINTVAL)((src->strlen - offs) * 1.5); 
     271                UINTVAL need = (UINTVAL)((src->strlen - iter.charpos) * 1.5); 
    273272                if (need < 16) 
    274273                    need = 16; 
    275274                Parrot_gc_reallocate_string_storage(interp, dest, 
    276275                        Buffer_buflen(dest) + need); 
    277276            } 
    278             iter.set_and_advance(interp, &iter, c); 
     277            STRING_ITER_SET_AND_ADVANCE(interp, dest, &iter, c); 
    279278        } 
    280279        dest->bufused = iter.bytepos; 
    281280        dest->strlen  = iter.charpos; 
  • src/string/charset/unicode.c

    diff --git a/src/string/charset/unicode.c b/src/string/charset/unicode.c
    index 77b0893..98f6e84 100644
    a b  
    704704{ 
    705705    ASSERT_ARGS(compare) 
    706706    String_iter l_iter, r_iter; 
    707     UINTVAL offs, cl, cr, min_len, l_len, r_len; 
     707    UINTVAL min_len, l_len, r_len; 
    708708 
    709709    /* TODO make optimized equal - strings are equal length then already */ 
    710     ENCODING_ITER_INIT(interp, lhs, &l_iter); 
    711     ENCODING_ITER_INIT(interp, rhs, &r_iter); 
     710    STRING_ITER_INIT(interp, &l_iter); 
     711    STRING_ITER_INIT(interp, &r_iter); 
    712712 
    713713    l_len = lhs->strlen; 
    714714    r_len = rhs->strlen; 
    715715 
    716716    min_len = l_len > r_len ? r_len : l_len; 
    717717 
    718     for (offs = 0; offs < min_len; ++offs) { 
    719         cl = l_iter.get_and_advance(interp, &l_iter); 
    720         cr = r_iter.get_and_advance(interp, &r_iter); 
     718    while (l_iter.charpos < min_len) { 
     719        UINTVAL cl = STRING_ITER_GET_AND_ADVANCE(interp, lhs, &l_iter); 
     720        UINTVAL cr = STRING_ITER_GET_AND_ADVANCE(interp, rhs, &r_iter); 
    721721 
    722722        if (cl != cr) 
    723723            return cl < cr ? -1 : 1; 
     
    769769validate(PARROT_INTERP, ARGIN(STRING *src)) 
    770770{ 
    771771    ASSERT_ARGS(validate) 
    772     UINTVAL     offset; 
     772    UINTVAL len = Parrot_str_byte_length(interp, src); 
    773773    String_iter iter; 
    774774 
    775     ENCODING_ITER_INIT(interp, src, &iter); 
    776     for (offset = 0; offset < Parrot_str_byte_length(interp, src); ++offset) { 
    777         const UINTVAL codepoint = iter.get_and_advance(interp, &iter); 
     775    STRING_ITER_INIT(interp, &iter); 
     776    while (iter.charpos < len) { 
     777        const UINTVAL codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    778778        /* Check for Unicode non-characters */ 
    779779        if (codepoint >= 0xfdd0 
    780780        && (codepoint <= 0xfdef || (codepoint & 0xfffe) == 0xfffe) 
     
    924924    ASSERT_ARGS(find_cclass) 
    925925    String_iter iter; 
    926926    UINTVAL     codepoint; 
    927     UINTVAL     pos = offset; 
    928927    UINTVAL     end = offset + count; 
    929928 
    930     ENCODING_ITER_INIT(interp, source_string, &iter); 
    931  
    932     iter.set_position(interp, &iter, pos); 
     929    STRING_ITER_INIT(interp, &iter); 
     930    STRING_ITER_SET_POSITION(interp, source_string, &iter, offset); 
    933931 
    934932    end = source_string->strlen < end ? source_string->strlen : end; 
    935933 
    936     for (; pos < end; ++pos) { 
    937         codepoint = iter.get_and_advance(interp, &iter); 
     934    while (iter.charpos < end) { 
     935        codepoint = STRING_ITER_GET_AND_ADVANCE(interp, source_string, &iter); 
    938936        if (codepoint >= 256) { 
    939937            if (u_iscclass(interp, codepoint, flags)) 
    940                     return pos; 
     938                    return iter.charpos - 1; 
    941939        } 
    942940        else { 
    943941            if (Parrot_iso_8859_1_typetable[codepoint] & flags) 
    944                 return pos; 
     942                return iter.charpos - 1; 
    945943        } 
    946944    } 
    947945 
     
    965963    ASSERT_ARGS(find_not_cclass) 
    966964    String_iter iter; 
    967965    UINTVAL     codepoint; 
    968     UINTVAL     pos = offset; 
    969966    UINTVAL     end = offset + count; 
    970967    int         bit; 
    971968 
    972     if (pos > source_string->strlen) { 
     969    if (offset > source_string->strlen) { 
    973970        /* XXX: Throw in this case? */ 
    974971        return offset + count; 
    975972    } 
    976973 
    977     ENCODING_ITER_INIT(interp, source_string, &iter); 
     974    STRING_ITER_INIT(interp, &iter); 
    978975 
    979     if (pos) 
    980         iter.set_position(interp, &iter, pos); 
     976    if (offset) 
     977        STRING_ITER_SET_POSITION(interp, source_string, &iter, offset); 
    981978 
    982979    end = source_string->strlen < end ? source_string->strlen : end; 
    983980 
    984981    if (flags == enum_cclass_any) 
    985982        return end; 
    986983 
    987     for (; pos < end; ++pos) { 
    988         codepoint = iter.get_and_advance(interp, &iter); 
     984    while (iter.charpos < end) { 
     985        codepoint = STRING_ITER_GET_AND_ADVANCE(interp, source_string, &iter); 
    989986        if (codepoint >= 256) { 
    990987            for (bit = enum_cclass_uppercase; 
    991988                    bit <= enum_cclass_word ; bit <<= 1) { 
    992989                if ((bit & flags) && !u_iscclass(interp, codepoint, bit)) 
    993                     return pos; 
     990                    return iter.charpos - 1; 
    994991            } 
    995992        } 
    996993        else { 
    997994            if (!(Parrot_iso_8859_1_typetable[codepoint] & flags)) 
    998                 return pos; 
     995                return iter.charpos - 1; 
    999996        } 
    1000997    } 
    1001998 
     
    10231020 
    10241021    dest->strlen = 1; 
    10251022 
    1026     ENCODING_ITER_INIT(interp, dest, &iter); 
    1027     iter.set_and_advance(interp, &iter, codepoint); 
     1023    STRING_ITER_INIT(interp, &iter); 
     1024    STRING_ITER_SET_AND_ADVANCE(interp, dest, &iter, codepoint); 
    10281025    dest->bufused = iter.bytepos; 
    10291026 
    10301027    return dest; 
     
    10471044{ 
    10481045    ASSERT_ARGS(compute_hash) 
    10491046    String_iter iter; 
    1050     UINTVAL     offs; 
    10511047    size_t      hashval = seed; 
    10521048 
    1053     ENCODING_ITER_INIT(interp, src, &iter); 
     1049    STRING_ITER_INIT(interp, &iter); 
    10541050 
    1055     for (offs = 0; offs < src->strlen; ++offs) { 
    1056         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     1051    while (iter.charpos < src->strlen) { 
     1052        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    10571053        hashval += hashval << 5; 
    10581054        hashval += c; 
    10591055    } 
  • src/string/encoding/fixed_8.c

    diff --git a/src/string/encoding/fixed_8.c b/src/string/encoding/fixed_8.c
    index dd41129..712479d 100644
    a b  
    5050        __attribute__nonnull__(2) 
    5151        FUNC_MODIFIES(*iter); 
    5252 
     53static UINTVAL fixed8_iter_get(PARROT_INTERP, 
     54    ARGIN(const STRING *str), 
     55    ARGIN(const String_iter *iter), 
     56    INTVAL offset) 
     57        __attribute__nonnull__(1) 
     58        __attribute__nonnull__(2) 
     59        __attribute__nonnull__(3); 
     60 
     61static UINTVAL fixed8_iter_get_and_advance(PARROT_INTERP, 
     62    ARGIN(const STRING *str), 
     63    ARGMOD(String_iter *iter)) 
     64        __attribute__nonnull__(1) 
     65        __attribute__nonnull__(2) 
     66        __attribute__nonnull__(3) 
     67        FUNC_MODIFIES(*iter); 
     68 
     69static void fixed8_iter_set_and_advance(PARROT_INTERP, 
     70    ARGMOD(STRING *str), 
     71    ARGMOD(String_iter *iter), 
     72    UINTVAL c) 
     73        __attribute__nonnull__(1) 
     74        __attribute__nonnull__(2) 
     75        __attribute__nonnull__(3) 
     76        FUNC_MODIFIES(*str) 
     77        FUNC_MODIFIES(*iter); 
     78 
     79static void fixed8_iter_set_position(SHIM_INTERP, 
     80    ARGIN(const STRING *str), 
     81    ARGMOD(String_iter *iter), 
     82    UINTVAL pos) 
     83        __attribute__nonnull__(2) 
     84        __attribute__nonnull__(3) 
     85        FUNC_MODIFIES(*iter); 
     86 
     87static void fixed8_iter_skip(SHIM_INTERP, 
     88    ARGIN(const STRING *str), 
     89    ARGMOD(String_iter *iter), 
     90    INTVAL skip) 
     91        __attribute__nonnull__(2) 
     92        __attribute__nonnull__(3) 
     93        FUNC_MODIFIES(*iter); 
     94 
    5395static void fixed8_set_next(PARROT_INTERP, 
    5496    ARGMOD(String_iter *iter), 
    5597    UINTVAL c) 
     
    181223#define ASSERT_ARGS_fixed8_get_next __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    182224       PARROT_ASSERT_ARG(interp) \ 
    183225    , PARROT_ASSERT_ARG(iter)) 
     226#define ASSERT_ARGS_fixed8_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     227       PARROT_ASSERT_ARG(interp) \ 
     228    , PARROT_ASSERT_ARG(str) \ 
     229    , PARROT_ASSERT_ARG(iter)) 
     230#define ASSERT_ARGS_fixed8_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     231       PARROT_ASSERT_ARG(interp) \ 
     232    , PARROT_ASSERT_ARG(str) \ 
     233    , PARROT_ASSERT_ARG(iter)) 
     234#define ASSERT_ARGS_fixed8_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     235       PARROT_ASSERT_ARG(interp) \ 
     236    , PARROT_ASSERT_ARG(str) \ 
     237    , PARROT_ASSERT_ARG(iter)) 
     238#define ASSERT_ARGS_fixed8_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     239       PARROT_ASSERT_ARG(str) \ 
     240    , PARROT_ASSERT_ARG(iter)) 
     241#define ASSERT_ARGS_fixed8_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     242       PARROT_ASSERT_ARG(str) \ 
     243    , PARROT_ASSERT_ARG(iter)) 
    184244#define ASSERT_ARGS_fixed8_set_next __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    185245       PARROT_ASSERT_ARG(interp) \ 
    186246    , PARROT_ASSERT_ARG(iter)) 
     
    581641 
    582642/* 
    583643 
     644=item C<static UINTVAL fixed8_iter_get(PARROT_INTERP, const STRING *str, const 
     645String_iter *iter, INTVAL offset)> 
     646 
     647Get the character at C<iter> plus C<offset>. 
     648 
     649=cut 
     650 
     651*/ 
     652 
     653static UINTVAL 
     654fixed8_iter_get(PARROT_INTERP, 
     655    ARGIN(const STRING *str), ARGIN(const String_iter *iter), INTVAL offset) 
     656{ 
     657    ASSERT_ARGS(fixed8_iter_get) 
     658    return get_byte(interp, str, iter->charpos + offset); 
     659} 
     660 
     661/* 
     662 
     663=item C<static void fixed8_iter_skip(PARROT_INTERP, const STRING *str, 
     664String_iter *iter, INTVAL skip)> 
     665 
     666Moves the string iterator C<i> by C<skip> characters. 
     667 
     668=cut 
     669 
     670*/ 
     671 
     672static void 
     673fixed8_iter_skip(SHIM_INTERP, 
     674    ARGIN(const STRING *str), ARGMOD(String_iter *iter), INTVAL skip) 
     675{ 
     676    ASSERT_ARGS(fixed8_iter_skip) 
     677    iter->bytepos += skip; 
     678    iter->charpos += skip; 
     679    PARROT_ASSERT(iter->bytepos <= Buffer_buflen(str)); 
     680} 
     681 
     682/* 
     683 
     684=item C<static UINTVAL fixed8_iter_get_and_advance(PARROT_INTERP, const STRING 
     685*str, String_iter *iter)> 
     686 
     687Moves the string iterator C<i> to the next codepoint. 
     688 
     689=cut 
     690 
     691*/ 
     692 
     693static UINTVAL 
     694fixed8_iter_get_and_advance(PARROT_INTERP, 
     695    ARGIN(const STRING *str), ARGMOD(String_iter *iter)) 
     696{ 
     697    ASSERT_ARGS(fixed8_iter_get_and_advance) 
     698    const UINTVAL c = get_byte(interp, str, iter->charpos++); 
     699    iter->bytepos++; 
     700    return c; 
     701} 
     702 
     703/* 
     704 
     705=item C<static void fixed8_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     706String_iter *iter, UINTVAL c)> 
     707 
     708With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     709next position in the string. 
     710 
     711=cut 
     712 
     713*/ 
     714 
     715static void 
     716fixed8_iter_set_and_advance(PARROT_INTERP, 
     717    ARGMOD(STRING *str), ARGMOD(String_iter *iter), UINTVAL c) 
     718{ 
     719    ASSERT_ARGS(fixed8_iter_set_and_advance) 
     720    set_byte(interp, str, iter->charpos++, c); 
     721    iter->bytepos++; 
     722} 
     723 
     724/* 
     725 
     726=item C<static void fixed8_iter_set_position(PARROT_INTERP, const STRING *str, 
     727String_iter *iter, UINTVAL pos)> 
     728 
     729Moves the string iterator C<i> to the position C<n> in the string. 
     730 
     731=cut 
     732 
     733*/ 
     734 
     735static void 
     736fixed8_iter_set_position(SHIM_INTERP, 
     737    ARGIN(const STRING *str), ARGMOD(String_iter *iter), UINTVAL pos) 
     738{ 
     739    ASSERT_ARGS(fixed8_iter_set_position) 
     740    iter->bytepos = iter->charpos = pos; 
     741    PARROT_ASSERT(pos <= Buffer_buflen(str)); 
     742} 
     743 
     744/* 
     745 
    584746=item C<static UINTVAL fixed8_get_next(PARROT_INTERP, String_iter *iter)> 
    585747 
    586748Moves the string iterator C<i> to the next codepoint. 
     
    695857        codepoints, 
    696858        bytes, 
    697859        iter_init, 
    698         find_cclass 
     860        find_cclass, 
     861        fixed8_iter_get, 
     862        fixed8_iter_skip, 
     863        fixed8_iter_get_and_advance, 
     864        fixed8_iter_set_and_advance, 
     865        fixed8_iter_set_position 
    699866 
    700867    }; 
    701868    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
  • src/string/encoding/ucs2.c

    diff --git a/src/string/encoding/ucs2.c b/src/string/encoding/ucs2.c
    index 71ef8b1..6a7459c 100644
    a b  
    164164        __attribute__nonnull__(2) 
    165165        FUNC_MODIFIES(*i); 
    166166 
     167static UINTVAL ucs2_iter_get(PARROT_INTERP, 
     168    ARGIN(const STRING *str), 
     169    ARGIN(const String_iter *i), 
     170    INTVAL offset) 
     171        __attribute__nonnull__(1) 
     172        __attribute__nonnull__(2) 
     173        __attribute__nonnull__(3); 
     174 
     175static UINTVAL ucs2_iter_get_and_advance(PARROT_INTERP, 
     176    ARGIN(const STRING *str), 
     177    ARGMOD(String_iter *i)) 
     178        __attribute__nonnull__(1) 
     179        __attribute__nonnull__(2) 
     180        __attribute__nonnull__(3) 
     181        FUNC_MODIFIES(*i); 
     182 
     183static void ucs2_iter_set_and_advance(PARROT_INTERP, 
     184    ARGMOD(STRING *str), 
     185    ARGMOD(String_iter *i), 
     186    UINTVAL c) 
     187        __attribute__nonnull__(1) 
     188        __attribute__nonnull__(2) 
     189        __attribute__nonnull__(3) 
     190        FUNC_MODIFIES(*str) 
     191        FUNC_MODIFIES(*i); 
     192 
     193static void ucs2_iter_set_position(SHIM_INTERP, 
     194    ARGIN(const STRING *str), 
     195    ARGMOD(String_iter *i), 
     196    UINTVAL n) 
     197        __attribute__nonnull__(2) 
     198        __attribute__nonnull__(3) 
     199        FUNC_MODIFIES(*i); 
     200 
     201static void ucs2_iter_skip(SHIM_INTERP, 
     202    ARGIN(const STRING *str), 
     203    ARGMOD(String_iter *i), 
     204    INTVAL skip) 
     205        __attribute__nonnull__(2) 
     206        __attribute__nonnull__(3) 
     207        FUNC_MODIFIES(*i); 
     208 
    167209static void ucs2_set_position(SHIM_INTERP, 
    168210    ARGMOD(String_iter *i), 
    169211    UINTVAL n) 
     
    219261#define ASSERT_ARGS_ucs2_encode_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    220262       PARROT_ASSERT_ARG(interp) \ 
    221263    , PARROT_ASSERT_ARG(i)) 
     264#define ASSERT_ARGS_ucs2_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     265       PARROT_ASSERT_ARG(interp) \ 
     266    , PARROT_ASSERT_ARG(str) \ 
     267    , PARROT_ASSERT_ARG(i)) 
     268#define ASSERT_ARGS_ucs2_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     269       PARROT_ASSERT_ARG(interp) \ 
     270    , PARROT_ASSERT_ARG(str) \ 
     271    , PARROT_ASSERT_ARG(i)) 
     272#define ASSERT_ARGS_ucs2_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     273       PARROT_ASSERT_ARG(interp) \ 
     274    , PARROT_ASSERT_ARG(str) \ 
     275    , PARROT_ASSERT_ARG(i)) 
     276#define ASSERT_ARGS_ucs2_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     277       PARROT_ASSERT_ARG(str) \ 
     278    , PARROT_ASSERT_ARG(i)) 
     279#define ASSERT_ARGS_ucs2_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     280       PARROT_ASSERT_ARG(str) \ 
     281    , PARROT_ASSERT_ARG(i)) 
    222282#define ASSERT_ARGS_ucs2_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    223283       PARROT_ASSERT_ARG(i)) 
    224284/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     
    397457        String_iter iter; 
    398458        UINTVAL start; 
    399459 
    400         iter_init(interp, src, &iter); 
    401         iter.set_position(interp, &iter, offset); 
     460        STRING_ITER_INIT(interp, &iter); 
     461        ucs2_iter_set_position(interp, src, &iter, offset); 
    402462        start = iter.bytepos; 
    403463        return_string->strstart = (char *)return_string->strstart + start; 
    404         iter.set_position(interp, &iter, offset + count); 
     464        ucs2_iter_set_position(interp, src, &iter, offset + count); 
    405465        return_string->bufused = iter.bytepos - start; 
    406466    } 
    407467#endif 
     
    576636 
    577637/* 
    578638 
     639=item C<static UINTVAL ucs2_iter_get(PARROT_INTERP, const STRING *str, const 
     640String_iter *i, INTVAL offset)> 
     641 
     642Get the character at C<i> + C<offset>. 
     643 
     644=cut 
     645 
     646*/ 
     647 
     648static UINTVAL 
     649ucs2_iter_get(PARROT_INTERP, 
     650    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     651{ 
     652    ASSERT_ARGS(ucs2_iter_get) 
     653    return get_codepoint(interp, str, i->charpos + offset); 
     654} 
     655 
     656/* 
     657 
     658=item C<static void ucs2_iter_skip(PARROT_INTERP, const STRING *str, String_iter 
     659*i, INTVAL skip)> 
     660 
     661Moves the string iterator C<i> by C<skip> characters. 
     662 
     663=cut 
     664 
     665*/ 
     666 
     667static void 
     668ucs2_iter_skip(SHIM_INTERP, 
     669    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     670{ 
     671    ASSERT_ARGS(ucs2_iter_skip) 
     672 
     673#if PARROT_HAS_ICU 
     674    i->charpos += skip; 
     675    i->bytepos += skip * sizeof (UChar); 
     676#else 
     677    /* This function must never be called if compiled without ICU. 
     678     * See TT #557 
     679     */ 
     680    PARROT_ASSERT(0); 
     681#endif 
     682} 
     683 
     684/* 
     685 
     686=item C<static UINTVAL ucs2_iter_get_and_advance(PARROT_INTERP, const STRING 
     687*str, String_iter *i)> 
     688 
     689Moves the string iterator C<i> to the next UCS-2 codepoint. 
     690 
     691=cut 
     692 
     693*/ 
     694 
     695static UINTVAL 
     696ucs2_iter_get_and_advance(PARROT_INTERP, 
     697    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     698{ 
     699    ASSERT_ARGS(ucs2_iter_get_and_advance) 
     700 
     701#if PARROT_HAS_ICU 
     702    UChar * const s = (UChar*) str->strstart; 
     703    size_t pos = i->bytepos / sizeof (UChar); 
     704 
     705    /* TODO either make sure that we don't go past end or use SAFE 
     706     *      iter versions 
     707     */ 
     708    const UChar c = s[pos++]; 
     709    i->charpos++; 
     710    i->bytepos = pos * sizeof (UChar); 
     711    return c; 
     712#else 
     713    /* This function must never be called if compiled without ICU. 
     714     * See TT #557 
     715     */ 
     716    PARROT_ASSERT(0); 
     717    return (UINTVAL)0; /* Stop the static analyzers from panicing */ 
     718#endif 
     719} 
     720 
     721/* 
     722 
     723=item C<static void ucs2_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     724String_iter *i, UINTVAL c)> 
     725 
     726With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     727next position in the string. 
     728 
     729=cut 
     730 
     731*/ 
     732 
     733static void 
     734ucs2_iter_set_and_advance(PARROT_INTERP, 
     735    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     736{ 
     737    ASSERT_ARGS(ucs2_iter_set_and_advance) 
     738 
     739#if PARROT_HAS_ICU 
     740    UChar * const s = (UChar*) str->strstart; 
     741    UINTVAL pos = i->bytepos / sizeof (UChar); 
     742    s[pos++] = (UChar)c; 
     743    i->charpos++; 
     744    i->bytepos = pos * sizeof (UChar); 
     745#else 
     746    /* This function must never be called if compiled without ICU. 
     747     * See TT #557 
     748     */ 
     749    PARROT_ASSERT(0); 
     750#endif 
     751} 
     752 
     753/* 
     754 
     755=item C<static void ucs2_iter_set_position(PARROT_INTERP, const STRING *str, 
     756String_iter *i, UINTVAL n)> 
     757 
     758Moves the string iterator C<i> to the position C<n> in the string. 
     759 
     760=cut 
     761 
     762*/ 
     763 
     764static void 
     765ucs2_iter_set_position(SHIM_INTERP, 
     766    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n) 
     767{ 
     768    ASSERT_ARGS(ucs2_iter_set_position) 
     769 
     770#if PARROT_HAS_ICU 
     771    i->charpos = n; 
     772    i->bytepos = n * sizeof (UChar); 
     773#else 
     774    /* This function must never be called if compiled without ICU. 
     775     * See TT #557 
     776     */ 
     777    PARROT_ASSERT(0); 
     778#endif 
     779} 
     780 
     781/* 
     782 
    579783=item C<static UINTVAL ucs2_decode_and_advance(PARROT_INTERP, String_iter *i)> 
    580784 
    581785Moves the string iterator C<i> to the next UCS-2 codepoint. 
     
    729933        codepoints, 
    730934        bytes, 
    731935        iter_init, 
    732         find_cclass 
     936        find_cclass, 
     937        ucs2_iter_get, 
     938        ucs2_iter_skip, 
     939        ucs2_iter_get_and_advance, 
     940        ucs2_iter_set_and_advance, 
     941        ucs2_iter_set_position 
    733942    }; 
    734943    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    735944    Parrot_register_encoding(interp, "ucs2", return_encoding); 
  • src/string/encoding/utf16.c

    diff --git a/src/string/encoding/utf16.c b/src/string/encoding/utf16.c
    index f94e6e8..4d810a7 100644
    a b  
    161161        __attribute__nonnull__(2) 
    162162        FUNC_MODIFIES(*i); 
    163163 
     164static UINTVAL utf16_iter_get(PARROT_INTERP, 
     165    ARGIN(const STRING *str), 
     166    ARGIN(const String_iter *i), 
     167    INTVAL offset) 
     168        __attribute__nonnull__(1) 
     169        __attribute__nonnull__(2) 
     170        __attribute__nonnull__(3); 
     171 
     172PARROT_WARN_UNUSED_RESULT 
     173static UINTVAL utf16_iter_get_and_advance(PARROT_INTERP, 
     174    ARGIN(const STRING *str), 
     175    ARGMOD(String_iter *i)) 
     176        __attribute__nonnull__(1) 
     177        __attribute__nonnull__(2) 
     178        __attribute__nonnull__(3) 
     179        FUNC_MODIFIES(*i); 
     180 
     181static void utf16_iter_set_and_advance(PARROT_INTERP, 
     182    ARGMOD(STRING *str), 
     183    ARGMOD(String_iter *i), 
     184    UINTVAL c) 
     185        __attribute__nonnull__(1) 
     186        __attribute__nonnull__(2) 
     187        __attribute__nonnull__(3) 
     188        FUNC_MODIFIES(*str) 
     189        FUNC_MODIFIES(*i); 
     190 
     191static void utf16_iter_set_position(PARROT_INTERP, 
     192    ARGIN(const STRING *str), 
     193    ARGMOD(String_iter *i), 
     194    UINTVAL n) 
     195        __attribute__nonnull__(1) 
     196        __attribute__nonnull__(2) 
     197        __attribute__nonnull__(3) 
     198        FUNC_MODIFIES(*i); 
     199 
     200static void utf16_iter_skip(PARROT_INTERP, 
     201    ARGIN(const STRING *str), 
     202    ARGMOD(String_iter *i), 
     203    INTVAL skip) 
     204        __attribute__nonnull__(1) 
     205        __attribute__nonnull__(2) 
     206        __attribute__nonnull__(3) 
     207        FUNC_MODIFIES(*i); 
     208 
    164209static void utf16_set_position(PARROT_INTERP, 
    165210    ARGMOD(String_iter *i), 
    166211    UINTVAL n) 
     
    223268#define ASSERT_ARGS_utf16_encode_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    224269       PARROT_ASSERT_ARG(interp) \ 
    225270    , PARROT_ASSERT_ARG(i)) 
     271#define ASSERT_ARGS_utf16_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     272       PARROT_ASSERT_ARG(interp) \ 
     273    , PARROT_ASSERT_ARG(str) \ 
     274    , PARROT_ASSERT_ARG(i)) 
     275#define ASSERT_ARGS_utf16_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     276       PARROT_ASSERT_ARG(interp) \ 
     277    , PARROT_ASSERT_ARG(str) \ 
     278    , PARROT_ASSERT_ARG(i)) 
     279#define ASSERT_ARGS_utf16_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     280       PARROT_ASSERT_ARG(interp) \ 
     281    , PARROT_ASSERT_ARG(str) \ 
     282    , PARROT_ASSERT_ARG(i)) 
     283#define ASSERT_ARGS_utf16_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     284       PARROT_ASSERT_ARG(interp) \ 
     285    , PARROT_ASSERT_ARG(str) \ 
     286    , PARROT_ASSERT_ARG(i)) 
     287#define ASSERT_ARGS_utf16_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     288       PARROT_ASSERT_ARG(interp) \ 
     289    , PARROT_ASSERT_ARG(str) \ 
     290    , PARROT_ASSERT_ARG(i)) 
    226291#define ASSERT_ARGS_utf16_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    227292       PARROT_ASSERT_ARG(interp) \ 
    228293    , PARROT_ASSERT_ARG(i)) 
     
    498563    UINTVAL start; 
    499564    STRING * const return_string = Parrot_str_new_COW(interp, src); 
    500565 
    501     iter_init(interp, src, &iter); 
    502     iter.set_position(interp, &iter, offset); 
     566    STRING_ITER_INIT(interp, &iter); 
     567    utf16_iter_set_position(interp, src, &iter, offset); 
    503568    start = iter.bytepos; 
    504569    return_string->strstart = (char *)return_string->strstart + start ; 
    505     iter.set_position(interp, &iter, offset + count); 
     570    utf16_iter_skip(interp, src, &iter, count); 
    506571    return_string->bufused = iter.bytepos - start; 
    507572    return_string->strlen = count; 
    508573    return_string->hashval = 0; 
     
    532597    String_iter iter; 
    533598    UINTVAL start; 
    534599    Parrot_str_reuse_COW(interp, src, return_string); 
    535     iter_init(interp, src, &iter); 
    536     iter.set_position(interp, &iter, offset); 
     600    STRING_ITER_INIT(interp, &iter); 
     601    utf16_iter_set_position(interp, src, &iter, offset); 
    537602    start = iter.bytepos; 
    538603    return_string->strstart = (char *)return_string->strstart + start ; 
    539     iter.set_position(interp, &iter, offset + count); 
     604    utf16_iter_skip(interp, src, &iter, count); 
    540605    return_string->bufused = iter.bytepos - start; 
    541606    return_string->strlen = count; 
    542607    return_string->hashval = 0; 
     
    675740codepoints(PARROT_INTERP, ARGIN(STRING *src)) 
    676741{ 
    677742    ASSERT_ARGS(codepoints) 
    678     String_iter iter; 
     743#if PARROT_HAS_ICU 
     744    UChar *s = (UChar*) src->strstart; 
     745    UINTVAL pos = 0; 
    679746    /* 
    680747     * this is used to initially calculate src->strlen, 
    681748     * therefore we must scan the whole string 
    682749     */ 
    683     iter_init(interp, src, &iter); 
    684     while (iter.bytepos < src->bufused) 
    685         iter.get_and_advance(interp, &iter); 
    686     return iter.charpos; 
     750    while (pos * sizeof(UChar) < src->bufused) { 
     751        U16_FWD_1_UNSAFE(s, pos); 
     752    } 
     753    return pos * sizeof(UChar); 
     754#else 
     755    UNUSED(src); 
     756 
     757    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     758        "no ICU lib loaded"); 
     759#endif 
    687760} 
    688761 
    689762/* 
     
    704777    return src->bufused; 
    705778} 
    706779 
     780/* 
     781 
     782=item C<static UINTVAL utf16_iter_get(PARROT_INTERP, const STRING *str, const 
     783String_iter *i, INTVAL offset)> 
     784 
     785Get the character at C<i> plus C<offset>. 
     786 
     787=cut 
     788 
     789*/ 
     790 
     791static UINTVAL 
     792utf16_iter_get(PARROT_INTERP, 
     793    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     794{ 
     795    ASSERT_ARGS(utf16_iter_get) 
     796#if PARROT_HAS_ICU 
     797    UChar *s = (UChar*) str->strstart; 
     798    UINTVAL c, pos; 
     799 
     800    pos = i->bytepos / sizeof (UChar); 
     801    if (offset > 0) { 
     802        U16_FWD_N_UNSAFE(s, pos, offset); 
     803    } 
     804    else if (offset < 0) { 
     805        U16_BACK_N_UNSAFE(s, pos, -offset); 
     806    } 
     807    U16_GET_UNSAFE(s, pos, c); 
     808 
     809    return c; 
     810#else 
     811    UNUSED(str); 
     812    UNUSED(i); 
     813    UNUSED(offset); 
     814 
     815    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     816        "no ICU lib loaded"); 
     817#endif 
     818} 
     819 
     820/* 
     821 
     822=item C<static void utf16_iter_skip(PARROT_INTERP, const STRING *str, 
     823String_iter *i, INTVAL skip)> 
     824 
     825Moves the string iterator C<i> by C<skip> characters. 
     826 
     827=cut 
     828 
     829*/ 
     830 
     831static void 
     832utf16_iter_skip(PARROT_INTERP, 
     833    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     834{ 
     835    ASSERT_ARGS(utf16_iter_skip) 
     836#if PARROT_HAS_ICU 
     837    UChar * const s = (UChar*) str->strstart; 
     838    UINTVAL pos = i->bytepos / sizeof (UChar); 
     839 
     840    if (skip > 0) { 
     841        U16_FWD_N_UNSAFE(s, pos, skip); 
     842    } 
     843    else if (skip < 0) { 
     844        U16_BACK_N_UNSAFE(s, pos, -skip); 
     845    } 
     846 
     847    i->charpos += skip; 
     848    i->bytepos = pos * sizeof (UChar); 
     849#else 
     850    UNUSED(str); 
     851    UNUSED(i); 
     852    UNUSED(skip); 
     853 
     854    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     855        "no ICU lib loaded"); 
     856#endif 
     857} 
     858 
     859/* 
     860 
     861=item C<static UINTVAL utf16_iter_get_and_advance(PARROT_INTERP, const STRING 
     862*str, String_iter *i)> 
     863 
     864Moves the string iterator C<i> to the next UTF-16 codepoint. 
     865 
     866=cut 
     867 
     868*/ 
     869 
     870PARROT_WARN_UNUSED_RESULT 
     871static UINTVAL 
     872utf16_iter_get_and_advance(PARROT_INTERP, 
     873    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     874{ 
     875    ASSERT_ARGS(utf16_iter_get_and_advance) 
     876#if PARROT_HAS_ICU 
     877    UChar *s = (UChar*) str->strstart; 
     878    UINTVAL c, pos; 
     879    pos = i->bytepos / sizeof (UChar); 
     880    /* TODO either make sure that we don't go past end or use SAFE 
     881     *      iter versions 
     882     */ 
     883    U16_NEXT_UNSAFE(s, pos, c); 
     884    i->charpos++; 
     885    i->bytepos = pos * sizeof (UChar); 
     886    return c; 
     887#else 
     888    UNUSED(str); 
     889    UNUSED(i); 
     890 
     891    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     892        "no ICU lib loaded"); 
     893#endif 
     894} 
     895 
     896/* 
     897 
     898=item C<static void utf16_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     899String_iter *i, UINTVAL c)> 
     900 
     901With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     902next position in the string. 
     903 
     904=cut 
     905 
     906*/ 
     907 
     908static void 
     909utf16_iter_set_and_advance(PARROT_INTERP, 
     910    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     911{ 
     912    ASSERT_ARGS(utf16_iter_set_and_advance) 
     913#if PARROT_HAS_ICU 
     914    UChar *s = (UChar*) str->strstart; 
     915    UINTVAL pos; 
     916    pos = i->bytepos / sizeof (UChar); 
     917    U16_APPEND_UNSAFE(s, pos, c); 
     918    i->charpos++; 
     919    i->bytepos = pos * sizeof (UChar); 
     920#else 
     921    UNUSED(str); 
     922    UNUSED(i); 
     923    UNUSED(c); 
     924 
     925    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     926        "no ICU lib loaded"); 
     927#endif 
     928} 
     929 
     930/* 
     931 
     932=item C<static void utf16_iter_set_position(PARROT_INTERP, const STRING *str, 
     933String_iter *i, UINTVAL n)> 
     934 
     935Moves the string iterator C<i> to the position C<n> in the string. 
     936 
     937=cut 
     938 
     939*/ 
     940 
     941static void 
     942utf16_iter_set_position(PARROT_INTERP, 
     943    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n) 
     944{ 
     945    ASSERT_ARGS(utf16_iter_set_position) 
     946#if PARROT_HAS_ICU 
     947    UChar * const s = (UChar*) str->strstart; 
     948    UINTVAL pos; 
     949    pos = 0; 
     950    U16_FWD_N_UNSAFE(s, pos, n); 
     951    i->charpos = n; 
     952    i->bytepos = pos * sizeof (UChar); 
     953#else 
     954    UNUSED(str); 
     955    UNUSED(i); 
     956    UNUSED(n); 
     957 
     958    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     959        "no ICU lib loaded"); 
     960#endif 
     961} 
     962 
    707963#if PARROT_HAS_ICU 
    708964/* 
    709965 
     
    8431099        codepoints, 
    8441100        bytes, 
    8451101        iter_init, 
    846         find_cclass 
     1102        find_cclass, 
     1103        utf16_iter_get, 
     1104        utf16_iter_skip, 
     1105        utf16_iter_get_and_advance, 
     1106        utf16_iter_set_and_advance, 
     1107        utf16_iter_set_position 
    8471108    }; 
    8481109    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    8491110    Parrot_register_encoding(interp, "utf16", return_encoding); 
  • src/string/encoding/utf8.c

    diff --git a/src/string/encoding/utf8.c b/src/string/encoding/utf8.c
    index 1da82fa..4706596 100644
    a b  
    170170        __attribute__nonnull__(2) 
    171171        FUNC_MODIFIES(*i); 
    172172 
     173static UINTVAL utf8_iter_get(PARROT_INTERP, 
     174    ARGIN(const STRING *str), 
     175    ARGIN(const String_iter *i), 
     176    INTVAL offset) 
     177        __attribute__nonnull__(1) 
     178        __attribute__nonnull__(2) 
     179        __attribute__nonnull__(3); 
     180 
     181static UINTVAL utf8_iter_get_and_advance(PARROT_INTERP, 
     182    ARGIN(const STRING *str), 
     183    ARGMOD(String_iter *i)) 
     184        __attribute__nonnull__(1) 
     185        __attribute__nonnull__(2) 
     186        __attribute__nonnull__(3) 
     187        FUNC_MODIFIES(*i); 
     188 
     189static void utf8_iter_set_and_advance(PARROT_INTERP, 
     190    ARGMOD(STRING *str), 
     191    ARGMOD(String_iter *i), 
     192    UINTVAL c) 
     193        __attribute__nonnull__(1) 
     194        __attribute__nonnull__(2) 
     195        __attribute__nonnull__(3) 
     196        FUNC_MODIFIES(*str) 
     197        FUNC_MODIFIES(*i); 
     198 
     199static void utf8_iter_set_position(SHIM_INTERP, 
     200    ARGIN(const STRING *str), 
     201    ARGMOD(String_iter *i), 
     202    UINTVAL pos) 
     203        __attribute__nonnull__(2) 
     204        __attribute__nonnull__(3) 
     205        FUNC_MODIFIES(*i); 
     206 
     207static void utf8_iter_skip(SHIM_INTERP, 
     208    ARGIN(const STRING *str), 
     209    ARGMOD(String_iter *i), 
     210    INTVAL skip) 
     211        __attribute__nonnull__(2) 
     212        __attribute__nonnull__(3) 
     213        FUNC_MODIFIES(*i); 
     214 
    173215static void utf8_set_position(SHIM_INTERP, 
    174216    ARGMOD(String_iter *i), 
    175217    UINTVAL pos) 
     
    244286#define ASSERT_ARGS_utf8_encode_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    245287       PARROT_ASSERT_ARG(interp) \ 
    246288    , PARROT_ASSERT_ARG(i)) 
     289#define ASSERT_ARGS_utf8_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     290       PARROT_ASSERT_ARG(interp) \ 
     291    , PARROT_ASSERT_ARG(str) \ 
     292    , PARROT_ASSERT_ARG(i)) 
     293#define ASSERT_ARGS_utf8_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     294       PARROT_ASSERT_ARG(interp) \ 
     295    , PARROT_ASSERT_ARG(str) \ 
     296    , PARROT_ASSERT_ARG(i)) 
     297#define ASSERT_ARGS_utf8_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     298       PARROT_ASSERT_ARG(interp) \ 
     299    , PARROT_ASSERT_ARG(str) \ 
     300    , PARROT_ASSERT_ARG(i)) 
     301#define ASSERT_ARGS_utf8_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     302       PARROT_ASSERT_ARG(str) \ 
     303    , PARROT_ASSERT_ARG(i)) 
     304#define ASSERT_ARGS_utf8_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     305       PARROT_ASSERT_ARG(str) \ 
     306    , PARROT_ASSERT_ARG(i)) 
    247307#define ASSERT_ARGS_utf8_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    248308       PARROT_ASSERT_ARG(i)) 
    249309#define ASSERT_ARGS_utf8_skip_backward __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     
    456516 
    457517/* 
    458518 
     519=item C<static UINTVAL utf8_iter_get(PARROT_INTERP, const STRING *str, const 
     520String_iter *i, INTVAL offset)> 
     521 
     522Get the character at C<i> plus C<offset>. 
     523 
     524=cut 
     525 
     526*/ 
     527 
     528static UINTVAL 
     529utf8_iter_get(PARROT_INTERP, 
     530    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     531{ 
     532    ASSERT_ARGS(utf8_iter_get) 
     533    const utf8_t *u8ptr = (utf8_t *)((char *)str->strstart + i->bytepos); 
     534 
     535    if (offset > 0) { 
     536        u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, offset); 
     537    } 
     538    else if (offset < 0) { 
     539        u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr, offset); 
     540    } 
     541 
     542    return utf8_decode(interp, u8ptr); 
     543} 
     544 
     545/* 
     546 
     547=item C<static void utf8_iter_skip(PARROT_INTERP, const STRING *str, String_iter 
     548*i, INTVAL skip)> 
     549 
     550Moves the string iterator C<i> by C<skip> characters. 
     551 
     552=cut 
     553 
     554*/ 
     555 
     556static void 
     557utf8_iter_skip(SHIM_INTERP, 
     558    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     559{ 
     560    ASSERT_ARGS(utf8_iter_skip) 
     561    const utf8_t *u8ptr = (const utf8_t *)str->strstart; 
     562 
     563    if (skip > 0) { 
     564        u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, skip); 
     565    } 
     566    else if (skip < 0) { 
     567        u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr, -skip); 
     568    } 
     569 
     570    i->charpos += skip; 
     571    i->bytepos = (const char *)u8ptr - (const char *)str->strstart; 
     572} 
     573 
     574/* 
     575 
     576=item C<static UINTVAL utf8_iter_get_and_advance(PARROT_INTERP, const STRING 
     577*str, String_iter *i)> 
     578 
     579The UTF-8 implementation of the string iterator's C<get_and_advance> 
     580function. 
     581 
     582=cut 
     583 
     584*/ 
     585 
     586static UINTVAL 
     587utf8_iter_get_and_advance(PARROT_INTERP,  
     588    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     589{ 
     590    ASSERT_ARGS(utf8_iter_get_and_advance) 
     591    const utf8_t *u8ptr = (utf8_t *)((char *)str->strstart + i->bytepos); 
     592    UINTVAL c = *u8ptr; 
     593 
     594    if (UTF8_IS_START(c)) { 
     595        UINTVAL len = UTF8SKIP(u8ptr); 
     596 
     597        c &= UTF8_START_MASK(len); 
     598        i->bytepos += len; 
     599        for (len--; len; len--) { 
     600            u8ptr++; 
     601 
     602            if (!UTF8_IS_CONTINUATION(*u8ptr)) 
     603                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     604                    "Malformed UTF-8 string\n"); 
     605            c = UTF8_ACCUMULATE(c, *u8ptr); 
     606        } 
     607 
     608        if (UNICODE_IS_SURROGATE(c)) 
     609            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     610                "Surrogate in UTF-8 string\n"); 
     611    } 
     612    else if (!UNICODE_IS_INVARIANT(c)) { 
     613        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     614            "Malformed UTF-8 string\n"); 
     615    } 
     616    else { 
     617        i->bytepos++; 
     618    } 
     619 
     620    i->charpos++; 
     621    return c; 
     622} 
     623 
     624/* 
     625 
     626=item C<static void utf8_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     627String_iter *i, UINTVAL c)> 
     628 
     629The UTF-8 implementation of the string iterator's C<set_and_advance> 
     630function. 
     631 
     632=cut 
     633 
     634*/ 
     635 
     636static void 
     637utf8_iter_set_and_advance(PARROT_INTERP, 
     638    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     639{ 
     640    ASSERT_ARGS(utf8_iter_set_and_advance) 
     641    unsigned char * const pos = (unsigned char *)str->strstart + i->bytepos; 
     642    unsigned char * const new_pos = (unsigned char *)utf8_encode(interp, pos, c); 
     643 
     644    i->bytepos += (new_pos - pos); 
     645    /* XXX possible buffer overrun exception? */ 
     646    PARROT_ASSERT(i->bytepos <= Buffer_buflen(str)); 
     647    i->charpos++; 
     648} 
     649 
     650/* 
     651 
     652=item C<static void utf8_iter_set_position(PARROT_INTERP, const STRING *str, 
     653String_iter *i, UINTVAL pos)> 
     654 
     655The UTF-8 implementation of the string iterator's C<set_position> 
     656function. 
     657 
     658=cut 
     659 
     660*/ 
     661 
     662static void 
     663utf8_iter_set_position(SHIM_INTERP, 
     664    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL pos) 
     665{ 
     666    ASSERT_ARGS(utf8_iter_set_position) 
     667    const utf8_t *u8ptr = (const utf8_t *)str->strstart; 
     668 
     669    if (pos == 0) { 
     670        i->charpos = 0; 
     671        i->bytepos = 0; 
     672        return; 
     673    } 
     674 
     675    /* 
     676     * we know the byte offsets of three positions: start, current and end 
     677     * now find the shortest way to reach pos 
     678     */ 
     679    if (pos < i->charpos) { 
     680        if (pos <= (i->charpos >> 1)) { 
     681            /* go forward from start */ 
     682            u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, pos); 
     683        } 
     684        else { 
     685            /* go backward from current */ 
     686            u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr + i->bytepos, i->charpos - pos); 
     687        } 
     688    } 
     689    else { 
     690        const UINTVAL  len = str->strlen; 
     691        if (pos <= i->charpos + ((len - i->charpos) >> 1)) { 
     692            /* go forward from current */ 
     693            u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr + i->bytepos, pos - i->charpos); 
     694        } 
     695        else { 
     696            /* go backward from end */ 
     697            u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr + str->bufused, len - pos); 
     698        } 
     699    } 
     700 
     701    i->charpos = pos; 
     702    i->bytepos = (const char *)u8ptr - (const char *)str->strstart; 
     703} 
     704 
     705/* 
     706 
    459707=item C<static UINTVAL utf8_decode_and_advance(PARROT_INTERP, String_iter *i)> 
    460708 
    461709The UTF-8 implementation of the string iterator's C<get_and_advance> 
     
    582830{ 
    583831    ASSERT_ARGS(to_encoding) 
    584832    STRING *result; 
    585     String_iter src_iter; 
    586     UINTVAL offs, dest_len, dest_pos, src_len; 
     833    const ENCODING *src_encoding; 
     834    UINTVAL dest_len, dest_pos, src_len; 
    587835    const int in_place = (dest == NULL); 
    588836    unsigned char *new_pos, *pos, *p; 
    589837 
     
    597845        result = dest; 
    598846    } 
    599847 
    600     /* init iter before possilby changing encoding */ 
    601     ENCODING_ITER_INIT(interp, src, &src_iter); 
     848    /* save source encoding before possibly changing it */ 
     849    src_encoding = src->encoding; 
    602850    result->charset  = Parrot_unicode_charset_ptr; 
    603851    result->encoding = Parrot_utf8_encoding_ptr; 
    604852    result->strlen   = src_len; 
     
    621869        result->bufused = dest_len; 
    622870    } 
    623871    else { 
     872        String_iter src_iter; 
     873        STRING_ITER_INIT(interp, &src_iter); 
    624874        dest_len = src_len; 
    625875        dest_pos = 0; 
    626         for (offs = 0; offs < src_len; ++offs) { 
    627             const UINTVAL c = src_iter.get_and_advance(interp, &src_iter); 
     876        while (src_iter.charpos < src_len) { 
     877            const UINTVAL c = src_encoding->iter_get_and_advance(interp, src, &src_iter); 
    628878            if (dest_len - dest_pos < 6) { 
    629                 UINTVAL need = (UINTVAL)((src->strlen - offs) * 1.5); 
     879                UINTVAL need = (UINTVAL)((src->strlen - src_iter.charpos + 1) * 1.5); 
    630880                if (need < 16) 
    631881                    need = 16; 
    632882                dest_len += need; 
     
    7901040    String_iter    iter; 
    7911041    UINTVAL        start; 
    7921042 
    793     iter_init(interp, src, &iter); 
     1043    STRING_ITER_INIT(interp, &iter); 
    7941044 
    7951045    if (offset) 
    796         iter.set_position(interp, &iter, offset); 
     1046        utf8_iter_set_position(interp, src, &iter, offset); 
    7971047 
    7981048    start                   = iter.bytepos; 
    7991049    return_string->strstart = (char *)return_string->strstart + start; 
    8001050 
    8011051    if (count) 
    802         iter.set_position(interp, &iter, offset + count); 
     1052        utf8_iter_set_position(interp, src, &iter, offset + count); 
    8031053 
    8041054    return_string->bufused  = iter.bytepos - start; 
    8051055    return_string->strlen   = count; 
     
    8601110    UINTVAL start; 
    8611111 
    8621112    Parrot_str_reuse_COW(interp, src, return_string); 
    863     iter_init(interp, src, &iter); 
    864     iter.set_position(interp, &iter, offset); 
     1113    STRING_ITER_INIT(interp, &iter); 
     1114    utf8_iter_set_position(interp, src, &iter, offset); 
    8651115 
    8661116    start = iter.bytepos; 
    8671117 
    8681118    return_string->strstart = (char *)return_string->strstart + start; 
    869     iter.set_position(interp, &iter, offset + count); 
     1119    utf8_iter_set_position(interp, src, &iter, offset + count); 
    8701120 
    8711121    return_string->bufused = iter.bytepos - start; 
    8721122    return_string->strlen  = count; 
     
    9731223     * this is used to initially calculate src->strlen, 
    9741224     * therefore we must scan the whole string 
    9751225     */ 
    976     iter_init(interp, src, &iter); 
     1226    STRING_ITER_INIT(interp, &iter); 
    9771227    while (iter.bytepos < src->bufused) 
    978         iter.get_and_advance(interp, &iter); 
     1228        utf8_iter_get_and_advance(interp, src, &iter); 
    9791229    return iter.charpos; 
    9801230} 
    9811231 
     
    10551305        codepoints, 
    10561306        bytes, 
    10571307        iter_init, 
    1058         find_cclass 
     1308        find_cclass, 
     1309        utf8_iter_get, 
     1310        utf8_iter_skip, 
     1311        utf8_iter_get_and_advance, 
     1312        utf8_iter_set_and_advance, 
     1313        utf8_iter_set_position 
    10591314    }; 
    10601315    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    10611316    Parrot_register_encoding(interp, "utf8", return_encoding);