]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
30f07f1a | 2 | * Copyright (c) 2008, 2009, 2010 Nicira Networks. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | ||
17 | #include <config.h> | |
18 | #include "ofpbuf.h" | |
19 | #include <assert.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
0ab8e15f | 22 | #include "dynamic-string.h" |
064af421 BP |
23 | #include "util.h" |
24 | ||
25 | /* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of | |
26 | * memory starting at 'base'. | |
27 | * | |
28 | * 'base' should ordinarily be the first byte of a region obtained from | |
29 | * malloc(), but in circumstances where it can be guaranteed that 'b' will | |
30 | * never need to be expanded or freed, it can be a pointer into arbitrary | |
31 | * memory. */ | |
32 | void | |
33 | ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated) | |
34 | { | |
35 | b->base = b->data = base; | |
36 | b->allocated = allocated; | |
37 | b->size = 0; | |
38 | b->l2 = b->l3 = b->l4 = b->l7 = NULL; | |
b3907fbc | 39 | list_poison(&b->list_node); |
d45e9c65 | 40 | b->private_p = NULL; |
064af421 BP |
41 | } |
42 | ||
0bc9407d BP |
43 | /* Initializes 'b' as an ofpbuf whose data starts at 'data' and continues for |
44 | * 'size' bytes. This is appropriate for an ofpbuf that will be used to | |
45 | * inspect existing data, without moving it around or reallocating it, and | |
46 | * generally without modifying it at all. */ | |
47 | void | |
48 | ofpbuf_use_const(struct ofpbuf *b, const void *data, size_t size) | |
49 | { | |
50 | ofpbuf_use(b, (void *) data, size); | |
51 | b->size = size; | |
52 | } | |
53 | ||
064af421 BP |
54 | /* Initializes 'b' as an empty ofpbuf with an initial capacity of 'size' |
55 | * bytes. */ | |
56 | void | |
57 | ofpbuf_init(struct ofpbuf *b, size_t size) | |
58 | { | |
59 | ofpbuf_use(b, size ? xmalloc(size) : NULL, size); | |
60 | } | |
61 | ||
62 | /* Frees memory that 'b' points to. */ | |
63 | void | |
d295e8e9 | 64 | ofpbuf_uninit(struct ofpbuf *b) |
064af421 BP |
65 | { |
66 | if (b) { | |
67 | free(b->base); | |
68 | } | |
69 | } | |
70 | ||
71 | /* Frees memory that 'b' points to and allocates a new ofpbuf */ | |
72 | void | |
73 | ofpbuf_reinit(struct ofpbuf *b, size_t size) | |
74 | { | |
75 | ofpbuf_uninit(b); | |
76 | ofpbuf_init(b, size); | |
77 | } | |
78 | ||
79 | /* Creates and returns a new ofpbuf with an initial capacity of 'size' | |
80 | * bytes. */ | |
81 | struct ofpbuf * | |
82 | ofpbuf_new(size_t size) | |
83 | { | |
84 | struct ofpbuf *b = xmalloc(sizeof *b); | |
85 | ofpbuf_init(b, size); | |
86 | return b; | |
87 | } | |
88 | ||
68efcbec BP |
89 | /* Creates and returns a new ofpbuf with an initial capacity of 'size + |
90 | * headroom' bytes, reserving the first 'headroom' bytes as headroom. */ | |
91 | struct ofpbuf * | |
92 | ofpbuf_new_with_headroom(size_t size, size_t headroom) | |
93 | { | |
94 | struct ofpbuf *b = ofpbuf_new(size + headroom); | |
95 | ofpbuf_reserve(b, headroom); | |
96 | return b; | |
97 | } | |
98 | ||
064af421 BP |
99 | struct ofpbuf * |
100 | ofpbuf_clone(const struct ofpbuf *buffer) | |
101 | { | |
102 | return ofpbuf_clone_data(buffer->data, buffer->size); | |
103 | } | |
104 | ||
68efcbec BP |
105 | /* Creates and returns a new ofpbuf whose data are copied from 'buffer'. The |
106 | * returned ofpbuf will additionally have 'headroom' bytes of headroom. */ | |
107 | struct ofpbuf * | |
108 | ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom) | |
109 | { | |
110 | struct ofpbuf *b = ofpbuf_new_with_headroom(buffer->size, headroom); | |
111 | ofpbuf_put(b, buffer->data, buffer->size); | |
112 | return b; | |
113 | } | |
114 | ||
064af421 BP |
115 | struct ofpbuf * |
116 | ofpbuf_clone_data(const void *data, size_t size) | |
117 | { | |
118 | struct ofpbuf *b = ofpbuf_new(size); | |
119 | ofpbuf_put(b, data, size); | |
120 | return b; | |
121 | } | |
122 | ||
123 | /* Frees memory that 'b' points to, as well as 'b' itself. */ | |
124 | void | |
d295e8e9 | 125 | ofpbuf_delete(struct ofpbuf *b) |
064af421 BP |
126 | { |
127 | if (b) { | |
128 | ofpbuf_uninit(b); | |
129 | free(b); | |
130 | } | |
131 | } | |
132 | ||
133 | /* Returns the number of bytes of headroom in 'b', that is, the number of bytes | |
134 | * of unused space in ofpbuf 'b' before the data that is in use. (Most | |
135 | * commonly, the data in a ofpbuf is at its beginning, and thus the ofpbuf's | |
136 | * headroom is 0.) */ | |
137 | size_t | |
5019f688 | 138 | ofpbuf_headroom(const struct ofpbuf *b) |
064af421 BP |
139 | { |
140 | return (char*)b->data - (char*)b->base; | |
141 | } | |
142 | ||
143 | /* Returns the number of bytes that may be appended to the tail end of ofpbuf | |
144 | * 'b' before the ofpbuf must be reallocated. */ | |
145 | size_t | |
5019f688 | 146 | ofpbuf_tailroom(const struct ofpbuf *b) |
064af421 BP |
147 | { |
148 | return (char*)ofpbuf_end(b) - (char*)ofpbuf_tail(b); | |
149 | } | |
150 | ||
1f5cbaa3 BP |
151 | /* Changes 'b->base' to 'new_base' and adjusts all of 'b''s internal pointers |
152 | * to reflect the change. */ | |
153 | static void | |
154 | ofpbuf_rebase__(struct ofpbuf *b, void *new_base) | |
064af421 | 155 | { |
1f5cbaa3 | 156 | if (b->base != new_base) { |
064af421 | 157 | uintptr_t base_delta = (char*)new_base - (char*)b->base; |
064af421 | 158 | b->base = new_base; |
064af421 BP |
159 | b->data = (char*)b->data + base_delta; |
160 | if (b->l2) { | |
161 | b->l2 = (char*)b->l2 + base_delta; | |
162 | } | |
163 | if (b->l3) { | |
164 | b->l3 = (char*)b->l3 + base_delta; | |
165 | } | |
166 | if (b->l4) { | |
167 | b->l4 = (char*)b->l4 + base_delta; | |
168 | } | |
169 | if (b->l7) { | |
170 | b->l7 = (char*)b->l7 + base_delta; | |
171 | } | |
172 | } | |
173 | } | |
174 | ||
1f5cbaa3 BP |
175 | /* Reallocates 'b' so that it has exactly 'new_tailroom' bytes of tailroom. */ |
176 | static void | |
177 | ofpbuf_resize_tailroom__(struct ofpbuf *b, size_t new_tailroom) | |
178 | { | |
179 | b->allocated = ofpbuf_headroom(b) + b->size + new_tailroom; | |
180 | ofpbuf_rebase__(b, xrealloc(b->base, b->allocated)); | |
181 | } | |
182 | ||
183 | /* Ensures that 'b' has room for at least 'size' bytes at its tail end, | |
184 | * reallocating and copying its data if necessary. Its headroom, if any, is | |
185 | * preserved. */ | |
186 | void | |
d295e8e9 | 187 | ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size) |
1f5cbaa3 BP |
188 | { |
189 | if (size > ofpbuf_tailroom(b)) { | |
190 | ofpbuf_resize_tailroom__(b, MAX(size, 64)); | |
191 | } | |
192 | } | |
193 | ||
064af421 | 194 | void |
d295e8e9 | 195 | ofpbuf_prealloc_headroom(struct ofpbuf *b, size_t size) |
064af421 BP |
196 | { |
197 | assert(size <= ofpbuf_headroom(b)); | |
198 | } | |
199 | ||
1f5cbaa3 BP |
200 | /* Trims the size of 'b' to fit its actual content, reducing its tailroom to |
201 | * 0. Its headroom, if any, is preserved. */ | |
064af421 BP |
202 | void |
203 | ofpbuf_trim(struct ofpbuf *b) | |
204 | { | |
1f5cbaa3 BP |
205 | if (ofpbuf_tailroom(b) > 0) { |
206 | ofpbuf_resize_tailroom__(b, 0); | |
064af421 BP |
207 | } |
208 | } | |
209 | ||
210 | /* Appends 'size' bytes of data to the tail end of 'b', reallocating and | |
211 | * copying its data if necessary. Returns a pointer to the first byte of the | |
212 | * new data, which is left uninitialized. */ | |
213 | void * | |
d295e8e9 | 214 | ofpbuf_put_uninit(struct ofpbuf *b, size_t size) |
064af421 BP |
215 | { |
216 | void *p; | |
217 | ofpbuf_prealloc_tailroom(b, size); | |
218 | p = ofpbuf_tail(b); | |
219 | b->size += size; | |
220 | return p; | |
221 | } | |
222 | ||
223 | /* Appends 'size' zeroed bytes to the tail end of 'b'. Data in 'b' is | |
224 | * reallocated and copied if necessary. Returns a pointer to the first byte of | |
225 | * the data's location in the ofpbuf. */ | |
226 | void * | |
227 | ofpbuf_put_zeros(struct ofpbuf *b, size_t size) | |
228 | { | |
229 | void *dst = ofpbuf_put_uninit(b, size); | |
230 | memset(dst, 0, size); | |
231 | return dst; | |
232 | } | |
233 | ||
234 | /* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b' | |
235 | * is reallocated and copied if necessary. Returns a pointer to the first | |
236 | * byte of the data's location in the ofpbuf. */ | |
237 | void * | |
d295e8e9 | 238 | ofpbuf_put(struct ofpbuf *b, const void *p, size_t size) |
064af421 BP |
239 | { |
240 | void *dst = ofpbuf_put_uninit(b, size); | |
241 | memcpy(dst, p, size); | |
242 | return dst; | |
243 | } | |
244 | ||
245 | /* Reserves 'size' bytes of headroom so that they can be later allocated with | |
246 | * ofpbuf_push_uninit() without reallocating the ofpbuf. */ | |
247 | void | |
d295e8e9 | 248 | ofpbuf_reserve(struct ofpbuf *b, size_t size) |
064af421 BP |
249 | { |
250 | assert(!b->size); | |
251 | ofpbuf_prealloc_tailroom(b, size); | |
252 | b->data = (char*)b->data + size; | |
253 | } | |
254 | ||
255 | void * | |
d295e8e9 | 256 | ofpbuf_push_uninit(struct ofpbuf *b, size_t size) |
064af421 BP |
257 | { |
258 | ofpbuf_prealloc_headroom(b, size); | |
259 | b->data = (char*)b->data - size; | |
260 | b->size += size; | |
261 | return b->data; | |
262 | } | |
263 | ||
30f07f1a BP |
264 | /* Prefixes 'size' zeroed bytes to the head end of 'b'. 'b' must have at least |
265 | * 'size' bytes of headroom. Returns a pointer to the first byte of the data's | |
266 | * location in the ofpbuf. */ | |
267 | void * | |
268 | ofpbuf_push_zeros(struct ofpbuf *b, size_t size) | |
269 | { | |
270 | void *dst = ofpbuf_push_uninit(b, size); | |
271 | memset(dst, 0, size); | |
272 | return dst; | |
273 | } | |
274 | ||
064af421 | 275 | void * |
d295e8e9 | 276 | ofpbuf_push(struct ofpbuf *b, const void *p, size_t size) |
064af421 BP |
277 | { |
278 | void *dst = ofpbuf_push_uninit(b, size); | |
279 | memcpy(dst, p, size); | |
280 | return dst; | |
281 | } | |
282 | ||
283 | /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to | |
284 | * byte 'offset'. Otherwise, returns a null pointer. */ | |
285 | void * | |
d295e8e9 | 286 | ofpbuf_at(const struct ofpbuf *b, size_t offset, size_t size) |
064af421 BP |
287 | { |
288 | return offset + size <= b->size ? (char *) b->data + offset : NULL; | |
289 | } | |
290 | ||
291 | /* Returns a pointer to byte 'offset' in 'b', which must contain at least | |
292 | * 'offset + size' bytes of data. */ | |
293 | void * | |
d295e8e9 | 294 | ofpbuf_at_assert(const struct ofpbuf *b, size_t offset, size_t size) |
064af421 BP |
295 | { |
296 | assert(offset + size <= b->size); | |
297 | return ((char *) b->data) + offset; | |
298 | } | |
299 | ||
300 | /* Returns the byte following the last byte of data in use in 'b'. */ | |
301 | void * | |
d295e8e9 | 302 | ofpbuf_tail(const struct ofpbuf *b) |
064af421 BP |
303 | { |
304 | return (char *) b->data + b->size; | |
305 | } | |
306 | ||
307 | /* Returns the byte following the last byte allocated for use (but not | |
308 | * necessarily in use) by 'b'. */ | |
309 | void * | |
d295e8e9 | 310 | ofpbuf_end(const struct ofpbuf *b) |
064af421 BP |
311 | { |
312 | return (char *) b->base + b->allocated; | |
313 | } | |
314 | ||
315 | /* Clears any data from 'b'. */ | |
316 | void | |
d295e8e9 | 317 | ofpbuf_clear(struct ofpbuf *b) |
064af421 BP |
318 | { |
319 | b->data = b->base; | |
320 | b->size = 0; | |
321 | } | |
322 | ||
323 | /* Removes 'size' bytes from the head end of 'b', which must contain at least | |
324 | * 'size' bytes of data. Returns the first byte of data removed. */ | |
325 | void * | |
d295e8e9 | 326 | ofpbuf_pull(struct ofpbuf *b, size_t size) |
064af421 BP |
327 | { |
328 | void *data = b->data; | |
329 | assert(b->size >= size); | |
330 | b->data = (char*)b->data + size; | |
331 | b->size -= size; | |
332 | return data; | |
333 | } | |
334 | ||
335 | /* If 'b' has at least 'size' bytes of data, removes that many bytes from the | |
336 | * head end of 'b' and returns the first byte removed. Otherwise, returns a | |
337 | * null pointer without modifying 'b'. */ | |
338 | void * | |
d295e8e9 | 339 | ofpbuf_try_pull(struct ofpbuf *b, size_t size) |
064af421 BP |
340 | { |
341 | return b->size >= size ? ofpbuf_pull(b, size) : NULL; | |
342 | } | |
0ab8e15f BP |
343 | |
344 | /* Returns a string that describes some of 'b''s metadata plus a hex dump of up | |
345 | * to 'maxbytes' from the start of the buffer. */ | |
346 | char * | |
347 | ofpbuf_to_string(const struct ofpbuf *b, size_t maxbytes) | |
348 | { | |
349 | struct ds s; | |
350 | ||
351 | ds_init(&s); | |
352 | ds_put_format(&s, "size=%zu, allocated=%zu, head=%zu, tail=%zu\n", | |
353 | b->size, b->allocated, | |
354 | ofpbuf_headroom(b), ofpbuf_tailroom(b)); | |
355 | ds_put_hex_dump(&s, b->data, MIN(b->size, maxbytes), 0, false); | |
356 | return ds_cstr(&s); | |
357 | } | |
b3907fbc BP |
358 | |
359 | /* Removes each of the "struct ofpbuf"s on 'list' from the list and frees | |
360 | * them. */ | |
361 | void | |
362 | ofpbuf_list_delete(struct list *list) | |
363 | { | |
364 | struct ofpbuf *b, *next; | |
365 | ||
366 | LIST_FOR_EACH_SAFE (b, next, list_node, list) { | |
367 | list_remove(&b->list_node); | |
368 | ofpbuf_delete(b); | |
369 | } | |
370 | } |