Changeset: a5d5e4043704 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a5d5e4043704
Modified Files:
        clients/mapilib/msettings.c
        common/utils/mstring.h
Branch: odbc-tls
Log Message:

Add reallocprintf and vreallocprintf to mstring.h


diffs (118 lines):

diff --git a/clients/mapilib/msettings.c b/clients/mapilib/msettings.c
--- a/clients/mapilib/msettings.c
+++ b/clients/mapilib/msettings.c
@@ -59,22 +59,19 @@ char* allocprintf(const char *fmt, ...)
 char *
 allocprintf(const char *fmt, ...)
 {
-       size_t buflen = 80;
-       while (1) {
-               char *buf = malloc(buflen);
-               if (buf == NULL)
-                       return NULL;
-               va_list ap;
-               va_start(ap, fmt);
-               int n = vsnprintf(buf, buflen, fmt, ap);
-               va_end(ap);
-               if (n >= 0 && (size_t)n < buflen)
-                       return buf;
-               free(buf);
-               if (n < 0)
-                       return NULL;
-               buflen = n + 1;
-       }
+       va_list ap;
+       char *buf = NULL;
+       size_t pos = 0, cap = 0;
+       int n;
+
+       va_start(ap, fmt);
+       n = vreallocprintf(&buf, &pos, &cap, fmt, ap);
+       va_end(ap);
+
+       if (n >= 0)
+               return buf;
+       free(buf);
+       return NULL;
 }
 
 
diff --git a/common/utils/mstring.h b/common/utils/mstring.h
--- a/common/utils/mstring.h
+++ b/common/utils/mstring.h
@@ -155,6 +155,75 @@ checkUTF8(const char *v)
        return true;
 }
 
+static inline int vreallocprintf(char **buf, size_t *pos, size_t *size, const 
char *fmt, va_list ap)
+       __attribute__((__format__(__printf__, 4, 0)));
+
+static inline int
+vreallocprintf(char **buf, size_t *pos, size_t *capacity, const char *fmt, 
va_list args)
+{
+       va_list ap;
+
+       assert(*pos <= *capacity);
+       assert(*buf == NULL || *capacity > 0);
+
+       size_t need_at_least = strlen(fmt);
+       need_at_least += 1; // trailing NUL
+       need_at_least += 80; // some space for the items
+       while (1) {
+               // Common cases:
+               // 1. buf=NULL, pos=cap=0: allocate reasonable amount
+               // 2. buf=NULL, pos=0, cap=something: start with allocating cap
+               // 3. buf not NULL, cap=something: allocate larger cap
+               if (*buf == NULL || need_at_least > *capacity - *pos) {
+                       size_t cap1 = *pos + need_at_least;
+                       size_t cap2 = *capacity;
+                       if (*buf)
+                               cap2 += cap2 / 2;
+                       size_t new_cap = cap1 > cap2 ? cap1 : cap2;
+                       char *new_buf = realloc(*buf, new_cap);
+                       if (new_buf == 0)
+                               return -1;
+                       *buf = new_buf;
+                       *capacity = new_cap;
+               }
+               assert(*buf);
+               assert(need_at_least <= *capacity - *pos);
+               char *output = &(*buf)[*pos];
+               size_t avail = *capacity - *pos;
+               assert(avail >= 1);
+
+               va_copy(ap, args);
+               int n = vsnprintf(output, avail, fmt, ap);
+               va_end(ap);
+
+               if (n < 0)
+                       return n;
+               size_t needed = (size_t)n;
+               if (needed <= avail - 1) {
+                       // it wanted to print n chars and it could
+                       *pos += needed;
+                       return n;
+               }
+               need_at_least = needed + 1;
+       }
+}
+
+static inline int reallocprintf(char **buf, size_t *pos, size_t *size, const 
char *fmt, ...)
+       __attribute__((__format__(__printf__, 4, 5)));
+
+static inline int
+reallocprintf(char **buf, size_t *pos, size_t *capacity, const char *fmt, ...)
+{
+       int n;
+       va_list ap;
+       va_start(ap, fmt);
+       n = vreallocprintf(buf, pos, capacity, fmt, ap);
+       va_end(ap);
+       return n;
+}
+
+
+
 #ifndef __GNUC__
 #undef __builtin_expect
 #endif
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to