blob: 589cf4c436e6d7df1a1e34988448d122899bd52d [file] [log] [blame]
Lev Walkind9221842017-08-22 01:44:56 -07001#include <sys/types.h>
2#include <stdlib.h>
3#include <stdarg.h>
4#include <string.h>
5#include <stdio.h>
6#include <assert.h>
7
8#include "asn1_buffer.h"
9
10/*
11 * Create and destroy the buffer.
12 */
13abuf *
14abuf_new() {
15 abuf *ab = calloc(1, sizeof(abuf));
16 assert(ab);
17 ab->length = 0;
18 ab->size = 32;
19 ab->buffer = calloc(1, ab->size);
20 assert(ab->buffer);
21 return ab;
22}
23
24void abuf_free(abuf *ab) {
25 if(ab) {
26 union {
27 const char *c_buf;
28 char *nc_buf;
29 } const_cast;
30 const_cast.c_buf = ab->buffer;
31 free(const_cast.nc_buf);
32 free(ab);
33 }
34}
35
36/*
37 * Erase contents of the buffer (without destroying it).
38 */
39void
40abuf_clear(abuf *ab) {
41 union {
42 const char *c_buf;
43 char *nc_buf;
44 } const_cast;
45 if(!ab->buffer) {
46 ab->size = 32;
47 ab->buffer = calloc(1, ab->size);
48 assert(ab->buffer);
49 }
50 const_cast.c_buf = ab->buffer;
51 ab->length = 0;
52 const_cast.nc_buf[0] = '\0';
53}
54
55static void
Lev Walkine3204e72017-08-23 06:22:53 -070056abuf_resize_by(abuf *ab, size_t size) {
Lev Walkind9221842017-08-22 01:44:56 -070057 union {
58 const char *c_buf;
59 char *nc_buf;
60 } const_cast;
61 const_cast.c_buf = ab->buffer;
62
Lev Walkine3204e72017-08-23 06:22:53 -070063 assert(!ab->buffer || ab->buffer[ab->length] == '\0');
Lev Walkind9221842017-08-22 01:44:56 -070064
Lev Walkine3204e72017-08-23 06:22:53 -070065 size_t new_size = ab->length + size;
Lev Walkind9221842017-08-22 01:44:56 -070066 char *p = realloc(const_cast.nc_buf, new_size);
67 assert(p);
Lev Walkine3204e72017-08-23 06:22:53 -070068 if(!ab->buffer) {
69 assert(ab->length == 0);
70 *p = '\0';
71 }
Lev Walkind9221842017-08-22 01:44:56 -070072 ab->buffer = p;
73 assert(ab->buffer[ab->length] == '\0');
74 ab->size = new_size;
75}
76
Lev Walkine3204e72017-08-23 06:22:53 -070077void abuf_add_bytes(abuf *ab, const char *str, size_t size) {
78 abuf_resize_by(ab, size + 1);
79 union {
80 const char *c_buf;
81 char *nc_buf;
82 } const_cast;
83 const_cast.c_buf = ab->buffer;
84 memcpy(&const_cast.nc_buf[ab->length], str, size);
85 ab->length += size;
86 const_cast.nc_buf[ab->length] = '\0';
87}
88
Lev Walkind9221842017-08-22 01:44:56 -070089void abuf_str(abuf *ab, const char *str) {
Lev Walkine3204e72017-08-23 06:22:53 -070090 abuf_add_bytes(ab, str, strlen(str));
Lev Walkind9221842017-08-22 01:44:56 -070091}
92
93void abuf_buf(abuf *ab, const abuf *buf) {
Lev Walkine3204e72017-08-23 06:22:53 -070094 abuf_add_bytes(ab, buf->buffer, buf->length);
Lev Walkind9221842017-08-22 01:44:56 -070095}
96
Lev Walkine3204e72017-08-23 06:22:53 -070097int abuf_printf(abuf *ab, const char *fmt, ...) {
Lev Walkind9221842017-08-22 01:44:56 -070098 va_list ap;
99
100 for(;;) {
101 union {
102 const char *c_buf;
103 char *nc_buf;
104 } const_cast;
105 const_cast.c_buf = ab->buffer;
106 va_start(ap, fmt);
107 int ret = vsnprintf(&const_cast.nc_buf[ab->length],
108 ab->size - ab->length, fmt, ap);
109 va_end(ap);
110 assert(ret >= 0);
111 if((size_t)ret < ab->size - ab->length) {
112 ab->length += ret;
113 assert(ab->buffer[ab->length] == '\0');
Lev Walkine3204e72017-08-23 06:22:53 -0700114 return ret;
Lev Walkind9221842017-08-22 01:44:56 -0700115 }
116 const_cast.nc_buf[ab->length] = '\0'; /* Restore order */
117 abuf_resize_by(ab, ret + 1);
118 }
119}
120
Lev Walkine3204e72017-08-23 06:22:53 -0700121int abuf_vprintf(abuf *ab, const char *fmt, va_list ap) {
122 int ret;
123 char *str = 0;
124
125 ret = vasprintf(&str, fmt, ap);
126 assert(ret >= 0);
127 assert(str != NULL);
128
129 abuf_add_bytes(ab, str, ret);
130
131 free(str);
132
133 return ret;
134}
135