ROHC compression/decompression library
|
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