1 /*
2 * libwbxml, the WBXML Library.
3 * Copyright (C) 2002-2008 Aymerick Jehanne <aymerick@jehanne.org>
4 * Copyright (C) 2011 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * LGPL v2.1: http://www.gnu.org/copyleft/lesser.txt
21 *
22 * Contact: aymerick@jehanne.org
23 * Home: http://libwbxml.aymerick.com
24 */
25
26 /**
27 * @file wbxml_buffers.c
28 * @ingroup wbxml_buffers
29 *
30 * @author Aymerick Jehanne <aymerick@jehanne.org>
31 * @date 02/03/12
32 *
33 * @brief Generic Buffers Functions
34 *
35 * @note Original idea: Kannel Project (http://www.kannel.org/)
36 */
37
38 #include <limits.h>
39 #include <ctype.h>
40
41 #include "wbxml_buffers.h"
42 #include "wbxml_base64.h"
43
44
45 /* Memory management define */
46 #define WBXML_BUFFER_SPLIT_BLOCK 20
47
48 /**
49 * The Generic Buffer type
50 */
51 struct WBXMLBuffer_s
52 {
53 WB_UTINY *data; /**< The data */
54 WB_ULONG len; /**< Length of data in buffer */
55 WB_ULONG malloced; /**< Length of buffer */
56 WB_BOOL is_static; /**< Is it a static buffer ? */
57 };
58
59
60 static WB_BOOL grow_buff(WBXMLBuffer *buffer, WB_ULONG size);
61 static WB_BOOL insert_data(WBXMLBuffer *buffer, WB_ULONG pos, const WB_UTINY *data, WB_ULONG len);
62
63
64
65 /**********************************
66 * Public functions
67 */
68
69
wbxml_buffer_create_real(const WB_UTINY * data,WB_ULONG len,WB_ULONG malloc_block)70 WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_create_real(const WB_UTINY *data, WB_ULONG len, WB_ULONG malloc_block)
71 {
72 WBXMLBuffer *buffer = NULL;
73
74 buffer = wbxml_malloc(sizeof(WBXMLBuffer));
75 if (buffer == NULL)
76 return NULL;
77
78 buffer->is_static = FALSE;
79
80 if ((len <= 0) || (data == NULL)) {
81 buffer->malloced = 0;
82 buffer->len = 0;
83 buffer->data = NULL;
84 }
85 else {
86 if (len + 1 > malloc_block + 1)
87 buffer->malloced = len + 1 + malloc_block;
88 else
89 buffer->malloced = malloc_block + 1;
90
91 buffer->data = wbxml_malloc(buffer->malloced * sizeof(WB_UTINY));
92 if (buffer->data == NULL) {
93 wbxml_free(buffer);
94 return NULL;
95 }
96
97 buffer->len = len;
98 memcpy(buffer->data, data, len);
99 buffer->data[len] = '\0';
100 }
101
102 return buffer;
103 }
104
105
wbxml_buffer_sta_create_real(const WB_UTINY * data,WB_ULONG len)106 WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_sta_create_real(const WB_UTINY *data, WB_ULONG len)
107 {
108 WBXMLBuffer *buffer = NULL;
109
110 buffer = wbxml_malloc(sizeof(WBXMLBuffer));
111 if (buffer == NULL) {
112 return NULL;
113 }
114
115 buffer->is_static = TRUE;
116 buffer->data = (WB_UTINY *) data;
117 buffer->len = len;
118
119 return buffer;
120 }
121
122
wbxml_buffer_destroy(WBXMLBuffer * buffer)123 WBXML_DECLARE(void) wbxml_buffer_destroy(WBXMLBuffer *buffer)
124 {
125 if (buffer != NULL) {
126 if (!buffer->is_static) {
127 /* Free dynamic data */
128 wbxml_free(buffer->data);
129 }
130
131 /* Free structure */
132 wbxml_free(buffer);
133 }
134 }
135
136
wbxml_buffer_destroy_item(void * buff)137 WBXML_DECLARE_NONSTD(void) wbxml_buffer_destroy_item(void *buff)
138 {
139 wbxml_buffer_destroy((WBXMLBuffer *) buff);
140 }
141
142
wbxml_buffer_duplicate(WBXMLBuffer * buff)143 WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_duplicate(WBXMLBuffer *buff)
144 {
145 WBXMLBuffer *result = NULL;
146
147 if (buff == NULL)
148 return NULL;
149
150 result = wbxml_buffer_create_real(wbxml_buffer_get_cstr(buff),
151 wbxml_buffer_len(buff),
152 wbxml_buffer_len(buff));
153
154 return result;
155 }
156
157
wbxml_buffer_len(WBXMLBuffer * buffer)158 WBXML_DECLARE(WB_ULONG) wbxml_buffer_len(WBXMLBuffer *buffer)
159 {
160 if (buffer == NULL)
161 return 0;
162
163 return buffer->len;
164 }
165
166
wbxml_buffer_get_char(WBXMLBuffer * buffer,WB_ULONG pos,WB_UTINY * result)167 WBXML_DECLARE(WB_BOOL) wbxml_buffer_get_char(WBXMLBuffer *buffer, WB_ULONG pos, WB_UTINY *result)
168 {
169 if ((buffer == NULL) || (pos >= buffer->len) || (result == NULL))
170 return FALSE;
171
172 *result = buffer->data[pos];
173 return TRUE;
174 }
175
176
wbxml_buffer_set_char(WBXMLBuffer * buffer,WB_ULONG pos,WB_UTINY ch)177 WBXML_DECLARE(WB_BOOL) wbxml_buffer_set_char(WBXMLBuffer *buffer, WB_ULONG pos, WB_UTINY ch)
178 {
179 if ((buffer == NULL) || (buffer->is_static) || (pos >= buffer->len))
180 return FALSE;
181
182 buffer->data[pos] = ch;
183
184 return TRUE;
185 }
186
187
wbxml_buffer_get_cstr(WBXMLBuffer * buffer)188 WBXML_DECLARE(WB_UTINY *) wbxml_buffer_get_cstr(WBXMLBuffer *buffer)
189 {
190 if ((buffer == NULL) || (buffer->len == 0))
191 return WBXML_UTINY_NULL_STRING;
192
193 return buffer->data;
194 }
195
196
wbxml_buffer_insert(WBXMLBuffer * to,WBXMLBuffer * buffer,WB_ULONG pos)197 WBXML_DECLARE(WB_BOOL) wbxml_buffer_insert(WBXMLBuffer *to, WBXMLBuffer *buffer, WB_ULONG pos)
198 {
199 if ((to != NULL) && (buffer != NULL) && !to->is_static)
200 return insert_data(to, pos, buffer->data, buffer->len);
201
202 return FALSE;
203 }
204
205
wbxml_buffer_insert_cstr(WBXMLBuffer * to,const WB_UTINY * str,WB_ULONG pos)206 WBXML_DECLARE(WB_BOOL) wbxml_buffer_insert_cstr(WBXMLBuffer *to, const WB_UTINY *str, WB_ULONG pos)
207 {
208 if ((to != NULL) && (str != NULL) && !to->is_static)
209 return insert_data(to, pos, str, WBXML_STRLEN(str));
210
211 return FALSE;
212 }
213
214
wbxml_buffer_append(WBXMLBuffer * dest,WBXMLBuffer * buff)215 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append(WBXMLBuffer *dest, WBXMLBuffer *buff)
216 {
217 if ((dest == NULL) || dest->is_static)
218 return FALSE;
219
220 if (buff == NULL)
221 return TRUE;
222
223 return wbxml_buffer_append_data(dest, wbxml_buffer_get_cstr(buff), wbxml_buffer_len(buff));
224 }
225
226
wbxml_buffer_append_data_real(WBXMLBuffer * buffer,const WB_UTINY * data,WB_ULONG len)227 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_data_real(WBXMLBuffer *buffer, const WB_UTINY *data, WB_ULONG len)
228 {
229 if ((buffer == NULL) || buffer->is_static)
230 return FALSE;
231
232 if ((data == NULL) || (len == 0))
233 return TRUE;
234
235 return insert_data(buffer, buffer->len, data, len);
236 }
237
wbxml_buffer_append_cstr_real(WBXMLBuffer * buffer,const WB_UTINY * data)238 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_cstr_real(WBXMLBuffer *buffer, const WB_UTINY *data)
239 {
240 if ((buffer == NULL) || buffer->is_static) {
241 return FALSE;
242 }
243
244 if (data == NULL)
245 return TRUE;
246
247 return wbxml_buffer_append_data(buffer, data, WBXML_STRLEN(data));
248 }
249
250
wbxml_buffer_append_char(WBXMLBuffer * buffer,WB_UTINY ch)251 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_char(WBXMLBuffer *buffer, WB_UTINY ch)
252 {
253 WB_UTINY c = ch;
254
255 if ((buffer == NULL) || buffer->is_static)
256 return FALSE;
257
258 return insert_data(buffer, buffer->len, &c, 1);
259 }
260
261
wbxml_buffer_append_mb_uint_32(WBXMLBuffer * buffer,WB_ULONG value)262 WBXML_DECLARE(WB_BOOL) wbxml_buffer_append_mb_uint_32(WBXMLBuffer *buffer, WB_ULONG value)
263 {
264 /**
265 * A uintvar is defined to be up to 32 bits large
266 * so it will fit in 5 octets (to handle continuation bits)
267 */
268 WB_UTINY octets[5];
269 WB_LONG i = 0, start = 0;
270
271 if ((buffer == NULL) || buffer->is_static)
272 return FALSE;
273
274 /**
275 * Handle last byte separately; it has no continuation bit,
276 * and must be encoded even if value is 0.
277 */
278 octets[4] = (WB_UTINY) (value & 0x7f);
279 value >>= 7;
280
281 for (i = 3; value > 0 && i >= 0; i--) {
282 octets[i] = (WB_UTINY) (0x80 | (value & 0x7f));
283 value >>= 7;
284 }
285 start = i + 1;
286
287 return wbxml_buffer_append_data(buffer, octets + start, 5 - start);
288 }
289
290
wbxml_buffer_delete(WBXMLBuffer * buffer,WB_ULONG pos,WB_ULONG len)291 WBXML_DECLARE(WB_BOOL) wbxml_buffer_delete(WBXMLBuffer *buffer, WB_ULONG pos, WB_ULONG len)
292 {
293 if ((buffer == NULL) || (buffer->is_static))
294 return FALSE;
295
296 if ((pos >= buffer->len) || (len <= 0))
297 return FALSE;
298
299 memmove(buffer->data + pos, buffer->data + pos + len,
300 buffer->len - pos - len);
301
302 buffer->len -= len;
303 buffer->data[buffer->len] = '\0';
304
305 return TRUE;
306 }
307
308
wbxml_buffer_shrink_blanks(WBXMLBuffer * buffer)309 WBXML_DECLARE(WB_BOOL) wbxml_buffer_shrink_blanks(WBXMLBuffer *buffer)
310 {
311 WB_ULONG i = 0, j = 0, end = 0;
312 WB_UTINY ch = 0;
313
314 if ((buffer == NULL) || buffer->is_static)
315 return FALSE;
316
317 end = wbxml_buffer_len(buffer);
318
319 for (i = 0; i < end; i++)
320 {
321 if (wbxml_buffer_get_char(buffer, i, &ch) && isspace(ch))
322 {
323 /* Replace space by a whitespace */
324 if (ch != ' ')
325 wbxml_buffer_set_char(buffer, i, ' ');
326
327 /* Remove all following spaces */
328 j = i = i + 1;
329 while (wbxml_buffer_get_char(buffer, j, &ch) && isspace(ch))
330 j++;
331
332 if (j - i > 1)
333 wbxml_buffer_delete(buffer, i, j - i);
334 }
335 }
336
337 return TRUE;
338 }
339
340
wbxml_buffer_strip_blanks(WBXMLBuffer * buffer)341 WBXML_DECLARE(WB_BOOL) wbxml_buffer_strip_blanks(WBXMLBuffer *buffer)
342 {
343 WB_ULONG start = 0, end = 0, len = 0;
344 WB_UTINY ch = 0;
345
346 if ((buffer == NULL) || buffer->is_static)
347 return FALSE;
348
349 /* Remove whitespaces at beginning of buffer... */
350 while (wbxml_buffer_get_char(buffer, start, &ch) &&
351 isspace(ch) &&
352 start <= wbxml_buffer_len(buffer))
353 {
354 start ++;
355 }
356
357 if (start > 0)
358 wbxml_buffer_delete(buffer, 0, start);
359
360 /* ... and at the end */
361 if ((len = wbxml_buffer_len(buffer)) > 0) {
362 end = len = len - 1;
363 while (wbxml_buffer_get_char(buffer, end, &ch) &&
364 isspace(ch))
365 {
366 end--;
367 }
368 wbxml_buffer_delete(buffer, end + 1, len - end);
369 }
370
371 return TRUE;
372 }
373
wbxml_buffer_no_spaces(WBXMLBuffer * buffer)374 WBXML_DECLARE(void) wbxml_buffer_no_spaces(WBXMLBuffer *buffer)
375 {
376 WB_ULONG i = 0, j = 0, end = 0;
377 WB_UTINY ch = 0;
378
379 if ((buffer == NULL) || buffer->is_static)
380 return;
381
382 while (i < wbxml_buffer_len(buffer))
383 {
384 if (wbxml_buffer_get_char(buffer, i, &ch) && isspace(ch))
385 {
386 wbxml_buffer_delete(buffer, i, 1);
387 } else {
388 i++;
389 }
390 }
391 }
392
wbxml_buffer_compare(WBXMLBuffer * buff1,WBXMLBuffer * buff2)393 WBXML_DECLARE(WB_LONG) wbxml_buffer_compare(WBXMLBuffer *buff1, WBXMLBuffer *buff2)
394 {
395 WB_LONG ret = 0, len = 0;
396
397 if ((buff1 == NULL) || (buff2 == NULL)) {
398 if ((buff1 == NULL) && (buff2 == NULL))
399 return 0;
400
401 if (buff1 == NULL)
402 return -1;
403 else
404 return 1;
405 }
406
407 if (buff1->len < buff2->len)
408 len = buff1->len;
409 else
410 len = buff2->len;
411
412 if (len == 0)
413 {
414 if (buff1->len == 0 && buff2->len > 0)
415 return -1;
416 if (buff1->len > 0 && buff2->len == 0)
417 return 1;
418 return 0;
419 }
420
421 if ((ret = memcmp(buff1->data, buff2->data, len)) == 0)
422 {
423 if (buff1->len < buff2->len)
424 ret = -1;
425 else {
426 if (buff1->len > buff2->len)
427 ret = 1;
428 }
429 }
430
431 return ret;
432 }
433
434
wbxml_buffer_compare_cstr(WBXMLBuffer * buff,const WB_TINY * str)435 WBXML_DECLARE(WB_LONG) wbxml_buffer_compare_cstr(WBXMLBuffer *buff, const WB_TINY *str)
436 {
437 WB_LONG ret = 0, len = 0;
438
439 if ((buff == NULL) || (str == NULL)) {
440 if ((buff == NULL) && (str == NULL))
441 return 0;
442
443 if (buff == NULL)
444 return -1;
445 else
446 return 1;
447 }
448
449 if (buff->len < WBXML_STRLEN(str))
450 len = buff->len;
451 else
452 len = WBXML_STRLEN(str);
453
454 if (len == 0)
455 {
456 if (buff->len == 0 && WBXML_STRLEN(str) > 0)
457 return -1;
458 if (buff->len > 0 && WBXML_STRLEN(str) == 0)
459 return 1;
460 return 0;
461 }
462
463 if ((ret = memcmp(buff->data, str, len)) == 0)
464 {
465 if (buff->len < WBXML_STRLEN(str))
466 ret = -1;
467 else {
468 if (buff->len > WBXML_STRLEN(str))
469 ret = 1;
470 }
471 }
472
473 return ret;
474 }
475
476
wbxml_buffer_split_words_real(WBXMLBuffer * buff)477 WBXML_DECLARE(WBXMLList *) wbxml_buffer_split_words_real(WBXMLBuffer *buff)
478 {
479 WB_UTINY *p = NULL;
480 WBXMLList *list = NULL;
481 WBXMLBuffer *word = NULL;
482 WB_ULONG i = 0, start = 0, end = 0;
483
484 if (buff == NULL)
485 return NULL;
486
487 if ((list = wbxml_list_create()) == NULL)
488 return NULL;
489
490 p = buff->data;
491 i = 0;
492 while (TRUE)
493 {
494 while (i < buff->len && isspace(*p)) {
495 ++p;
496 ++i;
497 }
498 start = i;
499
500 while (i < buff->len && !isspace(*p)) {
501 ++p;
502 ++i;
503 }
504 end = i;
505
506 if (start == end)
507 break;
508
509 if((word = wbxml_buffer_create(buff->data + start, end - start, WBXML_BUFFER_SPLIT_BLOCK)) == NULL) {
510 wbxml_list_destroy(list, wbxml_buffer_destroy_item);
511 return NULL;
512 }
513
514 wbxml_list_append(list, word);
515 }
516
517 return list;
518 }
519
520
wbxml_buffer_search_char(WBXMLBuffer * to,const WB_UTINY ch,WB_ULONG pos,WB_ULONG * result)521 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search_char(WBXMLBuffer *to, const WB_UTINY ch, WB_ULONG pos, WB_ULONG *result)
522 {
523 WB_UTINY *p = NULL;
524
525 if (to == NULL)
526 return FALSE;
527
528 if (pos >= to->len)
529 return FALSE;
530
531 if ((p = (WB_UTINY *) memchr(to->data + pos, ch, to->len - pos)) == NULL)
532 return FALSE;
533
534 if (result != NULL)
535 *result = p - to->data;
536
537 return TRUE;
538 }
539
540
wbxml_buffer_search(WBXMLBuffer * to,WBXMLBuffer * search,WB_ULONG pos,WB_ULONG * result)541 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search(WBXMLBuffer *to, WBXMLBuffer *search, WB_ULONG pos, WB_ULONG *result)
542 {
543 WB_UTINY first = 0;
544
545 if ((to == NULL) || (search == NULL))
546 return FALSE;
547
548 if (result != NULL)
549 *result = 0;
550
551 /* Always "find" an empty string */
552 if (search->len == 0)
553 return TRUE;
554
555 /* Check if 'search' is greater than 'to' */
556 if (search->len > to->len)
557 return FALSE;
558
559 /* We are searching for one char */
560 if (search->len == 1)
561 return wbxml_buffer_search_char(to, search->data[0], pos, result);
562
563 /* For each occurrence of search's first character in to, then check if the rest of needle follows.
564 * Stop if there are no more occurrences, or if the rest of 'search' can't possibly fit in 'to'. */
565 first = search->data[0];
566 while ((wbxml_buffer_search_char(to, first, pos, &pos)) &&
567 (to->len - pos >= search->len))
568 {
569 if (memcmp(to->data + pos, search->data, search->len) == 0) {
570 if (result != NULL)
571 *result = pos;
572 return TRUE;
573 }
574 pos++;
575 }
576
577 return FALSE;
578 }
579
580
wbxml_buffer_search_cstr(WBXMLBuffer * to,const WB_UTINY * search,WB_ULONG pos,WB_ULONG * result)581 WBXML_DECLARE(WB_BOOL) wbxml_buffer_search_cstr(WBXMLBuffer *to, const WB_UTINY *search, WB_ULONG pos, WB_ULONG *result)
582 {
583 WB_UTINY first = 0;
584
585 if ((to == NULL) || (search == NULL))
586 return FALSE;
587
588 if (result != NULL)
589 *result = 0;
590
591 /* Always "find" an empty string */
592 if (WBXML_STRLEN(search) == 0)
593 return TRUE;
594
595 /* Check if 'search' is greater than 'to' */
596 if (WBXML_STRLEN(search) > to->len)
597 return FALSE;
598
599 /* We are searching for one char */
600 if (WBXML_STRLEN(search) == 1)
601 return wbxml_buffer_search_char(to, search[0], pos, result);
602
603 /* For each occurrence of search's first character in to, then check if the rest of needle follows.
604 * Stop if there are no more occurrences, or if the rest of 'search' can't possibly fit in 'to'. */
605 first = search[0];
606 while ((wbxml_buffer_search_char(to, first, pos, &pos)) &&
607 (to->len - pos >= WBXML_STRLEN(search)))
608 {
609 if (memcmp(to->data + pos, search, WBXML_STRLEN(search)) == 0) {
610 if (result != NULL)
611 *result = pos;
612 return TRUE;
613 }
614 pos++;
615 }
616
617 return FALSE;
618 }
619
620
wbxml_buffer_contains_only_whitespaces(WBXMLBuffer * buffer)621 WBXML_DECLARE(WB_BOOL) wbxml_buffer_contains_only_whitespaces(WBXMLBuffer *buffer)
622 {
623 WB_ULONG i = 0;
624
625 if (buffer == NULL)
626 return FALSE;
627
628 for (i=0; i<buffer->len; i++) {
629 if (!isspace(*(buffer->data + i)))
630 return FALSE;
631 }
632
633 return TRUE;
634 }
635
636
wbxml_buffer_hex_to_binary(WBXMLBuffer * buffer)637 WBXML_DECLARE(WB_BOOL) wbxml_buffer_hex_to_binary(WBXMLBuffer *buffer)
638 {
639 WB_UTINY *p = NULL;
640 WB_ULONG i = 0, len = 0;
641
642 if ((buffer == NULL) || buffer->is_static)
643 return FALSE;
644
645 p = buffer->data;
646 len = wbxml_buffer_len(buffer);
647
648 /* Convert ascii data to binary values */
649 for (i = 0; i < len; i++, p++) {
650 if (*p >= '0' && *p <= '9')
651 *p -= '0';
652 else if (*p >= 'a' && *p <= 'f')
653 *p = (WB_UTINY) (*p - 'a' + 10);
654 else if (*p >= 'A' && *p <= 'F')
655 *p = (WB_UTINY) (*p - 'A' + 10);
656 else {
657 /* Bad Bad ! There should be only digits in the buffer ! */
658 *p = 0;
659 }
660 }
661
662 /* De-hexing will compress data by factor of 2 */
663 len = buffer->len / 2;
664
665 for (i = 0; i < len; i++)
666 buffer->data[i] = (WB_UTINY) (buffer->data[i * 2] * 16 | buffer->data[i * 2 + 1]);
667
668 buffer->len = len;
669 buffer->data[len] = '\0';
670
671 return TRUE;
672 }
673
674
wbxml_buffer_binary_to_hex(WBXMLBuffer * buffer,WB_BOOL uppercase)675 WBXML_DECLARE(WB_BOOL) wbxml_buffer_binary_to_hex(WBXMLBuffer *buffer, WB_BOOL uppercase)
676 {
677 WB_UTINY *hexits = NULL;
678 WB_LONG i = 0;
679
680 if ((buffer == NULL) || buffer->is_static)
681 return FALSE;
682
683 if (wbxml_buffer_len(buffer) == 0)
684 return TRUE;
685
686 hexits = (WB_UTINY *)(uppercase ? "0123456789ABCDEF" : "0123456789abcdef");
687
688 /* Grows the Buffer size by 2 */
689 grow_buff(buffer, buffer->len * 2);
690
691 /* In-place modification must be done back-to-front to avoid
692 * overwriting the data while we read it. Even the order of
693 * the two assignments is important, to get i == 0 right.
694 */
695 for (i = buffer->len - 1; i >= 0; i--) {
696 buffer->data[i * 2 + 1] = hexits[buffer->data[i] % 16];
697 buffer->data[i * 2] = hexits[(buffer->data[i] / 16) & 0xf];
698 }
699
700 buffer->len = buffer->len * 2;
701 buffer->data[buffer->len] = '\0';
702
703 return TRUE;
704 }
705
wbxml_buffer_decode_base64(WBXMLBuffer * buffer)706 WBXML_DECLARE(WBXMLError) wbxml_buffer_decode_base64(WBXMLBuffer *buffer)
707 {
708 WB_UTINY *result = NULL;
709 WB_LONG len = 0;
710 WBXMLError ret = WBXML_OK;
711
712 if ( (buffer == NULL) || (buffer->is_static) ) {
713 return WBXML_ERROR_INTERNAL;
714 }
715
716 wbxml_buffer_no_spaces(buffer);
717
718 if ((len = wbxml_base64_decode((const WB_UTINY *) wbxml_buffer_get_cstr(buffer),
719 wbxml_buffer_len(buffer), &result)) <= 0)
720 {
721 return WBXML_ERROR_B64_DEC;
722 }
723
724 /* Reset buffer */
725 wbxml_buffer_delete(buffer, 0, wbxml_buffer_len(buffer));
726
727 /* Set binary data */
728 if (!wbxml_buffer_append_data(buffer, result, len)) {
729 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
730 }
731
732 wbxml_free(result);
733
734 return ret;
735 }
736
wbxml_buffer_encode_base64(WBXMLBuffer * buffer)737 WBXML_DECLARE(WBXMLError) wbxml_buffer_encode_base64(WBXMLBuffer *buffer)
738 {
739 WB_UTINY *result = NULL;
740 WBXMLError ret = WBXML_OK;
741
742 if ( (buffer == NULL) || (buffer->is_static) ) {
743 return WBXML_ERROR_INTERNAL;
744 }
745
746 if ((result = wbxml_base64_encode((const WB_UTINY *) wbxml_buffer_get_cstr(buffer),
747 wbxml_buffer_len(buffer))) == NULL)
748 {
749 return WBXML_ERROR_B64_ENC;
750 }
751
752 /* Reset buffer */
753 wbxml_buffer_delete(buffer, 0, wbxml_buffer_len(buffer));
754
755 /* Set data */
756 if (!wbxml_buffer_append_cstr(buffer, result)) {
757 ret = WBXML_ERROR_NOT_ENOUGH_MEMORY;
758 }
759
760 wbxml_free(result);
761
762 return ret;
763 }
764
wbxml_buffer_remove_trailing_zeros(WBXMLBuffer * buffer)765 WBXML_DECLARE(WB_BOOL) wbxml_buffer_remove_trailing_zeros(WBXMLBuffer *buffer)
766 {
767 WB_UTINY ch = 0;
768
769 if ((buffer == NULL) || (buffer->is_static))
770 return FALSE;
771
772 while (buffer->len > 0) {
773 if (wbxml_buffer_get_char(buffer, wbxml_buffer_len(buffer) - 1, &ch) && (ch == '\0'))
774 wbxml_buffer_delete(buffer, wbxml_buffer_len(buffer) - 1, 1);
775 else
776 return TRUE;
777 }
778
779 return TRUE;
780 }
781
782
783 /**********************************
784 * Private functions
785 */
786
787 /**
788 * @brief Add space for at least 'size' octets
789 * @param buffer The buffer
790 * @param size The size to add
791 * @return TRUE is space successfully reserved, FALSE is size was negative, buffer was NULL or if not enough memory
792 */
grow_buff(WBXMLBuffer * buffer,WB_ULONG size)793 static WB_BOOL grow_buff(WBXMLBuffer *buffer, WB_ULONG size)
794 {
795 if ((buffer == NULL) || buffer->is_static)
796 return FALSE;
797
798 /* Make room for the invisible terminating NUL */
799 size++;
800
801 if ((buffer->len + size) > buffer->malloced) {
802 if ((buffer->malloced * 2) < (buffer->len + size))
803 buffer->malloced = buffer->len + size;
804 else
805 buffer->malloced *= 2;
806
807 buffer->data = wbxml_realloc(buffer->data, buffer->malloced);
808 if (buffer->data == NULL)
809 return FALSE;
810 }
811
812 return TRUE;
813 }
814
815
816 /**
817 * @brief Insert data into a Generic Buffer
818 * @param buffer The Generic Buffer
819 * @param pos Position in Generic Buffer where to insert data
820 * @param data Data to insert
821 * @param len Data length
822 * @return TRUE is data inserted, FALSE if not
823 */
insert_data(WBXMLBuffer * buffer,WB_ULONG pos,const WB_UTINY * data,WB_ULONG len)824 static WB_BOOL insert_data(WBXMLBuffer *buffer, WB_ULONG pos, const WB_UTINY *data, WB_ULONG len)
825 {
826 if ((buffer == NULL) || buffer->is_static || (len == 0) || (pos > buffer->len))
827 return FALSE;
828
829 if (!grow_buff(buffer, len))
830 return FALSE;
831
832 if (buffer->len > pos) {
833 /* Only if neccessary */
834 memmove(buffer->data + pos + len, buffer->data + pos, buffer->len - pos);
835 }
836
837 memcpy(buffer->data + pos, data, len);
838 buffer->len += len;
839 buffer->data[buffer->len] = '\0';
840
841 return TRUE;
842 }
843