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 {
54 /* Current data buffer being serialized/unserialized. */
57 /* Size of buffer in bytes. */
60 /* Current index into buffer. */
61 u32 current_buffer_index;
63 /* Overflow buffer for when there is not enough room at the end of
64 buffer to hold serialized/unserialized data. */
67 /* Current index in overflow buffer for reads. */
68 u32 current_overflow_index;
71 #define SERIALIZE_END_OF_STREAM (1 << 0)
73 uword data_function_opaque;
75 u32 opaque[64 - 4 * sizeof (u32) - 1 * sizeof (uword) - 2 * sizeof (void *)];
79 serialize_stream_set_end_of_stream (serialize_stream_t * s)
80 { s->flags |= SERIALIZE_END_OF_STREAM; }
83 serialize_stream_is_end_of_stream (serialize_stream_t * s)
84 { return (s->flags & SERIALIZE_END_OF_STREAM) != 0; }
86 typedef struct serialize_main_header_t {
89 /* Data callback function and opaque data. */
90 serialize_data_function_t * data_function;
92 /* Error if signaled by data function. */
95 /* Exit unwind point if error occurs. */
96 clib_longjmp_t error_longjmp;
97 } serialize_main_header_t;
100 serialize_error (serialize_main_header_t * m, clib_error_t * error)
101 { clib_longjmp (&m->error_longjmp, pointer_to_uword (error)); }
103 #define serialize_error_return(m,args...) \
104 serialize_error (&(m)->header, clib_error_return (0, args))
106 void * serialize_read_write_not_inline (serialize_main_header_t * m,
107 serialize_stream_t * s,
108 uword n_bytes, uword flags);
110 #define SERIALIZE_FLAG_IS_READ (1 << 0)
111 #define SERIALIZE_FLAG_IS_WRITE (1 << 1)
114 serialize_stream_read_write (serialize_main_header_t * header,
115 serialize_stream_t * s,
121 l = vec_len (s->overflow_buffer);
122 i = s->current_buffer_index;
124 s->current_buffer_index = j;
125 if (l == 0 && j <= s->n_buffer_bytes)
127 return s->buffer + i;
131 s->current_buffer_index = i;
132 return serialize_read_write_not_inline (header, s, n_bytes, flags);
137 serialize_main_header_t header;
138 serialize_stream_t stream;
142 serialize_set_end_of_stream (serialize_main_t * m)
143 { serialize_stream_set_end_of_stream (&m->stream); }
146 serialize_is_end_of_stream (serialize_main_t * m)
147 { return serialize_stream_is_end_of_stream (&m->stream); }
150 serialize_main_header_t header;
151 serialize_stream_t * streams;
152 } serialize_multiple_main_t;
154 typedef void (serialize_function_t) (serialize_main_t * m, va_list * va);
157 unserialize_get (serialize_main_t * m, uword n_bytes)
158 { return serialize_stream_read_write (&m->header, &m->stream, n_bytes, SERIALIZE_FLAG_IS_READ); }
161 serialize_get (serialize_main_t * m, uword n_bytes)
162 { return serialize_stream_read_write (&m->header, &m->stream, n_bytes, SERIALIZE_FLAG_IS_WRITE); }
165 serialize_integer (serialize_main_t * m, u64 x, u32 n_bytes)
167 u8 * p = serialize_get (m, n_bytes);
170 else if (n_bytes == 2)
171 clib_mem_unaligned (p, u16) = clib_host_to_net_u16 (x);
172 else if (n_bytes == 4)
173 clib_mem_unaligned (p, u32) = clib_host_to_net_u32 (x);
174 else if (n_bytes == 8)
175 clib_mem_unaligned (p, u64) = clib_host_to_net_u64 (x);
181 unserialize_integer (serialize_main_t * m, void * x, u32 n_bytes)
183 u8 * p = unserialize_get (m, n_bytes);
186 else if (n_bytes == 2)
187 *(u16 *) x = clib_net_to_host_unaligned_mem_u16 ((u16 *) p);
188 else if (n_bytes == 4)
189 *(u32 *) x = clib_net_to_host_unaligned_mem_u32 ((u32 *) p);
190 else if (n_bytes == 8)
191 *(u64 *) x = clib_net_to_host_unaligned_mem_u64 ((u64 *) p);
196 /* As above but tries to be more compact. */
198 serialize_likely_small_unsigned_integer (serialize_main_t * m, u64 x)
203 /* Low bit set means it fits into 1 byte. */
206 p = serialize_get (m, 1);
211 /* Low 2 bits 1 0 means it fits into 2 bytes. */
215 p = serialize_get (m, 2);
216 clib_mem_unaligned (p, u16) = clib_host_to_little_u16 (4 * r + 2);
223 p = serialize_get (m, 4);
224 clib_mem_unaligned (p, u32) = clib_host_to_little_u32 (8 * r + 4);
228 p = serialize_get (m, 9);
229 p[0] = 0; /* Only low 3 bits are used. */
230 clib_mem_unaligned (p + 1, u64) = clib_host_to_little_u64 (x);
234 unserialize_likely_small_unsigned_integer (serialize_main_t * m)
236 u8 * p = unserialize_get (m, 1);
246 p = unserialize_get (m, 1);
247 r += (y / 4) + (p[0] << 6);
254 p = unserialize_get (m, 3);
256 + (p[0] << (5 + 8*0))
257 + (p[1] << (5 + 8*1))
258 + (p[2] << (5 + 8*2)));
262 p = unserialize_get (m, 8);
263 r = clib_mem_unaligned (p, u64);
264 r = clib_little_to_host_u64 (r);
270 serialize_likely_small_signed_integer (serialize_main_t * m, i64 s)
272 u64 u = s < 0 ? -(2*s + 1) : 2*s;
273 serialize_likely_small_unsigned_integer (m, u);
277 unserialize_likely_small_signed_integer (serialize_main_t * m)
279 u64 u = unserialize_likely_small_unsigned_integer (m);
281 return (u & 1) ? -s : s;
285 serialize_multiple_1 (serialize_main_t * m,
290 serialize_multiple_2 (serialize_main_t * m,
295 serialize_multiple_4 (serialize_main_t * m,
301 unserialize_multiple_1 (serialize_main_t * m,
306 unserialize_multiple_2 (serialize_main_t * m,
311 unserialize_multiple_4 (serialize_main_t * m,
317 serialize_multiple (serialize_main_t * m,
323 if (n_data_bytes == 1)
324 serialize_multiple_1 (m, data, data_stride, n_data);
325 else if (n_data_bytes == 2)
326 serialize_multiple_2 (m, data, data_stride, n_data);
327 else if (n_data_bytes == 4)
328 serialize_multiple_4 (m, data, data_stride, n_data);
334 unserialize_multiple (serialize_main_t * m,
340 if (n_data_bytes == 1)
341 unserialize_multiple_1 (m, data, data_stride, n_data);
342 else if (n_data_bytes == 2)
343 unserialize_multiple_2 (m, data, data_stride, n_data);
344 else if (n_data_bytes == 4)
345 unserialize_multiple_4 (m, data, data_stride, n_data);
351 serialize_function_t serialize_64, unserialize_64;
352 serialize_function_t serialize_32, unserialize_32;
353 serialize_function_t serialize_16, unserialize_16;
354 serialize_function_t serialize_8, unserialize_8;
355 serialize_function_t serialize_f64, unserialize_f64;
356 serialize_function_t serialize_f32, unserialize_f32;
358 /* Basic vector types. */
359 serialize_function_t serialize_vec_8, unserialize_vec_8;
360 serialize_function_t serialize_vec_16, unserialize_vec_16;
361 serialize_function_t serialize_vec_32, unserialize_vec_32;
362 serialize_function_t serialize_vec_64, unserialize_vec_64;
364 /* Serialize generic vectors. */
365 serialize_function_t serialize_vector, unserialize_vector, unserialize_aligned_vector;
367 #define vec_serialize(m,v,f) \
368 serialize ((m), serialize_vector, (v), sizeof ((v)[0]), (f))
370 #define vec_unserialize(m,v,f) \
371 unserialize ((m), unserialize_vector, (v), sizeof ((*(v))[0]), (f))
373 #define vec_unserialize_aligned(m,v,f) \
374 unserialize ((m), unserialize_aligned_vector, (v), sizeof ((*(v))[0]), (f))
376 /* Serialize pools. */
377 serialize_function_t serialize_pool, unserialize_pool, unserialize_aligned_pool;
379 #define pool_serialize(m,v,f) \
380 serialize ((m), serialize_pool, (v), sizeof ((v)[0]), (f))
382 #define pool_unserialize(m,v,f) \
383 unserialize ((m), unserialize_pool, (v), sizeof ((*(v))[0]), (f))
385 #define pool_unserialize_aligned(m,v,a,f) \
386 unserialize ((m), unserialize_aligned_pool, (v), sizeof ((*(v))[0]), (a), (f))
388 /* Serialize heaps. */
389 serialize_function_t serialize_heap, unserialize_heap;
391 void serialize_bitmap (serialize_main_t * m, uword * b);
392 uword * unserialize_bitmap (serialize_main_t * m);
394 void serialize_cstring (serialize_main_t * m, char * string);
395 void unserialize_cstring (serialize_main_t * m, char ** string);
397 void serialize_close (serialize_main_t * m);
398 void unserialize_close (serialize_main_t * m);
400 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes);
401 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes);
403 /* Starts serialization with expanding vector as buffer. */
404 void serialize_open_vector (serialize_main_t * m, u8 * vector);
406 /* Serialization is done: returns vector buffer to caller. */
407 void * serialize_close_vector (serialize_main_t * m);
409 void unserialize_open_vector (serialize_main_t * m, u8 * vector);
412 clib_error_t * serialize_open_unix_file (serialize_main_t * m, char * file);
413 clib_error_t * unserialize_open_unix_file (serialize_main_t * m, char * file);
415 void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd);
416 void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd);
417 #endif /* CLIB_UNIX */
420 clib_error_t * serialize (serialize_main_t * m, ...);
421 clib_error_t * unserialize (serialize_main_t * m, ...);
422 clib_error_t * va_serialize (serialize_main_t * m, va_list * va);
424 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes);
425 void unserialize_check_magic (serialize_main_t * m, void * magic, u32 magic_bytes);
427 #endif /* included_clib_serialize_h */