| parrotcode: Perl 6 Strings | |
| Contents | Language Implementations | Perl6 | 

src/pmc/perl6str.pmc - Perl 6 Strings

Perl6Str extends String to provide Perl 6-specific string numifying behavior.

INTVAL get_integer()get_number() and return that as an integer.FLOATVAL get_number()void increment()void decrement()isalpha() or isdigit() respectively.    VTABLE void increment() {
        STRING            *str   = Parrot_unCOW_string(interp, PMC_str_val(SELF));
        char              *start = str->strstart;
        const char * const end   = start + string_length(INTERP, str);
        /* pointer to the substring we're going to increment */
        char       *substr;
        /* length of the substring */
        INTVAL      len;
        INTVAL i, carry;
        /* start of the current incrementable substring */
        char *s = start;
        /* end of the current incrementable substring */
        char *e = start;
        /* start of the previous incrementable substring */
        char *ps = 0;
        /* end of the previous incrementable substring */
        const char *pe = 0;
        /* find the portion of the string to increment */
        while (s < end) {
            while (!isalnum((unsigned char)*s) && s < end)
                s++;
            e = s;
            while (isalnum((unsigned char)*e) && e < end)
                e++;
            if (!(e < end))
                break;
            ps = s;
            pe = e;
            s = e;
        }
        if (ps == 0 || *pe != '.') {
            len    = e - s;
            substr = s;
        }
        else {
            len    = pe - ps;
            substr = ps;
        }
        /* Actual increment */
        for (i = len - 1, carry = 1; i >= 0 && carry; i--) {
            if (isdigit((unsigned char)substr[i])) {
                if (++substr[i] <= '9') {
                    carry = 0;
                }
                else {
                    substr[i] = '0';
                    carry     = 1;
                }
            }
            else {
                if (isalpha((unsigned char)++substr[i])) {
                    carry = 0;
                }
                else {
                    substr[i] -= 'z' - 'a' + 1;
                    carry      = 1;
                }
            }
        }
        /* If there's a carry, extend the string */
        if (carry && len > 0) {
            /* start index of incrementable portion */
            INTVAL a = substr - start;
            /* length to end of string */
            INTVAL b = str->strlen - a;
            STRING *rep = string_substr(INTERP, str, a, b, NULL, 0);
            INTVAL  c   = '1';
            if (isalpha((unsigned char)start[a]))
                c = start[a];
            string_replace(INTERP, str, a + 1, b, rep, 0);
            string_replace(INTERP, str, a, 1, string_chr(INTERP, c), 0);
        }
    }
    VTABLE void decrement() {
        STRING      *str   = Parrot_unCOW_string(interp, PMC_str_val(SELF));
        char        *start = str->strstart;
        char * const end   = start + string_length(INTERP, str);
        /* pointer to the substring we're going to decrement */
        char *substr;
        /* length of the substring */
        INTVAL len;
        INTVAL i, steal;
        /* start of the current decrementable substring */
        char *s = start;
        /* end of the current decrementable substring */
        char *e = start;
        /* start of the previous decrementable substring */
        char *ps = 0;
        /* end of the previous decrementable substring */
        const char *pe = 0;
        /* Find the portion of the string to decrement */
        while (s < end) {
            while (!isalnum((unsigned char)*s) && s < end)
                s++;
            e = s;
            while (isalnum((unsigned char)*e) && e < end)
                e++;
            if (!(e < end))
                break;
            ps = s;
            pe = e;
            s = e;
        }
        if (ps == 0 || *pe != '.') {
            len    = e - s;
            substr = s;
        }
        else {
            len    = pe - ps;
            substr = ps;
        }
        /* Check if we've bottomed out on decrementing */
        for (i = 0; i < len; i++) {
            if (substr[i] != 'a' && substr[i] != 'A' && substr[i] != '0')
                break;
        }
        if (i == len)
            return;
        /* Actual decrement */
        for (i = len - 1, steal = 1; i >= 0 && steal; i--) {
            if (isdigit((unsigned char)substr[i])) {
                if (--substr[i] >= '0') {
                    steal = 0;
                }
                else {
                    substr[i] = '9';
                    steal     = 1;
                }
            }
            else {
                if (isalpha((unsigned char)--substr[i])) {
                    steal = 0;
                }
                else {
                    substr[i] += 'z' - 'a' + 1;
                    steal      = 1;
                }
            }
        }
    }
|  |   |