2 * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
4 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
5 * Michael Clark <michael@metaparadigm.com>
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the MIT license. See COPYING for details.
11 * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
12 * The copyrights to the contents of this file are licensed under the MIT License
13 * (http://www.opensource.org/licenses/mit-license.php)
24 #else /* !HAVE_STDARG_H */
25 # error Not enough var arg support!
26 #endif /* HAVE_STDARG_H */
32 static int printbuf_extend(struct printbuf
*p
, int min_size
);
34 struct printbuf
* printbuf_new(void)
38 p
= (struct printbuf
*)calloc(1, sizeof(struct printbuf
));
42 if(!(p
->buf
= (char*)malloc(p
->size
))) {
51 * Extend the buffer p so it has a size of at least min_size.
53 * If the current size is large enough, nothing is changed.
55 * Note: this does not check the available space! The caller
56 * is responsible for performing those calculations.
58 static int printbuf_extend(struct printbuf
*p
, int min_size
)
63 if (p
->size
>= min_size
)
66 new_size
= json_max(p
->size
* 2, min_size
+ 8);
68 MC_DEBUG("printbuf_memappend: realloc "
69 "bpos=%d min_size=%d old_size=%d new_size=%d\n",
70 p
->bpos
, min_size
, p
->size
, new_size
);
71 #endif /* PRINTBUF_DEBUG */
72 if(!(t
= (char*)realloc(p
->buf
, new_size
)))
79 int printbuf_memappend(struct printbuf
*p
, const char *buf
, int size
)
81 if (p
->size
<= p
->bpos
+ size
+ 1) {
82 if (printbuf_extend(p
, p
->bpos
+ size
+ 1) < 0)
85 memcpy(p
->buf
+ p
->bpos
, buf
, size
);
87 p
->buf
[p
->bpos
]= '\0';
91 int printbuf_memset(struct printbuf
*pb
, int offset
, int charvalue
, int len
)
97 size_needed
= offset
+ len
;
98 if (pb
->size
< size_needed
)
100 if (printbuf_extend(pb
, size_needed
) < 0)
104 memset(pb
->buf
+ offset
, charvalue
, len
);
105 if (pb
->bpos
< size_needed
)
106 pb
->bpos
= size_needed
;
111 #if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER)
112 # define vsnprintf _vsnprintf
113 #elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */
114 # error Need vsnprintf!
115 #endif /* !HAVE_VSNPRINTF && defined(WIN32) */
117 #if !defined(HAVE_VASPRINTF)
118 /* CAW: compliant version of vasprintf */
119 static int vasprintf(char **buf
, const char *fmt
, va_list ap
)
122 static char _T_emptybuffer
= '\0';
123 #endif /* !defined(WIN32) */
127 if(!buf
) { return -1; }
130 chars
= _vscprintf(fmt
, ap
)+1;
131 #else /* !defined(WIN32) */
132 /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
133 our buffer like on some 64bit sun systems.... but hey, its time to move on */
134 chars
= vsnprintf(&_T_emptybuffer
, 0, fmt
, ap
)+1;
135 if(chars
< 0) { chars
*= -1; } /* CAW: old glibc versions have this problem */
136 #endif /* defined(WIN32) */
138 b
= (char*)malloc(sizeof(char)*chars
);
139 if(!b
) { return -1; }
141 if((chars
= vsprintf(b
, fmt
, ap
)) < 0)
150 #endif /* !HAVE_VASPRINTF */
152 int sprintbuf(struct printbuf
*p
, const char *msg
, ...)
159 /* user stack buffer first */
161 size
= vsnprintf(buf
, 128, msg
, ap
);
163 /* if string is greater than stack buffer, then use dynamic string
164 with vasprintf. Note: some implementation of vsnprintf return -1
165 if output is truncated whereas some return the number of bytes that
166 would have been written - this code handles both cases. */
167 if(size
== -1 || size
> 127) {
169 if((size
= vasprintf(&t
, msg
, ap
)) < 0) { va_end(ap
); return -1; }
171 printbuf_memappend(p
, t
, size
);
175 printbuf_memappend(p
, buf
, size
);
180 void printbuf_reset(struct printbuf
*p
)
186 void printbuf_free(struct printbuf
*p
)