Merge pull request #63 from BenceJanosSzabo/master
[deliverable/titan.core.git] / core / Octetstring.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * 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 ******************************************************************************/
970ed795
EL
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
46static const Token_Match
47 octetstring_value_match("^(([0-9A-Fa-f]{2})+).*$", TRUE);
48
49void 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
68void 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).
84OCTETSTRING::OCTETSTRING(int n_octets)
85{
86 init_struct(n_octets);
87}
88
89OCTETSTRING::OCTETSTRING()
90{
91 val_ptr = NULL;
92}
93
94OCTETSTRING::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
100OCTETSTRING::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
108OCTETSTRING::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
115OCTETSTRING::~OCTETSTRING()
116{
117 clean_up();
118}
119
120OCTETSTRING& 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
131OCTETSTRING& 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
142boolean 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
151boolean 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
160OCTETSTRING 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
175OCTETSTRING 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
186OCTETSTRING& 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
215OCTETSTRING& 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
236OCTETSTRING 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
245OCTETSTRING 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
260OCTETSTRING 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
272OCTETSTRING 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
287OCTETSTRING 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
299OCTETSTRING 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
314OCTETSTRING 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
326OCTETSTRING 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
342OCTETSTRING 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
349OCTETSTRING 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
364OCTETSTRING 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
371OCTETSTRING 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
387OCTETSTRING 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
394OCTETSTRING 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
410OCTETSTRING 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
417OCTETSTRING_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
446OCTETSTRING_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
453const 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
465const 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
473void 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
484int OCTETSTRING::lengthof() const
485{
486 must_bound("Getting the length of an unbound octetstring value.");
487 return val_ptr->n_octets;
488}
489
490OCTETSTRING::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
496void 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
517void OCTETSTRING::set_param(Module_Param& param) {
518 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "octetstring value");
3abe9331 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 }
970ed795 541 break;
3abe9331 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");
970ed795
EL
556 }
557 break;
558 default:
3abe9331 559 param.type_error("octetstring value");
560 break;
561 }
562}
563
564Module_Param* OCTETSTRING::get_param(Module_Param_Name& /* param_name */) const
565{
566 if (!is_bound()) {
567 return new Module_Param_Unbound();
970ed795 568 }
3abe9331 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);
970ed795
EL
572}
573
574void 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
582void 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
592void 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);
af710487 629 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
970ed795
EL
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
647void 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: {
af710487 701 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
970ed795
EL
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 }
feade998 710 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
970ed795
EL
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
734ASN_BER_TLV_t*
735OCTETSTRING::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
749ASN_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
757int 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
763int 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}
3f84031e 772
773int 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}
970ed795
EL
781#endif
782
783boolean 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
812int 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
909extern char base64_decoder_table[256];
910extern unsigned int xlate(cbyte* in, int phase, unsigned char* dest);
911extern const char cb64[];
912
913int OCTETSTRING::XER_encode(const XERdescriptor_t& p_td,
af710487 914 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
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
958int OCTETSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
feade998 959 unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
970ed795
EL
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 }
1100finished:
1101 return 1; // decode successful
1102}
1103
1104int 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
1160int 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
1200int 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
1258void 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
1269int 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
1290int 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
1347OCTETSTRING_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
1353OCTETSTRING_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
1366OCTETSTRING_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
1379boolean 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
1388boolean 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
1398OCTETSTRING 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
1409OCTETSTRING 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
1421OCTETSTRING 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
1428OCTETSTRING 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
1442OCTETSTRING 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
1454OCTETSTRING 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
1468OCTETSTRING 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
1480OCTETSTRING 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
1494OCTETSTRING 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
1506unsigned char OCTETSTRING_ELEMENT::get_octet() const
1507{
1508 return str_val.val_ptr->octets_ptr[octet_pos];
1509}
1510
1511void 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
1528void 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 default:
1542 break;
1543 }
1544 template_selection = UNINITIALIZED_TEMPLATE;
1545}
1546
1547void OCTETSTRING_template::copy_template
1548 (const OCTETSTRING_template& other_value)
1549{
1550 switch (other_value.template_selection) {
1551 case SPECIFIC_VALUE:
1552 single_value = other_value.single_value;
1553 break;
1554 case OMIT_VALUE:
1555 case ANY_VALUE:
1556 case ANY_OR_OMIT:
1557 break;
1558 case VALUE_LIST:
1559 case COMPLEMENTED_LIST:
1560 value_list.n_values = other_value.value_list.n_values;
1561 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
1562 for (unsigned int i = 0; i < value_list.n_values; i++)
1563 value_list.list_value[i].copy_template(
1564 other_value.value_list.list_value[i]);
1565 break;
1566 case STRING_PATTERN:
1567 pattern_value = other_value.pattern_value;
1568 pattern_value->ref_count++;
1569 break;
1570 default:
1571 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1572 }
1573 set_selection(other_value);
1574}
1575
1576/*
1577 This is the same algorithm that match_array uses
1578 to match 'record of' types.
1579 The only differences are: how two elements are matched and
1580 how an asterisk or ? is identified in the template
1581*/
1582boolean OCTETSTRING_template::match_pattern(
1583 const octetstring_pattern_struct *string_pattern,
1584 const OCTETSTRING::octetstring_struct *string_value)
1585{
1586 // the empty pattern matches the empty octetstring only
1587 if (string_pattern->n_elements == 0) return string_value->n_octets == 0;
1588
1589 int value_index = 0;
1590 unsigned int template_index = 0;
1591 int last_asterisk = -1;
1592 int last_value_to_asterisk = -1;
1593 //this variable is used to speed up the function
1594 unsigned short pattern_element;
1595
1596 for(;;)
1597 {
1598 pattern_element = string_pattern->elements_ptr[template_index];
1599 if( pattern_element < 256){
1600 if(string_value->octets_ptr[value_index] == pattern_element)
1601 {
1602 value_index++;
1603 template_index++;
1604 }else{
1605 if(last_asterisk == -1) return FALSE;
1606 template_index = last_asterisk +1;
1607 value_index = ++last_value_to_asterisk;
1608 }
1609 } else if(pattern_element == 256)
1610 {//? found
1611 value_index++;
1612 template_index++;
1613 }else if(pattern_element == 257)
1614 {//* found
1615 last_asterisk = template_index++;
1616 last_value_to_asterisk = value_index;
1617 } else TTCN_error("Internal error: invalid element in an octetstring "
1618 "pattern.");
1619
1620 if(value_index == string_value->n_octets
1621 && template_index == string_pattern->n_elements)
1622 {
1623 return TRUE;
1624 }else if (template_index == string_pattern->n_elements)
1625 {
1626 if(string_pattern->elements_ptr[template_index - 1] == 257)
1627 {
1628 return TRUE;
1629 }else if(last_asterisk == -1)
1630 {
1631 return FALSE;
1632 }else{
1633 template_index = last_asterisk+1;
1634 value_index = ++last_value_to_asterisk;
1635 }
1636 }else if(value_index == string_value->n_octets)
1637 {
1638 while(template_index < string_pattern->n_elements
1639 && string_pattern->elements_ptr[template_index] == 257)
1640 template_index++;
1641
1642 return template_index == string_pattern->n_elements;
1643 }
1644 }
1645}
1646
1647OCTETSTRING_template::OCTETSTRING_template()
1648{
1649}
1650
1651OCTETSTRING_template::OCTETSTRING_template(template_sel other_value)
1652 : Restricted_Length_Template(other_value)
1653{
1654 check_single_selection(other_value);
1655}
1656
1657OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING& other_value)
1658 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1659{
1660}
1661
1662OCTETSTRING_template::OCTETSTRING_template
1663 (const OCTETSTRING_ELEMENT& other_value)
1664 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1665{
1666}
1667
1668OCTETSTRING_template::OCTETSTRING_template
1669(const OPTIONAL<OCTETSTRING>& other_value)
1670{
1671 switch (other_value.get_selection()) {
1672 case OPTIONAL_PRESENT:
1673 set_selection(SPECIFIC_VALUE);
1674 single_value = (const OCTETSTRING&)other_value;
1675 break;
1676 case OPTIONAL_OMIT:
1677 set_selection(OMIT_VALUE);
1678 break;
1679 default:
1680 TTCN_error("Creating an octetstring template from an unbound optional "
1681 "field.");
1682 }
1683}
1684
1685OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements,
1686 const unsigned short *pattern_elements)
1687 : Restricted_Length_Template(STRING_PATTERN)
1688{
1689 pattern_value = (octetstring_pattern_struct*)
1690 Malloc(sizeof(octetstring_pattern_struct) +
1691 (n_elements - 1) * sizeof(unsigned short));
1692 pattern_value->ref_count = 1;
1693 pattern_value->n_elements = n_elements;
1694 memcpy(pattern_value->elements_ptr, pattern_elements,
1695 n_elements * sizeof(unsigned short));
1696}
1697
1698OCTETSTRING_template::OCTETSTRING_template
1699 (const OCTETSTRING_template& other_value)
1700: Restricted_Length_Template()
1701{
1702 copy_template(other_value);
1703}
1704
1705OCTETSTRING_template::~OCTETSTRING_template()
1706{
1707 clean_up();
1708}
1709
1710OCTETSTRING_template& OCTETSTRING_template::operator=(template_sel other_value)
1711{
1712 check_single_selection(other_value);
1713 clean_up();
1714 set_selection(other_value);
1715 return *this;
1716}
1717
1718OCTETSTRING_template& OCTETSTRING_template::operator=
1719(const OCTETSTRING& other_value)
1720{
1721 other_value.must_bound("Assignment of an unbound octetstring value to a "
1722 "template.");
1723 clean_up();
1724 set_selection(SPECIFIC_VALUE);
1725 single_value = other_value;
1726 return *this;
1727}
1728
1729OCTETSTRING_template& OCTETSTRING_template::operator=
1730 (const OCTETSTRING_ELEMENT& other_value)
1731{
1732 other_value.must_bound("Assignment of an unbound octetstring element to a "
1733 "template.");
1734 clean_up();
1735 set_selection(SPECIFIC_VALUE);
1736 single_value = other_value;
1737 return *this;
1738}
1739
1740OCTETSTRING_template& OCTETSTRING_template::operator=
1741 (const OPTIONAL<OCTETSTRING>& other_value)
1742{
1743 clean_up();
1744 switch (other_value.get_selection()) {
1745 case OPTIONAL_PRESENT:
1746 set_selection(SPECIFIC_VALUE);
1747 single_value = (const OCTETSTRING&)other_value;
1748 break;
1749 case OPTIONAL_OMIT:
1750 set_selection(OMIT_VALUE);
1751 break;
1752 default:
1753 TTCN_error("Assignment of an unbound optional field to an octetstring "
1754 "template.");
1755 }
1756 return *this;
1757}
1758
1759OCTETSTRING_template& OCTETSTRING_template::operator=
1760(const OCTETSTRING_template& other_value)
1761{
1762 if (&other_value != this) {
1763 clean_up();
1764 copy_template(other_value);
1765 }
1766 return *this;
1767}
1768
1769OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value)
1770{
1771 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1772 TTCN_error("Accessing an octetstring element of a non-specific "
1773 "octetstring template.");
1774 return single_value[index_value];
1775}
1776
1777OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value)
1778{
1779 index_value.must_bound("Indexing a octetstring value with an unbound "
1780 "integer value.");
1781 return (*this)[(int)index_value];
1782}
1783
1784const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value) const
1785{
1786 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1787 TTCN_error("Accessing an octetstring element of a non-specific "
1788 "octetstring template.");
1789 return single_value[index_value];
1790}
1791
1792const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value) const
1793{
1794 index_value.must_bound("Indexing a octetstring template with an unbound "
1795 "integer value.");
1796 return (*this)[(int)index_value];
1797}
1798
3abe9331 1799boolean OCTETSTRING_template::match(const OCTETSTRING& other_value,
1800 boolean /* legacy */) const
970ed795
EL
1801{
1802 if (!other_value.is_bound()) return FALSE;
1803 if (!match_length(other_value.val_ptr->n_octets)) return FALSE;
1804 switch (template_selection) {
1805 case SPECIFIC_VALUE:
1806 return single_value == other_value;
1807 case OMIT_VALUE:
1808 return FALSE;
1809 case ANY_VALUE:
1810 case ANY_OR_OMIT:
1811 return TRUE;
1812 case VALUE_LIST:
1813 case COMPLEMENTED_LIST:
1814 for(unsigned int i = 0; i < value_list.n_values; i++)
1815 if (value_list.list_value[i].match(other_value))
1816 return template_selection == VALUE_LIST;
1817 return template_selection == COMPLEMENTED_LIST;
1818 case STRING_PATTERN:
1819 return match_pattern(pattern_value, other_value.val_ptr);
1820 default:
1821 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1822 }
1823 return FALSE;
1824}
1825
1826const OCTETSTRING& OCTETSTRING_template::valueof() const
1827{
1828 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1829 TTCN_error("Performing a valueof or send operation on a non-specific "
1830 "octetstring template.");
1831 return single_value;
1832}
1833
1834int OCTETSTRING_template::lengthof() const
1835{
1836 int min_length;
1837 boolean has_any_or_none;
1838 if (is_ifpresent)
1839 TTCN_error("Performing lengthof() operation on a octetstring template "
1840 "which has an ifpresent attribute.");
1841 switch (template_selection)
1842 {
1843 case SPECIFIC_VALUE:
1844 min_length = single_value.lengthof();
1845 has_any_or_none = FALSE;
1846 break;
1847 case OMIT_VALUE:
1848 TTCN_error("Performing lengthof() operation on an octetstring template "
1849 "containing omit value.");
1850 case ANY_VALUE:
1851 case ANY_OR_OMIT:
1852 min_length = 0;
1853 has_any_or_none = TRUE; // max. length is infinity
1854 break;
1855 case VALUE_LIST:
1856 {
1857 // error if any element does not have length or the lengths differ
1858 if (value_list.n_values<1)
1859 TTCN_error("Internal error: "
1860 "Performing lengthof() operation on an octetstring template "
1861 "containing an empty list.");
1862 int item_length = value_list.list_value[0].lengthof();
1863 for (unsigned int i = 1; i < value_list.n_values; i++) {
1864 if (value_list.list_value[i].lengthof()!=item_length)
1865 TTCN_error("Performing lengthof() operation on an octetstring template "
1866 "containing a value list with different lengths.");
1867 }
1868 min_length = item_length;
1869 has_any_or_none = FALSE;
1870 break;
1871 }
1872 case COMPLEMENTED_LIST:
1873 TTCN_error("Performing lengthof() operation on an octetstring template "
1874 "containing complemented list.");
1875 case STRING_PATTERN:
1876 min_length = 0;
1877 has_any_or_none = FALSE; // TRUE if * chars in the pattern
1878 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
1879 {
1880 if (pattern_value->elements_ptr[i] < 257) min_length++;
1881 else has_any_or_none = TRUE; // case of * character
1882 }
1883 break;
1884 default:
1885 TTCN_error("Performing lengthof() operation on an "
1886 "uninitialized/unsupported octetstring template.");
1887 }
1888 return check_section_is_single(min_length, has_any_or_none,
1889 "length", "an", "octetstring template");
1890}
1891
1892void OCTETSTRING_template::set_type(template_sel template_type,
1893 unsigned int list_length)
1894{
1895 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
1896 TTCN_error("Setting an invalid list type for an octetstring template.");
1897 clean_up();
1898 set_selection(template_type);
1899 value_list.n_values = list_length;
1900 value_list.list_value = new OCTETSTRING_template[list_length];
1901}
1902
1903OCTETSTRING_template& OCTETSTRING_template::list_item(unsigned int list_index)
1904{
1905 if (template_selection != VALUE_LIST &&
1906 template_selection != COMPLEMENTED_LIST)
1907 TTCN_error("Accessing a list element of a non-list octetstring template.");
1908 if (list_index >= value_list.n_values)
1909 TTCN_error("Index overflow in an octetstring value list template.");
1910 return value_list.list_value[list_index];
1911}
1912
1913void OCTETSTRING_template::log() const
1914{
1915 switch (template_selection) {
1916 case SPECIFIC_VALUE:
1917 single_value.log();
1918 break;
1919 case COMPLEMENTED_LIST:
1920 TTCN_Logger::log_event_str("complement ");
1921 // no break
1922 case VALUE_LIST:
1923 TTCN_Logger::log_char('(');
1924 for(unsigned int i = 0; i < value_list.n_values; i++) {
1925 if (i > 0) TTCN_Logger::log_event_str(", ");
1926 value_list.list_value[i].log();
1927 }
1928 TTCN_Logger::log_char(')');
1929 break;
1930 case STRING_PATTERN:
1931 TTCN_Logger::log_char('\'');
1932 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1933 unsigned short pattern = pattern_value->elements_ptr[i];
1934 if (pattern < 256) TTCN_Logger::log_octet(pattern);
1935 else if (pattern == 256) TTCN_Logger::log_char('?');
1936 else if (pattern == 257) TTCN_Logger::log_char('*');
1937 else TTCN_Logger::log_event_str("<unknown>");
1938 }
1939 TTCN_Logger::log_event_str("'O");
1940 break;
1941 default:
1942 log_generic();
1943 break;
1944 }
1945 log_restricted();
1946 log_ifpresent();
1947}
1948
3abe9331 1949void OCTETSTRING_template::log_match(const OCTETSTRING& match_value,
1950 boolean /* legacy */) const
970ed795
EL
1951{
1952 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
1953 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1954 TTCN_Logger::print_logmatch_buffer();
1955 TTCN_Logger::log_event_str(" := ");
1956 }
1957 match_value.log();
1958 TTCN_Logger::log_event_str(" with ");
1959 log();
1960 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1961 else TTCN_Logger::log_event_str(" unmatched");
1962}
1963
1964void OCTETSTRING_template::set_param(Module_Param& param) {
1965 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "octetstring template");
3abe9331 1966 Module_Param_Ptr mp = &param;
1967 if (param.get_type() == Module_Param::MP_Reference) {
1968 mp = param.get_referenced_param();
1969 }
1970 switch (mp->get_type()) {
970ed795
EL
1971 case Module_Param::MP_Omit:
1972 *this = OMIT_VALUE;
1973 break;
1974 case Module_Param::MP_Any:
1975 *this = ANY_VALUE;
1976 break;
1977 case Module_Param::MP_AnyOrNone:
1978 *this = ANY_OR_OMIT;
1979 break;
1980 case Module_Param::MP_List_Template:
3abe9331 1981 case Module_Param::MP_ComplementList_Template: {
1982 OCTETSTRING_template temp;
1983 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1984 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1985 for (size_t i=0; i<mp->get_size(); i++) {
1986 temp.list_item(i).set_param(*mp->get_elem(i));
970ed795 1987 }
3abe9331 1988 *this = temp;
1989 break; }
970ed795 1990 case Module_Param::MP_Octetstring:
3abe9331 1991 *this = OCTETSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
970ed795
EL
1992 break;
1993 case Module_Param::MP_Octetstring_Template:
3abe9331 1994 *this = OCTETSTRING_template(mp->get_string_size(), (unsigned short*)mp->get_string_data());
1995 break;
1996 case Module_Param::MP_Expression:
1997 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
1998 OCTETSTRING operand1, operand2;
1999 operand1.set_param(*mp->get_operand1());
2000 operand2.set_param(*mp->get_operand2());
2001 *this = operand1 + operand2;
2002 }
2003 else {
2004 param.expr_type_error("a bitstring");
2005 }
970ed795
EL
2006 break;
2007 default:
2008 param.type_error("octetstring template");
2009 }
3abe9331 2010 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2011 if (param.get_length_restriction() != NULL) {
2012 set_length_range(param);
2013 }
2014 else {
2015 set_length_range(*mp);
2016 }
2017}
2018
2019Module_Param* OCTETSTRING_template::get_param(Module_Param_Name& param_name) const
2020{
2021 Module_Param* mp = NULL;
2022 switch (template_selection) {
2023 case UNINITIALIZED_TEMPLATE:
2024 mp = new Module_Param_Unbound();
2025 break;
2026 case OMIT_VALUE:
2027 mp = new Module_Param_Omit();
2028 break;
2029 case ANY_VALUE:
2030 mp = new Module_Param_Any();
2031 break;
2032 case ANY_OR_OMIT:
2033 mp = new Module_Param_AnyOrNone();
2034 break;
2035 case SPECIFIC_VALUE:
2036 mp = single_value.get_param(param_name);
2037 break;
2038 case VALUE_LIST:
2039 case COMPLEMENTED_LIST: {
2040 if (template_selection == VALUE_LIST) {
2041 mp = new Module_Param_List_Template();
2042 }
2043 else {
2044 mp = new Module_Param_ComplementList_Template();
2045 }
2046 for (size_t i = 0; i < value_list.n_values; ++i) {
2047 mp->add_elem(value_list.list_value[i].get_param(param_name));
2048 }
2049 break; }
2050 case STRING_PATTERN: {
2051 unsigned short* val_cpy = (unsigned short*)Malloc(pattern_value->n_elements *
2052 sizeof(unsigned short));
2053 memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements *
2054 sizeof(unsigned short));
2055 mp = new Module_Param_Octetstring_Template(pattern_value->n_elements, val_cpy);
2056 break; }
2057 default:
2058 break;
2059 }
2060 if (is_ifpresent) {
2061 mp->set_ifpresent();
2062 }
2063 mp->set_length_restriction(get_length_range());
2064 return mp;
970ed795
EL
2065}
2066
2067void OCTETSTRING_template::encode_text(Text_Buf& text_buf) const
2068{
2069 encode_text_restricted(text_buf);
2070 switch (template_selection) {
2071 case OMIT_VALUE:
2072 case ANY_VALUE:
2073 case ANY_OR_OMIT:
2074 break;
2075 case SPECIFIC_VALUE:
2076 single_value.encode_text(text_buf);
2077 break;
2078 case VALUE_LIST:
2079 case COMPLEMENTED_LIST:
2080 text_buf.push_int(value_list.n_values);
2081 for (unsigned int i = 0; i < value_list.n_values; i++)
2082 value_list.list_value[i].encode_text(text_buf);
2083 break;
2084 case STRING_PATTERN:
2085 text_buf.push_int(pattern_value->n_elements);
2086 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
2087 text_buf.push_int(pattern_value->elements_ptr[i]);
2088 break;
2089 default:
2090 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2091 "octetstring template.");
2092 }
2093}
2094
2095void OCTETSTRING_template::decode_text(Text_Buf& text_buf)
2096{
2097 clean_up();
2098 decode_text_restricted(text_buf);
2099 switch (template_selection) {
2100 case OMIT_VALUE:
2101 case ANY_VALUE:
2102 case ANY_OR_OMIT:
2103 break;
2104 case SPECIFIC_VALUE:
2105 single_value.decode_text(text_buf);
2106 break;
2107 case VALUE_LIST:
2108 case COMPLEMENTED_LIST:
2109 value_list.n_values = text_buf.pull_int().get_val();
2110 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
2111 for (unsigned int i = 0; i < value_list.n_values; i++)
2112 value_list.list_value[i].decode_text(text_buf);
2113 break;
2114 case STRING_PATTERN: {
2115 unsigned int n_elements = text_buf.pull_int().get_val();
2116 pattern_value = (octetstring_pattern_struct*)
2117 Malloc(sizeof(octetstring_pattern_struct) + (n_elements - 1) *
2118 sizeof(unsigned short));
2119 pattern_value->ref_count = 1;
2120 pattern_value->n_elements = n_elements;
2121 for (unsigned int i = 0; i < n_elements; i++)
2122 pattern_value->elements_ptr[i] = text_buf.pull_int().get_val();
2123 break;}
2124 default:
2125 TTCN_error("Text decoder: An unknown/unsupported selection was "
2126 "received for an octetstring template.");
2127 }
2128}
2129
3abe9331 2130boolean OCTETSTRING_template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
2131{
2132 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 2133 return !match_omit(legacy);
970ed795
EL
2134}
2135
3abe9331 2136boolean OCTETSTRING_template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
2137{
2138 if (is_ifpresent) return TRUE;
2139 switch (template_selection) {
2140 case OMIT_VALUE:
2141 case ANY_OR_OMIT:
2142 return TRUE;
2143 case VALUE_LIST:
2144 case COMPLEMENTED_LIST:
3abe9331 2145 if (legacy) {
2146 // legacy behavior: 'omit' can appear in the value/complement list
2147 for (unsigned int i=0; i<value_list.n_values; i++)
2148 if (value_list.list_value[i].match_omit())
2149 return template_selection==VALUE_LIST;
2150 return template_selection==COMPLEMENTED_LIST;
2151 }
2152 // else fall through
970ed795
EL
2153 default:
2154 return FALSE;
2155 }
2156 return FALSE;
2157}
2158
2159#ifndef TITAN_RUNTIME_2
3abe9331 2160void OCTETSTRING_template::check_restriction(template_res t_res, const char* t_name,
2161 boolean legacy /* = FALSE */) const
970ed795
EL
2162{
2163 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2164 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2165 case TR_VALUE:
2166 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2167 break;
2168 case TR_OMIT:
2169 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2170 template_selection==SPECIFIC_VALUE)) return;
2171 break;
2172 case TR_PRESENT:
3abe9331 2173 if (!match_omit(legacy)) return;
970ed795
EL
2174 break;
2175 default:
2176 return;
2177 }
2178 TTCN_error("Restriction `%s' on template of type %s violated.",
2179 get_res_name(t_res), t_name ? t_name : "octetstring");
2180}
2181#endif
This page took 0.103924 seconds and 5 git commands to generate.