RTS API Documentation  1.10.11
switch_bitpack.h
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  *
29  * switch_bitpack.h -- BITPACKING code for RFC3551 and AAL2 packing
30  *
31  */
32 /*! \file switch_bitpack.h
33  \brief BITPACKING code for RFC3551 and AAL2 packing
34 
35 */
36 #ifndef SWITCH_BITPACK_H
37 #define SWITCH_BITPACK_H
39 #include <switch.h>
40 #ifdef DEBUG_BITS
41 static char bb[80] = "";
42 static inline char *print_bits(switch_byte_t byte, char *x)
43 {
44 
45  int i, j = 0;
46  x[j++] = '[';
47  for (i = 7; i >= 0; i--) {
48  x[j++] = (byte & (1 << i)) ? '1' : '0';
49  }
50  x[j++] = ']';
51  x[j++] = '\0';
52  return x;
53 }
54 #endif
55 
56 
57 
58 /*!
59  \defgroup bp1 Bitpacking
60  \ingroup core1
61  \{
62 */
63 
64 static const uint8_t SWITCH_BITPACKED_MASKS[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
65 static const uint8_t SWITCH_REVERSE_BITPACKED_MASKS[] = { 255, 254, 252, 248, 240, 224, 192, 128 };
66 
67 /*!
68  \brief Initialize a bitpack object
69  \param pack the pack object
70  \param bitlen the number of bits per packet
71  \param buf the buffer to use for storage
72  \param buflen the length of the storage buffer
73  \param mode RFC3551 or AAL2 mode (curse you backwards folks)
74 */
75 DoxyDefine(void switch_bitpack_init(switch_bitpack_t *pack, int32_t bitlen, switch_byte_t *buf, uint32_t buflen, switch_bitpack_mode_t mode))
76  static inline int8_t switch_bitpack_init(switch_bitpack_t *pack, switch_byte_t bitlen, switch_byte_t *buf, uint32_t buflen,
78 {
79  if (!pack || (bitlen > SWITCH_BITS_PER_BYTE) || !buf || !buflen) {
80  return -1;
81  }
82 
83  memset(pack, 0, sizeof(*pack));
84  memset(buf, 0, buflen);
85  pack->frame_bits = bitlen;
86  pack->buf = buf;
87  pack->buflen = buflen;
88  pack->cur = pack->buf;
89  pack->mode = mode;
90 
91  return 0;
92 }
93 
94 static inline void pack_check_over(switch_bitpack_t *pack)
95 {
97 
98  if (pack->over) {
99  pack->bits_cur = pack->over;
100 
101  if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
102  switch_assert(pack->over <= 8);
103  this_byte &= SWITCH_BITPACKED_MASKS[pack->over];
104  this_byte <<= pack->under;
105  *pack->cur |= this_byte;
106  pack->cur++;
107  } else {
108  switch_byte_t mask = SWITCH_BITS_PER_BYTE - pack->over;
109  switch_assert(mask < 8); /* if pack->over this will allways be true */
110  this_byte &= SWITCH_REVERSE_BITPACKED_MASKS[mask];
111  this_byte >>= mask;
112 
113  *pack->cur <<= pack->over;
114  *pack->cur |= this_byte;
115  pack->cur++;
116  }
117 
118 
119  pack->bytes++;
120  pack->over = pack->under = 0;
121  }
122 }
123 
124 /*!
125  \brief finalize a bitpack object
126  \param pack the pack/unpack object
127 */
128 DoxyDefine(int8_t switch_bitpack_done(switch_bitpack_t *pack))
129  static inline int8_t switch_bitpack_done(switch_bitpack_t *pack)
130 {
131 
132  if (pack->bits_cur && pack->bits_cur < SWITCH_BITS_PER_BYTE) {
133  pack->bytes++;
134  if (pack->mode == SWITCH_BITPACK_MODE_AAL2) {
135  *pack->cur <<= SWITCH_BITS_PER_BYTE - pack->bits_cur;
136  }
137  }
138 
139  if (pack->over) {
140  pack_check_over(pack);
141  }
142  return 0;
143 }
144 
145 
146 /*!
147  \brief pull data out of a bitpack object into it's buffer
148  \param unpack the pack/unpack object
149  \param in a 1 byte int packed with bits
150  \return -1 if the buffer is full otherwise 0
151 */
152 DoxyDefine(int8_t switch_bitpack_out(switch_bitpack_t *unpack, switch_byte_t in))
153  static inline int8_t switch_bitpack_out(switch_bitpack_t *unpack, switch_byte_t in)
154 {
156 
157  if ((uint32_t) (unpack->cur - unpack->buf) > unpack->buflen) {
158  return -1;
159  }
160 
161  unpack->bits_cur = 0;
162  unpack->this_byte = this_byte = in;
163 
164 
165 
166  pack_check_over(unpack);
167  while (unpack->bits_cur <= SWITCH_BITS_PER_BYTE) {
168  switch_byte_t next = unpack->bits_cur + unpack->frame_bits;
169  switch_byte_t under_in;
170  switch_byte_t mask;
171  this_byte = unpack->this_byte;
172 
173  if (next > SWITCH_BITS_PER_BYTE) {
174  unpack->over = next - SWITCH_BITS_PER_BYTE;
175  unpack->under = unpack->frame_bits - unpack->over;
176 
177  if (unpack->mode == SWITCH_BITPACK_MODE_RFC3551) {
178  mask = SWITCH_BITS_PER_BYTE - unpack->under;
179 
180  under_in = this_byte & SWITCH_REVERSE_BITPACKED_MASKS[mask];
181  under_in >>= mask;
182  *unpack->cur |= under_in;
183  } else {
184  mask = unpack->under;
185  under_in = this_byte & SWITCH_BITPACKED_MASKS[mask];
186  *unpack->cur <<= mask;
187  *unpack->cur |= under_in;
188  }
189 
190  break;
191  }
192 
193  if (unpack->mode == SWITCH_BITPACK_MODE_RFC3551) {
194  this_byte >>= unpack->bits_cur;
195  this_byte &= SWITCH_BITPACKED_MASKS[unpack->frame_bits];
196  *unpack->cur |= this_byte;
197  unpack->cur++;
198  } else {
199  this_byte >>= (SWITCH_BITS_PER_BYTE - next);
200  this_byte &= SWITCH_BITPACKED_MASKS[unpack->frame_bits];
201 
202  *unpack->cur |= this_byte;
203  unpack->cur++;
204  }
205 
206  unpack->bits_cur = next;
207  unpack->bytes++;
208 
209 
210  }
211 
212 
213  return 0;
214 }
215 
216 
217 /*!
218  \brief pack data into a bitpack object's buffer
219  \param pack the pack/unpack object
220  \param in a 1 byte int with 1 packet worth of bits
221  \return -1 if the buffer is full otherwise 0
222 */
223 DoxyDefine(int8_t switch_bitpack_in(switch_bitpack_t *pack, switch_byte_t in))
224  static inline int8_t switch_bitpack_in(switch_bitpack_t *pack, switch_byte_t in)
225 {
226  int next = pack->bits_cur + pack->frame_bits;
227 
228  if ((uint32_t) (pack->cur - pack->buf) > pack->buflen) {
229  return -1;
230  }
231 
232  pack->bits_tot += pack->frame_bits;
233 
234  if (next > SWITCH_BITS_PER_BYTE) {
235  switch_byte_t a = 0, b = 0, rem, nxt;
236  rem = SWITCH_BITS_PER_BYTE - pack->bits_cur;
237  nxt = pack->frame_bits - rem;
238  if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
239  a = in & SWITCH_BITPACKED_MASKS[rem];
240  b = in >> rem;
241  a <<= pack->shiftby;
242  *pack->cur |= a;
243  pack->cur++;
244  *pack->cur |= b;
245  pack->bits_cur = pack->shiftby = nxt;
246  } else {
247  a = in >> nxt;
248  b = in & SWITCH_BITPACKED_MASKS[nxt];
249  *pack->cur <<= rem;
250  *pack->cur |= a;
251  pack->cur++;
252  *pack->cur |= b;
253  pack->bits_cur = nxt;
254 
255  }
256  pack->bytes++;
257 
258  } else {
259 
260  if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
261  in <<= pack->shiftby;
262  *pack->cur |= in;
263  pack->shiftby = (switch_byte_t) (pack->shiftby + pack->frame_bits);
264  } else {
265  *pack->cur <<= pack->frame_bits;
266  *pack->cur |= in;
267  }
268 
269  if (next == SWITCH_BITS_PER_BYTE) {
270  pack->cur++;
271  pack->bytes++;
272  pack->bits_cur = pack->shiftby = 0;
273  } else {
274  pack->bits_cur = (switch_byte_t) next;
275  }
276  }
277 
278  return 0;
279 }
280 
281 ///\}
282 
284 #endif
285 /* For Emacs:
286  * Local Variables:
287  * mode:c
288  * indent-tabs-mode:t
289  * tab-width:4
290  * c-basic-offset:4
291  * End:
292  * For VIM:
293  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
294  */
#define SWITCH_END_EXTERN_C
Definition: switch.h:43
switch_byte_t frame_bits
Definition: switch_types.h:541
static const uint8_t SWITCH_REVERSE_BITPACKED_MASKS[]
const cJSON *const b
Definition: switch_cJSON.h:243
switch_byte_t bitlen
switch_bitpack_mode_t mode
Definition: switch_types.h:546
switch_bitpack_mode_t
Definition: switch_types.h:511
static const uint8_t SWITCH_BITPACKED_MASKS[]
uint8_t switch_byte_t
Definition: switch_types.h:256
unpack this_byte
#define SWITCH_BITS_PER_BYTE
Definition: switch_types.h:235
switch_byte_t switch_byte_t * buf
switch_byte_t bits_cur
Definition: switch_types.h:539
switch_byte_t in
switch_byte_t * buf
Definition: switch_types.h:534
switch_byte_t this_byte
Definition: switch_types.h:543
DoxyDefine(void switch_bitpack_init(switch_bitpack_t *pack, int32_t bitlen, switch_byte_t *buf, uint32_t buflen, switch_bitpack_mode_t mode)) static inline int8_t switch_bitpack_init(switch_bitpack_t *pack
Initialize a bitpack object.
switch_byte_t switch_byte_t uint32_t switch_bitpack_mode_t mode
static void pack_check_over(switch_bitpack_t *pack)
switch_byte_t switch_byte_t uint32_t buflen
switch_byte_t under
Definition: switch_types.h:544
switch_byte_t shiftby
Definition: switch_types.h:542
Main Library Header.
switch_byte_t * cur
Definition: switch_types.h:536
switch_byte_t over
Definition: switch_types.h:545
#define switch_assert(expr)
memset(buf, 0, buflen)
#define SWITCH_BEGIN_EXTERN_C
Definition: switch.h:42