'LibPst'
vbuf.c
Go to the documentation of this file.
1 
2 #include "define.h"
3 
4 static int unicode_up = 0;
5 static iconv_t i16to8;
6 static const char *target_charset = NULL;
7 static int target_open_from = 0;
8 static int target_open_to = 0;
9 static iconv_t i8totarget = (iconv_t)-1;
10 static iconv_t target2i8 = (iconv_t)-1;
11 
12 
13 #define ASSERT(x,...) { if( !(x) ) DIE(( __VA_ARGS__)); }
14 
15 
18 static void pst_vbresize(pst_vbuf *vb, size_t len);
19 static void pst_vbresize(pst_vbuf *vb, size_t len)
20 {
21  vb->dlen = 0;
22 
23  if (vb->blen >= len) {
24  vb->b = vb->buf;
25  return;
26  }
27 
28  vb->buf = realloc(vb->buf, len);
29  vb->b = vb->buf;
30  vb->blen = len;
31 }
32 
33 
34 static size_t pst_vbavail(pst_vbuf * vb);
35 static size_t pst_vbavail(pst_vbuf * vb)
36 {
37  return vb->blen - vb->dlen - (size_t)(vb->b - vb->buf);
38 }
39 
40 
41 static void open_targets(const char* charset);
42 static void open_targets(const char* charset)
43 {
44  if (!target_charset || strcasecmp(target_charset, charset)) {
45  if (target_open_from) iconv_close(i8totarget);
46  if (target_open_to) iconv_close(target2i8);
47  if (target_charset) free((char *)target_charset);
48  target_charset = strdup(charset);
49  target_open_from = 1;
50  target_open_to = 1;
51  i8totarget = iconv_open(target_charset, "utf-8");
52  if (i8totarget == (iconv_t)-1) {
53  target_open_from = 0;
54  DEBUG_WARN(("Couldn't open iconv descriptor for utf-8 to %s.\n", target_charset));
55  }
56  target2i8 = iconv_open("utf-8", target_charset);
57  if (target2i8 == (iconv_t)-1) {
58  target_open_to = 0;
59  DEBUG_WARN(("Couldn't open iconv descriptor for %s to utf-8.\n", target_charset));
60  }
61  }
62 }
63 
64 
65 static size_t sbcs_conversion(pst_vbuf *dest, const char *inbuf, int iblen, iconv_t conversion);
66 static size_t sbcs_conversion(pst_vbuf *dest, const char *inbuf, int iblen, iconv_t conversion)
67 {
68  size_t inbytesleft = iblen;
69  size_t icresult = (size_t)-1;
70  size_t outbytesleft = 0;
71  char *outbuf = NULL;
72  int myerrno;
73 
74  DEBUG_ENT("sbcs_conversion");
75  pst_vbresize(dest, 2*iblen);
76 
77  do {
78  outbytesleft = dest->blen - dest->dlen;
79  outbuf = dest->b + dest->dlen;
80  icresult = iconv(conversion, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
81  myerrno = errno;
82  dest->dlen = outbuf - dest->b;
83  if (inbytesleft) pst_vbgrow(dest, 2*inbytesleft);
84  } while ((size_t)-1 == icresult && E2BIG == myerrno);
85 
86  if (icresult == (size_t)-1) {
87  DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
89  DEBUG_RET();
90  return (size_t)-1;
91  }
92  DEBUG_RET();
93  return 0;
94 }
95 
96 
97 static void pst_unicode_close();
98 static void pst_unicode_close()
99 {
100  iconv_close(i16to8);
101  if (target_open_from) iconv_close(i8totarget);
102  if (target_open_to) iconv_close(target2i8);
103  if (target_charset) free((char *)target_charset);
104  target_charset = NULL;
105  target_open_from = 0;
106  target_open_to = 0;
107  unicode_up = 0;
108 }
109 
110 
111 static int utf16_is_terminated(const char *str, int length);
112 static int utf16_is_terminated(const char *str, int length)
113 {
114  int len = -1;
115  int i;
116  for (i = 0; i < length; i += 2) {
117  if (str[i] == 0 && str[i + 1] == 0) {
118  len = i;
119  }
120  }
121 
122  if (len == -1) {
123  DEBUG_WARN(("utf16 string is not zero terminated\n"));
124  }
125 
126  return (len == -1) ? 0 : 1;
127 }
128 
129 
130 pst_vbuf *pst_vballoc(size_t len)
131 {
132  pst_vbuf *result = pst_malloc(sizeof(pst_vbuf));
133  if (result) {
134  result->dlen = 0;
135  result->blen = 0;
136  result->buf = NULL;
137  pst_vbresize(result, len);
138  }
139  else DIE(("malloc() failure"));
140  return result;
141 }
142 
143 
146 void pst_vbgrow(pst_vbuf *vb, size_t len)
147 {
148  if (0 == len)
149  return;
150 
151  if (0 == vb->blen) {
152  pst_vbresize(vb, len);
153  return;
154  }
155 
156  if (vb->dlen + len > vb->blen) {
157  if (vb->dlen + len < vb->blen * 1.5)
158  len = vb->blen * 1.5;
159  char *nb = pst_malloc(vb->blen + len);
160  if (!nb) DIE(("malloc() failure"));
161  vb->blen = vb->blen + len;
162  memcpy(nb, vb->b, vb->dlen);
163 
164  free(vb->buf);
165  vb->buf = nb;
166  vb->b = vb->buf;
167  } else {
168  if (vb->b != vb->buf)
169  memcpy(vb->buf, vb->b, vb->dlen);
170  }
171 
172  vb->b = vb->buf;
173 
174  ASSERT(pst_vbavail(vb) >= len, "vbgrow(): I have failed in my mission.");
175 }
176 
177 
180 void pst_vbset(pst_vbuf * vb, void *b, size_t len)
181 {
182  pst_vbresize(vb, len);
183  memcpy(vb->b, b, len);
184  vb->dlen = len;
185 }
186 
187 
190 void pst_vbappend(pst_vbuf *vb, void *b, size_t len)
191 {
192  if (0 == vb->dlen) {
193  pst_vbset(vb, b, len);
194  return;
195  }
196  pst_vbgrow(vb, len);
197  memcpy(vb->b + vb->dlen, b, len);
198  vb->dlen += len;
199 }
200 
201 
203 {
205  i16to8 = iconv_open("utf-8", "utf-16le");
206  if (i16to8 == (iconv_t)-1) {
207  DEBUG_WARN(("Couldn't open iconv descriptor for utf-16le to utf-8.\n"));
208  }
209  unicode_up = 1;
210 }
211 
212 
213 size_t pst_vb_utf16to8(pst_vbuf *dest, const char *inbuf, int iblen)
214 {
215  size_t inbytesleft = iblen;
216  size_t icresult = (size_t)-1;
217  size_t outbytesleft = 0;
218  char *outbuf = NULL;
219  int myerrno;
220 
221  if (!unicode_up) return (size_t)-1; // failure to open iconv
222  pst_vbresize(dest, iblen);
223 
224  //Bad Things can happen if a non-zero-terminated utf16 string comes through here
225  if (!utf16_is_terminated(inbuf, iblen))
226  return (size_t)-1;
227 
228  do {
229  outbytesleft = dest->blen - dest->dlen;
230  outbuf = dest->b + dest->dlen;
231  icresult = iconv(i16to8, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
232  myerrno = errno;
233  dest->dlen = outbuf - dest->b;
234  if (inbytesleft) pst_vbgrow(dest, inbytesleft);
235  } while ((size_t)-1 == icresult && E2BIG == myerrno);
236 
237  if (icresult == (size_t)-1) {
238  DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
240  return (size_t)-1;
241  }
242  return (icresult) ? (size_t)-1 : 0;
243 }
244 
245 
246 size_t pst_vb_utf8to8bit(pst_vbuf *dest, const char *inbuf, int iblen, const char* charset)
247 {
248  open_targets(charset);
249  if (!target_open_from) return (size_t)-1; // failure to open the target
250  return sbcs_conversion(dest, inbuf, iblen, i8totarget);
251 }
252 
253 
254 size_t pst_vb_8bit2utf8(pst_vbuf *dest, const char *inbuf, int iblen, const char* charset)
255 {
256  open_targets(charset);
257  if (!target_open_to) return (size_t)-1; // failure to open the target
258  return sbcs_conversion(dest, inbuf, iblen, target2i8);
259 }
260 
pst_vbuf * pst_vballoc(size_t len)
Definition: vbuf.c:130
void pst_vbappend(pst_vbuf *vb, void *b, size_t len)
append len bytes of b to vb, resize if necessary
Definition: vbuf.c:190
#define DEBUG_WARN(x)
Definition: define.h:165
#define DIE(x)
Definition: define.h:160
size_t pst_vb_utf16to8(pst_vbuf *dest, const char *inbuf, int iblen)
Definition: vbuf.c:213
size_t dlen
Definition: vbuf.h:10
void * pst_malloc(size_t size)
Definition: debug.c:169
Definition: vbuf.h:9
static void open_targets(const char *charset)
Definition: vbuf.c:42
size_t pst_vb_8bit2utf8(pst_vbuf *dest, const char *inbuf, int iblen, const char *charset)
Definition: vbuf.c:254
#define DEBUG_ENT(x)
Definition: define.h:171
#define DEBUG_RET()
Definition: define.h:176
static iconv_t i16to8
Definition: vbuf.c:5
static iconv_t i8totarget
Definition: vbuf.c:9
size_t pst_vb_utf8to8bit(pst_vbuf *dest, const char *inbuf, int iblen, const char *charset)
Definition: vbuf.c:246
static iconv_t target2i8
Definition: vbuf.c:10
void pst_vbgrow(pst_vbuf *vb, size_t len)
out: vbavail(vb) >= len, data are preserved
Definition: vbuf.c:146
char * b
Definition: vbuf.h:13
static int target_open_from
Definition: vbuf.c:7
void pst_vbset(pst_vbuf *vb, void *b, size_t len)
set vbuf b size=len, resize if necessary, relen = how much to over-allocate
Definition: vbuf.c:180
#define ASSERT(x,...)
Definition: vbuf.c:13
#define ICONV_CONST
Definition: config.h:393
static size_t pst_vbavail(pst_vbuf *vb)
Definition: vbuf.c:35
static int utf16_is_terminated(const char *str, int length)
Definition: vbuf.c:112
char * buf
Definition: vbuf.h:12
static void pst_vbresize(pst_vbuf *vb, size_t len)
DESTRUCTIVELY grow or shrink buffer.
Definition: vbuf.c:19
size_t blen
Definition: vbuf.h:11
string conversion
Definition: pst2dii.cpp:53
static int unicode_up
Definition: vbuf.c:4
void pst_unicode_init()
Definition: vbuf.c:202
static size_t sbcs_conversion(pst_vbuf *dest, const char *inbuf, int iblen, iconv_t conversion)
Definition: vbuf.c:66
static const char * target_charset
Definition: vbuf.c:6
static int target_open_to
Definition: vbuf.c:8
static void pst_unicode_close()
Definition: vbuf.c:98