File Coverage

File:src/pmc/string.pmc
Coverage:71.8%

linestmtcode
1/*
2Copyright (C) 2003-2009, Parrot Foundation.
3$Id: string.pmc 41447 2009-09-24 19:30:17Z NotFound $
4
5 - 19
=head1 NAME

src/pmc/string.pmc - String PMC Class

=head1 DESCRIPTION

C<String> extends C<scalar> to provide a string for languages that want a
C<string> type without going to an S register.  It acts as a wrapper for the
functions in F<src/string.c>.

=head2 Methods

=over 4

=cut
20
21*/
22
23pmclass String extends scalar provides string provides scalar auto_attrs {
24    ATTR STRING * str_val;
25
26/*
27
28 - 32
=item C<void init()>

Initializes the string.

=cut
33
34*/
35
36    VTABLE void init() {
37
12947340
        STRING *str_val = Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0);
38
12947340
        SET_ATTR_str_val(INTERP, SELF, str_val);
39
40
12947340
        PObj_custom_mark_SET(SELF);
41    }
42
43/*
44
45 - 49
=item C<PMC instantiate_str(STRING *rep)>

Class method to construct a String from the string representation C<rep>.

=cut
50
51*/
52    VTABLE PMC *instantiate_str(STRING *rep, INTVAL flags) {
53        PMC *res;
54
12
        const INTVAL type = SELF->vtable->base_type;
55
56
12
        if (flags & PObj_constant_FLAG)
57
12
            res = constant_pmc_new(INTERP, type);
58        else
59
0
            res = pmc_new(INTERP, type);
60
61
12
        SET_ATTR_str_val(INTERP, res, rep);
62
12
        return res;
63    }
64
65/*
66
67 - 71
=item C<void mark()>

Marks the string as live.

=cut
72
73*/
74
75    VTABLE void mark() {
76        STRING *str_val;
77
65491260
        GET_ATTR_str_val(INTERP, SELF, str_val);
78
65491260
        Parrot_gc_mark_STRING_alive(INTERP, str_val);
79    }
80
81/*
82
83 - 87
=item C<PMC *clone()>

Creates a copy of the string.

=cut
88
89*/
90
91    VTABLE PMC *clone() {
92
69446
        PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type);
93
69446
        VTABLE_set_string_native(INTERP, dest, Parrot_str_copy(INTERP, SELF.get_string()));
94
69446
        return dest;
