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 | * Balasko, Jeno | |
10 | * Baranyi, Botond | |
11 | * Feher, Csaba | |
12 | * Forstner, Matyas | |
13 | * Ormandi, Matyas | |
14 | * Raduly, Csaba | |
15 | * Szabados, Kristof | |
16 | * Szabo, Janos Zoltan – initial implementation | |
17 | * Szalai, Gabor | |
18 | * Zalanyi, Balazs Andor | |
19 | * | |
20 | ******************************************************************************/ | |
970ed795 EL |
21 | #include "Encdec.hh" |
22 | ||
23 | #include "../common/memory.h" | |
24 | #include "Octetstring.hh" | |
25 | #include "Charstring.hh" | |
26 | #include "String_struct.hh" | |
27 | #include "RAW.hh" | |
28 | #include "Error.hh" | |
29 | #include "Logger.hh" | |
30 | ||
31 | const TTCN_EncDec::error_behavior_t | |
32 | TTCN_EncDec::default_error_behavior[TTCN_EncDec::ET_ALL] = { | |
33 | TTCN_EncDec::EB_ERROR, | |
34 | TTCN_EncDec::EB_ERROR, | |
35 | TTCN_EncDec::EB_ERROR, | |
36 | TTCN_EncDec::EB_WARNING, | |
37 | TTCN_EncDec::EB_ERROR, | |
38 | TTCN_EncDec::EB_WARNING, | |
39 | TTCN_EncDec::EB_ERROR, | |
40 | TTCN_EncDec::EB_WARNING, | |
41 | TTCN_EncDec::EB_WARNING, | |
42 | TTCN_EncDec::EB_ERROR, | |
43 | TTCN_EncDec::EB_ERROR, | |
44 | TTCN_EncDec::EB_ERROR, | |
45 | TTCN_EncDec::EB_ERROR, | |
46 | TTCN_EncDec::EB_ERROR, | |
47 | TTCN_EncDec::EB_WARNING, | |
48 | TTCN_EncDec::EB_WARNING, | |
49 | TTCN_EncDec::EB_WARNING, | |
50 | TTCN_EncDec::EB_ERROR, | |
51 | TTCN_EncDec::EB_ERROR, | |
52 | TTCN_EncDec::EB_ERROR, | |
53 | TTCN_EncDec::EB_ERROR, | |
54 | TTCN_EncDec::EB_IGNORE, | |
55 | TTCN_EncDec::EB_WARNING, | |
56 | TTCN_EncDec::EB_ERROR, | |
57 | TTCN_EncDec::EB_ERROR | |
58 | }; | |
59 | ||
60 | TTCN_EncDec::error_behavior_t | |
61 | TTCN_EncDec::error_behavior[TTCN_EncDec::ET_ALL] = { | |
62 | TTCN_EncDec::EB_ERROR, | |
63 | TTCN_EncDec::EB_ERROR, | |
64 | TTCN_EncDec::EB_ERROR, | |
65 | TTCN_EncDec::EB_WARNING, | |
66 | TTCN_EncDec::EB_ERROR, | |
67 | TTCN_EncDec::EB_WARNING, | |
68 | TTCN_EncDec::EB_ERROR, | |
69 | TTCN_EncDec::EB_WARNING, | |
70 | TTCN_EncDec::EB_WARNING, | |
71 | TTCN_EncDec::EB_ERROR, | |
72 | TTCN_EncDec::EB_ERROR, | |
73 | TTCN_EncDec::EB_ERROR, | |
74 | TTCN_EncDec::EB_ERROR, | |
75 | TTCN_EncDec::EB_ERROR, | |
76 | TTCN_EncDec::EB_WARNING, | |
77 | TTCN_EncDec::EB_WARNING, | |
78 | TTCN_EncDec::EB_WARNING, | |
79 | TTCN_EncDec::EB_ERROR, | |
80 | TTCN_EncDec::EB_ERROR, | |
81 | TTCN_EncDec::EB_ERROR, | |
82 | TTCN_EncDec::EB_ERROR, | |
83 | TTCN_EncDec::EB_IGNORE, | |
84 | TTCN_EncDec::EB_WARNING, | |
85 | TTCN_EncDec::EB_ERROR, | |
86 | TTCN_EncDec::EB_ERROR | |
87 | }; | |
88 | ||
89 | TTCN_EncDec::error_type_t TTCN_EncDec::last_error_type=ET_NONE; | |
90 | char *TTCN_EncDec::error_str=NULL; | |
91 | ||
92 | static TTCN_EncDec::error_type_t& operator++(TTCN_EncDec::error_type_t& eb) | |
93 | { | |
94 | return eb | |
95 | =(eb==TTCN_EncDec::ET_NONE) | |
96 | ?TTCN_EncDec::ET_UNDEF | |
97 | :TTCN_EncDec::error_type_t(eb+1); | |
98 | } | |
99 | ||
100 | void TTCN_EncDec::set_error_behavior(error_type_t p_et, error_behavior_t p_eb) | |
101 | { | |
102 | if(p_et<ET_UNDEF || p_et>ET_ALL || p_eb<EB_DEFAULT || p_eb>EB_IGNORE) | |
103 | TTCN_error("EncDec::set_error_behavior(): Invalid parameter."); | |
104 | if(p_eb==EB_DEFAULT) { | |
105 | if(p_et==ET_ALL) | |
106 | for(error_type_t i=ET_UNDEF; i<ET_ALL; ++i) | |
107 | error_behavior[i]=default_error_behavior[i]; | |
108 | else | |
109 | error_behavior[p_et]=default_error_behavior[p_et]; | |
110 | } | |
111 | else { | |
112 | if(p_et==ET_ALL) | |
113 | for(error_type_t i=ET_UNDEF; i<ET_ALL; ++i) | |
114 | error_behavior[i]=p_eb; | |
115 | else | |
116 | error_behavior[p_et]=p_eb; | |
117 | } | |
118 | } | |
119 | ||
120 | TTCN_EncDec::error_behavior_t | |
121 | TTCN_EncDec::get_error_behavior(error_type_t p_et) | |
122 | { | |
123 | if(p_et<ET_UNDEF || p_et>=ET_ALL) | |
124 | TTCN_error("EncDec::get_error_behavior(): Invalid parameter."); | |
125 | return error_behavior[p_et]; | |
126 | } | |
127 | ||
128 | TTCN_EncDec::error_behavior_t | |
129 | TTCN_EncDec::get_default_error_behavior(error_type_t p_et) | |
130 | { | |
131 | if(p_et<ET_UNDEF || p_et>=ET_ALL) | |
132 | TTCN_error("EncDec::get_error_behavior(): Invalid parameter."); | |
133 | return default_error_behavior[p_et]; | |
134 | } | |
135 | ||
136 | void TTCN_EncDec::clear_error() | |
137 | { | |
138 | last_error_type=ET_NONE; | |
139 | Free(error_str); error_str=NULL; | |
140 | } | |
141 | ||
142 | void TTCN_EncDec::error(error_type_t p_et, char *msg) | |
143 | { | |
144 | last_error_type=p_et; | |
145 | Free(error_str); | |
146 | error_str=msg; | |
147 | if (p_et >= ET_UNDEF && p_et < ET_ALL) { | |
148 | switch(error_behavior[p_et]) { | |
149 | case TTCN_EncDec::EB_ERROR: | |
150 | TTCN_error("%s", error_str); | |
151 | case TTCN_EncDec::EB_WARNING: | |
152 | TTCN_warning("%s", error_str); | |
153 | break; | |
154 | default: | |
155 | break; | |
156 | } // switch | |
157 | } | |
158 | } | |
159 | ||
160 | TTCN_EncDec_ErrorContext *TTCN_EncDec_ErrorContext::head=NULL; | |
161 | TTCN_EncDec_ErrorContext *TTCN_EncDec_ErrorContext::tail=NULL; | |
162 | ||
163 | TTCN_EncDec_ErrorContext::TTCN_EncDec_ErrorContext() | |
164 | { | |
165 | msg=NULL; | |
166 | if(!head) head=this; | |
167 | if(tail) tail->next=this; | |
168 | prev=tail; | |
169 | next=0; | |
170 | tail=this; | |
171 | } | |
172 | ||
173 | TTCN_EncDec_ErrorContext::TTCN_EncDec_ErrorContext(const char *fmt, ...) | |
174 | { | |
175 | va_list args; | |
176 | va_start(args, fmt); | |
177 | msg=mprintf_va_list(fmt, args); | |
178 | va_end(args); | |
179 | if(!head) head=this; | |
180 | if(tail) tail->next=this; | |
181 | prev=tail; | |
182 | next=0; | |
183 | tail=this; | |
184 | } | |
185 | ||
186 | TTCN_EncDec_ErrorContext::~TTCN_EncDec_ErrorContext() | |
187 | { | |
188 | Free(msg); | |
189 | if(tail!=this) | |
190 | TTCN_error("Internal error:" | |
191 | " TTCN_EncDec_ErrorContext::~TTCN_EncDec_ErrorContext()"); | |
192 | if(prev) prev->next=NULL; | |
193 | else head=NULL; | |
194 | tail=prev; | |
195 | } | |
196 | ||
197 | void TTCN_EncDec_ErrorContext::set_msg(const char *fmt, ...) | |
198 | { | |
199 | Free(msg); | |
200 | va_list args; | |
201 | va_start(args, fmt); | |
202 | msg=mprintf_va_list(fmt, args); | |
203 | va_end(args); | |
204 | } | |
205 | ||
206 | void TTCN_EncDec_ErrorContext::error(TTCN_EncDec::error_type_t p_et, | |
207 | const char *fmt, ...) | |
208 | { | |
209 | char *err_msg=NULL; | |
210 | for(TTCN_EncDec_ErrorContext *p=head; p!=NULL; p=p->next) | |
211 | err_msg=mputstr(err_msg, p->msg); | |
212 | va_list parameters; | |
213 | va_start(parameters, fmt); | |
214 | err_msg=mputprintf_va_list(err_msg, fmt, parameters); | |
215 | va_end(parameters); | |
216 | TTCN_EncDec::error(p_et, err_msg); | |
217 | } | |
218 | ||
219 | void TTCN_EncDec_ErrorContext::error_internal(const char *fmt, ...) | |
220 | { | |
221 | char *err_msg=mcopystr("Internal error: "); | |
222 | for(TTCN_EncDec_ErrorContext *p=head; p!=NULL; p=p->next) | |
223 | err_msg=mputstr(err_msg, p->msg); | |
224 | va_list parameters; | |
225 | va_start(parameters, fmt); | |
226 | err_msg=mputprintf_va_list(err_msg, fmt, parameters); | |
227 | va_end(parameters); | |
228 | TTCN_EncDec::error(TTCN_EncDec::ET_INTERNAL, err_msg); | |
229 | TTCN_error("%s", TTCN_EncDec::get_error_str()); | |
230 | } | |
231 | ||
232 | void TTCN_EncDec_ErrorContext::warning(const char *fmt, ...) | |
233 | { | |
234 | char *warn_msg=NULL; | |
235 | for(TTCN_EncDec_ErrorContext *p=head; p!=NULL; p=p->next) | |
236 | warn_msg=mputstr(warn_msg, p->msg); | |
237 | va_list parameters; | |
238 | va_start(parameters, fmt); | |
239 | warn_msg=mputprintf_va_list(warn_msg, fmt, parameters); | |
240 | va_end(parameters); | |
241 | TTCN_warning("%s", warn_msg); | |
242 | Free(warn_msg); | |
243 | } | |
244 | ||
245 | #define INITIAL_SIZE 1024 | |
246 | #define MEMORY_SIZE(n) (sizeof(buffer_struct) - sizeof(int) + (n)) | |
247 | ||
248 | void TTCN_Buffer::reset_buffer() | |
249 | { | |
250 | buf_pos = 0; | |
251 | bit_pos = 0; | |
252 | last_bit_pos = 0; | |
253 | last_bit_bitpos = 0; | |
254 | start_of_ext_bit = 0; | |
255 | last_bit = FALSE; | |
256 | current_bitorder = FALSE; | |
257 | ext_bit_reverse = FALSE; | |
258 | ext_level = 0; | |
259 | } | |
260 | ||
261 | void TTCN_Buffer::release_memory() | |
262 | { | |
263 | if (buf_ptr != NULL) { | |
264 | if (buf_ptr->ref_count > 1) buf_ptr->ref_count--; | |
265 | else if (buf_ptr->ref_count == 1) Free(buf_ptr); | |
266 | else { | |
267 | TTCN_EncDec_ErrorContext::error_internal("Invalid reference counter %u " | |
268 | "when freeing a TTCN_Buffer.", buf_ptr->ref_count); | |
269 | } | |
270 | } | |
271 | } | |
272 | ||
273 | size_t TTCN_Buffer::get_memory_size(size_t target_size) | |
274 | { | |
275 | size_t new_size = INITIAL_SIZE; | |
276 | while (new_size < target_size) { | |
277 | size_t next_size = new_size + new_size; | |
278 | if (next_size > new_size) new_size = next_size; | |
279 | else { | |
280 | // integer overflow occurred | |
281 | return static_cast<size_t>(-1); | |
282 | } | |
283 | } | |
284 | return new_size; | |
285 | } | |
286 | ||
287 | void TTCN_Buffer::copy_memory() | |
288 | { | |
289 | if (buf_ptr != NULL && buf_ptr->ref_count > 1) { | |
290 | buffer_struct *old_ptr = buf_ptr; | |
291 | old_ptr->ref_count--; | |
292 | buf_size = get_memory_size(buf_len); | |
293 | buf_ptr = (buffer_struct*)Malloc(MEMORY_SIZE(buf_size)); | |
294 | buf_ptr->ref_count = 1; | |
295 | memcpy(buf_ptr->data_ptr, old_ptr->data_ptr, buf_len); | |
296 | } | |
297 | } | |
298 | ||
299 | void TTCN_Buffer::increase_size(size_t size_incr) | |
300 | { | |
301 | if (buf_ptr != NULL) { | |
302 | size_t target_size = buf_len + size_incr; | |
303 | if (target_size < buf_len) | |
304 | TTCN_EncDec_ErrorContext::error_internal("TTCN_Buffer: Overflow error " | |
305 | "(cannot increase buffer size)."); // unsigned overflow | |
306 | if (buf_ptr->ref_count > 1) { // shared, need to split (copy-on-write) | |
307 | buffer_struct *old_ptr = buf_ptr; | |
308 | old_ptr->ref_count--; | |
309 | buf_size = get_memory_size(target_size); | |
310 | buf_ptr = (buffer_struct*)Malloc(MEMORY_SIZE(buf_size)); | |
311 | #ifndef NDEBUG | |
312 | memset(buf_ptr->data_ptr,0, buf_size); | |
313 | #endif | |
314 | buf_ptr->ref_count = 1; | |
315 | memcpy(buf_ptr->data_ptr, old_ptr->data_ptr, buf_len); | |
316 | } else if (target_size > buf_size) { // not shared, just change the size | |
317 | buf_size = get_memory_size(target_size); | |
318 | buf_ptr = (buffer_struct*)Realloc(buf_ptr, MEMORY_SIZE(buf_size)); | |
319 | #ifndef NDEBUG | |
320 | memset(buf_ptr->data_ptr + buf_len,0, buf_size - buf_len); | |
321 | #endif | |
322 | } | |
323 | } else { // a brand new buffer | |
324 | buf_size = get_memory_size(size_incr); | |
325 | buf_ptr = (buffer_struct*)Malloc(MEMORY_SIZE(buf_size)); | |
326 | #ifndef NDEBUG | |
327 | memset(buf_ptr->data_ptr,0, buf_size); | |
328 | #endif | |
329 | buf_ptr->ref_count = 1; | |
330 | } | |
331 | } | |
332 | ||
333 | TTCN_Buffer::TTCN_Buffer() | |
334 | { | |
335 | buf_ptr = NULL; | |
336 | buf_size = 0; | |
337 | buf_len = 0; | |
338 | reset_buffer(); | |
339 | } | |
340 | ||
341 | TTCN_Buffer::TTCN_Buffer(const TTCN_Buffer& p_buf) | |
342 | { | |
343 | buf_ptr = p_buf.buf_ptr; | |
344 | buf_ptr->ref_count++; | |
345 | buf_size = p_buf.buf_size; | |
346 | buf_len = p_buf.buf_len; | |
347 | reset_buffer(); | |
348 | } | |
349 | ||
350 | TTCN_Buffer::TTCN_Buffer(const OCTETSTRING& p_os) | |
351 | { | |
352 | p_os.must_bound("Initializing a TTCN_Buffer with an unbound octetstring " | |
353 | "value."); | |
354 | buf_ptr = (buffer_struct*)p_os.val_ptr; | |
355 | buf_ptr->ref_count++; | |
356 | buf_size = p_os.val_ptr->n_octets; | |
357 | buf_len = p_os.val_ptr->n_octets; | |
358 | reset_buffer(); | |
359 | } | |
360 | ||
361 | TTCN_Buffer::TTCN_Buffer(const CHARSTRING& p_cs) | |
362 | { | |
363 | p_cs.must_bound("Initializing a TTCN_Buffer with an unbound charstring " | |
364 | "value."); | |
365 | buf_ptr = (buffer_struct*)p_cs.val_ptr; | |
366 | buf_ptr->ref_count++; | |
367 | buf_size = p_cs.val_ptr->n_chars + 1; | |
368 | buf_len = p_cs.val_ptr->n_chars; | |
369 | reset_buffer(); | |
370 | } | |
371 | ||
372 | TTCN_Buffer& TTCN_Buffer::operator=(const TTCN_Buffer& p_buf) | |
373 | { | |
374 | if (&p_buf != this) { | |
375 | release_memory(); | |
376 | buf_ptr = p_buf.buf_ptr; | |
377 | buf_ptr->ref_count++; | |
378 | buf_size = p_buf.buf_size; | |
379 | buf_len = p_buf.buf_len; | |
380 | } | |
381 | reset_buffer(); | |
382 | return *this; | |
383 | } | |
384 | ||
385 | TTCN_Buffer& TTCN_Buffer::operator=(const OCTETSTRING& p_os) | |
386 | { | |
387 | p_os.must_bound("Assignment of an unbound octetstring value to a " | |
388 | "TTCN_Buffer."); | |
389 | release_memory(); | |
390 | buf_ptr = (buffer_struct*)p_os.val_ptr; | |
391 | buf_ptr->ref_count++; | |
392 | buf_size = p_os.val_ptr->n_octets; | |
393 | buf_len = p_os.val_ptr->n_octets; | |
394 | reset_buffer(); | |
395 | return *this; | |
396 | } | |
397 | ||
398 | TTCN_Buffer& TTCN_Buffer::operator=(const CHARSTRING& p_cs) | |
399 | { | |
400 | p_cs.must_bound("Assignment of an unbound charstring value to a " | |
401 | "TTCN_Buffer."); | |
402 | release_memory(); | |
403 | buf_ptr = (buffer_struct*)p_cs.val_ptr; | |
404 | buf_ptr->ref_count++; | |
405 | buf_size = p_cs.val_ptr->n_chars + 1; | |
406 | buf_len = p_cs.val_ptr->n_chars; | |
407 | reset_buffer(); | |
408 | return *this; | |
409 | } | |
410 | ||
411 | void TTCN_Buffer::clear() | |
412 | { | |
413 | release_memory(); | |
414 | buf_ptr = NULL; | |
415 | buf_size = 0; | |
416 | buf_len = 0; | |
417 | reset_buffer(); | |
418 | } | |
419 | ||
420 | const unsigned char* TTCN_Buffer::get_data() const | |
421 | { | |
422 | if (buf_ptr != NULL) return buf_ptr->data_ptr; | |
423 | else return NULL; | |
424 | } | |
425 | ||
426 | const unsigned char* TTCN_Buffer::get_read_data() const | |
427 | { | |
428 | if (buf_ptr != NULL) return buf_ptr->data_ptr + buf_pos; | |
429 | else return NULL; | |
430 | } | |
431 | ||
432 | void TTCN_Buffer::set_pos(size_t new_pos) | |
433 | { | |
434 | if (new_pos < buf_len) buf_pos = new_pos; | |
435 | else buf_pos = buf_len; | |
436 | } | |
437 | ||
438 | void TTCN_Buffer::increase_pos(size_t delta) | |
439 | { | |
440 | size_t new_buf_pos=buf_pos+delta; | |
441 | if(new_buf_pos<buf_pos || new_buf_pos>buf_len) | |
442 | buf_pos=buf_len; | |
443 | else | |
444 | buf_pos=new_buf_pos; | |
445 | } | |
446 | ||
447 | void TTCN_Buffer::get_end(unsigned char*& end_ptr, size_t& end_len) | |
448 | { | |
449 | increase_size(end_len); | |
450 | end_len = buf_size - buf_len; | |
451 | if (buf_ptr != NULL) end_ptr = buf_ptr->data_ptr + buf_len; | |
452 | else end_ptr = NULL; | |
453 | } | |
454 | ||
455 | void TTCN_Buffer::increase_length(size_t size_incr) | |
456 | { | |
457 | if (buf_size < buf_len + size_incr) increase_size(size_incr); | |
458 | buf_len += size_incr; | |
459 | } | |
460 | ||
461 | void TTCN_Buffer::put_c(unsigned char c) | |
462 | { | |
463 | increase_size(1); | |
464 | buf_ptr->data_ptr[buf_len] = c; | |
465 | buf_len++; | |
466 | } | |
467 | ||
468 | void TTCN_Buffer::put_s(size_t len, const unsigned char *s) | |
469 | { | |
470 | if (len > 0) { | |
471 | increase_size(len); | |
472 | memcpy(buf_ptr->data_ptr + buf_len, s, len); | |
473 | buf_len += len; | |
474 | } | |
475 | } | |
476 | ||
477 | void TTCN_Buffer::put_string(const OCTETSTRING& p_os) | |
478 | { | |
479 | p_os.must_bound("Appending an unbound octetstring value to a TTCN_Buffer."); | |
480 | if (p_os.val_ptr->n_octets > 0) { | |
481 | if (buf_len > 0) { | |
482 | increase_size(p_os.val_ptr->n_octets); | |
483 | memcpy(buf_ptr->data_ptr + buf_len, p_os.val_ptr->octets_ptr, | |
484 | p_os.val_ptr->n_octets); | |
485 | buf_len += p_os.val_ptr->n_octets; | |
486 | } else { | |
487 | release_memory(); | |
488 | buf_ptr = (buffer_struct*)p_os.val_ptr; | |
489 | buf_ptr->ref_count++; | |
490 | buf_size = p_os.val_ptr->n_octets; | |
491 | buf_len = p_os.val_ptr->n_octets; | |
492 | } | |
493 | } | |
494 | } | |
495 | ||
496 | void TTCN_Buffer::put_string(const CHARSTRING& p_cs) | |
497 | { | |
498 | p_cs.must_bound("Appending an unbound charstring value to a TTCN_Buffer."); | |
499 | if (p_cs.val_ptr->n_chars > 0) { // there is something in the CHARSTRING | |
500 | if (buf_len > 0) { // there is something in this buffer, append | |
501 | increase_size(p_cs.val_ptr->n_chars); | |
502 | memcpy(buf_ptr->data_ptr + buf_len, p_cs.val_ptr->chars_ptr, | |
503 | p_cs.val_ptr->n_chars); | |
504 | buf_len += p_cs.val_ptr->n_chars; | |
505 | } else { // share the data | |
506 | release_memory(); | |
507 | buf_ptr = (buffer_struct*)p_cs.val_ptr; | |
508 | buf_ptr->ref_count++; | |
509 | buf_size = p_cs.val_ptr->n_chars + 1; | |
510 | buf_len = p_cs.val_ptr->n_chars; | |
511 | } | |
512 | } | |
513 | } | |
514 | ||
515 | void TTCN_Buffer::put_buf(const TTCN_Buffer& p_buf) { | |
516 | if (p_buf.buf_ptr == 0) return; | |
517 | if (p_buf.buf_len > 0) { // there is something in the other buffer | |
518 | if (buf_len > 0) { // there is something in this buffer, append | |
519 | increase_size(p_buf.buf_len); | |
520 | memcpy(buf_ptr->data_ptr + buf_len, p_buf.buf_ptr->data_ptr, | |
521 | p_buf.buf_len); | |
522 | buf_len += p_buf.buf_len; | |
523 | } | |
524 | else { // share the data | |
525 | *this = p_buf; | |
526 | } | |
527 | } | |
528 | } | |
529 | ||
530 | void TTCN_Buffer::get_string(OCTETSTRING& p_os) | |
531 | { | |
532 | p_os.clean_up(); | |
533 | if (buf_len > 0) { | |
534 | if (buf_ptr->ref_count > 1) { | |
535 | p_os.init_struct(buf_len); | |
536 | memcpy(p_os.val_ptr->octets_ptr, buf_ptr->data_ptr, buf_len); | |
537 | } else { | |
538 | if (buf_size != buf_len) { | |
539 | buf_ptr = (buffer_struct*)Realloc(buf_ptr, MEMORY_SIZE(buf_len)); | |
540 | buf_size = buf_len; | |
541 | } | |
542 | p_os.val_ptr = (OCTETSTRING::octetstring_struct*)buf_ptr; | |
543 | p_os.val_ptr->ref_count++; | |
544 | p_os.val_ptr->n_octets = buf_len; | |
545 | } | |
546 | } else p_os.init_struct(0); | |
547 | } | |
548 | ||
549 | void TTCN_Buffer::get_string(CHARSTRING& p_cs) | |
550 | { | |
551 | p_cs.clean_up(); | |
552 | if (buf_len > 0) { | |
553 | if (buf_ptr->ref_count > 1) { // buffer is shared, copy is needed | |
554 | p_cs.init_struct(buf_len); | |
555 | memcpy(p_cs.val_ptr->chars_ptr, buf_ptr->data_ptr, buf_len); | |
556 | } else { // we are the sole owner | |
557 | // Share our buffer_struct with CHARSTRING's charstring_struct | |
558 | // (they have the same layout), after putting in a string terminator. | |
559 | if (buf_size != buf_len + 1) { | |
560 | buf_ptr = (buffer_struct*)Realloc(buf_ptr, MEMORY_SIZE(buf_len + 1)); | |
561 | buf_size = buf_len + 1; | |
562 | } | |
563 | p_cs.val_ptr = (CHARSTRING::charstring_struct*)buf_ptr; | |
564 | p_cs.val_ptr->ref_count++; | |
565 | p_cs.val_ptr->n_chars = buf_len; | |
566 | p_cs.val_ptr->chars_ptr[buf_len] = '\0'; | |
567 | } | |
568 | } else p_cs.init_struct(0); | |
569 | } | |
570 | ||
571 | void TTCN_Buffer::get_string(UNIVERSAL_CHARSTRING& p_cs) | |
572 | { | |
573 | p_cs.clean_up(); | |
574 | if (buf_len > 0) { | |
575 | // TODO what if not multiple of 4 ? | |
576 | p_cs.init_struct(buf_len / 4); | |
577 | memcpy(p_cs.val_ptr->uchars_ptr, buf_ptr->data_ptr, buf_len); | |
578 | } else p_cs.init_struct(0); | |
579 | } | |
580 | ||
581 | void TTCN_Buffer::cut() | |
582 | { | |
583 | if (buf_pos > 0) { | |
584 | if (buf_pos > buf_len) | |
585 | TTCN_EncDec_ErrorContext::error_internal("Read pointer points beyond " | |
586 | "the buffer end when cutting from a TTCN_Buffer."); | |
587 | size_t new_len = buf_len - buf_pos; | |
588 | if (new_len > 0) { | |
589 | if (buf_ptr->ref_count > 1) { | |
590 | buffer_struct *old_ptr = buf_ptr; | |
591 | old_ptr->ref_count--; | |
592 | buf_size = get_memory_size(new_len); | |
593 | buf_ptr = (buffer_struct*)Malloc(MEMORY_SIZE(buf_size)); | |
594 | buf_ptr->ref_count = 1; | |
595 | memcpy(buf_ptr->data_ptr, old_ptr->data_ptr + buf_pos, new_len); | |
596 | } else { | |
597 | memmove(buf_ptr->data_ptr, buf_ptr->data_ptr + buf_pos, new_len); | |
598 | size_t new_size = get_memory_size(new_len); | |
599 | if (new_size < buf_size) { | |
600 | buf_ptr = (buffer_struct*)Realloc(buf_ptr, MEMORY_SIZE(new_size)); | |
601 | buf_size = new_size; | |
602 | } | |
603 | } | |
604 | } else { | |
605 | release_memory(); | |
606 | buf_ptr = NULL; | |
607 | buf_size = 0; | |
608 | } | |
609 | buf_len = new_len; | |
610 | } | |
611 | reset_buffer(); | |
612 | } | |
613 | ||
614 | void TTCN_Buffer::cut_end() | |
615 | { | |
616 | if (buf_pos > buf_len) | |
617 | TTCN_EncDec_ErrorContext::error_internal("Read pointer points beyond " | |
618 | "the buffer end when cutting from a TTCN_Buffer."); | |
619 | if (buf_pos < buf_len) { | |
620 | if (buf_pos > 0) { | |
621 | if (buf_ptr == NULL) | |
622 | TTCN_EncDec_ErrorContext::error_internal("Data pointer is NULL when " | |
623 | "cutting from a TTCN_Buffer."); | |
624 | if (buf_ptr->ref_count == 1) { | |
625 | size_t new_size = get_memory_size(buf_pos); | |
626 | if (new_size < buf_size) { | |
627 | buf_ptr = (buffer_struct*)Realloc(buf_ptr, MEMORY_SIZE(new_size)); | |
628 | buf_size = new_size; | |
629 | } | |
630 | } | |
631 | } else { | |
632 | release_memory(); | |
633 | buf_ptr = NULL; | |
634 | buf_size = 0; | |
635 | } | |
636 | buf_len = buf_pos; | |
637 | } | |
638 | last_bit_pos = 0; | |
639 | last_bit_bitpos = 0; | |
640 | start_of_ext_bit = 0; | |
641 | last_bit = FALSE; | |
642 | current_bitorder = FALSE; | |
643 | ext_bit_reverse = FALSE; | |
644 | ext_level = 0; | |
645 | } | |
646 | ||
647 | boolean TTCN_Buffer::contains_complete_TLV() | |
648 | { | |
649 | if (buf_len > buf_pos) { | |
650 | ASN_BER_TLV_t tmp_tlv; | |
651 | return ASN_BER_str2TLV(buf_len - buf_pos, buf_ptr->data_ptr + buf_pos, | |
652 | tmp_tlv, BER_ACCEPT_ALL); | |
653 | } else return FALSE; | |
654 | } | |
655 | ||
656 | void TTCN_Buffer::log() const | |
657 | { | |
658 | TTCN_Logger::log_event("Buffer: size: %lu, pos: %lu, len: %lu data: (", | |
659 | (unsigned long)buf_size, (unsigned long)buf_pos, (unsigned long)buf_len); | |
660 | if (buf_len > 0) { | |
661 | const unsigned char *data_ptr = buf_ptr->data_ptr; | |
662 | for(size_t i=0; i<buf_pos; i++) | |
663 | TTCN_Logger::log_octet(data_ptr[i]); | |
664 | TTCN_Logger::log_event_str(" | "); | |
665 | for(size_t i=buf_pos; i<buf_len; i++) | |
666 | TTCN_Logger::log_octet(data_ptr[i]); | |
667 | } | |
668 | TTCN_Logger::log_char(')'); | |
669 | } | |
670 | ||
671 | void TTCN_Buffer::put_b(size_t len, const unsigned char *s, | |
672 | const RAW_coding_par& coding_par, int align) | |
673 | { | |
674 | ||
675 | unsigned char* st=NULL; | |
676 | unsigned char* st2=NULL; | |
677 | int loc_align=align<0?-align:align; | |
678 | bool must_align=false; | |
679 | raw_order_t local_bitorder=coding_par.bitorder; | |
680 | raw_order_t local_fieldorder=coding_par.fieldorder; | |
681 | if(current_bitorder) { | |
682 | if(local_bitorder==ORDER_LSB) local_bitorder=ORDER_MSB; | |
683 | else local_bitorder=ORDER_LSB; | |
684 | if(local_fieldorder==ORDER_LSB) local_fieldorder=ORDER_MSB; | |
685 | else local_fieldorder=ORDER_LSB; | |
686 | } | |
687 | /*printf("len:%d\r\n",len); | |
688 | printf("align:%d\r\n",align); | |
689 | printf("coding bito:%s,byte:%s,field:%s\r\n",coding_par.bitorder==ORDER_MSB?"M":"L", | |
690 | coding_par.byteorder==ORDER_MSB?"M":"L", | |
691 | coding_par.fieldorder==ORDER_MSB?"M":"L" | |
692 | ); | |
693 | printf("local bito:%s,field:%s\r\n",local_bitorder==ORDER_MSB?"M":"L", | |
694 | local_fieldorder==ORDER_MSB?"M":"L" | |
695 | );*/ | |
696 | if(align) { | |
697 | if((local_fieldorder==ORDER_LSB && (local_bitorder!=coding_par.byteorder))|| | |
698 | (local_fieldorder==ORDER_MSB && (local_bitorder==coding_par.byteorder))) { | |
699 | st=(unsigned char*)Malloc((len+loc_align+7)/8*sizeof(unsigned char)); | |
700 | memset(st,0,(len+loc_align+7)/8*sizeof(unsigned char)); | |
701 | if(align>0){ | |
702 | memcpy(st,s,(len+7)/8*sizeof(unsigned char)); | |
703 | if(len%8) st[(len+7)/8-1]&=BitMaskTable[len%8]; | |
704 | } | |
705 | else{ | |
706 | if(loc_align%8){ | |
707 | int bit_bound=loc_align%8; | |
708 | size_t max_index=(len+loc_align+7)/8-loc_align/8-1; | |
709 | unsigned char* ptr=st+loc_align/8; | |
710 | unsigned char mask=BitMaskTable[bit_bound]; | |
711 | for(size_t a=0;a<(len+7)/8;a++){ | |
712 | ptr[a]&=mask; | |
713 | ptr[a]|=s[a]<<(8-bit_bound); | |
714 | if(a<max_index) ptr[a+1]=s[a]>>bit_bound; | |
715 | } | |
716 | } | |
717 | else{ | |
718 | memcpy(st+loc_align/8,s,(len+7)/8*sizeof(unsigned char)); | |
719 | } | |
720 | } | |
721 | s=st; | |
722 | len+=loc_align; | |
723 | } | |
724 | else{ | |
725 | if(coding_par.byteorder==ORDER_MSB) align=-align; | |
726 | if(align<0) put_zero(loc_align,local_fieldorder); | |
727 | else must_align=true; | |
728 | } | |
729 | } | |
730 | if(len==0) { | |
731 | if(must_align) put_zero(loc_align,local_fieldorder); | |
732 | return; | |
733 | } | |
734 | size_t new_size=((bit_pos==0?buf_len*8:buf_len*8-(8-bit_pos))+len+7)/8; | |
735 | size_t new_bit_pos=(bit_pos+len)%8; | |
736 | if (new_size > buf_len) increase_size(new_size - buf_len); | |
737 | else copy_memory(); | |
738 | unsigned char *data_ptr = buf_ptr != NULL ? buf_ptr->data_ptr : NULL; | |
739 | //printf("buf_len:%d bit_pos:%d\r\n",buf_len,bit_pos); | |
740 | //printf("new_size:%d new_bit_pos:%d\r\n",new_size,new_bit_pos); | |
741 | if(coding_par.hexorder==ORDER_MSB){ | |
742 | st2=(unsigned char*)Malloc((len+7)/8*sizeof(unsigned char)); | |
743 | if(bit_pos==4){ | |
744 | st2[0]=s[0]; | |
745 | for(size_t a=1;a<(len+7)/8;a++){ | |
746 | unsigned char ch='\0'; | |
747 | ch|=s[a-1]>>4; | |
748 | st2[a-1]=(st2[a-1]&0x0f)|(s[a]<<4); | |
749 | st2[a]=(s[a]&0xf0)|ch; | |
750 | } | |
751 | } | |
752 | else{ | |
753 | for(size_t a=0;a<(len+7)/8;a++) st2[a]=(s[a]<<4)|(s[a]>>4); | |
754 | if(len%8) st2[(len+7)/8]>>=4; | |
755 | } | |
756 | s=st2; | |
757 | } | |
758 | if(bit_pos+len<=8){ // there is enough space within 1 octet to store the data | |
759 | if(local_bitorder==ORDER_LSB){ | |
760 | if(local_fieldorder==ORDER_LSB){ | |
761 | data_ptr[new_size-1]= | |
762 | (data_ptr[new_size-1]&BitMaskTable[bit_pos])| | |
763 | (s[0]<<bit_pos); | |
764 | }else{ | |
765 | data_ptr[new_size-1]= | |
766 | (data_ptr[new_size-1]&~BitMaskTable[8-bit_pos])| | |
767 | ((s[0]&BitMaskTable[len])<<(8-bit_pos-len)); | |
768 | } | |
769 | } | |
770 | else{ | |
771 | if(local_fieldorder==ORDER_LSB){ | |
772 | data_ptr[new_size-1]= | |
773 | (data_ptr[new_size-1]&BitMaskTable[bit_pos])| | |
774 | (REVERSE_BITS(s[0])>>(8-len-bit_pos)); | |
775 | }else{ | |
776 | data_ptr[new_size-1]= | |
777 | (data_ptr[new_size-1]&~BitMaskTable[8-bit_pos])| | |
778 | (REVERSE_BITS(s[0]&BitMaskTable[len])>>bit_pos); | |
779 | } | |
780 | } | |
781 | } | |
782 | else if(bit_pos==0 && (len%8)==0){ // octet aligned data | |
783 | if(coding_par.byteorder==ORDER_LSB){ | |
784 | if(local_bitorder==ORDER_LSB){ | |
785 | memcpy(data_ptr+buf_len, s, len/8); | |
786 | } | |
787 | else{ | |
788 | unsigned char *prt=data_ptr+buf_len; | |
789 | for(size_t a=0;a<len/8;a++) prt[a]=REVERSE_BITS(s[a]); | |
790 | } | |
791 | } | |
792 | else{ | |
793 | if(local_bitorder==ORDER_LSB){ | |
794 | unsigned char *prt=data_ptr+buf_len; | |
795 | for(size_t a=0,b=len/8-1;a<len/8;a++,b--) prt[a]=s[b]; | |
796 | } | |
797 | else{ | |
798 | unsigned char *prt=data_ptr+buf_len; | |
799 | for(size_t a=0,b=len/8-1;a<len/8;a++,b--) prt[a]=REVERSE_BITS(s[b]); | |
800 | } | |
801 | } | |
802 | } | |
803 | else{ | |
804 | size_t maxindex=new_size-1; | |
805 | if(coding_par.byteorder==ORDER_LSB){ | |
806 | if(local_bitorder==ORDER_LSB){ | |
807 | if(bit_pos){ | |
808 | unsigned char mask1=BitMaskTable[bit_pos]; | |
809 | unsigned char *prt=data_ptr+(buf_len==0?0:buf_len-1); | |
810 | if(local_fieldorder==ORDER_MSB){ | |
811 | unsigned int num_bytes = (len+7) / 8; | |
812 | unsigned int active_bits_in_last = len % 8; | |
3abe9331 | 813 | if(!active_bits_in_last) active_bits_in_last=8; |
970ed795 EL |
814 | for(unsigned int a=0; a < num_bytes; a++){ |
815 | prt[a]&=REVERSE_BITS(mask1); | |
816 | unsigned char sa = s[a]; | |
817 | if (a == num_bytes - 1) { // last byte | |
818 | sa <<= (8 - active_bits_in_last); | |
819 | // push bits up so the first active bit is in MSB | |
820 | } | |
821 | prt[a]|=(sa>>bit_pos)&~REVERSE_BITS(mask1); | |
822 | if(a<maxindex) | |
823 | prt[a+1]=sa<<(8-bit_pos); | |
824 | } | |
825 | } | |
826 | else{ | |
827 | for(unsigned int a=0;a<(len+7)/8;a++){ | |
828 | prt[a]&=mask1; | |
829 | prt[a]|=s[a]<<bit_pos; | |
830 | if(a<maxindex) | |
831 | prt[a+1]=s[a]>>(8-bit_pos); | |
832 | } | |
833 | } | |
834 | } | |
835 | else{ // start from octet boundary | |
836 | memcpy(data_ptr+buf_len, s, (len+7)/8*sizeof(unsigned char)); | |
3abe9331 | 837 | if(local_fieldorder==ORDER_MSB && new_bit_pos){ |
838 | data_ptr[new_size-1]<<=(8-new_bit_pos); | |
839 | ||
840 | } | |
970ed795 EL |
841 | } |
842 | } | |
843 | else{ // bitorder==ORDER_MSB | |
844 | if(bit_pos){ | |
845 | unsigned char mask1=REVERSE_BITS(BitMaskTable[bit_pos]); | |
846 | unsigned char *prt=data_ptr+(buf_len==0?0:buf_len-1); | |
847 | if(local_fieldorder==ORDER_MSB){ | |
848 | prt[0]&=mask1; | |
849 | prt[0]|=REVERSE_BITS(s[0])>>bit_pos; | |
850 | prt[1]=REVERSE_BITS(s[0])<<(8-bit_pos); | |
851 | } | |
852 | else{ | |
853 | prt[0]&=REVERSE_BITS(mask1); | |
854 | prt[0]|=REVERSE_BITS(s[0])&~REVERSE_BITS(mask1); | |
855 | prt[1]=REVERSE_BITS(s[0])<<(8-bit_pos); | |
856 | } | |
857 | for(unsigned int a=1;a<(len+7)/8;a++){ | |
858 | prt[a]&=mask1; | |
859 | prt[a]|=REVERSE_BITS(s[a])>>bit_pos; | |
860 | if(a<maxindex) | |
861 | prt[a+1]=REVERSE_BITS(s[a])<<(8-bit_pos); | |
862 | } | |
863 | } | |
864 | else{ // start from octet boundary | |
865 | unsigned char *prt=data_ptr+buf_len; | |
866 | for(unsigned int a=0;a<(len+7)/8;a++) prt[a]=REVERSE_BITS(s[a]); | |
867 | } | |
868 | if(local_fieldorder==ORDER_LSB && new_bit_pos) | |
869 | data_ptr[new_size-1]>>=(8-new_bit_pos); | |
870 | } | |
871 | } | |
872 | else{ // byteorder==ORDER_MSB | |
873 | if(local_bitorder==ORDER_LSB){ | |
874 | if(bit_pos){ | |
875 | unsigned char mask1=BitMaskTable[bit_pos]; | |
876 | unsigned char ch=get_byte_rev(s,len,0); | |
877 | unsigned char *prt=data_ptr+(buf_len==0?0:buf_len-1); | |
878 | if(local_fieldorder==ORDER_MSB){ | |
879 | prt[0]&=REVERSE_BITS(mask1); | |
880 | prt[0]|=ch>>bit_pos; | |
881 | prt[1]=ch<<(8-bit_pos); | |
882 | } | |
883 | else{ | |
884 | prt[0]&=mask1; | |
885 | prt[0]|=ch&~mask1; | |
886 | prt[1]=ch<<(8-bit_pos); | |
887 | } | |
888 | for(unsigned int a=1;a<(len+7)/8;a++){ | |
889 | ch=get_byte_rev(s,len,a); | |
890 | prt[a]&=REVERSE_BITS(mask1); | |
891 | prt[a]|=ch>>bit_pos; | |
892 | if(a<maxindex) | |
893 | prt[a+1]=ch<<(8-bit_pos); | |
894 | } | |
895 | } | |
896 | else{ | |
897 | unsigned char *prt=data_ptr+buf_len; | |
898 | for(unsigned int a=0;a<(len+7)/8;a++) prt[a]=get_byte_rev(s,len,a); | |
899 | } | |
900 | if(local_fieldorder==ORDER_LSB && new_bit_pos) | |
901 | data_ptr[new_size-1]>>=(8-new_bit_pos); | |
902 | } | |
903 | else{ // bitorder==ORDER_MSB | |
904 | if(bit_pos){ | |
905 | unsigned char mask1=BitMaskTable[bit_pos]; | |
906 | unsigned char ch=get_byte_rev(s,len,0); | |
907 | unsigned char *prt=data_ptr+(buf_len==0?0:buf_len-1); | |
908 | if(local_fieldorder==ORDER_MSB){ | |
909 | prt[0]&=REVERSE_BITS(mask1); | |
910 | prt[0]|=REVERSE_BITS(ch)&~REVERSE_BITS(mask1); | |
911 | prt[1]=REVERSE_BITS(ch)>>(8-bit_pos); | |
912 | } | |
913 | else{ | |
914 | prt[0]&=mask1; | |
915 | prt[0]|=REVERSE_BITS(ch)<<bit_pos; | |
916 | prt[1]=REVERSE_BITS(ch)>>(8-bit_pos); | |
917 | } | |
918 | for(unsigned int a=1;a<(len+7)/8;a++){ | |
919 | ch=get_byte_rev(s,len,a); | |
920 | prt[a]&=mask1; | |
921 | prt[a]|=REVERSE_BITS(ch)<<bit_pos; | |
922 | if(a<maxindex) | |
923 | prt[a+1]=REVERSE_BITS(ch)>>(8-bit_pos); | |
924 | } | |
925 | } | |
926 | else{ // start from octet boundary | |
927 | unsigned char *prt=data_ptr+buf_len; | |
928 | for(unsigned int a=0;a<(len+7)/8;a++) prt[a]= | |
929 | REVERSE_BITS(get_byte_rev(s,len,a)); | |
930 | } | |
931 | if(local_fieldorder==ORDER_MSB && new_bit_pos) | |
932 | data_ptr[new_size-1]<<=(8-new_bit_pos); | |
933 | } | |
934 | } | |
935 | } | |
936 | if(st) Free(st); | |
937 | if(st2) Free(st2); | |
938 | /* last_bit_pos=((bit_pos==0?buf_len*8:buf_len*8-(8-bit_pos))+len+6)/8; | |
939 | if(local_fieldorder==ORDER_LSB) | |
940 | last_bit_bitpos=(bit_pos+len-1)%8; | |
941 | else | |
942 | last_bit_bitpos=7-(bit_pos+len-1)%8;*/ | |
943 | buf_len=new_size; | |
944 | bit_pos=new_bit_pos; | |
945 | if(bit_pos){ | |
946 | last_bit_pos=buf_len-1; | |
947 | if(local_fieldorder==ORDER_LSB) | |
948 | last_bit_bitpos=bit_pos-1; | |
949 | else | |
950 | last_bit_bitpos=7-(bit_pos-1); | |
951 | } | |
952 | else{ | |
953 | last_bit_pos=buf_len-1; | |
954 | if(local_fieldorder==ORDER_LSB) | |
955 | last_bit_bitpos=7; | |
956 | else | |
957 | last_bit_bitpos=0; | |
958 | } | |
959 | if(must_align) put_zero(loc_align,local_fieldorder); | |
960 | } | |
961 | ||
962 | void TTCN_Buffer::get_b(size_t len, unsigned char *s, | |
963 | const RAW_coding_par& coding_par, raw_order_t top_bit_order) | |
964 | { | |
965 | if(len==0) return; | |
966 | size_t new_buf_pos=buf_pos+(bit_pos+len)/8; | |
967 | size_t new_bit_pos=(bit_pos+len)%8; | |
968 | raw_order_t local_bitorder=coding_par.bitorder; | |
969 | raw_order_t local_fieldorder=coding_par.fieldorder; | |
970 | if(top_bit_order==ORDER_LSB){ | |
971 | if(local_bitorder==ORDER_LSB) local_bitorder=ORDER_MSB; | |
972 | else local_bitorder=ORDER_LSB; | |
973 | if(local_fieldorder==ORDER_LSB) local_fieldorder=ORDER_MSB; | |
974 | else local_fieldorder=ORDER_LSB; | |
975 | } | |
976 | const unsigned char *data_ptr = buf_ptr != NULL ? buf_ptr->data_ptr : NULL; | |
977 | if(bit_pos+len<=8){ // the data is within 1 octet | |
978 | if(local_bitorder==ORDER_LSB){ | |
979 | if(local_fieldorder==ORDER_LSB){ | |
980 | s[0]=data_ptr[buf_pos]>>bit_pos; | |
981 | }else{ | |
982 | s[0]=data_ptr[buf_pos]>>(8-bit_pos-len); | |
983 | } | |
984 | } | |
985 | else{ | |
986 | if(local_fieldorder==ORDER_LSB){ | |
987 | s[0]=REVERSE_BITS(data_ptr[buf_pos])>>(8-bit_pos-len); | |
988 | }else{ | |
989 | s[0]=REVERSE_BITS(data_ptr[buf_pos])>>bit_pos; | |
990 | } | |
991 | } | |
992 | } | |
993 | else if(bit_pos==0 && (len%8)==0){ // octet aligned data | |
994 | if(coding_par.byteorder==ORDER_LSB){ | |
995 | if(local_bitorder==ORDER_LSB){ | |
996 | memcpy(s, data_ptr+buf_pos, len/8*sizeof(unsigned char)); | |
997 | } | |
998 | else{ | |
999 | const unsigned char *prt=data_ptr+buf_pos; | |
1000 | for(size_t a=0;a<len/8;a++) s[a]=REVERSE_BITS(prt[a]); | |
1001 | } | |
1002 | } | |
1003 | else{ | |
1004 | if(local_bitorder==ORDER_LSB){ | |
1005 | const unsigned char *prt=data_ptr+buf_pos; | |
1006 | for(size_t a=0,b=len/8-1;a<len/8;a++,b--) s[a]=prt[b]; | |
1007 | } | |
1008 | else{ | |
1009 | const unsigned char *prt=data_ptr+buf_pos; | |
1010 | for(size_t a=0,b=len/8-1;a<len/8;a++,b--) s[a]=REVERSE_BITS(prt[b]); | |
1011 | } | |
1012 | } | |
1013 | } | |
1014 | else{ // unaligned | |
1015 | size_t num_bytes = (len + 7) / 8; | |
1016 | if(coding_par.byteorder==ORDER_LSB){ | |
1017 | if(local_bitorder==ORDER_LSB){ | |
1018 | if(bit_pos){ | |
1019 | unsigned char mask1=BitMaskTable[8-bit_pos]; | |
1020 | if(local_fieldorder==ORDER_LSB){ | |
1021 | for(unsigned int a=0;a<num_bytes;a++){ | |
1022 | s[a]=(get_byte_align(len,local_fieldorder,ORDER_MSB,a+1) | |
1023 | <<(8-bit_pos))| | |
1024 | ((get_byte_align(len,local_fieldorder,ORDER_MSB,a) | |
1025 | >>bit_pos)&mask1); | |
1026 | } | |
1027 | } else { | |
1028 | mask1=BitMaskTable[bit_pos]; | |
1029 | for(unsigned int a=0;a<num_bytes;a++){ | |
1030 | s[a]=(get_byte_align(len,local_fieldorder,ORDER_LSB,a+1) | |
1031 | >>(8-bit_pos)&mask1)| | |
1032 | ((get_byte_align(len,local_fieldorder,ORDER_LSB,a) | |
1033 | <<bit_pos)); | |
1034 | } | |
1035 | int active_bits_in_last_byte = len % 8; | |
1036 | if (active_bits_in_last_byte) { | |
1037 | s[num_bytes - 1] >>= (8 - active_bits_in_last_byte); | |
1038 | } | |
1039 | } | |
1040 | } | |
1041 | else{ // start from octet boundary | |
1042 | memcpy(s, data_ptr+buf_pos, num_bytes*sizeof(unsigned char)); | |
1043 | if(local_fieldorder==ORDER_MSB && new_bit_pos) | |
1044 | s[num_bytes-1]>>=(8-new_bit_pos); | |
1045 | } | |
1046 | } | |
1047 | else{ // bitorder==ORDER_MSB | |
1048 | if(bit_pos){ | |
1049 | unsigned char mask1=BitMaskTable[bit_pos]; | |
1050 | for(unsigned int a=0;a<num_bytes;a++){ | |
1051 | s[a]=REVERSE_BITS( | |
1052 | ((get_byte_align(len,local_fieldorder,ORDER_LSB,a+1) | |
1053 | >>(8-bit_pos))&mask1)| | |
1054 | (get_byte_align(len,local_fieldorder,ORDER_LSB,a) | |
1055 | <<bit_pos)); | |
1056 | } | |
1057 | } | |
1058 | else{ // start from octet boundary | |
1059 | const unsigned char *prt=data_ptr+buf_pos; | |
1060 | for(unsigned int a=0;a<num_bytes;a++) s[a]=REVERSE_BITS(prt[a]); | |
1061 | if(local_fieldorder==ORDER_LSB && new_bit_pos) | |
1062 | s[num_bytes-1]>>=(8-new_bit_pos); | |
1063 | } | |
1064 | } | |
1065 | } | |
1066 | else{ // byteorder==ORDER_MSB | |
1067 | if(local_bitorder==ORDER_LSB){ | |
1068 | if(new_bit_pos){ | |
1069 | unsigned char mask1=BitMaskTable[new_bit_pos]; | |
1070 | for(unsigned int a=0,b=(bit_pos+len)/8;a<num_bytes;a++,b--){ | |
1071 | s[a]=((get_byte_align(len,local_fieldorder,ORDER_LSB,b) | |
1072 | >>(8-new_bit_pos))&mask1)| | |
1073 | (get_byte_align(len,local_fieldorder,ORDER_LSB,b-1) | |
1074 | <<new_bit_pos); | |
1075 | } | |
1076 | } | |
1077 | else{ | |
1078 | // unsigned char *prt=data_ptr+buf_pos; | |
1079 | for(unsigned int a=0,b=new_buf_pos-1;a<num_bytes;a++,b--) | |
1080 | s[a]=data_ptr[b]; | |
1081 | if(local_fieldorder==ORDER_LSB && bit_pos) | |
1082 | s[num_bytes-1]>>=bit_pos; | |
1083 | } | |
1084 | } | |
1085 | else{ // bitorder==ORDER_MSB | |
1086 | if(new_bit_pos){ | |
1087 | // unsigned char mask1=BitMaskTable[new_bit_pos]; | |
1088 | for(unsigned int a=0,b=(bit_pos+len)/8;a<num_bytes;a++,b--){ | |
1089 | s[a]=REVERSE_BITS( | |
1090 | (get_byte_align(len,local_fieldorder,ORDER_MSB,b) | |
1091 | <<(8-new_bit_pos))| | |
1092 | (get_byte_align(len,local_fieldorder,ORDER_MSB,b-1) | |
1093 | >>new_bit_pos)); | |
1094 | } | |
1095 | } | |
1096 | else{ // start from octet boundary | |
1097 | // unsigned char *prt=data_ptr+buf_pos; | |
1098 | for(unsigned int a=0,b=new_buf_pos-1;a<num_bytes;a++,b--) | |
1099 | s[a]=REVERSE_BITS(data_ptr[b]); | |
1100 | if(local_fieldorder==ORDER_MSB && bit_pos) | |
1101 | s[num_bytes-1]>>=bit_pos; | |
1102 | } | |
1103 | } | |
1104 | } | |
1105 | } | |
1106 | if(coding_par.hexorder==ORDER_MSB){ | |
1107 | if(bit_pos==4){ | |
1108 | for(size_t a=1;a<(len+7)/8;a++){ | |
1109 | unsigned char ch='\0'; | |
1110 | ch|=s[a-1]>>4; | |
1111 | s[a-1]=(s[a-1]&0x0f)|(s[a]<<4); | |
1112 | s[a]=(s[a]&0xf0)|ch; | |
1113 | } | |
1114 | } | |
1115 | else{ | |
1116 | for(size_t a=0;a<(len+7)/8;a++) s[a]=(s[a]<<4)|(s[a]>>4); | |
1117 | if(len%8) s[(len+7)/8]>>=4; | |
1118 | } | |
1119 | } | |
1120 | ||
1121 | size_t last_bit_offset = bit_pos + len - 1; | |
1122 | unsigned char last_bit_octet = data_ptr[buf_pos + last_bit_offset / 8]; | |
1123 | if (local_fieldorder == ORDER_LSB) last_bit_octet >>= last_bit_offset % 8; | |
1124 | else last_bit_octet >>= 7 - last_bit_offset % 8; | |
1125 | if (last_bit_octet & 0x01) last_bit = TRUE; | |
1126 | else last_bit = FALSE; | |
1127 | ||
1128 | buf_pos=new_buf_pos; | |
1129 | bit_pos=new_bit_pos; | |
1130 | } | |
1131 | ||
1132 | void TTCN_Buffer::put_zero(size_t len, raw_order_t fieldorder) | |
1133 | { | |
1134 | if(len==0) return; | |
1135 | size_t new_size=((bit_pos==0?buf_len*8:buf_len*8-(8-bit_pos))+len+7)/8; | |
1136 | if (new_size > buf_len) increase_size(new_size - buf_len); | |
1137 | else copy_memory(); | |
1138 | unsigned char *data_ptr = buf_ptr != NULL ? buf_ptr->data_ptr : NULL; | |
1139 | if(bit_pos){ | |
1140 | if(bit_pos+len>8){ | |
1141 | unsigned char mask1=BitMaskTable[bit_pos]; | |
1142 | unsigned char *prt=data_ptr+(buf_len==0?0:buf_len-1); | |
1143 | if(fieldorder==ORDER_LSB) prt[0]&=mask1; | |
1144 | else prt[0]&=~mask1; | |
1145 | memset(prt+1, 0, (len-1+bit_pos)/8); | |
1146 | } | |
1147 | else { | |
1148 | if(fieldorder==ORDER_LSB) | |
1149 | data_ptr[new_size-1]=data_ptr[new_size-1]&BitMaskTable[bit_pos]; | |
1150 | else | |
1151 | data_ptr[new_size-1]=data_ptr[new_size-1]& | |
1152 | REVERSE_BITS(BitMaskTable[bit_pos]); | |
1153 | } | |
1154 | } | |
1155 | else { | |
1156 | memset(data_ptr+buf_len, 0, (len+7)/8); | |
1157 | } | |
1158 | buf_len=new_size; | |
1159 | bit_pos=(bit_pos+len)%8; | |
1160 | if(bit_pos){ | |
1161 | last_bit_pos=buf_len-1; | |
1162 | if(fieldorder==ORDER_LSB) | |
1163 | last_bit_bitpos=bit_pos-1; | |
1164 | else | |
1165 | last_bit_bitpos=7-(bit_pos-1); | |
1166 | } | |
1167 | else{ | |
1168 | last_bit_pos=buf_len-1; | |
1169 | if(fieldorder==ORDER_LSB) | |
1170 | last_bit_bitpos=7; | |
1171 | else | |
1172 | last_bit_bitpos=0; | |
1173 | } | |
1174 | } | |
1175 | ||
1176 | const unsigned char* TTCN_Buffer::get_read_data(size_t &bitpos) const | |
1177 | { | |
1178 | bitpos=bit_pos; | |
1179 | if (buf_ptr != NULL) return buf_ptr->data_ptr + buf_pos; | |
1180 | else return NULL; | |
1181 | } | |
1182 | ||
1183 | void TTCN_Buffer::set_pos(size_t pos, size_t bitpos) | |
1184 | { | |
1185 | buf_pos=pos<buf_len?pos:buf_len; | |
1186 | bit_pos=bitpos; | |
1187 | } | |
1188 | ||
1189 | ||
1190 | void TTCN_Buffer::set_pos_bit(size_t new_bit_pos) | |
1191 | { | |
1192 | size_t new_pos = new_bit_pos / 8; | |
1193 | if (new_pos < buf_len) { | |
1194 | buf_pos = new_pos; | |
1195 | bit_pos = new_bit_pos % 8; | |
1196 | } else { | |
1197 | buf_pos = buf_len; | |
1198 | bit_pos = 0; | |
1199 | } | |
1200 | } | |
1201 | ||
1202 | void TTCN_Buffer::increase_pos_bit(size_t delta) | |
1203 | { | |
1204 | size_t new_buf_pos=buf_pos+(bit_pos+delta)/8; // bytes | |
1205 | if(new_buf_pos<buf_pos || new_buf_pos>buf_len) { | |
1206 | buf_pos=buf_len; | |
1207 | bit_pos=7; | |
1208 | } | |
1209 | else { | |
1210 | buf_pos=new_buf_pos; | |
1211 | bit_pos=(bit_pos+delta)%8; | |
1212 | } | |
1213 | } | |
1214 | ||
1215 | int TTCN_Buffer::increase_pos_padd(int padding) | |
1216 | { | |
1217 | if(padding) { // <---old bit pos---> | |
1218 | size_t new_bit_pos = ((buf_pos*8 + bit_pos + padding-1)/padding) * padding; | |
1219 | int padded = new_bit_pos - buf_pos * 8 - bit_pos; | |
1220 | // padded = bits skipped to reach the next multiple of padding (bits) | |
1221 | buf_pos = new_bit_pos / 8; | |
1222 | bit_pos = new_bit_pos % 8; | |
1223 | return padded; | |
1224 | }else | |
1225 | return 0; | |
1226 | } | |
1227 | ||
1228 | size_t TTCN_Buffer::unread_len_bit() | |
1229 | { | |
1230 | return (buf_len-buf_pos)*8-bit_pos; | |
1231 | } | |
1232 | ||
1233 | void TTCN_Buffer::start_ext_bit(boolean p_reverse) | |
1234 | { | |
1235 | if (ext_level++ == 0) { | |
1236 | start_of_ext_bit = buf_len; | |
1237 | ext_bit_reverse = p_reverse; | |
1238 | } | |
1239 | } | |
1240 | ||
1241 | void TTCN_Buffer::stop_ext_bit() | |
1242 | { | |
1243 | if (ext_level <= 0) | |
1244 | TTCN_EncDec_ErrorContext::error_internal("TTCN_Buffer::stop_ext_bit() " | |
1245 | "was called without start_ext_bit()."); | |
1246 | if (--ext_level == 0) { | |
1247 | unsigned char one = current_bitorder ? 0x01 : 0x80; | |
1248 | unsigned char zero= ~one; | |
1249 | unsigned char *data_ptr = buf_ptr != NULL ? buf_ptr->data_ptr : NULL; | |
1250 | if (ext_bit_reverse) { | |
1251 | for(size_t a=start_of_ext_bit;a<buf_len-1;a++) data_ptr[a] |= one; | |
1252 | data_ptr[buf_len-1] &= zero; | |
1253 | } else { | |
1254 | for(size_t a=start_of_ext_bit;a<buf_len-1;a++) data_ptr[a] &= zero; | |
1255 | data_ptr[buf_len-1] |= one; | |
1256 | } | |
1257 | } | |
1258 | } | |
1259 | ||
1260 | void TTCN_Buffer::put_pad(size_t len, const unsigned char *s, | |
1261 | int pat_len, raw_order_t fieldorder) | |
1262 | { | |
1263 | if(len==0) return; | |
1264 | if(pat_len==0){ | |
1265 | put_zero(len,fieldorder); | |
1266 | return; | |
1267 | } | |
1268 | RAW_coding_par cp; | |
1269 | cp.bitorder=ORDER_LSB; | |
1270 | cp.byteorder=ORDER_LSB; | |
1271 | cp.fieldorder=fieldorder; | |
1272 | cp.hexorder=ORDER_LSB; | |
1273 | int length=len; | |
1274 | while(length>0){ | |
1275 | put_b(length>pat_len?pat_len:length,s,cp,0); | |
1276 | length-=pat_len; | |
1277 | } | |
1278 | } | |
1279 | ||
1280 | void TTCN_Buffer::set_last_bit(boolean p_last_bit) | |
1281 | { | |
1282 | unsigned char *last_bit_ptr = buf_ptr->data_ptr + last_bit_pos; | |
1283 | unsigned char bitmask = 0x01 << last_bit_bitpos; | |
1284 | if (p_last_bit) *last_bit_ptr |= bitmask; | |
1285 | else *last_bit_ptr &= ~bitmask; | |
1286 | } | |
1287 | ||
1288 | unsigned char TTCN_Buffer::get_byte_rev(const unsigned char* data, | |
1289 | size_t len, size_t idx) | |
1290 | { | |
1291 | unsigned char ch='\0'; | |
1292 | size_t hossz=(len+7)/8-1; | |
1293 | int bit_limit=len%8; | |
1294 | if(idx>hossz) return ch; | |
1295 | if(bit_limit==0)return data[hossz-idx]; | |
1296 | ch=data[hossz-idx]<<(8-bit_limit); | |
1297 | if((hossz-idx)>0) ch|=(data[hossz-idx-1]>>bit_limit) | |
1298 | &BitMaskTable[8-bit_limit]; | |
1299 | return ch; | |
1300 | } | |
1301 | ||
1302 | unsigned char TTCN_Buffer::get_byte_align(size_t len, | |
1303 | raw_order_t fieldorder, | |
1304 | raw_order_t req_align, | |
1305 | size_t idx) | |
1306 | { | |
1307 | if(idx>(bit_pos+len)/8) return '\0'; | |
1308 | const unsigned char *data_ptr = buf_ptr != NULL ? buf_ptr->data_ptr : NULL; | |
1309 | if(idx==0){ // first byte | |
1310 | if(fieldorder==req_align){ | |
1311 | if(fieldorder==ORDER_LSB){ | |
1312 | return data_ptr[buf_pos]>>bit_pos; | |
1313 | } | |
1314 | else {return data_ptr[buf_pos]<<bit_pos;} | |
1315 | } | |
1316 | else {return data_ptr[buf_pos];} | |
1317 | } | |
1318 | if(idx==(bit_pos+len)/8){ // last byte | |
1319 | if(fieldorder==req_align){ | |
1320 | if(fieldorder==ORDER_LSB){ | |
1321 | return data_ptr[buf_pos+idx]<<(8-(bit_pos+len)%8); | |
1322 | } | |
1323 | else {return data_ptr[buf_pos+idx]>>(8-(bit_pos+len)%8);} | |
1324 | } | |
1325 | else {return data_ptr[buf_pos+idx];} | |
1326 | } | |
1327 | return data_ptr[buf_pos+idx]; | |
1328 | } |