printbuf.c
Go to the documentation of this file.
00001 /*
00002  * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
00003  *
00004  * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
00005  * Michael Clark <michael@metaparadigm.com>
00006  *
00007  * This library is free software; you can redistribute it and/or modify
00008  * it under the terms of the MIT license. See COPYING for details.
00009  *
00010  */
00011 
00012 #include "config.h"
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 
00018 #if HAVE_STDARG_H
00019 # include <stdarg.h>
00020 #else /* !HAVE_STDARG_H */
00021 # error Not enough var arg support!
00022 #endif /* HAVE_STDARG_H */
00023 
00024 #include "bits.h"
00025 #include "debug.h"
00026 #include "printbuf.h"
00027 
00028 struct printbuf* printbuf_new()
00029 {
00030   struct printbuf *p;
00031 
00032   if(!(p = calloc(1, sizeof(struct printbuf)))) return NULL;
00033   p->size = 32;
00034   p->bpos = 0;
00035   if(!(p->buf = malloc( (size_t) p->size))) {
00036     free(p);
00037     return NULL;
00038   }
00039   return p;
00040 }
00041 
00042 
00043 int printbuf_memappend(struct printbuf *p, const char *buf, int size)
00044 {
00045   char *t;
00046   if(p->size - p->bpos <= size) {
00047     int new_size = max(p->size * 2, p->bpos + size + 8);
00048 #ifdef PRINTBUF_DEBUG
00049     mc_debug("printbuf_memappend: realloc "
00050              "bpos=%d wrsize=%d old_size=%d new_size=%d\n",
00051              p->bpos, size, p->size, new_size);
00052 #endif /* PRINTBUF_DEBUG */
00053     if(!(t = realloc(p->buf,  (size_t) new_size))) return -1;
00054     p->size = new_size;
00055     p->buf = t;
00056   }
00057   memcpy(p->buf + p->bpos, buf,  (size_t) size);
00058   p->bpos += size;
00059   p->buf[p->bpos]= '\0';
00060   return size;
00061 }
00062 
00063 #if !HAVE_VSNPRINTF && defined(WIN32)
00064 # define vsnprintf _vsnprintf
00065 #elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */
00066 # error Need vsnprintf!
00067 #endif /* !HAVE_VSNPRINTF && defined(WIN32) */
00068 
00069 #if !HAVE_VASPRINTF
00070 /* CAW: compliant version of vasprintf */
00071 static int vasprintf(char **buf, const char *fmt, va_list ap)
00072 {
00073 #ifndef WIN32
00074         static char _T_emptybuffer = '\0';
00075 #endif /* !defined(WIN32) */
00076         int chars;
00077         char *b;
00078 
00079         if(!buf) { return -1; }
00080 
00081 #ifdef WIN32
00082         chars = _vscprintf(fmt, ap)+1;
00083 #else /* !defined(WIN32) */
00084         /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
00085            our buffer like on some 64bit sun systems.... but hey, its time to move on */
00086         chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
00087         if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
00088 #endif /* defined(WIN32) */
00089 
00090         b = (char*)malloc(sizeof(char)*chars);
00091         if(!b) { return -1; }
00092 
00093         if((chars = vsprintf(b, fmt, ap)) < 0)
00094         {
00095                 free(b);
00096         } else {
00097                 *buf = b;
00098         }
00099 
00100         return chars;
00101 }
00102 #endif /* !HAVE_VASPRINTF */
00103 
00104 int sprintbuf(struct printbuf *p, const char *msg, ...)
00105 {
00106   va_list ap;
00107   char *t;
00108   int size;
00109   char buf[128];
00110 
00111   /* user stack buffer first */
00112   va_start(ap, msg);
00113   size = vsnprintf(buf, 128, msg, ap);
00114   va_end(ap);
00115   /* if string is greater than stack buffer, then use dynamic string
00116      with vasprintf.  Note: some implementation of vsnprintf return -1
00117      if output is truncated whereas some return the number of bytes that
00118      would have been writen - this code handles both cases. */
00119   if(size == -1 || size > 127) {
00120     int ret;
00121     va_start(ap, msg);
00122     if((size = vasprintf(&t, msg, ap)) == -1) return -1;
00123     va_end(ap);
00124     ret = printbuf_memappend(p, t, size);
00125     free(t);
00126     return ret;
00127   } else {
00128     return printbuf_memappend(p, buf, size);
00129   }
00130 }
00131 
00132 void printbuf_reset(struct printbuf *p)
00133 {
00134   p->buf[0] = '\0';
00135   p->bpos = 0;
00136 }
00137 
00138 void printbuf_free(struct printbuf *p)
00139 {
00140   if(p) {
00141     free(p->buf);
00142     free(p);
00143   }
00144 }


csm
Author(s): Andrea Censi
autogenerated on Mon Jan 16 2017 03:48:29