95    }
96
97/*
98
99 - 103
=item C<INTVAL get_integer()>

Returns the integer representation of the string.

=cut
104
105*/
106
107    VTABLE INTVAL get_integer() {
108
3850
        STRING * const s = SELF.get_string();
109
3850
        return Parrot_str_to_int(INTERP, s);
110    }
111
112/*
113
114 - 118
=item C<FLOATVAL get_number()>

Returns the floating-point representation of the string.

=cut
119
120*/
121
122    VTABLE FLOATVAL get_number() {
123
601430
        STRING * const s = SELF.get_string();
124
601430
        return Parrot_str_to_num(INTERP, s);
125    }
126
127/*
128
129 - 133
=item C<PMC *get_bignum()>

Returns the big numbers representation of the string.

=cut
134
135*/
136
137    VTABLE PMC *get_bignum() {
138
0
        STRING * const s = SELF.get_string();
139
0
        PMC * const ret = pmc_new(INTERP, enum_class_BigInt);
140
0
        VTABLE_set_string_native(INTERP, ret, s);
141
0
        return ret;
142    }
143
144/*
145
146 - 150
=item C<STRING *get_string()>

Returns the string itself.

=cut
151
152*/
153
154    VTABLE STRING *get_string() {
155        STRING *str_val;
156
4552672
        GET_ATTR_str_val(INTERP, SELF, str_val);
157
4552672
        return str_val ? Parrot_str_copy(INTERP, str_val) : NULL;
158    }
159
160/*
161
162 - 166
=item C<INTVAL get_bool()>

Returns the boolean value of the string.

=cut
167
168*/
169
170    VTABLE INTVAL get_bool() {
171
53090
        STRING * const s = SELF.get_string();
172
53090
        return Parrot_str_boolean(INTERP, s);
173    }
174
175/*
176
177 - 183
=item C<VOID set_integer_native(INTVAL value)>

=item C<VOID set_bool(INTVAL value)>

Sets the value of the string to the integer C<value>.

=cut
184
185*/
186
187    VTABLE void set_integer_native(INTVAL value) {
188
272
        SELF.set_string_native(Parrot_str_from_int(INTERP, value));
189    }
190
191    VTABLE void set_bool(INTVAL value) {
192
0
        SELF.set_string_native(Parrot_str_from_int(INTERP, value));
193    }
194
195/*
196
197 - 201
=item C<VOID set_number_native(FLOATVAL value)>

Sets the value of the string to the floating-point C<value>.

=cut
202
203*/
204
205    VTABLE void set_number_native(FLOATVAL value) {
206
134
        SELF.set_string_native(Parrot_str_from_num(INTERP, value));
207    }
208
209
210/*
211
212 - 216
=item C<VOID set_string_native(STRING *value)>

Sets the value of the string to that of the specified C<string>.

=cut
217
218*/
219
220    VTABLE void set_string_native(STRING *value) {
221        /* in lieu of a STRINGNULL, promote any NULL STRINGs to empty ones */
222
3567018
        if (!value)
223
8198
            value = Parrot_str_new(INTERP, NULL, 0);
224
225        /* Only allow constant PMCs to embed constant strings */
226
3567018
        if (PObj_constant_TEST(SELF) && !PObj_constant_TEST(value)) {
227
2520
            char *copy = Parrot_str_to_cstring(INTERP, value);
228
2520
            value = Parrot_str_new_init(INTERP, copy, strlen(copy),
229                PARROT_DEFAULT_ENCODING, PARROT_DEFAULT_CHARSET,
230                PObj_constant_FLAG);
231
2520
            Parrot_str_free_cstring(copy);
232        }
233
234
3567018
        SET_ATTR_str_val(INTERP, SELF, value);
235    }
236
237/*
238
239 - 243
=item C<VOID assign_string_native(STRING *value)>

Sets the value of the string to a copy of the specified C<string>.

=cut
244
245*/
246
247    VTABLE void assign_string_native(STRING *value) {
248
7684
        if (!STRING_IS_NULL(value))
249
7672
            SET_ATTR_str_val(INTERP, SELF,
250                    Parrot_str_set(INTERP, SELF.get_string(), value));
251        else
252
12
            SET_ATTR_str_val(INTERP, SELF, NULL);
253    }
254
255/*
256
257 - 262
=item C<VOID set_pmc(PMC *value)>

Sets the value of the string to the string value of
the specified C<PMC>.

=cut
263
264*/
265    VTABLE void set_pmc(PMC *value) {
266
0
        SELF.set_string_native(VTABLE_get_string(INTERP, value));
267    }
268
269/*
270
271 - 305
=item C<PMC *bitwise_ors(PMC *value, PMC *dest)>

=item C<PMC *bitwise_ors_str(PMC *value, PMC *dest)>

=item C<PMC *bitwise_ands(PMC *value, PMC *dest)>

=item C<PMC *bitwise_ands_str(PMC *value, PMC *dest)>

=item C<PMC *bitwise_xors(PMC *value, PMC *dest)>

=item C<PMC *bitwise_xors_str(PMC *value, PMC *dest)>

=item C<void bitwise_nots(PMC *value)>

These functions perform bitwise operations on entire
strings, and place the result in C<dest>.

=item C<void i_bitwise_ors(PMC *value)>

=item C<void i_bitwise_ors_str(PMC *value)>

=item C<void i_bitwise_ands(PMC *value)>

=item C<void i_bitwise_ands_str(PMC *value)>

=item C<void i_bitwise_xors(PMC *value)>

=item C<void i_bitwise_xors_str(PMC *value)>

=item C<void i_bitwise_nots(PMC *value)>

These functions perform bitwise operations on entire
strings in place.

=cut
306
307*/
308    VTABLE PMC *bitwise_ors(PMC *value, PMC *dest) {
309
72
        STRING * const s = VTABLE_get_string(INTERP, SELF);
310
72
        STRING * const v = VTABLE_get_string(INTERP, value);
311
312
72
        if (!dest)
313
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
314
315
72
        VTABLE_set_string_native(INTERP, dest,
316            Parrot_str_bitwise_or(INTERP, s, v, NULL));
317
318
72
        return dest;
319    }
320
321    VTABLE PMC *bitwise_ors_str(STRING *value, PMC *dest) {
322
0
        STRING * const s = VTABLE_get_string(INTERP, SELF);
323
324
0
        if (!dest)
325
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
326
327
0
        VTABLE_set_string_native(INTERP, dest,
328            Parrot_str_bitwise_or(INTERP, s, value, NULL));
329
330
0
        return dest;
331    }
332
333    VTABLE void i_bitwise_ors(PMC *value) {
334
72
        STRING *s = VTABLE_get_string(INTERP, SELF);
335
72
        STRING * const v = VTABLE_get_string(INTERP, value);
336
72
        SELF.set_string_native(Parrot_str_bitwise_or(INTERP, s, v, &s));
337    }
338
339    VTABLE void i_bitwise_ors_str(STRING *value) {
340
0
        STRING *s = VTABLE_get_string(INTERP, SELF);
341
0
        SELF.set_string_native(Parrot_str_bitwise_or(INTERP, s, value, &s));
342    }
343
344    VTABLE PMC *bitwise_ands(PMC *value, PMC *dest) {
345
12
        STRING * const s = VTABLE_get_string(INTERP, SELF);
346
12
        STRING * const v = VTABLE_get_string(INTERP, value);
347
348
12
        if (!dest)
349
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
350
351
12
        VTABLE_set_string_native(INTERP, dest,
352            Parrot_str_bitwise_and(INTERP, s, v, NULL));
353
354
12
        return dest;
355    }
356
357    VTABLE PMC *bitwise_ands_str(STRING *value, PMC *dest) {
358
0
        STRING * const s = VTABLE_get_string(INTERP, SELF);
359
360
0
        if (!dest)
361
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
362
363
0
        VTABLE_set_string_native(INTERP, dest,
364            Parrot_str_bitwise_and(INTERP, s, value, NULL));
365
366
0
        return dest;
367    }
368
369
370    VTABLE void i_bitwise_ands(PMC *value) {
371
60
        STRING *s = VTABLE_get_string(INTERP, SELF);
372
60
        STRING * const v = VTABLE_get_string(INTERP, value);
373
60
        SELF.set_string_native(Parrot_str_bitwise_and(INTERP, s, v, &s));
374    }
375
376    VTABLE void i_bitwise_ands_str(STRING *value) {
377
0
        STRING *s = VTABLE_get_string(INTERP, SELF);
378
0
        SELF.set_string_native(Parrot_str_bitwise_and(INTERP, s, value, &s));
379    }
380
381    VTABLE PMC *bitwise_xors(PMC *value, PMC *dest) {
382
84
        STRING * const s = VTABLE_get_string(INTERP, SELF);
383
84
        STRING * const v = VTABLE_get_string(INTERP, value);
384
385
84
        if (!dest)
386
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
387
388
84
        VTABLE_set_string_native(INTERP, dest,
389            Parrot_str_bitwise_xor(INTERP, s, v, NULL));
390
391
84
        return dest;
392    }
393
394    VTABLE PMC *bitwise_xors_str(STRING *value, PMC *dest) {
395
0
        STRING * const s = VTABLE_get_string(INTERP, SELF);
396
397
0
        if (!dest)
398
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
399
400
0
        VTABLE_set_string_native(INTERP, dest,
401            Parrot_str_bitwise_xor(INTERP, s, value, NULL));
402
403
0
        return dest;
404    }
405
406    VTABLE void i_bitwise_xors(PMC *value) {
407
84
        STRING *s = VTABLE_get_string(INTERP, SELF);
408
84
        STRING * const v = VTABLE_get_string(INTERP, value);
409
84
        SELF.set_string_native(Parrot_str_bitwise_xor(INTERP, s, v, &s));
410    }
411
412    VTABLE void i_bitwise_xors_str(STRING *value) {
413
0
        STRING *s = VTABLE_get_string(INTERP, SELF);
414
0
        SELF.set_string_native(Parrot_str_bitwise_xor(INTERP, s, value, &s));
415    }
416
417    VTABLE PMC *bitwise_nots(PMC *dest) {
418
36
        STRING * const s = VTABLE_get_string(INTERP, SELF);
419
420
36
        if (!dest)
421
0
            dest = pmc_new(INTERP, SELF->vtable->base_type);
422
423
36
        VTABLE_set_string_native(INTERP, dest,
424            Parrot_str_bitwise_not(INTERP, s, NULL));
425
426
36
        return dest;
427    }
428
429    VTABLE void i_bitwise_nots() {
430
0
        STRING *s = VTABLE_get_string(INTERP, SELF);
431
0
        VTABLE_set_string_native(
432            INTERP, SELF, Parrot_str_bitwise_not(INTERP, s, &s));
433    }
434
435/*
436
437 - 442
=item C<INTVAL is_equal(PMC *value)>

Compares the string with C<value>; returns true if
they match.

=cut
443
444*/
445    VTABLE INTVAL is_equal(PMC *value) {
446
210
        STRING * const s = VTABLE_get_string(INTERP, SELF);
447
210
        STRING * const v = VTABLE_get_string(INTERP, value);
448
210
        return (INTVAL)(Parrot_str_equal(INTERP, s, v));
449    }
450
451    MULTI INTVAL is_equal(PMC *value) {
452
0
        return SELF.is_equal(value);
453    }
454
455/*
456
457 - 462
=item C<INTVAL is_equal_num(PMC *value)>

Compares the numerical value of the string with that of
C<value>; returns true if they match.

=cut
463
464*/
465
466    VTABLE INTVAL is_equal_num(PMC *value) {
467
0
        const FLOATVAL sf = Parrot_str_to_num(INTERP, VTABLE_get_string(INTERP, SELF));
468
0
        const FLOATVAL vf = VTABLE_get_number(INTERP, value);
469
0
        return (INTVAL)(sf == vf);
470    }
471
472/*
473
474 - 478
=item C<INTVAL is_equal_string(PMC *value)>

Compares the string with C<value>; returns FALSE if they match.

=cut
479
480*/
481
482    VTABLE INTVAL is_equal_string(PMC *value) {
483
36
        STRING * const s = VTABLE_get_string(INTERP, SELF);
484
36
        STRING * const v = VTABLE_get_string(INTERP, value);
485
36
        return Parrot_str_equal(INTERP, s, v);
486    }
487
488/*
489
490 - 496
=item C<INTVAL cmp(PMC *value)>

Compares the string with C<value>; returns -1 if the
string is smaller, 0 if they are equal, and 1 if C<value>
is smaller.

=cut
497
498*/
499    VTABLE INTVAL cmp(PMC *value) {
500
52648
        STRING * const s = VTABLE_get_string(INTERP, SELF);
501
52648
        STRING * const v = VTABLE_get_string(INTERP, value);
502
52648
        return Parrot_str_compare(INTERP, s, v);
503    }
504
505/*
506
507 - 513
=item C<INTVAL cmp_num(PMC *value)>

Compares the numerical value of the string with that of
C<value>; returns -1 if the string is smaller, 0 if they
are equal, and 1 if C<value> is smaller.

=cut
514
515*/
516    VTABLE INTVAL cmp_num(PMC *value) {
517
0
        const FLOATVAL sf = Parrot_str_to_num(INTERP, VTABLE_get_string(INTERP, SELF));
518
0
        const FLOATVAL vf = VTABLE_get_number(INTERP, value);
519
520
0
        if (sf < vf)
521
0
            return (INTVAL)(-1);
522
523
0
        if (sf > vf)
524
0
            return (INTVAL)(1);
525
526
0
        return (INTVAL)(0);
527    }
528
529/*
530
531 - 537
=item C<INTVAL cmp_string(PMC *value)>

Compares the string with C<value>; returns -1 if the
string is smaller, 0 if they are equal, and 1 if C<value>
is smaller.

=cut
538
539*/
540    VTABLE INTVAL cmp_string(PMC *value) {
541
36
        STRING * const s = VTABLE_get_string(INTERP, SELF);
542
36
        STRING * const v = VTABLE_get_string(INTERP, value);
543
36
        return Parrot_str_compare(INTERP, s, v);
544    }
545
546/*
547
548 - 553
=item C<void substr(INTVAL offset, INTVAL length, PMC *dest)>

Extracts the substring starting at C<offset>, with size
C<length>, and places it in C<dest>.

=cut
554
555*/
556    VTABLE void substr(INTVAL offset, INTVAL length, PMC *dest) {
557
0
        STRING * const s = VTABLE_get_string(INTERP, SELF);
558
0
        STRING * const s2 = Parrot_str_substr(INTERP, s, offset, length, NULL, 0);
559
0
        VTABLE_set_string_native(INTERP, dest, s2);
560    }
561
562/*
563
564 - 569
=item C<STRING *substr_str(INTVAL offset, INTVAL length)>

Extracts the substring starting at C<offset>, with size
C<length>, and returns it.

=cut
570
571*/
572    VTABLE STRING *substr_str(INTVAL offset, INTVAL length) {
573
21236
        STRING * const s = VTABLE_get_string(INTERP, SELF);
574
21236
        return Parrot_str_substr(INTERP, s, offset, length, NULL, 0);
575    }
576
577/*
578
579 - 584
=item C<INTVAL exists_keyed(PMC *key)>

Returns true if the C<key>'th character in the string exists. Negative
numbers count from the end.

=cut
585
586*/
587
588    VTABLE INTVAL exists_keyed(PMC *key) {
589
0
        const INTVAL n = Parrot_str_byte_length(INTERP, VTABLE_get_string(INTERP, SELF));
590
0
        const INTVAL k = VTABLE_get_integer(INTERP, key);
591
0
        return (INTVAL)((k>=0 && k<=n) || (k<0 && -k<=n));
592    }
593
594/*
595
596 - 613
=item C<STRING *get_string_keyed(PMC *key)>

Returns the C<key>'th character in the string. Negative numbers count
from the end.

=item C<INTVAL get_integer_keyed(PMC *key)>

Returns the integer value (ord) at C<*key>.

=item C<void set_string_keyed(PMC *key, STRING *val)>

Replace the string at C<key> with C<value>.

=item C<void set_integer_keyed(PMC *key, INTVAL val)>

Replace the string at C<key> with the chr of C<value>.

=cut
614
615*/
616
617    VTABLE STRING *get_string_keyed(PMC *key) {
618
0
        return SELF.get_string_keyed_int(VTABLE_get_integer(INTERP, key));
619    }
620
621    VTABLE STRING *get_string_keyed_int(INTVAL pos) {
622
312
        STRING * const s = SELF.get_string();
623
312
        return Parrot_str_substr(INTERP, s, pos, 1, NULL, 0);
624    }
625
626    VTABLE INTVAL get_integer_keyed(PMC *key) {
627
0
        return SELF.get_integer_keyed_int(VTABLE_get_integer(INTERP, key));
628    }
629
630    VTABLE INTVAL get_integer_keyed_int(INTVAL pos) {
631
216
        STRING * const s = SELF.get_string();
632
216
        return string_ord(INTERP, s, pos);
633    }
634
635    VTABLE PMC *get_pmc_keyed(PMC *key) {
636
0
        return SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
637    }
638
639    VTABLE PMC *get_pmc_keyed_int(INTVAL pos) {
640
12
        PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type);
