subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From br...@apache.org
Subject svn commit: r1413482 - /subversion/trunk/subversion/libsvn_subr/string.c
Date Mon, 26 Nov 2012 05:27:21 GMT
Author: brane
Date: Mon Nov 26 05:27:20 2012
New Revision: 1413482

URL: http://svn.apache.org/viewvc?rev=1413482&view=rev
Log:
Factor the svn_stringbuf_t and svn_membuf_t implementation to a common code base.

* subversion/libsvn_subr/string.c (membuf_create, membuf_ensure): New, private
   helper functions for membufs and stringbufs.
  (svn_membuf__create): Call membuf_create.
  (svn_membuf__ensure): Call membuf_ensure.
  (svn_membuf__resize): Call membuf_ensure for resizing the buffer.
  (my__realloc): Remove.
  (create_stringbuf): Remove. Inline implementation into the single call.
  (svn_stringbuf_createv): Inline the previous contents of create_stringbuf.
  (svn_stringbuf_create_ensure): Call membuf_create to allocate the buffer.
  (svn_stringbuf_ensure): Call membuf_ensure to resize the buffer.

Modified:
    subversion/trunk/subversion/libsvn_subr/string.c

Modified: subversion/trunk/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/string.c?rev=1413482&r1=1413481&r2=1413482&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/string.c (original)
+++ subversion/trunk/subversion/libsvn_subr/string.c Mon Nov 26 05:27:20 2012
@@ -38,23 +38,73 @@
 
 
 
+/* Allocate the space for a memory buffer. The data pointer will be NULL
+ * if the size is NULL.
+ * N.B.: The stringbuf creation functions use this, but since stringbufs
+ *       stringbufs alwase consume at least 1 byte for the NUL terminator,
+ *       the resulting data pointers will never be NULL.
+ */
+static APR_INLINE void
+membuf_create(apr_size_t size, apr_pool_t *pool,
+              void **rdata, apr_size_t *rsize, apr_pool_t **rpool)
+{
+  /* apr_palloc will allocate multiples of 8.
+   * Thus, we would waste some of that memory if we stuck to the
+   * smaller size. Note that this is safe even if apr_palloc would
+   * use some other aligment or none at all. */
+  *rsize = (size ? APR_ALIGN_DEFAULT(size) : 0);
+  *rdata = (!*rsize ? NULL : apr_palloc(pool, *rsize));
+  if (rpool)
+    *rpool = pool;
+}
+
+/* Ensure that the size of a given memory buffer is at least SIZE
+ * bytes. An existing buffer will be resized by multiplying its size
+ * by a power of two.
+ */
+static APR_INLINE void
+membuf_ensure(apr_size_t size, apr_pool_t *pool,
+              void **data, apr_size_t *rsize)
+{
+  if (size > *rsize)
+    {
+      apr_size_t new_size = *rsize;
+
+      if (new_size == 0)
+        /* APR will increase odd allocation sizes to the next
+         * multiple for 8, for instance. Take advantage of that
+         * knowledge and allow for the extra size to be used. */
+        new_size = APR_ALIGN_DEFAULT(size);
+      else
+        while (new_size < size)
+          {
+            /* new_size is aligned; doubling it should keep it aligned */
+            const apr_size_t prev_size = new_size;
+            new_size *= 2;
+
+            /* check for apr_size_t overflow */
+            if (prev_size > new_size)
+              {
+                new_size = APR_ALIGN_DEFAULT(size);
+                break;
+              }
+          }
+
+      *data = (!new_size ? NULL : apr_palloc(pool, new_size));
+      *rsize = new_size;
+    }
+}
+
 void
 svn_membuf__create(svn_membuf_t *membuf, apr_size_t size, apr_pool_t *pool)
 {
-  membuf->pool = pool;
-  membuf->size = (size ? APR_ALIGN_DEFAULT(size) : 0);
-  membuf->data = (!membuf->size ? NULL : apr_palloc(pool, membuf->size));
+  membuf_create(size, pool, &membuf->data, &membuf->size, &membuf->pool);
 }
 
 void
 svn_membuf__ensure(svn_membuf_t *membuf, apr_size_t size)
 {
-  if (size > membuf->size)
-    {
-      membuf->size = APR_ALIGN_DEFAULT(size);
-      membuf->data = (!membuf->size ? NULL
-                      : apr_palloc(membuf->pool, membuf->size));
-    }
+  membuf_ensure(size, membuf->pool, &membuf->data, &membuf->size);
 }
 
 void
@@ -63,8 +113,8 @@ svn_membuf__resize(svn_membuf_t *membuf,
   const void *const old_data = membuf->data;
   const apr_size_t old_size = membuf->size;
 
-  svn_membuf__ensure(membuf, size);
-  if (old_data && old_data != membuf->data)
+  membuf_ensure(size, membuf->pool, &membuf->data, &membuf->size);
+  if (membuf->data && old_data && old_data != membuf->data)
     memcpy(membuf->data, old_data, old_size);
 }
 
@@ -84,32 +134,6 @@ svn_membuf__nzero(svn_membuf_t *membuf, 
   SVN_MEMBUF__NZERO(membuf, size);
 }
 
