浏览代码

Updated some string methods and fixed unit test.

Marco Bambini 8 年之前
父节点
当前提交
4795b2913b
共有 2 个文件被更改,包括 52 次插入56 次删除
  1. 50 54
      src/runtime/gravity_core.c
  2. 2 2
      test/string/string_repeat_method.gravity

+ 50 - 54
src/runtime/gravity_core.c

@@ -1429,15 +1429,6 @@ static bool operator_string_neg (gravity_vm *vm, gravity_value_t *args, uint16_t
 	RETURN_VALUE(VALUE_FROM_OBJECT(string), rindex);
 }
 
-static bool string_length (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
-	#pragma unused(vm, nargs)
-	
-	DECLARE_1VARIABLE(v1, 0);
-	gravity_string_t *s1 = VALUE_AS_STRING(v1);
-	
-	RETURN_VALUE(VALUE_FROM_INT(s1->len), rindex);
-}
-
 static bool operator_string_cmp (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
 	
@@ -1450,29 +1441,33 @@ static bool operator_string_cmp (gravity_vm *vm, gravity_value_t *args, uint16_t
 	RETURN_VALUE(VALUE_FROM_INT(strcmp(s1->s, s2->s)), rindex);
 }
 
+static bool string_length (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+	#pragma unused(vm, nargs)
+	
+	DECLARE_1VARIABLE(v1, 0);
+	gravity_string_t *s1 = VALUE_AS_STRING(v1);
+	
+	RETURN_VALUE(VALUE_FROM_INT(s1->len), rindex);
+}
+
 static bool string_index (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	gravity_string_t *main_str     = VALUE_AS_STRING(GET_VALUE(0));
 
-	if (nargs != 2) {
-		RETURN_ERROR("String.index() expects 1 argument");
-	}
-	if (!VALUE_ISA_STRING(GET_VALUE(1))) {
+	if ((nargs != 2) || (!VALUE_ISA_STRING(GET_VALUE(1)))) {
 		RETURN_ERROR("String.index() expects a string as an argument");
 	}
-
+	
+	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_string_t *str_to_index = VALUE_AS_STRING(GET_VALUE(1));
 
-	char *ptr;
-
-	// Search for the string
-	ptr = strstr(main_str->s, str_to_index->s);
+	// search for the string
+	char *ptr = strstr(main_str->s, str_to_index->s);
 
-	// If it doesn't exist, return null
+	// if it doesn't exist, return null
 	if (ptr == NULL) {
 		RETURN_VALUE(VALUE_FROM_NULL, rindex);
 	}
-	// Otherwise, return the difference, which is the index that the string starts at
+	// otherwise, return the difference, which is the index that the string starts at
 	else {
 		RETURN_VALUE(VALUE_FROM_INT(ptr-main_str->s), rindex);
 	}
@@ -1480,23 +1475,21 @@ static bool string_index (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 static bool string_count (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	gravity_string_t *main_str     = VALUE_AS_STRING(GET_VALUE(0));
 
-	if (nargs != 2) {
-		RETURN_ERROR("String.count() expects 1 argument");
-	}
-	if (!VALUE_ISA_STRING(GET_VALUE(1))) {
+	if ((nargs != 2) || (!VALUE_ISA_STRING(GET_VALUE(1)))) {
 		RETURN_ERROR("String.count() expects a string as an argument");
 	}
+	
+	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_string_t *str_to_count = VALUE_AS_STRING(GET_VALUE(1));
 
 	int j = 0;
 	int count = 0;
 
-	// Iterate through whole string
+	// iterate through whole string
 	for (int i = 0; i < main_str->len; i++) {
 		if (main_str->s[i] == str_to_count->s[j]) {
-			// If the characters match and we are on the last character of the search
+			// if the characters match and we are on the last character of the search
 			// string, then we have found a match
 			if (j == str_to_count->len - 1) {
 				count++;
@@ -1504,12 +1497,12 @@ static bool string_count (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 				continue;
 			}
 		}
-		// Reset if it isn't a match
+		// reset if it isn't a match
 		else {
 			j = 0;
 			continue;
 		}
-		// Move forward in the search string if we found a match but we aren't
+		// move forward in the search string if we found a match but we aren't
 		// finished checking all the characters of the search string yet
 		j++;
 	}
@@ -1520,39 +1513,38 @@ static bool string_count (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 static bool string_repeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
-
-	if (nargs != 2) {
-		RETURN_ERROR("String.string_repeat() expects 1 argument");
-	}
-	if (!VALUE_ISA_INT(GET_VALUE(1))) {
-		RETURN_ERROR("String.string_repeat() expects an integer as an argument");
+	
+	if ((nargs != 2) || (!VALUE_ISA_INT(GET_VALUE(1)))) {
+		RETURN_ERROR("String.repeat() expects an integer argument");
 	}
+	
+	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_int_t times_to_repeat = VALUE_AS_INT(GET_VALUE(1));
-
 	if (times_to_repeat < 1) {
-		RETURN_ERROR("String.string_repeat() expects an integer >=1");
+		RETURN_ERROR("String.repeat() expects an integer >= 1");
 	}
 
-	// Figure out the size of the array we need to make to hold the new string
-	int new_size = main_str->len*times_to_repeat;
-	char new_str[new_size];
+	// figure out the size of the array we need to make to hold the new string
+	uint32_t new_size = (uint32_t)(main_str->len * times_to_repeat);
+	char new_str[new_size+1];
+	
+	// this code could be much faster with a memcpy
 	strcpy(new_str, main_str->s);
-	for (int i = 0; i < times_to_repeat-1; i++) {
+	for (int i = 0; i < times_to_repeat-1; ++i) {
 		strcat(new_str, main_str->s);
 	}
 
-	RETURN_VALUE(VALUE_FROM_STRING(vm, new_str, strlen(new_str)), rindex);
+	RETURN_VALUE(VALUE_FROM_CSTRING(vm, new_str), rindex);
 }
 
 static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
 	if (nargs != 1) {
 		RETURN_ERROR("String.upper() expects no argument");
 	}
-
+	
+	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	for (int i = 0; i < main_str->len; i++) {
 		main_str->s[i] = toupper(main_str->s[i]);
 	}
@@ -1562,12 +1554,12 @@ static bool string_upper (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 static bool string_lower (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs)
-	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 
 	if (nargs != 1) {
 		RETURN_ERROR("String.lower() expects no argument");
 	}
 
+	gravity_string_t *main_str = VALUE_AS_STRING(GET_VALUE(0));
 	for (int i = 0; i < main_str->len; i++) {
 		main_str->s[i] = tolower(main_str->s[i]);
 	}
@@ -1581,11 +1573,12 @@ static bool string_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 	gravity_value_t value = GET_VALUE(1);
 	if (!VALUE_ISA_INT(value)) RETURN_ERROR("An integer index is required to access a string item.");
 	
-	register int32_t index = (int32_t)VALUE_AS_INT(value);
+	int32_t index = (int32_t)VALUE_AS_INT(value);
 	
 	if (index < 0) index = string->len + index;
 	if ((index < 0) || ((uint32_t)index >= string->len)) RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, string->len-1);
 
+	// this code is not UTF-8 safe
 	char c[2] = "\0";
 	c[0] = string->s[index];
 	
@@ -1594,24 +1587,27 @@ static bool string_loadat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs
 
 static bool string_storeat (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
 	#pragma unused(vm, nargs, rindex)
+	
 	gravity_string_t *string = VALUE_AS_STRING(GET_VALUE(0));
 	gravity_value_t idxvalue = GET_VALUE(1);
 	if (!VALUE_ISA_INT(idxvalue)) RETURN_ERROR("An integer index is required to access a string item.");
 	if (!VALUE_ISA_STRING(GET_VALUE(2))) RETURN_ERROR("A string needs to be assigned to a string index");
 
 	gravity_string_t *value = VALUE_AS_STRING(GET_VALUE(2));
-
-	/* if (value->len != 1) RETURN_ERROR("Assigned string must be one character long."); */
-	
 	register int32_t index = (int32_t)VALUE_AS_INT(idxvalue);
 	
 	if (index < 0) index = string->len + index;
 	if (index < 0 || index >= string->len) RETURN_ERROR("Out of bounds error: index %d beyond bounds 0...%d", index, string->len-1);
 	if (index+value->len - 1 >= string->len) RETURN_ERROR("Out of bounds error: End of inserted string exceeds the length of the initial string");
 
-	for (int i = index; i < index+value->len; i++) {
-	 string->s[i] = value->s[i-index];
+	// this code is not UTF-8 safe
+	for (int i = index; i < index+value->len; ++i) {
+		string->s[i] = value->s[i-index];
 	}
+	
+	// characters inside string changed so we need to re-compute hash
+	string->hash = gravity_hash_compute_buffer((const char *)string->s, string->len);
+	
 	RETURN_NOVALUE();
 }
 
@@ -2010,7 +2006,7 @@ static void gravity_core_init (void) {
 	gravity_class_bind(gravity_class_string, "length", VALUE_FROM_OBJECT(computed_property(NULL, NEW_FUNCTION(string_length), NULL)));
 	gravity_class_bind(gravity_class_string, "index", NEW_CLOSURE_VALUE(string_index));
 	gravity_class_bind(gravity_class_string, "count", NEW_CLOSURE_VALUE(string_count));
-	gravity_class_bind(gravity_class_string, "string_repeat", NEW_CLOSURE_VALUE(string_repeat));
+	gravity_class_bind(gravity_class_string, "repeat", NEW_CLOSURE_VALUE(string_repeat));
 	gravity_class_bind(gravity_class_string, "upper", NEW_CLOSURE_VALUE(string_upper));
 	gravity_class_bind(gravity_class_string, "lower", NEW_CLOSURE_VALUE(string_lower));
 	

+ 2 - 2
test/string/string_repeat_method.gravity

@@ -6,7 +6,7 @@
 
 func main () {
 	var s = "Hello World"
-	var b = s.string_repeat(3) == "Hello WorldHello WorldHello World"
-	var c = s.string_repeat(1) == s
+	var b = s.repeat(3) == "Hello WorldHello WorldHello World"
+	var c = s.repeat(1) == s
 	return b && c
 }