LCOV - code coverage report
Current view: top level - vppinfra - serialize.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 53 85 62.4 %
Date: 2023-10-26 01:39:38 Functions: 9 10 90.0 %

          Line data    Source code
       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             : #ifndef included_clib_serialize_h
      39             : #define included_clib_serialize_h
      40             : 
      41             : #include <stdarg.h>
      42             : #include <vppinfra/byte_order.h>
      43             : #include <vppinfra/types.h>
      44             : #include <vppinfra/vec.h>
      45             : #include <vppinfra/longjmp.h>
      46             : 
      47             : struct serialize_main_header_t;
      48             : struct serialize_stream_t;
      49             : 
      50             : typedef void (serialize_data_function_t) (struct serialize_main_header_t * h,
      51             :                                           struct serialize_stream_t * s);
      52             : 
      53             : typedef struct serialize_stream_t
      54             : {
      55             :   /* Current data buffer being serialized/unserialized. */
      56             :   u8 *buffer;
      57             : 
      58             :   /* Size of buffer in bytes. */
      59             :   u32 n_buffer_bytes;
      60             : 
      61             :   /* Current index into buffer. */
      62             :   u32 current_buffer_index;
      63             : 
      64             :   /* Overflow buffer for when there is not enough room at the end of
      65             :      buffer to hold serialized/unserialized data. */
      66             :   u8 *overflow_buffer;
      67             : 
      68             :   /* Current index in overflow buffer for reads. */
      69             :   u32 current_overflow_index;
      70             : 
      71             :   u32 flags;
      72             : #define SERIALIZE_END_OF_STREAM (1 << 0)
      73             : 
      74             :   uword data_function_opaque;
      75             : 
      76             :   u32 opaque[64 - 4 * sizeof (u32) - 1 * sizeof (uword) -
      77             :              2 * sizeof (void *)];
      78             : } serialize_stream_t;
      79             : 
      80             : always_inline void
      81        1635 : serialize_stream_set_end_of_stream (serialize_stream_t * s)
      82             : {
      83        1635 :   s->flags |= SERIALIZE_END_OF_STREAM;
      84        1635 : }
      85             : 
      86             : always_inline uword
      87       21255 : serialize_stream_is_end_of_stream (serialize_stream_t * s)
      88             : {
      89       21255 :   return (s->flags & SERIALIZE_END_OF_STREAM) != 0;
      90             : }
      91             : 
      92             : typedef struct serialize_main_header_t
      93             : {
      94             :   u32 recursion_level;
      95             : 
      96             :   /* Data callback function and opaque data. */
      97             :   serialize_data_function_t *data_function;
      98             : 
      99             :   /* Error if signaled by data function. */
     100             :   clib_error_t *error;
     101             : 
     102             :   /* Exit unwind point if error occurs. */
     103             :   clib_longjmp_t error_longjmp;
     104             : } serialize_main_header_t;
     105             : 
     106             : always_inline void
     107           0 : serialize_error (serialize_main_header_t * m, clib_error_t * error)
     108             : {
     109           0 :   clib_longjmp (&m->error_longjmp, pointer_to_uword (error));
     110           0 : }
     111             : 
     112             : #define serialize_error_return(m,args...)                       \
     113             :   serialize_error (&(m)->header, clib_error_return (0, args))
     114             : 
     115             : void *serialize_read_write_not_inline (serialize_main_header_t * m,
     116             :                                        serialize_stream_t * s,
     117             :                                        uword n_bytes, uword flags);
     118             : 
     119             : #define SERIALIZE_FLAG_IS_READ  (1 << 0)
     120             : #define SERIALIZE_FLAG_IS_WRITE (1 << 1)
     121             : 
     122             : always_inline void *
     123     8969726 : serialize_stream_read_write (serialize_main_header_t * header,
     124             :                              serialize_stream_t * s,
     125             :                              uword n_bytes, uword flags)
     126             : {
     127             :   uword i, j, l;
     128             : 
     129     8969726 :   l = vec_len (s->overflow_buffer);
     130     8969726 :   i = s->current_buffer_index;
     131     8969726 :   j = i + n_bytes;
     132     8969726 :   s->current_buffer_index = j;
     133     8969726 :   if (l == 0 && j <= s->n_buffer_bytes)
     134             :     {
     135     8937026 :       return s->buffer + i;
     136             :     }
     137             :   else
     138             :     {
     139       32697 :       s->current_buffer_index = i;
     140       32697 :       return serialize_read_write_not_inline (header, s, n_bytes, flags);
     141             :     }
     142             : }
     143             : 
     144             : typedef struct
     145             : {
     146             :   serialize_main_header_t header;
     147             :   serialize_stream_t stream;
     148             : } serialize_main_t;
     149             : 
     150             : always_inline void
     151             : serialize_set_end_of_stream (serialize_main_t * m)
     152             : {
     153             :   serialize_stream_set_end_of_stream (&m->stream);
     154             : }
     155             : 
     156             : always_inline uword
     157             : serialize_is_end_of_stream (serialize_main_t * m)
     158             : {
     159             :   return serialize_stream_is_end_of_stream (&m->stream);
     160             : }
     161             : 
     162             : typedef struct
     163             : {
     164             :   serialize_main_header_t header;
     165             :   serialize_stream_t *streams;
     166             : } serialize_multiple_main_t;
     167             : 
     168             : typedef void (serialize_function_t) (serialize_main_t * m, va_list * va);
     169             : 
     170             : always_inline void *
     171      325334 : unserialize_get (serialize_main_t * m, uword n_bytes)
     172             : {
     173      325334 :   return serialize_stream_read_write (&m->header, &m->stream, n_bytes,
     174             :                                       SERIALIZE_FLAG_IS_READ);
     175             : }
     176             : 
     177             : always_inline void *
     178     8644390 : serialize_get (serialize_main_t * m, uword n_bytes)
     179             : {
     180     8644390 :   return serialize_stream_read_write (&m->header, &m->stream, n_bytes,
     181             :                                       SERIALIZE_FLAG_IS_WRITE);
     182             : }
     183             : 
     184             : always_inline void
     185        1635 : serialize_integer (serialize_main_t * m, u64 x, u32 n_bytes)
     186             : {
     187        1635 :   u8 *p = serialize_get (m, n_bytes);
     188        1635 :   if (n_bytes == 1)
     189           0 :     p[0] = x;
     190        1635 :   else if (n_bytes == 2)
     191           0 :     clib_mem_unaligned (p, u16) = clib_host_to_net_u16 (x);
     192        1635 :   else if (n_bytes == 4)
     193        1635 :     clib_mem_unaligned (p, u32) = clib_host_to_net_u32 (x);
     194           0 :   else if (n_bytes == 8)
     195           0 :     clib_mem_unaligned (p, u64) = clib_host_to_net_u64 (x);
     196             :   else
     197           0 :     ASSERT (0);
     198        1635 : }
     199             : 
     200             : always_inline void
     201          47 : unserialize_integer (serialize_main_t * m, void *x, u32 n_bytes)
     202             : {
     203          47 :   u8 *p = unserialize_get (m, n_bytes);
     204          47 :   if (n_bytes == 1)
     205           0 :     *(u8 *) x = p[0];
     206          47 :   else if (n_bytes == 2)
     207           0 :     *(u16 *) x = clib_net_to_host_unaligned_mem_u16 ((u16 *) p);
     208          47 :   else if (n_bytes == 4)
     209          47 :     *(u32 *) x = clib_net_to_host_unaligned_mem_u32 ((u32 *) p);
     210           0 :   else if (n_bytes == 8)
     211           0 :     *(u64 *) x = clib_net_to_host_unaligned_mem_u64 ((u64 *) p);
     212             :   else
     213           0 :     ASSERT (0);
     214          47 : }
     215             : 
     216             : /* As above but tries to be more compact. */
     217             : always_inline void
     218     5761840 : serialize_likely_small_unsigned_integer (serialize_main_t * m, u64 x)
     219             : {
     220     5761840 :   u64 r = x;
     221             :   u8 *p;
     222             : 
     223             :   /* Low bit set means it fits into 1 byte. */
     224     5761840 :   if (r < (1 << 7))
     225             :     {
     226     3088565 :       p = serialize_get (m, 1);
     227     3088565 :       p[0] = 1 + 2 * r;
     228     3088565 :       return;
     229             :     }
     230             : 
     231             :   /* Low 2 bits 1 0 means it fits into 2 bytes. */
     232     2673270 :   r -= (1 << 7);
     233     2673270 :   if (r < (1 << 14))
     234             :     {
     235     2673270 :       p = serialize_get (m, 2);
     236     2673270 :       clib_mem_unaligned (p, u16) = clib_host_to_little_u16 (4 * r + 2);
     237     2673270 :       return;
     238             :     }
     239             : 
     240           0 :   r -= (1 << 14);
     241           0 :   if (r < (1 << 29))
     242             :     {
     243           0 :       p = serialize_get (m, 4);
     244           0 :       clib_mem_unaligned (p, u32) = clib_host_to_little_u32 (8 * r + 4);
     245           0 :       return;
     246             :     }
     247             : 
     248           0 :   p = serialize_get (m, 9);
     249           0 :   p[0] = 0;                     /* Only low 3 bits are used. */
     250           0 :   clib_mem_unaligned (p + 1, u64) = clib_host_to_little_u64 (x);
     251             : }
     252             : 
     253             : always_inline u64
     254      165628 : unserialize_likely_small_unsigned_integer (serialize_main_t * m)
     255             : {
     256      165628 :   u8 *p = unserialize_get (m, 1);
     257             :   u64 r;
     258      165628 :   u32 y = p[0];
     259             : 
     260      165628 :   if (y & 1)
     261       88783 :     return y / 2;
     262             : 
     263       76845 :   r = 1 << 7;
     264       76845 :   if (y & 2)
     265             :     {
     266       76845 :       p = unserialize_get (m, 1);
     267       76845 :       r += (y / 4) + (p[0] << 6);
     268       76845 :       return r;
     269             :     }
     270             : 
     271           0 :   r += 1 << 14;
     272           0 :   if (y & 4)
     273             :     {
     274           0 :       p = unserialize_get (m, 3);
     275           0 :       r += ((y / 8)
     276           0 :             + (p[0] << (5 + 8 * 0))
     277           0 :             + (p[1] << (5 + 8 * 1)) + (p[2] << (5 + 8 * 2)));
     278           0 :       return r;
     279             :     }
     280             : 
     281           0 :   p = unserialize_get (m, 8);
     282           0 :   r = clib_mem_unaligned (p, u64);
     283           0 :   r = clib_little_to_host_u64 (r);
     284             : 
     285           0 :   return r;
     286             : }
     287             : 
     288             : always_inline void
     289             : serialize_likely_small_signed_integer (serialize_main_t * m, i64 s)
     290             : {
     291             :   u64 u = s < 0 ? -(2 * s + 1) : 2 * s;
     292             :   serialize_likely_small_unsigned_integer (m, u);
     293             : }
     294             : 
     295             : always_inline i64
     296             : unserialize_likely_small_signed_integer (serialize_main_t * m)
     297             : {
     298             :   u64 u = unserialize_likely_small_unsigned_integer (m);
     299             :   i64 s = u / 2;
     300             :   return (u & 1) ? -s : s;
     301             : }
     302             : 
     303             : void
     304             : serialize_multiple_1 (serialize_main_t * m,
     305             :                       void *data, uword data_stride, uword n_data);
     306             : void
     307             : serialize_multiple_2 (serialize_main_t * m,
     308             :                       void *data, uword data_stride, uword n_data);
     309             : void
     310             : serialize_multiple_4 (serialize_main_t * m,
     311             :                       void *data, uword data_stride, uword n_data);
     312             : 
     313             : void
     314             : unserialize_multiple_1 (serialize_main_t * m,
     315             :                         void *data, uword data_stride, uword n_data);
     316             : void
     317             : unserialize_multiple_2 (serialize_main_t * m,
     318             :                         void *data, uword data_stride, uword n_data);
     319             : void
     320             : unserialize_multiple_4 (serialize_main_t * m,
     321             :                         void *data, uword data_stride, uword n_data);
     322             : 
     323             : always_inline void
     324             : serialize_multiple (serialize_main_t * m,
     325             :                     void *data,
     326             :                     uword n_data_bytes, uword data_stride, uword n_data)
     327             : {
     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);
     334             :   else
     335             :     ASSERT (0);
     336             : }
     337             : 
     338             : always_inline void
     339             : unserialize_multiple (serialize_main_t * m,
     340             :                       void *data,
     341             :                       uword n_data_bytes, uword data_stride, uword n_data)
     342             : {
     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);
     349             :   else
     350             :     ASSERT (0);
     351             : }
     352             : 
     353             : /* Basic types. */
     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;
     360             : 
     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;
     366             : 
     367             : /* Serialize generic vectors. */
     368             : serialize_function_t serialize_vector, unserialize_vector,
     369             :   unserialize_aligned_vector;
     370             : 
     371             : #define vec_serialize(m,v,f) \
     372             :   serialize ((m), serialize_vector, (v), sizeof ((v)[0]), (f))
     373             : 
     374             : #define vec_unserialize(m,v,f) \
     375             :   unserialize ((m), unserialize_vector, (v), sizeof ((*(v))[0]), (f))
     376             : 
     377             : #define vec_unserialize_aligned(m,v,f) \
     378             :   unserialize ((m), unserialize_aligned_vector, (v), sizeof ((*(v))[0]), (f))
     379             : 
     380             : /* Serialize pools. */
     381             : serialize_function_t serialize_pool, unserialize_pool,
     382             :   unserialize_aligned_pool;
     383             : 
     384             : #define pool_serialize(m,v,f) \
     385             :   serialize ((m), serialize_pool, (v), sizeof ((v)[0]), (f))
     386             : 
     387             : #define pool_unserialize(m,v,f) \
     388             :   unserialize ((m), unserialize_pool, (v), sizeof ((*(v))[0]), (f))
     389             : 
     390             : #define pool_unserialize_aligned(m,v,a,f)                               \
     391             :   unserialize ((m), unserialize_aligned_pool, (v), sizeof ((*(v))[0]), (a), (f))
     392             : 
     393             : /* Serialize heaps. */
     394             : serialize_function_t serialize_heap, unserialize_heap;
     395             : 
     396             : void serialize_bitmap (serialize_main_t * m, uword * b);
     397             : uword *unserialize_bitmap (serialize_main_t * m);
     398             : 
     399             : void serialize_cstring (serialize_main_t * m, char *string);
     400             : void unserialize_cstring (serialize_main_t * m, char **string);
     401             : 
     402             : void serialize_close (serialize_main_t * m);
     403             : void unserialize_close (serialize_main_t * m);
     404             : 
     405             : void serialize_open_data (serialize_main_t * m, u8 * data,
     406             :                           uword n_data_bytes);
     407             : void unserialize_open_data (serialize_main_t * m, u8 * data,
     408             :                             uword n_data_bytes);
     409             : 
     410             : /* Starts serialization with expanding vector as buffer. */
     411             : void serialize_open_vector (serialize_main_t * m, u8 * vector);
     412             : 
     413             : /* Serialization is done: returns vector buffer to caller. */
     414             : void *serialize_close_vector (serialize_main_t * m);
     415             : 
     416             : void unserialize_open_vector (serialize_main_t * m, u8 * vector);
     417             : 
     418             : #ifdef CLIB_UNIX
     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);
     421             : 
     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 */
     425             : 
     426             : /* Main routines. */
     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);
     430             : 
     431             : void serialize_magic (serialize_main_t * m, void *magic, u32 magic_bytes);
     432             : void unserialize_check_magic (serialize_main_t * m, void *magic,
     433             :                               u32 magic_bytes);
     434             : 
     435             : #endif /* included_clib_serialize_h */
     436             : 
     437             : /*
     438             :  * fd.io coding-style-patch-verification: ON
     439             :  *
     440             :  * Local Variables:
     441             :  * eval: (c-set-style "gnu")
     442             :  * End:
     443             :  */

Generated by: LCOV version 1.14