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