ROHC compression/decompression library
rohc_bit_ops.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010,2012,2013 Didier Barvaux
00003  * Copyright 2013 Viveris Technologies
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 /**
00021  * @file    rohc_bit_ops.h
00022  * @brief   Bitwised operations for ROHC compression/decompression
00023  * @author  Didier Barvaux <didier.barvaux@toulouse.viveris.com>
00024  * @author  Didier Barvaux <didier@barvaux.org>
00025  */
00026 
00027 #ifndef ROHC_BIT_OPS_H
00028 #define ROHC_BIT_OPS_H
00029 
00030 #ifdef __KERNEL__
00031 #       include <endian.h>
00032 #else
00033 #       include "config.h" /* for WORDS_BIGENDIAN */
00034 #endif
00035 
00036 
00037 /*
00038  * GET_BIT_n(x) macros: extract the (n+1) th bit from byte x starting from
00039  *                      the right and do not right-shift it
00040  */
00041 
00042 #define GET_BIT_0(x)  ((*(x)) & 0x01)
00043 #define GET_BIT_1(x)  ((*(x)) & 0x02)
00044 #define GET_BIT_2(x)  ((*(x)) & 0x04)
00045 #define GET_BIT_3(x)  ((*(x)) & 0x08)
00046 #define GET_BIT_4(x)  ((*(x)) & 0x10)
00047 #define GET_BIT_5(x)  ((*(x)) & 0x20)
00048 #define GET_BIT_6(x)  ((*(x)) & 0x40)
00049 #define GET_BIT_7(x)  ((*(x)) & 0x80)
00050 
00051 
00052 /*
00053  * GET_BIT_0_m(x) macros: extract bits 0 to m included from byte x and do not
00054  *                        right-shift them
00055  */
00056 
00057 #define GET_BIT_0_2(x)  ((*(x)) & 0x07)
00058 #define GET_BIT_0_4(x)  ((*(x)) & 0x1f)
00059 #define GET_BIT_0_3(x)  ((*(x)) & 0x0f)
00060 #define GET_BIT_0_5(x)  ((*(x)) & 0x3f)
00061 #define GET_BIT_0_6(x)  ((*(x)) & 0x7f)
00062 #define GET_BIT_0_7(x)  ((*(x)) & 0xff)
00063 
00064 
00065 /*
00066  * GET_BIT_n_m(x) macros: extract bits n to m included from byte x and
00067  *                        right-shift them
00068  */
00069 
00070 #define GET_BIT_1_7(x)  ( ((*(x)) & 0xfe) >> 1 )
00071 #define GET_BIT_3_4(x)  ( ((*(x)) & 0x18) >> 3 )
00072 #define GET_BIT_3_5(x)  ( ((*(x)) & 0x38) >> 3 )
00073 #define GET_BIT_3_6(x)  ( ((*(x)) & 0x78) >> 3 )
00074 #define GET_BIT_3_7(x)  ( ((*(x)) & 0xf8) >> 3 )
00075 #define GET_BIT_4_7(x)  ( ((*(x)) & 0xf0) >> 4 )
00076 #define GET_BIT_5_7(x)  ( ((*(x)) & 0xe0) >> 5 )
00077 #define GET_BIT_6_7(x)  ( ((*(x)) & 0xc0) >> 6 )
00078 #define GET_BIT_4_6(x)  ( ((*(x)) & 0x70) >> 4 )
00079 
00080 
00081 /**
00082  * @brief Convert GET_BIT_* values to 0 or 1
00083  *
00084  * example: GET_REAL(GET_BIT_5(data_ptr));
00085  */
00086 #define GET_REAL(x)  ((x) ? 1 : 0)
00087 
00088 
00089 /**
00090  * @brief Convert GET_BIT_* values to boolean
00091  *
00092  * example: GET_BOOL(GET_BIT_5(data_ptr));
00093  */
00094 #define GET_BOOL(x)  ((x) ? true : false)
00095 
00096 
00097 /**
00098  * @brief Get the next 16 bits at the given memory location
00099  *        in Network Byte Order
00100  */
00101 #if WORDS_BIGENDIAN == 1
00102         #define GET_NEXT_16_BITS(x) \
00103                 ((((*(x)) << 8) & 0xff00) | ((*((x) + 1)) & 0x00ff))
00104 #else
00105         #define GET_NEXT_16_BITS(x) \
00106                 ((((*((x) + 1)) << 8) & 0xff00) | ((*(x)) & 0x00ff))
00107 #endif
00108 
00109 
00110 /** Append new LSB bits to already extracted bits */
00111 #define APPEND_BITS(field_descr, ext_no, field, field_nr, bits, bits_nr, max) \
00112         do \
00113         { \
00114                 /* ensure not to eval variables several times */ \
00115                 const typeof(bits) _bits = (bits); \
00116                 const size_t _bits_nr = (bits_nr); \
00117                 const size_t _max = (max); \
00118                 /* print a description of what we do */ \
00119                 rohc_decomp_debug(context, \
00120                                   "%zd bits of " #field_descr " found in %s = 0x%x", \
00121                                   (_bits_nr), rohc_get_ext_descr(ext_no), (_bits)); \
00122                 /* is there enough room for all existing and new bits? */ \
00123                 if(((field_nr) + (_bits_nr)) <= (_max)) \
00124                 { \
00125                         /* enough room: make and clear room, copy LSB */ \
00126                         field <<= (_bits_nr); \
00127                         field &= ~((1 << (_bits_nr)) - 1); \
00128                         field |= (_bits); \
00129                         field_nr += (_bits_nr); \
00130                 } \
00131                 else \
00132                 { \
00133                         /* not enough room: drop some MSB */ \
00134                         typeof(field) _mask; \
00135                         assert((_bits_nr) > 0); \
00136                         assert((_bits_nr) <= (_max)); \
00137                         /* remove extra MSB (warn if dropped MSB are non-zero) */ \
00138                         _mask = (1 << ((_max) - (_bits_nr))) - 1; \
00139                         if((field & _mask) != field) \
00140                         { \
00141                                 rohc_info((context)->decompressor, ROHC_TRACE_DECOMP, \
00142                                           (context)->profile->id, \
00143                                           "too many bits for " #field_descr ": %zu bits found " \
00144                                           "in %s, and %zu bits already found before for a " \
00145                                           "%zu-bit field", (_bits_nr), \
00146                                           rohc_get_ext_descr(ext_no), (field_nr), (_max)); \
00147                         } \
00148                         field &= _mask; \
00149                         /* make room and clear that room for new LSB */ \
00150                         field <<= (_bits_nr); \
00151                         field &= ~((1 << (_bits_nr)) - 1); \
00152                         /* add new LSB */ \
00153                         field |= (_bits); \
00154                         field_nr = (_max); \
00155                 } \
00156         } \
00157         while(0)
00158 
00159 /** SN: append new LSB bits to already extracted bits */
00160 #define APPEND_SN_BITS(ext_no, base, bits, bits_nr) \
00161         APPEND_BITS(SN, ext_no, \
00162                     (base)->sn, (base)->sn_nr, \
00163                     (bits), (bits_nr), 32)
00164 
00165 /** Outer IP-ID: append new LSB bits to already extracted bits */
00166 #define APPEND_OUTER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
00167         APPEND_BITS(outer IP-ID, ext_no, \
00168                     (base)->outer_ip.id, (base)->outer_ip.id_nr, \
00169                     (bits), (bits_nr), 16)
00170 
00171 /** Inner IP-ID: append new LSB bits to already extracted bits */
00172 #define APPEND_INNER_IP_ID_BITS(ext_no, base, bits, bits_nr) \
00173         APPEND_BITS(inner IP-ID, ext_no, \
00174                     (base)->inner_ip.id, (base)->inner_ip.id_nr, \
00175                     (bits), (bits_nr), 16)
00176 
00177 /** TS: append new LSB bits to already extracted bits */
00178 #define APPEND_TS_BITS(ext_no, base, bits, bits_nr) \
00179         APPEND_BITS(TS, ext_no, \
00180                     (base)->ts, (base)->ts_nr, \
00181                     (bits), (bits_nr), 32)
00182 
00183 #endif
00184