641
12
        VTABLE_set_string_native(INTERP, dest, SELF.get_string_keyed_int(pos));
642
12
        return dest;
643    }
644
645    VTABLE void set_string_keyed(PMC *key, STRING * const value) {
646
0
        SELF.set_string_keyed_int(VTABLE_get_integer(INTERP, key), value);
647    }
648
649    VTABLE void set_string_keyed_int(INTVAL pos, STRING * const value) {
650
36
        STRING * const s = SELF.get_string();
651
36
        const INTVAL len = Parrot_str_byte_length(INTERP, value);
652
36
        Parrot_str_replace(INTERP, s, pos, len, value, NULL);
653
36
        VTABLE_set_string_native(INTERP, SELF, s);
654    }
655
656    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
657
0
        SELF.set_integer_keyed_int(VTABLE_get_integer(INTERP, key), value);
658    }
659
660    VTABLE void set_integer_keyed_int(INTVAL pos, INTVAL value) {
661
24
        STRING * const s = SELF.get_string();
662
24
        STRING * const c = string_chr(INTERP, (UINTVAL) value);
663
24
        Parrot_str_replace(INTERP, s, pos, 1, c, NULL);
664
24
        VTABLE_set_string_native(INTERP, SELF, s);
665    }
666
667    VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
668
0
        SELF.set_pmc_keyed_int(VTABLE_get_integer(INTERP, key), value);
