|
@@ -1535,82 +1535,13 @@ static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
|
|
RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
|
|
RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-// Returns -1 for out of bounds error
|
|
|
|
-// Returns -2 if we exit the loop wrong.
|
|
|
|
-// Returns 0 otherwise
|
|
|
|
-// Also return function arguments: index and ret
|
|
|
|
-// index: will help us to print out a runtime error if we go out of bounds
|
|
|
|
-// ret: is the returned string that our upper() and lower() methods return.
|
|
|
|
-static int parse_arguments_for_upper_and_lower(gravity_vm *vm, int (*is_case)(int), int (*to_case)(int), gravity_value_t value, int32_t *index, char *ret, int ret_len) {
|
|
|
|
- // If argument is an integer, capitalize the character specified by that integer
|
|
|
|
- if (VALUE_ISA_INT(value)) {
|
|
|
|
- *index = (int32_t)VALUE_AS_INT(value);
|
|
|
|
-
|
|
|
|
- if (*index < 0) *index = ret_len + *index;
|
|
|
|
- if ((*index < 0) || ((uint32_t)*index >= ret_len)) return -1;
|
|
|
|
-
|
|
|
|
- ret[*index] = to_case(ret[*index]);
|
|
|
|
- }
|
|
|
|
- // If argument is a string, capitalize the characters specified by that string
|
|
|
|
- else if (VALUE_ISA_STRING(value)) {
|
|
|
|
- gravity_string_t *search_str = VALUE_AS_STRING(value);
|
|
|
|
-
|
|
|
|
- // Check if all of search_string is already the case we want
|
|
|
|
- bool is_all_correct_case = true;
|
|
|
|
- for (int j = 0; j < search_str->len; ++j) {
|
|
|
|
- // Better also make sure that it is an alpha character.
|
|
|
|
- if (!is_case(search_str->s[j]) && isalpha(search_str->s[j])) {
|
|
|
|
- is_all_correct_case = false;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // If it is all the correct case already, go to the next argument
|
|
|
|
- if (is_all_correct_case) {
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Otherwise, parse it, and change the case
|
|
|
|
- int iterations = 0;
|
|
|
|
- bool isNotInfiniteLoop;
|
|
|
|
- do {
|
|
|
|
- char *ptr = strstr(ret, search_str->s);
|
|
|
|
-
|
|
|
|
- if (ptr == NULL) {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- int match_index_ret = ptr - ret;
|
|
|
|
-
|
|
|
|
- for (int j = match_index_ret; j < match_index_ret + search_str->len; ++j) {
|
|
|
|
- if (is_case(ret[j])) {
|
|
|
|
- // Skip if it is already the correct case
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- ret[j] = to_case(ret[j]);
|
|
|
|
- }
|
|
|
|
- ++iterations;
|
|
|
|
- } while(isNotInfiniteLoop = iterations < ret_len);
|
|
|
|
- // Breaks out when no matches are found
|
|
|
|
- // We should never break out of this loop by this while
|
|
|
|
- // condition, as we should break out once we have no more
|
|
|
|
- // matches (when ptr == NULL). This is just a fail safe.
|
|
|
|
- if (!isNotInfiniteLoop) {
|
|
|
|
- return -2;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
|
|
static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
|
|
gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
|
|
gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
|
|
|
|
|
|
char ret[main_str->len + 1];
|
|
char ret[main_str->len + 1];
|
|
strcpy(ret, main_str->s);
|
|
strcpy(ret, main_str->s);
|
|
- int err;
|
|
|
|
|
|
|
|
- // if no arguments passed, change case of the whole string
|
|
|
|
|
|
+ // if no arguments passed, change the whole string to uppercase
|
|
if (nargs == 1) {
|
|
if (nargs == 1) {
|
|
for (int i = 0; i <= main_str->len; i++) {
|
|
for (int i = 0; i <= main_str->len; i++) {
|
|
ret[i] = toupper(ret[i]);
|
|
ret[i] = toupper(ret[i]);
|
|
@@ -1620,22 +1551,16 @@ static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
|
|
else {
|
|
else {
|
|
for (int i = 1; i < nargs; ++i) {
|
|
for (int i = 1; i < nargs; ++i) {
|
|
gravity_value_t value = GET_VALUE(i);
|
|
gravity_value_t value = GET_VALUE(i);
|
|
- int32_t index = (int32_t)VALUE_AS_INT(value);
|
|
|
|
- // if the argument is a string or int, proceed, otherwise we throw a
|
|
|
|
- // runtime error
|
|
|
|
- if (VALUE_ISA_STRING(value) || VALUE_ISA_INT(value)) {
|
|
|
|
- // new string is returned by the "ret" argument
|
|
|
|
- err = parse_arguments_for_upper_and_lower(vm, isupper, toupper, value, &index, ret, strlen(ret));
|
|
|
|
|
|
+ if (VALUE_ISA_INT(value)) {
|
|
|
|
+ int32_t index = (int32_t)VALUE_AS_INT(value);
|
|
|
|
+
|
|
|
|
+ if (index < 0) index = main_str->len + index;
|
|
|
|
+ if ((index < 0) || ((uint32_t)index >= main_str->len)) RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, main_str->len-1);
|
|
|
|
+
|
|
|
|
+ ret[index] = toupper(ret[index]);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- RETURN_ERROR("upper() expects either no arguments, or arguments that are Strings or Ints only.");
|
|
|
|
- }
|
|
|
|
- // If the parse through a -1 error, the argument was ou of bounds
|
|
|
|
- if (err == -1) {
|
|
|
|
- RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, main_str->len-1);
|
|
|
|
- }
|
|
|
|
- else if (err == -2) {
|
|
|
|
- RETURN_ERROR("search parse ran into an infinite loop");
|
|
|
|
|
|
+ RETURN_ERROR("upper() expects either no arguments, or integer arguments.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1647,9 +1572,8 @@ static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
|
|
|
|
|
|
char ret[main_str->len + 1];
|
|
char ret[main_str->len + 1];
|
|
strcpy(ret, main_str->s);
|
|
strcpy(ret, main_str->s);
|
|
- int err;
|
|
|
|
|
|
|
|
- // if no arguments passed, change case of the whole string
|
|
|
|
|
|
+ // if no arguments passed, change the whole string to lowercase
|
|
if (nargs == 1) {
|
|
if (nargs == 1) {
|
|
for (int i = 0; i <= main_str->len; i++) {
|
|
for (int i = 0; i <= main_str->len; i++) {
|
|
ret[i] = tolower(ret[i]);
|
|
ret[i] = tolower(ret[i]);
|
|
@@ -1659,22 +1583,16 @@ static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
|
|
else {
|
|
else {
|
|
for (int i = 1; i < nargs; ++i) {
|
|
for (int i = 1; i < nargs; ++i) {
|
|
gravity_value_t value = GET_VALUE(i);
|
|
gravity_value_t value = GET_VALUE(i);
|
|
- int32_t index = (int32_t)VALUE_AS_INT(value);
|
|
|
|
- // if the argument is a string or int, proceed, otherwise we throw a
|
|
|
|
- // runtime error
|
|
|
|
- if (VALUE_ISA_STRING(value) || VALUE_ISA_INT(value)) {
|
|
|
|
- // new string is returned by the "ret" argument
|
|
|
|
- err = parse_arguments_for_upper_and_lower(vm, islower, tolower, value, &index, ret, strlen(ret));
|
|
|
|
|
|
+ if (VALUE_ISA_INT(value)) {
|
|
|
|
+ int32_t index = (int32_t)VALUE_AS_INT(value);
|
|
|
|
+
|
|
|
|
+ if (index < 0) index = main_str->len + index;
|
|
|
|
+ if ((index < 0) || ((uint32_t)index >= main_str->len)) RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, main_str->len-1);
|
|
|
|
+
|
|
|
|
+ ret[index] = tolower(ret[index]);
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- RETURN_ERROR("lower() expects either no arguments, or arguments that are Strings or Ints only.");
|
|
|
|
- }
|
|
|
|
- // If the parse through a -1 error, the argument was ou of bounds
|
|
|
|
- if (err == -1) {
|
|
|
|
- RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, main_str->len-1);
|
|
|
|
- }
|
|
|
|
- else if (err == -2) {
|
|
|
|
- RETURN_ERROR("search parse ran into an infinite loop");
|
|
|
|
|
|
+ RETURN_ERROR("lower() expects either no arguments, or integer arguments.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|