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_1(x) ((*(x)) & 0x03)
59 #define GET_BIT_0_2(x) ((*(x)) & 0x07)
60 #define GET_BIT_0_4(x) ((*(x)) & 0x1f)
61 #define GET_BIT_0_3(x) ((*(x)) & 0x0f)
62 #define GET_BIT_0_5(x) ((*(x)) & 0x3f)
63 #define GET_BIT_0_6(x) ((*(x)) & 0x7f)
64 #define GET_BIT_0_7(x) ((*(x)) & 0xff)
65 
66 
67 /*
68  * GET_BIT_n_m(x) macros: extract bits n to m included from byte x and
69  * right-shift them
70  */
71 
72 #define GET_BIT_1_7(x) ( ((*(x)) & 0xfe) >> 1 )
73 #define GET_BIT_2_5(x) ( ((*(x)) & 0x3c) >> 2 )
74 #define GET_BIT_3_4(x) ( ((*(x)) & 0x18) >> 3 )
75 #define GET_BIT_3_5(x) ( ((*(x)) & 0x38) >> 3 )
76 #define GET_BIT_3_6(x) ( ((*(x)) & 0x78) >> 3 )
77 #define GET_BIT_3_7(x) ( ((*(x)) & 0xf8) >> 3 )
78 #define GET_BIT_4_7(x) ( ((*(x)) & 0xf0) >> 4 )
79 #define GET_BIT_5_7(x) ( ((*(x)) & 0xe0) >> 5 )
80 #define GET_BIT_6_7(x) ( ((*(x)) & 0xc0) >> 6 )
81 #define GET_BIT_4_6(x) ( ((*(x)) & 0x70) >> 4 )
82 
83 
84 /**
85  * @brief Convert GET_BIT_* values to 0 or 1
86  *
87  * example: GET_REAL(GET_BIT_5(data_ptr));
88  */
89 #define GET_REAL(x) ((x) ? 1 : 0)
90 
91 
92 /**
93  * @brief Convert GET_BIT_* values to boolean
94  *
95  * example: GET_BOOL(GET_BIT_5(data_ptr));
96  */
97 #define GET_BOOL(x) ((x) ? true : false)
98 
99 
100 /**
101  * @brief Get the next 16 bits at the given memory location
102  * in Network Byte Order
103  */
104 #if WORDS_BIGENDIAN == 1
105 # define GET_NEXT_16_BITS(x) \
106  ((((*(x)) << 8) & 0xff00) | ((*((x) + 1)) & 0x00ff))
107 #else
108 # define GET_NEXT_16_BITS(x) \
109  ((((*((x) + 1)) << 8) & 0xff00) | ((*(x)) & 0x00ff))
110 #endif
111 
112 
113 /** Append new LSB bits to already extracted bits */
114 #define APPEND_BITS(field_descr, ext_no, field, field_nr, bits, bits_nr, max) \
115  do \
116  { \
117  /* ensure not to eval variables several times */ \
118  const typeof(bits) _bits = (bits); \
119  const size_t _bits_nr = (bits_nr); \
120  const size_t _max = (max); \
121  /* print a description of what we do */ \
122  rohc_decomp_debug(context, \
123  "%zd bits of " #field_descr " found in %s = 0x%x", \
124  (_bits_nr), rohc_get_ext_descr(ext_no), (_bits)); \
125  /* is there enough room for all existing and new bits? */ \
126  if(((field_nr) + (_bits_nr)) <= (_max)) \
127  { \
128  /* enough room: make and clear room, copy LSB */ \
129  field <<= (_bits_nr); \
130  field &= ~((1U << (_bits_nr)) - 1); \
131  field |= (_bits); \
132  field_nr += (_bits_nr); \
133  } \
134  else \
135  { \
136  /* not enough room: drop some MSB */ \
137  typeof(field) _mask; \
138  assert((_bits_nr) > 0); \
139  assert((_bits_nr) <= (_max)); \
140  /* remove extra MSB (warn if dropped MSB are non-zero) */ \
141  _mask = (1U << ((_max) - (_bits_nr))) - 1; \
142  if((field & _mask) != field) \
143  { \
144  rohc_info((context)->decompressor, ROHC_TRACE_DECOMP, \
145  (context)->profile->id, \
146  "too many bits for " #field_descr ": %zu bits found " \
147  "in %s, and %zu bits already found before for a " \
148  "%zu-bit field", (_bits_nr), \
149  rohc_get_ext_descr(ext_no), (field_nr), (_max)); \
150  } \
151  field &= _mask; \
152  /* make room and clear that room for new LSB */ \
153  field <<= (_bits_nr); \
154  field &= ~((1U << (_bits_nr)) - 1); \
155  /* add new LSB */ \
156  field |= (_bits); \
157  field_nr = (_max); \
158  } \
159  } \
160  while(0)
161 
162 /** SN: append new LSB bits to already extracted bits */
163 #define APPEND_SN_BITS(ext_no, base, bits, bits_nr) \
164  APPEND_BITS(SN, ext_no, \
165  (base)->sn, (base)->sn_nr, \
166  (bits), (bits_nr), 32)
167 
168 /** Outer IP-ID: append new LSB bits to already extracted bits */
169 #define APPEND_OUTER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
170  APPEND_BITS(outer IP-ID, ext_no, \
171  (base)->outer_ip.id, (base)->outer_ip.id_nr, \
172  (bits), (bits_nr), 16)
173 
174 /** Inner IP-ID: append new LSB bits to already extracted bits */
175 #define APPEND_INNER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
176  APPEND_BITS(inner IP-ID, ext_no, \
177  (base)->inner_ip.id, (base)->inner_ip.id_nr, \
178  (bits), (bits_nr), 16)
179 
180 /** TS: append new LSB bits to already extracted bits */
181 #define APPEND_TS_BITS(ext_no, base, bits, bits_nr) \
182  APPEND_BITS(TS, ext_no, \
183  (base)->ts, (base)->ts_nr, \
184  (bits), (bits_nr), 32)
185 
186 #endif
187