Ticket #1456: string-iter-v7.diff

File string-iter-v7.diff, 84.2 KB (added by nwellnhof, 4 years ago)
  • include/parrot/encoding.h

    diff --git a/include/parrot/encoding.h b/include/parrot/encoding.h
    index 84d42eb..5965ad6 100644
    a b  
    3232 
    3333typedef void (*encoding_iter_init_t)(PARROT_INTERP, const STRING *src, 
    3434        struct string_iterator_t *); 
     35typedef UINTVAL (*encoding_iter_get_t)( 
     36    PARROT_INTERP, const STRING *str, const String_iter *i, INTVAL  offset); 
     37typedef void    (*encoding_iter_skip_t)( 
     38    PARROT_INTERP, const STRING *str,       String_iter *i, INTVAL  skip); 
     39typedef UINTVAL (*encoding_iter_get_and_advance_t)( 
     40    PARROT_INTERP, const STRING *str,       String_iter *i); 
     41typedef void    (*encoding_iter_set_and_advance_t)( 
     42    PARROT_INTERP,       STRING *str,       String_iter *i, UINTVAL c); 
     43typedef void    (*encoding_iter_set_position_t)( 
     44    PARROT_INTERP, const STRING *str,       String_iter *i, UINTVAL pos); 
    3545 
    3646struct _encoding { 
    3747    ARGIN(const char *name); 
     
    4757    encoding_iter_init_t                iter_init; 
    4858    encoding_find_cclass_t              find_cclass; 
    4959    encoding_hash_t                     hash; 
     60    encoding_iter_get_t                 iter_get; 
     61    encoding_iter_skip_t                iter_skip; 
     62    encoding_iter_get_and_advance_t     iter_get_and_advance; 
     63    encoding_iter_set_and_advance_t     iter_set_and_advance; 
     64    encoding_iter_set_position_t        iter_set_position; 
    5065}; 
    5166 
    5267typedef struct _encoding ENCODING; 
  • include/parrot/string.h

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

    diff --git a/include/parrot/string_funcs.h b/include/parrot/string_funcs.h
    index 7c35265..63501fe 100644
    a b  
    226226INTVAL Parrot_str_is_null(SHIM_INTERP, ARGIN_NULLOK(const STRING *s)); 
    227227 
    228228PARROT_EXPORT 
     229INTVAL Parrot_str_iter_index(PARROT_INTERP, 
     230    ARGIN(const STRING *src), 
     231    ARGMOD(String_iter *start), 
     232    ARGOUT(String_iter *end), 
     233    ARGIN(const STRING *search)) 
     234        __attribute__nonnull__(1) 
     235        __attribute__nonnull__(2) 
     236        __attribute__nonnull__(3) 
     237        __attribute__nonnull__(4) 
     238        __attribute__nonnull__(5) 
     239        FUNC_MODIFIES(*start) 
     240        FUNC_MODIFIES(*end); 
     241 
     242PARROT_EXPORT 
     243PARROT_CANNOT_RETURN_NULL 
     244PARROT_WARN_UNUSED_RESULT 
     245STRING * Parrot_str_iter_substr(PARROT_INTERP, 
     246    ARGIN(const STRING *str), 
     247    ARGIN(const String_iter *l), 
     248    ARGIN_NULLOK(const String_iter *r)) 
     249        __attribute__nonnull__(1) 
     250        __attribute__nonnull__(2) 
     251        __attribute__nonnull__(3); 
     252 
     253PARROT_EXPORT 
    229254PARROT_WARN_UNUSED_RESULT 
    230255PARROT_CANNOT_RETURN_NULL 
    231256STRING* Parrot_str_join(PARROT_INTERP, 
     
    559584       PARROT_ASSERT_ARG(interp) \ 
    560585    , PARROT_ASSERT_ARG(s)) 
    561586#define ASSERT_ARGS_Parrot_str_is_null __attribute__unused__ int _ASSERT_ARGS_CHECK = (0) 
     587#define ASSERT_ARGS_Parrot_str_iter_index __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     588       PARROT_ASSERT_ARG(interp) \ 
     589    , PARROT_ASSERT_ARG(src) \ 
     590    , PARROT_ASSERT_ARG(start) \ 
     591    , PARROT_ASSERT_ARG(end) \ 
     592    , PARROT_ASSERT_ARG(search)) 
     593#define ASSERT_ARGS_Parrot_str_iter_substr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     594       PARROT_ASSERT_ARG(interp) \ 
     595    , PARROT_ASSERT_ARG(str) \ 
     596    , PARROT_ASSERT_ARG(l)) 
    562597#define ASSERT_ARGS_Parrot_str_join __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    563598       PARROT_ASSERT_ARG(interp) \ 
    564599    , PARROT_ASSERT_ARG(ar)) 
  • src/io/utf8.c

    diff --git a/src/io/utf8.c b/src/io/utf8.c
    index a4dc6a4..1c5b034 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) { 
     
    8484 
    8585                s->strlen    = iter.charpos; 
    8686                s            = Parrot_str_concat(interp, s, s2); 
    87                 /* String is updated. Poke into iterator to replace old string */ 
    88                 iter.str     = s; 
    8987                *buf         = s; 
    9088                len         += len2 + 1; 
    9189 
     
    9391            } 
    9492        } 
    9593ok: 
    96         iter.get_and_advance(interp, &iter); 
     94        Parrot_utf8_encoding_ptr->iter_get_and_advance(interp, *buf, &iter); 
    9795    } 
    9896    s->strlen = iter.charpos; 
    9997    return len; 
  • src/pmc/stringiterator.pmc

    diff --git a/src/pmc/stringiterator.pmc b/src/pmc/stringiterator.pmc
    index ce9001c..bda81b7 100644
    a b  
    2727/* HEADERIZER END: static */ 
    2828 
    2929pmclass StringIterator auto_attrs extends Iterator { 
    30     ATTR PMC    *string;    /* String to iterate over */ 
    31     ATTR INTVAL  pos;       /* Current position of iterator for forward iterator */ 
    32                             /* Previous position of iterator for reverse iterator */ 
    33     ATTR INTVAL  length;    /* Length of C<string> */ 
    34     ATTR INTVAL  reverse;   /* Direction of iteration. 1 - for reverse iteration */ 
     30    ATTR STRING      *str_val;   /* String to iterate over */ 
     31    ATTR String_iter  iter;      /* String iterator */ 
     32    ATTR INTVAL       reverse;   /* Direction of iteration. 1 - for reverse iteration */ 
    3533 
    3634/* 
    3735 
     
    4341 
    4442*/ 
    4543    VTABLE void init_pmc(PMC *string) { 
    46         SET_ATTR_string(INTERP, SELF, string); 
     44        String_iter * const iter    = &PARROT_STRINGITERATOR(SELF)->iter; 
     45        STRING      * const str_val = VTABLE_get_string(INTERP, string); 
     46 
     47        SET_ATTR_str_val(INTERP, SELF, str_val); 
     48        STRING_ITER_INIT(INTERP, iter); 
     49        SET_ATTR_reverse(INTERP, SELF, ITERATE_FROM_START); 
    4750 
    48         /* by default, iterate from start */ 
    49         SELF.set_integer_native(ITERATE_FROM_START); 
    5051        PObj_custom_mark_SET(SELF); 
    5152    } 
    5253 
     
    6162*/ 
    6263 
    6364    VTABLE void mark() { 
    64         PMC *string; 
    65         GET_ATTR_string(INTERP, SELF, string); 
    66         Parrot_gc_mark_PMC_alive(INTERP, string); 
     65        STRING *str_val; 
     66 
     67        GET_ATTR_str_val(INTERP, SELF, str_val); 
     68        Parrot_gc_mark_STRING_alive(INTERP, str_val); 
    6769    } 
    6870 
    6971/* 
     
    7476 
    7577*/ 
    7678    VTABLE PMC* clone() { 
    77         Parrot_StringIterator_attributes * const attrs = 
    78                 PARROT_STRINGITERATOR(SELF); 
    79         PMC                              * const clone = 
    80                 Parrot_pmc_new_init(INTERP, enum_class_StringIterator, attrs->string); 
    81         Parrot_StringIterator_attributes * const clone_attrs = 
    82                 PARROT_STRINGITERATOR(clone); 
    83  
    84         clone_attrs->pos     = attrs->pos; 
    85         clone_attrs->reverse = attrs->reverse; 
     79        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     80        PMC         *clone, *str_pmc; 
     81        String_iter *clone_iter; 
     82        STRING      *str_val; 
     83        INTVAL       reverse; 
     84 
     85        str_pmc = Parrot_pmc_new(INTERP, enum_class_String); 
     86        GET_ATTR_str_val(INTERP, SELF, str_val); 
     87        VTABLE_set_string_native(INTERP, str_pmc, str_val); 
     88        clone = Parrot_pmc_new_init(INTERP, enum_class_StringIterator, str_pmc); 
     89        clone_iter = &PARROT_STRINGITERATOR(clone)->iter; 
     90        *clone_iter = *iter; 
     91        GET_ATTR_reverse(INTERP, SELF, reverse); 
     92        SET_ATTR_reverse(INTERP, clone, reverse); 
     93 
    8694        return clone; 
    8795    } 
    8896 
     
    111119*/ 
    112120 
    113121    VTABLE INTVAL elements() { 
    114         Parrot_StringIterator_attributes * const attrs = 
    115                 PARROT_STRINGITERATOR(SELF); 
    116         if (attrs->reverse) 
    117             return attrs->pos; 
     122        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     123        STRING *str_val; 
     124        INTVAL  reverse; 
     125 
     126        GET_ATTR_str_val(INTERP, SELF, str_val); 
     127        GET_ATTR_reverse(INTERP, SELF, reverse); 
     128 
     129        if (reverse) 
     130            return iter->charpos; 
    118131        else 
    119             return attrs->length - attrs->pos; 
     132            return str_val->strlen - iter->charpos; 
    120133    } 
    121134 
    122135    VTABLE INTVAL get_integer() { 
     
    137150*/ 
    138151 
    139152    VTABLE void set_integer_native(INTVAL value) { 
    140         Parrot_StringIterator_attributes * const attrs = 
    141                 PARROT_STRINGITERATOR(SELF); 
    142         switch (value) { 
    143           case ITERATE_FROM_START: 
    144             attrs->reverse   = 0; 
    145             attrs->pos       = 0; 
    146             attrs->length    = VTABLE_elements(INTERP, attrs->string); 
    147             break; 
    148           case ITERATE_FROM_END: 
    149             attrs->reverse   = 1; 
    150             attrs->pos       = attrs->length 
    151                              = VTABLE_elements(INTERP, attrs->string); 
    152             break; 
    153           default: 
     153        STRING *str_val; 
     154        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     155 
     156        GET_ATTR_str_val(INTERP, SELF, str_val); 
     157        if (value == ITERATE_FROM_START) { 
     158            SET_ATTR_reverse(INTERP, SELF, 0); 
     159            STRING_ITER_SET_POSITION(INTERP, str_val, iter, 0); 
     160        } 
     161        else if (value == ITERATE_FROM_END) { 
     162            SET_ATTR_reverse(INTERP, SELF, 1); 
     163            STRING_ITER_SET_POSITION(INTERP, str_val, iter, str_val->strlen); 
     164        } 
     165        else { 
    154166            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, 
    155167                    "Wrong direction for StringIterator"); 
    156168        } 
     
    167179*/ 
    168180 
    169181    VTABLE PMC *get_pmc() { 
    170         PMC *string; 
    171         GET_ATTR_string(INTERP, SELF, string); 
    172         return string ? string : PMCNULL; 
     182        PMC * const string = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type( 
     183            interp, enum_class_String)); 
     184        STRING *str_val; 
     185 
     186        GET_ATTR_str_val(INTERP, SELF, str_val); 
     187        VTABLE_set_string_native(interp, string, str_val); 
     188        return string; 
    173189    } 
    174190 
    175191/* 
     
    182198 
    183199*/ 
    184200    VTABLE PMC *shift_pmc() { 
    185         Parrot_StringIterator_attributes * const attrs = 
    186                 PARROT_STRINGITERATOR(SELF); 
     201        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
    187202        PMC *ret; 
     203        STRING *str_val, *substr; 
     204        const String_iter old_iter = *iter; 
    188205 
    189         if (attrs->pos >= attrs->length) 
     206        GET_ATTR_str_val(INTERP, SELF, str_val); 
     207        if (iter->charpos >= str_val->strlen) 
    190208            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    191209                "StopIteration"); 
    192210 
    193211        ret = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp, enum_class_String)); 
    194         VTABLE_set_string_native(INTERP, ret, 
    195                 VTABLE_get_string_keyed_int(INTERP, attrs->string, attrs->pos++)); 
     212        STRING_ITER_SKIP(INTERP, str_val, iter, 1); 
     213        substr = Parrot_str_iter_substr(INTERP, str_val, &old_iter, iter); 
     214        VTABLE_set_string_native(INTERP, ret, substr); 
    196215        return ret; 
    197216    } 
    198217 
     
    206225 
    207226*/ 
    208227    VTABLE STRING *shift_string() { 
    209         Parrot_StringIterator_attributes * const attrs = 
    210                 PARROT_STRINGITERATOR(SELF); 
     228        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     229        STRING *str_val; 
     230        const String_iter old_iter = *iter; 
    211231 
    212         if (attrs->pos >= attrs->length) 
     232        GET_ATTR_str_val(INTERP, SELF, str_val); 
     233        if (iter->charpos >= str_val->strlen) 
    213234            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    214235                "StopIteration"); 
    215236 
    216         return VTABLE_get_string_keyed_int(INTERP, attrs->string, attrs->pos++); 
     237        STRING_ITER_SKIP(INTERP, str_val, iter, 1); 
     238        return Parrot_str_iter_substr(INTERP, str_val, &old_iter, iter); 
    217239    } 
    218240 
    219241/* 
     
    226248 
    227249*/ 
    228250    VTABLE INTVAL shift_integer() { 
    229         Parrot_StringIterator_attributes * const attrs = 
    230                 PARROT_STRINGITERATOR(SELF); 
     251        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     252        STRING *str_val; 
    231253 
    232         if (attrs->pos >= attrs->length) 
     254        GET_ATTR_str_val(INTERP, SELF, str_val); 
     255        if (iter->charpos >= str_val->strlen) 
    233256            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    234257                "StopIteration"); 
    235258 
    236         return VTABLE_get_integer_keyed_int(INTERP, attrs->string, attrs->pos++); 
     259        return STRING_ITER_GET_AND_ADVANCE(INTERP, str_val, iter); 
    237260    } 
    238261 
    239262/* 
     
    246269 
    247270*/ 
    248271    VTABLE PMC *pop_pmc() { 
    249         Parrot_StringIterator_attributes * const attrs = 
    250                 PARROT_STRINGITERATOR(SELF); 
     272        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     273        STRING *str_val, *substr; 
    251274        PMC *ret; 
     275        const String_iter old_iter = *iter; 
    252276 
    253         if (!STATICSELF.get_bool()) 
     277        GET_ATTR_str_val(INTERP, SELF, str_val); 
     278        /* Shouldn't this test be (iter->charpos <= 0) ? */ 
     279        if (SELF.elements() <= 0) 
    254280            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    255281                "StopIteration"); 
    256282 
    257283        ret = Parrot_pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp, enum_class_String)); 
    258         VTABLE_set_string_native(INTERP, ret, 
    259                 VTABLE_get_string_keyed_int(INTERP, attrs->string, --attrs->pos)); 
     284        STRING_ITER_SKIP(INTERP, str_val, iter, -1); 
     285        substr = Parrot_str_iter_substr(INTERP, str_val, iter, &old_iter); 
     286        VTABLE_set_string_native(INTERP, ret, substr); 
    260287        return ret; 
    261288    } 
    262289 
     
    270297 
    271298*/ 
    272299    VTABLE STRING *pop_string() { 
    273         Parrot_StringIterator_attributes * const attrs = 
    274                 PARROT_STRINGITERATOR(SELF); 
     300        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     301        STRING *str_val; 
     302        const String_iter old_iter = *iter; 
    275303 
    276         if (!STATICSELF.get_bool()) 
     304        GET_ATTR_str_val(INTERP, SELF, str_val); 
     305        /* Shouldn't this test be (iter->charpos <= 0) ? */ 
     306        if (SELF.elements() <= 0) 
    277307            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    278308                "StopIteration"); 
    279309 
    280         return VTABLE_get_string_keyed_int(INTERP, attrs->string, --attrs->pos); 
     310        STRING_ITER_SKIP(INTERP, str_val, iter, -1); 
     311        return Parrot_str_iter_substr(INTERP, str_val, iter, &old_iter); 
    281312    } 
    282313 
    283314/* 
     
    290321 
    291322*/ 
    292323    VTABLE INTVAL pop_integer() { 
    293         Parrot_StringIterator_attributes * const attrs = 
    294                 PARROT_STRINGITERATOR(SELF); 
     324        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     325        STRING *str_val; 
    295326 
    296         if (!STATICSELF.get_bool()) 
     327        GET_ATTR_str_val(INTERP, SELF, str_val); 
     328        /* Shouldn't this test be (iter->charpos <= 0) ? */ 
     329        if (SELF.elements() <= 0) 
    297330            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
    298331                "StopIteration"); 
    299332 
    300         return VTABLE_get_integer_keyed_int(INTERP, attrs->string, --attrs->pos); 
     333        STRING_ITER_SKIP(INTERP, str_val, iter, -1); 
     334        return STRING_ITER_GET(INTERP, str_val, iter, 0); 
    301335    } 
    302336 
    303337/* 
     
    311345*/ 
    312346 
    313347    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) { 
    314         return VTABLE_get_integer_keyed_int(INTERP, STATICSELF.get_pmc(), 
    315                 PARROT_STRINGITERATOR(SELF)->pos + idx); 
     348        String_iter * const iter = &PARROT_STRINGITERATOR(SELF)->iter; 
     349        STRING *str_val; 
     350        const UINTVAL offset = iter->charpos + idx; 
     351 
     352        GET_ATTR_str_val(INTERP, SELF, str_val); 
     353        if (offset >= str_val->strlen) 
     354            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
     355                "StopIteration"); 
     356 
     357        return STRING_ITER_GET(INTERP, str_val, iter, idx); 
    316358    } 
    317359 
    318360/* 
     
    326368*/ 
    327369 
    328370    VTABLE STRING *get_string_keyed_int(INTVAL idx) { 
    329         return VTABLE_get_string_keyed_int(INTERP, STATICSELF.get_pmc(), 
    330                 PARROT_STRINGITERATOR(SELF)->pos + idx); 
     371        String_iter iter = PARROT_STRINGITERATOR(SELF)->iter; 
     372        String_iter next_iter; 
     373        STRING *str_val; 
     374        const UINTVAL offset = iter.charpos + idx; 
     375 
     376        GET_ATTR_str_val(INTERP, SELF, str_val); 
     377        if (offset >= str_val->strlen) 
     378            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS, 
     379                "StopIteration"); 
     380 
     381        if (idx != 0) 
     382            STRING_ITER_SKIP(INTERP, str_val, &iter, idx); 
     383        next_iter = iter; 
     384        STRING_ITER_SKIP(INTERP, str_val, &next_iter, 1); 
     385 
     386        return Parrot_str_iter_substr(INTERP, str_val, &iter, &next_iter); 
    331387    } 
    332388} 
    333389 
  • src/string/api.c

    diff --git a/src/string/api.c b/src/string/api.c
    index e37354e..e2a558e 100644
    a b  
    11041104    return CHARSET_GET_CODEPOINTS(interp, src, true_offset, true_length); 
    11051105} 
    11061106 
     1107/* 
     1108 
     1109=item C<STRING * Parrot_str_iter_substr(PARROT_INTERP, const STRING *str, const 
     1110String_iter *l, const String_iter *r)> 
     1111 
     1112Returns the substring between iterators C<l> and C<r>. 
     1113 
     1114=cut 
     1115 
     1116*/ 
     1117 
     1118PARROT_EXPORT 
     1119PARROT_CANNOT_RETURN_NULL 
     1120PARROT_WARN_UNUSED_RESULT 
     1121STRING * 
     1122Parrot_str_iter_substr(PARROT_INTERP, 
     1123    ARGIN(const STRING *str), 
     1124    ARGIN(const String_iter *l), ARGIN_NULLOK(const String_iter *r)) 
     1125{ 
     1126    ASSERT_ARGS(Parrot_str_iter_substr) 
     1127    STRING *dest = Parrot_str_copy(interp, str); 
     1128 
     1129    dest->strstart = (char *)dest->strstart + l->bytepos; 
     1130 
     1131    if (r == NULL) { 
     1132        dest->bufused = str->bufused - l->bytepos; 
     1133        dest->strlen  = str->strlen  - l->charpos; 
     1134    } 
     1135    else { 
     1136        dest->bufused = r->bytepos - l->bytepos; 
     1137        dest->strlen  = r->charpos - l->charpos; 
     1138    } 
     1139 
     1140    dest->hashval = 0; 
     1141 
     1142    return dest; 
     1143} 
     1144 
     1145/* 
     1146 
     1147=item C<INTVAL Parrot_str_iter_index(PARROT_INTERP, const STRING *src, 
     1148String_iter *start, String_iter *end, const STRING *search)> 
     1149 
     1150Find the next occurence of STRING C<search> in STRING C<src> starting at 
     1151String_iter C<start>. If C<search> is found C<start> is modified to mark the 
     1152beginning of C<search> and String_iter C<end> is set to the character after 
     1153C<search> in C<src>.  Returns the character position where C<search> was found 
     1154or -1 if it wasn't found. 
     1155 
     1156=cut 
     1157 
     1158*/ 
     1159 
     1160PARROT_EXPORT 
     1161INTVAL 
     1162Parrot_str_iter_index(PARROT_INTERP, 
     1163    ARGIN(const STRING *src), 
     1164    ARGMOD(String_iter *start), ARGOUT(String_iter *end), 
     1165    ARGIN(const STRING *search)) 
     1166{ 
     1167    ASSERT_ARGS(Parrot_str_iter_index) 
     1168    String_iter search_iter, search_start, next_start; 
     1169    const UINTVAL len = search->strlen; 
     1170    UINTVAL c0; 
     1171 
     1172    if (len == 0) { 
     1173        *end = *start; 
     1174        return start->charpos; 
     1175    } 
     1176 
     1177    STRING_ITER_INIT(interp, &search_iter); 
     1178    c0 = STRING_ITER_GET_AND_ADVANCE(interp, search, &search_iter); 
     1179    search_start = search_iter; 
     1180    next_start = *start; 
     1181 
     1182    while (start->charpos + len <= src->strlen) { 
     1183        UINTVAL c1 = STRING_ITER_GET_AND_ADVANCE(interp, src, &next_start); 
     1184 
     1185        if (c1 == c0) { 
     1186            UINTVAL c2; 
     1187            *end = next_start; 
     1188 
     1189            do { 
     1190                if (search_iter.charpos >= len) 
     1191                    return start->charpos; 
     1192                c1 = STRING_ITER_GET_AND_ADVANCE(interp, src, end); 
     1193                c2 = STRING_ITER_GET_AND_ADVANCE(interp, search, &search_iter); 
     1194            } while (c1 == c2); 
     1195 
     1196            search_iter = search_start; 
     1197        } 
     1198 
     1199        *start = next_start; 
     1200    } 
     1201 
     1202    return -1; 
     1203} 
     1204 
    11071205 
    11081206/* 
    11091207 
     
    11451243    UINTVAL         true_offset = (UINTVAL)offset; 
    11461244    UINTVAL         true_length = (UINTVAL)length; 
    11471245 
    1148     UINTVAL         start_byte, end_byte; 
     1246    UINTVAL         start_byte, end_byte, start_char, end_char; 
    11491247    INTVAL          buf_size; 
    11501248 
    11511249    if (STRING_IS_NULL(src)) { 
     
    11811279    } 
    11821280 
    11831281    /* get byte position of the part that will be replaced */ 
    1184     ENCODING_ITER_INIT(interp, src, &iter); 
     1282    STRING_ITER_INIT(interp, &iter); 
    11851283 
    1186     iter.set_position(interp, &iter, true_offset); 
     1284    STRING_ITER_SET_POSITION(interp, src, &iter, true_offset); 
    11871285    start_byte = iter.bytepos; 
     1286    start_char = iter.charpos; 
    11881287 
    1189     iter.set_position(interp, &iter, true_offset + true_length); 
     1288    STRING_ITER_SKIP(interp, src, &iter, true_length); 
    11901289    end_byte   = iter.bytepos; 
     1290    end_char   = iter.charpos; 
    11911291 
    11921292    /* not possible.... */ 
    11931293    if (end_byte < start_byte) 
     
    12261326            (char *)src->strstart + end_byte, 
    12271327            src->bufused - end_byte); 
    12281328 
    1229     dest->strlen  = CHARSET_CODEPOINTS(interp, dest); 
     1329    dest->strlen  = src->strlen - (end_char - start_char) + rep->strlen; 
    12301330    dest->hashval = 0; 
    12311331 
    12321332    return dest; 
     
    12521352    ASSERT_ARGS(Parrot_str_chopn) 
    12531353 
    12541354    STRING * const chopped = Parrot_str_copy(interp, s); 
    1255     UINTVAL new_length, uchar_size; 
     1355    UINTVAL new_length; 
    12561356 
    12571357    if (n < 0) { 
    12581358        new_length = -n; 
     
    12731373        return chopped; 
    12741374    } 
    12751375 
    1276     uchar_size      = chopped->bufused / chopped->strlen; 
    1277     chopped->strlen = new_length; 
    1278  
    12791376    if (chopped->encoding == Parrot_fixed_8_encoding_ptr) { 
    12801377        chopped->bufused = new_length; 
    12811378    } 
    12821379    else if (chopped->encoding == Parrot_ucs2_encoding_ptr) { 
     1380        const UINTVAL uchar_size = chopped->bufused / chopped->strlen; 
    12831381        chopped->bufused = new_length * uchar_size; 
    12841382    } 
    12851383    else { 
    12861384        String_iter iter; 
    12871385 
    1288         ENCODING_ITER_INIT(interp, s, &iter); 
    1289         iter.set_position(interp, &iter, new_length); 
     1386        STRING_ITER_INIT(interp, &iter); 
     1387        STRING_ITER_SET_POSITION(interp, s, &iter, new_length); 
    12901388        chopped->bufused = iter.bytepos; 
    12911389    } 
    12921390 
     1391    chopped->strlen = new_length; 
     1392 
    12931393    return chopped; 
    12941394} 
    12951395 
     
    18601960        int                 sign      = 1; 
    18611961        UINTVAL             i         = 0; 
    18621962        String_iter         iter; 
    1863         UINTVAL             offs; 
    18641963        number_parse_state  state = parse_start; 
    18651964 
    1866         ENCODING_ITER_INIT(interp, s, &iter); 
     1965        STRING_ITER_INIT(interp, &iter); 
    18671966 
    1868         for (offs = 0; (state != parse_end) && (offs < s->strlen); ++offs) { 
    1869             const UINTVAL c = iter.get_and_advance(interp, &iter); 
     1967        while (state != parse_end && iter.charpos < s->strlen) { 
     1968            const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, s, &iter); 
    18701969            /* Check for overflow */ 
    18711970            if (c > 255) 
    18721971                break; 
     
    19562055    int           d_length  = 0; 
    19572056    int           check_nan = 0;    /* Check for NaN and Inf after main loop */ 
    19582057    String_iter iter; 
    1959     UINTVAL     offs; 
    19602058    number_parse_state state = parse_start; 
    19612059 
    19622060    if (STRING_IS_NULL(s)) 
    19632061        return 0.0; 
    19642062 
    1965     ENCODING_ITER_INIT(interp, s, &iter); 
     2063    STRING_ITER_INIT(interp, &iter); 
    19662064 
    19672065    /* Handcrafter FSM to read float value */ 
    1968     for (offs = 0; (state != parse_end) && (offs < s->strlen); ++offs) { 
    1969         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     2066    while (state != parse_end && iter.charpos < s->strlen) { 
     2067        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, s, &iter); 
    19702068        /* Check for overflow */ 
    19712069        if (c > 255) 
    19722070            break; 
     
    24172515            Parrot_fixed_8_encoding_ptr, Parrot_ascii_charset_ptr, 0); 
    24182516 
    24192517    /* more work TODO */ 
    2420     ENCODING_ITER_INIT(interp, src, &iter); 
     2518    STRING_ITER_INIT(interp, &iter); 
    24212519    dp = (unsigned char *)result->strstart; 
    24222520 
    24232521    for (i = 0; len > 0; --len) { 
    2424         UINTVAL c = iter.get_and_advance(interp, &iter); 
     2522        UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    24252523        if (c < 0x7f) { 
    24262524            /* process ASCII chars */ 
    24272525            if (i >= charlen - 2) { 
     
    25612659    Parrot_gc_allocate_string_storage(interp, result, reserved); 
    25622660    result->bufused = reserved; 
    25632661 
    2564     src->encoding->iter_init(interp, src, &itersrc); 
    2565     encoding->iter_init(interp, result, &iterdest); 
     2662    STRING_ITER_INIT(interp, &itersrc); 
     2663    STRING_ITER_INIT(interp, &iterdest); 
    25662664    while (itersrc.bytepos < srclen) { 
    2567         INTVAL c = itersrc.get_and_advance(interp, &itersrc); 
     2665        INTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    25682666        INTVAL next; 
    25692667 
    25702668        do { 
    25712669            pending = 0; 
    25722670            next = c; 
    25732671            if (c == '\\') { 
    2574                 c = itersrc.get_and_advance(interp, &itersrc); 
     2672                c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    25752673                switch (c) { 
    25762674                /* Common one char sequences */ 
    25772675                case 'a': next = '\a'; break; 
     
    25842682                case 'e': next = '\e'; break; 
    25852683                /* Escape character */ 
    25862684                case 'c': 
    2587                     c = itersrc.get_and_advance(interp, &itersrc); 
     2685                    c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    25882686                    /* This assumes ascii-alike encoding */ 
    25892687                    if (c < 'A' || c > 'Z') 
    25902688                        throw_illegal_escape(interp); 
     
    25922690                    break; 
    25932691                case 'x': 
    25942692                    digcount = 0; 
    2595                     c = itersrc.get_and_advance(interp, &itersrc); 
     2693                    c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    25962694                    if (c == '{') { 
    25972695                        /* \x{h..h} 1..8 hex digits */ 
    25982696                        while (itersrc.bytepos < srclen) { 
    2599                             c = itersrc.get_and_advance(interp, &itersrc); 
     2697                            c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    26002698                            if (c == '}') 
    26012699                                break; 
    26022700                            if (!isxdigit(c)) 
     
    26202718                                pending = 0; 
    26212719                                break; 
    26222720                            } 
    2623                             c = itersrc.get_and_advance(interp, &itersrc); 
     2721                            c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    26242722                        } 
    26252723                    } 
    26262724                    if (digcount == 0) 
     
    26312729                case 'u': 
    26322730                    /* \uhhhh 4 hex digits */ 
    26332731                    for (digcount = 0; digcount < 4; ++digcount) { 
    2634                         c = itersrc.get_and_advance(interp, &itersrc); 
     2732                        c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    26352733                        if (!isxdigit(c)) 
    26362734                            throw_illegal_escape(interp); 
    26372735                        digbuf[digcount] = c; 
     
    26422740                case 'U': 
    26432741                    /* \Uhhhhhhhh 8 hex digits */ 
    26442742                    for (digcount = 0; digcount < 8; ++digcount) { 
    2645                         c = itersrc.get_and_advance(interp, &itersrc); 
     2743                        c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    26462744                        if (!isxdigit(c)) 
    26472745                            throw_illegal_escape(interp); 
    26482746                        digbuf[digcount] = c; 
     
    26552753                    /* \ooo 1..3 oct digits */ 
    26562754                    digbuf[0] = c; 
    26572755                    for (digcount = 1; digcount < 3; ++digcount) { 
    2658                         c = itersrc.get_and_advance(interp, &itersrc); 
     2756                        c = STRING_ITER_GET_AND_ADVANCE(interp, src, &itersrc); 
    26592757                        if (c < '0' || c > '7') 
    26602758                            break; 
    26612759                        digbuf[digcount] = c; 
     
    26692767                    next = c; 
    26702768                } 
    26712769            } 
    2672             iterdest.set_and_advance(interp, &iterdest, next); 
     2770            STRING_ITER_SET_AND_ADVANCE(interp, result, &iterdest, next); 
    26732771        } while (pending); 
    26742772    } 
    26752773    result->bufused = iterdest.bytepos; 
     
    27502848        encoding = result->encoding; 
    27512849    } 
    27522850 
    2753     encoding->iter_init(interp, result, &iter); 
     2851    STRING_ITER_INIT(interp, &iter); 
    27542852 
    27552853    for (offs = d = 0; offs < clength; ++offs) { 
    27562854        r = (Parrot_UInt4)((unsigned char *)result->strstart)[offs]; 
     
    27732871        } 
    27742872 
    27752873        PARROT_ASSERT(d < offs); 
    2776         iter.set_and_advance(interp, &iter, r); 
     2874        encoding->iter_set_and_advance(interp, result, &iter, r); 
    27772875        ++d; 
    27782876    } 
    27792877 
     
    32713369    ARGIN_NULLOK(const STRING *delim), ARGIN_NULLOK(STRING *str)) 
    32723370{ 
    32733371    ASSERT_ARGS(Parrot_str_split) 
    3274     PMC    *res; 
    3275     INTVAL  slen, dlen, ps, pe; 
     3372    PMC     *res; 
     3373    STRING  *tstr; 
     3374    UINTVAL  slen, dlen; 
     3375    String_iter iter; 
    32763376 
    32773377    if (STRING_IS_NULL(delim) || STRING_IS_NULL(str)) 
    32783378        return PMCNULL; 
     
    32843384    if (!slen) 
    32853385        return res; 
    32863386 
     3387    STRING_ITER_INIT(interp, &iter); 
    32873388    dlen = Parrot_str_length(interp, delim); 
    32883389 
    32893390    if (dlen == 0) { 
    3290         int i; 
    32913391        VTABLE_set_integer_native(interp, res, slen); 
    32923392 
    3293         for (i = 0; i < slen; ++i) { 
    3294             STRING * const p = Parrot_str_substr(interp, str, i, 1); 
    3295             VTABLE_set_string_keyed_int(interp, res, i, p); 
    3296         } 
    3297  
    3298         return res; 
    3299     } 
     3393        do { 
     3394            const String_iter old_iter = iter; 
    33003395 
    3301     pe = Parrot_str_find_index(interp, str, delim, 0); 
     3396            STRING_ITER_SKIP(interp, str, &iter, 1); 
     3397            tstr = Parrot_str_iter_substr(interp, str, &old_iter, &iter); 
     3398            VTABLE_set_string_keyed_int(interp, res, old_iter.charpos, tstr); 
     3399        } while (iter.charpos < slen); 
    33023400 
    3303     if (pe < 0) { 
    3304         VTABLE_push_string(interp, res, str); 
    33053401        return res; 
    33063402    } 
    33073403 
    3308     ps = 0; 
    3309  
    3310     while (ps <= slen) { 
    3311         const int      pl   = pe - ps; 
    3312         STRING * const tstr = Parrot_str_substr(interp, str, ps, pl); 
    3313  
    3314         VTABLE_push_string(interp, res, tstr); 
    3315         ps = pe + Parrot_str_length(interp, delim); 
     3404    do { 
     3405        String_iter start, end; 
     3406        INTVAL pos; 
    33163407 
    3317         if (ps > slen) 
     3408        start = iter; 
     3409        if (Parrot_str_iter_index(interp, str, &start, &end, delim) < 0) 
    33183410            break; 
    33193411 
    3320         pe = Parrot_str_find_index(interp, str, delim, ps); 
     3412        tstr = Parrot_str_iter_substr(interp, str, &iter, &start); 
     3413        VTABLE_push_string(interp, res, tstr); 
     3414        iter = end; 
     3415    } while (iter.charpos < slen); 
    33213416 
    3322         if (pe < 0) 
    3323             pe = slen; 
    3324     } 
     3417    tstr = Parrot_str_iter_substr(interp, str, &iter, NULL); 
     3418    VTABLE_push_string(interp, res, tstr); 
    33253419 
    33263420    return res; 
    33273421} 
  • src/string/charset/ascii.c

    diff --git a/src/string/charset/ascii.c b/src/string/charset/ascii.c
    index 5c8371a..761a60e 100644
    a b  
    201201{ 
    202202    ASSERT_ARGS(to_ascii) 
    203203    String_iter iter; 
    204     UINTVAL offs; 
    205204    unsigned char *p; 
    206205    const UINTVAL len = src->strlen; 
    207206 
     
    209208    STRING * const dest = Parrot_str_clone(interp, src); 
    210209 
    211210    p = (unsigned char *)dest->strstart; 
    212     ENCODING_ITER_INIT(interp, src, &iter); 
    213     for (offs = 0; offs < len; ++offs) { 
    214         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     211    STRING_ITER_INIT(interp, &iter); 
     212    while (iter.charpos < len) { 
     213        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    215214        if (c >= 128) 
    216215            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LOSSY_CONVERSION, 
    217216                    "can't convert unicode string to ascii"); 
     
    493492            return ret_val < 0 ? -1 : 1; 
    494493    } 
    495494    else { 
    496         UINTVAL offs; 
    497         ENCODING_ITER_INIT(interp, rhs, &iter); 
    498         for (offs = 0; offs < min_len; ++offs) { 
    499             const UINTVAL cl = ENCODING_GET_BYTE(interp, lhs, offs); 
    500             const UINTVAL cr = iter.get_and_advance(interp, &iter); 
     495        STRING_ITER_INIT(interp, &iter); 
     496        while (iter.charpos < min_len) { 
     497            const UINTVAL cl = ENCODING_GET_BYTE(interp, lhs, iter.charpos); 
     498            const UINTVAL cr = STRING_ITER_GET_AND_ADVANCE(interp, rhs, &iter); 
    501499            if (cl != cr) 
    502500                return cl < cr ? -1 : 1; 
    503501        } 
     
    531529    UINTVAL offs) 
    532530{ 
    533531    ASSERT_ARGS(mixed_cs_index) 
     532    String_iter start, end; 
    534533 
    535     if (search->strlen <= src->strlen) { 
    536         String_iter src_iter, search_iter; 
    537         const UINTVAL maxpos = src->strlen - search->strlen + 1; 
    538         const UINTVAL cfirst = Parrot_str_indexed(interp, search, 0); 
    539  
    540         ENCODING_ITER_INIT(interp, src, &src_iter); 
    541         src_iter.set_position(interp, &src_iter, offs); 
    542         ENCODING_ITER_INIT(interp, search, &search_iter); 
    543  
    544         while (src_iter.charpos < maxpos) { 
    545             if (cfirst == src_iter.get_and_advance(interp, &src_iter)) { 
    546                 const INTVAL next_pos = src_iter.charpos; 
    547                 const INTVAL next_byte = src_iter.bytepos; 
    548                 UINTVAL len; 
    549                 search_iter.set_position(interp, &search_iter, 1); 
    550                 for (len = search->strlen - 1; len; --len) { 
    551                     if ((src_iter.get_and_advance(interp, &src_iter)) != 
    552                             (search_iter.get_and_advance(interp, &search_iter))) 
    553                         break; 
    554                 } 
    555                 if (len == 0) 
    556                     return next_pos - 1; 
    557                 src_iter.charpos = next_pos; 
    558                 src_iter.bytepos = next_byte; 
    559             } 
    560         } 
    561     } 
    562     return -1; 
     534    STRING_ITER_INIT(interp, &start); 
     535    STRING_ITER_SET_POSITION(interp, src, &start, offs); 
     536 
     537    return Parrot_str_iter_index(interp, src, &start, &end, search); 
    563538} 
    564539 
    565540/* 
     
    638613validate(PARROT_INTERP, ARGIN(const STRING *src)) 
    639614{ 
    640615    ASSERT_ARGS(validate) 
    641     INTVAL      offset; 
    642616    String_iter iter; 
    643617    const INTVAL length = Parrot_str_length(interp, src); 
    644618 
    645     ENCODING_ITER_INIT(interp, src, &iter); 
    646     for (offset = 0; offset < length; ++offset) { 
    647         const UINTVAL codepoint = iter.get_and_advance(interp, &iter); 
     619    STRING_ITER_INIT(interp, &iter); 
     620    while (iter.charpos < length) { 
     621        const UINTVAL codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    648622        if (codepoint >= 0x80) 
    649623            return 0; 
    650624    } 
  • 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 8e965fa..b795e0d 100644
    a b  
    178178to_iso_8859_1(PARROT_INTERP, ARGIN(const STRING *src)) 
    179179{ 
    180180    ASSERT_ARGS(to_iso_8859_1) 
    181     UINTVAL offs, src_len; 
     181    UINTVAL src_len; 
    182182    String_iter iter; 
    183183    /* iso-8859-1 is never bigger then source */ 
    184184    STRING * dest = Parrot_str_clone(interp, src); 
    185185 
    186     ENCODING_ITER_INIT(interp, src, &iter); 
     186    STRING_ITER_INIT(interp, &iter); 
    187187    src_len = src->strlen; 
    188188    dest->bufused = src_len; 
    189     dest->charset = Parrot_iso_8859_1_charset_ptr; 
    190     dest->encoding = Parrot_fixed_8_encoding_ptr; 
    191     for (offs = 0; offs < src_len; ++offs) { 
    192         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     189    while (iter.charpos < src_len) { 
     190        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    193191        if (c >= 0x100) 
    194192            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LOSSY_CONVERSION, 
    195193                "lossy conversion to iso-8559-1"); 
    196194 
    197         ENCODING_SET_BYTE(interp, dest, offs, c); 
     195        Parrot_fixed_8_encoding_ptr->set_byte(interp, dest, iter.charpos - 1, c); 
    198196    } 
     197    dest->charset = Parrot_iso_8859_1_charset_ptr; 
     198    dest->encoding = Parrot_fixed_8_encoding_ptr; 
    199199    return dest; 
    200200} 
    201201 
     
    221221    dest->charset = Parrot_unicode_charset_ptr; 
    222222    dest->encoding = CHARSET_GET_PREFERRED_ENCODING(interp, dest); 
    223223    Parrot_gc_reallocate_string_storage(interp, dest, src->strlen); 
    224     ENCODING_ITER_INIT(interp, dest, &iter); 
    225     for (offs = 0; offs < src->strlen; ++offs) { 
    226         const UINTVAL c = ENCODING_GET_BYTE(interp, src, offs); 
     224    STRING_ITER_INIT(interp, &iter); 
     225    while (iter.charpos < src->strlen) { 
     226        const UINTVAL c = ENCODING_GET_BYTE(interp, src, iter.charpos); 
    227227 
    228228        if (iter.bytepos >= Buffer_buflen(dest) - 4) { 
    229             UINTVAL need = (UINTVAL)((src->strlen - offs) * 1.5); 
     229            UINTVAL need = (UINTVAL)((src->strlen - iter.charpos) * 1.5); 
    230230            if (need < 16) 
    231231                need = 16; 
    232232            Parrot_gc_reallocate_string_storage(interp, dest, 
    233233                    Buffer_buflen(dest) + need); 
    234234        } 
    235         iter.set_and_advance(interp, &iter, c); 
     235        STRING_ITER_SET_AND_ADVANCE(interp, dest, &iter, c); 
    236236    } 
    237237    dest->bufused = iter.bytepos; 
    238238    dest->strlen  = iter.charpos; 
  • src/string/charset/unicode.c

    diff --git a/src/string/charset/unicode.c b/src/string/charset/unicode.c
    index e1de74c..03555e2 100644
    a b  
    651651{ 
    652652    ASSERT_ARGS(compare) 
    653653    String_iter l_iter, r_iter; 
    654     UINTVAL offs, cl, cr, min_len, l_len, r_len; 
     654    UINTVAL min_len, l_len, r_len; 
    655655 
    656656    /* TODO make optimized equal - strings are equal length then already */ 
    657     ENCODING_ITER_INIT(interp, lhs, &l_iter); 
    658     ENCODING_ITER_INIT(interp, rhs, &r_iter); 
     657    STRING_ITER_INIT(interp, &l_iter); 
     658    STRING_ITER_INIT(interp, &r_iter); 
    659659 
    660660    l_len = lhs->strlen; 
    661661    r_len = rhs->strlen; 
    662662 
    663663    min_len = l_len > r_len ? r_len : l_len; 
    664664 
    665     for (offs = 0; offs < min_len; ++offs) { 
    666         cl = l_iter.get_and_advance(interp, &l_iter); 
    667         cr = r_iter.get_and_advance(interp, &r_iter); 
     665    while (l_iter.charpos < min_len) { 
     666        const UINTVAL cl = STRING_ITER_GET_AND_ADVANCE(interp, lhs, &l_iter); 
     667        const UINTVAL cr = STRING_ITER_GET_AND_ADVANCE(interp, rhs, &r_iter); 
    668668 
    669669        if (cl != cr) 
    670670            return cl < cr ? -1 : 1; 
     
    716716validate(PARROT_INTERP, ARGIN(const STRING *src)) 
    717717{ 
    718718    ASSERT_ARGS(validate) 
    719     INTVAL      offset; 
    720719    String_iter iter; 
    721720    const INTVAL length = Parrot_str_length(interp, src); 
    722721 
    723     ENCODING_ITER_INIT(interp, src, &iter); 
    724     for (offset = 0; offset < length; ++offset) { 
    725         const UINTVAL codepoint = iter.get_and_advance(interp, &iter); 
     722    STRING_ITER_INIT(interp, &iter); 
     723    while (iter.charpos < length) { 
     724        const UINTVAL codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    726725        /* Check for Unicode non-characters */ 
    727726        if (codepoint >= 0xfdd0 
    728727        && (codepoint <= 0xfdef || (codepoint & 0xfffe) == 0xfffe) 
     
    877876    ASSERT_ARGS(find_cclass) 
    878877    String_iter iter; 
    879878    UINTVAL     codepoint; 
    880     UINTVAL     pos = offset; 
    881879    UINTVAL     end = offset + count; 
    882880 
    883     ENCODING_ITER_INIT(interp, src, &iter); 
    884  
    885     iter.set_position(interp, &iter, pos); 
     881    STRING_ITER_INIT(interp, &iter); 
     882    STRING_ITER_SET_POSITION(interp, src, &iter, offset); 
    886883 
    887884    end = src->strlen < end ? src->strlen : end; 
    888885 
    889     for (; pos < end; ++pos) { 
    890         codepoint = iter.get_and_advance(interp, &iter); 
     886    while (iter.charpos < end) { 
     887        codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    891888        if (codepoint >= 256) { 
    892889            if (u_iscclass(interp, codepoint, flags)) 
    893                     return pos; 
     890                    return iter.charpos - 1; 
    894891        } 
    895892        else { 
    896893            if (Parrot_iso_8859_1_typetable[codepoint] & flags) 
    897                 return pos; 
     894                return iter.charpos - 1; 
    898895        } 
    899896    } 
    900897 
     
    920917    ASSERT_ARGS(find_not_cclass) 
    921918    String_iter iter; 
    922919    UINTVAL     codepoint; 
    923     UINTVAL     pos = offset; 
    924920    UINTVAL     end = offset + count; 
    925921    int         bit; 
    926922 
    927     if (pos > src->strlen) { 
     923    if (offset > src->strlen) { 
    928924        /* XXX: Throw in this case? */ 
    929925        return offset + count; 
    930926    } 
    931927 
    932     ENCODING_ITER_INIT(interp, src, &iter); 
     928    STRING_ITER_INIT(interp, &iter); 
    933929 
    934     if (pos) 
    935         iter.set_position(interp, &iter, pos); 
     930    if (offset) 
     931        STRING_ITER_SET_POSITION(interp, src, &iter, offset); 
    936932 
    937933    end = src->strlen < end ? src->strlen : end; 
    938934 
    939935    if (flags == enum_cclass_any) 
    940936        return end; 
    941937 
    942     for (; pos < end; ++pos) { 
    943         codepoint = iter.get_and_advance(interp, &iter); 
     938    while (iter.charpos < end) { 
     939        codepoint = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    944940        if (codepoint >= 256) { 
    945941            for (bit = enum_cclass_uppercase; 
    946942                    bit <= enum_cclass_word ; bit <<= 1) { 
    947943                if ((bit & flags) && !u_iscclass(interp, codepoint, bit)) 
    948                     return pos; 
     944                    return iter.charpos - 1; 
    949945            } 
    950946        } 
    951947        else { 
    952948            if (!(Parrot_iso_8859_1_typetable[codepoint] & flags)) 
    953                 return pos; 
     949                return iter.charpos - 1; 
    954950        } 
    955951    } 
    956952 
     
    978974 
    979975    dest->strlen = 1; 
    980976 
    981     ENCODING_ITER_INIT(interp, dest, &iter); 
    982     iter.set_and_advance(interp, &iter, codepoint); 
     977    STRING_ITER_INIT(interp, &iter); 
     978    STRING_ITER_SET_AND_ADVANCE(interp, dest, &iter, codepoint); 
    983979    dest->bufused = iter.bytepos; 
    984980 
    985981    return dest; 
     
    1002998{ 
    1003999    ASSERT_ARGS(compute_hash) 
    10041000    String_iter iter; 
    1005     UINTVAL     offs; 
    10061001    size_t      hashval = seed; 
    10071002 
    1008     ENCODING_ITER_INIT(interp, src, &iter); 
     1003    STRING_ITER_INIT(interp, &iter); 
    10091004 
    1010     for (offs = 0; offs < src->strlen; ++offs) { 
    1011         const UINTVAL c = iter.get_and_advance(interp, &iter); 
     1005    while (iter.charpos < src->strlen) { 
     1006        const UINTVAL c = STRING_ITER_GET_AND_ADVANCE(interp, src, &iter); 
    10121007        hashval += hashval << 5; 
    10131008        hashval += c; 
    10141009    } 
  • src/string/encoding/fixed_8.c

    diff --git a/src/string/encoding/fixed_8.c b/src/string/encoding/fixed_8.c
    index 52008a5..ec51147 100644
    a b  
    4646        __attribute__nonnull__(2) 
    4747        FUNC_MODIFIES(*iter); 
    4848 
     49static UINTVAL fixed8_iter_get(PARROT_INTERP, 
     50    ARGIN(const STRING *str), 
     51    ARGIN(const String_iter *iter), 
     52    INTVAL offset) 
     53        __attribute__nonnull__(1) 
     54        __attribute__nonnull__(2) 
     55        __attribute__nonnull__(3); 
     56 
     57static UINTVAL fixed8_iter_get_and_advance(PARROT_INTERP, 
     58    ARGIN(const STRING *str), 
     59    ARGMOD(String_iter *iter)) 
     60        __attribute__nonnull__(1) 
     61        __attribute__nonnull__(2) 
     62        __attribute__nonnull__(3) 
     63        FUNC_MODIFIES(*iter); 
     64 
     65static void fixed8_iter_set_and_advance(PARROT_INTERP, 
     66    ARGMOD(STRING *str), 
     67    ARGMOD(String_iter *iter), 
     68    UINTVAL c) 
     69        __attribute__nonnull__(1) 
     70        __attribute__nonnull__(2) 
     71        __attribute__nonnull__(3) 
     72        FUNC_MODIFIES(*str) 
     73        FUNC_MODIFIES(*iter); 
     74 
     75static void fixed8_iter_set_position(SHIM_INTERP, 
     76    ARGIN(const STRING *str), 
     77    ARGMOD(String_iter *iter), 
     78    UINTVAL pos) 
     79        __attribute__nonnull__(2) 
     80        __attribute__nonnull__(3) 
     81        FUNC_MODIFIES(*iter); 
     82 
     83static void fixed8_iter_skip(SHIM_INTERP, 
     84    ARGIN(const STRING *str), 
     85    ARGMOD(String_iter *iter), 
     86    INTVAL skip) 
     87        __attribute__nonnull__(2) 
     88        __attribute__nonnull__(3) 
     89        FUNC_MODIFIES(*iter); 
     90 
    4991static void fixed8_set_next(PARROT_INTERP, 
    5092    ARGMOD(String_iter *iter), 
    5193    UINTVAL c) 
     
    125167#define ASSERT_ARGS_fixed8_get_next __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    126168       PARROT_ASSERT_ARG(interp) \ 
    127169    , PARROT_ASSERT_ARG(iter)) 
     170#define ASSERT_ARGS_fixed8_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     171       PARROT_ASSERT_ARG(interp) \ 
     172    , PARROT_ASSERT_ARG(str) \ 
     173    , PARROT_ASSERT_ARG(iter)) 
     174#define ASSERT_ARGS_fixed8_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     175       PARROT_ASSERT_ARG(interp) \ 
     176    , PARROT_ASSERT_ARG(str) \ 
     177    , PARROT_ASSERT_ARG(iter)) 
     178#define ASSERT_ARGS_fixed8_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     179       PARROT_ASSERT_ARG(interp) \ 
     180    , PARROT_ASSERT_ARG(str) \ 
     181    , PARROT_ASSERT_ARG(iter)) 
     182#define ASSERT_ARGS_fixed8_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     183       PARROT_ASSERT_ARG(str) \ 
     184    , PARROT_ASSERT_ARG(iter)) 
     185#define ASSERT_ARGS_fixed8_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     186       PARROT_ASSERT_ARG(str) \ 
     187    , PARROT_ASSERT_ARG(iter)) 
    128188#define ASSERT_ARGS_fixed8_set_next __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    129189       PARROT_ASSERT_ARG(interp) \ 
    130190    , PARROT_ASSERT_ARG(iter)) 
     
    375435 
    376436/* 
    377437 
     438=item C<static UINTVAL fixed8_iter_get(PARROT_INTERP, const STRING *str, const 
     439String_iter *iter, INTVAL offset)> 
     440 
     441Get the character at C<iter> plus C<offset>. 
     442 
     443=cut 
     444 
     445*/ 
     446 
     447static UINTVAL 
     448fixed8_iter_get(PARROT_INTERP, 
     449    ARGIN(const STRING *str), ARGIN(const String_iter *iter), INTVAL offset) 
     450{ 
     451    ASSERT_ARGS(fixed8_iter_get) 
     452    return get_byte(interp, str, iter->charpos + offset); 
     453} 
     454 
     455/* 
     456 
     457=item C<static void fixed8_iter_skip(PARROT_INTERP, const STRING *str, 
     458String_iter *iter, INTVAL skip)> 
     459 
     460Moves the string iterator C<i> by C<skip> characters. 
     461 
     462=cut 
     463 
     464*/ 
     465 
     466static void 
     467fixed8_iter_skip(SHIM_INTERP, 
     468    ARGIN(const STRING *str), ARGMOD(String_iter *iter), INTVAL skip) 
     469{ 
     470    ASSERT_ARGS(fixed8_iter_skip) 
     471    iter->bytepos += skip; 
     472    iter->charpos += skip; 
     473    PARROT_ASSERT(iter->bytepos <= Buffer_buflen(str)); 
     474} 
     475 
     476/* 
     477 
     478=item C<static UINTVAL fixed8_iter_get_and_advance(PARROT_INTERP, const STRING 
     479*str, String_iter *iter)> 
     480 
     481Moves the string iterator C<i> to the next codepoint. 
     482 
     483=cut 
     484 
     485*/ 
     486 
     487static UINTVAL 
     488fixed8_iter_get_and_advance(PARROT_INTERP, 
     489    ARGIN(const STRING *str), ARGMOD(String_iter *iter)) 
     490{ 
     491    ASSERT_ARGS(fixed8_iter_get_and_advance) 
     492    const UINTVAL c = get_byte(interp, str, iter->charpos++); 
     493    iter->bytepos++; 
     494    return c; 
     495} 
     496 
     497/* 
     498 
     499=item C<static void fixed8_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     500String_iter *iter, UINTVAL c)> 
     501 
     502With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     503next position in the string. 
     504 
     505=cut 
     506 
     507*/ 
     508 
     509static void 
     510fixed8_iter_set_and_advance(PARROT_INTERP, 
     511    ARGMOD(STRING *str), ARGMOD(String_iter *iter), UINTVAL c) 
     512{ 
     513    ASSERT_ARGS(fixed8_iter_set_and_advance) 
     514    set_byte(interp, str, iter->charpos++, c); 
     515    iter->bytepos++; 
     516} 
     517 
     518/* 
     519 
     520=item C<static void fixed8_iter_set_position(PARROT_INTERP, const STRING *str, 
     521String_iter *iter, UINTVAL pos)> 
     522 
     523Moves the string iterator C<i> to the position C<n> in the string. 
     524 
     525=cut 
     526 
     527*/ 
     528 
     529static void 
     530fixed8_iter_set_position(SHIM_INTERP, 
     531    ARGIN(const STRING *str), ARGMOD(String_iter *iter), UINTVAL pos) 
     532{ 
     533    ASSERT_ARGS(fixed8_iter_set_position) 
     534    iter->bytepos = iter->charpos = pos; 
     535    PARROT_ASSERT(pos <= Buffer_buflen(str)); 
     536} 
     537 
     538/* 
     539 
    378540=item C<static UINTVAL fixed8_get_next(PARROT_INTERP, String_iter *iter)> 
    379541 
    380542Moves the string iterator C<i> to the next codepoint. 
     
    511673        bytes, 
    512674        iter_init, 
    513675        find_cclass, 
    514         fixed_8_hash 
     676        fixed_8_hash, 
     677        fixed8_iter_get, 
     678        fixed8_iter_skip, 
     679        fixed8_iter_get_and_advance, 
     680        fixed8_iter_set_and_advance, 
     681        fixed8_iter_set_position 
    515682    }; 
    516683 
    517684    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 1c9cd48..6e2ec93 100644
    a b  
    120120        __attribute__nonnull__(1) 
    121121        __attribute__nonnull__(2); 
    122122 
     123static UINTVAL ucs2_iter_get(PARROT_INTERP, 
     124    ARGIN(const STRING *str), 
     125    ARGIN(const String_iter *i), 
     126    INTVAL offset) 
     127        __attribute__nonnull__(1) 
     128        __attribute__nonnull__(2) 
     129        __attribute__nonnull__(3); 
     130 
     131static UINTVAL ucs2_iter_get_and_advance(PARROT_INTERP, 
     132    ARGIN(const STRING *str), 
     133    ARGMOD(String_iter *i)) 
     134        __attribute__nonnull__(1) 
     135        __attribute__nonnull__(2) 
     136        __attribute__nonnull__(3) 
     137        FUNC_MODIFIES(*i); 
     138 
     139static void ucs2_iter_set_and_advance(PARROT_INTERP, 
     140    ARGMOD(STRING *str), 
     141    ARGMOD(String_iter *i), 
     142    UINTVAL c) 
     143        __attribute__nonnull__(1) 
     144        __attribute__nonnull__(2) 
     145        __attribute__nonnull__(3) 
     146        FUNC_MODIFIES(*str) 
     147        FUNC_MODIFIES(*i); 
     148 
     149static void ucs2_iter_set_position(PARROT_INTERP, 
     150    ARGIN(const STRING *str), 
     151    ARGMOD(String_iter *i), 
     152    UINTVAL n) 
     153        __attribute__nonnull__(1) 
     154        __attribute__nonnull__(2) 
     155        __attribute__nonnull__(3) 
     156        FUNC_MODIFIES(*i); 
     157 
     158static void ucs2_iter_skip(PARROT_INTERP, 
     159    ARGIN(const STRING *str), 
     160    ARGMOD(String_iter *i), 
     161    INTVAL skip) 
     162        __attribute__nonnull__(1) 
     163        __attribute__nonnull__(2) 
     164        __attribute__nonnull__(3) 
     165        FUNC_MODIFIES(*i); 
     166 
    123167static void ucs2_set_position(SHIM_INTERP, 
    124168    ARGMOD(String_iter *i), 
    125169    UINTVAL n) 
     
    161205#define ASSERT_ARGS_ucs2_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    162206       PARROT_ASSERT_ARG(interp) \ 
    163207    , PARROT_ASSERT_ARG(s)) 
     208#define ASSERT_ARGS_ucs2_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     209       PARROT_ASSERT_ARG(interp) \ 
     210    , PARROT_ASSERT_ARG(str) \ 
     211    , PARROT_ASSERT_ARG(i)) 
     212#define ASSERT_ARGS_ucs2_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     213       PARROT_ASSERT_ARG(interp) \ 
     214    , PARROT_ASSERT_ARG(str) \ 
     215    , PARROT_ASSERT_ARG(i)) 
     216#define ASSERT_ARGS_ucs2_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     217       PARROT_ASSERT_ARG(interp) \ 
     218    , PARROT_ASSERT_ARG(str) \ 
     219    , PARROT_ASSERT_ARG(i)) 
     220#define ASSERT_ARGS_ucs2_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     221       PARROT_ASSERT_ARG(interp) \ 
     222    , PARROT_ASSERT_ARG(str) \ 
     223    , PARROT_ASSERT_ARG(i)) 
     224#define ASSERT_ARGS_ucs2_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     225       PARROT_ASSERT_ARG(interp) \ 
     226    , PARROT_ASSERT_ARG(str) \ 
     227    , PARROT_ASSERT_ARG(i)) 
    164228#define ASSERT_ARGS_ucs2_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    165229       PARROT_ASSERT_ARG(i)) 
    166230/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     
    323387        String_iter iter; 
    324388        UINTVAL start; 
    325389 
    326         iter_init(interp, src, &iter); 
    327         iter.set_position(interp, &iter, offset); 
     390        STRING_ITER_INIT(interp, &iter); 
     391        ucs2_iter_set_position(interp, src, &iter, offset); 
    328392        start = iter.bytepos; 
    329393        return_string->strstart = (char *)return_string->strstart + start; 
    330         iter.set_position(interp, &iter, offset + count); 
     394        ucs2_iter_set_position(interp, src, &iter, offset + count); 
    331395        return_string->bufused = iter.bytepos - start; 
    332396    } 
    333397#endif 
     
    402466 
    403467/* 
    404468 
     469=item C<static UINTVAL ucs2_iter_get(PARROT_INTERP, const STRING *str, const 
     470String_iter *i, INTVAL offset)> 
     471 
     472Get the character at C<i> + C<offset>. 
     473 
     474=cut 
     475 
     476*/ 
     477 
     478static UINTVAL 
     479ucs2_iter_get(PARROT_INTERP, 
     480    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     481{ 
     482    ASSERT_ARGS(ucs2_iter_get) 
     483    return get_codepoint(interp, str, i->charpos + offset); 
     484} 
     485 
     486/* 
     487 
     488=item C<static void ucs2_iter_skip(PARROT_INTERP, const STRING *str, String_iter 
     489*i, INTVAL skip)> 
     490 
     491Moves the string iterator C<i> by C<skip> characters. 
     492 
     493=cut 
     494 
     495*/ 
     496 
     497static void 
     498ucs2_iter_skip(PARROT_INTERP, 
     499    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     500{ 
     501    ASSERT_ARGS(ucs2_iter_skip) 
     502    UNUSED(str); 
     503 
     504#if PARROT_HAS_ICU 
     505    i->charpos += skip; 
     506    i->bytepos += skip * sizeof (UChar); 
     507#else 
     508    UNUSED(i); 
     509    UNUSED(skip); 
     510    no_ICU_lib(interp); 
     511#endif 
     512} 
     513 
     514/* 
     515 
     516=item C<static UINTVAL ucs2_iter_get_and_advance(PARROT_INTERP, const STRING 
     517*str, String_iter *i)> 
     518 
     519Moves the string iterator C<i> to the next UCS-2 codepoint. 
     520 
     521=cut 
     522 
     523*/ 
     524 
     525static UINTVAL 
     526ucs2_iter_get_and_advance(PARROT_INTERP, 
     527    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     528{ 
     529    ASSERT_ARGS(ucs2_iter_get_and_advance) 
     530 
     531#if PARROT_HAS_ICU 
     532    UChar * const s = (UChar*) str->strstart; 
     533    size_t pos = i->bytepos / sizeof (UChar); 
     534 
     535    /* TODO either make sure that we don't go past end or use SAFE 
     536     *      iter versions 
     537     */ 
     538    const UChar c = s[pos++]; 
     539    i->charpos++; 
     540    i->bytepos = pos * sizeof (UChar); 
     541    return c; 
     542#else 
     543    UNUSED(str); 
     544    UNUSED(i); 
     545    no_ICU_lib(interp); 
     546    return (UINTVAL)0; /* Stop the static analyzers from panicing */ 
     547#endif 
     548} 
     549 
     550/* 
     551 
     552=item C<static void ucs2_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     553String_iter *i, UINTVAL c)> 
     554 
     555With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     556next position in the string. 
     557 
     558=cut 
     559 
     560*/ 
     561 
     562static void 
     563ucs2_iter_set_and_advance(PARROT_INTERP, 
     564    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     565{ 
     566    ASSERT_ARGS(ucs2_iter_set_and_advance) 
     567 
     568#if PARROT_HAS_ICU 
     569    UChar * const s = (UChar*) str->strstart; 
     570    UINTVAL pos = i->bytepos / sizeof (UChar); 
     571    s[pos++] = (UChar)c; 
     572    i->charpos++; 
     573    i->bytepos = pos * sizeof (UChar); 
     574#else 
     575    UNUSED(str); 
     576    UNUSED(i); 
     577    UNUSED(c); 
     578    no_ICU_lib(interp); 
     579#endif 
     580} 
     581 
     582/* 
     583 
     584=item C<static void ucs2_iter_set_position(PARROT_INTERP, const STRING *str, 
     585String_iter *i, UINTVAL n)> 
     586 
     587Moves the string iterator C<i> to the position C<n> in the string. 
     588 
     589=cut 
     590 
     591*/ 
     592 
     593static void 
     594ucs2_iter_set_position(PARROT_INTERP, 
     595    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n) 
     596{ 
     597    ASSERT_ARGS(ucs2_iter_set_position) 
     598    UNUSED(str); 
     599 
     600#if PARROT_HAS_ICU 
     601    i->charpos = n; 
     602    i->bytepos = n * sizeof (UChar); 
     603#else 
     604    UNUSED(i); 
     605    UNUSED(n); 
     606    no_ICU_lib(interp); 
     607#endif 
     608} 
     609 
     610/* 
     611 
    405612=item C<static UINTVAL ucs2_decode_and_advance(PARROT_INTERP, String_iter *i)> 
    406613 
    407614Moves the string iterator C<i> to the next UCS-2 codepoint. 
     
    592799        bytes, 
    593800        iter_init, 
    594801        find_cclass, 
    595         ucs2_hash 
     802        ucs2_hash, 
     803        ucs2_iter_get, 
     804        ucs2_iter_skip, 
     805        ucs2_iter_get_and_advance, 
     806        ucs2_iter_set_and_advance, 
     807        ucs2_iter_set_position 
    596808    }; 
    597809    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    598810    Parrot_register_encoding(interp, "ucs2", return_encoding); 
  • src/string/encoding/ucs4.c

    diff --git a/src/string/encoding/ucs4.c b/src/string/encoding/ucs4.c
    index c608ef8..e4d0409 100644
    a b  
    123123        __attribute__nonnull__(1) 
    124124        __attribute__nonnull__(2); 
    125125 
     126static UINTVAL ucs4_iter_get(PARROT_INTERP, 
     127    ARGIN(const STRING *str), 
     128    ARGIN(const String_iter *i), 
     129    INTVAL offset) 
     130        __attribute__nonnull__(1) 
     131        __attribute__nonnull__(2) 
     132        __attribute__nonnull__(3); 
     133 
     134static UINTVAL ucs4_iter_get_and_advance(PARROT_INTERP, 
     135    ARGIN(const STRING *str), 
     136    ARGMOD(String_iter *i)) 
     137        __attribute__nonnull__(1) 
     138        __attribute__nonnull__(2) 
     139        __attribute__nonnull__(3) 
     140        FUNC_MODIFIES(*i); 
     141 
     142static void ucs4_iter_set_and_advance(PARROT_INTERP, 
     143    ARGMOD(STRING *str), 
     144    ARGMOD(String_iter *i), 
     145    UINTVAL c) 
     146        __attribute__nonnull__(1) 
     147        __attribute__nonnull__(2) 
     148        __attribute__nonnull__(3) 
     149        FUNC_MODIFIES(*str) 
     150        FUNC_MODIFIES(*i); 
     151 
     152static void ucs4_iter_set_position(PARROT_INTERP, 
     153    ARGIN(const STRING *str), 
     154    ARGMOD(String_iter *i), 
     155    UINTVAL n) 
     156        __attribute__nonnull__(1) 
     157        __attribute__nonnull__(2) 
     158        __attribute__nonnull__(3) 
     159        FUNC_MODIFIES(*i); 
     160 
     161static void ucs4_iter_skip(PARROT_INTERP, 
     162    ARGIN(const STRING *str), 
     163    ARGMOD(String_iter *i), 
     164    INTVAL skip) 
     165        __attribute__nonnull__(1) 
     166        __attribute__nonnull__(2) 
     167        __attribute__nonnull__(3) 
     168        FUNC_MODIFIES(*i); 
     169 
    126170static void ucs4_set_position(PARROT_INTERP, 
    127171    ARGMOD(String_iter *i), 
    128172    UINTVAL n) 
     
    167211#define ASSERT_ARGS_ucs4_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    168212       PARROT_ASSERT_ARG(interp) \ 
    169213    , PARROT_ASSERT_ARG(s)) 
     214#define ASSERT_ARGS_ucs4_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     215       PARROT_ASSERT_ARG(interp) \ 
     216    , PARROT_ASSERT_ARG(str) \ 
     217    , PARROT_ASSERT_ARG(i)) 
     218#define ASSERT_ARGS_ucs4_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     219       PARROT_ASSERT_ARG(interp) \ 
     220    , PARROT_ASSERT_ARG(str) \ 
     221    , PARROT_ASSERT_ARG(i)) 
     222#define ASSERT_ARGS_ucs4_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     223       PARROT_ASSERT_ARG(interp) \ 
     224    , PARROT_ASSERT_ARG(str) \ 
     225    , PARROT_ASSERT_ARG(i)) 
     226#define ASSERT_ARGS_ucs4_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     227       PARROT_ASSERT_ARG(interp) \ 
     228    , PARROT_ASSERT_ARG(str) \ 
     229    , PARROT_ASSERT_ARG(i)) 
     230#define ASSERT_ARGS_ucs4_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     231       PARROT_ASSERT_ARG(interp) \ 
     232    , PARROT_ASSERT_ARG(str) \ 
     233    , PARROT_ASSERT_ARG(i)) 
    170234#define ASSERT_ARGS_ucs4_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    171235       PARROT_ASSERT_ARG(interp) \ 
    172236    , PARROT_ASSERT_ARG(i)) 
     
    414478 
    415479/* 
    416480 
     481=item C<static UINTVAL ucs4_iter_get(PARROT_INTERP, const STRING *str, const 
     482String_iter *i, INTVAL offset)> 
     483 
     484Get the character at C<i> + C<offset>. 
     485 
     486=cut 
     487 
     488*/ 
     489 
     490static UINTVAL 
     491ucs4_iter_get(PARROT_INTERP, 
     492    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     493{ 
     494    ASSERT_ARGS(ucs4_iter_get) 
     495    return get_codepoint(interp, str, i->charpos + offset); 
     496} 
     497 
     498/* 
     499 
     500=item C<static void ucs4_iter_skip(PARROT_INTERP, const STRING *str, String_iter 
     501*i, INTVAL skip)> 
     502 
     503Moves the string iterator C<i> by C<skip> characters. 
     504 
     505=cut 
     506 
     507*/ 
     508 
     509static void 
     510ucs4_iter_skip(PARROT_INTERP, 
     511    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     512{ 
     513    ASSERT_ARGS(ucs4_iter_skip) 
     514    UNUSED(str); 
     515 
     516#if PARROT_HAS_ICU 
     517    i->charpos += skip; 
     518    i->bytepos += skip * sizeof (UChar32); 
     519#else 
     520    UNUSED(i); 
     521    UNUSED(skip); 
     522    no_ICU_lib(interp); 
     523#endif 
     524} 
     525 
     526/* 
     527 
     528=item C<static UINTVAL ucs4_iter_get_and_advance(PARROT_INTERP, const STRING 
     529*str, String_iter *i)> 
     530 
     531Moves the string iterator C<i> to the next codepoint. 
     532 
     533=cut 
     534 
     535*/ 
     536 
     537static UINTVAL 
     538ucs4_iter_get_and_advance(PARROT_INTERP, 
     539    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     540{ 
     541    ASSERT_ARGS(ucs4_iter_get_and_advance) 
     542 
     543#if PARROT_HAS_ICU 
     544    const UChar32 * const s = (const UChar32*) str->strstart; 
     545    const UChar32 c = s[i->charpos++]; 
     546    i->bytepos += sizeof (UChar32); 
     547    return c; 
     548#else 
     549    UNUSED(str); 
     550    UNUSED(i); 
     551    no_ICU_lib(interp); 
     552    return (UINTVAL)0; /* Stop the static analyzers from panicing */ 
     553#endif 
     554} 
     555 
     556/* 
     557 
     558=item C<static void ucs4_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     559String_iter *i, UINTVAL c)> 
     560 
     561With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     562next position in the string. 
     563 
     564=cut 
     565 
     566*/ 
     567 
     568static void 
     569ucs4_iter_set_and_advance(PARROT_INTERP, 
     570    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     571{ 
     572    ASSERT_ARGS(ucs4_iter_set_and_advance) 
     573 
     574#if PARROT_HAS_ICU 
     575    UChar32 * const s = (UChar32*) str->strstart; 
     576    s[i->charpos++] = (UChar32)c; 
     577    i->bytepos += sizeof (UChar32); 
     578#else 
     579    UNUSED(str); 
     580    UNUSED(i); 
     581    UNUSED(c); 
     582    no_ICU_lib(interp); 
     583#endif 
     584} 
     585 
     586/* 
     587 
     588=item C<static void ucs4_iter_set_position(PARROT_INTERP, const STRING *str, 
     589String_iter *i, UINTVAL n)> 
     590 
     591Moves the string iterator C<i> to the position C<n> in the string. 
     592 
     593=cut 
     594 
     595*/ 
     596 
     597static void 
     598ucs4_iter_set_position(PARROT_INTERP, 
     599    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n) 
     600{ 
     601    ASSERT_ARGS(ucs4_iter_set_position) 
     602    UNUSED(str); 
     603 
     604#if PARROT_HAS_ICU 
     605    i->charpos = n; 
     606    i->bytepos = n * sizeof (UChar32); 
     607#else 
     608    UNUSED(i); 
     609    UNUSED(n); 
     610    no_ICU_lib(interp); 
     611#endif 
     612} 
     613 
     614/* 
     615 
    417616=item C<static UINTVAL ucs4_decode_and_advance(PARROT_INTERP, String_iter *i)> 
    418617 
    419618Moves the string iterator C<i> to the next UCS-4 codepoint. 
     
    580779        iter_init, 
    581780        find_cclass, 
    582781#if PARROT_HAS_ICU 
    583         ucs4_hash 
     782        ucs4_hash, 
    584783#else 
    585         NULL 
     784        NULL, 
    586785#endif 
     786        ucs4_iter_get, 
     787        ucs4_iter_skip, 
     788        ucs4_iter_get_and_advance, 
     789        ucs4_iter_set_and_advance, 
     790        ucs4_iter_set_position 
    587791    }; 
    588792    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    589793    Parrot_register_encoding(interp, "ucs4", return_encoding); 
  • src/string/encoding/utf16.c

    diff --git a/src/string/encoding/utf16.c b/src/string/encoding/utf16.c
    index 0c5ec2d..2570de5 100644
    a b  
    107107        __attribute__nonnull__(2) 
    108108        FUNC_MODIFIES(*i); 
    109109 
     110static UINTVAL utf16_iter_get(PARROT_INTERP, 
     111    ARGIN(const STRING *str), 
     112    ARGIN(const String_iter *i), 
     113    INTVAL offset) 
     114        __attribute__nonnull__(1) 
     115        __attribute__nonnull__(2) 
     116        __attribute__nonnull__(3); 
     117 
     118PARROT_WARN_UNUSED_RESULT 
     119static UINTVAL utf16_iter_get_and_advance(PARROT_INTERP, 
     120    ARGIN(const STRING *str), 
     121    ARGMOD(String_iter *i)) 
     122        __attribute__nonnull__(1) 
     123        __attribute__nonnull__(2) 
     124        __attribute__nonnull__(3) 
     125        FUNC_MODIFIES(*i); 
     126 
     127static void utf16_iter_set_and_advance(PARROT_INTERP, 
     128    ARGMOD(STRING *str), 
     129    ARGMOD(String_iter *i), 
     130    UINTVAL c) 
     131        __attribute__nonnull__(1) 
     132        __attribute__nonnull__(2) 
     133        __attribute__nonnull__(3) 
     134        FUNC_MODIFIES(*str) 
     135        FUNC_MODIFIES(*i); 
     136 
     137static void utf16_iter_set_position(PARROT_INTERP, 
     138    ARGIN(const STRING *str), 
     139    ARGMOD(String_iter *i), 
     140    UINTVAL n) 
     141        __attribute__nonnull__(1) 
     142        __attribute__nonnull__(2) 
     143        __attribute__nonnull__(3) 
     144        FUNC_MODIFIES(*i); 
     145 
     146static void utf16_iter_skip(PARROT_INTERP, 
     147    ARGIN(const STRING *str), 
     148    ARGMOD(String_iter *i), 
     149    INTVAL skip) 
     150        __attribute__nonnull__(1) 
     151        __attribute__nonnull__(2) 
     152        __attribute__nonnull__(3) 
     153        FUNC_MODIFIES(*i); 
     154 
    110155static void utf16_set_position(SHIM_INTERP, 
    111156    ARGMOD(String_iter *i), 
    112157    UINTVAL n) 
     
    147192       PARROT_ASSERT_ARG(i)) 
    148193#define ASSERT_ARGS_utf16_encode_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    149194       PARROT_ASSERT_ARG(i)) 
     195#define ASSERT_ARGS_utf16_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     196       PARROT_ASSERT_ARG(interp) \ 
     197    , PARROT_ASSERT_ARG(str) \ 
     198    , PARROT_ASSERT_ARG(i)) 
     199#define ASSERT_ARGS_utf16_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     200       PARROT_ASSERT_ARG(interp) \ 
     201    , PARROT_ASSERT_ARG(str) \ 
     202    , PARROT_ASSERT_ARG(i)) 
     203#define ASSERT_ARGS_utf16_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     204       PARROT_ASSERT_ARG(interp) \ 
     205    , PARROT_ASSERT_ARG(str) \ 
     206    , PARROT_ASSERT_ARG(i)) 
     207#define ASSERT_ARGS_utf16_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     208       PARROT_ASSERT_ARG(interp) \ 
     209    , PARROT_ASSERT_ARG(str) \ 
     210    , PARROT_ASSERT_ARG(i)) 
     211#define ASSERT_ARGS_utf16_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     212       PARROT_ASSERT_ARG(interp) \ 
     213    , PARROT_ASSERT_ARG(str) \ 
     214    , PARROT_ASSERT_ARG(i)) 
    150215#define ASSERT_ARGS_utf16_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    151216       PARROT_ASSERT_ARG(i)) 
    152217/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */ 
     
    377442get_codepoints(PARROT_INTERP, ARGIN(const STRING *src), UINTVAL offset, UINTVAL count) 
    378443{ 
    379444    ASSERT_ARGS(get_codepoints) 
    380     String_iter iter; 
    381     UINTVAL start; 
     445#if PARROT_HAS_ICU 
     446    UINTVAL pos = 0, start; 
     447    const UChar * const s = (UChar*) src->strstart; 
    382448    STRING * const return_string = Parrot_str_copy(interp, src); 
    383449 
    384     iter_init(interp, src, &iter); 
    385     iter.set_position(interp, &iter, offset); 
    386     start = iter.bytepos; 
    387     return_string->strstart = (char *)return_string->strstart + start ; 
    388     iter.set_position(interp, &iter, offset + count); 
    389     return_string->bufused = iter.bytepos - start; 
     450    U16_FWD_N_UNSAFE(s, pos, offset); 
     451    start = pos * sizeof (UChar); 
     452    return_string->strstart = (char *)return_string->strstart + start; 
     453    U16_FWD_N_UNSAFE(s, pos, count); 
     454    return_string->bufused = pos * sizeof (UChar) - start; 
    390455    return_string->strlen = count; 
    391456    return_string->hashval = 0; 
    392457    return return_string; 
     458#else 
     459    UNUSED(src); 
     460    UNUSED(offset); 
     461    UNUSED(count); 
     462 
     463    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     464        "no ICU lib loaded"); 
     465#endif 
    393466} 
    394467 
    395468 
     
    432505codepoints(PARROT_INTERP, ARGIN(const STRING *src)) 
    433506{ 
    434507    ASSERT_ARGS(codepoints) 
    435     String_iter iter; 
     508#if PARROT_HAS_ICU 
     509    const UChar * const s = (UChar*) src->strstart; 
     510    UINTVAL pos = 0, charpos = 0; 
    436511    /* 
    437512     * this is used to initially calculate src->strlen, 
    438513     * therefore we must scan the whole string 
    439514     */ 
    440     iter_init(interp, src, &iter); 
    441     while (iter.bytepos < src->bufused) 
    442         iter.get_and_advance(interp, &iter); 
    443     return iter.charpos; 
     515    while (pos * sizeof (UChar) < src->bufused) { 
     516        U16_FWD_1_UNSAFE(s, pos); 
     517        ++charpos; 
     518    } 
     519    return charpos; 
     520#else 
     521    UNUSED(src); 
     522 
     523    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     524        "no ICU lib loaded"); 
     525#endif 
    444526} 
    445527 
    446528/* 
     
    461543    return src->bufused; 
    462544} 
    463545 
     546/* 
     547 
     548=item C<static UINTVAL utf16_iter_get(PARROT_INTERP, const STRING *str, const 
     549String_iter *i, INTVAL offset)> 
     550 
     551Get the character at C<i> plus C<offset>. 
     552 
     553=cut 
     554 
     555*/ 
     556 
     557static UINTVAL 
     558utf16_iter_get(PARROT_INTERP, 
     559    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     560{ 
     561    ASSERT_ARGS(utf16_iter_get) 
     562#if PARROT_HAS_ICU 
     563    const UChar * const s = (UChar*) str->strstart; 
     564    UINTVAL c, pos; 
     565 
     566    pos = i->bytepos / sizeof (UChar); 
     567    if (offset > 0) { 
     568        U16_FWD_N_UNSAFE(s, pos, offset); 
     569    } 
     570    else if (offset < 0) { 
     571        U16_BACK_N_UNSAFE(s, pos, -offset); 
     572    } 
     573    U16_GET_UNSAFE(s, pos, c); 
     574 
     575    return c; 
     576#else 
     577    UNUSED(str); 
     578    UNUSED(i); 
     579    UNUSED(offset); 
     580 
     581    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     582        "no ICU lib loaded"); 
     583#endif 
     584} 
     585 
     586/* 
     587 
     588=item C<static void utf16_iter_skip(PARROT_INTERP, const STRING *str, 
     589String_iter *i, INTVAL skip)> 
     590 
     591Moves the string iterator C<i> by C<skip> characters. 
     592 
     593=cut 
     594 
     595*/ 
     596 
     597static void 
     598utf16_iter_skip(PARROT_INTERP, 
     599    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     600{ 
     601    ASSERT_ARGS(utf16_iter_skip) 
     602#if PARROT_HAS_ICU 
     603    const UChar * const s = (UChar*) str->strstart; 
     604    UINTVAL pos = i->bytepos / sizeof (UChar); 
     605 
     606    if (skip > 0) { 
     607        U16_FWD_N_UNSAFE(s, pos, skip); 
     608    } 
     609    else if (skip < 0) { 
     610        U16_BACK_N_UNSAFE(s, pos, -skip); 
     611    } 
     612 
     613    i->charpos += skip; 
     614    i->bytepos = pos * sizeof (UChar); 
     615#else 
     616    UNUSED(str); 
     617    UNUSED(i); 
     618    UNUSED(skip); 
     619 
     620    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     621        "no ICU lib loaded"); 
     622#endif 
     623} 
     624 
     625/* 
     626 
     627=item C<static UINTVAL utf16_iter_get_and_advance(PARROT_INTERP, const STRING 
     628*str, String_iter *i)> 
     629 
     630Moves the string iterator C<i> to the next UTF-16 codepoint. 
     631 
     632=cut 
     633 
     634*/ 
     635 
     636PARROT_WARN_UNUSED_RESULT 
     637static UINTVAL 
     638utf16_iter_get_and_advance(PARROT_INTERP, 
     639    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     640{ 
     641    ASSERT_ARGS(utf16_iter_get_and_advance) 
     642#if PARROT_HAS_ICU 
     643    const UChar * const s = (UChar*) str->strstart; 
     644    UINTVAL c, pos; 
     645    pos = i->bytepos / sizeof (UChar); 
     646    /* TODO either make sure that we don't go past end or use SAFE 
     647     *      iter versions 
     648     */ 
     649    U16_NEXT_UNSAFE(s, pos, c); 
     650    i->charpos++; 
     651    i->bytepos = pos * sizeof (UChar); 
     652    return c; 
     653#else 
     654    UNUSED(str); 
     655    UNUSED(i); 
     656 
     657    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     658        "no ICU lib loaded"); 
     659#endif 
     660} 
     661 
     662/* 
     663 
     664=item C<static void utf16_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     665String_iter *i, UINTVAL c)> 
     666 
     667With the string iterator C<i>, appends the codepoint C<c> and advances to the 
     668next position in the string. 
     669 
     670=cut 
     671 
     672*/ 
     673 
     674static void 
     675utf16_iter_set_and_advance(PARROT_INTERP, 
     676    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     677{ 
     678    ASSERT_ARGS(utf16_iter_set_and_advance) 
     679#if PARROT_HAS_ICU 
     680    UChar * const s = (UChar*) str->strstart; 
     681    UINTVAL pos; 
     682    pos = i->bytepos / sizeof (UChar); 
     683    U16_APPEND_UNSAFE(s, pos, c); 
     684    i->charpos++; 
     685    i->bytepos = pos * sizeof (UChar); 
     686#else 
     687    UNUSED(str); 
     688    UNUSED(i); 
     689    UNUSED(c); 
     690 
     691    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     692        "no ICU lib loaded"); 
     693#endif 
     694} 
     695 
     696/* 
     697 
     698=item C<static void utf16_iter_set_position(PARROT_INTERP, const STRING *str, 
     699String_iter *i, UINTVAL n)> 
     700 
     701Moves the string iterator C<i> to the position C<n> in the string. 
     702 
     703=cut 
     704 
     705*/ 
     706 
     707static void 
     708utf16_iter_set_position(PARROT_INTERP, 
     709    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL n) 
     710{ 
     711    ASSERT_ARGS(utf16_iter_set_position) 
     712#if PARROT_HAS_ICU 
     713    UChar * const s = (UChar*) str->strstart; 
     714    UINTVAL pos; 
     715    pos = 0; 
     716    U16_FWD_N_UNSAFE(s, pos, n); 
     717    i->charpos = n; 
     718    i->bytepos = pos * sizeof (UChar); 
     719#else 
     720    UNUSED(str); 
     721    UNUSED(i); 
     722    UNUSED(n); 
     723 
     724    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, 
     725        "no ICU lib loaded"); 
     726#endif 
     727} 
     728 
    464729#if PARROT_HAS_ICU 
    465730/* 
    466731 
     
    595860        bytes, 
    596861        iter_init, 
    597862        find_cclass, 
    598         NULL 
     863        NULL, 
     864        utf16_iter_get, 
     865        utf16_iter_skip, 
     866        utf16_iter_get_and_advance, 
     867        utf16_iter_set_and_advance, 
     868        utf16_iter_set_position 
    599869    }; 
    600870    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    601871    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 ff17761..811ce76 100644
    a b  
    118118        __attribute__nonnull__(2) 
    119119        FUNC_MODIFIES(*i); 
    120120 
     121static UINTVAL utf8_iter_get(PARROT_INTERP, 
     122    ARGIN(const STRING *str), 
     123    ARGIN(const String_iter *i), 
     124    INTVAL offset) 
     125        __attribute__nonnull__(1) 
     126        __attribute__nonnull__(2) 
     127        __attribute__nonnull__(3); 
     128 
     129static UINTVAL utf8_iter_get_and_advance(PARROT_INTERP, 
     130    ARGIN(const STRING *str), 
     131    ARGMOD(String_iter *i)) 
     132        __attribute__nonnull__(1) 
     133        __attribute__nonnull__(2) 
     134        __attribute__nonnull__(3) 
     135        FUNC_MODIFIES(*i); 
     136 
     137static void utf8_iter_set_and_advance(PARROT_INTERP, 
     138    ARGMOD(STRING *str), 
     139    ARGMOD(String_iter *i), 
     140    UINTVAL c) 
     141        __attribute__nonnull__(1) 
     142        __attribute__nonnull__(2) 
     143        __attribute__nonnull__(3) 
     144        FUNC_MODIFIES(*str) 
     145        FUNC_MODIFIES(*i); 
     146 
     147static void utf8_iter_set_position(SHIM_INTERP, 
     148    ARGIN(const STRING *str), 
     149    ARGMOD(String_iter *i), 
     150    UINTVAL pos) 
     151        __attribute__nonnull__(2) 
     152        __attribute__nonnull__(3) 
     153        FUNC_MODIFIES(*i); 
     154 
     155static void utf8_iter_skip(SHIM_INTERP, 
     156    ARGIN(const STRING *str), 
     157    ARGMOD(String_iter *i), 
     158    INTVAL skip) 
     159        __attribute__nonnull__(2) 
     160        __attribute__nonnull__(3) 
     161        FUNC_MODIFIES(*i); 
     162 
    121163static void utf8_set_position(SHIM_INTERP, 
    122164    ARGMOD(String_iter *i), 
    123165    UINTVAL pos) 
     
    175217#define ASSERT_ARGS_utf8_encode_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    176218       PARROT_ASSERT_ARG(interp) \ 
    177219    , PARROT_ASSERT_ARG(i)) 
     220#define ASSERT_ARGS_utf8_iter_get __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     221       PARROT_ASSERT_ARG(interp) \ 
     222    , PARROT_ASSERT_ARG(str) \ 
     223    , PARROT_ASSERT_ARG(i)) 
     224#define ASSERT_ARGS_utf8_iter_get_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     225       PARROT_ASSERT_ARG(interp) \ 
     226    , PARROT_ASSERT_ARG(str) \ 
     227    , PARROT_ASSERT_ARG(i)) 
     228#define ASSERT_ARGS_utf8_iter_set_and_advance __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     229       PARROT_ASSERT_ARG(interp) \ 
     230    , PARROT_ASSERT_ARG(str) \ 
     231    , PARROT_ASSERT_ARG(i)) 
     232#define ASSERT_ARGS_utf8_iter_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     233       PARROT_ASSERT_ARG(str) \ 
     234    , PARROT_ASSERT_ARG(i)) 
     235#define ASSERT_ARGS_utf8_iter_skip __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     236       PARROT_ASSERT_ARG(str) \ 
     237    , PARROT_ASSERT_ARG(i)) 
    178238#define ASSERT_ARGS_utf8_set_position __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
    179239       PARROT_ASSERT_ARG(i)) 
    180240#define ASSERT_ARGS_utf8_skip_backward __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 
     
    387447 
    388448/* 
    389449 
     450=item C<static UINTVAL utf8_iter_get(PARROT_INTERP, const STRING *str, const 
     451String_iter *i, INTVAL offset)> 
     452 
     453Get the character at C<i> plus C<offset>. 
     454 
     455=cut 
     456 
     457*/ 
     458 
     459static UINTVAL 
     460utf8_iter_get(PARROT_INTERP, 
     461    ARGIN(const STRING *str), ARGIN(const String_iter *i), INTVAL offset) 
     462{ 
     463    ASSERT_ARGS(utf8_iter_get) 
     464    const utf8_t *u8ptr = (utf8_t *)((char *)str->strstart + i->bytepos); 
     465 
     466    if (offset > 0) { 
     467        u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, offset); 
     468    } 
     469    else if (offset < 0) { 
     470        u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr, -offset); 
     471    } 
     472 
     473    return utf8_decode(interp, u8ptr); 
     474} 
     475 
     476/* 
     477 
     478=item C<static void utf8_iter_skip(PARROT_INTERP, const STRING *str, String_iter 
     479*i, INTVAL skip)> 
     480 
     481Moves the string iterator C<i> by C<skip> characters. 
     482 
     483=cut 
     484 
     485*/ 
     486 
     487static void 
     488utf8_iter_skip(SHIM_INTERP, 
     489    ARGIN(const STRING *str), ARGMOD(String_iter *i), INTVAL skip) 
     490{ 
     491    ASSERT_ARGS(utf8_iter_skip) 
     492    const utf8_t *u8ptr = (utf8_t *)((char *)str->strstart + i->bytepos); 
     493 
     494    if (skip > 0) { 
     495        u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, skip); 
     496    } 
     497    else if (skip < 0) { 
     498        u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr, -skip); 
     499    } 
     500 
     501    i->charpos += skip; 
     502    i->bytepos = (const char *)u8ptr - (const char *)str->strstart; 
     503} 
     504 
     505/* 
     506 
     507=item C<static UINTVAL utf8_iter_get_and_advance(PARROT_INTERP, const STRING 
     508*str, String_iter *i)> 
     509 
     510The UTF-8 implementation of the string iterator's C<get_and_advance> 
     511function. 
     512 
     513=cut 
     514 
     515*/ 
     516 
     517static UINTVAL 
     518utf8_iter_get_and_advance(PARROT_INTERP, 
     519    ARGIN(const STRING *str), ARGMOD(String_iter *i)) 
     520{ 
     521    ASSERT_ARGS(utf8_iter_get_and_advance) 
     522    const utf8_t *u8ptr = (utf8_t *)((char *)str->strstart + i->bytepos); 
     523    UINTVAL c = *u8ptr; 
     524 
     525    if (UTF8_IS_START(c)) { 
     526        UINTVAL len = UTF8SKIP(u8ptr); 
     527 
     528        c &= UTF8_START_MASK(len); 
     529        i->bytepos += len; 
     530        for (len--; len; len--) { 
     531            u8ptr++; 
     532 
     533            if (!UTF8_IS_CONTINUATION(*u8ptr)) 
     534                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     535                    "Malformed UTF-8 string\n"); 
     536            c = UTF8_ACCUMULATE(c, *u8ptr); 
     537        } 
     538 
     539        if (UNICODE_IS_SURROGATE(c)) 
     540            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     541                "Surrogate in UTF-8 string\n"); 
     542    } 
     543    else if (!UNICODE_IS_INVARIANT(c)) { 
     544        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_UTF8, 
     545            "Malformed UTF-8 string\n"); 
     546    } 
     547    else { 
     548        i->bytepos++; 
     549    } 
     550 
     551    i->charpos++; 
     552    return c; 
     553} 
     554 
     555/* 
     556 
     557=item C<static void utf8_iter_set_and_advance(PARROT_INTERP, STRING *str, 
     558String_iter *i, UINTVAL c)> 
     559 
     560The UTF-8 implementation of the string iterator's C<set_and_advance> 
     561function. 
     562 
     563=cut 
     564 
     565*/ 
     566 
     567static void 
     568utf8_iter_set_and_advance(PARROT_INTERP, 
     569    ARGMOD(STRING *str), ARGMOD(String_iter *i), UINTVAL c) 
     570{ 
     571    ASSERT_ARGS(utf8_iter_set_and_advance) 
     572    unsigned char * const pos = (unsigned char *)str->strstart + i->bytepos; 
     573    unsigned char * const new_pos = (unsigned char *)utf8_encode(interp, pos, c); 
     574 
     575    i->bytepos += (new_pos - pos); 
     576    /* XXX possible buffer overrun exception? */ 
     577    PARROT_ASSERT(i->bytepos <= Buffer_buflen(str)); 
     578    i->charpos++; 
     579} 
     580 
     581/* 
     582 
     583=item C<static void utf8_iter_set_position(PARROT_INTERP, const STRING *str, 
     584String_iter *i, UINTVAL pos)> 
     585 
     586The UTF-8 implementation of the string iterator's C<set_position> 
     587function. 
     588 
     589=cut 
     590 
     591*/ 
     592 
     593static void 
     594utf8_iter_set_position(SHIM_INTERP, 
     595    ARGIN(const STRING *str), ARGMOD(String_iter *i), UINTVAL pos) 
     596{ 
     597    ASSERT_ARGS(utf8_iter_set_position) 
     598    const utf8_t *u8ptr = (const utf8_t *)str->strstart; 
     599 
     600    if (pos == 0) { 
     601        i->charpos = 0; 
     602        i->bytepos = 0; 
     603        return; 
     604    } 
     605 
     606    /* 
     607     * we know the byte offsets of three positions: start, current and end 
     608     * now find the shortest way to reach pos 
     609     */ 
     610    if (pos < i->charpos) { 
     611        if (pos <= (i->charpos >> 1)) { 
     612            /* go forward from start */ 
     613            u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr, pos); 
     614        } 
     615        else { 
     616            /* go backward from current */ 
     617            u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr + i->bytepos, i->charpos - pos); 
     618        } 
     619    } 
     620    else { 
     621        const UINTVAL  len = str->strlen; 
     622        if (pos <= i->charpos + ((len - i->charpos) >> 1)) { 
     623            /* go forward from current */ 
     624            u8ptr = (const utf8_t *)utf8_skip_forward(u8ptr + i->bytepos, pos - i->charpos); 
     625        } 
     626        else { 
     627            /* go backward from end */ 
     628            u8ptr = (const utf8_t *)utf8_skip_backward(u8ptr + str->bufused, len - pos); 
     629        } 
     630    } 
     631 
     632    i->charpos = pos; 
     633    i->bytepos = (const char *)u8ptr - (const char *)str->strstart; 
     634} 
     635 
     636/* 
     637 
    390638=item C<static UINTVAL utf8_decode_and_advance(PARROT_INTERP, String_iter *i)> 
    391639 
    392640The UTF-8 implementation of the string iterator's C<get_and_advance> 
     
    513761{ 
    514762    ASSERT_ARGS(to_encoding) 
    515763    STRING *result; 
    516     String_iter src_iter; 
    517     UINTVAL offs, dest_len, dest_pos, src_len; 
     764    const ENCODING *src_encoding; 
     765    UINTVAL dest_len, dest_pos, src_len; 
    518766    unsigned char *p; 
    519767 
    520768    if (src->encoding == Parrot_utf8_encoding_ptr) 
     
    523771    result = Parrot_gc_new_string_header(interp, 0); 
    524772    src_len = src->strlen; 
    525773 
    526     /* init iter before possilby changing encoding */ 
    527     ENCODING_ITER_INIT(interp, src, &src_iter); 
     774    /* save source encoding before possibly changing it */ 
     775    src_encoding = src->encoding; 
    528776    result->charset  = Parrot_unicode_charset_ptr; 
    529777    result->encoding = Parrot_utf8_encoding_ptr; 
    530778    result->strlen   = src_len; 
     
    542790        result->bufused = dest_len; 
    543791    } 
    544792    else { 
     793        String_iter src_iter; 
     794        STRING_ITER_INIT(interp, &src_iter); 
    545795        dest_len = src_len; 
    546796        dest_pos = 0; 
    547         for (offs = 0; offs < src_len; ++offs) { 
    548             const UINTVAL c = src_iter.get_and_advance(interp, &src_iter); 
     797        while (src_iter.charpos < src_len) { 
     798            const UINTVAL c = src_encoding->iter_get_and_advance(interp, src, &src_iter); 
    549799            unsigned char *new_pos; 
    550800            unsigned char *pos; 
    551801 
    552802            if (dest_len - dest_pos < 6) { 
    553                 UINTVAL need = (UINTVAL)((src->strlen - offs) * 1.5); 
     803                UINTVAL need = (UINTVAL)((src->strlen - src_iter.charpos + 1) * 1.5); 
    554804                if (need < 16) 
    555805                    need = 16; 
    556806                dest_len += need; 
     
    683933    String_iter    iter; 
    684934    UINTVAL        start; 
    685935 
    686     iter_init(interp, src, &iter); 
     936    STRING_ITER_INIT(interp, &iter); 
    687937 
    688938    if (offset) 
    689         iter.set_position(interp, &iter, offset); 
     939        utf8_iter_set_position(interp, src, &iter, offset); 
    690940 
    691941    start                   = iter.bytepos; 
    692942    return_string->strstart = (char *)return_string->strstart + start; 
    693943 
    694944    if (count) 
    695         iter.set_position(interp, &iter, offset + count); 
     945        utf8_iter_set_position(interp, src, &iter, offset + count); 
    696946 
    697947    return_string->bufused  = iter.bytepos - start; 
    698948    return_string->strlen   = count; 
     
    749999     * this is used to initially calculate src->strlen, 
    7501000     * therefore we must scan the whole string 
    7511001     */ 
    752     iter_init(interp, src, &iter); 
     1002    STRING_ITER_INIT(interp, &iter); 
    7531003    while (iter.bytepos < src->bufused) 
    754         iter.get_and_advance(interp, &iter); 
     1004        utf8_iter_get_and_advance(interp, src, &iter); 
    7551005    return iter.charpos; 
    7561006} 
    7571007 
     
    8251075        bytes, 
    8261076        iter_init, 
    8271077        find_cclass, 
    828         NULL 
     1078        NULL, 
     1079        utf8_iter_get, 
     1080        utf8_iter_skip, 
     1081        utf8_iter_get_and_advance, 
     1082        utf8_iter_set_and_advance, 
     1083        utf8_iter_set_position 
    8291084    }; 
    8301085    STRUCT_COPY_FROM_STRUCT(return_encoding, base_encoding); 
    8311086    Parrot_register_encoding(interp, "utf8", return_encoding);