669    }
670
671    VTABLE void set_pmc_keyed_int(INTVAL pos, PMC *value) {
672
12
        SELF.set_string_keyed_int(pos, VTABLE_get_string(INTERP, value));
673    }
674/*
675
676 - 680
=item C<void replace(STRING *orig, STRING *_new)>

Replace every occurrence of C<orig> with C<_new>.

=cut
681
682*/
683
684    METHOD replace(STRING *orig, STRING *_new) {
685
36
        const INTVAL old_len = Parrot_str_byte_length(INTERP, orig);
686
36
        const INTVAL new_len = Parrot_str_byte_length(INTERP, _new);
687
36
        STRING * const s = VTABLE_get_string(INTERP, SELF);
688
36
        INTVAL i = 0;
689
690
132
        while (-1 != (i = Parrot_str_find_index(INTERP, s, orig, i))) {
691
60
            (void)Parrot_str_replace(INTERP, s, i, old_len, _new, NULL);
692
60
            i += new_len;
693        }
694
695
36
        VTABLE_set_string_native(INTERP, SELF, s);
696    }
697/*
698
699 - 710
=item C<PMC *to_int(INTVAL base)>

Return the integer equivalent of SELF, which is assumed to be a C<base>
digit string. The String is assumed to be in an ascii-compatible encoding.
The String is considered being unsigned, and no I<+> or I<-> chars are
processed. C<base> has to be within [2..36].

If any chars in the String aren't converted, an exception is thrown.

TODO Currently overflow to BigInt is B<not> handled nor detected.

=cut
711
712*/
713
714    METHOD to_int(INTVAL base) {
715        PMC *result = pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp,
716
124
                        enum_class_Integer));
