]> Kevux Git Server - fll/commitdiff
Bugfix: The f_memory array append and append all need to allow for sources to be...
authorKevin Day <Kevin@kevux.org>
Sun, 7 Jul 2024 03:05:54 +0000 (22:05 -0500)
committerKevin Day <Kevin@kevux.org>
Sun, 7 Jul 2024 03:07:56 +0000 (22:07 -0500)
A valid array that is not allocated will have a size of 0.
Passing these to the function should not result in an error.
If the size is 0, then there is nothing to copy even though array is NULL
This is all fine.

Update the documentation comments to be more explicit on NULL in the parameters.

level_0/f_memory/c/memory/array.c
level_0/f_memory/c/memory/array.h
level_0/f_memory/tests/unit/c/test-memory-array_append.c
level_0/f_memory/tests/unit/c/test-memory-array_append_all.c

index 15530f9274a566ebeca19838a870253b7e8e1304..d80db1d1ecab6aac39b9ee3b98a9d33b79e98ef9 100644 (file)
@@ -23,13 +23,13 @@ extern "C" {
 #ifndef _di_f_memory_array_append_
   f_status_t f_memory_array_append(const void * const source, const size_t width, void ** const array, f_number_unsigned_t * restrict const used, f_number_unsigned_t * restrict const size) {
     #ifndef _di_level_0_parameter_checking_
-      if (!source) return F_status_set_error(F_parameter);
       if (!width) return F_status_set_error(F_parameter);
       if (!array) return F_status_set_error(F_parameter);
       if (!used) return F_status_set_error(F_parameter);
       if (!size) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
+    if (!source) return F_data_not;
     if (*used >= F_number_t_size_unsigned_d) return F_status_set_error(F_array_too_large);
 
     {
@@ -55,11 +55,13 @@ extern "C" {
 #ifndef _di_f_memory_array_append_all_
   f_status_t f_memory_array_append_all(const void * const sources, const f_number_unsigned_t amount, const size_t width, void ** const array, f_number_unsigned_t * restrict const used, f_number_unsigned_t * restrict const size) {
     #ifndef _di_level_0_parameter_checking_
-      if (!sources) return F_status_set_error(F_parameter);
       if (!width) return F_status_set_error(F_parameter);
       if (!array) return F_status_set_error(F_parameter);
       if (!used) return F_status_set_error(F_parameter);
       if (!size) return F_status_set_error(F_parameter);
+
+      // Sources might be un-allocated, so this is not actually an error if amount is 0.
+      if (!sources && amount) return F_status_set_error(F_parameter);
     #endif // _di_level_0_parameter_checking_
 
     if (!amount) return F_data_not;
index 86e848206036acafe693373fc3f7806ea6502e57..3e68c3d6f1baa58e1036e766ad69e66e2a893a84 100644 (file)
@@ -27,14 +27,21 @@ extern "C" {
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *
@@ -53,10 +60,13 @@ extern "C" {
  * If the simple type that is "array" requires additional memory manipulation on allocation or de-allocation, then do not use this function.
  *
  * @param source
- *   The source structure to copy from.
+ *   A pointer to the source structure to copy from.
+ *
+ *   May be NULL, which means source is not allocated.
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array destination.
@@ -75,13 +85,20 @@ extern "C" {
  *       ...
  *       f_memory_array_append(source, width, (void **) &arr_pounter, used, size);
  *     }
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used destination.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size destination.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
+ *   F_data_not on success but source is NULL.
  *
  *   F_array_too_large (with error bit) if the new array length is too large.
  *   F_memory_not (with error bit) on out of memory.
@@ -101,14 +118,18 @@ extern "C" {
  *          Be careful that the resulting multiplication does not overflow f_number_unsigned_t.
  *
  * @param sources
- *   The source structure to copy from.
+ *   A pointer to the source structure to copy from.
  *   This is generally a structure.array value.
+ *
+ *   May be NULL when amount is 0, which means sources is not allocated.
+ *   May not be NULL when amount is greater than 0.
  * @param amount
  *   The total length of the sources to copy.
  *   The is generally the structure.used value.
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array destination.
@@ -129,9 +150,13 @@ extern "C" {
  *     }
  * @param used
  *   The structure.used destination.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size destination.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *   F_data_not if amount is 0.
@@ -159,14 +184,21 @@ extern "C" {
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *
@@ -192,14 +224,21 @@ extern "C" {
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *
@@ -218,18 +257,26 @@ extern "C" {
  *
  * @param step
  *   The allocation step to use.
- *   Must be greater than 0.
+ *
+ *   Must not be 0.
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *   F_data_not on success, but there is no reason to increase size (used + 1 <= size).
@@ -255,14 +302,21 @@ extern "C" {
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *   F_data_not on success, but there is no reason to increase size (used + amount <= size).
@@ -286,14 +340,21 @@ extern "C" {
  * @param width
  *   The size of the structure represented by array.
  *   The word "width" is used due to conflicts of already using "length" and "size".
+ *
  *   Must not be 0.
  * @param array
  *   The structure.array to resize.
+ *
+ *   Must not be NULL.
  * @param used
  *   The structure.used.
+ *
+ *   Must not be NULL.
  * @param size
  *   The structure.size.
  *
+ *   Must not be NULL.
+ *
  * @return
  *   F_okay on success.
  *
index 4c8606f8b91d69ce9d4e44f49e16495ba8ee560b..259d030e1729e57d327fc1b5adc76a2fe507e307 100644 (file)
@@ -10,8 +10,17 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   const int number = 1;
   test_memory_array_t data = test_memory_array_t_initialize;
 
+  // In this case, the usual parameter checking must not return F_parameter error when source is NULL.
   {
-    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), 0, 0, 0);
+    const f_status_t status = f_memory_array_append(0, sizeof(int), (void **) &data.array, &data.used, &data.size);
+
+    assert_int_equal(status, F_data_not);
+    assert_int_equal(data.used, 0);
+    assert_int_equal(data.size, 0);
+  }
+
+  {
+    const f_status_t status = f_memory_array_append(0, sizeof(int), 0, 0, 0);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
@@ -19,7 +28,7 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   }
 
   {
-    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), 0, &data.used, &data.size);
+    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), 0, 0, 0);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
@@ -27,7 +36,7 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   }
 
   {
-    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), (void **) &data.array, 0, &data.size);
+    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), 0, &data.used, &data.size);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
@@ -35,7 +44,7 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   }
 
   {
-    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), (void **) &data.array, &data.used, 0);
+    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), (void **) &data.array, 0, &data.size);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
@@ -43,7 +52,7 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   }
 
   {
-    const f_status_t status = f_memory_array_append((void *) &number, 0, (void **) &data.array, &data.used, &data.size);
+    const f_status_t status = f_memory_array_append((void *) &number, sizeof(int), (void **) &data.array, &data.used, 0);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
@@ -51,7 +60,7 @@ void test__f_memory_array_append__parameter_checking(void **state) {
   }
 
   {
-    const f_status_t status = f_memory_array_append(0, sizeof(int), (void **) &data.array, &data.used, &data.size);
+    const f_status_t status = f_memory_array_append((void *) &number, 0, (void **) &data.array, &data.used, &data.size);
 
     assert_int_equal(status, F_status_set_error(F_parameter));
     assert_int_equal(data.used, 0);
index b730e2c8dc8645f09b2659e6ffc5936cc3bcb038..34890add2042b0fc2767544f99eb1489f0a9d9ab 100644 (file)
@@ -11,6 +11,31 @@ void test__f_memory_array_append_all__parameter_checking(void **state) {
   test_memory_array_t sources = { .array = sources_array, .used = 2, .size = 0 };
   test_memory_array_t data = test_memory_array_t_initialize;
 
+  // In this case, the usual parameter checking must not return F_parameter error when sources is NULL and amount is 0.
+  {
+    const f_status_t status = f_memory_array_append_all(0, 0, sizeof(int), (void **) &data.array, &data.used, &data.size);
+
+    assert_int_equal(status, F_data_not);
+    assert_int_equal(data.used, 0);
+    assert_int_equal(data.size, 0);
+  }
+
+  {
+    const f_status_t status = f_memory_array_append_all(0, sources.used, sizeof(int), (void **) &data.array, &data.used, &data.size);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+    assert_int_equal(data.used, 0);
+    assert_int_equal(data.size, 0);
+  }
+
+  {
+    const f_status_t status = f_memory_array_append_all(0, 0, sizeof(int), 0, 0, 0);
+
+    assert_int_equal(status, F_status_set_error(F_parameter));
+    assert_int_equal(data.used, 0);
+    assert_int_equal(data.size, 0);
+  }
+
   {
     const f_status_t status = f_memory_array_append_all((void *) sources.array, sources.used, sizeof(int), 0, 0, 0);