]> granicus.if.org Git - graphviz/commitdiff
Revert "remove now-unused vmresize"
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Wed, 11 Aug 2021 00:20:22 +0000 (17:20 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 14 Aug 2021 01:31:32 +0000 (18:31 -0700)
This reverts commit ab322d219b7dae03fe5f7114dfd0e1d2fc7d3b5d. A `realloc`
analogue appears to be the simplest way of removing sfputr/sfputc usage in
exeval.c. Related to #1998.

lib/vmalloc/test.c
lib/vmalloc/vmalloc.c
lib/vmalloc/vmalloc.h

index dddf180fb11efb5b9e493da06aed0bbfd5ccc72e..73352d917fdb2557f43827241e8ebed03dcceed5 100644 (file)
@@ -138,6 +138,72 @@ static void test_lifecycle(void) {
   assert(r == 0);
 }
 
+// some testing of our realloc analogue
+static void test_resize(void) {
+  static const size_t s = 10;
+
+  // create a new vmalloc region
+  Vmalloc_t *v = vmopen();
+  assert(v != NULL);
+
+  // resizing NULL should give us a new pointer
+  unsigned char *p = vmresize(v, NULL, s);
+  assert(p != NULL);
+
+  // confirm we can read and write to this allocated memory
+  for (size_t i = 0; i < s; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i];
+    *q = (unsigned char)i;
+  }
+  for (size_t i = 0; i < s; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i];
+    assert(*q == (unsigned char)i);
+  }
+
+  // discard this
+  vmfree(v, p);
+
+  // get a new pointer
+  p = vmalloc(v, s);
+  assert(p != NULL);
+
+  // setup some data in this memory
+  for (size_t i = 0; i < s; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i];
+    *q = (unsigned char)(s - i);
+  }
+
+  // expand the memory
+  p = vmresize(v, p, s * 2);
+  assert(p != NULL);
+
+  // confirm our previous data is still intact
+  for (size_t i = 0; i < s; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i];
+    assert(*q == (unsigned char)(s - i));
+  }
+
+  // confirm we can access the extended part
+  for (size_t i = 0; i < s; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i + s];
+    *q = (unsigned char)(s - i);
+  }
+
+  // shrink the memory
+  p = vmresize(v, p, s / 2);
+  assert(p != NULL);
+
+  // confirm the part that we retained still has its data intact
+  for (size_t i = 0; i < s / 2; ++i) {
+    volatile unsigned char *q = (volatile unsigned char *)&p[i];
+    assert(*q == (unsigned char)(s - i));
+  }
+
+  // clean up
+  int r = vmclose(v);
+  assert(r == 0);
+}
+
 // basic test of our strdup analogue
 static void test_strdup(void) {
 
@@ -200,6 +266,7 @@ int main(void) {
   RUN(basic_lifecycle);
   RUN(empty_vmclear);
   RUN(lifecycle);
+  RUN(resize);
   RUN(strdup);
 
 #undef RUN
index 18ead8959c27c3705463c133388959a4caa413aa..2f203006ece1e66e1db44c59b1ee23670f0a1fde 100644 (file)
@@ -78,3 +78,30 @@ void vmfree(Vmalloc_t *vm, void *data) {
 
   // we did not find this pointer; free() of something we did not allocate
 }
+
+void *vmresize(Vmalloc_t *vm, void *data, size_t size) {
+
+  if (!data) {
+    return vmalloc(vm, size);
+  }
+
+  // find the pointer we previously allocated
+  for (size_t i = 0; i < vm->size; ++i) {
+    if (vm->allocated[i] == data) {
+
+      // resize the allocation
+      void *p = realloc(data, size);
+      if (p == NULL) {
+        return p;
+      }
+
+      // save the updated pointer
+      vm->allocated[i] = p;
+
+      return p;
+    }
+  }
+
+  // the pointer the caller gave us was not allocated by us
+  return NULL;
+}
index 85c83c95bd03eacb7a2c1c711ec6ff755c1e5a8b..75ab3c4f42eacb297ed80e6000a66b216fe81da5 100644 (file)
@@ -41,6 +41,15 @@ extern "C" {
  */
 void *vmalloc(Vmalloc_t *vm, size_t size);
 
+/** resize an area of allocated memory
+ *
+ * @param vm region allocation from
+ * @param data old block of data
+ * @param size new size
+ * @returns Pointer to the newly resized area or NULL on failure
+ */
+void *vmresize(Vmalloc_t *vm, void *data, size_t size);
+
 /** free heap memory
  *
  * @param vm Region the pointer was originally allocated from