717
718        /* TODO verify encoding */
719
124
        const STRING *me = VTABLE_get_string(INTERP, SELF);
720
124
        char *str = Parrot_str_to_cstring(INTERP, me);
721
124
        UINTVAL i = 0;
722
124
        size_t j = 0;
723
124
        size_t len = strlen(str);
724
725
124
        if (base < 2 || base > 36)
726
12
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
727                    "invalid conversion to int - bad base %d", base);
728
729
612
        while (j < len) {
730
400
            const unsigned char c = str[j];
731            int dig;
732
733
400
            if (isdigit((unsigned char)c))
734
370
                dig = c - '0';
735
60
            else if (c >= 'a' && c <= 'z')
736
30
                dig = c - 'a' + 10;
737
0
            else if (c >= 'A' && c <= 'Z')
738
0
                dig = c - 'A' + 10;
739            else
740                break;
741
742
400
            if (dig >= base)
743
12
                break;
744
745
388
            i = i * base + dig;
746
388
            j++;
747        }
748
749
112
        if (j < len) {
750
12
            char ch = str[j];
751
12
            Parrot_str_free_cstring(str);
752
12
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
753                    "invalid conversion to int - bad char %c", ch);
754        }
755
756
100
        Parrot_str_free_cstring(str);
757        /* TODO: autopromote to BigInt instead of casting away the high bit */
758
100
        VTABLE_set_integer_native(INTERP, result, (INTVAL)i);
