Initial commit of vpp code.
[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       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       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   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   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, l*elt_bytes, header_bytes, /* align */ align);
285
286   while (l != 0)
287     {
288       u32 n = clib_min (SERIALIZE_VECTOR_CHUNK_SIZE, l);
289       unserialize (m, f, p, n);
290       l -= n;
291       p += SERIALIZE_VECTOR_CHUNK_SIZE * elt_bytes;
292     }
293   return v;
294 }
295
296 void unserialize_aligned_vector (serialize_main_t * m, va_list * va)
297 {
298   void ** vec = va_arg (*va, void **);
299   u32 elt_bytes = va_arg (*va, u32);
300   serialize_function_t * f = va_arg (*va, serialize_function_t *);
301   u32 align = va_arg (*va, u32);
302
303   *vec = unserialize_vector_ha (m, elt_bytes,
304                                 /* header_bytes */ 0,
305                                 /* align */ align,
306                                 /* max_length */ ~0,
307                                 f);
308 }
309
310 void unserialize_vector (serialize_main_t * m, va_list * va)
311 {
312   void ** vec = va_arg (*va, void **);
313   u32 elt_bytes = va_arg (*va, u32);
314   serialize_function_t * f = va_arg (*va, serialize_function_t *);
315
316   *vec = unserialize_vector_ha (m, elt_bytes,
317                                 /* header_bytes */ 0,
318                                 /* align */ 0,
319                                 /* max_length */ ~0,
320                                 f);
321 }
322
323 void serialize_bitmap (serialize_main_t * m, uword * b)
324 {
325   u32 l, i, n_u32s;
326
327   l = vec_len (b);
328   n_u32s = l * sizeof (b[0]) / sizeof (u32);
329   serialize_integer (m, n_u32s, sizeof (n_u32s));
330
331   /* Send 32 bit words, low-order word first on 64 bit. */
332   for (i = 0; i < l; i++)
333     {
334       serialize_integer (m, b[i], sizeof (u32));
335       if (BITS (uword) == 64)
336         serialize_integer (m, (u64) b[i] >> (u64) 32, sizeof (u32));
337     }
338 }
339
340 uword * unserialize_bitmap (serialize_main_t * m)
341 {
342   uword * b = 0;
343   u32 i, n_u32s;
344
345   unserialize_integer (m, &n_u32s, sizeof (n_u32s));
346   if (n_u32s == 0)
347     return b;
348
349   i = (n_u32s * sizeof (u32) + sizeof (b[0]) - 1) / sizeof (b[0]);
350   vec_resize (b, i);
351   for (i = 0; i < n_u32s; i++)
352     {
353       u32 data;
354       unserialize_integer (m, &data, sizeof (u32));
355
356       /* Low-word is first on 64 bit. */
357       if (BITS (uword) == 64)
358         {
359           if ((i % 2) == 0)
360             b[i/2] |= (u64) data << (u64) 0;
361           else
362             b[i/2] |= (u64) data << (u64) 32;
363         }
364       else
365         {
366           b[i] = data;
367         }
368     }
369
370   return b;
371 }
372
373 void serialize_pool (serialize_main_t * m, va_list * va)
374 {
375   void * pool = va_arg (*va, void *);
376   u32 elt_bytes = va_arg (*va, u32);
377   serialize_function_t * f = va_arg (*va, serialize_function_t *);
378   u32 l, lo, hi;
379   pool_header_t * p;
380
381   l = vec_len (pool);
382   serialize_integer (m, l, sizeof (u32));
383   if (l == 0)
384     return;
385   p = pool_header (pool);
386
387   /* No need to send free bitmap.  Need to send index vector
388      to guarantee that unserialized pool will be identical. */
389   vec_serialize (m, p->free_indices, serialize_vec_32);
390
391   pool_foreach_region (lo, hi, pool,
392                        serialize (m, f, pool + lo*elt_bytes, hi - lo));
393 }
394
395 static void *
396 unserialize_pool_helper (serialize_main_t * m,
397                          u32 elt_bytes, u32 align,
398                          serialize_function_t * f)
399 {
400   void * v;
401   u32 i, l, lo, hi;
402   pool_header_t * p;
403
404   unserialize_integer (m, &l, sizeof (l));
405   if (l == 0)
406     {
407       return 0;
408     }
409
410   v = _vec_resize (0, l, l*elt_bytes, sizeof (p[0]), align);
411   p = pool_header (v);
412
413   vec_unserialize (m, &p->free_indices, unserialize_vec_32);
414
415   /* Construct free bitmap. */
416   p->free_bitmap = 0;
417   for (i = 0; i < vec_len (p->free_indices); i++)
418     p->free_bitmap = clib_bitmap_ori (p->free_bitmap, p->free_indices[i]);
419
420   pool_foreach_region (lo, hi, v,
421                        unserialize (m, f, v + lo*elt_bytes, hi - lo));
422
423   return v;
424 }
425
426 void unserialize_pool (serialize_main_t * m, va_list * va)
427 {
428   void ** result = va_arg (*va, void **);
429   u32 elt_bytes = va_arg (*va, u32);
430   serialize_function_t * f = va_arg (*va, serialize_function_t *);
431   *result = unserialize_pool_helper (m, elt_bytes, /* align */ 0, f);
432 }
433
434 void unserialize_aligned_pool (serialize_main_t * m, va_list * va)
435 {
436   void ** result = va_arg (*va, void **);
437   u32 elt_bytes = va_arg (*va, u32);
438   u32 align = va_arg (*va, u32);
439   serialize_function_t * f = va_arg (*va, serialize_function_t *);
440   *result = unserialize_pool_helper (m, elt_bytes, align, f);
441 }
442
443 static void serialize_vec_heap_elt (serialize_main_t * m, va_list * va)
444 {
445   heap_elt_t * e = va_arg (*va, heap_elt_t *);
446   u32 i, n = va_arg (*va, u32);
447   for (i = 0; i < n; i++)
448     {
449       serialize_integer (m, e[i].offset, sizeof (e[i].offset));
450       serialize_integer (m, e[i].next, sizeof (e[i].next));
451       serialize_integer (m, e[i].prev, sizeof (e[i].prev));
452     }
453 }
454
455 static void unserialize_vec_heap_elt (serialize_main_t * m, va_list * va)
456 {
457   heap_elt_t * e = va_arg (*va, heap_elt_t *);
458   u32 i, n = va_arg (*va, u32);
459   for (i = 0; i < n; i++)
460     {
461       unserialize_integer (m, &e[i].offset, sizeof (e[i].offset));
462       unserialize_integer (m, &e[i].next, sizeof (e[i].next));
463       unserialize_integer (m, &e[i].prev, sizeof (e[i].prev));
464     }
465 }
466
467 void serialize_heap (serialize_main_t * m, va_list * va)
468 {
469   void * heap = va_arg (*va, void *);
470   serialize_function_t * f = va_arg (*va, serialize_function_t *);
471   u32 i, l;
472   heap_header_t * h;
473
474   l = vec_len (heap);
475   serialize_integer (m, l, sizeof (u32));
476   if (l == 0)
477     return;
478
479   h = heap_header (heap);
480
481 #define foreach_serialize_heap_header_integer \
482   _ (head) _ (tail) _ (used_count) _ (max_len) _ (flags) _ (elt_bytes)
483
484 #define _(f) serialize_integer (m, h->f, sizeof (h->f));
485   foreach_serialize_heap_header_integer;
486 #undef _
487
488   serialize_integer (m, vec_len (h->free_lists), sizeof (u32));
489   for (i = 0; i < vec_len (h->free_lists); i++)
490     vec_serialize (m, h->free_lists[i], serialize_vec_32);
491
492   vec_serialize (m, h->elts, serialize_vec_heap_elt);
493   vec_serialize (m, h->small_free_elt_free_index, serialize_vec_32);
494   vec_serialize (m, h->free_elts, serialize_vec_32);
495
496   /* Serialize data in heap. */
497   {
498     heap_elt_t * e, * end;
499     e = h->elts + h->head;
500     end = h->elts + h->tail;
501     while (1)
502       {
503         if (! heap_is_free (e))
504           {
505             void * v = heap + heap_offset (e) * h->elt_bytes;
506             u32 n = heap_elt_size (heap, e);
507             serialize (m, f, v, n);
508           }
509         if (e == end)
510           break;
511         e = heap_next (e);
512       }
513   }
514 }
515
516 void unserialize_heap (serialize_main_t * m, va_list * va)
517 {
518   void ** result = va_arg (*va, void **);
519   serialize_function_t * f = va_arg (*va, serialize_function_t *);
520   u32 i, vl, fl;
521   heap_header_t h;
522   void * heap;
523
524   unserialize_integer (m, &vl, sizeof (u32));
525   if (vl == 0)
526     {
527       *result = 0;
528       return;
529     }
530
531   memset (&h, 0, sizeof (h));
532 #define _(f) unserialize_integer (m, &h.f, sizeof (h.f));
533   foreach_serialize_heap_header_integer;
534 #undef _
535
536   unserialize_integer (m, &fl, sizeof (u32));
537   vec_resize (h.free_lists, fl);
538
539   for (i = 0; i < vec_len (h.free_lists); i++)
540     vec_unserialize (m, &h.free_lists[i], unserialize_vec_32);
541
542   vec_unserialize (m, &h.elts, unserialize_vec_heap_elt);
543   vec_unserialize (m, &h.small_free_elt_free_index, unserialize_vec_32);
544   vec_unserialize (m, &h.free_elts, unserialize_vec_32);
545
546   /* Re-construct used elt bitmap. */
547   if (CLIB_DEBUG > 0)
548     {
549       heap_elt_t * e;
550       vec_foreach (e, h.elts)
551         {
552           if (! heap_is_free (e))
553             h.used_elt_bitmap = clib_bitmap_ori (h.used_elt_bitmap, e - h.elts);
554         }
555     }
556
557   heap = *result = _heap_new (vl, h.elt_bytes);
558   heap_header (heap)[0] = h;
559
560   /* Unserialize data in heap. */
561   {
562     heap_elt_t * e, * end;
563     e = h.elts + h.head;
564     end = h.elts + h.tail;
565     while (1)
566       {
567         if (! heap_is_free (e))
568           {
569             void * v = heap + heap_offset (e) * h.elt_bytes;
570             u32 n = heap_elt_size (heap, e);
571             unserialize (m, f, v, n);
572           }
573         if (e == end)
574           break;
575         e = heap_next (e);
576       }
577   }
578 }
579
580 void serialize_magic (serialize_main_t * m, void * magic, u32 magic_bytes)
581 {
582   void * p;
583   serialize_integer (m, magic_bytes, sizeof (magic_bytes));
584   p = serialize_get (m, magic_bytes);
585   memcpy (p, magic, magic_bytes);
586 }
587
588 void unserialize_check_magic (serialize_main_t * m, void * magic,
589                               u32 magic_bytes)
590 {
591   u32 l;
592   void * d;
593
594   unserialize_integer (m, &l, sizeof (l));
595   if (l != magic_bytes)
596     {
597     bad:
598       serialize_error_return (m, "bad magic number");
599     }
600   d = serialize_get (m, magic_bytes);
601   if (memcmp (magic, d, magic_bytes))
602     goto bad;
603 }
604
605 clib_error_t *
606 va_serialize (serialize_main_t * sm, va_list * va)
607 {
608   serialize_main_header_t * m = &sm->header;
609   serialize_function_t * f = va_arg (*va, serialize_function_t *);
610   clib_error_t * error = 0;
611
612   m->recursion_level += 1;
613   if (m->recursion_level == 1)
614     {
615       uword r = clib_setjmp (&m->error_longjmp, 0);
616       error = uword_to_pointer (r, clib_error_t *);
617     }
618         
619   if (! error)
620     f (sm, va);
621
622   m->recursion_level -= 1;
623   return error;
624 }
625
626 clib_error_t *
627 serialize (serialize_main_t * m, ...)
628 {
629   clib_error_t * error;
630   va_list va;
631
632   va_start (va, m);
633   error = va_serialize (m, &va);
634   va_end (va);
635   return error;
636 }
637
638 clib_error_t *
639 unserialize (serialize_main_t * m, ...)
640 {
641   clib_error_t * error;
642   va_list va;
643
644   va_start (va, m);
645   error = va_serialize (m, &va);
646   va_end (va);
647   return error;
648 }
649
650 static void * serialize_write_not_inline (serialize_main_header_t * m,
651                                           serialize_stream_t * s,
652                                           uword n_bytes_to_write,
653                                           uword flags)
654 {
655   uword cur_bi, n_left_b, n_left_o;
656
657   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
658   cur_bi = s->current_buffer_index;
659   n_left_b = s->n_buffer_bytes - cur_bi;
660   n_left_o = vec_len (s->overflow_buffer);
661
662   /* Prepend overflow buffer if present. */
663   do {
664     if (n_left_o > 0 && n_left_b > 0)
665       {
666         uword n = clib_min (n_left_b, n_left_o);
667         memcpy (s->buffer + cur_bi, s->overflow_buffer, n);
668         cur_bi += n;
669         n_left_b -= n;
670         n_left_o -= n;
671         if (n_left_o == 0)
672           _vec_len (s->overflow_buffer) = 0;
673         else
674           vec_delete (s->overflow_buffer, n, 0);
675       }
676
677     /* Call data function when buffer is complete.  Data function should
678        dispatch with current buffer and give us a new one to write more
679        data into. */
680     if (n_left_b == 0)
681       {
682         s->current_buffer_index = cur_bi;
683         m->data_function (m, s);
684         cur_bi = s->current_buffer_index;
685         n_left_b = s->n_buffer_bytes - cur_bi;
686       }
687   } while (n_left_o > 0);
688
689   if (n_left_o > 0 || n_left_b < n_bytes_to_write)
690     {
691       u8 * r;
692       vec_add2 (s->overflow_buffer, r, n_bytes_to_write);
693       return r;
694     }
695   else
696     {
697       s->current_buffer_index = cur_bi + n_bytes_to_write;
698       return s->buffer + cur_bi;
699     }
700 }
701
702 static void * serialize_read_not_inline (serialize_main_header_t * m,
703                                          serialize_stream_t * s,
704                                          uword n_bytes_to_read,
705                                          uword flags)
706 {
707   uword cur_bi, cur_oi, n_left_b, n_left_o, n_left_to_read;
708
709   ASSERT (s->current_buffer_index <= s->n_buffer_bytes);
710
711   cur_bi = s->current_buffer_index;
712   cur_oi = s->current_overflow_index;
713
714   n_left_b = s->n_buffer_bytes - cur_bi;
715   n_left_o = vec_len (s->overflow_buffer) - cur_oi;
716
717   /* Read from overflow? */
718   if (n_left_o >= n_bytes_to_read)
719     {
720       s->current_overflow_index = cur_oi + n_bytes_to_read;
721       return vec_elt_at_index (s->overflow_buffer, cur_oi);
722     }
723
724   /* Reset overflow buffer. */
725   if (n_left_o == 0 && s->overflow_buffer)
726     {
727       s->current_overflow_index = 0;
728       _vec_len (s->overflow_buffer) = 0;
729     }
730
731   n_left_to_read = n_bytes_to_read;
732   while (n_left_to_read > 0)
733     {
734       uword n;
735
736       /* If we don't have enough data between overflow and normal buffer
737          call read function. */
738       if (n_left_o + n_left_b < n_bytes_to_read)
739         {
740           /* Save any left over buffer in overflow vector. */
741           if (n_left_b > 0)
742             {
743               vec_add (s->overflow_buffer, s->buffer + cur_bi, n_left_b);
744               n_left_o += n_left_b;
745               n_left_to_read -= n_left_b;
746               /* Advance buffer to end --- even if
747                  SERIALIZE_FLAG_NO_ADVANCE_CURRENT_BUFFER_INDEX is set. */
748               cur_bi = s->n_buffer_bytes;
749               n_left_b = 0;
750             }
751
752           if (m->data_function)
753             {
754               m->data_function (m, s);
755               cur_bi = s->current_buffer_index;
756               n_left_b = s->n_buffer_bytes - cur_bi;
757             }
758         }
759
760       /* For first time through loop return if we have enough data
761          in normal buffer and overflow vector is empty. */
762       if (n_left_o == 0
763           && n_left_to_read == n_bytes_to_read
764           && n_left_b >= n_left_to_read)
765         {
766           s->current_buffer_index = cur_bi + n_bytes_to_read;
767           return s->buffer + cur_bi;
768         }
769
770       if (! m->data_function
771           || serialize_stream_is_end_of_stream (s))
772         {
773           /* This can happen for a peek at end of file.
774              Pad overflow buffer with 0s. */
775           vec_resize (s->overflow_buffer, n_left_to_read);
776           n_left_o += n_left_to_read;
777           n_left_to_read = 0;
778         }
779       else
780         {
781           /* Copy from buffer to overflow vector. */
782           n = clib_min (n_left_to_read, n_left_b);
783           vec_add (s->overflow_buffer, s->buffer + cur_bi, n);
784           cur_bi += n;
785           n_left_b -= n;
786           n_left_o += n;
787           n_left_to_read -= n;
788         }
789     }
790       
791   s->current_buffer_index = cur_bi;
792   s->current_overflow_index = cur_oi + n_bytes_to_read;
793   return vec_elt_at_index (s->overflow_buffer, cur_oi);
794 }
795
796 void * serialize_read_write_not_inline (serialize_main_header_t * m,
797                                         serialize_stream_t * s,
798                                         uword n_bytes,
799                                         uword flags)
800 {
801   return (((flags & SERIALIZE_FLAG_IS_READ) ? serialize_read_not_inline : serialize_write_not_inline)
802           (m, s, n_bytes, flags));
803 }
804
805 static void serialize_read_write_close (serialize_main_header_t * m, serialize_stream_t * s, uword flags)
806 {
807   if (serialize_stream_is_end_of_stream (s))
808     return;
809
810   if (flags & SERIALIZE_FLAG_IS_WRITE)
811     /* "Write" 0 bytes to flush overflow vector. */
812     serialize_write_not_inline (m, s, /* n bytes */ 0, flags);
813
814   serialize_stream_set_end_of_stream (s);
815
816   /* Call it one last time to flush buffer and close. */
817   m->data_function (m, s);
818
819   vec_free (s->overflow_buffer);
820 }
821
822 void serialize_close (serialize_main_t * m)
823 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_WRITE); }
824
825 void unserialize_close (serialize_main_t * m)
826 { serialize_read_write_close (&m->header, &m->stream, SERIALIZE_FLAG_IS_READ); }
827
828 void serialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
829 {
830   memset (m, 0, sizeof (m[0]));
831   m->stream.buffer = data;
832   m->stream.n_buffer_bytes = n_data_bytes;
833 }
834
835 void unserialize_open_data (serialize_main_t * m, u8 * data, uword n_data_bytes)
836 { serialize_open_data (m, data, n_data_bytes); }
837
838 static void serialize_vector_write (serialize_main_header_t * m, serialize_stream_t * s)
839 {
840   if (! serialize_stream_is_end_of_stream (s))
841     {
842       /* Double buffer size. */
843       uword l = vec_len (s->buffer);
844       vec_resize (s->buffer, l > 0 ? l : 64);
845       s->n_buffer_bytes = vec_len (s->buffer);
846     }
847 }
848
849 void serialize_open_vector (serialize_main_t * m, u8 * vector)
850 {
851   memset (m, 0, sizeof (m[0]));
852   m->header.data_function = serialize_vector_write;
853   m->stream.buffer = vector;
854   m->stream.current_buffer_index = 0;
855   m->stream.n_buffer_bytes = vec_len (vector);
856 }
857  
858 void * serialize_close_vector (serialize_main_t * m)
859 {
860   serialize_stream_t * s = &m->stream;
861   void * result;
862
863   serialize_close (m);          /* frees overflow buffer */
864
865   if (s->buffer)
866     _vec_len (s->buffer) = s->current_buffer_index;
867   result = s->buffer;
868   memset (m, 0, sizeof (m[0]));
869   return result;
870 }
871  
872 void
873 serialize_multiple_1 (serialize_main_t * m,
874                       void * data,
875                       uword data_stride,
876                       uword n_data)
877 {
878   u8 * d = data;
879   u8 * p;
880   uword n_left = n_data;
881
882   while (n_left >= 4)
883     {
884       p = serialize_get (m, 4 * sizeof (d[0]));
885       p[0] = d[0 * data_stride];
886       p[1] = d[1 * data_stride];
887       p[2] = d[2 * data_stride];
888       p[3] = d[3 * data_stride];
889       n_left -= 4;
890       d += 4 * data_stride;
891     }
892
893   if (n_left > 0)
894     {
895       p = serialize_get (m, n_left * sizeof (p[0]));
896       while (n_left > 0)
897         {
898           p[0] = d[0];
899           p += 1;
900           d += 1 * data_stride;
901           n_left -= 1;
902         }
903     }
904 }
905
906 void
907 serialize_multiple_2 (serialize_main_t * m,
908                       void * data,
909                       uword data_stride,
910                       uword n_data)
911 {
912   void * d = data;
913   u16 * p;
914   uword n_left = n_data;
915
916   while (n_left >= 4)
917     {
918       p = serialize_get (m, 4 * sizeof (p[0]));
919       clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
920       clib_mem_unaligned (p + 1, u16) = clib_host_to_net_mem_u16 (d + 1 * data_stride);
921       clib_mem_unaligned (p + 2, u16) = clib_host_to_net_mem_u16 (d + 2 * data_stride);
922       clib_mem_unaligned (p + 3, u16) = clib_host_to_net_mem_u16 (d + 3 * data_stride);
923       n_left -= 4;
924       d += 4 * data_stride;
925     }
926
927   if (n_left > 0)
928     {
929       p = serialize_get (m, n_left * sizeof (p[0]));
930       while (n_left > 0)
931         {
932           clib_mem_unaligned (p + 0, u16) = clib_host_to_net_mem_u16 (d + 0 * data_stride);
933           p += 1;
934           d += 1 * data_stride;
935           n_left -= 1;
936         }
937     }
938 }
939
940 void
941 serialize_multiple_4 (serialize_main_t * m,
942                       void * data,
943                       uword data_stride,
944                       uword n_data)
945 {
946   void * d = data;
947   u32 * p;
948   uword n_left = n_data;
949
950   while (n_left >= 4)
951     {
952       p = serialize_get (m, 4 * sizeof (p[0]));
953       clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
954       clib_mem_unaligned (p + 1, u32) = clib_host_to_net_mem_u32 (d + 1 * data_stride);
955       clib_mem_unaligned (p + 2, u32) = clib_host_to_net_mem_u32 (d + 2 * data_stride);
956       clib_mem_unaligned (p + 3, u32) = clib_host_to_net_mem_u32 (d + 3 * data_stride);
957       n_left -= 4;
958       d += 4 * data_stride;
959     }
960
961   if (n_left > 0)
962     {
963       p = serialize_get (m, n_left * sizeof (p[0]));
964       while (n_left > 0)
965         {
966           clib_mem_unaligned (p + 0, u32) = clib_host_to_net_mem_u32 (d + 0 * data_stride);
967           p += 1;
968           d += 1 * data_stride;
969           n_left -= 1;
970         }
971     }
972 }
973
974 void
975 unserialize_multiple_1 (serialize_main_t * m,
976                         void * data,
977                         uword data_stride,
978                         uword n_data)
979 {
980   u8 * d = data;
981   u8 * p;
982   uword n_left = n_data;
983
984   while (n_left >= 4)
985     {
986       p = unserialize_get (m, 4 * sizeof (d[0]));
987       d[0 * data_stride] = p[0];
988       d[1 * data_stride] = p[1];
989       d[2 * data_stride] = p[2];
990       d[3 * data_stride] = p[3];
991       n_left -= 4;
992       d += 4 * data_stride;
993     }
994
995   if (n_left > 0)
996     {
997       p = unserialize_get (m, n_left * sizeof (p[0]));
998       while (n_left > 0)
999         {
1000           d[0] = p[0];
1001           p += 1;
1002           d += 1 * data_stride;
1003           n_left -= 1;
1004         }
1005     }
1006 }
1007
1008 void
1009 unserialize_multiple_2 (serialize_main_t * m,
1010                         void * data,
1011                         uword data_stride,
1012                         uword n_data)
1013 {
1014   void * d = data;
1015   u16 * p;
1016   uword n_left = n_data;
1017
1018   while (n_left >= 4)
1019     {
1020       p = unserialize_get (m, 4 * sizeof (p[0]));
1021       clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1022       clib_mem_unaligned (d + 1 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 1);
1023       clib_mem_unaligned (d + 2 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 2);
1024       clib_mem_unaligned (d + 3 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 3);
1025       n_left -= 4;
1026       d += 4 * data_stride;
1027     }
1028
1029   if (n_left > 0)
1030     {
1031       p = unserialize_get (m, n_left * sizeof (p[0]));
1032       while (n_left > 0)
1033         {
1034           clib_mem_unaligned (d + 0 * data_stride, u16) = clib_net_to_host_mem_u16 (p + 0);
1035           p += 1;
1036           d += 1 * data_stride;
1037           n_left -= 1;
1038         }
1039     }
1040 }
1041
1042 void
1043 unserialize_multiple_4 (serialize_main_t * m,
1044                         void * data,
1045                         uword data_stride,
1046                         uword n_data)
1047 {
1048   void * d = data;
1049   u32 * p;
1050   uword n_left = n_data;
1051
1052   while (n_left >= 4)
1053     {
1054       p = unserialize_get (m, 4 * sizeof (p[0]));
1055       clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1056       clib_mem_unaligned (d + 1 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 1);
1057       clib_mem_unaligned (d + 2 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 2);
1058       clib_mem_unaligned (d + 3 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 3);
1059       n_left -= 4;
1060       d += 4 * data_stride;
1061     }
1062
1063   if (n_left > 0)
1064     {
1065       p = unserialize_get (m, n_left * sizeof (p[0]));
1066       while (n_left > 0)
1067         {
1068           clib_mem_unaligned (d + 0 * data_stride, u32) = clib_net_to_host_mem_u32 (p + 0);
1069           p += 1;
1070           d += 1 * data_stride;
1071           n_left -= 1;
1072         }
1073     }
1074 }
1075
1076 #ifdef CLIB_UNIX
1077
1078 #include <unistd.h>
1079 #include <fcntl.h>
1080
1081 static void unix_file_write (serialize_main_header_t * m, serialize_stream_t * s)
1082 {
1083   int fd, n;
1084
1085   fd = s->data_function_opaque;
1086   n = write (fd, s->buffer, s->current_buffer_index);
1087   if (n < 0)
1088     {
1089       if (! unix_error_is_fatal (errno))
1090         n = 0;
1091       else
1092         serialize_error (m, clib_error_return_unix (0, "write"));
1093     }
1094   if (n == s->current_buffer_index)
1095     _vec_len (s->buffer) = 0;
1096   else
1097     vec_delete (s->buffer, n, 0);
1098   s->current_buffer_index = vec_len (s->buffer);
1099 }
1100
1101 static void unix_file_read (serialize_main_header_t * m, serialize_stream_t * s)
1102 {
1103   int fd, n;
1104
1105   fd = s->data_function_opaque;
1106   n = read (fd, s->buffer, vec_len (s->buffer));
1107   if (n < 0)
1108     {
1109       if (! unix_error_is_fatal (errno))
1110         n = 0;
1111       else
1112         serialize_error (m, clib_error_return_unix (0, "read"));
1113     }
1114   else if (n == 0)
1115     serialize_stream_set_end_of_stream (s);
1116   s->current_buffer_index = 0;
1117   s->n_buffer_bytes = n;
1118 }
1119
1120 static void
1121 serialize_open_unix_file_descriptor_helper (serialize_main_t * m, int fd, uword is_read)
1122 {
1123   memset (m, 0, sizeof (m[0]));
1124   vec_resize (m->stream.buffer, 4096);
1125   
1126   if (! is_read)
1127     {
1128       m->stream.n_buffer_bytes = vec_len (m->stream.buffer);
1129       _vec_len (m->stream.buffer) = 0;
1130     }
1131
1132   m->header.data_function = is_read ? unix_file_read : unix_file_write;
1133   m->stream.data_function_opaque = fd;
1134 }
1135
1136 void serialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1137 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 0); }
1138
1139 void unserialize_open_unix_file_descriptor (serialize_main_t * m, int fd)
1140 { serialize_open_unix_file_descriptor_helper (m, fd, /* is_read */ 1); }
1141
1142 static clib_error_t *
1143 serialize_open_unix_file_helper (serialize_main_t * m, char * file, uword is_read)
1144 {
1145   int fd, mode;
1146
1147   mode = is_read ? O_RDONLY : O_RDWR | O_CREAT | O_TRUNC;
1148   fd = open (file, mode, 0666);
1149   if (fd < 0)
1150     return clib_error_return_unix (0, "open `%s'", file);
1151
1152   serialize_open_unix_file_descriptor_helper (m, fd, is_read);
1153   return 0;
1154 }
1155
1156 clib_error_t *
1157 serialize_open_unix_file (serialize_main_t * m, char * file)
1158 { return serialize_open_unix_file_helper (m, file, /* is_read */ 0); }
1159
1160 clib_error_t *
1161 unserialize_open_unix_file (serialize_main_t * m, char * file)
1162 { return serialize_open_unix_file_helper (m, file, /* is_read */ 1); }
1163
1164 #endif /* CLIB_UNIX */