better split up of library files "types.h" & "definitions.h"
[strongswan.git] / src / libstrongswan / chunk.c
1 /**
2 * @file chunk.c
3 *
4 * @brief Pointer/lenght abstraction and its functions.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <stdio.h>
25
26 #include "chunk.h"
27
28 #include <printf_hook.h>
29
30 /**
31 * Empty chunk.
32 */
33 chunk_t chunk_empty = { NULL, 0 };
34
35 /**
36 * Described in header.
37 */
38 chunk_t chunk_clone(chunk_t chunk)
39 {
40 chunk_t clone = chunk_empty;
41
42 if (chunk.ptr && chunk.len > 0)
43 {
44 clone.ptr = malloc(chunk.len);
45 clone.len = chunk.len;
46 memcpy(clone.ptr, chunk.ptr, chunk.len);
47 }
48
49 return clone;
50 }
51
52 /**
53 * Decribed in header.
54 */
55 chunk_t chunk_cat(const char* mode, ...)
56 {
57 chunk_t construct;
58 va_list chunks;
59 u_char *pos;
60 int i;
61 int count = strlen(mode);
62
63 /* sum up lengths of individual chunks */
64 va_start(chunks, mode);
65 construct.len = 0;
66 for (i = 0; i < count; i++)
67 {
68 chunk_t ch = va_arg(chunks, chunk_t);
69 construct.len += ch.len;
70 }
71 va_end(chunks);
72
73 /* allocate needed memory for construct */
74 construct.ptr = malloc(construct.len);
75 pos = construct.ptr;
76
77 /* copy or move the chunks */
78 va_start(chunks, mode);
79 for (i = 0; i < count; i++)
80 {
81 chunk_t ch = va_arg(chunks, chunk_t);
82 switch (*mode++)
83 {
84 case 'm':
85 memcpy(pos, ch.ptr, ch.len);
86 pos += ch.len;
87 free(ch.ptr);
88 break;
89 case 'c':
90 default:
91 memcpy(pos, ch.ptr, ch.len);
92 pos += ch.len;
93 }
94 }
95 va_end(chunks);
96
97 return construct;
98 }
99
100 /**
101 * Described in header.
102 */
103 void chunk_free(chunk_t *chunk)
104 {
105 free(chunk->ptr);
106 chunk->ptr = NULL;
107 chunk->len = 0;
108 }
109
110 /**
111 * Described in header.
112 */
113 chunk_t chunk_alloc(size_t bytes)
114 {
115 chunk_t new_chunk;
116 new_chunk.ptr = malloc(bytes);
117 new_chunk.len = bytes;
118 return new_chunk;
119 }
120
121 /**
122 * Described in header.
123 */
124 bool chunk_equals(chunk_t a, chunk_t b)
125 {
126 return a.ptr != NULL && b.ptr != NULL &&
127 a.len == b.len && memeq(a.ptr, b.ptr, a.len);
128 }
129
130 /**
131 * Described in header.
132 */
133 bool chunk_equals_or_null(chunk_t a, chunk_t b)
134 {
135 if (a.ptr == NULL || b.ptr == NULL)
136 return TRUE;
137 return a.len == b.len && memeq(a.ptr, b.ptr, a.len);
138 }
139
140 /**
141 * Number of bytes per line to dump raw data
142 */
143 #define BYTES_PER_LINE 16
144
145 /**
146 * output handler in printf() for byte ranges
147 */
148 static int print_bytes(FILE *stream, const struct printf_info *info,
149 const void *const *args)
150 {
151 char *bytes = *((void**)(args[0]));
152 int len = *((size_t*)(args[1]));
153
154 char buffer[BYTES_PER_LINE * 3];
155 char ascii_buffer[BYTES_PER_LINE + 1];
156 char *buffer_pos = buffer;
157 char *bytes_pos = bytes;
158 char *bytes_roof = bytes + len;
159 int line_start = 0;
160 int i = 0;
161 int written = 0;
162
163 written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
164
165 while (bytes_pos < bytes_roof)
166 {
167 static char hexdig[] = "0123456789ABCDEF";
168
169 *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
170 *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
171
172 ascii_buffer[i++] =
173 (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
174
175 if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
176 {
177 int padding = 3 * (BYTES_PER_LINE - i);
178 int written;
179
180 while (padding--)
181 {
182 *buffer_pos++ = ' ';
183 }
184 *buffer_pos++ = '\0';
185 ascii_buffer[i] = '\0';
186
187 written += fprintf(stream, "\n%4d: %s %s",
188 line_start, buffer, ascii_buffer);
189
190
191 buffer_pos = buffer;
192 line_start += BYTES_PER_LINE;
193 i = 0;
194 }
195 else
196 {
197 *buffer_pos++ = ' ';
198 }
199 }
200 return written;
201 }
202
203 /**
204 * output handler in printf() for chunks
205 */
206 static int print_chunk(FILE *stream, const struct printf_info *info,
207 const void *const *args)
208 {
209 chunk_t *chunk = *((chunk_t**)(args[0]));
210 bool first = TRUE;
211 chunk_t copy = *chunk;
212 int written = 0;
213
214 if (!info->alt)
215 {
216 const void *new_args[] = {&chunk->ptr, &chunk->len};
217 return print_bytes(stream, info, new_args);
218 }
219
220 while (copy.len > 0)
221 {
222 if (first)
223 {
224 first = FALSE;
225 }
226 else
227 {
228 written += fprintf(stream, ":");
229 }
230 written += fprintf(stream, "%02x", *copy.ptr++);
231 copy.len--;
232 }
233 return written;
234 }
235
236 /**
237 * register printf() handlers
238 */
239 static void __attribute__ ((constructor))print_register()
240 {
241 register_printf_function(PRINTF_CHUNK, print_chunk, arginfo_ptr);
242 register_printf_function(PRINTF_BYTES, print_bytes, arginfo_ptr_int);
243 }