759        RETURN(PMC *result);
760    }
761/*
762
763=back
764
765 - 784
=head2 Iterator Interface

=over 4

=item C<PMC *slice(PMC *key, INTVAL f)>

Return a new iterator for the slice PMC C<key> if f==0.

Return a new pythonic slice if f == 1.

=item C<PMC *get_iter(PMC *key)>

Return a new iterator for this string.

=item C<INTVAL elements()>

Return length of the string.


=cut
785
786*/
787
788    VTABLE INTVAL elements() {
789
228
        return Parrot_str_byte_length(INTERP, VTABLE_get_string(INTERP, SELF));
790    }
791
792    VTABLE PMC *slice(PMC *key, INTVAL f) {
793
0
        if (f == 0) {
794
0
            STRING *name = CONST_STRING(interp, "set_key");
795
0
            PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
796
0
            Parrot_PCCINVOKE(interp, iter, name, "P->", key);
797
0
            return iter;
798        }
799
800
0
        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
801
36
                "String: Unknown slice type");
802
36
    }
803
804    VTABLE PMC *get_iter() {
805
132
        return pmc_new_init(INTERP, enum_class_StringIterator, SELF);
806    }
807
808/*
809
810=back
811
812 - 820
=head2 Freeze/thaw Interface

=over 4

=item C<void freeze(visit_info *info)>

Used to archive the string.

=cut
821
822*/
823    VTABLE void freeze(visit_info *info) {
824
12110
        IMAGE_IO * const io = info->image_io;
825
12110
        SUPER(info);
826
12110
        VTABLE_push_string(INTERP, io, VTABLE_get_string(INTERP, SELF));
827    }
828
829/*
830
831 - 835
=item C<void thaw(visit_info *info)>

Used to unarchive the string.

=cut
836
837*/
838    VTABLE void thaw(visit_info *info) {
839
9462178
        IMAGE_IO * const io = info->image_io;
840
9462178
        SUPER(info);
841
9462178
        if (info->extra_flags == EXTRA_IS_NULL)
842
9462178
            SET_ATTR_str_val(INTERP, SELF, VTABLE_shift_string(INTERP, io));
843    }
844/*
845
846=back
847
848 - 856
=head2 NCI methods

=over 4

=item C<PMC *lower()>

Downcase this string

=cut
857
858*/
859
860    METHOD lower() {
861        STRING * const s = Parrot_str_downcase(INTERP,
862
24
            VTABLE_get_string(INTERP, SELF));
863
864        RETURN(STRING *s);
865    }
866
867/*
868
869 - 873
=item C<void trans(STRING *src, PMC *trams_table)>

Translate ascii string C<src> with entries from C<trans_table>.

=cut
874
875*/
876
877    METHOD trans(STRING *src, PMC *table) {
878        unsigned char *p;
879        INTVAL *tr_data;
880        INTVAL i;
881
882
12
        const INTVAL len = Parrot_str_byte_length(interp, src);
883
884
12
        if (!len)
885            RETURN(void);
886
887
12
        if (src->charset != Parrot_ascii_charset_ptr)
888
0
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING,
889                "Can't translate non-ascii");
890
891
12
        p = (unsigned char *)Buffer_bufstart(src);
