ROHC compression/decompression library
rohc_bit_ops.h
Go to the documentation of this file.
1 /*
2  * Copyright 2010,2012,2013 Didier Barvaux
3  * Copyright 2013 Viveris Technologies
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /**
21  * @file rohc_bit_ops.h
22  * @brief Bitwised operations for ROHC compression/decompression
23  * @author Didier Barvaux <didier.barvaux@toulouse.viveris.com>
24  * @author Didier Barvaux <didier@barvaux.org>
25  */
26 
27 #ifndef ROHC_BIT_OPS_H
28 #define ROHC_BIT_OPS_H
29 
30 #ifdef __KERNEL__
31 # include <endian.h>
32 # include <bitops.h>
33 #else
34 # include "config.h" /* for WORDS_BIGENDIAN */
35 #endif
36 
37 
38 /*
39  * GET_BIT_n(x) macros: extract the (n+1) th bit from byte x starting from
40  * the right and do not right-shift it
41  */
42 
43 #define GET_BIT_0(x) ((*(x)) & 0x01)
44 #define GET_BIT_1(x) ((*(x)) & 0x02)
45 #define GET_BIT_2(x) ((*(x)) & 0x04)
46 #define GET_BIT_3(x) ((*(x)) & 0x08)
47 #define GET_BIT_4(x) ((*(x)) & 0x10)
48 #define GET_BIT_5(x) ((*(x)) & 0x20)
49 #define GET_BIT_6(x) ((*(x)) & 0x40)
50 #define GET_BIT_7(x) ((*(x)) & 0x80)
51 
52 
53 /*
54  * GET_BIT_0_m(x) macros: extract bits 0 to m included from byte x and do not
55  * right-shift them
56  */
57 
58 #define GET_BIT_0_2(x) ((*(x)) & 0x07)
59 #define GET_BIT_0_4(x) ((*(x)) & 0x1f)
60 #define GET_BIT_0_3(x) ((*(x)) & 0x0f)
61 #define GET_BIT_0_5(x) ((*(x)) & 0x3f)
62 #define GET_BIT_0_6(x) ((*(x)) & 0x7f)
63 #define GET_BIT_0_7(x) ((*(x)) & 0xff)
64 
65 
66 /*
67  * GET_BIT_n_m(x) macros: extract bits n to m included from byte x and
68  * right-shift them
69  */
70 
71 #define GET_BIT_1_7(x) ( ((*(x)) & 0xfe) >> 1 )
72 #define GET_BIT_3_4(x) ( ((*(x)) & 0x18) >> 3 )
73 #define GET_BIT_3_5(x) ( ((*(x)) & 0x38) >> 3 )
74 #define GET_BIT_3_6(x) ( ((*(x)) & 0x78) >> 3 )
75 #define GET_BIT_3_7(x) ( ((*(x)) & 0xf8) >> 3 )
76 #define GET_BIT_4_7(x) ( ((*(x)) & 0xf0) >> 4 )
77 #define GET_BIT_5_7(x) ( ((*(x)) & 0xe0) >> 5 )
78 #define GET_BIT_6_7(x) ( ((*(x)) & 0xc0) >> 6 )
79 #define GET_BIT_4_6(x) ( ((*(x)) & 0x70) >> 4 )
80 
81 
82 /**
83  * @brief Convert GET_BIT_* values to 0 or 1
84  *
85  * example: GET_REAL(GET_BIT_5(data_ptr));
86  */
87 #define GET_REAL(x) ((x) ? 1 : 0)
88 
89 
90 /**
91  * @brief Convert GET_BIT_* values to boolean
92  *
93  * example: GET_BOOL(GET_BIT_5(data_ptr));
94  */
95 #define GET_BOOL(x) ((x) ? true : false)
96 
97 
98 /**
99  * @brief Get the next 16 bits at the given memory location
100  * in Network Byte Order
101  */
102 #if WORDS_BIGENDIAN == 1
103 # define GET_NEXT_16_BITS(x) \
104  ((((*(x)) << 8) & 0xff00) | ((*((x) + 1)) & 0x00ff))
105 #else
106 # define GET_NEXT_16_BITS(x) \
107  ((((*((x) + 1)) << 8) & 0xff00) | ((*(x)) & 0x00ff))
108 #endif
109 
110 
111 /** Append new LSB bits to already extracted bits */
112 #define APPEND_BITS(field_descr, ext_no, field, field_nr, bits, bits_nr, max) \
113  do \
114  { \
115  /* ensure not to eval variables several times */ \
116  const typeof(bits) _bits = (bits); \
117  const size_t _bits_nr = (bits_nr); \
118  const size_t _max = (max); \
119  /* print a description of what we do */ \
120  rohc_decomp_debug(context, \
121  "%zd bits of " #field_descr " found in %s = 0x%x", \
122  (_bits_nr), rohc_get_ext_descr(ext_no), (_bits)); \
123  /* is there enough room for all existing and new bits? */ \
124  if(((field_nr) + (_bits_nr)) <= (_max)) \
125  { \
126  /* enough room: make and clear room, copy LSB */ \
127  field <<= (_bits_nr); \
128  field &= ~((1U << (_bits_nr)) - 1); \
129  field |= (_bits); \
130  field_nr += (_bits_nr); \
131  } \
132  else \
133  { \
134  /* not enough room: drop some MSB */ \
135  typeof(field) _mask; \
136  assert((_bits_nr) > 0); \
137  assert((_bits_nr) <= (_max)); \
138  /* remove extra MSB (warn if dropped MSB are non-zero) */ \
139  _mask = (1U << ((_max) - (_bits_nr))) - 1; \
140  if((field & _mask) != field) \
141  { \
142  rohc_info((context)->decompressor, ROHC_TRACE_DECOMP, \
143  (context)->profile->id, \
144  "too many bits for " #field_descr ": %zu bits found " \
145  "in %s, and %zu bits already found before for a " \
146  "%zu-bit field", (_bits_nr), \
147  rohc_get_ext_descr(ext_no), (field_nr), (_max)); \
148  } \
149  field &= _mask; \
150  /* make room and clear that room for new LSB */ \
151  field <<= (_bits_nr); \
152  field &= ~((1U << (_bits_nr)) - 1); \
153  /* add new LSB */ \
154  field |= (_bits); \
155  field_nr = (_max); \
156  } \
157  } \
158  while(0)
159 
160 /** SN: append new LSB bits to already extracted bits */
161 #define APPEND_SN_BITS(ext_no, base, bits, bits_nr) \
162  APPEND_BITS(SN, ext_no, \
163  (base)->sn, (base)->sn_nr, \
164  (bits), (bits_nr), 32)
165 
166 /** Outer IP-ID: append new LSB bits to already extracted bits */
167 #define APPEND_OUTER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
168  APPEND_BITS(outer IP-ID, ext_no, \
169  (base)->outer_ip.id, (base)->outer_ip.id_nr, \
170  (bits), (bits_nr), 16)
171 
172 /** Inner IP-ID: append new LSB bits to already extracted bits */
173 #define APPEND_INNER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
174  APPEND_BITS(inner IP-ID, ext_no, \
175  (base)->inner_ip.id, (base)->inner_ip.id_nr, \
176  (bits), (bits_nr), 16)
177 
178 /** TS: append new LSB bits to already extracted bits */
179 #define APPEND_TS_BITS(ext_no, base, bits, bits_nr) \
180  APPEND_BITS(TS, ext_no, \
181  (base)->ts, (base)->ts_nr, \
182  (bits), (bits_nr), 32)
183 
184 #endif
185