Explorar o código

SCDString removal and copy functions

Aaro Saila hai 1 mes
pai
achega
7882bd4d19
Modificáronse 5 ficheiros con 147 adicións e 10 borrados
  1. 4 0
      include/scufcont/DString.h
  2. 2 1
      include/scufcont/scufcont.h
  3. 55 0
      src/DString.c
  4. 78 0
      tests/cmocka/DString_tests.c
  5. 8 9
      tests/cmocka/main.c

+ 4 - 0
include/scufcont/DString.h

@@ -20,6 +20,7 @@ typedef struct {
 ScufContResult SCDString_alloc(SCDString *const dstr, const char *str, const size_t len);
 ScufContResult SCDString_reserve(SCDString *const dstr, const size_t new_capacity);
 void SCDString_free(SCDString *const dstr);
+ScufContResult SCDString_copy(const SCDString *const src, SCDString *const dst);
 bool SCDString_equal(const SCDString *const s1, const SCDString *s2);
 bool SCDString_equal_c_str(const SCDString *const s1, const char *s2);
 bool SCDString_equal_next_chars_c_str(
@@ -48,5 +49,8 @@ ScufContResult SCDString_split(
     size_t *const arr_len
 );
 void SCDString_split_arr_free(SCDString **const arr, const size_t arr_len);
+ScufContResult SCDString_char_mod(SCDString *const dstr, const size_t at, const char ch);
+ScufContResult SCDString_char_remove_no_resize(SCDString *const dstr, const size_t at);
+ScufContResult SCDString_char_remove(SCDString *const dstr, const size_t at);
 
 #endif // SCUFCONT_DSTRING_H_

+ 2 - 1
include/scufcont/scufcont.h

@@ -3,7 +3,8 @@
 
 #define SCUFCONT_RESULT_X(X) \
     X(SCUFCONT_SUCCESS) \
-    X(SCUFCONT_OUT_OF_MEMORY)
+    X(SCUFCONT_OUT_OF_MEMORY) \
+    X(SCUFCONT_OUT_OF_BOUNDS)
 
 #define X(val) val,
 

+ 55 - 0
src/DString.c

@@ -41,6 +41,30 @@ void SCDString_free(SCDString *const dstr) {
     dstr->capacity = 0;
 }
 
+void SCDString_resize_to_fit(SCDString *const dstr) {
+    if (dstr->capacity > dstr->len + 1) {
+        dstr->capacity = dstr->len + 1;
+        dstr->data = (char *) realloc(dstr->data, dstr->capacity);
+    }
+}
+
+/**
+  @param dst Must have been allocated with one of the allocation functions.
+*/
+ScufContResult SCDString_copy(const SCDString *const src, SCDString *const dst) {
+    ScufContResult res = SCDString_reserve(dst, src->len + 1);
+    if (res != SCUFCONT_SUCCESS) {
+        return res;
+    }
+
+    dst->len = src->len;
+
+    memcpy(dst->data, src->data, dst->len);
+    dst->data[dst->len] = '\0';
+
+    return SCUFCONT_SUCCESS;
+}
+
 bool SCDString_equal(const SCDString *const s1, const SCDString *const s2) {
     if (s1->data == NULL || s2->data == NULL) {
         return false;
@@ -212,3 +236,34 @@ void SCDString_split_arr_free(SCDString **const arr, const size_t arr_len) {
     free(*arr);
     *arr = NULL;
 }
+
+ScufContResult SCDString_char_mod(SCDString *const dstr, const size_t at, const char ch) {
+    if (at > dstr->len - 1) {
+        return SCUFCONT_OUT_OF_BOUNDS;
+    }
+
+    dstr->data[at] = ch;
+
+    return SCUFCONT_SUCCESS;
+}
+
+ScufContResult SCDString_char_remove_no_resize(SCDString *const dstr, const size_t at) {
+    if (at > dstr->len - 1) {
+        return SCUFCONT_OUT_OF_BOUNDS;
+    }
+    memmove(&dstr->data[at], &dstr->data[at] + 1, dstr->len - at);
+    dstr->len--;
+
+    return SCUFCONT_SUCCESS;
+}
+
+ScufContResult SCDString_char_remove(SCDString *const dstr, const size_t at) {
+    const ScufContResult res = SCDString_char_remove_no_resize(dstr, at);
+    if (res != SCUFCONT_SUCCESS) {
+        return res;
+    }
+
+    SCDString_resize_to_fit(dstr);
+
+    return SCUFCONT_SUCCESS;
+}

+ 78 - 0
tests/cmocka/DString_tests.c

@@ -34,6 +34,26 @@ void test_SCDString_free(void **state) {
     assert_true(dstr.capacity == 0);
 }
 
+void test_SCDString_copy(void **state) {
+    (void) state;
+
+    SCDString dstr1;
+    assert_true(SCDString_alloc(&dstr1, "Hello", strlen("Hello")) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr1), "Hello");
+
+    SCDString dstr2;
+    assert_true(SCDString_alloc(&dstr2, "foo", strlen("foo")) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr2), "foo");
+
+    assert_true(SCDString_copy(&dstr1, &dstr2) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr2), "Hello");
+    assert_uint_equal(dstr2.len, dstr1.len);
+    assert_uint_equal(dstr2.capacity, dstr1.len + 1);
+
+    SCDString_free(&dstr1);
+    SCDString_free(&dstr2);
+}
+
 void test_SCDString_equal(void **state) {
     (void) state;
 
@@ -102,6 +122,8 @@ void test_SCDString_concat_char(void **state) {
 
     SCDString_concat_char(&dstr, 'y');
     assert_string_equal(dstr.data, "Worldly");
+
+    SCDString_free(&dstr);
 }
 
 void test_SCDString_concat_c_str(void **state) {
@@ -164,10 +186,64 @@ void test_SCDString_split(void **state) {
     assert_true(arr == NULL);
 }
 
+void test_SCDString_char_mod(void **state) {
+    (void) state;
+
+    SCDString dstr;
+    assert_true(SCDString_alloc(&dstr, "foo", strlen("foo")) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), "foo");
+
+    assert_true(SCDString_char_mod(&dstr, 0, 'h') == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), "hoo");
+
+    assert_true(SCDString_char_mod(&dstr, 1, 'a') == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), "hao");
+
+    assert_true(SCDString_char_mod(&dstr, 2, 'b') == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), "hab");
+
+    assert_true(SCDString_char_mod(&dstr, 3, 'b') == SCUFCONT_OUT_OF_BOUNDS);
+    assert_string_equal(SCDString_c_str(&dstr), "hab");
+
+    SCDString_free(&dstr);
+}
+
+void test_SCDString_char_remove(void **state) {
+    (void) state;
+
+    char *text = "World";
+    SCDString dstr;
+    assert_true(SCDString_alloc(&dstr, text, strlen(text)) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), text);
+    assert_uint_equal(dstr.len, strlen(text));
+
+    text = "Worl";
+    assert_true(SCDString_char_remove(&dstr, dstr.len - 1) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), text);
+    assert_uint_equal(dstr.len, strlen(text));
+
+    text = "Wol";
+    assert_true(SCDString_char_remove(&dstr, 2) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), text);
+    assert_uint_equal(dstr.len, strlen(text));
+
+    text = "ol";
+    assert_true(SCDString_char_remove(&dstr, 0) == SCUFCONT_SUCCESS);
+    assert_string_equal(SCDString_c_str(&dstr), text);
+    assert_uint_equal(dstr.len, strlen(text));
+
+    assert_true(SCDString_char_remove(&dstr, dstr.len) == SCUFCONT_OUT_OF_BOUNDS);
+    assert_string_equal(SCDString_c_str(&dstr), text);
+    assert_uint_equal(dstr.len, strlen(text));
+
+    SCDString_free(&dstr);
+}
+
 int DString_tests_run(void) {
     const struct CMUnitTest tests[] = {
         cmocka_unit_test(test_SCDString_alloc),
         cmocka_unit_test(test_SCDString_free),
+        cmocka_unit_test(test_SCDString_copy),
         cmocka_unit_test(test_SCDString_equal),
         cmocka_unit_test(test_SCDString_equal_c_str),
         cmocka_unit_test(test_SCDString_equal_next_chars_c_str),
@@ -175,6 +251,8 @@ int DString_tests_run(void) {
         cmocka_unit_test(test_SCDString_concat_c_str),
         cmocka_unit_test(test_SCDString_c_str),
         cmocka_unit_test(test_SCDString_split),
+        cmocka_unit_test(test_SCDString_char_mod),
+        cmocka_unit_test(test_SCDString_char_remove),
     };
 
     return cmocka_run_group_tests_name("DString", tests, NULL, NULL);

+ 8 - 9
tests/cmocka/main.c

@@ -1,20 +1,19 @@
 #include <cmocka.h>
 
+#define RUN_SUITE(suite)      \
+        failed = suite(); \
+        if (failed) {         \
+            return failed;    \
+        }                     \
+
 int DString_tests_run(void);
 int DArray_tests_run(void);
 
 int main(void) {
     int failed = 0;
 
-    failed = DString_tests_run();
-    if (failed) {
-        return failed;
-    }
-    failed = DArray_tests_run();
-    if (failed) {
-        return failed;
-    }
+    RUN_SUITE(DString_tests_run);
+    RUN_SUITE(DArray_tests_run);
 
     return failed;
 }
-