Browse Source

test this more

Steven Hall 8 years ago
parent
commit
268775f970
1 changed files with 135 additions and 22 deletions
  1. 135 22
      src/runtime/gravity_core.c

+ 135 - 22
src/runtime/gravity_core.c

@@ -1536,41 +1536,154 @@ static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 }
 
 static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
-	if (nargs != 1) {
-		RETURN_ERROR("String.upper() expects no argument");
-	}
-	
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
-	// I don't want this function to modify the main_str directly. I just want
-	// this method to return a new capitalized string, so copy main_str to a
-	// different string and manipulate that.
-	char new_str[main_str->len + 1]; // + 1 for the null character
+	char ret[main_str->len + 1];
+	strcpy(ret, main_str->s);
 
-	for (int i = 0; i <= main_str->len; i++) {
-		new_str[i] = toupper(main_str->s[i]);
+	// if no arguments passed, change case of the whole string
+	if (nargs == 1) {
+		for (int i = 0; i <= main_str->len; i++) {
+		 ret[i] = toupper(ret[i]);
+		}
 	}
+	// otherwise, evaluate all the arguments
+	else {
+		for (int i = 1; i < nargs; ++i) {
+			gravity_value_t value = GET_VALUE(i);
 
-	RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
-}
+			// If argument is an integer, capitalize the character specified by that integer
+			if (VALUE_ISA_INT(value)) {
+				int32_t index = (int32_t)VALUE_AS_INT(value);
 
-static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
-	if (nargs != 1) {
-		RETURN_ERROR("String.lower() expects no argument");
+				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]);
+			}
+			// If argument is a string, capitalize the characters specified by that string
+			else if (VALUE_ISA_STRING(value)) {
+				// TODO: right now this will infinite loop if we are passed a uppercase string
+				gravity_string_t *search_str = VALUE_AS_STRING(value);
+
+				// Check if all of search_string is already uppercase
+				bool is_all_upper = true;
+				for (int j = 0; j < search_str->len; ++j) {
+					if (!isupper(search_str->s[j])) {
+						is_all_upper = false;
+						break;
+					}
+				}
+
+				// If it is all uppercase already, go to the next argument
+				if (is_all_upper) {
+				 continue;
+				}
+
+				// Otherwise, parse it, and uppercase it.
+				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 (isupper(ret[j])) {
+						 // Skip if it is already uppercase
+						 continue;
+						}
+						ret[j] = toupper(ret[j]);
+					}
+				} while(1); // Breaks out when no matches are found
+				            // This results in an infinite loop if the user searches for
+				            // a string that is already uppercase completely. Hence, the
+				            // check further up
+			}
+			else {
+			 RETURN_ERROR("upper() expects either no arguments, or arguments that are Strings or Ints only.");
+			}
+
+		}
 	}
+	RETURN_VALUE(VALUE_FROM_CSTRING(vm, ret), rindex);
+}
 
+static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
-	// I don't want this function to modify the main_str directly. I just want
-	// this method to return a new capitalized string, so copy main_str to a
-	// different string and manipulate that.
-	char new_str[main_str->len + 1]; // + 1 for the null character
+	char ret[main_str->len + 1];
+	strcpy(ret, main_str->s);
 
-	for (int i = 0; i <= main_str->len; i++) {
-		new_str[i] = tolower(main_str->s[i]);
+	// if no arguments passed, change case of the whole string
+	if (nargs == 1) {
+		for (int i = 0; i <= main_str->len; i++) {
+		 ret[i] = tolower(ret[i]);
+		}
 	}
+	// otherwise, evaluate all the arguments
+	else {
+		for (int i = 1; i < nargs; ++i) {
+			gravity_value_t value = GET_VALUE(i);
 
-	RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
+			// If argument is an integer, change case to lower the character specified by that integer
+			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]);
+			}
+			// 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 lowercase
+				bool is_all_lower = true;
+				for (int j = 0; j < search_str->len; ++j) {
+					if (!islower(search_str->s[j])) {
+						is_all_lower = false;
+						break;
+					}
+				}
+
+				// If it is all lowercase already, go to the next argument
+				if (is_all_lower) {
+				 continue;
+				}
+
+				// Otherwise, parse it, and lowercase it.
+				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 (islower(ret[j])) {
+						 // Skip if it is already lowercase
+						 continue;
+						}
+						ret[j] = tolower(ret[j]);
+					}
+				} while(1); // Breaks out when no matches are found
+				            // This results in an infinite loop if the user searches for
+				            // a string that is already lowercase completely. Hence, the
+				            // check further up
+			}
+			else {
+			 RETURN_ERROR("lower() expects either no arguments, or arguments that are Strings or Ints only.");
+			}
+
+		}
+	}
+	RETURN_VALUE(VALUE_FROM_CSTRING(vm, ret), rindex);
 }
 
 static bool string_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {