Browse Source

Merge pull request #112 from hallzy/str-split

Added a String.split() method.
Marco Bambini 8 years ago
parent
commit
935847ca42

+ 6 - 0
docs/types.html

@@ -124,6 +124,12 @@
 	// upper() and lower() can both take multiple integer arguments
 	n = b.upper(1, -1)     // n is now "HEllo WorlD"
 
+	// split() is the opposite of a list join
+	var string = "Roses are Red, Violets are Blue"
+	var list = string.split(", ")
+	list[0]                // "Roses are Red"
+	list[1]                // "Violets are Blue"
+
 	// You are also able to edit strings by character...
 	b[0] = "Z"              // b is now "Zello World"
 	b[1] = "abc"            // b is now "Zabco World"

+ 26 - 0
src/runtime/gravity_core.c

@@ -1677,6 +1677,31 @@ static bool string_storeat (gravity_vm *vm, gravity_value_t *args, uint16_t narg
 	RETURN_NOVALUE();
 }
 
+static bool string_split (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+	gravity_string_t *string = VALUE_AS_STRING(GET_VALUE(0));
+	const char *sep = NULL;
+	if ((nargs == 2) && VALUE_ISA_STRING(GET_VALUE(1))) sep = VALUE_AS_CSTRING(GET_VALUE(1));
+	else RETURN_ERROR("String.split() expects 1 string separator.");
+
+	// Initialize the list to have a size of 0
+	gravity_list_t *list = gravity_list_new(vm, 0);
+
+	char *str = strdup(string->s);
+
+	while (1) {
+		char *to_push = strdup(str);
+		char *p = strstr(str, sep);
+		if (p == NULL) {
+			marray_push(gravity_value_t, list->array, VALUE_FROM_STRING(vm, to_push, strlen(to_push)));
+			break;
+		}
+		to_push[strlen(str) - strlen(p)] = '\0';
+		str = p + strlen(sep);
+		marray_push(gravity_value_t, list->array, VALUE_FROM_STRING(vm, to_push, strlen(to_push)));
+	}
+	RETURN_VALUE(VALUE_FROM_OBJECT(list), rindex);
+}
+
 // MARK: - Fiber Class -
 
 static bool fiber_create (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
@@ -2072,6 +2097,7 @@ static void gravity_core_init (void) {
 	gravity_class_bind(gravity_class_string, GRAVITY_OPERATOR_NEG_NAME, NEW_CLOSURE_VALUE(operator_string_neg));
 	gravity_class_bind(gravity_class_string, GRAVITY_INTERNAL_LOADAT_NAME, NEW_CLOSURE_VALUE(string_loadat));
 	gravity_class_bind(gravity_class_string, GRAVITY_INTERNAL_STOREAT_NAME, NEW_CLOSURE_VALUE(string_storeat));
+	gravity_class_bind(gravity_class_string, "split", NEW_CLOSURE_VALUE(string_split));
 	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));

+ 21 - 0
test/string/complex_split.gravity

@@ -0,0 +1,21 @@
+#unittest {
+	name: "Complex split() Test";
+	error: NONE;
+	result: true;
+};
+
+func main () {
+	var s = "1, ,2, ,3, ,4, ,5, ,6, ,7, ,8, ,9, ,10"
+  var list = s.split(", ,")
+
+	var ret = true;
+
+	var expected = 0
+	list.loop( func(value) {
+		expected += 1
+		ret = ret and value == expected.String()
+	})
+
+	// Check expected just to make sure the loop actually ran
+	return ret and expected == 10
+}

+ 12 - 0
test/string/no-split.gravity

@@ -0,0 +1,12 @@
+#unittest {
+	name: "No split() Test";
+	error: NONE;
+	result: true;
+};
+
+func main () {
+	var s = "1 2 3 4 5 6 7 8 9 10"
+  var list = s.split("=")
+
+  return list[0] == s and list.count == 1
+}

+ 21 - 0
test/string/split.gravity

@@ -0,0 +1,21 @@
+#unittest {
+	name: "Basic split() Test";
+	error: NONE;
+	result: true;
+};
+
+func main () {
+	var s = "1 2 3 4 5 6 7 8 9 10"
+  var list = s.split(" ")
+
+	var ret = true;
+
+	var expected = 0
+	list.loop( func(value) {
+		expected += 1
+		ret = ret and value == expected.String()
+	})
+
+	// Check expected just to make sure the loop actually ran
+	return ret and expected == 10
+}

+ 9 - 0
test/string/split_runtime_error.gravity

@@ -0,0 +1,9 @@
+#unittest {
+	name: "Error split() Test";
+	error: RUNTIME;
+};
+
+func main () {
+	var s = "1 2 3 4 5 6 7 8 9 10"
+  var list = s.split("=", " ")
+}