]> granicus.if.org Git - graphviz/commitdiff
add a new 'disown' API for agxbuf
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Sat, 15 Aug 2020 20:06:43 +0000 (13:06 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Thu, 20 Aug 2020 14:40:31 +0000 (07:40 -0700)
CHANGELOG.md
lib/cgraph/agxbuf.c
lib/cgraph/agxbuf.h

index 9ed978b7257983a07a78172c8953d6d6f037c869..a67677542e283d315dc6973f80b66e4401f703ea 100644 (file)
@@ -5,6 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+
+### Added
+- Cgraph's agxbuf API gained a new function agxbdisown(), for dissociating
+  backing memory from the managed buffer
+
+### Changed
 - Cgraph's agheap() API has been removed
 
 ### Fixed
index 4e320670aae3181038caea283a24fbcf1171fe14..6c5bfeecbc70caf2b46c191c4df6c82fd7122369 100644 (file)
@@ -110,3 +110,37 @@ int agxbpop(agxbuf * xb)
        return -1;
 
 }
+
+char *agxbdisown(agxbuf * xb) {
+
+  size_t size;
+  char *buf;
+
+  /* terminate the existing string */
+  agxbputc(xb, '\0');
+
+  size = (size_t)(xb->ptr - xb->buf);
+
+  if (!xb->dyna) {
+    /* the buffer is not dynamically allocated, so we need to copy its contents
+     * to heap memory
+     */
+
+    buf = malloc(size);
+    if (buf == NULL) {
+      return NULL;
+    }
+
+    memcpy(buf, xb->buf, size);
+
+  } else {
+    /* the buffer is already dynamically allocated, so take it as-is */
+    buf = (char*)xb->buf;
+  }
+
+  /* reset xb to a state where it is usable */
+  xb->buf = xb->ptr = xb->eptr = NULL;
+  xb->dyna = 1;
+
+  return buf;
+}
index 7cbb22088a19b86703c48db6a45cdf7bb5befada..6a7bada96e3bf633bc42b12baa6cd0c4e1b6207c 100644 (file)
@@ -77,7 +77,10 @@ extern "C" {
 #define agxbputc(X,C) ((((X)->ptr >= (X)->eptr) ? agxbmore(X,1) : 0), (void)(*(X)->ptr++ = ((unsigned char)C)))
 
 /* agxbuse:
- * Null-terminates buffer; resets and returns pointer to data;
+ * Null-terminates buffer; resets and returns pointer to data. The buffer is
+ * still associated with the agxbuf and will be overwritten on the next, e.g.,
+ * agxbput. If you want to retrieve and disassociate the buffer, use agxbdisown
+ * instead.
  *  char* agxbuse(agxbuf* xb)
  */
 #define agxbuse(X) ((void)agxbputc(X,'\0'),(char*)((X)->ptr = (X)->buf))
@@ -106,6 +109,16 @@ extern "C" {
  */
 #define agxbnext(X) ((char*)((X)->ptr))
 
+/* agxbdisown:
+ * Disassociate the backing buffer from this agxbuf and return it. The buffer is
+ * NUL terminated before being returned. If the agxbuf is using stack memory,
+ * this will first copy the data to a new heap buffer to then return. If failure
+ * occurs, NULL is returned. If you want to temporarily access the string in the
+ * buffer, but have it overwritten and reused the next time, e.g., agxbput is
+ * called, use agxbuse instead of agxbdisown.
+ */
+    AGXBUF_API char *agxbdisown(agxbuf * xb);
+
 #endif
 
 #ifdef __cplusplus