892
124
        /* TODO verify trans table */
893
894
12
        GETATTR_FixedIntegerArray_int_array(INTERP, table, tr_data);
895
896
156
        for (i = 0; i < len; ++i, ++p) {
897
144
            const unsigned char ch = (unsigned char)tr_data[*p];
898
144
            if (ch)
899
132
                *p = ch;
900        }
901    }
902
903/*
904
905 - 909
=item C<void reverse(STRING *src)>

Reverse the ascii STRING C<src> in place.

=cut
910
911*/
912
913    METHOD reverse(STRING *src) {
914        INTVAL i;
915        unsigned char *p;
916
12
        INTVAL len = Parrot_str_byte_length(interp, src);
917
918
12
        if (!len)
919            RETURN(void);
920
921
12
        if (src->charset != Parrot_ascii_charset_ptr)
922
0
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING,
923                "Can't reverse non-ascii");
924
925
12
        p = (unsigned char *)Buffer_bufstart(src);
926
927
48
        for (i = 0, --len; i < len; ++i, --len) {
928
36
            const unsigned char ch = p[len];
929
930
36
            p[len] = p[i];
931
36
            p[i] = ch;
932        }
933    }
934
935/*
936
937 - 941
=item C<INTEGER is_integer(STRING *src)>

Checks if the ascii STRING C<str> is just an integer.

=cut
942
943*/
944
945    METHOD is_integer(STRING *src) {
946        INTVAL i;
947        unsigned char *p;
948
72
        const INTVAL len = Parrot_str_byte_length(interp, src);
949
950
172
        if (!len)
951            RETURN(INTVAL 0);
952
953
72
        if (src->charset != Parrot_ascii_charset_ptr)
954
0
            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING,
955                "Can't is_integer non-ascii");
956
957
72
        i = 0;
