forked from json-c/json-c
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprintbuf.c
149 lines (130 loc) · 3.5 KB
/
printbuf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <[email protected]>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_STDARG_H
# include <stdarg.h>
#else /* !HAVE_STDARG_H */
# error Not enough var arg support!
#endif /* HAVE_STDARG_H */
#include "bits.h"
#include "debug.h"
#include "printbuf.h"
struct printbuf* printbuf_new(void)
{
struct printbuf *p;
p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
if(!p) return NULL;
p->size = 32;
p->bpos = 0;
if(!(p->buf = (char*)malloc(p->size))) {
free(p);
return NULL;
}
return p;
}
int printbuf_memappend(struct printbuf *p, const char *buf, int size)
{
char *t;
if(p->size - p->bpos <= size) {
int new_size = json_max(p->size * 2, p->bpos + size + 8);
#ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d wrsize=%d old_size=%d new_size=%d\n",
p->bpos, size, p->size, new_size);
#endif /* PRINTBUF_DEBUG */
if(!(t = (char*)realloc(p->buf, new_size))) return -1;
p->size = new_size;
p->buf = t;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos]= '\0';
return size;
}
#if !HAVE_VSNPRINTF && defined(WIN32)
# define vsnprintf _vsnprintf
#elif !HAVE_VSNPRINTF /* !HAVE_VSNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
#if !HAVE_VASPRINTF
/* CAW: compliant version of vasprintf */
static int vasprintf(char **buf, const char *fmt, va_list ap)
{
#ifndef WIN32
static char _T_emptybuffer = '\0';
#endif /* !defined(WIN32) */
int chars;
char *b;
if(!buf) { return -1; }
#ifdef WIN32
chars = _vscprintf(fmt, ap)+1;
#else /* !defined(WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
our buffer like on some 64bit sun systems.... but hey, its time to move on */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
#endif /* defined(WIN32) */
b = (char*)malloc(sizeof(char)*chars);
if(!b) { return -1; }
if((chars = vsprintf(b, fmt, ap)) < 0)
{
free(b);
} else {
*buf = b;
}
return chars;
}
#endif /* !HAVE_VASPRINTF */
int sprintbuf(struct printbuf *p, const char *msg, ...)
{
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = vsnprintf(buf, 128, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
with vasprintf. Note: some implementation of vsnprintf return -1
if output is truncated whereas some return the number of bytes that
would have been written - this code handles both cases. */
if(size == -1 || size > 127) {
va_start(ap, msg);
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
} else {
printbuf_memappend(p, buf, size);
return size;
}
}
void printbuf_reset(struct printbuf *p)
{
p->buf[0] = '\0';
p->bpos = 0;
}
void printbuf_free(struct printbuf *p)
{
if(p) {
free(p->buf);
free(p);
}
}