Răsfoiți Sursa

[utarray] Add utarray_replace macro to safely replace elements (#272)

Introduces a new macro function utarray_replace in utarray.h,
which enables safe replacement of an element in a UT_array.

Currently, modifying an element in a UT_array often involves retrieving
a pointer via utarray_eltptr and then directly assigning a new value.
However, this method bypasses any user-defined ctor or dtor functions,
potentially leading to memory leaks or undefined behavior when managing
complex data types.

The new utarray_replace macro ensures that when an element is replaced:
- The existing element is properly destroyed using the dtor, if defined.
- The new element is constructed via the ctor, if defined.
xunicatt 4 luni în urmă
părinte
comite
af6e637f19
7 a modificat fișierele cu 106 adăugiri și 1 ștergeri
  1. 1 0
      doc/utarray.txt
  2. 6 0
      src/utarray.h
  3. 1 1
      tests/Makefile
  4. 10 0
      tests/test100.ans
  5. 53 0
      tests/test100.c
  6. 10 0
      tests/test99.ans
  7. 25 0
      tests/test99.c

+ 1 - 0
doc/utarray.txt

@@ -325,6 +325,7 @@ Operations
 | utarray_eltptr(UT_array *a,int j)    | get pointer of element from index
 | utarray_eltidx(UT_array *a,void *e)  | get index of element from pointer
 | utarray_insert(UT_array *a,void *p, int j) | insert element p to index j
+| utarray_replace(UT_array *a,void *p, int j) | replace element p at index j
 | utarray_inserta(UT_array *a,UT_array *w, int j) | insert array w into array a at index j
 | utarray_resize(UT_array *dst,int num)  | extend or shrink array to num elements
 | utarray_concat(UT_array *dst,UT_array *src) | copy src to end of dst array

+ 6 - 0
src/utarray.h

@@ -136,6 +136,12 @@ typedef struct {
   (a)->i++;                                                                   \
 } while(0)
 
+#define utarray_replace(a,p,j) do {                                           \
+  if ((a)->icd.dtor) { (a)->icd.dtor(_utarray_eltptr(a,j)); }                 \
+  if ((a)->icd.copy) { (a)->icd.copy(_utarray_eltptr(a,j), p); }              \
+  else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }                      \
+} while(0)
+
 #define utarray_inserta(a,w,j) do {                                           \
   if (utarray_len(w) == 0) break;                                             \
   if ((j) > (a)->i) utarray_resize(a,j);                                      \

+ 1 - 1
tests/Makefile

@@ -13,7 +13,7 @@ PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9   \
         test74 test75 test76 test77 test78 test79 test80 test81 \
         test82 test83 test84 test85 test86 test87 test88 test89 \
         test90 test91 test92 test93 test94 test95 test96 test97 \
-        test98
+        test98 test99 test100
 CFLAGS += -I$(HASHDIR)
 #CFLAGS += -DHASH_BLOOM=16
 #CFLAGS += -O2

+ 10 - 0
tests/test100.ans

@@ -0,0 +1,10 @@
+id: 0 dept: A
+id: 1 dept: B
+id: 2 dept: C
+id: 3 dept: D
+id: 4 dept: E
+id: 25 dept: Z
+id: 6 dept: G
+id: 7 dept: H
+id: 8 dept: I
+id: 9 dept: J

+ 53 - 0
tests/test100.c

@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "utarray.h"
+
+typedef struct {
+    int id;
+    char *dept;
+} Data;
+
+void Data_copy(void* vdst, const void* vsrc) {
+  Data *dst = (Data*)vdst;
+  Data *src = (Data*)vsrc;
+  dst->id = src->id;
+  dst->dept = strdup(src->dept);
+}
+
+void Data_deinit(void* vdata) {
+    Data *data = (Data*)vdata;
+    free(data->dept);
+}
+
+int main(void) {
+    UT_array *datas;
+    int i;
+    Data d, *dp;
+    char tmp[2] = "A";
+
+    UT_icd data_icd = {sizeof(Data), NULL, Data_copy, Data_deinit};
+    utarray_new(datas, &data_icd);
+
+    for(i = 0; i < 10; i++) {
+        d.id = i;
+        d.dept = strdup(tmp);
+        utarray_push_back(datas, &d);
+        Data_deinit(&d);
+        tmp[0] += 1;
+    }
+
+    d.id = 25;
+    d.dept = strdup("Z");
+    utarray_replace(datas, &d, 5);
+    Data_deinit(&d);
+
+    for(dp = (Data*)utarray_front(datas);
+        dp != NULL;
+        dp = (Data*)utarray_next(datas, dp)) {
+        printf("id: %d dept: %s\n", dp->id, dp->dept);
+    }
+
+    utarray_free(datas);
+    return 0;
+}

+ 10 - 0
tests/test99.ans

@@ -0,0 +1,10 @@
+1
+2
+4
+8
+16
+110
+64
+128
+256
+512

+ 25 - 0
tests/test99.c

@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include "utarray.h"
+
+int main(void) {
+    UT_array *nums;
+    int i, *p;
+
+    utarray_new(nums, &ut_int_icd);
+
+    for(i = 1; i < 1024; i <<= 1){
+      utarray_push_back(nums, &i);
+    }
+
+    i = 110;
+    utarray_replace(nums, &i, 5);
+
+    for(p = (int*)utarray_front(nums);
+        p != NULL;
+        p = (int*)utarray_next(nums, p)) {
+        printf("%d\n",*p);
+    }
+
+    utarray_free(nums);
+    return 0;
+}