-
Notifications
You must be signed in to change notification settings - Fork 0
/
bintex.h
367 lines (288 loc) · 12.2 KB
/
bintex.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/* Copyright 2010-2012, JP Norair
*
* Licensed under the OpenTag License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.indigresso.com/wiki/doku.php?id=opentag:license_1_0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file bintex.h
* @author JP Norair
* @version V1.0
* @date 13 May 2012
* @brief BinTex Parser, for clients with STD C libraries (i.e. POSIX)
* @defgroup BinTex
* @ingroup BinTex
*
* @note This version of BinTex is fully modular, with no other requirement.
*
* "BinTex" is a markup langauge (or in modern jargon a "markdown" language)
* for working with raw, byte-wise data. It allows integration of multiple
* input formats, and it will parse them into a big-endian / network-ordered
* binary stream.
*
* The official BinTex reference can be found on the included Wiki link. A
* quickstart reference is posted in the comments below.
* http://www.indigresso.com/wiki/
*
*
* Single Data Expressions: <BR>
* Single Data Expressions are of a consistent input format, and they are
* bounded by whitespace. Hex and Decimal input formats are available.
*
* 1. Variable Length Hex: (example, x098a52B248) <BR>
* In this mode, an ASCII string that starts with a leading "x" and ends with
* whitespace will be parsed as a single hex data stream. Valid characters
* are 0-9, a-f, and A-F. Non valid characters will be converted to 0. The
* hex stream terminates when the next character read is whitespace or an end-
* bracket "]".
*
* 2. 8/16/32 bit integer: (examples, d9, d-13252, d8uc, d8l ...)
* An ASCII string that starts with a leading "d" and ends with whitespace will
* be parsed as a single decimal number. Valid chars are digits (0-9) and
* minus sign (-). Supplied numerals are parsed into 8, 16, or 32 bits. The
* parser will use the minimum container to fit the supplied number unless you
* explicitly specify a type-code at the end of the number. The parser will
* consider the number terminated after it reads whitespace, an end-parenthesis
* ")" or a supported type-code.
*
* Supported Integer Type-code characters: <BR>
* - u: unsigned (must be first) <BR>
* - c: char (8 bits) <BR>
* - s: short (16 bits) <BR>
* - l: long (32 bits)
*
* Supported Integer Type-codes:
* - [none]: signed, implicit length <BR>
* - u: unsigned, implicit length <BR>
* - uc: unsigned 8 bits <BR>
* - us: unsigned 16 bits <BR>
* - ul: unsigned 32 bits <BR>
* - c: signed, 8 bits <BR>
* - s: signed, 16 bits <BR>
* - l: signed, 32 bits <BR>
*
*
* Multiple data expressions: <BR>
* Multiple data expressions are bounded by open and close characters (such as
* [], (), and ""). Whitespace can exist inside the open and close characters.
*
* 1. Multiple Hex expression: <BR>
* Use the square brackets [] to enclose one or more hex sequences. Inside the
* brackets, the leading "x" is not included. Therefore, an example can be:
* [0346 83c6 35 2b89 28a860f3]. If you want to load items from a struct,
* this format can make it easier, since each element is separated.
*
* 2. Multiple Integer Expression: <BR>
* Use the parenthesis () to enclose one or more decimal integers. An example
* can be (84 13 -93s 25026ul).
*
* 3. ASCII string: <BR>
* Use the double-quotes "" to enclose an ASCII string. The escape sequence
* is the backslash \, and the input rules are the same as those from printf.
******************************************************************************
*/
#ifndef __BINTEX_H
#define __BINTEX_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
//#define __DEBUG__
/** @typedef Queue
*
* The Queue data type does not contain the data in the queues themselves, just
* information on how to get that data as well as any other useful variables.
*
* uint16_t alloc Allocation of the queue data, in bytes
*
* uint16_t length The current extent of the queue data, in bytes
* Twobytes options User flags
* uint8_t* front First address of queue data
* uint8_t* back Used for boundary checking (user adjustable)
* uint8_t* getcursor Cursor address for reading from queue
* uint8_t* putcursor Cursor address for writing to queue
*/
typedef struct {
int alloc;
uint16_t options;
uint8_t* getcursor;
uint8_t* putcursor;
uint8_t* front;
uint8_t* back;
} bintex_q;
/** @brief Parse a complete Bintex File, outputting binary to stream
* @param file (FILE*) input file, nominally encoded as UTF-8
* @param stream_out (unsigned char*) byte-wise, binary output stream
* @param size (int) allocation limit of stream_out
* @retval (int) negative on error, else number of bytes output to stream
* @ingroup BinTex
* @sa bintex_ss()
*/
int bintex_fs(FILE* file, unsigned char* stream_out, int size);
/** @brief Parse a complete Bintex null-terminated string, outputting binary to stream
* @param string (unsigned char*) input string
* @param stream_out (unsigned char*) byte-wise, binary output stream
* @param size (int) allocation limit of stream_out
* @retval (int) negative on error, else number of bytes output to stream
* @ingroup BinTex
* @sa bintex_fs()
*
* @note bintex_ss() will increment the string pointer (*string)
*/
int bintex_ss(unsigned char* string, unsigned char* stream_out, int size);
/** @brief Iteratively parses a Bintex File, outputting to persistent Queue
* @param file (FILE*) input file, nominally encoded as UTF-8
* @param msg (Queue*) output Queue of binary datastream
* @retval (int) negative on error, else number of bytes written to queue
* @ingroup BinTex
* @sa bintex_iter_sq
*
* This function is different from bintex_fs() because it will return after
* parsing each input BinTex expression in the file. The File and Queue
* objects should be retained by the caller/user.
*/
int bintex_iter_fq(FILE* file, bintex_q* msg);
/** @brief Iteratively parses a Bintex null-terminated string, outputting to persistent Queue
* @param string (unsigned char**) input string handle
* @param msg (Queue*) output Queue of binary datastream
* @retval (int) negative on error, else number of bytes written to queue
* @ingroup BinTex
* @sa bintex_iter_fq
*
* This function is different from bintex_ss() because it will return after
* parsing each input BinTex expression in the input string. The String and
* Queue objects should be retained by the caller/user.
*/
int bintex_iter_sq(unsigned char** string, bintex_q* msg, int size);
// Input Parser Tester
#ifdef __DEBUG__
int main(int argc, char** argv);
#endif
///@note I'm not sure what was the intent of exposing these queue prototypes
#ifdef Q_PROTOTYPES
/** @brief Generic initialization routine for Queues.
* @param q (bintex_q*) Pointer to the Queue ADT
* @param buffer (uint8_t*) Queue data buffer
* @param alloc (uint16_t) allocated bytes for queue
* @retval none
* @ingroup Queue
*/
void q_init(bintex_q* q, uint8_t* buffer, uint16_t alloc);
/** @brief Reposition the Queue pointers to a new buffer, don't change attributes
* @param q (bintex_q*) Pointer to the Queue ADT
* @param buffer (uint8_t*) Queue data buffer
* @retval none
* @ingroup Queue
*
* Most commonly used when multiple frames are in the same queue.
*/
void q_rebase(bintex_q* q, uint8_t* buffer);
/** @brief Copies one Queue "object" to another, without copying the data
* @param q1 (bintex_q*) Queue to copy into
* @param q2 (bintex_q*) Queue to copy from
* @retval none
* @ingroup Queue
*/
void q_copy(bintex_q* q1, bintex_q* q2);
/** @brief Returns the length of the queue
* @param q (bintex_q*) Queue to determine length
* @retval none
* @ingroup Queue
*/
int16_t q_length(bintex_q* q);
int16_t q_span(bintex_q* q);
int16_t q_space(bintex_q* q);
/** @brief Empties the supplied Queue, but doesn't actually erase data
* @param q (bintex_q*) Pointer to the Queue ADT
* @retval none
* @ingroup Queue
*/
void q_empty(bintex_q* q);
/** @brief Starts a queue by loading in config data
* @param q (bintex_q*) Pointer to the Queue ADT
* @param offset (int) bytes to offset the fist data writes from the front
* @param options (uint16_t) option bits. user-defined usage.
* @retval uint8_t* Pointer to queue get & putcursor, or NULL if an error
* @ingroup Queue
*/
uint8_t* q_start(bintex_q* q, int offset, uint16_t options);
/** @brief Returns the current getcursor position, and then moves it forward
* @param q (bintex_q*) Pointer to the Queue ADT
* @param shift (int) bytes to move getcursor forward
* @retval uint8_t* Pointer to getcursor at original position
* @ingroup Queue
*/
uint8_t* q_markbyte(bintex_q* q, int shift);
/** @brief Writes a byte to a Queue's putcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @param byte_in (uint8_t) byte to write
* @retval none
* @ingroup Queue
*/
void q_writebyte(bintex_q* q, uint8_t byte_in);
/** @brief Writes a 16 bit short integer to the Queue's putcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @param short_in (uint16_t) Short integer to write
* @retval none
* @ingroup Queue
* @note The _be variant will use big endian, which is fast for copying data
* from the UDB, given that the UDB is big endian and DASH7 also uses big
* endian for data streams. The normal variant will do endian conversion
* in order to move integers from memory to the queue.
*/
void q_writeshort(bintex_q* q, uint16_t short_in);
void q_writeshort_be(bintex_q* q, uint16_t short_in);
/** @brief Writes a 32 bit long integer to the Queue's putcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @param long_in (uint32_t) Long integer to write
* @retval none
* @ingroup Queue
* @note The _be variant will use big endian, which is fast for copying data
* from the UDB, given that the UDB is big endian and DASH7 also uses big
* endian for data streams. The normal variant will do endian conversion
* in order to move integers from memory to the queue.
*/
void q_writelong(bintex_q* q, uint32_t long_in);
/** @brief Reads a byte at the Queue's getcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @retval uint8_t Byte read
* @ingroup Queue
*/
uint8_t q_readbyte(bintex_q* q);
/** @brief Reads a 16 bit short integer at the Queue's getcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @retval uint16_t Short integer read.
* @ingroup Queue
* @note The _be variant will use big endian, which is fast for copying data
* from the UDB, given that the UDB is big endian and DASH7 also uses big
* endian for data streams. The normal variant will do endian conversion
* in order to move integers from memory to the queue.
*/
uint16_t q_readshort(bintex_q* q);
uint16_t q_readshort_be(bintex_q* q);
/** @brief Reads a 32 bit long integer at the Queue's getcursor, and advances it
* @param q (bintex_q*) Pointer to the Queue ADT
* @retval uint32_t Long integer read.
* @ingroup Queue
* @note The _be variant will use big endian, which is fast for copying data
* from the UDB, given that the UDB is big endian and DASH7 also uses big
* endian for data streams. The normal variant will do endian conversion
* in order to move integers from memory to the queue.
*/
uint32_t q_readlong(bintex_q* q);
void q_writestring(bintex_q* q, uint8_t* string, int length);
void q_readstring(bintex_q* q, uint8_t* string, int length);
#endif
#ifdef __cplusplus
}
#endif
#endif