2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 Copyright (c) 2005 Eliot Dresselhaus
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #ifndef included_clib_serialize_h
39 #define included_clib_serialize_h
42 #include <vppinfra/byte_order.h>
43 #include <vppinfra/types.h>
44 #include <vppinfra/vec.h>
45 #include <vppinfra/longjmp.h>
47 struct serialize_main_header_t;
48 struct serialize_stream_t;
50 typedef void (serialize_data_function_t) (struct serialize_main_header_t * h,
51 struct serialize_stream_t * s);
53 typedef struct serialize_stream_t
55 /* Current data buffer being serialized/unserialized. */
58 /* Size of buffer in bytes. */
61 /* Current index into buffer. */
62 u32 current_buffer_index;
64 /* Overflow buffer for when there is not enough room at the end of
65 buffer to hold serialized/unserialized data. */
68 /* Current index in overflow buffer for reads. */
69 u32 current_overflow_index;
72 #define SERIALIZE_END_OF_STREAM (1 << 0)
74 uword data_function_opaque;
76 u32 opaque[64 - 4 * sizeof (u32) - 1 * sizeof (uword) -
81 serialize_stream_set_end_of_stream (serialize_stream_t * s)
83 s->flags |= SERIALIZE_END_OF_STREAM;
87 serialize_stream_is_end_of_stream (serialize_stream_t * s)
89 return (s->flags & SERIALIZE_END_OF_STREAM) != 0;
92 typedef struct serialize_main_header_t
96 /* Data callback function and opaque data. */
97 serialize_data_function_t *data_function;
99 /* Error if signaled by data function. */
102 /* Exit unwind point if error occurs. */
103 clib_longjmp_t error_longjmp;
104 } serialize_main_header_t;
107 serialize_error (serialize_main_header_t * m, clib_error_t * error)
109 clib_longjmp (&m->error_longjmp, pointer_to_uword (error));
112 #define serialize_error_return(m,args...) \
113 serialize_error (&(m)->header, clib_error_return (0, args))
115 void *serialize_read_write_not_inline (serialize_main_header_t * m,
116 serialize_stream_t * s,
117 uword n_bytes, uword flags);
119 #define SERIALIZE_FLAG_IS_READ (1 << 0)
120 #define SERIALIZE_FLAG_IS_WRITE (1 << 1)
123 serialize_stream_read_write (serialize_main_header_t * header,
124 serialize_stream_t * s,
125 uword n_bytes, uword flags)
129 l = vec_len (s->overflow_buffer);
130 i = s->current_buffer_index;
132 s->current_buffer_index = j;
133 if (l == 0 && j <= s->n_buffer_bytes)
135 return s->buffer + i;
139 s->current_buffer_index = i;
140 return serialize_read_write_not_inline (header, s, n_bytes, flags);
146 serialize_main_header_t header;
147 serialize_stream_t stream;
151 serialize_set_end_of_stream (serialize_main_t * m)
153 serialize_stream_set_end_of_stream (&m->stream);
157 serialize_is_end_of_stream (serialize_main_t * m)
159 return serialize_stream_is_end_of_stream (&m->stream);
164 serialize_main_header_t header;
165 serialize_stream_t *streams;
166 } serialize_multiple_main_t;
168 typedef void (serialize_function_t) (serialize_main_t * m, va_list * va);
171 unserialize_get (serialize_main_t * m, uword n_bytes)
173 return serialize_stream_read_write (&m->header, &m->stream, n_bytes,
174 SERIALIZE_FLAG_IS_READ);
178 serialize_get (serialize_main_t * m, uword n_bytes)
180 return serialize_stream_read_write (&m->header, &m->stream, n_bytes,
181 SERIALIZE_FLAG_IS_WRITE);
185 serialize_integer (serialize_main_t * m, u64 x, u32 n_bytes)
187 u8 *p = serialize_get (m, n_bytes);
190 else if (n_bytes == 2)
191 clib_mem_unaligned (p, u16) = clib_host_to_net_u16 (x);
192 else if (n_bytes == 4)
193 clib_mem_unaligned (p, u32) = clib_host_to_net_u32 (x);
194 else if (n_bytes == 8)
195 clib_mem_unaligned (p, u64) = clib_host_to_net_u64 (x);
201 unserialize_integer (serialize_main_t * m, void *x, u32 n_bytes)
203 u8 *p = unserialize_get (m, n_bytes);
206 else if (n_bytes == 2)
207 *(u16 *) x = clib_net_to_host_unaligned_mem_u16 ((u16 *) p);
208 else if (n_bytes == 4)
209 *(u32 *) x = clib_net_to_host_unaligned_mem_u32 ((u32 *) p);
210 else if (n_bytes == 8)
211 *(u64 *) x = clib_net_to_host_unaligned_mem_u64 ((u64 *) p);
216 /* As above but tries to be more compact. */
218 serialize_likely_small_unsigned_integer (serialize_main_t * m, u64 x)
223 /* Low bit set means it fits into 1 byte. */
226 p = serialize_get (m, 1);
231 /* Low 2 bits 1 0 means it fits into 2 bytes. */
235 p = serialize_get (m, 2);
236 clib_mem_unaligned (p, u16) = clib_host_to_little_u16 (4 * r + 2);
243 p = serialize_get (m, 4);
244 clib_mem_unaligned (p, u32) = clib_host_to_little_u32 (8 * r + 4);
248 p = serialize_get (m, 9);
249 p[0] = 0; /* Only low 3 bits are used. */
250 clib_mem_unaligned (p + 1, u64) = clib_host_to_little_u64 (x);
254 unserialize_likely_small_unsigned_integer (serialize_main_t * m)
256 u8 *p = unserialize_get (m, 1);
266 p = unserialize_get (m, 1);
267 r += (y / 4) + (p[0] << 6);
274 p = unserialize_get (m, 3);
276 + (p[0] << (5 + 8 * 0))
277 + (p[1] << (5 + 8 * 1)) + (p[2] << (5 + 8 * 2)));
281 p = unserialize_get (m, 8);
282 r = clib_mem_unaligned (p, u64);
283 r = clib_little_to_host_u64 (r);
289 serialize_likely_small_signed_integer (serialize_main_t * m, i64 s)
291 u64 u = s < 0 ? -(2 * s + 1) : 2 * s;
292 serialize_likely_small_unsigned_integer (m, u);
296 unserialize_likely_small_signed_integer (serialize_main_t * m)
298 u64 u = unserialize_likely_small_unsigned_integer (m);
300 return (u & 1) ? -s : s;
304 serialize_multiple_1 (serialize_main_t * m,
305 void *data, uword data_stride, uword n_data);
307 serialize_multiple_2 (serialize_main_t * m,
308 void *data, uword data_stride, uword n_data);
310 serialize_multiple_4 (serialize_main_t * m,
311 void *data, uword data_stride, uword n_data);
314 unserialize_multiple_1 (serialize_main_t * m,
315 void *data, uword data_stride, uword n_data);
317 unserialize_multiple_2 (serialize_main_t * m,
318 void *data, uword data_stride, uword n_data);
320 unserialize_multiple_4 (serialize_main_t * m,
321 void *data, uword data_stride, uword n_data);
324 serialize_multiple (serialize_main_t * m,
326 uword n_data_bytes, uword data_stride, uword n_data)
328 if (n_data_bytes == 1)
329 serialize_multiple_1 (m, data, data_stride, n_data);
330 else if (n_data_bytes == 2)
331 serialize_multiple_2 (m, data, data_stride, n_data);
332 else if (n_data_bytes == 4)
333 serialize_multiple_4 (m, data, data_stride, n_data);
339 unserialize_multiple (serialize_main_t * m,
341 uword n_data_bytes, uword data_stride, uword n_data)
343 if (n_data_bytes == 1)
344 unserialize_multiple_1 (m, data, data_stride, n_data);
345 else if (n_data_bytes == 2)
346 unserialize_multiple_2 (m, data, data_stride, n_data);
347 else if (n_data_bytes == 4)
348 unserialize_multiple_4 (m, data, data_stride, n_data);
354 serialize_function_t serialize_64, unserialize_64;
355 serialize_function_t serialize_32, unserialize_32;
356 serialize_function_t serialize_16, unserialize_16;
357 serialize_function_t serialize_8, unserialize_8;
358 serialize_function_t serialize_f64, unserialize_f64;
359 serialize_function_t serialize_f32, unserialize_f32;
361 /* Basic vector types. */
362 serialize_function_t serialize_vec_8, unserialize_vec_8;
363 serialize_function_t serialize_vec_16, unserialize_vec_16;
364 serialize_function_t serialize_vec_32, unserialize_vec_32;
365 serialize_function_t serialize_vec_64, unserialize_vec_64;
367 /* Serialize generic vectors. */
368 serialize_function_t serialize_vector, unserialize_vector,
369 unserialize_aligned_vector;
371 #define vec_serialize(m,v,f) \
372 serialize ((m), serialize_vector, (v), sizeof ((v)[0]), (f))
374 #define vec_unserialize(m,v,f) \
375 unserialize ((m), unserialize_vector, (v), sizeof ((*(v))[0]), (f))
377 #define vec_unserialize_aligned(m,v,f) \
378 unserialize ((m), unserialize_aligned_vector, (v), sizeof ((*(v))[0]), (f))
380 /* Serialize pools. */
381 serialize_function_t serialize_pool, unserialize_pool,
382 unserialize_aligned_pool;
384 #define pool_serialize(m,v,f) \
385 serialize ((m), serialize_pool, (v), sizeof ((v)[0]), (f))
387 #define pool_unserialize(m,v,f) \
388 unserialize ((m), unserialize_pool, (v), sizeof ((*(v))[0]), (f))
390 #define pool_unserialize_aligned(m,v,a,f) \
391 unserialize ((m), unserialize_aligned_pool, (v), sizeof ((*(v))[0]), (a), (f))
393 /* Serialize heaps. */
394 serialize_function_t serialize_heap, unserialize_heap;
396 void serialize_bitmap (serialize_main_t * m, uword * b);
397 uword *unserialize_bitmap (serialize_main_t * m);
399 void serialize_cstring (serialize_main_t * m, char *string);
400 void unserialize_cstring (serialize_main_t * m, char **string);
402 void serialize_close (serialize_main_t * m);
403 void unserialize_close (serialize_main_t * m);
405 void serialize_open_data (serialize_main_t * m, u8 * data,
407 void unserialize_open_data (serialize_main_t * m, u8 * data,
410 /* Starts serialization with expanding vector as buffer. */
411 void serialize_open_vector (serialize_main_t * m, u8 * vector);
413 /* Serialization is done: returns vector buffer to caller. */
414 void *serialize_close_vector (serialize_main_t * m);
416 void unserialize_open_vector (serialize_main_t * m, u8 * vector);
419 clib_error_t *serialize_open_clib_file (serialize_main_t * m, char *file);
420 clib_error_t *unserialize_open_clib_file (serialize_main_t * m, char *file);
422 void serialize_open_clib_file_descriptor (serialize_main_t * m, int fd);
423 void unserialize_open_clib_file_descriptor (serialize_main_t * m, int fd);
424 #endif /* CLIB_UNIX */
427 clib_error_t *serialize (serialize_main_t * m, ...);
428 clib_error_t *unserialize (serialize_main_t * m, ...);
429 clib_error_t *va_serialize (serialize_main_t * m, va_list * va);
431 void serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes);
432 void unserialize_check_magic (serialize_main_t * m, void *magic,
435 #endif /* included_clib_serialize_h */
438 * fd.io coding-style-patch-verification: ON
441 * eval: (c-set-style "gnu")