Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Baranyi, Botond | |
12 | * Forstner, Matyas | |
13 | * Kovacs, Ferenc | |
14 | * Raduly, Csaba | |
15 | * Szabados, Kristof | |
16 | * Szabo, Janos Zoltan – initial implementation | |
17 | * Szalai, Gabor | |
18 | * | |
19 | ******************************************************************************/ | |
970ed795 EL |
20 | #ifndef ENCDEC_HH |
21 | #define ENCDEC_HH | |
22 | ||
23 | #include "Types.h" | |
24 | ||
25 | typedef const unsigned char cbyte; | |
26 | ||
27 | ||
28 | class OCTETSTRING; | |
29 | class CHARSTRING; | |
30 | class UNIVERSAL_CHARSTRING; | |
31 | struct RAW_coding_par; | |
32 | ||
33 | /** Endianness indicator */ | |
34 | enum raw_order_t { | |
35 | ORDER_MSB, | |
36 | ORDER_LSB | |
37 | }; | |
38 | ||
39 | /** | |
40 | * Static class which encapsulates the stuff related to | |
41 | * encoding/decoding. | |
42 | */ | |
43 | class TTCN_EncDec { | |
44 | public: | |
45 | /** Coding types. */ | |
46 | enum coding_t { | |
47 | CT_BER, /**< BER */ | |
48 | CT_PER, /**< PER */ | |
49 | CT_RAW, /**< RAW */ | |
50 | CT_TEXT, /**< TEXT */ | |
51 | CT_XER, /**< XER */ | |
52 | CT_JSON /**< JSON */ | |
53 | }; | |
54 | /** Error type enum type. If you want to add new values, please put | |
55 | * them before ET_ALL. Values must be consecutive, starting at zero. | |
56 | * When adding a new value, a corresponding string (without "ET_") | |
57 | * must be added to compiler2/ttcn3/Ttcnstuff.cc */ | |
58 | enum error_type_t { | |
59 | ET_UNDEF = 0, /**< Undefined error. */ | |
60 | ET_UNBOUND = 1, /**< Encoding of an unbound value. */ | |
61 | ET_INCOMPL_ANY, /**< Encoding of an ASN ANY value which does not | |
62 | contain a valid BER TLV. */ | |
63 | ET_ENC_ENUM, /**< Encoding of an unknown enumerated value. */ | |
64 | ET_INCOMPL_MSG, /**< Decode error: incomplete message. */ | |
65 | ET_LEN_FORM, /**< During decoding: the received message has a | |
66 | non-acceptable length form (BER). 5*/ | |
67 | ET_INVAL_MSG, /**< Decode error: invalid message. */ | |
68 | ET_REPR, /**< Representation error, e.g.: internal | |
69 | representation of integral numbers. */ | |
70 | ET_CONSTRAINT, /**< The value breaks some constraint. */ | |
71 | ET_TAG, /**< During decoding: unexpected tag. */ | |
72 | ET_SUPERFL, /**< During decoding: superfluous part | |
73 | detected. In case of BER, this can be | |
74 | superfluous TLV at the end of a constructed | |
75 | TLV. 10 */ | |
76 | ET_EXTENSION, /**< During decoding: there was something in the | |
77 | extension (e.g.: in ASN.1 ellipsis). */ | |
78 | ET_DEC_ENUM, /**< During decoding of an (inextensible) | |
79 | enumerated value: unknown value received. */ | |
80 | ET_DEC_DUPFLD, /**< During decoding: duplicated field. For | |
81 | example, while decoding a SET type. */ | |
82 | ET_DEC_MISSFLD, /**< During decoding: missing field. For example, | |
83 | while decoding a SET type. */ | |
84 | ET_DEC_OPENTYPE, /**< Cannot decode an opentype (broken component | |
85 | relation constraint). 15 */ | |
86 | ET_DEC_UCSTR, /**< During decoding a universal charstring: | |
87 | something went wrong. */ | |
88 | ET_LEN_ERR, /**< During RAW encoding: the specified field | |
89 | length is not enough to encode the value of | |
90 | the field. During RAW decoding: the available | |
91 | number of bits is less than it needed to | |
92 | decode the field. */ | |
93 | ET_SIGN_ERR, /**< Unsigned encoding of a negative number. */ | |
94 | ET_INCOMP_ORDER, /**< Incompatible combination of orders attribute | |
95 | for RAW coding. */ | |
96 | ET_TOKEN_ERR, /**< During TEXT decoding the specified token is | |
97 | not found. 20 */ | |
98 | ET_LOG_MATCHING, /**< During TEXT decoding the matching is logged | |
99 | if the behavior was set to EB_WARNING. */ | |
100 | ET_FLOAT_TR, /**< The float value will be truncated during | |
101 | double -> single precision conversion */ | |
102 | ET_FLOAT_NAN, /**< Not a Number has been received */ | |
103 | ET_OMITTED_TAG, /**< During encoding the key of a tag references | |
104 | an optional field with omitted value */ | |
105 | ET_NEGTEST_CONFL, /**< Contradictory negative testing and RAW attributes. */ | |
106 | ET_ALL, /**< Used only when setting error behavior. 25 */ | |
107 | ET_INTERNAL, /**< Internal error. Error behavior cannot be set | |
108 | for this. */ | |
109 | ET_NONE /**< There was no error. */ | |
110 | }; | |
111 | /** Error behavior enum type. */ | |
112 | enum error_behavior_t { | |
113 | EB_DEFAULT, /**< Used only when setting error behavior. */ | |
114 | EB_ERROR, /**< Raises an error. */ | |
115 | EB_WARNING, /**< Logs the error but continues the activity. */ | |
116 | EB_IGNORE /**< Totally ignores the error. */ | |
117 | }; | |
118 | ||
119 | /** @brief Set the error behaviour for encoding/decoding functions | |
120 | * | |
121 | * @param p_et error type | |
122 | * @param p_eb error behaviour | |
123 | */ | |
124 | static void set_error_behavior(error_type_t p_et, error_behavior_t p_eb); | |
125 | ||
126 | /** @brief Get the current error behaviour | |
127 | * | |
128 | * @param p_et error type | |
129 | * @return error behaviour for the supplied error type | |
130 | */ | |
131 | static error_behavior_t get_error_behavior(error_type_t p_et); | |
132 | ||
133 | /** @brief Get the default error behaviour | |
134 | * | |
135 | * @param p_et error type | |
136 | * @return default error behaviour for the supplied error type | |
137 | */ | |
138 | static error_behavior_t get_default_error_behavior(error_type_t p_et); | |
139 | ||
140 | /** @brief Get the last error code. | |
141 | * | |
142 | * @return last_error_type | |
143 | */ | |
144 | static error_type_t get_last_error_type() { return last_error_type; } | |
145 | ||
146 | /** @brief Get the error string corresponding to the last error. | |
147 | * | |
148 | * @return error_str | |
149 | */ | |
150 | static const char* get_error_str() { return error_str; } | |
151 | ||
152 | /** @brief Set a clean slate | |
153 | * | |
154 | * Sets last_error_type to ET_NONE. | |
155 | * Frees error_str. | |
156 | */ | |
157 | static void clear_error(); | |
158 | ||
159 | /* The stuff below this line is for internal use only */ | |
160 | static void error(error_type_t p_et, char *msg); | |
161 | ||
162 | private: | |
163 | /** Default error behaviours for all error types */ | |
164 | static const error_behavior_t default_error_behavior[ET_ALL]; | |
165 | ||
166 | /** Current error behaviours for all error types */ | |
167 | static error_behavior_t error_behavior[ET_ALL]; | |
168 | ||
169 | /** Last error value */ | |
170 | static error_type_t last_error_type; | |
171 | ||
172 | /** Error string for the last error */ | |
173 | static char *error_str; | |
174 | }; | |
175 | ||
176 | /** @brief Error context | |
177 | * | |
178 | * Maintains a list of linked TTCN_EncDec_ErrorContext objects | |
179 | * | |
180 | */ | |
181 | class TTCN_EncDec_ErrorContext { | |
182 | private: | |
183 | /** Variables for the linked list */ | |
184 | static TTCN_EncDec_ErrorContext *head, *tail; | |
185 | ||
186 | /** Pointers for the linked list */ | |
187 | TTCN_EncDec_ErrorContext *prev, *next; | |
188 | ||
189 | /** */ | |
190 | char *msg; | |
191 | /// Copy constructor disabled | |
192 | TTCN_EncDec_ErrorContext(const TTCN_EncDec_ErrorContext&); | |
193 | /// Assignment disabled | |
194 | TTCN_EncDec_ErrorContext& operator=(const TTCN_EncDec_ErrorContext&); | |
195 | public: | |
196 | /** @brief Default constructor. | |
197 | * | |
198 | * Adds this object of the end of the list | |
199 | * | |
200 | * @post msg == 0 | |
201 | * @post tail == this | |
202 | * | |
203 | */ | |
204 | TTCN_EncDec_ErrorContext(); | |
205 | ||
206 | /** @brief Constructor. | |
207 | * | |
208 | * Adds this object of the end of the list | |
209 | * and sets msg. | |
210 | * | |
211 | * @post msg != 0 | |
212 | * @post tail == this | |
213 | * | |
214 | * @param fmt printf-like format string | |
215 | * @param ... printf-like parameters | |
216 | */ | |
217 | TTCN_EncDec_ErrorContext(const char *fmt, ...) | |
218 | __attribute__ ((__format__ (__printf__, 2, 3))); // 'this' is at index 1 | |
219 | ||
220 | /** @brief Destructor. | |
221 | * | |
222 | * Removes this object from the end of the list | |
223 | * | |
224 | * @pre tail == this | |
225 | * | |
226 | */ | |
227 | ~TTCN_EncDec_ErrorContext(); | |
228 | ||
229 | /** @brief Replaces msg with a new string | |
230 | * | |
231 | * Calls Free, then mprintf_va_list | |
232 | * | |
233 | * @param fmt printf-like format string | |
234 | * @param ... printf-like parameters | |
235 | */ | |
236 | void set_msg(const char *fmt, ...) | |
237 | __attribute__ ((__format__ (__printf__, 2, 3))); // 'this' is at index 1 | |
238 | ||
239 | /** @brief Collects error strings from all active error contexts and logs an error | |
240 | * | |
241 | * If the error behaviour for \p p_et is not TTCN_EncDec::EB_IGNORE, then | |
242 | * walks the list of TTCN_EncDec_ErrorContext and concatenates the error messages, | |
243 | * then calls TTCN_EncDec::error | |
244 | * | |
245 | * @param p_et a TTCN_EncDec::error_type_t error type | |
246 | * @param fmt printf-like format string | |
247 | * @param ... printf-like parameters | |
248 | * | |
249 | */ | |
250 | static void error(TTCN_EncDec::error_type_t p_et, const char *fmt, ...) | |
251 | __attribute__ ((__format__ (__printf__, 2, 3))); | |
252 | static void error_internal(const char *fmt, ...) | |
253 | __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__)); | |
254 | static void warning(const char *fmt, ...) | |
255 | __attribute__ ((__format__ (__printf__, 1, 2))); | |
256 | }; | |
257 | ||
258 | /** | |
259 | * Buffer used by the different encoders/decoders. | |
260 | */ | |
261 | class TTCN_Buffer { | |
262 | private: | |
263 | struct buffer_struct; // no user serviceable parts | |
264 | buffer_struct *buf_ptr; ///< pointer to internal data | |
265 | size_t buf_size;///< The number of bytes of memory allocated | |
266 | size_t buf_len; ///< The number of bytes of memory used (buf_len <= buf_size) | |
267 | size_t buf_pos; ///< Read offset in bytes in the buffer (buf_pos <= buf_len) | |
268 | size_t bit_pos; ///< Read offset of the current bit inside the byte at buf_pos | |
269 | size_t last_bit_pos; | |
270 | size_t last_bit_bitpos; | |
271 | size_t start_of_ext_bit; | |
272 | boolean last_bit; ///< the state of the "last bit" (only after get_b was called) | |
273 | boolean current_bitorder; ///< \c true for TOP_BIT_LEFT | |
274 | boolean ext_bit_reverse; ///< \c true if 0 signals the end | |
275 | unsigned int ext_level; | |
276 | ||
277 | /** Resets all fields except the size and length indicators. */ | |
278 | void reset_buffer(); | |
279 | /** Deallocates the memory area that is associated with the buffer. */ | |
280 | void release_memory(); | |
281 | /** Returns the smallest preferred size of the allocated memory area | |
282 | * that is at least \a target_size. */ | |
283 | static size_t get_memory_size(size_t target_size); | |
284 | /** Ensures that buffer has its own writable memory area. */ | |
285 | void copy_memory(); | |
286 | /** Ensures that there are at least \a target_size writable bytes in the | |
287 | * memory area after \a buf_len. */ | |
288 | void increase_size(size_t size_incr); | |
289 | ||
290 | public: | |
291 | /** Creates an empty buffer. */ | |
292 | TTCN_Buffer(); | |
293 | /** Copy constructor. */ | |
294 | TTCN_Buffer(const TTCN_Buffer& p_buf); | |
295 | /** Initializes the buffer with the contents of \a p_os. | |
296 | * @pre The argument must be bound. */ | |
297 | TTCN_Buffer(const OCTETSTRING& p_os); | |
298 | /** Initializes the buffer with the contents of \a p_cs. | |
299 | * @pre The argument must be bound. */ | |
300 | TTCN_Buffer(const CHARSTRING& p_cs); | |
301 | /** Destructor. */ | |
302 | ~TTCN_Buffer() { release_memory(); } | |
303 | /** Copies the contents of \a p_buf into \a this. | |
304 | * The read pointers and other attributes are reset. */ | |
305 | TTCN_Buffer& operator=(const TTCN_Buffer& p_buf); | |
306 | /** Copies the contents of \a p_os into \a this. | |
307 | * The read pointers and other attributes are reset. */ | |
308 | TTCN_Buffer& operator=(const OCTETSTRING& p_os); | |
309 | /** Copies the contents of \a p_cs into \a this. | |
310 | * The read pointers and other attributes are reset. */ | |
311 | TTCN_Buffer& operator=(const CHARSTRING& p_cs); | |
312 | /** Erases the content of the buffer. */ | |
313 | void clear(); | |
314 | /** Returns how many bytes are in the buffer. */ | |
315 | inline size_t get_len() const { return buf_len; } | |
316 | /** Returns a pointer to the beginning of data. */ | |
317 | const unsigned char* get_data() const; | |
318 | /** Returns how many bytes are in the buffer to read. */ | |
319 | inline size_t get_read_len() const { return buf_len - buf_pos; } | |
320 | /** Returns a pointer which points to read position of data. */ | |
321 | const unsigned char* get_read_data() const; | |
322 | /** Sets the read position to the beginning of the buffer. */ | |
323 | inline void rewind() { buf_pos = 0; bit_pos = 0; } | |
324 | /** Returns the (reading) position of the buffer. */ | |
325 | inline size_t get_pos() const { return buf_pos; } | |
326 | /** Sets the (reading) position to \a pos, or to the end of buffer, | |
327 | * if pos > len. */ | |
328 | void set_pos(size_t pos); | |
329 | /** Increases the (reading) position by \a delta, or sets it to the | |
330 | * end of buffer, if get_pos() + delta > len. */ | |
331 | void increase_pos(size_t delta); | |
332 | /** You can write up to \a end_len chars beginning from \a end_ptr; | |
333 | * after writing, you have to call also increase_length()! Useful | |
334 | * if you want to use memcpy. @see increase_length(). \param | |
335 | * end_ptr out. \param end_len inout. */ | |
336 | void get_end(unsigned char*& end_ptr, size_t& end_len); | |
337 | /** How many chars have you written after a get_end(), beginning | |
338 | * from end_ptr. @see get_end() */ | |
339 | void increase_length(size_t size_incr); | |
340 | /** Appends single character \a c to the buffer. */ | |
341 | void put_c(unsigned char c); | |
342 | /** Appends \a len bytes starting from address \a s to the buffer. */ | |
343 | void put_s(size_t len, const unsigned char *s); | |
344 | /** Appends the contents of octetstring \a p_os to the buffer. */ | |
345 | void put_string(const OCTETSTRING& p_os); | |
346 | /** Same as \a put_string(). Provided only for backward compatibility. */ | |
347 | inline void put_os(const OCTETSTRING& p_os) { put_string(p_os); } | |
348 | /** Appends the contents of charstring \a p_cs to the buffer. */ | |
349 | void put_string(const CHARSTRING& p_cs); | |
350 | /** Same as \a put_string(). Provided only for backward compatibility. */ | |
351 | inline void put_cs(const CHARSTRING& p_cs) { put_string(p_cs); } | |
352 | /** Appends the content of \a p_buf to the buffer */ | |
353 | void put_buf(const TTCN_Buffer& p_buf); | |
354 | /** Stores the current contents of the buffer to variable \a p_os. */ | |
355 | void get_string(OCTETSTRING& p_os); | |
356 | /** Stores the current contents of the buffer to variable \a p_cs. */ | |
357 | void get_string(CHARSTRING& p_cs); | |
358 | /** Stores the current contents of the buffer to variable \a p_cs. */ | |
359 | void get_string(UNIVERSAL_CHARSTRING& p_cs); | |
360 | /** Cuts the bytes between the beginning of the buffer and the read | |
361 | * position. After that the read position will point to the beginning | |
362 | * of the updated buffer. */ | |
363 | void cut(); | |
364 | /** Cuts the bytes between the read position and the end of the buffer. | |
365 | * The read position remains unchanged (i.e. it will point to the end | |
366 | * of the truncated buffer. */ | |
367 | void cut_end(); | |
368 | /** Returns whether the buffer (beginning from the read position) | |
369 | * contains a complete TLV. */ | |
370 | boolean contains_complete_TLV(); | |
371 | ||
372 | /* The members below this line are for internal use only. */ | |
373 | /* ------------------------------------------------------ */ | |
374 | ||
375 | void log() const; | |
376 | ||
377 | /** Puts a bit string in the buffer. Use only this function if you | |
378 | * use the buffer as bit buffer. | |
379 | * | |
380 | * @param len number of _bits_ to write | |
381 | * @param s pointer to the data (bytes) | |
382 | * @param coding_par | |
383 | * @param align alignment length (in ???) | |
384 | */ | |
385 | void put_b(size_t len, const unsigned char *s, | |
386 | const RAW_coding_par& coding_par, int align); | |
387 | /** Reads a bit string from the buffer. Use only this function if you | |
388 | * use the buffer as bit buffer. */ | |
389 | void get_b(size_t len, unsigned char *s, const RAW_coding_par& coding_par, | |
390 | raw_order_t top_bit_order); | |
391 | /** Puts @p len number of zeros in the buffer. */ | |
392 | void put_zero(size_t len, raw_order_t fieldorder); | |
393 | /** Returns a pointer which points to read position of data and the | |
394 | * starting position of the bitstring within first the octet. */ | |
395 | const unsigned char* get_read_data(size_t& bitpos) const; | |
396 | /** Sets the (reading) position to \a pos and the bit position to \a | |
397 | * bit_pos, or to the end of buffer, if pos > len. */ | |
398 | void set_pos(size_t pos, size_t bitpos); | |
399 | /** Sets the (reading) position to \a pos | |
400 | * or to the end of buffer, if pos > len. */ | |
401 | void set_pos_bit(size_t new_bit_pos); | |
402 | /** Returns the (reading) position of the buffer in bits. */ | |
403 | inline size_t get_pos_bit() const { return buf_pos * 8 + bit_pos; } | |
404 | /** Increases the (reading) position by \a delta bits, or sets it to | |
405 | * the end of buffer, if get_pos() + delta > len. */ | |
406 | void increase_pos_bit(size_t delta); | |
407 | /** Increases the (reading) position to a multiple of \p padding. | |
408 | * @return the number of bits used up. */ | |
409 | int increase_pos_padd(int padding); | |
410 | /** Returns the number of bits remaining in the buffer */ | |
411 | size_t unread_len_bit(); | |
412 | /** Mark the start of extension bit processing during encoding. */ | |
413 | void start_ext_bit(boolean p_reverse); | |
414 | /** Apply the extension bit to the encoded bytes. */ | |
415 | void stop_ext_bit(); | |
416 | inline boolean get_order() const { return current_bitorder; } | |
417 | inline void set_order(boolean new_order) { current_bitorder = new_order; } | |
418 | void put_pad(size_t len, const unsigned char *s, int pat_len, | |
419 | raw_order_t fieldorder); | |
420 | void set_last_bit(boolean p_last_bit); | |
421 | inline boolean get_last_bit() const { return last_bit; } | |
422 | ||
423 | private: | |
424 | static unsigned char get_byte_rev(const unsigned char* data, size_t len, | |
425 | size_t index); | |
426 | unsigned char get_byte_align(size_t len, raw_order_t fieldorder, | |
427 | raw_order_t req_align ,size_t index); | |
428 | }; | |
429 | ||
430 | #endif |