implemented decmatch (artf724241)
[deliverable/titan.core.git] / core / Octetstring.cc
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 * Beres, Szabolcs
13 * Delic, Adam
14 * Forstner, Matyas
15 * Kovacs, Ferenc
16 * Raduly, Csaba
17 * Szabados, Kristof
18 * Szabo, Bence Janos
19 * Szabo, Janos Zoltan – initial implementation
20 * Szalai, Gabor
21 * Tatarka, Gabor
22 * Pandi, Krisztian
23 *
24 ******************************************************************************/
25 #include "Octetstring.hh"
26 #include "../common/memory.h"
27 #include "Integer.hh"
28 #include "String_struct.hh"
29 #include "Param_Types.hh"
30 #include "Error.hh"
31 #include "Logger.hh"
32 #include "Encdec.hh"
33 #include "RAW.hh"
34 #include "BER.hh"
35 #include "TEXT.hh"
36 #include "Addfunc.hh"
37
38 #include "../common/dbgnew.hh"
39 #include <string.h>
40
41 // octetstring value class
42
43 /** The amount of memory needed for a string containing n octets. */
44 #define MEMORY_SIZE(n) (sizeof(octetstring_struct) - sizeof(int) + (n))
45
46 static const Token_Match
47 octetstring_value_match("^(([0-9A-Fa-f]{2})+).*$", TRUE);
48
49 void OCTETSTRING::init_struct(int n_octets)
50 {
51 if (n_octets < 0) {
52 val_ptr = NULL;
53 TTCN_error("Initializing an octetstring with a negative length.");
54 } else if (n_octets == 0) {
55 /* This will represent the empty strings so they won't need allocated
56 * memory, this delays the memory allocation until it is really needed.
57 */
58 static octetstring_struct empty_string = { 1, 0, "" };
59 val_ptr = &empty_string;
60 empty_string.ref_count++;
61 } else {
62 val_ptr = (octetstring_struct*)Malloc(MEMORY_SIZE(n_octets));
63 val_ptr->ref_count = 1;
64 val_ptr->n_octets = n_octets;
65 }
66 }
67
68 void OCTETSTRING::copy_value()
69 {
70 if (val_ptr == NULL || val_ptr->n_octets <= 0)
71 TTCN_error("Internal error: Invalid internal data structure when copying "
72 "the memory area of an octetstring value.");
73 if (val_ptr->ref_count > 1) {
74 octetstring_struct *old_ptr = val_ptr;
75 old_ptr->ref_count--;
76 init_struct(old_ptr->n_octets);
77 memcpy(val_ptr->octets_ptr, old_ptr->octets_ptr, old_ptr->n_octets);
78 }
79 }
80
81 // Called by operator+, operator~, operator&, operator|
82 // to initialize the return value to the appropriate capacity
83 // without copying bytes (which will be altered).
84 OCTETSTRING::OCTETSTRING(int n_octets)
85 {
86 init_struct(n_octets);
87 }
88
89 OCTETSTRING::OCTETSTRING()
90 {
91 val_ptr = NULL;
92 }
93
94 OCTETSTRING::OCTETSTRING(int n_octets, const unsigned char* octets_ptr)
95 {
96 init_struct(n_octets);
97 memcpy(val_ptr->octets_ptr, octets_ptr, n_octets);
98 }
99
100 OCTETSTRING::OCTETSTRING(const OCTETSTRING& other_value)
101 : Base_Type(other_value)
102 {
103 other_value.must_bound("Copying an unbound octetstring value.");
104 val_ptr = other_value.val_ptr;
105 val_ptr->ref_count++;
106 }
107
108 OCTETSTRING::OCTETSTRING(const OCTETSTRING_ELEMENT& other_value)
109 {
110 other_value.must_bound("Copying an unbound octetstring element.");
111 init_struct(1);
112 val_ptr->octets_ptr[0] = other_value.get_octet();
113 }
114
115 OCTETSTRING::~OCTETSTRING()
116 {
117 clean_up();
118 }
119
120 OCTETSTRING& OCTETSTRING::operator=(const OCTETSTRING& other_value)
121 {
122 other_value.must_bound("Assignment of an unbound octetstring value.");
123 if (&other_value != this) {
124 clean_up();
125 val_ptr = other_value.val_ptr;
126 val_ptr->ref_count++;
127 }
128 return *this;
129 }
130
131 OCTETSTRING& OCTETSTRING::operator=(const OCTETSTRING_ELEMENT& other_value)
132 {
133 other_value.must_bound("Assignment of an unbound octetstring element to an "
134 "octetstring.");
135 unsigned char octet_value = other_value.get_octet();
136 clean_up();
137 init_struct(1);
138 val_ptr->octets_ptr[0] = octet_value;
139 return *this;
140 }
141
142 boolean OCTETSTRING::operator==(const OCTETSTRING& other_value) const
143 {
144 must_bound("Unbound left operand of octetstring comparison.");
145 other_value.must_bound("Unbound right operand of octetstring comparison.");
146 if (val_ptr->n_octets != other_value.val_ptr->n_octets) return FALSE;
147 return !memcmp(val_ptr->octets_ptr, other_value.val_ptr->octets_ptr,
148 val_ptr->n_octets);
149 }
150
151 boolean OCTETSTRING::operator==(const OCTETSTRING_ELEMENT& other_value) const
152 {
153 must_bound("Unbound left operand of octetstring comparison.");
154 other_value.must_bound("Unbound right operand of octetstring element "
155 "comparison.");
156 if (val_ptr->n_octets != 1) return FALSE;
157 return val_ptr->octets_ptr[0] == other_value.get_octet();
158 }
159
160 OCTETSTRING OCTETSTRING::operator+(const OCTETSTRING& other_value) const
161 {
162 must_bound("Unbound left operand of octetstring concatenation.");
163 other_value.must_bound("Unbound right operand of octetstring concatenation.");
164 int left_n_octets = val_ptr->n_octets;
165 if (left_n_octets == 0) return other_value;
166 int right_n_octets = other_value.val_ptr->n_octets;
167 if (right_n_octets == 0) return *this;
168 OCTETSTRING ret_val(left_n_octets + right_n_octets);
169 memcpy(ret_val.val_ptr->octets_ptr, val_ptr->octets_ptr, left_n_octets);
170 memcpy(ret_val.val_ptr->octets_ptr + left_n_octets,
171 other_value.val_ptr->octets_ptr, right_n_octets);
172 return ret_val;
173 }
174
175 OCTETSTRING OCTETSTRING::operator+(const OCTETSTRING_ELEMENT& other_value) const
176 {
177 must_bound("Unbound left operand of octetstring concatenation.");
178 other_value.must_bound("Unbound right operand of octetstring element "
179 "concatenation.");
180 OCTETSTRING ret_val(val_ptr->n_octets + 1);
181 memcpy(ret_val.val_ptr->octets_ptr, val_ptr->octets_ptr, val_ptr->n_octets);
182 ret_val.val_ptr->octets_ptr[val_ptr->n_octets] = other_value.get_octet();
183 return ret_val;
184 }
185
186 OCTETSTRING& OCTETSTRING::operator+=(const OCTETSTRING& other_value)
187 {
188 must_bound("Appending an octetstring value to an unbound octetstring value.");
189 other_value.must_bound("Appending an unbound octetstring value to another "
190 "octetstring value.");
191 int other_n_octets = other_value.val_ptr->n_octets;
192 if (other_n_octets > 0) {
193 if (val_ptr->n_octets == 0) {
194 clean_up();
195 val_ptr = other_value.val_ptr;
196 val_ptr->ref_count++;
197 } else if (val_ptr->ref_count > 1) {
198 octetstring_struct *old_ptr = val_ptr;
199 old_ptr->ref_count--;
200 init_struct(old_ptr->n_octets + other_n_octets);
201 memcpy(val_ptr->octets_ptr, old_ptr->octets_ptr, old_ptr->n_octets);
202 memcpy(val_ptr->octets_ptr + old_ptr->n_octets,
203 other_value.val_ptr->octets_ptr, other_n_octets);
204 } else {
205 val_ptr = (octetstring_struct*)
206 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_octets + other_n_octets));
207 memcpy(val_ptr->octets_ptr + val_ptr->n_octets,
208 other_value.val_ptr->octets_ptr, other_n_octets);
209 val_ptr->n_octets += other_n_octets;
210 }
211 }
212 return *this;
213 }
214
215 OCTETSTRING& OCTETSTRING::operator+=(const OCTETSTRING_ELEMENT& other_value)
216 {
217 must_bound("Appending an octetstring element to an unbound octetstring "
218 "value.");
219 other_value.must_bound("Appending an unbound octetstring element to an "
220 "octetstring value.");
221 if (val_ptr->ref_count > 1) {
222 octetstring_struct *old_ptr = val_ptr;
223 old_ptr->ref_count--;
224 init_struct(old_ptr->n_octets + 1);
225 memcpy(val_ptr->octets_ptr, old_ptr->octets_ptr, old_ptr->n_octets);
226 val_ptr->octets_ptr[old_ptr->n_octets] = other_value.get_octet();
227 } else {
228 val_ptr = (octetstring_struct*)
229 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_octets + 1));
230 val_ptr->octets_ptr[val_ptr->n_octets] = other_value.get_octet();
231 val_ptr->n_octets++;
232 }
233 return *this;
234 }
235
236 OCTETSTRING OCTETSTRING::operator~() const
237 {
238 must_bound("Unbound octetstring operand of operator not4b.");
239 OCTETSTRING ret_val(val_ptr->n_octets);
240 for (int i = 0; i < val_ptr->n_octets; i++)
241 ret_val.val_ptr->octets_ptr[i] = ~val_ptr->octets_ptr[i];
242 return ret_val;
243 }
244
245 OCTETSTRING OCTETSTRING::operator&(const OCTETSTRING& other_value) const
246 {
247 must_bound("Left operand of operator and4b is an unbound octetstring value.");
248 other_value.must_bound("Right operand of operator and4b is an unbound "
249 "octetstring value.");
250 if (val_ptr->n_octets != other_value.val_ptr->n_octets)
251 TTCN_error("The octetstring operands of operator and4b must have the "
252 "same length.");
253 OCTETSTRING ret_val(val_ptr->n_octets);
254 for (int i = 0; i < val_ptr->n_octets; i++)
255 ret_val.val_ptr->octets_ptr[i] =
256 val_ptr->octets_ptr[i] & other_value.val_ptr->octets_ptr[i];
257 return ret_val;
258 }
259
260 OCTETSTRING OCTETSTRING::operator&(const OCTETSTRING_ELEMENT& other_value) const
261 {
262 must_bound("Left operand of operator and4b is an unbound octetstring value.");
263 other_value.must_bound("Right operand of operator and4b is an unbound "
264 "octetstring element.");
265 if (val_ptr->n_octets != 1)
266 TTCN_error("The octetstring operands of "
267 "operator and4b must have the same length.");
268 unsigned char result = val_ptr->octets_ptr[0] & other_value.get_octet();
269 return OCTETSTRING(1, &result);
270 }
271
272 OCTETSTRING OCTETSTRING::operator|(const OCTETSTRING& other_value) const
273 {
274 must_bound("Left operand of operator or4b is an unbound octetstring value.");
275 other_value.must_bound("Right operand of operator or4b is an unbound "
276 "octetstring value.");
277 if (val_ptr->n_octets != other_value.val_ptr->n_octets)
278 TTCN_error("The octetstring operands of operator or4b must have the "
279 "same length.");
280 OCTETSTRING ret_val(val_ptr->n_octets);
281 for (int i = 0; i < val_ptr->n_octets; i++)
282 ret_val.val_ptr->octets_ptr[i] =
283 val_ptr->octets_ptr[i] | other_value.val_ptr->octets_ptr[i];
284 return ret_val;
285 }
286
287 OCTETSTRING OCTETSTRING::operator|(const OCTETSTRING_ELEMENT& other_value) const
288 {
289 must_bound("Left operand of operator or4b is an unbound octetstring value.");
290 other_value.must_bound("Right operand of operator or4b is an unbound "
291 "octetstring element.");
292 if (val_ptr->n_octets != 1)
293 TTCN_error("The octetstring operands of "
294 "operator or4b must have the same length.");
295 unsigned char result = val_ptr->octets_ptr[0] | other_value.get_octet();
296 return OCTETSTRING(1, &result);
297 }
298
299 OCTETSTRING OCTETSTRING::operator^(const OCTETSTRING& other_value) const
300 {
301 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
302 other_value.must_bound("Right operand of operator xor4b is an unbound "
303 "octetstring value.");
304 if (val_ptr->n_octets != other_value.val_ptr->n_octets)
305 TTCN_error("The octetstring operands of operator xor4b must have the "
306 "same length.");
307 OCTETSTRING ret_val(val_ptr->n_octets);
308 for (int i = 0; i < val_ptr->n_octets; i++)
309 ret_val.val_ptr->octets_ptr[i] =
310 val_ptr->octets_ptr[i] ^ other_value.val_ptr->octets_ptr[i];
311 return ret_val;
312 }
313
314 OCTETSTRING OCTETSTRING::operator^(const OCTETSTRING_ELEMENT& other_value) const
315 {
316 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
317 other_value.must_bound("Right operand of operator xor4b is an unbound "
318 "octetstring element.");
319 if (val_ptr->n_octets != 1)
320 TTCN_error("The octetstring operands of "
321 "operator xor4b must have the same length.");
322 unsigned char result = val_ptr->octets_ptr[0] ^ other_value.get_octet();
323 return OCTETSTRING(1, &result);
324 }
325
326 OCTETSTRING OCTETSTRING::operator<<(int shift_count) const
327 {
328 must_bound("Unbound octetstring operand of shift left operator.");
329 if (shift_count > 0) {
330 if (val_ptr->n_octets == 0) return *this;
331 OCTETSTRING ret_val(val_ptr->n_octets);
332 if (shift_count > val_ptr->n_octets) shift_count = val_ptr->n_octets;
333 memcpy(ret_val.val_ptr->octets_ptr, val_ptr->octets_ptr + shift_count,
334 val_ptr->n_octets - shift_count);
335 memset(ret_val.val_ptr->octets_ptr + val_ptr->n_octets - shift_count,
336 0, shift_count);
337 return ret_val;
338 } else if (shift_count == 0) return *this;
339 else return *this >> (-shift_count);
340 }
341
342 OCTETSTRING OCTETSTRING::operator<<(const INTEGER& shift_count) const
343 {
344 shift_count.must_bound("Unbound right operand of octetstring shift left "
345 "operator.");
346 return *this << (int)shift_count;
347 }
348
349 OCTETSTRING OCTETSTRING::operator>>(int shift_count) const
350 {
351 must_bound("Unbound octetstring operand of shift right operator.");
352 if (shift_count > 0) {
353 if (val_ptr->n_octets == 0) return *this;
354 OCTETSTRING ret_val(val_ptr->n_octets);
355 if (shift_count > val_ptr->n_octets) shift_count = val_ptr->n_octets;
356 memset(ret_val.val_ptr->octets_ptr, 0, shift_count);
357 memcpy(ret_val.val_ptr->octets_ptr + shift_count, val_ptr->octets_ptr,
358 val_ptr->n_octets - shift_count);
359 return ret_val;
360 } else if (shift_count == 0) return *this;
361 else return *this << (-shift_count);
362 }
363
364 OCTETSTRING OCTETSTRING::operator>>(const INTEGER& shift_count) const
365 {
366 shift_count.must_bound("Unbound right operand of octetstring shift right "
367 "operator.");
368 return *this >> (int)shift_count;
369 }
370
371 OCTETSTRING OCTETSTRING::operator<<=(int rotate_count) const
372 {
373 must_bound("Unbound octetstring operand of rotate left operator.");
374 if (val_ptr->n_octets == 0) return *this;
375 if (rotate_count >= 0) {
376 rotate_count %= val_ptr->n_octets;
377 if (rotate_count == 0) return *this;
378 OCTETSTRING ret_val(val_ptr->n_octets);
379 memcpy(ret_val.val_ptr->octets_ptr, val_ptr->octets_ptr +
380 rotate_count, val_ptr->n_octets - rotate_count);
381 memcpy(ret_val.val_ptr->octets_ptr + val_ptr->n_octets - rotate_count,
382 val_ptr->octets_ptr, rotate_count);
383 return ret_val;
384 } else return *this >>= (-rotate_count);
385 }
386
387 OCTETSTRING OCTETSTRING::operator<<=(const INTEGER& rotate_count) const
388 {
389 rotate_count.must_bound("Unbound right operand of octetstring rotate left "
390 "operator.");
391 return *this <<= (int)rotate_count;
392 }
393
394 OCTETSTRING OCTETSTRING::operator>>=(int rotate_count) const
395 {
396 must_bound("Unbound octetstring operand of rotate right operator.");
397 if (val_ptr->n_octets == 0) return *this;
398 if (rotate_count >= 0) {
399 rotate_count %= val_ptr->n_octets;
400 if (rotate_count == 0) return *this;
401 OCTETSTRING ret_val(val_ptr->n_octets);
402 memcpy(ret_val.val_ptr->octets_ptr, val_ptr->octets_ptr +
403 val_ptr->n_octets - rotate_count, rotate_count);
404 memcpy(ret_val.val_ptr->octets_ptr + rotate_count,
405 val_ptr->octets_ptr, val_ptr->n_octets - rotate_count);
406 return ret_val;
407 } else return *this <<= (-rotate_count);
408 }
409
410 OCTETSTRING OCTETSTRING::operator>>=(const INTEGER& rotate_count) const
411 {
412 rotate_count.must_bound("Unbound right operand of octetstring rotate right "
413 "operator.");
414 return *this >>= (int)rotate_count;
415 }
416
417 OCTETSTRING_ELEMENT OCTETSTRING::operator[](int index_value)
418 {
419 if (val_ptr == NULL && index_value == 0) {
420 init_struct(1);
421 return OCTETSTRING_ELEMENT(FALSE, *this, 0);
422 } else {
423 must_bound("Accessing an element of an unbound octetstring value.");
424 if (index_value < 0) TTCN_error("Accessing an octetstring element using "
425 "a negative index (%d).", index_value);
426 int n_octets = val_ptr->n_octets;
427 if (index_value > n_octets) TTCN_error("Index overflow when accessing a "
428 "octetstring element: The index is %d, but the string has only %d "
429 "octets.", index_value, n_octets);
430 if (index_value == n_octets) {
431 if (val_ptr->ref_count == 1) {
432 val_ptr = (octetstring_struct*)
433 Realloc(val_ptr, MEMORY_SIZE(n_octets + 1));
434 val_ptr->n_octets++;
435 } else {
436 octetstring_struct *old_ptr = val_ptr;
437 old_ptr->ref_count--;
438 init_struct(n_octets + 1);
439 memcpy(val_ptr->octets_ptr, old_ptr->octets_ptr, n_octets);
440 }
441 return OCTETSTRING_ELEMENT(FALSE, *this, index_value);
442 } else return OCTETSTRING_ELEMENT(TRUE, *this, index_value);
443 }
444 }
445
446 OCTETSTRING_ELEMENT OCTETSTRING::operator[](const INTEGER& index_value)
447 {
448 index_value.must_bound("Indexing a octetstring value with an unbound integer "
449 "value.");
450 return (*this)[(int)index_value];
451 }
452
453 const OCTETSTRING_ELEMENT OCTETSTRING::operator[](int index_value) const
454 {
455 must_bound("Accessing an element of an unbound octetstring value.");
456 if (index_value < 0) TTCN_error("Accessing an octetstring element using a "
457 "negative index (%d).", index_value);
458 if (index_value >= val_ptr->n_octets) TTCN_error("Index overflow when "
459 "accessing a octetstring element: The index is %d, but the string has "
460 "only %d octets.", index_value, val_ptr->n_octets);
461 return OCTETSTRING_ELEMENT(TRUE, const_cast<OCTETSTRING&>(*this),
462 index_value);
463 }
464
465 const OCTETSTRING_ELEMENT OCTETSTRING::operator[](const INTEGER& index_value)
466 const
467 {
468 index_value.must_bound("Indexing a octetstring value with an unbound integer "
469 "value.");
470 return (*this)[(int)index_value];
471 }
472
473 void OCTETSTRING::clean_up()
474 {
475 if (val_ptr != NULL) {
476 if (val_ptr->ref_count > 1) val_ptr->ref_count--;
477 else if (val_ptr->ref_count == 1) Free(val_ptr);
478 else TTCN_error("Internal error: Invalid reference counter in an "
479 "octetstring value.");
480 val_ptr = NULL;
481 }
482 }
483
484 int OCTETSTRING::lengthof() const
485 {
486 must_bound("Getting the length of an unbound octetstring value.");
487 return val_ptr->n_octets;
488 }
489
490 OCTETSTRING::operator const unsigned char*() const
491 {
492 must_bound("Casting an unbound octetstring value to const unsigned char*.");
493 return val_ptr->octets_ptr;
494 }
495
496 void OCTETSTRING::log() const
497 {
498 if (val_ptr != NULL) {
499 boolean only_printable = TRUE;
500 TTCN_Logger::log_char('\'');
501 for (int i = 0; i < val_ptr->n_octets; i++) {
502 unsigned char octet = val_ptr->octets_ptr[i];
503 TTCN_Logger::log_octet(octet);
504 if (only_printable && !TTCN_Logger::is_printable(octet))
505 only_printable = FALSE;
506 }
507 TTCN_Logger::log_event_str("'O");
508 if (only_printable && val_ptr->n_octets > 0) {
509 TTCN_Logger::log_event_str(" (\"");
510 for (int i = 0; i < val_ptr->n_octets; i++)
511 TTCN_Logger::log_char_escaped(val_ptr->octets_ptr[i]);
512 TTCN_Logger::log_event_str("\")");
513 }
514 } else TTCN_Logger::log_event_unbound();
515 }
516
517 void OCTETSTRING::set_param(Module_Param& param) {
518 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "octetstring value");
519 Module_Param_Ptr mp = &param;
520 if (param.get_type() == Module_Param::MP_Reference) {
521 mp = param.get_referenced_param();
522 }
523 switch (mp->get_type()) {
524 case Module_Param::MP_Octetstring:
525 switch (param.get_operation_type()) {
526 case Module_Param::OT_ASSIGN:
527 clean_up();
528 init_struct(mp->get_string_size());
529 memcpy(val_ptr->octets_ptr, mp->get_string_data(), val_ptr->n_octets);
530 break;
531 case Module_Param::OT_CONCAT:
532 if (is_bound()) {
533 *this += OCTETSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
534 } else {
535 *this = OCTETSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
536 }
537 break;
538 default:
539 TTCN_error("Internal error: OCTETSTRING::set_param()");
540 }
541 break;
542 case Module_Param::MP_Expression:
543 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
544 OCTETSTRING operand1, operand2;
545 operand1.set_param(*mp->get_operand1());
546 operand2.set_param(*mp->get_operand2());
547 if (param.get_operation_type() == Module_Param::OT_CONCAT) {
548 *this = *this + operand1 + operand2;
549 }
550 else {
551 *this = operand1 + operand2;
552 }
553 }
554 else {
555 param.expr_type_error("a octetstring");
556 }
557 break;
558 default:
559 param.type_error("octetstring value");
560 break;
561 }
562 }
563
564 Module_Param* OCTETSTRING::get_param(Module_Param_Name& /* param_name */) const
565 {
566 if (!is_bound()) {
567 return new Module_Param_Unbound();
568 }
569 unsigned char* val_cpy = (unsigned char *)Malloc(val_ptr->n_octets);
570 memcpy(val_cpy, val_ptr->octets_ptr, val_ptr->n_octets);
571 return new Module_Param_Octetstring(val_ptr->n_octets, val_cpy);
572 }
573
574 void OCTETSTRING::encode_text(Text_Buf& text_buf) const
575 {
576 must_bound("Text encoder: Encoding an unbound octetstring value.");
577 text_buf.push_int(val_ptr->n_octets);
578 if(val_ptr->n_octets > 0)
579 text_buf.push_raw(val_ptr->n_octets, val_ptr->octets_ptr);
580 }
581
582 void OCTETSTRING::decode_text(Text_Buf& text_buf)
583 {
584 int n_octets = text_buf.pull_int().get_val();
585 if (n_octets < 0)
586 TTCN_error("Text decoder: Invalid length was received for an octetstring.");
587 clean_up();
588 init_struct(n_octets);
589 if (n_octets > 0) text_buf.pull_raw(n_octets, val_ptr->octets_ptr);
590 }
591
592 void OCTETSTRING::encode(const TTCN_Typedescriptor_t& p_td,
593 TTCN_Buffer& p_buf,
594 TTCN_EncDec::coding_t p_coding, ...) const
595 {
596 va_list pvar;
597 va_start(pvar, p_coding);
598 switch(p_coding) {
599 case TTCN_EncDec::CT_BER: {
600 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
601 unsigned BER_coding=va_arg(pvar, unsigned);
602 BER_encode_chk_coding(BER_coding);
603 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
604 tlv->put_in_buffer(p_buf);
605 ASN_BER_TLV_t::destruct(tlv);
606 break;}
607 case TTCN_EncDec::CT_RAW: {
608 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
609 if(!p_td.raw)
610 TTCN_EncDec_ErrorContext::error_internal
611 ("No RAW descriptor available for type '%s'.", p_td.name);
612 RAW_enc_tr_pos rp;
613 rp.level=0;
614 rp.pos=NULL;
615 RAW_enc_tree root(true,NULL,&rp,1,p_td.raw);
616 RAW_encode(p_td, root);
617 root.put_to_buf(p_buf);
618 break;}
619 case TTCN_EncDec::CT_TEXT: {
620 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
621 if(!p_td.text)
622 TTCN_EncDec_ErrorContext::error_internal
623 ("No TEXT descriptor available for type '%s'.", p_td.name);
624 TEXT_encode(p_td,p_buf);
625 break;}
626 case TTCN_EncDec::CT_XER: {
627 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
628 unsigned XER_coding=va_arg(pvar, unsigned);
629 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
630 break;}
631 case TTCN_EncDec::CT_JSON: {
632 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
633 if(!p_td.json)
634 TTCN_EncDec_ErrorContext::error_internal
635 ("No JSON descriptor available for type '%s'.", p_td.name);
636 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
637 JSON_encode(p_td, tok);
638 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
639 break;}
640 default:
641 TTCN_error("Unknown coding method requested to encode type '%s'",
642 p_td.name);
643 }
644 va_end(pvar);
645 }
646
647 void OCTETSTRING::decode(const TTCN_Typedescriptor_t& p_td,
648 TTCN_Buffer& p_buf,
649 TTCN_EncDec::coding_t p_coding, ...)
650 {
651 va_list pvar;
652 va_start(pvar, p_coding);
653 switch(p_coding) {
654 case TTCN_EncDec::CT_BER: {
655 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
656 unsigned L_form=va_arg(pvar, unsigned);
657 ASN_BER_TLV_t tlv;
658 BER_decode_str2TLV(p_buf, tlv, L_form);
659 BER_decode_TLV(p_td, tlv, L_form);
660 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
661 break;}
662 case TTCN_EncDec::CT_RAW: {
663 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
664 if(!p_td.raw)
665 TTCN_EncDec_ErrorContext::error_internal
666 ("No RAW descriptor available for type '%s'.", p_td.name);
667 raw_order_t order;
668 switch(p_td.raw->top_bit_order){
669 case TOP_BIT_LEFT:
670 order=ORDER_LSB;
671 break;
672 case TOP_BIT_RIGHT:
673 default:
674 order=ORDER_MSB;
675 }
676 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
677 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
678 "Can not decode type '%s', because invalid or incomplete"
679 " message was received"
680 , p_td.name);
681 break;}
682 case TTCN_EncDec::CT_TEXT: {
683 Limit_Token_List limit;
684 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
685 if(!p_td.text)
686 TTCN_EncDec_ErrorContext::error_internal
687 ("No TEXT descriptor available for type '%s'.", p_td.name);
688 const unsigned char *b=p_buf.get_data();
689 if(b[p_buf.get_len()-1]!='\0'){
690 p_buf.set_pos(p_buf.get_len());
691 p_buf.put_zero(8,ORDER_LSB);
692 p_buf.rewind();
693 }
694 if(TEXT_decode(p_td,p_buf,limit)<0)
695 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
696 "Can not decode type '%s', because invalid or incomplete"
697 " message was received"
698 , p_td.name);
699 break;}
700 case TTCN_EncDec::CT_XER: {
701 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
702 unsigned XER_coding=va_arg(pvar, unsigned);
703 XmlReaderWrap reader(p_buf);
704 int success = reader.Read();
705 for (; success==1; success=reader.Read()) {
706 int type = reader.NodeType();
707 if (type==XML_READER_TYPE_ELEMENT)
708 break;
709 }
710 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
711 size_t bytes = reader.ByteConsumed();
712 p_buf.set_pos(bytes);
713 break;}
714 case TTCN_EncDec::CT_JSON: {
715 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
716 if(!p_td.json)
717 TTCN_EncDec_ErrorContext::error_internal
718 ("No JSON descriptor available for type '%s'.", p_td.name);
719 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
720 if(JSON_decode(p_td, tok, false)<0)
721 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
722 "Can not decode type '%s', because invalid or incomplete"
723 " message was received"
724 , p_td.name);
725 p_buf.set_pos(tok.get_buf_pos());
726 break;}
727 default:
728 TTCN_error("Unknown coding method requested to decode type '%s'",
729 p_td.name);
730 }
731 va_end(pvar);
732 }
733
734 ASN_BER_TLV_t*
735 OCTETSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
736 unsigned p_coding) const
737 {
738 BER_chk_descr(p_td);
739 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
740 if(!new_tlv) {
741 new_tlv=BER_encode_TLV_OCTETSTRING
742 (p_coding, val_ptr->n_octets, val_ptr->octets_ptr);
743 }
744 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
745 return new_tlv;
746 }
747
748 #ifdef TITAN_RUNTIME_2
749 ASN_BER_TLV_t* OCTETSTRING::BER_encode_negtest_raw() const
750 {
751 unsigned char *p_Vstr = (unsigned char *)Malloc(val_ptr->n_octets);
752 memcpy(p_Vstr, val_ptr->octets_ptr, val_ptr->n_octets);
753 ASN_BER_TLV_t* new_tlv = ASN_BER_TLV_t::construct(val_ptr->n_octets, p_Vstr);
754 return new_tlv;
755 }
756
757 int OCTETSTRING::encode_raw(TTCN_Buffer& p_buf) const
758 {
759 p_buf.put_string(*this);
760 return val_ptr ? val_ptr->n_octets : 0;
761 }
762
763 int OCTETSTRING::RAW_encode_negtest_raw(RAW_enc_tree& p_myleaf) const
764 {
765 if (p_myleaf.must_free)
766 Free(p_myleaf.body.leaf.data_ptr);
767 p_myleaf.must_free = false;
768 p_myleaf.data_ptr_used = true;
769 p_myleaf.body.leaf.data_ptr = val_ptr->octets_ptr;
770 return p_myleaf.length = val_ptr->n_octets * 8;
771 }
772
773 int OCTETSTRING::JSON_encode_negtest_raw(JSON_Tokenizer& p_tok) const
774 {
775 if (val_ptr != NULL) {
776 p_tok.put_raw_data((const char*)val_ptr->octets_ptr, val_ptr->n_octets);
777 return val_ptr->n_octets;
778 }
779 return 0;
780 }
781 #endif
782
783 boolean OCTETSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
784 const ASN_BER_TLV_t& p_tlv,
785 unsigned L_form)
786 {
787 clean_up();
788 BER_chk_descr(p_td);
789 ASN_BER_TLV_t stripped_tlv;
790 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
791 TTCN_EncDec_ErrorContext ec("While decoding OCTETSTRING type: ");
792 /* Upper estimation for the length. */
793 size_t stripped_tlv_len = stripped_tlv.get_len();
794 if (stripped_tlv_len < 2) return FALSE;
795 int max_len = stripped_tlv_len - 2;
796 init_struct(max_len);
797 unsigned int octetnum_start = 0;
798 BER_decode_TLV_OCTETSTRING(stripped_tlv, L_form, octetnum_start,
799 val_ptr->n_octets, val_ptr->octets_ptr);
800 if (val_ptr->n_octets < max_len) {
801 if (val_ptr->n_octets == 0) {
802 clean_up();
803 init_struct(0);
804 } else {
805 val_ptr = (octetstring_struct*)
806 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_octets));
807 }
808 }
809 return TRUE;
810 }
811
812 int OCTETSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
813 TTCN_Buffer& buff, Limit_Token_List& limit,
814 boolean no_err, boolean /*first_call*/)
815 {
816 int decoded_length=0;
817 int str_len=0;
818 clean_up();
819 if(p_td.text->begin_decode){
820 int tl;
821 if((tl=p_td.text->begin_decode->match_begin(buff))<0){
822 if(no_err)return -1;
823 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
824 "The specified token '%s' not found for '%s': ",
825 (const char*)*(p_td.text->begin_decode), p_td.name);
826 return 0;
827 }
828 decoded_length+=tl;
829 buff.increase_pos(tl);
830 }
831 // never returns "too short"
832 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
833
834 if(p_td.text->select_token){
835 int tl;
836 if((tl=p_td.text->select_token->match_begin(buff))<0) {
837 if(no_err) return -1;
838 else tl=0;
839 }
840 str_len=tl;
841 } else
842 if( p_td.text->val.parameters
843 && p_td.text->val.parameters->decoding_params.min_length!=-1){
844 str_len=p_td.text->val.parameters->decoding_params.min_length*2;
845 } else if(p_td.text->end_decode){
846 int tl;
847 if((tl=p_td.text->end_decode->match_first(buff))<0) {
848 if(no_err) return -1;
849 else tl=0;
850 }
851 str_len=tl;
852 } else if (limit.has_token()){
853 int tl;
854 if((tl=limit.match(buff))<0)
855 tl=buff.get_read_len()-1;;
856 str_len=tl;
857 } else {
858 int tl;
859 if((tl=octetstring_value_match.match_begin(buff))<0) {
860 if(no_err) {return -1; }
861 else tl=0;
862 }
863 str_len=tl;
864 }
865 str_len=(str_len/2)*2;
866 //printf("HALI chr:%d ",str_len);
867 int n_octets = str_len / 2;
868 init_struct(n_octets);
869 unsigned char *octets_ptr = val_ptr->octets_ptr;
870 const char *value=(const char*)buff.get_read_data();
871 for (int i = 0; i < n_octets; i++) {
872 unsigned char upper_nibble = char_to_hexdigit(value[2 * i]);
873 unsigned char lower_nibble = char_to_hexdigit(value[2 * i + 1]);
874 if (upper_nibble > 0x0F){
875 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
876 "The octetstring value may contain hexadecimal digits only. "
877 "Character \"%c\" was found.", value[2 * i]);
878 upper_nibble=0;
879 }
880 if (lower_nibble > 0x0F){
881 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
882 "The octetstring value str2oct() may contain hexadecimal digits only. "
883 "Character \"%c\" was found.", value[2 * i + 1]);
884 lower_nibble=0;
885 }
886 octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
887 }
888
889 //printf("%s\n\r",val_ptr->chars_ptr);
890 decoded_length+=str_len;
891 buff.increase_pos(str_len);
892
893 if(p_td.text->end_decode){
894 int tl;
895 if((tl=p_td.text->end_decode->match_begin(buff))<0){
896 if(no_err)return -1;
897 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
898 "The specified token '%s' not found for '%s': ",
899 (const char*)*(p_td.text->end_decode), p_td.name);
900 return 0;
901 }
902 decoded_length+=tl;
903 buff.increase_pos(tl);
904 }
905 return decoded_length;
906 }
907
908 // From Charstring.cc
909 extern char base64_decoder_table[256];
910 extern unsigned int xlate(cbyte* in, int phase, unsigned char* dest);
911 extern const char cb64[];
912
913 int OCTETSTRING::XER_encode(const XERdescriptor_t& p_td,
914 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
915 {
916 if(!is_bound()) {
917 TTCN_EncDec_ErrorContext::error
918 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound octetstring value.");
919 }
920 int exer = is_exer(flavor |= SIMPLE_TYPE);
921 // SIMPLE_TYPE has no influence on is_exer, we set it for later
922 int encoded_length=(int)p_buf.get_len();
923 int empty_element = val_ptr==NULL || val_ptr->n_octets == 0;
924
925 flavor &= ~XER_RECOF; // octetstring doesn't care
926 begin_xml(p_td, p_buf, flavor, indent, empty_element);
927
928 if (exer && (p_td.xer_bits & BASE_64)) {
929 // bit more work
930 size_t clear_len = lengthof();
931 const unsigned char * in = operator const unsigned char*();
932
933 /* Encode 3 bytes of cleartext into 4 bytes of Base64.
934 * Note that the algorithm is slightly different from Charstring.cc:
935 * we can't pad the source because it's const (this),
936 * so we need to check the indexes i+1 and i+2 before dereferencing */
937 for (size_t i = 0; i < clear_len; i += 3) {
938 p_buf.put_c( cb64[ in[i] >> 2 ] );
939 p_buf.put_c( cb64[ ((in[i] & 0x03) << 4) | (i+1 < clear_len
940 ? ((in[i+1] & 0xf0) >> 4)
941 :-0) ] );
942 p_buf.put_c( i+1 < clear_len
943 ? cb64[ ((in[i+1] & 0x0f) << 2) | (i+2 < clear_len ? ((in[i+2] & 0xc0) >> 6) :-0) ]
944 :'=');
945 p_buf.put_c( i+2 < clear_len ? cb64[ in[i+2] & 0x3f ] : '=' );
946 } // next i
947 }
948 else {
949 CHARSTRING val = oct2str(*this);
950 p_buf.put_string(val);
951 }
952
953 end_xml(p_td, p_buf, flavor, indent, empty_element);
954
955 return (int)p_buf.get_len() - encoded_length;
956 }
957
958 int OCTETSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
959 unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
960 {
961 int exer = is_exer(flavor);
962 int success = reader.Ok(), depth = -1, type;
963 boolean own_tag = !is_exerlist(flavor) && !(exer && (p_td.xer_bits & UNTAGGED));
964
965 const char * value = 0;
966 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
967 const char * name = verify_name(reader, p_td, exer);
968 (void)name;
969 }
970 else
971 if (own_tag) for (; success == 1; success = reader.Read()) {
972 type = reader.NodeType();
973 if (XML_READER_TYPE_ELEMENT == type) {
974 verify_name(reader, p_td, exer);
975 depth = reader.Depth();
976 if (reader.IsEmptyElement()) {
977 if (exer && p_td.dfeValue != 0) {
978 *this = *static_cast<const OCTETSTRING*> (p_td.dfeValue);
979 }
980 else init_struct(0);
981 reader.Read();
982 goto finished;
983 }
984 }
985 else if (XML_READER_TYPE_TEXT == type && depth != -1) break;
986 else if (XML_READER_TYPE_END_ELEMENT == type) {
987 // End tag without intervening #text == empty content
988 verify_end(reader, p_td, depth, exer);
989 if (exer && p_td.dfeValue != 0) {
990 *this = *static_cast<const OCTETSTRING*>(p_td.dfeValue);
991 }
992 else init_struct(0);
993 reader.Read();
994 goto finished;
995 }
996 }
997
998 type = reader.NodeType();
999 if (success == 1 && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_ATTRIBUTE == type)) {
1000 value = (const char *)reader.Value();
1001 size_t len = value ? strlen(value) : 0;
1002
1003 if (exer && (p_td.xer_bits & BASE_64)) {
1004 xmlChar in[4];
1005
1006 int phase = 0;
1007 init_struct(len * 3 / 4);
1008 unsigned char * dest = val_ptr->octets_ptr;
1009
1010 for (size_t o=0; o<len; ++o) {
1011 xmlChar c = value[o];
1012 if(c == '=') { // padding starts
1013 dest += xlate(in, phase, dest);
1014 break;
1015 }
1016
1017 int val = base64_decoder_table[c];
1018 if(val >= 0) {
1019 in[phase] = val;
1020 phase = (phase + 1) % 4;
1021 if(phase == 0) {
1022 dest += xlate(in,phase, dest);
1023 in[0]=in[1]=in[2]=in[3]=0;
1024 }
1025 }
1026 else if (exer && (flavor & EXIT_ON_ERROR)) {
1027 clean_up();
1028 return -1;
1029 } else {
1030 TTCN_EncDec_ErrorContext::warning(
1031 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1032 "Invalid character for Base64 '%02X'", c);
1033 }
1034 } // while
1035 // adjust
1036 val_ptr->n_octets = dest - val_ptr->octets_ptr;
1037
1038 }
1039 else { // not base64
1040 if (len & 1) { // that's odd...
1041 if (exer && (flavor & EXIT_ON_ERROR)) {
1042 clean_up();
1043 return -1;
1044 } else {
1045 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1046 "Odd number of characters in octetstring");
1047 len &= ~1; // make it even
1048 }
1049 }
1050 size_t n_octets = len / 2;
1051 init_struct(n_octets);
1052
1053 len = 0; // will act as 2*i
1054 for (size_t i = 0; i < n_octets; ++i, ++++len) {
1055 unsigned char upper_nibble = char_to_hexdigit(value[len]);
1056 unsigned char lower_nibble = char_to_hexdigit(value[len+1]);
1057 if (upper_nibble > 0x0F) {
1058 if (exer && (flavor & EXIT_ON_ERROR)) {
1059 clean_up();
1060 return -1;
1061 } else {
1062 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1063 "The octetstring value may contain hexadecimal digits only. "
1064 "Character \"%c\" was found.", value[len]);
1065 upper_nibble=0;
1066 }
1067 }
1068 if (lower_nibble > 0x0F) {
1069 if (exer && (flavor & EXIT_ON_ERROR)) {
1070 clean_up();
1071 return -1;
1072 } else {
1073 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1074 "The octetstring value may contain hexadecimal digits only. "
1075 "Character \"%c\" was found.", value[len+1]);
1076 lower_nibble=0;
1077 }
1078 }
1079 val_ptr->octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
1080 } // next
1081 } // if base64
1082 } // if success
1083
1084 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1085 // Let the caller do reader.AdvanceAttribute();
1086 }
1087 else
1088 if (own_tag) for (success = reader.Read(); success == 1; success = reader.Read()) {
1089 type = reader.NodeType();
1090 if (XML_READER_TYPE_END_ELEMENT == type) {
1091 verify_end(reader, p_td, depth, exer);
1092 if (val_ptr == 0 && p_td.dfeValue != 0) {
1093 // The end tag must have followed the start tag
1094 *this = *static_cast<const OCTETSTRING*>(p_td.dfeValue);
1095 }
1096 reader.Read(); // one last time
1097 break;
1098 }
1099 }
1100 finished:
1101 return 1; // decode successful
1102 }
1103
1104 int OCTETSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1105 TTCN_Buffer& buff) const{
1106 int encoded_length=0;
1107 if(p_td.text->begin_encode){
1108 buff.put_cs(*p_td.text->begin_encode);
1109 encoded_length+=p_td.text->begin_encode->lengthof();
1110 }
1111 if(!is_bound()) {
1112 TTCN_EncDec_ErrorContext::error
1113 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
1114 if(p_td.text->end_encode){
1115 buff.put_cs(*p_td.text->end_encode);
1116 encoded_length+=p_td.text->end_encode->lengthof();
1117 }
1118 return encoded_length;
1119 }
1120
1121 int chars_before=0;
1122
1123 if(p_td.text->val.parameters){
1124 if(val_ptr->n_octets<p_td.text->val.parameters->coding_params.min_length){
1125 chars_before=(p_td.text->
1126 val.parameters->coding_params.min_length-val_ptr->n_octets)*2;
1127 }
1128 }
1129
1130 if(chars_before){
1131 unsigned char* p=NULL;
1132 size_t len=chars_before;
1133 buff.get_end(p,len);
1134 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)'0';
1135 buff.increase_length(chars_before);
1136 encoded_length+=chars_before;
1137 }
1138
1139 if(val_ptr->n_octets){
1140 unsigned char* p=NULL;
1141 size_t len=val_ptr->n_octets*2;
1142 buff.get_end(p,len);
1143 len=val_ptr->n_octets;
1144 for(size_t i=0;i<len;i++){
1145 p[2 * i] = hexdigit_to_char(val_ptr->octets_ptr[i] >> 4);
1146 p[2 * i + 1] = hexdigit_to_char(val_ptr->octets_ptr[i] & 0x0F);
1147 }
1148 buff.increase_length(len*2);
1149 encoded_length+=len*2;
1150 }
1151
1152
1153 if(p_td.text->end_encode){
1154 buff.put_cs(*p_td.text->end_encode);
1155 encoded_length+=p_td.text->end_encode->lengthof();
1156 }
1157 return encoded_length;
1158 }
1159
1160 int OCTETSTRING::RAW_encode(const TTCN_Typedescriptor_t& p_td,
1161 RAW_enc_tree& myleaf) const
1162 {
1163 if (!is_bound()) {
1164 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1165 "Encoding an unbound value.");
1166 }
1167 unsigned char *bc;
1168 int bl = val_ptr->n_octets * 8;
1169 int align_length = p_td.raw->fieldlength ? p_td.raw->fieldlength - bl : 0;
1170 int blength = val_ptr->n_octets;
1171 if ((bl + align_length) < val_ptr->n_octets * 8) {
1172 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1173 "There are insufficient bits to encode '%s': ", p_td.name);
1174 blength = p_td.raw->fieldlength / 8;
1175 bl = p_td.raw->fieldlength;
1176 align_length = 0;
1177 }
1178 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
1179 myleaf.must_free = false;
1180 myleaf.data_ptr_used = true;
1181 if (p_td.raw->extension_bit != EXT_BIT_NO
1182 && myleaf.coding_par.bitorder == ORDER_MSB) {
1183 if (blength > RAW_INT_ENC_LENGTH) {
1184 myleaf.body.leaf.data_ptr = bc = (unsigned char*)Malloc(blength*sizeof(*bc));
1185 myleaf.must_free = true;
1186 myleaf.data_ptr_used = true;
1187 }
1188 else {
1189 bc = myleaf.body.leaf.data_array;
1190 myleaf.data_ptr_used = false;
1191 }
1192 for (int a = 0; a < blength; a++) bc[a] = val_ptr->octets_ptr[a] << 1;
1193 }
1194 else myleaf.body.leaf.data_ptr = val_ptr->octets_ptr;
1195 if (p_td.raw->endianness == ORDER_MSB) myleaf.align = -align_length;
1196 else myleaf.align = align_length;
1197 return myleaf.length = bl + align_length;
1198 }
1199
1200 int OCTETSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td,
1201 TTCN_Buffer& buff, int limit, raw_order_t top_bit_ord, boolean no_err,
1202 int /*sel_field*/, boolean /*first_call*/)
1203 {
1204 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
1205 limit -= prepaddlength;
1206 int decode_length = p_td.raw->fieldlength == 0
1207 ? (limit / 8) * 8 : p_td.raw->fieldlength;
1208 if (decode_length > limit || decode_length > (int) buff.unread_len_bit()) {
1209 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
1210 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1211 "There is not enough bits in the buffer to decode type %s.", p_td.name);
1212 decode_length = ((limit > (int) buff.unread_len_bit()
1213 ? (int)buff.unread_len_bit() : limit) / 8) * 8;
1214 }
1215 RAW_coding_par cp;
1216 bool orders = false;
1217 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = true;
1218 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1219 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
1220 orders = false;
1221 if (p_td.raw->byteorder == ORDER_MSB) orders = true;
1222 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1223 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
1224 cp.fieldorder = p_td.raw->fieldorder;
1225 cp.hexorder = ORDER_LSB;
1226 if (p_td.raw->extension_bit != EXT_BIT_NO) {
1227 const unsigned char* data = buff.get_read_data();
1228 int count = 1;
1229 int rot = top_bit_ord == ORDER_LSB ? 0 : 7;
1230 if (p_td.raw->extension_bit == EXT_BIT_YES) {
1231 while (((data[count - 1] >> rot) & 0x01) == 0 && count * 8 < decode_length)
1232 count++;
1233 }
1234 else {
1235 while (((data[count - 1] >> rot) & 0x01) == 1 && count * 8 < decode_length)
1236 count++;
1237 }
1238 decode_length = count * 8;
1239 }
1240 clean_up();
1241 init_struct(decode_length / 8);
1242 buff.get_b((size_t) decode_length, val_ptr->octets_ptr, cp, top_bit_ord);
1243
1244 if (p_td.raw->length_restrition != -1) {
1245 val_ptr->n_octets = p_td.raw->length_restrition;
1246 if (p_td.raw->endianness == ORDER_MSB) memmove(val_ptr->octets_ptr,
1247 val_ptr->octets_ptr + (decode_length / 8 - val_ptr->n_octets),
1248 val_ptr->n_octets * sizeof(unsigned char));
1249 }
1250 if (p_td.raw->extension_bit != EXT_BIT_NO && cp.bitorder == ORDER_MSB) {
1251 for (int a = 0; a < decode_length / 8; a++)
1252 val_ptr->octets_ptr[a] = val_ptr->octets_ptr[a] >> 1 | val_ptr->octets_ptr[a] << 7;
1253 }
1254 decode_length += buff.increase_pos_padd(p_td.raw->padding);
1255 return decode_length + prepaddlength;
1256 }
1257
1258 void OCTETSTRING::dump () const
1259 {
1260 if (val_ptr != NULL) {
1261 printf("octetstring(%d) :\n", val_ptr->n_octets);
1262 for (int i = 0; i < val_ptr->n_octets; i++) {
1263 printf("%02X ", val_ptr->octets_ptr[i]);
1264 }
1265 printf("\n");
1266 }
1267 }
1268
1269 int OCTETSTRING::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1270 {
1271 if (!is_bound()) {
1272 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1273 "Encoding an unbound octetstring value.");
1274 return -1;
1275 }
1276
1277 char* tmp_str = (char*)Malloc(val_ptr->n_octets * 2 + 3);
1278 tmp_str[0] = '\"';
1279 tmp_str[val_ptr->n_octets * 2 + 1] = '\"';
1280 for(int i = 0; i < val_ptr->n_octets; ++i) {
1281 tmp_str[2 * i + 1] = hexdigit_to_char(val_ptr->octets_ptr[i] >> 4);
1282 tmp_str[2 * i + 2] = hexdigit_to_char(val_ptr->octets_ptr[i] & 0x0F);
1283 }
1284 tmp_str[val_ptr->n_octets * 2 + 2] = 0;
1285 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
1286 Free(tmp_str);
1287 return enc_len;
1288 }
1289
1290 int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1291 {
1292 json_token_t token = JSON_TOKEN_NONE;
1293 char* value = 0;
1294 size_t value_len = 0;
1295 boolean error = false;
1296 int dec_len = 0;
1297 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1298 if (use_default) {
1299 // No JSON data in the buffer -> use default value
1300 value = (char*)p_td.json->default_value;
1301 value_len = strlen(value);
1302 } else {
1303 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1304 }
1305 if (JSON_TOKEN_ERROR == token) {
1306 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1307 return JSON_ERROR_FATAL;
1308 }
1309 else if (JSON_TOKEN_STRING == token || use_default) {
1310 if (0 == value_len % 2 && (use_default ||
1311 (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"'))) {
1312 if (!use_default) {
1313 // The default value doesn't have quotes around it
1314 value_len -= 2;
1315 ++value;
1316 }
1317 size_t octets = value_len / 2;
1318 init_struct(octets);
1319 for (size_t i = 0; i < octets; ++i) {
1320 unsigned char upper_nibble = char_to_hexdigit(value[2 * i]);
1321 unsigned char lower_nibble = char_to_hexdigit(value[2 * i + 1]);
1322 if (upper_nibble <= 0x0F && lower_nibble <= 0x0F) {
1323 val_ptr->octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
1324 } else {
1325 error = true;
1326 }
1327 }
1328 } else {
1329 error = true;
1330 }
1331 } else {
1332 return JSON_ERROR_INVALID_TOKEN;
1333 }
1334
1335 if (error) {
1336 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "octetstring");
1337 if (p_silent) {
1338 clean_up();
1339 }
1340 return JSON_ERROR_FATAL;
1341 }
1342 return dec_len;
1343 }
1344
1345 // octetstring element class
1346
1347 OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag,
1348 OCTETSTRING& par_str_val, int par_octet_pos)
1349 : bound_flag(par_bound_flag), str_val(par_str_val), octet_pos(par_octet_pos)
1350 {
1351 }
1352
1353 OCTETSTRING_ELEMENT& OCTETSTRING_ELEMENT::operator=
1354 (const OCTETSTRING& other_value)
1355 {
1356 other_value.must_bound("Assignment of an unbound octetstring value.");
1357 if(other_value.val_ptr->n_octets != 1)
1358 TTCN_error("Assignment of an octetstring "
1359 "with length other than 1 to an octetstring element.");
1360 bound_flag = TRUE;
1361 str_val.copy_value();
1362 str_val.val_ptr->octets_ptr[octet_pos] = other_value.val_ptr->octets_ptr[0];
1363 return *this;
1364 }
1365
1366 OCTETSTRING_ELEMENT& OCTETSTRING_ELEMENT::operator=
1367 (const OCTETSTRING_ELEMENT& other_value)
1368 {
1369 other_value.must_bound("Assignment of an unbound octetstring element.");
1370 if (&other_value != this) {
1371 bound_flag = TRUE;
1372 str_val.copy_value();
1373 str_val.val_ptr->octets_ptr[octet_pos] =
1374 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1375 }
1376 return *this;
1377 }
1378
1379 boolean OCTETSTRING_ELEMENT::operator==(const OCTETSTRING& other_value) const
1380 {
1381 must_bound("Unbound left operand of octetstring element comparison.");
1382 other_value.must_bound("Unbound right operand of octetstring comparison.");
1383 if(other_value.val_ptr->n_octets != 1) return FALSE;
1384 return str_val.val_ptr->octets_ptr[octet_pos] ==
1385 other_value.val_ptr->octets_ptr[0];
1386 }
1387
1388 boolean OCTETSTRING_ELEMENT::operator==
1389 (const OCTETSTRING_ELEMENT& other_value) const
1390 {
1391 must_bound("Unbound left operand of octetstring element comparison.");
1392 other_value.must_bound("Unbound right operand of octetstring element "
1393 "comparison.");
1394 return str_val.val_ptr->octets_ptr[octet_pos] ==
1395 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1396 }
1397
1398 OCTETSTRING OCTETSTRING_ELEMENT::operator+(const OCTETSTRING& other_value) const
1399 {
1400 must_bound("Unbound left operand of octetstring element concatenation.");
1401 other_value.must_bound("Unbound right operand of octetstring concatenation.");
1402 OCTETSTRING ret_val(other_value.val_ptr->n_octets + 1);
1403 ret_val.val_ptr->octets_ptr[0] = str_val.val_ptr->octets_ptr[octet_pos];
1404 memcpy(ret_val.val_ptr->octets_ptr + 1,
1405 other_value.val_ptr->octets_ptr, other_value.val_ptr->n_octets);
1406 return ret_val;
1407 }
1408
1409 OCTETSTRING OCTETSTRING_ELEMENT::operator+
1410 (const OCTETSTRING_ELEMENT& other_value) const
1411 {
1412 must_bound("Unbound left operand of octetstring element concatenation.");
1413 other_value.must_bound("Unbound right operand of octetstring element "
1414 "concatenation.");
1415 unsigned char result[2];
1416 result[0] = str_val.val_ptr->octets_ptr[octet_pos];
1417 result[1] = other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1418 return OCTETSTRING(2, result);
1419 }
1420
1421 OCTETSTRING OCTETSTRING_ELEMENT::operator~() const
1422 {
1423 must_bound("Unbound octetstring element operand of operator not4b.");
1424 unsigned char result = ~str_val.val_ptr->octets_ptr[octet_pos];
1425 return OCTETSTRING(1, &result);
1426 }
1427
1428 OCTETSTRING OCTETSTRING_ELEMENT::operator&(const OCTETSTRING& other_value) const
1429 {
1430 must_bound("Left operand of operator and4b is an unbound octetstring "
1431 "element.");
1432 other_value.must_bound("Right operand of operator and4b is an unbound "
1433 "octetstring value.");
1434 if (other_value.val_ptr->n_octets != 1)
1435 TTCN_error("The octetstring "
1436 "operands of operator and4b must have the same length.");
1437 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] &
1438 other_value.val_ptr->octets_ptr[0];
1439 return OCTETSTRING(1, &result);
1440 }
1441
1442 OCTETSTRING OCTETSTRING_ELEMENT::operator&
1443 (const OCTETSTRING_ELEMENT& other_value) const
1444 {
1445 must_bound("Left operand of operator and4b is an unbound octetstring "
1446 "element.");
1447 other_value.must_bound("Right operand of operator and4b is an unbound "
1448 "octetstring element.");
1449 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] &
1450 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1451 return OCTETSTRING(1, &result);
1452 }
1453
1454 OCTETSTRING OCTETSTRING_ELEMENT::operator|(const OCTETSTRING& other_value) const
1455 {
1456 must_bound("Left operand of operator or4b is an unbound octetstring "
1457 "element.");
1458 other_value.must_bound("Right operand of operator or4b is an unbound "
1459 "octetstring value.");
1460 if (other_value.val_ptr->n_octets != 1)
1461 TTCN_error("The octetstring "
1462 "operands of operator or4b must have the same length.");
1463 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] |
1464 other_value.val_ptr->octets_ptr[0];
1465 return OCTETSTRING(1, &result);
1466 }
1467
1468 OCTETSTRING OCTETSTRING_ELEMENT::operator|
1469 (const OCTETSTRING_ELEMENT& other_value) const
1470 {
1471 must_bound("Left operand of operator or4b is an unbound octetstring "
1472 "element.");
1473 other_value.must_bound("Right operand of operator or4b is an unbound "
1474 "octetstring element.");
1475 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] |
1476 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1477 return OCTETSTRING(1, &result);
1478 }
1479
1480 OCTETSTRING OCTETSTRING_ELEMENT::operator^(const OCTETSTRING& other_value) const
1481 {
1482 must_bound("Left operand of operator xor4b is an unbound octetstring "
1483 "element.");
1484 other_value.must_bound("Right operand of operator xor4b is an unbound "
1485 "octetstring value.");
1486 if (other_value.val_ptr->n_octets != 1)
1487 TTCN_error("The octetstring "
1488 "operands of operator xor4b must have the same length.");
1489 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] ^
1490 other_value.val_ptr->octets_ptr[0];
1491 return OCTETSTRING(1, &result);
1492 }
1493
1494 OCTETSTRING OCTETSTRING_ELEMENT::operator^
1495 (const OCTETSTRING_ELEMENT& other_value) const
1496 {
1497 must_bound("Left operand of operator xor4b is an unbound octetstring "
1498 "element.");
1499 other_value.must_bound("Right operand of operator xor4b is an unbound "
1500 "octetstring element.");
1501 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] ^
1502 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1503 return OCTETSTRING(1, &result);
1504 }
1505
1506 unsigned char OCTETSTRING_ELEMENT::get_octet() const
1507 {
1508 return str_val.val_ptr->octets_ptr[octet_pos];
1509 }
1510
1511 void OCTETSTRING_ELEMENT::log() const
1512 {
1513 if (bound_flag) {
1514 unsigned char octet = str_val.val_ptr->octets_ptr[octet_pos];
1515 TTCN_Logger::log_char('\'');
1516 TTCN_Logger::log_octet(octet);
1517 TTCN_Logger::log_event_str("'O");
1518 if (TTCN_Logger::is_printable(octet)) {
1519 TTCN_Logger::log_event_str(" (\"");
1520 TTCN_Logger::log_char_escaped(octet);
1521 TTCN_Logger::log_event_str("\")");
1522 }
1523 } else TTCN_Logger::log_event_unbound();
1524 }
1525
1526 // octetstring template class
1527
1528 void OCTETSTRING_template::clean_up()
1529 {
1530 switch (template_selection) {
1531 case VALUE_LIST:
1532 case COMPLEMENTED_LIST:
1533 delete [] value_list.list_value;
1534 break;
1535 case STRING_PATTERN:
1536 if (pattern_value->ref_count > 1) pattern_value->ref_count--;
1537 else if (pattern_value->ref_count == 1) Free(pattern_value);
1538 else TTCN_error("Internal error: Invalid reference counter in an "
1539 "octetstring pattern.");
1540 break;
1541 case DECODE_MATCH:
1542 if (dec_match->ref_count > 1) {
1543 dec_match->ref_count--;
1544 }
1545 else if (dec_match->ref_count == 1) {
1546 delete dec_match->instance;
1547 delete dec_match;
1548 }
1549 else {
1550 TTCN_error("Internal error: Invalid reference counter in a "
1551 "decoded content match.");
1552 }
1553 break;
1554 default:
1555 break;
1556 }
1557 template_selection = UNINITIALIZED_TEMPLATE;
1558 }
1559
1560 void OCTETSTRING_template::copy_template
1561 (const OCTETSTRING_template& other_value)
1562 {
1563 switch (other_value.template_selection) {
1564 case SPECIFIC_VALUE:
1565 single_value = other_value.single_value;
1566 break;
1567 case OMIT_VALUE:
1568 case ANY_VALUE:
1569 case ANY_OR_OMIT:
1570 break;
1571 case VALUE_LIST:
1572 case COMPLEMENTED_LIST:
1573 value_list.n_values = other_value.value_list.n_values;
1574 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
1575 for (unsigned int i = 0; i < value_list.n_values; i++)
1576 value_list.list_value[i].copy_template(
1577 other_value.value_list.list_value[i]);
1578 break;
1579 case STRING_PATTERN:
1580 pattern_value = other_value.pattern_value;
1581 pattern_value->ref_count++;
1582 break;
1583 case DECODE_MATCH:
1584 dec_match = other_value.dec_match;
1585 dec_match->ref_count++;
1586 break;
1587 default:
1588 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1589 }
1590 set_selection(other_value);
1591 }
1592
1593 /*
1594 This is the same algorithm that match_array uses
1595 to match 'record of' types.
1596 The only differences are: how two elements are matched and
1597 how an asterisk or ? is identified in the template
1598 */
1599 boolean OCTETSTRING_template::match_pattern(
1600 const octetstring_pattern_struct *string_pattern,
1601 const OCTETSTRING::octetstring_struct *string_value)
1602 {
1603 // the empty pattern matches the empty octetstring only
1604 if (string_pattern->n_elements == 0) return string_value->n_octets == 0;
1605
1606 int value_index = 0;
1607 unsigned int template_index = 0;
1608 int last_asterisk = -1;
1609 int last_value_to_asterisk = -1;
1610 //this variable is used to speed up the function
1611 unsigned short pattern_element;
1612
1613 for(;;)
1614 {
1615 pattern_element = string_pattern->elements_ptr[template_index];
1616 if( pattern_element < 256){
1617 if(string_value->octets_ptr[value_index] == pattern_element)
1618 {
1619 value_index++;
1620 template_index++;
1621 }else{
1622 if(last_asterisk == -1) return FALSE;
1623 template_index = last_asterisk +1;
1624 value_index = ++last_value_to_asterisk;
1625 }
1626 } else if(pattern_element == 256)
1627 {//? found
1628 value_index++;
1629 template_index++;
1630 }else if(pattern_element == 257)
1631 {//* found
1632 last_asterisk = template_index++;
1633 last_value_to_asterisk = value_index;
1634 } else TTCN_error("Internal error: invalid element in an octetstring "
1635 "pattern.");
1636
1637 if(value_index == string_value->n_octets
1638 && template_index == string_pattern->n_elements)
1639 {
1640 return TRUE;
1641 }else if (template_index == string_pattern->n_elements)
1642 {
1643 if(string_pattern->elements_ptr[template_index - 1] == 257)
1644 {
1645 return TRUE;
1646 }else if(last_asterisk == -1)
1647 {
1648 return FALSE;
1649 }else{
1650 template_index = last_asterisk+1;
1651 value_index = ++last_value_to_asterisk;
1652 }
1653 }else if(value_index == string_value->n_octets)
1654 {
1655 while(template_index < string_pattern->n_elements
1656 && string_pattern->elements_ptr[template_index] == 257)
1657 template_index++;
1658
1659 return template_index == string_pattern->n_elements;
1660 }
1661 }
1662 }
1663
1664 OCTETSTRING_template::OCTETSTRING_template()
1665 {
1666 }
1667
1668 OCTETSTRING_template::OCTETSTRING_template(template_sel other_value)
1669 : Restricted_Length_Template(other_value)
1670 {
1671 check_single_selection(other_value);
1672 }
1673
1674 OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING& other_value)
1675 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1676 {
1677 }
1678
1679 OCTETSTRING_template::OCTETSTRING_template
1680 (const OCTETSTRING_ELEMENT& other_value)
1681 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1682 {
1683 }
1684
1685 OCTETSTRING_template::OCTETSTRING_template
1686 (const OPTIONAL<OCTETSTRING>& other_value)
1687 {
1688 switch (other_value.get_selection()) {
1689 case OPTIONAL_PRESENT:
1690 set_selection(SPECIFIC_VALUE);
1691 single_value = (const OCTETSTRING&)other_value;
1692 break;
1693 case OPTIONAL_OMIT:
1694 set_selection(OMIT_VALUE);
1695 break;
1696 default:
1697 TTCN_error("Creating an octetstring template from an unbound optional "
1698 "field.");
1699 }
1700 }
1701
1702 OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements,
1703 const unsigned short *pattern_elements)
1704 : Restricted_Length_Template(STRING_PATTERN)
1705 {
1706 pattern_value = (octetstring_pattern_struct*)
1707 Malloc(sizeof(octetstring_pattern_struct) +
1708 (n_elements - 1) * sizeof(unsigned short));
1709 pattern_value->ref_count = 1;
1710 pattern_value->n_elements = n_elements;
1711 memcpy(pattern_value->elements_ptr, pattern_elements,
1712 n_elements * sizeof(unsigned short));
1713 }
1714
1715 OCTETSTRING_template::OCTETSTRING_template
1716 (const OCTETSTRING_template& other_value)
1717 : Restricted_Length_Template()
1718 {
1719 copy_template(other_value);
1720 }
1721
1722 OCTETSTRING_template::~OCTETSTRING_template()
1723 {
1724 clean_up();
1725 }
1726
1727 OCTETSTRING_template& OCTETSTRING_template::operator=(template_sel other_value)
1728 {
1729 check_single_selection(other_value);
1730 clean_up();
1731 set_selection(other_value);
1732 return *this;
1733 }
1734
1735 OCTETSTRING_template& OCTETSTRING_template::operator=
1736 (const OCTETSTRING& other_value)
1737 {
1738 other_value.must_bound("Assignment of an unbound octetstring value to a "
1739 "template.");
1740 clean_up();
1741 set_selection(SPECIFIC_VALUE);
1742 single_value = other_value;
1743 return *this;
1744 }
1745
1746 OCTETSTRING_template& OCTETSTRING_template::operator=
1747 (const OCTETSTRING_ELEMENT& other_value)
1748 {
1749 other_value.must_bound("Assignment of an unbound octetstring element to a "
1750 "template.");
1751 clean_up();
1752 set_selection(SPECIFIC_VALUE);
1753 single_value = other_value;
1754 return *this;
1755 }
1756
1757 OCTETSTRING_template& OCTETSTRING_template::operator=
1758 (const OPTIONAL<OCTETSTRING>& other_value)
1759 {
1760 clean_up();
1761 switch (other_value.get_selection()) {
1762 case OPTIONAL_PRESENT:
1763 set_selection(SPECIFIC_VALUE);
1764 single_value = (const OCTETSTRING&)other_value;
1765 break;
1766 case OPTIONAL_OMIT:
1767 set_selection(OMIT_VALUE);
1768 break;
1769 default:
1770 TTCN_error("Assignment of an unbound optional field to an octetstring "
1771 "template.");
1772 }
1773 return *this;
1774 }
1775
1776 OCTETSTRING_template& OCTETSTRING_template::operator=
1777 (const OCTETSTRING_template& other_value)
1778 {
1779 if (&other_value != this) {
1780 clean_up();
1781 copy_template(other_value);
1782 }
1783 return *this;
1784 }
1785
1786 OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value)
1787 {
1788 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1789 TTCN_error("Accessing an octetstring element of a non-specific "
1790 "octetstring template.");
1791 return single_value[index_value];
1792 }
1793
1794 OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value)
1795 {
1796 index_value.must_bound("Indexing a octetstring value with an unbound "
1797 "integer value.");
1798 return (*this)[(int)index_value];
1799 }
1800
1801 const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value) const
1802 {
1803 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1804 TTCN_error("Accessing an octetstring element of a non-specific "
1805 "octetstring template.");
1806 return single_value[index_value];
1807 }
1808
1809 const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value) const
1810 {
1811 index_value.must_bound("Indexing a octetstring template with an unbound "
1812 "integer value.");
1813 return (*this)[(int)index_value];
1814 }
1815
1816 boolean OCTETSTRING_template::match(const OCTETSTRING& other_value,
1817 boolean /* legacy */) const
1818 {
1819 if (!other_value.is_bound()) return FALSE;
1820 if (!match_length(other_value.val_ptr->n_octets)) return FALSE;
1821 switch (template_selection) {
1822 case SPECIFIC_VALUE:
1823 return single_value == other_value;
1824 case OMIT_VALUE:
1825 return FALSE;
1826 case ANY_VALUE:
1827 case ANY_OR_OMIT:
1828 return TRUE;
1829 case VALUE_LIST:
1830 case COMPLEMENTED_LIST:
1831 for(unsigned int i = 0; i < value_list.n_values; i++)
1832 if (value_list.list_value[i].match(other_value))
1833 return template_selection == VALUE_LIST;
1834 return template_selection == COMPLEMENTED_LIST;
1835 case STRING_PATTERN:
1836 return match_pattern(pattern_value, other_value.val_ptr);
1837 case DECODE_MATCH: {
1838 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
1839 TTCN_EncDec::clear_error();
1840 TTCN_Buffer buff(other_value);
1841 boolean ret_val = dec_match->instance->match(buff);
1842 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT);
1843 TTCN_EncDec::clear_error();
1844 return ret_val; }
1845 default:
1846 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1847 }
1848 return FALSE;
1849 }
1850
1851 const OCTETSTRING& OCTETSTRING_template::valueof() const
1852 {
1853 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1854 TTCN_error("Performing a valueof or send operation on a non-specific "
1855 "octetstring template.");
1856 return single_value;
1857 }
1858
1859 int OCTETSTRING_template::lengthof() const
1860 {
1861 int min_length;
1862 boolean has_any_or_none;
1863 if (is_ifpresent)
1864 TTCN_error("Performing lengthof() operation on a octetstring template "
1865 "which has an ifpresent attribute.");
1866 switch (template_selection)
1867 {
1868 case SPECIFIC_VALUE:
1869 min_length = single_value.lengthof();
1870 has_any_or_none = FALSE;
1871 break;
1872 case OMIT_VALUE:
1873 TTCN_error("Performing lengthof() operation on an octetstring template "
1874 "containing omit value.");
1875 case ANY_VALUE:
1876 case ANY_OR_OMIT:
1877 min_length = 0;
1878 has_any_or_none = TRUE; // max. length is infinity
1879 break;
1880 case VALUE_LIST:
1881 {
1882 // error if any element does not have length or the lengths differ
1883 if (value_list.n_values<1)
1884 TTCN_error("Internal error: "
1885 "Performing lengthof() operation on an octetstring template "
1886 "containing an empty list.");
1887 int item_length = value_list.list_value[0].lengthof();
1888 for (unsigned int i = 1; i < value_list.n_values; i++) {
1889 if (value_list.list_value[i].lengthof()!=item_length)
1890 TTCN_error("Performing lengthof() operation on an octetstring template "
1891 "containing a value list with different lengths.");
1892 }
1893 min_length = item_length;
1894 has_any_or_none = FALSE;
1895 break;
1896 }
1897 case COMPLEMENTED_LIST:
1898 TTCN_error("Performing lengthof() operation on an octetstring template "
1899 "containing complemented list.");
1900 case STRING_PATTERN:
1901 min_length = 0;
1902 has_any_or_none = FALSE; // TRUE if * chars in the pattern
1903 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
1904 {
1905 if (pattern_value->elements_ptr[i] < 257) min_length++;
1906 else has_any_or_none = TRUE; // case of * character
1907 }
1908 break;
1909 default:
1910 TTCN_error("Performing lengthof() operation on an "
1911 "uninitialized/unsupported octetstring template.");
1912 }
1913 return check_section_is_single(min_length, has_any_or_none,
1914 "length", "an", "octetstring template");
1915 }
1916
1917 void OCTETSTRING_template::set_type(template_sel template_type,
1918 unsigned int list_length)
1919 {
1920 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST &&
1921 template_type != DECODE_MATCH)
1922 TTCN_error("Setting an invalid type for an octetstring template.");
1923 clean_up();
1924 set_selection(template_type);
1925 if (template_type != DECODE_MATCH) {
1926 value_list.n_values = list_length;
1927 value_list.list_value = new OCTETSTRING_template[list_length];
1928 }
1929 }
1930
1931 OCTETSTRING_template& OCTETSTRING_template::list_item(unsigned int list_index)
1932 {
1933 if (template_selection != VALUE_LIST &&
1934 template_selection != COMPLEMENTED_LIST)
1935 TTCN_error("Accessing a list element of a non-list octetstring template.");
1936 if (list_index >= value_list.n_values)
1937 TTCN_error("Index overflow in an octetstring value list template.");
1938 return value_list.list_value[list_index];
1939 }
1940
1941 void OCTETSTRING_template::set_decmatch(Dec_Match_Interface* new_instance)
1942 {
1943 if (template_selection != DECODE_MATCH) {
1944 TTCN_error("Setting the decoded content matching mechanism of a non-decmatch "
1945 "octetstring template.");
1946 }
1947 dec_match = new decmatch_struct;
1948 dec_match->ref_count = 1;
1949 dec_match->instance = new_instance;
1950 }
1951
1952 void OCTETSTRING_template::log() const
1953 {
1954 switch (template_selection) {
1955 case SPECIFIC_VALUE:
1956 single_value.log();
1957 break;
1958 case COMPLEMENTED_LIST:
1959 TTCN_Logger::log_event_str("complement ");
1960 // no break
1961 case VALUE_LIST:
1962 TTCN_Logger::log_char('(');
1963 for(unsigned int i = 0; i < value_list.n_values; i++) {
1964 if (i > 0) TTCN_Logger::log_event_str(", ");
1965 value_list.list_value[i].log();
1966 }
1967 TTCN_Logger::log_char(')');
1968 break;
1969 case STRING_PATTERN:
1970 TTCN_Logger::log_char('\'');
1971 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1972 unsigned short pattern = pattern_value->elements_ptr[i];
1973 if (pattern < 256) TTCN_Logger::log_octet(pattern);
1974 else if (pattern == 256) TTCN_Logger::log_char('?');
1975 else if (pattern == 257) TTCN_Logger::log_char('*');
1976 else TTCN_Logger::log_event_str("<unknown>");
1977 }
1978 TTCN_Logger::log_event_str("'O");
1979 break;
1980 case DECODE_MATCH:
1981 TTCN_Logger::log_event_str("decmatch ");
1982 dec_match->instance->log();
1983 break;
1984 default:
1985 log_generic();
1986 break;
1987 }
1988 log_restricted();
1989 log_ifpresent();
1990 }
1991
1992 void OCTETSTRING_template::log_match(const OCTETSTRING& match_value,
1993 boolean /* legacy */) const
1994 {
1995 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
1996 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1997 TTCN_Logger::print_logmatch_buffer();
1998 TTCN_Logger::log_event_str(" := ");
1999 }
2000 match_value.log();
2001 TTCN_Logger::log_event_str(" with ");
2002 log();
2003 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
2004 else TTCN_Logger::log_event_str(" unmatched");
2005 }
2006
2007 void OCTETSTRING_template::set_param(Module_Param& param) {
2008 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "octetstring template");
2009 Module_Param_Ptr mp = &param;
2010 if (param.get_type() == Module_Param::MP_Reference) {
2011 mp = param.get_referenced_param();
2012 }
2013 switch (mp->get_type()) {
2014 case Module_Param::MP_Omit:
2015 *this = OMIT_VALUE;
2016 break;
2017 case Module_Param::MP_Any:
2018 *this = ANY_VALUE;
2019 break;
2020 case Module_Param::MP_AnyOrNone:
2021 *this = ANY_OR_OMIT;
2022 break;
2023 case Module_Param::MP_List_Template:
2024 case Module_Param::MP_ComplementList_Template: {
2025 OCTETSTRING_template temp;
2026 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
2027 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
2028 for (size_t i=0; i<mp->get_size(); i++) {
2029 temp.list_item(i).set_param(*mp->get_elem(i));
2030 }
2031 *this = temp;
2032 break; }
2033 case Module_Param::MP_Octetstring:
2034 *this = OCTETSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
2035 break;
2036 case Module_Param::MP_Octetstring_Template:
2037 *this = OCTETSTRING_template(mp->get_string_size(), (unsigned short*)mp->get_string_data());
2038 break;
2039 case Module_Param::MP_Expression:
2040 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
2041 OCTETSTRING operand1, operand2;
2042 operand1.set_param(*mp->get_operand1());
2043 operand2.set_param(*mp->get_operand2());
2044 *this = operand1 + operand2;
2045 }
2046 else {
2047 param.expr_type_error("a bitstring");
2048 }
2049 break;
2050 default:
2051 param.type_error("octetstring template");
2052 }
2053 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2054 if (param.get_length_restriction() != NULL) {
2055 set_length_range(param);
2056 }
2057 else {
2058 set_length_range(*mp);
2059 }
2060 }
2061
2062 Module_Param* OCTETSTRING_template::get_param(Module_Param_Name& param_name) const
2063 {
2064 Module_Param* mp = NULL;
2065 switch (template_selection) {
2066 case UNINITIALIZED_TEMPLATE:
2067 mp = new Module_Param_Unbound();
2068 break;
2069 case OMIT_VALUE:
2070 mp = new Module_Param_Omit();
2071 break;
2072 case ANY_VALUE:
2073 mp = new Module_Param_Any();
2074 break;
2075 case ANY_OR_OMIT:
2076 mp = new Module_Param_AnyOrNone();
2077 break;
2078 case SPECIFIC_VALUE:
2079 mp = single_value.get_param(param_name);
2080 break;
2081 case VALUE_LIST:
2082 case COMPLEMENTED_LIST: {
2083 if (template_selection == VALUE_LIST) {
2084 mp = new Module_Param_List_Template();
2085 }
2086 else {
2087 mp = new Module_Param_ComplementList_Template();
2088 }
2089 for (size_t i = 0; i < value_list.n_values; ++i) {
2090 mp->add_elem(value_list.list_value[i].get_param(param_name));
2091 }
2092 break; }
2093 case STRING_PATTERN: {
2094 unsigned short* val_cpy = (unsigned short*)Malloc(pattern_value->n_elements *
2095 sizeof(unsigned short));
2096 memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements *
2097 sizeof(unsigned short));
2098 mp = new Module_Param_Octetstring_Template(pattern_value->n_elements, val_cpy);
2099 break; }
2100 case DECODE_MATCH:
2101 mp->error("Referencing a decoded content matching template is not supported.");
2102 break;
2103 default:
2104 break;
2105 }
2106 if (is_ifpresent) {
2107 mp->set_ifpresent();
2108 }
2109 mp->set_length_restriction(get_length_range());
2110 return mp;
2111 }
2112
2113 void OCTETSTRING_template::encode_text(Text_Buf& text_buf) const
2114 {
2115 encode_text_restricted(text_buf);
2116 switch (template_selection) {
2117 case OMIT_VALUE:
2118 case ANY_VALUE:
2119 case ANY_OR_OMIT:
2120 break;
2121 case SPECIFIC_VALUE:
2122 single_value.encode_text(text_buf);
2123 break;
2124 case VALUE_LIST:
2125 case COMPLEMENTED_LIST:
2126 text_buf.push_int(value_list.n_values);
2127 for (unsigned int i = 0; i < value_list.n_values; i++)
2128 value_list.list_value[i].encode_text(text_buf);
2129 break;
2130 case STRING_PATTERN:
2131 text_buf.push_int(pattern_value->n_elements);
2132 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
2133 text_buf.push_int(pattern_value->elements_ptr[i]);
2134 break;
2135 default:
2136 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2137 "octetstring template.");
2138 }
2139 }
2140
2141 void OCTETSTRING_template::decode_text(Text_Buf& text_buf)
2142 {
2143 clean_up();
2144 decode_text_restricted(text_buf);
2145 switch (template_selection) {
2146 case OMIT_VALUE:
2147 case ANY_VALUE:
2148 case ANY_OR_OMIT:
2149 break;
2150 case SPECIFIC_VALUE:
2151 single_value.decode_text(text_buf);
2152 break;
2153 case VALUE_LIST:
2154 case COMPLEMENTED_LIST:
2155 value_list.n_values = text_buf.pull_int().get_val();
2156 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
2157 for (unsigned int i = 0; i < value_list.n_values; i++)
2158 value_list.list_value[i].decode_text(text_buf);
2159 break;
2160 case STRING_PATTERN: {
2161 unsigned int n_elements = text_buf.pull_int().get_val();
2162 pattern_value = (octetstring_pattern_struct*)
2163 Malloc(sizeof(octetstring_pattern_struct) + (n_elements - 1) *
2164 sizeof(unsigned short));
2165 pattern_value->ref_count = 1;
2166 pattern_value->n_elements = n_elements;
2167 for (unsigned int i = 0; i < n_elements; i++)
2168 pattern_value->elements_ptr[i] = text_buf.pull_int().get_val();
2169 break;}
2170 default:
2171 TTCN_error("Text decoder: An unknown/unsupported selection was "
2172 "received for an octetstring template.");
2173 }
2174 }
2175
2176 boolean OCTETSTRING_template::is_present(boolean legacy /* = FALSE */) const
2177 {
2178 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
2179 return !match_omit(legacy);
2180 }
2181
2182 boolean OCTETSTRING_template::match_omit(boolean legacy /* = FALSE */) const
2183 {
2184 if (is_ifpresent) return TRUE;
2185 switch (template_selection) {
2186 case OMIT_VALUE:
2187 case ANY_OR_OMIT:
2188 return TRUE;
2189 case VALUE_LIST:
2190 case COMPLEMENTED_LIST:
2191 if (legacy) {
2192 // legacy behavior: 'omit' can appear in the value/complement list
2193 for (unsigned int i=0; i<value_list.n_values; i++)
2194 if (value_list.list_value[i].match_omit())
2195 return template_selection==VALUE_LIST;
2196 return template_selection==COMPLEMENTED_LIST;
2197 }
2198 // else fall through
2199 default:
2200 return FALSE;
2201 }
2202 return FALSE;
2203 }
2204
2205 #ifndef TITAN_RUNTIME_2
2206 void OCTETSTRING_template::check_restriction(template_res t_res, const char* t_name,
2207 boolean legacy /* = FALSE */) const
2208 {
2209 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2210 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2211 case TR_VALUE:
2212 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2213 break;
2214 case TR_OMIT:
2215 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2216 template_selection==SPECIFIC_VALUE)) return;
2217 break;
2218 case TR_PRESENT:
2219 if (!match_omit(legacy)) return;
2220 break;
2221 default:
2222 return;
2223 }
2224 TTCN_error("Restriction `%s' on template of type %s violated.",
2225 get_res_name(t_res), t_name ? t_name : "octetstring");
2226 }
2227 #endif
This page took 0.076984 seconds and 5 git commands to generate.