9c6987dd0e9fe949ae8dcf844085e67780bbb634
[vpp.git] / vppinfra / vppinfra / serialize.c
1 /*
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 /*
16   Copyright (c) 2005 Eliot Dresselhaus
17
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:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
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.
36 */
37
38 /* Turn data structures into byte streams for saving or transport. */
39
40 #include <vppinfra/heap.h>
41 #include <vppinfra/pool.h>
42 #include <vppinfra/serialize.h>
43
44 void serialize_64 (serialize_main_t * m, va_list * va)
45 {
46   u64 x = va_arg (*va, u64);
47   u32 lo, hi;
48   lo = x;
49   hi = x >> 32;
50   serialize_integer (m, lo, sizeof (lo));
51   serialize_integer (m, hi, sizeof (hi));
52 }
53
54 void serialize_32 (serialize_main_t * m, va_list * va)
55 {
56   u32 x = va_arg (*va, u32);
57   serialize_integer (m, x, sizeof (x));
58 }
59
60 void serialize_16 (serialize_main_t * m, va_list * va)
61 {
62   u32 x = va_arg (*va, u32);
63   serialize_integer (m, x, sizeof (u16));
64 }
65
66 void serialize_8 (serialize_main_t * m, va_list * va)
67 {
68   u32 x = va_arg (*va, u32);
69   serialize_integer (m, x, sizeof (u8));
70 }
71
72 void unserialize_64 (serialize_main_t * m, va_list * va)
73 {
74   u64 * x = va_arg (*va, u64 *);
75   u32 lo, hi;
76   unserialize_integer (m, &lo, sizeof (lo));
77   unserialize_integer (m, &hi, sizeof (hi));
78   *x = ((u64) hi << 32) | (u64) lo;
79 }
80
81 void unserialize_32 (serialize_main_t * m, va_list * va)
82 {
83   u32 * x = va_arg (*va, u32 *);
84   unserialize_integer (m, x, sizeof (x[0]));
85 }
86
87 void unserialize_16 (serialize_main_t * m, va_list * va)
88 {
89   u16 * x = va_arg (*va, u16 *);
90   u32 t;
91   unserialize_integer (m, &t, sizeof (x[0]));
92   x[0] = t;
93 }
94
95 void unserialize_8 (serialize_main_t * m, va_list * va)
96 {
97   u8 * x = va_arg (*va, u8 *);
98   u32 t;
99   unserialize_integer (m, &t, sizeof (x[0]));
100   x[0] = t;
101 }
102
103 void serialize_f64 (serialize_main_t * m, va_list * va)
104 {
105   f64 x = va_arg (*va, f64);
106   union { f64 f; u64 i; } y;
107   y.f = x;
108   serialize (m, serialize_64, y.i);
109 }
110
111 void serialize_f32 (serialize_main_t * m, va_list * va)
112 {
113   f32 x = va_arg (*va, f64);
114   union { f32 f; u32 i; } y;
115   y.f = x;
116   serialize_integer (m, y.i, sizeof (y.i));
117 }
118
119 void unserialize_f64 (serialize_main_t * m, va_list * va)
120 {
121   f64 * x = va_arg (*va, f64 *);
122   union { f64 f; u64 i; } y;
123   unserialize (m, unserialize_64, &y.i);
124   *x = y.f;
125 }
126
127 void unserialize_f32 (serialize_main_t * m, va_list * va)
128 {
129   f32 * x = va_arg (*va, f32 *);
130   union { f32 f; u32 i; } y;
131   unserialize_integer (m, &y.i, sizeof (y.i));
132   *x = y.f;
133 }
134
135 void serialize_cstring (serialize_main_t * m, char * s)
136 {
137   u32 len = s ? strlen (s) : 0;
138   void * p;
139
140   serialize_likely_small_unsigned_integer (m, len);
141   if (len > 0) 
142     {
143       p = serialize_get (m, len);
144       clib_memcpy (p, s, len);
145     }
146 }
147
148 void unserialize_cstring (serialize_main_t * m, char ** s)
149 {
150   char * p, * r = 0;
151   u32 len;
152
153   len = unserialize_likely_small_unsigned_integer (m);
154
155   /*
156    * Given broken enough data, we could get len = 0xFFFFFFFF.
157    * Add one, it overflows, we call vec_new (char, 0), then
158    * memcpy until we bus error.
159    */
160   if (len > 0 && len != 0xFFFFFFFF)
161     {
162       r = vec_new (char, len + 1);
163       p = unserialize_get (m, len);
164       clib_memcpy (r, p, len);
165       
166       /* Null terminate. */
167       r[len] = 0;
168     }
169   *s = r;
170 }
171
172 /* vec_serialize/vec_unserialize helper functions for basic vector types. */
173 void serialize_vec_8 (serialize_main_t * m, va_list * va)
174 {
175   u8 * s = va_arg (*va, u8 *);
176   u32 n = va_arg (*va, u32);
177   u8 * p = serialize_get (m, n * sizeof (u8));
178   clib_memcpy (p, s, n * sizeof (u8));
179 }
180
181 void unserialize_vec_8 (serialize_main_t * m, va_list * va)
182 {
183   u8 * s = va_arg (*va, u8 *);
184   u32 n = va_arg (*va, u32);
185   u8 * p = unserialize_get (m, n);
186   clib_memcpy (s, p, n);
187 }
188
189 #define _(n_bits)                                                       \
190   void serialize_vec_##n_bits (serialize_main_t * m, va_list * va)      \
191   {                                                                     \
192     u##n_bits * s = va_arg (*va, u##n_bits *);                          \
193     u32 n = va_arg (*va, u32);                                          \
194     u##n_bits * p = serialize_get (m, n * sizeof (s[0]));               \
195                                                                         \
196     while (n >= 4)                                                      \
197       {                                                                 \
198         p[0] = clib_host_to_net_u##n_bits (s[0]);                       \
199         p[1] = clib_host_to_net_u##n_bits (s[1]);                       \
200         p[2] = clib_host_to_net_u##n_bits (s[2]);                       \
201         p[3] = clib_host_to_net_u##n_bits (s[3]);                       \
202         s += 4;                                                         \
203         p += 4;                                                         \
204         n -= 4;                                                         \
205       }                                                                 \
206                                                                         \
207     while (n >= 1)                                                      \
208       {                                                                 \
209         p[0] = clib_host_to_net_u##n_bits (s[0]);                       \
210         s += 1;                                                         \
211         p += 1;                                                         \
212         n -= 1;                                                         \
213       }                                                                 \
214   }                                                                     \
215                                                                         \
216   void unserialize_vec_##n_bits (serialize_main_t * m, va_list * va)    \
217   {                                                                     \
218     u##n_bits * s = va_arg (*va, u##n_bits *);                          \
219     u32 n = va_arg (*va, u32);                                          \
220     u##n_bits * p = unserialize_get (m, n * sizeof (s[0]));             \
221                                                                         \
222     while (n >= 4)                                                      \
223       {                                                                 \
224         s[0] = clib_net_to_host_mem_u##n_bits (&p[0]);                  \
225         s[1] = clib_net_to_host_mem_u##n_bits (&p[1]);                  \
226         s[2] = clib_net_to_host_mem_u##n_bits (&p[2]);                  \
227         s[3] = clib_net_to_host_mem_u##n_bits (&p[3]);                  \
228         s += 4;                                                         \
229         p += 4;                                                         \
230         n -= 4;                                                         \
231       }                                                                 \
232                                                                         \
233     while (n >= 1)                                                      \
234       {                                                                 \
235         s[0] = clib_net_to_host_mem_u##n_bits (&p[0]);                  \
236         s += 1;                                                         \
237         p += 1;                                                         \
238         n -= 1;                                                         \
239       }                                                                 \
240   }
241
242 _ (16);
243 _ (32);
244 _ (64);
245
246 #undef _
247
248 #define SERIALIZE_VECTOR_CHUNK_SIZE 64
249
250 void serialize_vector (serialize_main_t * m, va_list * va)
251 {
252   void * vec = va_arg (*va, void *);
253   u32 elt_bytes = va_arg (*va, u32);
254   serialize_function_t * f = va_arg (*va, serialize_function_t *);
255   u32 l = vec_len (vec);
256   void * p = vec;
257
258   serialize_integer (m, l, sizeof (l));
259
260   /* Serialize vector in chunks for cache locality. */
261   while (l != 0)
262     {
263       u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
264       serialize (m, f, p, n);
265       l -= n;
266       p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
267     }
268 }
269
270 void *
271 unserialize_vector_ha (serialize_main_t * m, 
272                        u32 elt_bytes,
273                        u32 header_bytes,
274                        u32 align,
275                        u32 max_length,
276                        serialize_function_t * f)
277 {
278   void * v, * p;
279   u32 l;
280
281   unserialize_integer (m, &l, sizeof (l));
282   if (l > max_length)
283     serialize_error (&m->header, clib_error_create ("bad vector length %d", l));
284   p = v = _vec_resize (0, l, (uword) l*elt_bytes, header_bytes, 
285                        /* align */ align);
286
287   while (l != 0)
288     {
289       u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
290       unserialize (m, f, p, n);
291       l -= n;
292       p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
293     }
294   return v;
295 }
296
297 void unserialize_aligned_vector (serialize_main_t * m, va_list * va)
298 {
299   void ** vec = va_arg (*va, void **);
300   u32 elt_bytes = va_arg (*va, u32);
301   serialize_function_t * f = va_arg (*va, serialize_function_t *);
302   u32 align = va_arg (*va, u32);
303
304   *vec = unserialize_vector_ha (m, elt_bytes,
305                                 /* header_bytes */ 0,
306                                 /* align */ align,
307                                 /* max_length */ ~0,
308                                 f);
309 }
310
311 void unserialize_vector (serialize_main_t * m, va_list * va)
312 {
313   void ** vec = va_arg (*va, void **);
314   u32 elt_bytes = va_arg (*va, u32);
315   serialize_function_t * f = va_arg (*va, serialize_function_t *);
316
317   *vec = unserialize_vector_ha (m, elt_bytes,
318                                 /* header_bytes */ 0,
319                                 /* align */ 0,
320                                 /* max_length */ ~0,
321                                 f);
322 }
323
324 void serialize_bitmap (serialize_main_t * m, uword * b)
325 {
326   u32 l, i, n_u32s;
327
328   l = vec_len (b);
329   n_u32s = l * sizeof (b[0]) / sizeof (u32);
330   serialize_integer (m, n_u32s, sizeof (n_u32s));
331
332   /* Send 32 bit words, low-order word first on 64 bit. */
333   for (i = 0; i < l; i++)
334     {
335       serialize_integer (m, b[i], sizeof (u32));
336       if (BITS (uword) == 64)
337         serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
338     }
339 }
340
341 uword * unserialize_bitmap (serialize_main_t * m)
342 {
343   uword * b = 0;
344   u32 i, n_u32s;
345
346   unserialize_integer (m, &n_u32s, sizeof (n_u32s));
347   if (n_u32s == 0)
348     return b;
349
350   i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
351   vec_resize (b, i);
352   for (i = 0; i < n_u32s; i++)
353     {
354       u32 data;
355       unserialize_integer (m, &data, sizeof (u32));
356
357       /* Low-word is first on 64 bit. */
358       if (BITS (uword) == 64)
359         {
360           if ((i % 2) == 0)
361             b[i/2] |= (u64) data << (u64) 0;
362           else
363             b[i/2] |= (u64) data << (u64) 32;
364         }
365       else
366         {
367           b[i] = data;
368         }
369     }
370
371   return b;
372 }
373
374 void serialize_pool (serialize_main_t * m, va_list * va)
375 {
376   void * pool = va_arg (*va, void *);
377   u32 elt_bytes = va_arg (*va, u32);
378   serialize_function_t * f = va_arg (*va, serialize_function_t *);
379   u32 l, lo, hi;
380   pool_header_t * p;
381
382   l = vec_len (pool);
383   serialize_integer (m, l, sizeof (u32));
384   if (l == 0)
385     return;
386   p = pool_header (pool);
387
388   /* No need to send free bitmap.  Need to send index vector
389      to guarantee that unserialized pool will be identical. */
390   vec_serialize (m, p->free_indices, serialize_vec_32);
391
392   pool_foreach_region (lo, hi, pool,
393                        serialize (m, f, pool + lo*elt_bytes, hi - lo));
394 }
395
396 static void *
397 unserialize_pool_helper (serialize_main_t * m,
398                          u32 elt_bytes, u32 align,
399                          serialize_function_t * f)
400 {
401   void * v;
402   u32 i, l, lo, hi;
403   pool_header_t * p;
404
405   unserialize_integer (m, &l, sizeof (l));
406   if (l == 0)
407     {
408       return 0;
409     }
410
411   v = _vec_resize (0, l, (uword) l*elt_bytes, sizeof (p[0]), align);
412   p = pool_header (v);
413
414   vec_unserialize (m, &p->free_indices, unserialize_vec_32);
415
416   /* Construct free bitmap. */
417   p->free_bitmap = 0;
418   for (i = 0; i < vec_len (p->free_indices); i++)
419     p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
420
421   pool_foreach_region (lo, hi, v,
422                        unserialize (m, f, v + lo*elt_bytes, hi - lo));
423
424   return v;
425 }
426
427 void unserialize_pool (serialize_main_t * m, va_list * va)
428 {
429   void ** result = va_arg (*va, void **);
430   u32 elt_bytes = va_arg (*va, u32);
431   serialize_function_t * f = va_arg (*va, serialize_function_t *);
432   *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
433 }
434
435 void unserialize_aligned_pool (serialize_main_t * m, va_list * va)
436 {
437   void ** result = va_arg (*va, void **);
438   u32 elt_bytes = va_arg (*va, u32);
439   u32 align = va_arg (*va, u32);
440   serialize_function_t * f = va_arg (*va, serialize_function_t *);
441   *result = unserialize_pool_helper (m, elt_bytes, align, f);
442 }
443
444 static void serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
445 {
446   heap_elt_t * e = va_arg (*va, heap_elt_t *);
447   u32 i, n = va_arg (*va, u32);
448   for (i = 0; i < n; i++)
449     {
450       serialize_integer (m, e[i].offset, sizeof (e[i].offset));
451       serialize_integer (m, e[i].next, sizeof (e[i].next));
452       serialize_integer (m, e[i].prev, sizeof (e[i].prev));
453     }
454 }
455
456 static void unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
457 {
458   heap_elt_t * e = va_arg (*va, heap_elt_t *);
459   u32 i, n = va_arg (*va, u32);
460   for (i = 0; i < n; i++)
461     {
462       unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
463       unserialize_integer (m, &e[i].next, sizeof (e[i].next));
464       unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
465     }
466 }
467
468 void serialize_heap (serialize_main_t * m, va_list * va)
469 {
470   void * heap = va_arg (*va, void *);
471   serialize_function_t * f = va_arg (*va, serialize_function_t *);
472   u32 i, l;
473   heap_header_t * h;
474
475   l = vec_len (heap);
476   serialize_integer (m, l, sizeof (u32));
477   if (l == 0)
478     return;
479
480   h = heap_header (heap);
481
482 #define foreach_serialize_heap_header_integer \
483   _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
484
485 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
486   foreach_serialize_heap_header_integer;
487 #undef _
488
489   serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
490   for (i = 0; i < vec_len (h->free_lists); i++)
491     vec_serialize (m, h->free_lists[i], serialize_vec_32);
492
493   vec_serialize (m, h->elts, serialize_vec_heap_elt);
494   vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
495   vec_serialize (m, h->free_elts, serialize_vec_32);
496
497   /* Serialize data in heap. */
498   {
499     heap_elt_t * e, * end;
500     e = h->elts + h->head;
501     end = h->elts + h->tail;
502     while (1)
503       {
504         if (! heap_is_free (e))
505           {
506             void * v = heap + heap_offset (e) * h->elt_bytes;
507             u32 n = heap_elt_size (heap, e);
508             serialize (m, f, v, n);
509           }
510         if (e == end)
511           break;
512         e = heap_next (e);
513       }
514   }
515 }
516
517 void unserialize_heap (serialize_main_t * m, va_list * va)
518 {
519   void ** result = va_arg (*va, void **);
520   serialize_function_t * f = va_arg (*va, serialize_function_t *);
521   u32 i, vl, fl;
522   heap_header_t h;
523   void * heap;
524
525   unserialize_integer (m, &vl, sizeof (u32));
526   if (vl == 0)
527     {
528       *result = 0;
529       return;
530     }
531
532   memset (&h, 0, sizeof (h));
533 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
534   foreach_serialize_heap_header_integer;
535 #undef _
536
537   unserialize_integer (m, &fl, sizeof (u32));
538   vec_resize (h.free_lists, fl);
539
540   for (i = 0; i < vec_len (h.free_lists); i++)
541     vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
542
543   vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
544   vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
545   vec_unserialize (m, &h.free_elts, unserialize_vec_32);
546
547   /* Re-construct used elt bitmap. */
548   if (CLIB_DEBUG > 0)
549     {
550       heap_elt_t * e;
551       vec_foreach (e, h.elts)
552         {
553           if (! heap_is_free (e))
554             h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
555         }
556     }
557
558   heap = *result = _heap_new (vl, h.elt_bytes);
559   heap_header (heap)[0] = h;
560
561   /* Unserialize data in heap. */
562   {
563     heap_elt_t * e, * end;
564     e = h.elts + h.head;
565     end = h.elts + h.tail;
566     while (1)
567       {
568         if (! heap_is_free (e))
569           {
570             void * v = heap + heap_offset (e) * h.elt_bytes;
571             u32 n = heap_elt_size (heap, e);
572             unserialize (m, f, v, n);
573           }
574         if (e == end)
575           break;
576         e = heap_next (e);
577       }
578   }
579 }
580
581 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes)
582 {
583   void * p;
584   serialize_integer (m, magic_bytes, sizeof (magic_bytes));
585   p = serialize_get (m, magic_bytes);
586   clib_memcpy (p, magic, magic_bytes);
587 }
588
589 void unserialize_check_magic (serialize_main_t * m, void * magic,
590                               u32 magic_bytes)
591 {
592   u32 l;
593   void * d;
594
595   unserialize_integer (m, &l, sizeof (l));
596   if (l != magic_bytes)
597     {
598     bad:
599       serialize_error_return (m, "bad magic number");
600     }
601   d = serialize_get (m, magic_bytes);
602   if (memcmp (magic, d, magic_bytes))
603     goto bad;
604 }
605
606 clib_error_t *
607 va_serialize (serialize_main_t * sm, va_list * va)
608 {
609   serialize_main_header_t * m = &sm->header;
610   serialize_function_t * f = va_arg (*va, serialize_function_t *);
611   clib_error_t * error = 0;
612
613   m->recursion_level += 1;
614   if (m->recursion_level == 1)
615     {
616       uword r = clib_setjmp (&m->error_longjmp, 0);
617       error = uword_to_pointer (r, clib_error_t *);
618     }
619         
620   if (! error)
621     f (sm, va);
622
623   m->recursion_level -= 1;
624   return error;
625 }
626
627 clib_error_t *
628 serialize (serialize_main_t * m, ...)
629 {
630   clib_error_t * error;
631   va_list va;
632
633   va_start (va, m);
634   error = va_serialize (m, &va);
635   va_end (va);
636   return error;
637 }
638
639 clib_error_t *
640 unserialize (serialize_main_t * m, ...)
641 {
642   clib_error_t * error;
643   va_list va;
644
645   va_start (va, m);
646   error = va_serialize (m, &va);
647   va_end (va);
648   return error;
649 }
650
651 static void * serialize_write_not_inline (serialize_main_header_t * m,
652                                           serialize_stream_t * s,
653                                           uword n_bytes_to_write,
654                                           uword flags)
655 {
656   uword cur_bi, n_left_b, n_left_o;
657
658   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
659   cur_bi = s->current_buffer_index;
660   n_left_b = s->n_buffer_bytes - cur_bi;
661   n_left_o = vec_len (s->overflow_buffer);
662
663   /* Prepend overflow buffer if present. */
664   do {
665     if (n_left_o > 0 && n_left_b > 0)
666       {
667         uword n = clib_min (n_left_b, n_left_o);
668         clib_memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
669         cur_bi += n;
670         n_left_b -= n;
671         n_left_o -= n;
672         if (n_left_o == 0)
673           _vec_len (s->overflow_buffer) = 0;
674         else
675           vec_delete (s->overflow_buffer, n, 0);
676       }
677
678     /* Call data function when buffer is complete.  Data function should
679        dispatch with current buffer and give us a new one to write more
680        data into. */
681     if (n_left_b == 0)
682       {
683         s->current_buffer_index = cur_bi;
684         m->data_function (m, s);
685         cur_bi = s->current_buffer_index;
686         n_left_b = s->n_buffer_bytes - cur_bi;
687       }
688   } while (n_left_o > 0);
689
690   if (n_left_o > 0 || n_left_b < n_bytes_to_write)
691     {
692       u8 * r;
693       vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
694       return r;
695     }
696   else
697     {
698       s->current_buffer_index = cur_bi + n_bytes_to_write;
699       return s->buffer + cur_bi;
700     }
701 }
702
703 static void * serialize_read_not_inline (serialize_main_header_t * m,
704                                          serialize_stream_t * s,
705                                          uword n_bytes_to_read,
706                                          uword flags)
707 {
708   uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
709
710   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
711
712   cur_bi = s->current_buffer_index;
713   cur_oi = s->current_overflow_index;
714
715   n_left_b = s->n_buffer_bytes - cur_bi;
716   n_left_o = vec_len (s->overflow_buffer) - cur_oi;
717
718   /* Read from overflow? */
719   if (n_left_o >= n_bytes_to_read)
720     {
721       s->current_overflow_index = cur_oi + n_bytes_to_read;
722       return vec_elt_at_index (s->overflow_buffer, cur_oi);
723     }
724
725   /* Reset overflow buffer. */
726   if (n_left_o == 0 && s->overflow_buffer)
727     {
728       s->current_overflow_index = 0;
729       _vec_len (s->overflow_buffer) = 0;
730     }
731
732   n_left_to_read = n_bytes_to_read;
733   while (n_left_to_read > 0)
734     {
735       uword n;
736
737       /* If we don't have enough data between overflow and normal buffer
738          call read function. */
739       if (n_left_o + n_left_b < n_bytes_to_read)
740         {
741           /* Save any left over buffer in overflow vector. */
742           if (n_left_b > 0)
743             {
744               vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
745               n_left_o += n_left_b;
746               n_left_to_read -= n_left_b;
747               /* Advance buffer to end --- even if
748                  SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
749               cur_bi = s->n_buffer_bytes;
750               n_left_b = 0;
751             }
752
753           if (m->data_function)
754             {
755               m->data_function (m, s);
756               cur_bi = s->current_buffer_index;
757               n_left_b = s->n_buffer_bytes - cur_bi;
758             }
759         }
760
761       /* For first time through loop return if we have enough data
762          in normal buffer and overflow vector is empty. */
763       if (n_left_o == 0
764           && n_left_to_read == n_bytes_to_read
765           && n_left_b >= n_left_to_read)
766         {
767           s->current_buffer_index = cur_bi + n_bytes_to_read;
768           return s->buffer + cur_bi;
769         }
770
771       if (! m->data_function
772           || serialize_stream_is_end_of_stream (s))
773         {
774           /* This can happen for a peek at end of file.
775              Pad overflow buffer with 0s. */
776           vec_resize (s->overflow_buffer, n_left_to_read);
777           n_left_o += n_left_to_read;
778           n_left_to_read = 0;
779         }
780       else
781         {
782           /* Copy from buffer to overflow vector. */
783           n = clib_min (n_left_to_read, n_left_b);
784           vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
785           cur_bi += n;
786           n_left_b -= n;
787           n_left_o += n;
788           n_left_to_read -= n;
789         }
790     }
791       
792   s->current_buffer_index = cur_bi;
793   s->current_overflow_index = cur_oi + n_bytes_to_read;
794   return vec_elt_at_index (s->overflow_buffer, cur_oi);
795 }
796
797 void * serialize_read_write_not_inline (serialize_main_header_t * m,
798                                         serialize_stream_t * s,
799                                         uword n_bytes,
800                                         uword flags)
801 {
802   return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline : serialize_write_not_inline)
803           (m, s, n_bytes, flags));
804 }
805
806 static void serialize_read_write_close (serialize_main_header_t * m, serialize_stream_t * s, uword flags)
807 {
808   if (serialize_stream_is_end_of_stream (s))
809     return;
810
811   if (flags & SERIALIZE_FLAG_IS_WRITE)
812     /* "Write" 0 bytes to flush overflow vector. */
813     serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
814
815   serialize_stream_set_end_of_stream (s);
816
817   /* Call it one last time to flush buffer and close. */
818   m->data_function (m, s);
819
820   vec_free (s->overflow_buffer);
821 }
822
823 void serialize_close (serialize_main_t * m)
824 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_WRITE); }
825
826 void unserialize_close (serialize_main_t * m)
827 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ); }
828
829 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
830 {
831   memset (m, 0, sizeof (m[0]));
832   m->stream.buffer = data;
833   m->stream.n_buffer_bytes = n_data_bytes;
834 }
835
836 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
837 { serialize_open_data (m, data, n_data_bytes); }
838
839 static void serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
840 {
841   if (! serialize_stream_is_end_of_stream (s))
842     {
843       /* Double buffer size. */
844       uword l = vec_len (s->buffer);
845       vec_resize (s->buffer, l > 0 ? l : 64);
846       s->n_buffer_bytes = vec_len (s->buffer);
847     }
848 }
849
850 void serialize_open_vector (serialize_main_t * m, u8 * vector)
851 {
852   memset (m, 0, sizeof (m[0]));
853   m->header.data_function = serialize_vector_write;
854   m->stream.buffer = vector;
855   m->stream.current_buffer_index = 0;
856   m->stream.n_buffer_bytes = vec_len (vector);
857 }
858  
859 void * serialize_close_vector (serialize_main_t * m)
860 {
861   serialize_stream_t * s = &m->stream;
862   void * result;
863
864   serialize_close (m);          /* frees overflow buffer */
865
866   if (s->buffer)
867     _vec_len (s->buffer) = s->current_buffer_index;
868   result = s->buffer;
869   memset (m, 0, sizeof (m[0]));
870   return result;
871 }
872  
873 void
874 serialize_multiple_1 (serialize_main_t * m,
875                       void * data,
876                       uword data_stride,
877                       uword n_data)
878 {
879   u8 * d = data;
880   u8 * p;
881   uword n_left = n_data;
882
883   while (n_left >= 4)
884     {
885       p = serialize_get (m, 4 * sizeof (d[0]));
886       p[0] = d[0 * data_stride];
887       p[1] = d[1 * data_stride];
888       p[2] = d[2 * data_stride];
889       p[3] = d[3 * data_stride];
890       n_left -= 4;
891       d += 4 * data_stride;
892     }
893
894   if (n_left > 0)
895     {
896       p = serialize_get (m, n_left * sizeof (p[0]));
897       while (n_left > 0)
898         {
899           p[0] = d[0];
900           p += 1;
901           d += 1 * data_stride;
902           n_left -= 1;
903         }
904     }
905 }
906
907 void
908 serialize_multiple_2 (serialize_main_t * m,
909                       void * data,
910                       uword data_stride,
911                       uword n_data)
912 {
913   void * d = data;
914   u16 * p;
915   uword n_left = n_data;
916
917   while (n_left >= 4)
918     {
919       p = serialize_get (m, 4 * sizeof (p[0]));
920       clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
921       clib_mem_unaligned (p + 1, u16) = clib_host_to_net_mem_u16 (d + 1 * data_stride);
922       clib_mem_unaligned (p + 2, u16) = clib_host_to_net_mem_u16 (d + 2 * data_stride);
923       clib_mem_unaligned (p + 3, u16) = clib_host_to_net_mem_u16 (d + 3 * data_stride);
924       n_left -= 4;
925       d += 4 * data_stride;
926     }
927
928   if (n_left > 0)
929     {
930       p = serialize_get (m, n_left * sizeof (p[0]));
931       while (n_left > 0)
932         {
933           clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
934           p += 1;
935           d += 1 * data_stride;
936           n_left -= 1;
937         }
938     }
939 }
940
941 void
942 serialize_multiple_4 (serialize_main_t * m,
943                       void * data,
944                       uword data_stride,
945                       uword n_data)
946 {
947   void * d = data;
948   u32 * p;
949   uword n_left = n_data;
950
951   while (n_left >= 4)
952     {
953       p = serialize_get (m, 4 * sizeof (p[0]));
954       clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
955       clib_mem_unaligned (p + 1, u32) = clib_host_to_net_mem_u32 (d + 1 * data_stride);
956       clib_mem_unaligned (p + 2, u32) = clib_host_to_net_mem_u32 (d + 2 * data_stride);
957       clib_mem_unaligned (p + 3, u32) = clib_host_to_net_mem_u32 (d + 3 * data_stride);
958       n_left -= 4;
959       d += 4 * data_stride;
960     }
961
962   if (n_left > 0)
963     {
964       p = serialize_get (m, n_left * sizeof (p[0]));
965       while (n_left > 0)
966         {
967           clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
968           p += 1;
969           d += 1 * data_stride;
970           n_left -= 1;
971         }
972     }
973 }
974
975 void
976 unserialize_multiple_1 (serialize_main_t * m,
977                         void * data,
978                         uword data_stride,
979                         uword n_data)
980 {
981   u8 * d = data;
982   u8 * p;
983   uword n_left = n_data;
984
985   while (n_left >= 4)
986     {
987       p = unserialize_get (m, 4 * sizeof (d[0]));
988       d[0 * data_stride] = p[0];
989       d[1 * data_stride] = p[1];
990       d[2 * data_stride] = p[2];
991       d[3 * data_stride] = p[3];
992       n_left -= 4;
993       d += 4 * data_stride;
994     }
995
996   if (n_left > 0)
997     {
998       p = unserialize_get (m, n_left * sizeof (p[0]));
999       while (n_left > 0)
1000         {
1001           d[0] = p[0];
1002           p += 1;
1003           d += 1 * data_stride;
1004           n_left -= 1;
1005         }
1006     }
1007 }
1008
1009 void
1010 unserialize_multiple_2 (serialize_main_t * m,
1011                         void * data,
1012                         uword data_stride,
1013                         uword n_data)
1014 {
1015   void * d = data;
1016   u16 * p;
1017   uword n_left = n_data;
1018
1019   while (n_left >= 4)
1020     {
1021       p = unserialize_get (m, 4 * sizeof (p[0]));
1022       clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1023       clib_mem_unaligned (d + 1 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 1);
1024       clib_mem_unaligned (d + 2 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 2);
1025       clib_mem_unaligned (d + 3 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 3);
1026       n_left -= 4;
1027       d += 4 * data_stride;
1028     }
1029
1030   if (n_left > 0)
1031     {
1032       p = unserialize_get (m, n_left * sizeof (p[0]));
1033       while (n_left > 0)
1034         {
1035           clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1036           p += 1;
1037           d += 1 * data_stride;
1038           n_left -= 1;
1039         }
1040     }
1041 }
1042
1043 void
1044 unserialize_multiple_4 (serialize_main_t * m,
1045                         void * data,
1046                         uword data_stride,
1047                         uword n_data)
1048 {
1049   void * d = data;
1050   u32 * p;
1051   uword n_left = n_data;
1052
1053   while (n_left >= 4)
1054     {
1055       p = unserialize_get (m, 4 * sizeof (p[0]));
1056       clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1057       clib_mem_unaligned (d + 1 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 1);
1058       clib_mem_unaligned (d + 2 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 2);
1059       clib_mem_unaligned (d + 3 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 3);
1060       n_left -= 4;
1061       d += 4 * data_stride;
1062     }
1063
1064   if (n_left > 0)
1065     {
1066       p = unserialize_get (m, n_left * sizeof (p[0]));
1067       while (n_left > 0)
1068         {
1069           clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1070           p += 1;
1071           d += 1 * data_stride;
1072           n_left -= 1;
1073         }
1074     }
1075 }
1076
1077 #ifdef CLIB_UNIX
1078
1079 #include <unistd.h>
1080 #include <fcntl.h>
1081
1082 static void unix_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1083 {
1084   int fd, n;
1085
1086   fd = s->data_function_opaque;
1087   n = write (fd, s->buffer, s->current_buffer_index);
1088   if (n < 0)
1089     {
1090       if (! unix_error_is_fatal (errno))
1091         n = 0;
1092       else
1093         serialize_error (m, clib_error_return_unix (0, "write"));
1094     }
1095   if (n == s->current_buffer_index)
1096     _vec_len (s->buffer) = 0;
1097   else
1098     vec_delete (s->buffer, n, 0);
1099   s->current_buffer_index = vec_len (s->buffer);
1100 }
1101
1102 static void unix_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1103 {
1104   int fd, n;
1105
1106   fd = s->data_function_opaque;
1107   n = read (fd, s->buffer, vec_len (s->buffer));
1108   if (n < 0)
1109     {
1110       if (! unix_error_is_fatal (errno))
1111         n = 0;
1112       else
1113         serialize_error (m, clib_error_return_unix (0, "read"));
1114     }
1115   else if (n == 0)
1116     serialize_stream_set_end_of_stream (s);
1117   s->current_buffer_index = 0;
1118   s->n_buffer_bytes = n;
1119 }
1120
1121 static void
1122 serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd, uword is_read)
1123 {
1124   memset (m, 0, sizeof (m[0]));
1125   vec_resize (m->stream.buffer, 4096);
1126   
1127   if (! is_read)
1128     {
1129       m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1130       _vec_len (m->stream.buffer) = 0;
1131     }
1132
1133   m->header.data_function = is_read ? unix_file_read : unix_file_write;
1134   m->stream.data_function_opaque = fd;
1135 }
1136
1137 void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1138 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); }
1139
1140 void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1141 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); }
1142
1143 static clib_error_t *
1144 serialize_open_unix_file_helper (serialize_main_t * m, char * file, uword is_read)
1145 {
1146   int fd, mode;
1147
1148   mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1149   fd = open (file, mode, 0666);
1150   if (fd < 0)
1151     return clib_error_return_unix (0, "open `%s'", file);
1152
1153   serialize_open_unix_file_descriptor_helper (m, fd, is_read);
1154   return 0;
1155 }
1156
1157 clib_error_t *
1158 serialize_open_unix_file (serialize_main_t * m, char * file)
1159 { return serialize_open_unix_file_helper (m, file, /* is_read */ 0); }
1160
1161 clib_error_t *
1162 unserialize_open_unix_file (serialize_main_t * m, char * file)
1163 { return serialize_open_unix_file_helper (m, file, /* is_read */ 1); }
1164
1165 #endif /* CLIB_UNIX */