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 = PMC_str_val(SELF);
const 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 */
const char *s = start;
/* end of the current incrementable substring */
const char *e = start;
/* start of the previous incrementable substring */
const 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 = (char *)s;
}
else {
len = pe - ps;
substr = (char*)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 = PMC_str_val(SELF);
const char *start = str->strstart;
const 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 */
const char *s = start;
/* end of the current decrementable substring */
const char *e = start;
/* start of the previous decrementable substring */
const 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 = (char *)s;
}
else {
len = pe - ps;
substr = (char *)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;
}
}
}
}
|