MediaProcessors
bitparser.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 2016, 2017, 2018 Rafael Antoniello
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
35 #include "bitparser.h"
36 
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdint.h>
40 #include <endian.h>
41 
42 #include "log.h"
43 #include "stat_codes.h"
44 #include "check_utils.h"
45 
46 /* **** Definitions **** */
47 
48 //#define ENABLE_LOGS //uncomment to trace logs
49 #ifndef ENABLE_LOGS
50 #undef LOG
51 #define LOG(...) // none
52 #endif
53 
54 #define SHL(x, y) ( ((x) << (y)) )
55 #define SHR(x, y) ( ((y) & DPATHW) ? 0 : ((x) >> (y)) )
56 
57 #define GLBIC_ENDIAN
58 
59 #ifdef LITTLEENDIAN
60 #ifdef GLBIC_ENDIAN
61 #define SWAP2(x) be16toh(x)
62 #define SWAP4(x) be32toh(x)
63 #define SWAP8(x) be64toh(x)
64 #else
65 #define SWAP2(x) ( (((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8) )
66 #define SWAP4(x) (((x) >> 24)|(((x) & 0x00ff0000) >> 8)| \
67  (((x) & 0x0000ff00) << 8)|(((x) & 0x000000ff) << 24))
68 #define SWAP8(x) something... //TODO
69 #endif
70 #else
71 #define SWAP2(x) (x)
72 #define SWAP4(x) (x)
73 #define SWAP8(x) (x)
74 #endif
75 
76 #define IS_POW_OF_2(x) (\
77  ((x)!= 0)&& (((x)& ((x)- 1))== 0)\
78  )
79 
80 /* **** Implementations **** */
81 
82 bitparser_ctx_t* bitparser_open(void *buf, size_t buf_size)
83 {
84  register WORD_T word0;
85  int end_code= STAT_ERROR;
86  bitparser_ctx_t *bitparser_ctx= NULL;
87  LOG_CTX_INIT(NULL);
88 
89  /* Check arguments:
90  * - Buffer size MUST be multiple of 8 bytes
91  */
92  CHECK_DO(buf!= NULL, return NULL);
93  CHECK_DO(buf_size> 0 && SIZE_IS_MULTIPLE(buf_size, sizeof(WORD_T)),
94  return NULL);
95 
96  /* Allocate context structure */
97  bitparser_ctx= (bitparser_ctx_t*)calloc(1, sizeof(bitparser_ctx_t));
98  CHECK_DO(bitparser_ctx!= NULL, goto end);
99 
100  /* Initialize context structure members */
101  bitparser_ctx->buf= (WORD_T*)buf;
102  bitparser_ctx->buf_size= buf_size;
103  bitparser_ctx->bcnt= 0;
104  bitparser_ctx->word0= word0= SWAPW(((WORD_T*)buf)[0]);
105  bitparser_ctx->word1= SWAPW(((WORD_T*)buf)[1]);
106  bitparser_ctx->top= word0;
107 
108  end_code= STAT_SUCCESS;
109 end:
110  if(end_code!= STAT_SUCCESS)
111  bitparser_close(&bitparser_ctx);
112  return bitparser_ctx;
113 }
114 
115 void bitparser_close(bitparser_ctx_t **ref_bitparser_ctx)
116 {
117  bitparser_ctx_t *bitparser_ctx;
118  //LOG_CTX_INIT(NULL);
119 
120  if(ref_bitparser_ctx== NULL)
121  return;
122 
123  if((bitparser_ctx= *ref_bitparser_ctx)!= NULL) {
124  free(bitparser_ctx);
125  *ref_bitparser_ctx= NULL;
126  }
127 }
128 
129 void bitparser_flush(bitparser_ctx_t* bitparser_ctx, size_t n)
130 {
131  register WORD_T buf_size, bcnt, bcnt_new, wcnt, wcnt_new, word0, word1,
132  wcnt_max;
133  register const WORD_T *buf;
134  LOG_CTX_INIT(NULL);
135 
136  CHECK_DO(bitparser_ctx!= NULL, return);
137 
138  buf= bitparser_ctx->buf;
139  buf_size= bitparser_ctx->buf_size;
140  bcnt= bitparser_ctx->bcnt;
141  wcnt= bcnt>> DPATHW_SHIFTb;
142  bcnt_new= bcnt+ n;
143  bitparser_ctx->bcnt= bcnt_new;
144  wcnt_new= bcnt_new>> DPATHW_SHIFTb;
145  word0= bitparser_ctx->word0;
146  word1= bitparser_ctx->word1;
147  wcnt_max= buf_size>> DPATHW_SHIFTB;
148  CHECK_DO(wcnt_new<= wcnt_max, return);
149 
150  if(wcnt_new!= wcnt) {
151  bitparser_ctx->word0= word0= SWAPW(buf[wcnt_new% wcnt_max]);
152  bitparser_ctx->word1= word1= SWAPW(buf[(wcnt_new+ 1)% wcnt_max]);
153  }
154 
155  /* Notes:
156  * - Endianess requires "swapping" word0/1;
157  * - Buffer may read up to two words out-of-bounds circularly (harmless).
158  */
159  bitparser_ctx->top= SHL(word0, bcnt_new&(DPATHW-1))+
160  SHR(word1, DPATHW- (bcnt_new&(DPATHW-1)));
161 }
162 
163 WORD_T bitparser_get(bitparser_ctx_t* bitparser_ctx, size_t n)
164 {
165  WORD_T bits_value;
166  LOG_CTX_INIT(NULL);
167 
168  CHECK_DO(bitparser_ctx!= NULL, return 0);
169 
170  bits_value= (bitparser_ctx->top>> (DPATHW-n));
171  bitparser_flush(bitparser_ctx, n);
172  return bits_value;
173 }
174 
175 WORD_T bitparser_show(bitparser_ctx_t* bitparser_ctx, size_t n)
176 {
177  WORD_T bits_value;
178  LOG_CTX_INIT(NULL);
179 
180  CHECK_DO(bitparser_ctx!= NULL, return 0);
181 
182  bits_value= (bitparser_ctx->top>> (DPATHW-n));
183  return bits_value;
184 }
185 
186 void* bitparser_copy_bytes(bitparser_ctx_t* bitparser_ctx, size_t cnt)
187 {
188  register WORD_T bytecnt, buf_size, avail_size;
189  const uint8_t *pbuf= (uint8_t*)bitparser_ctx->buf;
190  void *p_ret= NULL;
191  int end_code= STAT_ERROR;
192  LOG_CTX_INIT(NULL);
193 
194  CHECK_DO(bitparser_ctx!= NULL, return NULL);
195  CHECK_DO(cnt> 0, return NULL);
196 
197  bytecnt= bitparser_ctx->bcnt>> 3;
198  buf_size= bitparser_ctx->buf_size;
199  CHECK_DO(bytecnt< buf_size, goto end);
200  avail_size= buf_size- bytecnt;
201  CHECK_DO(cnt<= avail_size, goto end);
202 
203  p_ret= malloc(EXTEND_SIZE_TO_MULTIPLE(cnt, sizeof(WORD_T)));
204  CHECK_DO(p_ret!= NULL, goto end);
205 
206  memcpy(p_ret, pbuf+ bytecnt, cnt);
207  bitparser_flush(bitparser_ctx, cnt<< 3);
208 
209  end_code= STAT_SUCCESS;
210 end:
211  if(end_code!= STAT_SUCCESS)
212  if(p_ret!= NULL)
213  free(p_ret);
214  return p_ret;
215 }
216 
218 {
219  register WORD_T bits_unaligned, bits2flush;
220  LOG_CTX_INIT(NULL);
221 
222  CHECK_DO(bitparser_ctx!= NULL, return);
223 
224  bits_unaligned= bitparser_ctx->bcnt& 7;
225  bits2flush= bits_unaligned? 8- bits_unaligned: 0;
226 
227  if(bits_unaligned> 0)
228  bitparser_flush(bitparser_ctx, bits2flush);
229 }
void * bitparser_copy_bytes(bitparser_ctx_t *bitparser_ctx, size_t cnt)
Definition: bitparser.c:186
WORD_T word0
Definition: bitparser.h:67
size_t buf_size
Definition: bitparser.h:59
void bitparser_flush(bitparser_ctx_t *bitparser_ctx, size_t n)
Definition: bitparser.c:129
#define EXTEND_SIZE_TO_MULTIPLE(SIZE, MULTIPLE)
Definition: mem_utils.h:52
WORD_T word1
Definition: bitparser.h:71
void bitparser_close(bitparser_ctx_t **ref_bitparser_ctx)
Definition: bitparser.c:115
WORD_T * buf
Definition: bitparser.h:55
WORD_T bitparser_show(bitparser_ctx_t *bitparser_ctx, size_t n)
Definition: bitparser.c:175
void bitparser_align_2byte(bitparser_ctx_t *bitparser_ctx)
Definition: bitparser.c:217
General status codes enumeration.
#define CHECK_DO(COND, ACTION)
Definition: check_utils.h:57
#define SIZE_IS_MULTIPLE(SIZE, MULTIPLE)
Definition: mem_utils.h:60
bitparser_ctx_t * bitparser_open(void *buf, size_t buf_size)
Definition: bitparser.c:82
WORD_T bitparser_get(bitparser_ctx_t *bitparser_ctx, size_t n)
Definition: bitparser.c:163
Bit parsing module utility.