-/* Our own realloc, since APR doesn't have one.  Note: this is a
-   generic realloc for memory pools, *not* for strings. */
-static void *
-my__realloc(char *data, apr_size_t oldsize, apr_size_t request,
-            apr_pool_t *pool)
-{
-  void *new_area;
-
-  /* kff todo: it's a pity APR doesn't give us this -- sometimes it
-     could realloc the block merely by extending in place, sparing us
-     a memcpy(), but only the pool would know enough to be able to do
-     this.  We should add a realloc() to APR if someone hasn't
-     already. */
-
-  /* malloc new area */
-  new_area = apr_palloc(pool, request);
-
-  /* copy data to new area */
-  memcpy(new_area, data, oldsize);
-
-  /* I'm NOT freeing old area here -- cuz we're using pools, ugh. */
-
-  /* return new area */
-  return new_area;
-}
-
 static APR_INLINE svn_boolean_t
 string_compare(const char *str1,
                const char *str2,
@@ -330,28 +354,6 @@ svn_stringbuf__morph_into_string(svn_str
 
 /* svn_stringbuf functions */
 
-/* Create a stringbuf referring to (not copying) an existing block of memory
- * at DATA, of which SIZE bytes are the user data and BLOCKSIZE bytes are
- * allocated in total.  DATA[SIZE] must be a zero byte. */
-static svn_stringbuf_t *
-create_stringbuf(char *data, apr_size_t size, apr_size_t blocksize,
-                 apr_pool_t *pool)
-{
-  svn_stringbuf_t *new_string;
-
-  new_string = apr_palloc(pool, sizeof(*new_string));
-
-  SVN_ERR_ASSERT_NO_RETURN(size < blocksize);
-  SVN_ERR_ASSERT_NO_RETURN(data[size] == '\0');
-
-  new_string->data = data;
-  new_string->len = size;
-  new_string->blocksize = blocksize;
-  new_string->pool = pool;
-
-  return new_string;
-}
-
 svn_stringbuf_t *
 svn_stringbuf_create_empty(apr_pool_t *pool)
 {
@@ -364,24 +366,17 @@ svn_stringbuf_create_ensure(apr_size_t b
   void *mem;
   svn_stringbuf_t *new_string;
 
-  /* apr_palloc will allocate multiples of 8.
-   * Thus, we would waste some of that memory if we stuck to the
-   * smaller size. Note that this is safe even if apr_palloc would
-   * use some other aligment or none at all. */
-
   ++blocksize; /* + space for '\0' */
-  blocksize = APR_ALIGN_DEFAULT(blocksize);
 
   /* Allocate memory for svn_string_t and data in one chunk. */
-  mem = apr_palloc(pool, sizeof(*new_string) + blocksize);
+  membuf_create(blocksize + sizeof(*new_string), pool, &mem, &blocksize, NULL);
 
   /* Initialize header and string */
   new_string = mem;
-
   new_string->data = (char*)mem + sizeof(*new_string);
   new_string->data[0] = '\0';
   new_string->len = 0;
-  new_string->blocksize = blocksize;
+  new_string->blocksize = blocksize - sizeof(*new_string);
   new_string->pool = pool;
 
   return new_string;
@@ -422,9 +417,15 @@ svn_stringbuf_createv(apr_pool_t *pool, 
 {
   char *data = apr_pvsprintf(pool, fmt, ap);
   apr_size_t size = strlen(data);
+  svn_stringbuf_t *new_string;
 
-  /* wrap an svn_stringbuf_t around the new data */
-  return create_stringbuf(data, size, size + 1, pool);
+  new_string = apr_palloc(pool, sizeof(*new_string));
+  new_string->data = data;
+  new_string->len = size;
+  new_string->blocksize = size + 1;
+  new_string->pool = pool;
+
+  return new_string;
 }
 
 
@@ -491,38 +492,15 @@ svn_stringbuf_isempty(const svn_stringbu
 void
 svn_stringbuf_ensure(svn_stringbuf_t *str, apr_size_t minimum_size)
 {
+  void *mem = NULL;
   ++minimum_size;  /* + space for '\0' */
 
-  /* Keep doubling capacity until have enough. */
-  if (str->blocksize < minimum_size)
+  membuf_ensure(minimum_size, str->pool, &mem, &str->blocksize);
+  if (mem && mem != str->data)
     {
-      if (str->blocksize == 0)
-        /* APR will increase odd allocation sizes to the next
-         * multiple for 8, for instance. Take advantage of that
-         * knowledge and allow for the extra size to be used. */
-        str->blocksize = APR_ALIGN_DEFAULT(minimum_size);
-      else
-        while (str->blocksize < minimum_size)
-          {
-            /* str->blocksize is aligned;
-             * doubling it should keep it aligned */
-            apr_size_t prev_size = str->blocksize;
-            str->blocksize *= 2;
-
-            /* check for apr_size_t overflow */
-            if (prev_size > str->blocksize)
-              {
-                str->blocksize = minimum_size;
-                break;
-              }
-          }
-
-      str->data = (char *) my__realloc(str->data,
-                                       str->len + 1,
-                                       /* We need to maintain (and thus copy)
-                                          the trailing nul */
-                                       str->blocksize,
-                                       str->pool);
+      if (str->data)
+        memcpy(mem, str->data, str->len + 1);
+      str->data = mem;
     }
 }
 



Mime
View raw message