958
72
        p = (unsigned char *)Buffer_bufstart(src);
959
960
72
        if (p[i] == '-' || p[i] == '+' ||
961            (p[i] >= '0' && p[i] <= '9')) {
962
108
            for (i = 1; i < len; ++i)
963
72
                if (p[i] < '0' || p[i] > '9')
964                    RETURN(INTVAL 0);
965
966            RETURN(INTVAL 1);
967        }
968        else
969            RETURN(INTVAL 0);
970    }
971
972    VTABLE PMC *share_ro() {
973        STRING *str_val;
974
0
        PMC * const ret = SUPER();
975
976
0
        GET_ATTR_str_val(INTERP, SELF, str_val);
977
0
        if (!STRING_IS_NULL(str_val)) {
978            /* prevent wrong garbage collection */
979
0
            PObj_is_shared_SET(str_val);
980        }
981
0
        return ret;
982    }
983
984    VTABLE STRING* get_repr() {
985
0
        return VTABLE_get_string(INTERP, SELF);
986    }
987
988/*
989
990 - 994
=item C<INTEGER reverse_index(STRING *substring, INTVAL start)>

Find last occurrence of C<substring>, but not after the C<start> position.

=cut
995
996*/
997
998    METHOD reverse_index(STRING *substring, INTVAL start) {
999
72
        STRING * const src = VTABLE_get_string(INTERP, SELF);
1000
72
        INTVAL res = -1;
1001        UINTVAL len;
1002
1003
72
        if (start < 0)
1004            RETURN(INTVAL res);
1005
1006
60
        len = Parrot_str_byte_length(interp, src);
1007
1008
60
        if (!len)
1009            RETURN(INTVAL res);
1010
1011
48
        if (start >= (INTVAL)len)
1012            RETURN(INTVAL res);
1013
1014
36
        if (!Parrot_str_byte_length(interp, substring))
1015            RETURN(INTVAL res);
1016
1017
24
        res = CHARSET_RINDEX(INTERP, src, substring, (UINTVAL)start);
1018        RETURN(INTVAL res);
1019    }
1020}
1021
1022/*
1023
1024=back
1025
1026=cut
1027
1028*/
1029
1030
1031/*
1032 * Local variables:
1033 * c-file-style: "parrot"
1034 * End:
1035 * vim: expandtab shiftwidth=4:
1036 */