Sync with 5.3.0
[deliverable/titan.core.git] / core / Octetstring.cc
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 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#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");
502 if (param.get_type()!=Module_Param::MP_Octetstring) param.type_error("octetstring value");
503 switch (param.get_operation_type()) {
504 case Module_Param::OT_ASSIGN:
505 clean_up();
506 init_struct(param.get_string_size());
507 memcpy(val_ptr->octets_ptr, param.get_string_data(), val_ptr->n_octets);
508 break;
509 case Module_Param::OT_CONCAT:
510 if (is_bound()) {
511 *this += OCTETSTRING(param.get_string_size(), (unsigned char*)param.get_string_data());
512 } else {
513 *this = OCTETSTRING(param.get_string_size(), (unsigned char*)param.get_string_data());
514 }
515 break;
516 default:
517 TTCN_error("Internal error: OCTETSTRING::set_param()");
518 }
519}
520
521void OCTETSTRING::encode_text(Text_Buf& text_buf) const
522{
523 must_bound("Text encoder: Encoding an unbound octetstring value.");
524 text_buf.push_int(val_ptr->n_octets);
525 if(val_ptr->n_octets > 0)
526 text_buf.push_raw(val_ptr->n_octets, val_ptr->octets_ptr);
527}
528
529void OCTETSTRING::decode_text(Text_Buf& text_buf)
530{
531 int n_octets = text_buf.pull_int().get_val();
532 if (n_octets < 0)
533 TTCN_error("Text decoder: Invalid length was received for an octetstring.");
534 clean_up();
535 init_struct(n_octets);
536 if (n_octets > 0) text_buf.pull_raw(n_octets, val_ptr->octets_ptr);
537}
538
539void OCTETSTRING::encode(const TTCN_Typedescriptor_t& p_td,
540 TTCN_Buffer& p_buf,
541 TTCN_EncDec::coding_t p_coding, ...) const
542{
543 va_list pvar;
544 va_start(pvar, p_coding);
545 switch(p_coding) {
546 case TTCN_EncDec::CT_BER: {
547 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
548 unsigned BER_coding=va_arg(pvar, unsigned);
549 BER_encode_chk_coding(BER_coding);
550 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
551 tlv->put_in_buffer(p_buf);
552 ASN_BER_TLV_t::destruct(tlv);
553 break;}
554 case TTCN_EncDec::CT_RAW: {
555 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
556 if(!p_td.raw)
557 TTCN_EncDec_ErrorContext::error_internal
558 ("No RAW descriptor available for type '%s'.", p_td.name);
559 RAW_enc_tr_pos rp;
560 rp.level=0;
561 rp.pos=NULL;
562 RAW_enc_tree root(true,NULL,&rp,1,p_td.raw);
563 RAW_encode(p_td, root);
564 root.put_to_buf(p_buf);
565 break;}
566 case TTCN_EncDec::CT_TEXT: {
567 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
568 if(!p_td.text)
569 TTCN_EncDec_ErrorContext::error_internal
570 ("No TEXT descriptor available for type '%s'.", p_td.name);
571 TEXT_encode(p_td,p_buf);
572 break;}
573 case TTCN_EncDec::CT_XER: {
574 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
575 unsigned XER_coding=va_arg(pvar, unsigned);
af710487 576 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
970ed795
EL
577 break;}
578 case TTCN_EncDec::CT_JSON: {
579 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
580 if(!p_td.json)
581 TTCN_EncDec_ErrorContext::error_internal
582 ("No JSON descriptor available for type '%s'.", p_td.name);
583 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
584 JSON_encode(p_td, tok);
585 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
586 break;}
587 default:
588 TTCN_error("Unknown coding method requested to encode type '%s'",
589 p_td.name);
590 }
591 va_end(pvar);
592}
593
594void OCTETSTRING::decode(const TTCN_Typedescriptor_t& p_td,
595 TTCN_Buffer& p_buf,
596 TTCN_EncDec::coding_t p_coding, ...)
597{
598 va_list pvar;
599 va_start(pvar, p_coding);
600 switch(p_coding) {
601 case TTCN_EncDec::CT_BER: {
602 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
603 unsigned L_form=va_arg(pvar, unsigned);
604 ASN_BER_TLV_t tlv;
605 BER_decode_str2TLV(p_buf, tlv, L_form);
606 BER_decode_TLV(p_td, tlv, L_form);
607 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
608 break;}
609 case TTCN_EncDec::CT_RAW: {
610 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
611 if(!p_td.raw)
612 TTCN_EncDec_ErrorContext::error_internal
613 ("No RAW descriptor available for type '%s'.", p_td.name);
614 raw_order_t order;
615 switch(p_td.raw->top_bit_order){
616 case TOP_BIT_LEFT:
617 order=ORDER_LSB;
618 break;
619 case TOP_BIT_RIGHT:
620 default:
621 order=ORDER_MSB;
622 }
623 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
624 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
625 "Can not decode type '%s', because invalid or incomplete"
626 " message was received"
627 , p_td.name);
628 break;}
629 case TTCN_EncDec::CT_TEXT: {
630 Limit_Token_List limit;
631 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
632 if(!p_td.text)
633 TTCN_EncDec_ErrorContext::error_internal
634 ("No TEXT descriptor available for type '%s'.", p_td.name);
635 const unsigned char *b=p_buf.get_data();
636 if(b[p_buf.get_len()-1]!='\0'){
637 p_buf.set_pos(p_buf.get_len());
638 p_buf.put_zero(8,ORDER_LSB);
639 p_buf.rewind();
640 }
641 if(TEXT_decode(p_td,p_buf,limit)<0)
642 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
643 "Can not decode type '%s', because invalid or incomplete"
644 " message was received"
645 , p_td.name);
646 break;}
647 case TTCN_EncDec::CT_XER: {
af710487 648 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
970ed795
EL
649 unsigned XER_coding=va_arg(pvar, unsigned);
650 XmlReaderWrap reader(p_buf);
651 int success = reader.Read();
652 for (; success==1; success=reader.Read()) {
653 int type = reader.NodeType();
654 if (type==XML_READER_TYPE_ELEMENT)
655 break;
656 }
af710487 657 XER_decode(*p_td.xer, reader, XER_coding, 0);
970ed795
EL
658 size_t bytes = reader.ByteConsumed();
659 p_buf.set_pos(bytes);
660 break;}
661 case TTCN_EncDec::CT_JSON: {
662 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
663 if(!p_td.json)
664 TTCN_EncDec_ErrorContext::error_internal
665 ("No JSON descriptor available for type '%s'.", p_td.name);
666 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
667 if(JSON_decode(p_td, tok, false)<0)
668 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
669 "Can not decode type '%s', because invalid or incomplete"
670 " message was received"
671 , p_td.name);
672 p_buf.set_pos(tok.get_buf_pos());
673 break;}
674 default:
675 TTCN_error("Unknown coding method requested to decode type '%s'",
676 p_td.name);
677 }
678 va_end(pvar);
679}
680
681ASN_BER_TLV_t*
682OCTETSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
683 unsigned p_coding) const
684{
685 BER_chk_descr(p_td);
686 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
687 if(!new_tlv) {
688 new_tlv=BER_encode_TLV_OCTETSTRING
689 (p_coding, val_ptr->n_octets, val_ptr->octets_ptr);
690 }
691 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
692 return new_tlv;
693}
694
695#ifdef TITAN_RUNTIME_2
696ASN_BER_TLV_t* OCTETSTRING::BER_encode_negtest_raw() const
697{
698 unsigned char *p_Vstr = (unsigned char *)Malloc(val_ptr->n_octets);
699 memcpy(p_Vstr, val_ptr->octets_ptr, val_ptr->n_octets);
700 ASN_BER_TLV_t* new_tlv = ASN_BER_TLV_t::construct(val_ptr->n_octets, p_Vstr);
701 return new_tlv;
702}
703
704int OCTETSTRING::encode_raw(TTCN_Buffer& p_buf) const
705{
706 p_buf.put_string(*this);
707 return val_ptr ? val_ptr->n_octets : 0;
708}
709
710int OCTETSTRING::RAW_encode_negtest_raw(RAW_enc_tree& p_myleaf) const
711{
712 if (p_myleaf.must_free)
713 Free(p_myleaf.body.leaf.data_ptr);
714 p_myleaf.must_free = false;
715 p_myleaf.data_ptr_used = true;
716 p_myleaf.body.leaf.data_ptr = val_ptr->octets_ptr;
717 return p_myleaf.length = val_ptr->n_octets * 8;
718}
719#endif
720
721boolean OCTETSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
722 const ASN_BER_TLV_t& p_tlv,
723 unsigned L_form)
724{
725 clean_up();
726 BER_chk_descr(p_td);
727 ASN_BER_TLV_t stripped_tlv;
728 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
729 TTCN_EncDec_ErrorContext ec("While decoding OCTETSTRING type: ");
730 /* Upper estimation for the length. */
731 size_t stripped_tlv_len = stripped_tlv.get_len();
732 if (stripped_tlv_len < 2) return FALSE;
733 int max_len = stripped_tlv_len - 2;
734 init_struct(max_len);
735 unsigned int octetnum_start = 0;
736 BER_decode_TLV_OCTETSTRING(stripped_tlv, L_form, octetnum_start,
737 val_ptr->n_octets, val_ptr->octets_ptr);
738 if (val_ptr->n_octets < max_len) {
739 if (val_ptr->n_octets == 0) {
740 clean_up();
741 init_struct(0);
742 } else {
743 val_ptr = (octetstring_struct*)
744 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_octets));
745 }
746 }
747 return TRUE;
748}
749
750int OCTETSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
751 TTCN_Buffer& buff, Limit_Token_List& limit,
752 boolean no_err, boolean /*first_call*/)
753{
754 int decoded_length=0;
755 int str_len=0;
756 clean_up();
757 if(p_td.text->begin_decode){
758 int tl;
759 if((tl=p_td.text->begin_decode->match_begin(buff))<0){
760 if(no_err)return -1;
761 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
762 "The specified token '%s' not found for '%s': ",
763 (const char*)*(p_td.text->begin_decode), p_td.name);
764 return 0;
765 }
766 decoded_length+=tl;
767 buff.increase_pos(tl);
768 }
769// never returns "too short"
770// if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
771
772 if(p_td.text->select_token){
773 int tl;
774 if((tl=p_td.text->select_token->match_begin(buff))<0) {
775 if(no_err) return -1;
776 else tl=0;
777 }
778 str_len=tl;
779 } else
780 if( p_td.text->val.parameters
781 && p_td.text->val.parameters->decoding_params.min_length!=-1){
782 str_len=p_td.text->val.parameters->decoding_params.min_length*2;
783 } else if(p_td.text->end_decode){
784 int tl;
785 if((tl=p_td.text->end_decode->match_first(buff))<0) {
786 if(no_err) return -1;
787 else tl=0;
788 }
789 str_len=tl;
790 } else if (limit.has_token()){
791 int tl;
792 if((tl=limit.match(buff))<0)
793 tl=buff.get_read_len()-1;;
794 str_len=tl;
795 } else {
796 int tl;
797 if((tl=octetstring_value_match.match_begin(buff))<0) {
798 if(no_err) {return -1; }
799 else tl=0;
800 }
801 str_len=tl;
802 }
803 str_len=(str_len/2)*2;
804//printf("HALI chr:%d ",str_len);
805 int n_octets = str_len / 2;
806 init_struct(n_octets);
807 unsigned char *octets_ptr = val_ptr->octets_ptr;
808 const char *value=(const char*)buff.get_read_data();
809 for (int i = 0; i < n_octets; i++) {
810 unsigned char upper_nibble = char_to_hexdigit(value[2 * i]);
811 unsigned char lower_nibble = char_to_hexdigit(value[2 * i + 1]);
812 if (upper_nibble > 0x0F){
813 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
814 "The octetstring value may contain hexadecimal digits only. "
815 "Character \"%c\" was found.", value[2 * i]);
816 upper_nibble=0;
817 }
818 if (lower_nibble > 0x0F){
819 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
820 "The octetstring value str2oct() may contain hexadecimal digits only. "
821 "Character \"%c\" was found.", value[2 * i + 1]);
822 lower_nibble=0;
823 }
824 octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
825 }
826
827//printf("%s\n\r",val_ptr->chars_ptr);
828 decoded_length+=str_len;
829 buff.increase_pos(str_len);
830
831 if(p_td.text->end_decode){
832 int tl;
833 if((tl=p_td.text->end_decode->match_begin(buff))<0){
834 if(no_err)return -1;
835 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
836 "The specified token '%s' not found for '%s': ",
837 (const char*)*(p_td.text->end_decode), p_td.name);
838 return 0;
839 }
840 decoded_length+=tl;
841 buff.increase_pos(tl);
842 }
843 return decoded_length;
844}
845
846// From Charstring.cc
847extern char base64_decoder_table[256];
848extern unsigned int xlate(cbyte* in, int phase, unsigned char* dest);
849extern const char cb64[];
850
851int OCTETSTRING::XER_encode(const XERdescriptor_t& p_td,
af710487 852 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
853{
854 if(!is_bound()) {
855 TTCN_EncDec_ErrorContext::error
856 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound octetstring value.");
857 }
858 int exer = is_exer(flavor |= SIMPLE_TYPE);
859 // SIMPLE_TYPE has no influence on is_exer, we set it for later
860 int encoded_length=(int)p_buf.get_len();
861 int empty_element = val_ptr==NULL || val_ptr->n_octets == 0;
862
863 flavor &= ~XER_RECOF; // octetstring doesn't care
864 begin_xml(p_td, p_buf, flavor, indent, empty_element);
865
866 if (exer && (p_td.xer_bits & BASE_64)) {
867 // bit more work
868 size_t clear_len = lengthof();
869 const unsigned char * in = operator const unsigned char*();
870
871 /* Encode 3 bytes of cleartext into 4 bytes of Base64.
872 * Note that the algorithm is slightly different from Charstring.cc:
873 * we can't pad the source because it's const (this),
874 * so we need to check the indexes i+1 and i+2 before dereferencing */
875 for (size_t i = 0; i < clear_len; i += 3) {
876 p_buf.put_c( cb64[ in[i] >> 2 ] );
877 p_buf.put_c( cb64[ ((in[i] & 0x03) << 4) | (i+1 < clear_len
878 ? ((in[i+1] & 0xf0) >> 4)
879 :-0) ] );
880 p_buf.put_c( i+1 < clear_len
881 ? cb64[ ((in[i+1] & 0x0f) << 2) | (i+2 < clear_len ? ((in[i+2] & 0xc0) >> 6) :-0) ]
882 :'=');
883 p_buf.put_c( i+2 < clear_len ? cb64[ in[i+2] & 0x3f ] : '=' );
884 } // next i
885 }
886 else {
887 CHARSTRING val = oct2str(*this);
888 p_buf.put_string(val);
889 }
890
891 end_xml(p_td, p_buf, flavor, indent, empty_element);
892
893 return (int)p_buf.get_len() - encoded_length;
894}
895
896int OCTETSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
af710487 897 unsigned int flavor, embed_values_dec_struct_t*)
970ed795
EL
898{
899 int exer = is_exer(flavor);
900 int success = reader.Ok(), depth = -1, type;
901 boolean own_tag = !is_exerlist(flavor) && !(exer && (p_td.xer_bits & UNTAGGED));
902
903 const char * value = 0;
904 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
905 const char * name = verify_name(reader, p_td, exer);
906 (void)name;
907 }
908 else
909 if (own_tag) for (; success == 1; success = reader.Read()) {
910 type = reader.NodeType();
911 if (XML_READER_TYPE_ELEMENT == type) {
912 verify_name(reader, p_td, exer);
913 depth = reader.Depth();
914 if (reader.IsEmptyElement()) {
915 if (exer && p_td.dfeValue != 0) {
916 *this = *static_cast<const OCTETSTRING*> (p_td.dfeValue);
917 }
918 else init_struct(0);
919 reader.Read();
920 goto finished;
921 }
922 }
923 else if (XML_READER_TYPE_TEXT == type && depth != -1) break;
924 else if (XML_READER_TYPE_END_ELEMENT == type) {
925 // End tag without intervening #text == empty content
926 verify_end(reader, p_td, depth, exer);
927 if (exer && p_td.dfeValue != 0) {
928 *this = *static_cast<const OCTETSTRING*>(p_td.dfeValue);
929 }
930 else init_struct(0);
931 reader.Read();
932 goto finished;
933 }
934 }
935
936 type = reader.NodeType();
937 if (success == 1 && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_ATTRIBUTE == type)) {
938 value = (const char *)reader.Value();
939 size_t len = value ? strlen(value) : 0;
940
941 if (exer && (p_td.xer_bits & BASE_64)) {
942 xmlChar in[4];
943
944 int phase = 0;
945 init_struct(len * 3 / 4);
946 unsigned char * dest = val_ptr->octets_ptr;
947
948 for (size_t o=0; o<len; ++o) {
949 xmlChar c = value[o];
950 if(c == '=') { // padding starts
951 dest += xlate(in, phase, dest);
952 break;
953 }
954
955 int val = base64_decoder_table[c];
956 if(val >= 0) {
957 in[phase] = val;
958 phase = (phase + 1) % 4;
959 if(phase == 0) {
960 dest += xlate(in,phase, dest);
961 in[0]=in[1]=in[2]=in[3]=0;
962 }
963 }
964 else if (exer && (flavor & EXIT_ON_ERROR)) {
965 clean_up();
966 return -1;
967 } else {
968 TTCN_EncDec_ErrorContext::warning(
969 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
970 "Invalid character for Base64 '%02X'", c);
971 }
972 } // while
973 // adjust
974 val_ptr->n_octets = dest - val_ptr->octets_ptr;
975
976 }
977 else { // not base64
978 if (len & 1) { // that's odd...
979 if (exer && (flavor & EXIT_ON_ERROR)) {
980 clean_up();
981 return -1;
982 } else {
983 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
984 "Odd number of characters in octetstring");
985 len &= ~1; // make it even
986 }
987 }
988 size_t n_octets = len / 2;
989 init_struct(n_octets);
990
991 len = 0; // will act as 2*i
992 for (size_t i = 0; i < n_octets; ++i, ++++len) {
993 unsigned char upper_nibble = char_to_hexdigit(value[len]);
994 unsigned char lower_nibble = char_to_hexdigit(value[len+1]);
995 if (upper_nibble > 0x0F) {
996 if (exer && (flavor & EXIT_ON_ERROR)) {
997 clean_up();
998 return -1;
999 } else {
1000 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1001 "The octetstring value may contain hexadecimal digits only. "
1002 "Character \"%c\" was found.", value[len]);
1003 upper_nibble=0;
1004 }
1005 }
1006 if (lower_nibble > 0x0F) {
1007 if (exer && (flavor & EXIT_ON_ERROR)) {
1008 clean_up();
1009 return -1;
1010 } else {
1011 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1012 "The octetstring value may contain hexadecimal digits only. "
1013 "Character \"%c\" was found.", value[len+1]);
1014 lower_nibble=0;
1015 }
1016 }
1017 val_ptr->octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
1018 } // next
1019 } // if base64
1020 } // if success
1021
1022 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1023 // Let the caller do reader.AdvanceAttribute();
1024 }
1025 else
1026 if (own_tag) for (success = reader.Read(); success == 1; success = reader.Read()) {
1027 type = reader.NodeType();
1028 if (XML_READER_TYPE_END_ELEMENT == type) {
1029 verify_end(reader, p_td, depth, exer);
1030 if (val_ptr == 0 && p_td.dfeValue != 0) {
1031 // The end tag must have followed the start tag
1032 *this = *static_cast<const OCTETSTRING*>(p_td.dfeValue);
1033 }
1034 reader.Read(); // one last time
1035 break;
1036 }
1037 }
1038finished:
1039 return 1; // decode successful
1040}
1041
1042int OCTETSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1043 TTCN_Buffer& buff) const{
1044 int encoded_length=0;
1045 if(p_td.text->begin_encode){
1046 buff.put_cs(*p_td.text->begin_encode);
1047 encoded_length+=p_td.text->begin_encode->lengthof();
1048 }
1049 if(!is_bound()) {
1050 TTCN_EncDec_ErrorContext::error
1051 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
1052 if(p_td.text->end_encode){
1053 buff.put_cs(*p_td.text->end_encode);
1054 encoded_length+=p_td.text->end_encode->lengthof();
1055 }
1056 return encoded_length;
1057 }
1058
1059 int chars_before=0;
1060
1061 if(p_td.text->val.parameters){
1062 if(val_ptr->n_octets<p_td.text->val.parameters->coding_params.min_length){
1063 chars_before=(p_td.text->
1064 val.parameters->coding_params.min_length-val_ptr->n_octets)*2;
1065 }
1066 }
1067
1068 if(chars_before){
1069 unsigned char* p=NULL;
1070 size_t len=chars_before;
1071 buff.get_end(p,len);
1072 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)'0';
1073 buff.increase_length(chars_before);
1074 encoded_length+=chars_before;
1075 }
1076
1077 if(val_ptr->n_octets){
1078 unsigned char* p=NULL;
1079 size_t len=val_ptr->n_octets*2;
1080 buff.get_end(p,len);
1081 len=val_ptr->n_octets;
1082 for(size_t i=0;i<len;i++){
1083 p[2 * i] = hexdigit_to_char(val_ptr->octets_ptr[i] >> 4);
1084 p[2 * i + 1] = hexdigit_to_char(val_ptr->octets_ptr[i] & 0x0F);
1085 }
1086 buff.increase_length(len*2);
1087 encoded_length+=len*2;
1088 }
1089
1090
1091 if(p_td.text->end_encode){
1092 buff.put_cs(*p_td.text->end_encode);
1093 encoded_length+=p_td.text->end_encode->lengthof();
1094 }
1095 return encoded_length;
1096}
1097
1098int OCTETSTRING::RAW_encode(const TTCN_Typedescriptor_t& p_td,
1099 RAW_enc_tree& myleaf) const
1100{
1101 if (!is_bound()) {
1102 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1103 "Encoding an unbound value.");
1104 }
1105 unsigned char *bc;
1106 int bl = val_ptr->n_octets * 8;
1107 int align_length = p_td.raw->fieldlength ? p_td.raw->fieldlength - bl : 0;
1108 int blength = val_ptr->n_octets;
1109 if ((bl + align_length) < val_ptr->n_octets * 8) {
1110 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1111 "There are insufficient bits to encode '%s': ", p_td.name);
1112 blength = p_td.raw->fieldlength / 8;
1113 bl = p_td.raw->fieldlength;
1114 align_length = 0;
1115 }
1116 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
1117 myleaf.must_free = false;
1118 myleaf.data_ptr_used = true;
1119 if (p_td.raw->extension_bit != EXT_BIT_NO
1120 && myleaf.coding_par.bitorder == ORDER_MSB) {
1121 if (blength > RAW_INT_ENC_LENGTH) {
1122 myleaf.body.leaf.data_ptr = bc = (unsigned char*)Malloc(blength*sizeof(*bc));
1123 myleaf.must_free = true;
1124 myleaf.data_ptr_used = true;
1125 }
1126 else {
1127 bc = myleaf.body.leaf.data_array;
1128 myleaf.data_ptr_used = false;
1129 }
1130 for (int a = 0; a < blength; a++) bc[a] = val_ptr->octets_ptr[a] << 1;
1131 }
1132 else myleaf.body.leaf.data_ptr = val_ptr->octets_ptr;
1133 if (p_td.raw->endianness == ORDER_MSB) myleaf.align = -align_length;
1134 else myleaf.align = align_length;
1135 return myleaf.length = bl + align_length;
1136}
1137
1138int OCTETSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td,
1139 TTCN_Buffer& buff, int limit, raw_order_t top_bit_ord, boolean no_err,
1140 int /*sel_field*/, boolean /*first_call*/)
1141{
1142 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
1143 limit -= prepaddlength;
1144 int decode_length = p_td.raw->fieldlength == 0
1145 ? (limit / 8) * 8 : p_td.raw->fieldlength;
1146 if (decode_length > limit || decode_length > (int) buff.unread_len_bit()) {
1147 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
1148 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1149 "There is not enough bits in the buffer to decode type %s.", p_td.name);
1150 decode_length = ((limit > (int) buff.unread_len_bit()
1151 ? (int)buff.unread_len_bit() : limit) / 8) * 8;
1152 }
1153 RAW_coding_par cp;
1154 bool orders = false;
1155 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = true;
1156 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1157 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
1158 orders = false;
1159 if (p_td.raw->byteorder == ORDER_MSB) orders = true;
1160 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1161 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
1162 cp.fieldorder = p_td.raw->fieldorder;
1163 cp.hexorder = ORDER_LSB;
1164 if (p_td.raw->extension_bit != EXT_BIT_NO) {
1165 const unsigned char* data = buff.get_read_data();
1166 int count = 1;
1167 int rot = top_bit_ord == ORDER_LSB ? 0 : 7;
1168 if (p_td.raw->extension_bit == EXT_BIT_YES) {
1169 while (((data[count - 1] >> rot) & 0x01) == 0 && count * 8 < decode_length)
1170 count++;
1171 }
1172 else {
1173 while (((data[count - 1] >> rot) & 0x01) == 1 && count * 8 < decode_length)
1174 count++;
1175 }
1176 decode_length = count * 8;
1177 }
1178 clean_up();
1179 init_struct(decode_length / 8);
1180 buff.get_b((size_t) decode_length, val_ptr->octets_ptr, cp, top_bit_ord);
1181
1182 if (p_td.raw->length_restrition != -1) {
1183 val_ptr->n_octets = p_td.raw->length_restrition;
1184 if (p_td.raw->endianness == ORDER_MSB) memmove(val_ptr->octets_ptr,
1185 val_ptr->octets_ptr + (decode_length / 8 - val_ptr->n_octets),
1186 val_ptr->n_octets * sizeof(unsigned char));
1187 }
1188 if (p_td.raw->extension_bit != EXT_BIT_NO && cp.bitorder == ORDER_MSB) {
1189 for (int a = 0; a < decode_length / 8; a++)
1190 val_ptr->octets_ptr[a] = val_ptr->octets_ptr[a] >> 1 | val_ptr->octets_ptr[a] << 7;
1191 }
1192 decode_length += buff.increase_pos_padd(p_td.raw->padding);
1193 return decode_length + prepaddlength;
1194}
1195
1196void OCTETSTRING::dump () const
1197{
1198 if (val_ptr != NULL) {
1199 printf("octetstring(%d) :\n", val_ptr->n_octets);
1200 for (int i = 0; i < val_ptr->n_octets; i++) {
1201 printf("%02X ", val_ptr->octets_ptr[i]);
1202 }
1203 printf("\n");
1204 }
1205}
1206
1207int OCTETSTRING::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1208{
1209 if (!is_bound()) {
1210 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1211 "Encoding an unbound octetstring value.");
1212 return -1;
1213 }
1214
1215 char* tmp_str = (char*)Malloc(val_ptr->n_octets * 2 + 3);
1216 tmp_str[0] = '\"';
1217 tmp_str[val_ptr->n_octets * 2 + 1] = '\"';
1218 for(int i = 0; i < val_ptr->n_octets; ++i) {
1219 tmp_str[2 * i + 1] = hexdigit_to_char(val_ptr->octets_ptr[i] >> 4);
1220 tmp_str[2 * i + 2] = hexdigit_to_char(val_ptr->octets_ptr[i] & 0x0F);
1221 }
1222 tmp_str[val_ptr->n_octets * 2 + 2] = 0;
1223 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
1224 Free(tmp_str);
1225 return enc_len;
1226}
1227
1228int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1229{
1230 json_token_t token = JSON_TOKEN_NONE;
1231 char* value = 0;
1232 size_t value_len = 0;
1233 boolean error = false;
1234 int dec_len = 0;
1235 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1236 if (use_default) {
1237 // No JSON data in the buffer -> use default value
1238 value = (char*)p_td.json->default_value;
1239 value_len = strlen(value);
1240 } else {
1241 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1242 }
1243 if (JSON_TOKEN_ERROR == token) {
1244 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1245 return JSON_ERROR_FATAL;
1246 }
1247 else if (JSON_TOKEN_STRING == token || use_default) {
1248 if (0 == value_len % 2 && (use_default ||
1249 (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"'))) {
1250 if (!use_default) {
1251 // The default value doesn't have quotes around it
1252 value_len -= 2;
1253 ++value;
1254 }
1255 size_t octets = value_len / 2;
1256 init_struct(octets);
1257 for (size_t i = 0; i < octets; ++i) {
1258 unsigned char upper_nibble = char_to_hexdigit(value[2 * i]);
1259 unsigned char lower_nibble = char_to_hexdigit(value[2 * i + 1]);
1260 if (upper_nibble <= 0x0F && lower_nibble <= 0x0F) {
1261 val_ptr->octets_ptr[i] = (upper_nibble << 4) | lower_nibble;
1262 } else {
1263 error = true;
1264 }
1265 }
1266 } else {
1267 error = true;
1268 }
1269 } else {
1270 return JSON_ERROR_INVALID_TOKEN;
1271 }
1272
1273 if (error) {
1274 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "octetstring");
1275 if (p_silent) {
1276 clean_up();
1277 }
1278 return JSON_ERROR_FATAL;
1279 }
1280 return dec_len;
1281}
1282
1283// octetstring element class
1284
1285OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag,
1286 OCTETSTRING& par_str_val, int par_octet_pos)
1287 : bound_flag(par_bound_flag), str_val(par_str_val), octet_pos(par_octet_pos)
1288{
1289}
1290
1291OCTETSTRING_ELEMENT& OCTETSTRING_ELEMENT::operator=
1292(const OCTETSTRING& other_value)
1293{
1294 other_value.must_bound("Assignment of an unbound octetstring value.");
1295 if(other_value.val_ptr->n_octets != 1)
1296 TTCN_error("Assignment of an octetstring "
1297 "with length other than 1 to an octetstring element.");
1298 bound_flag = TRUE;
1299 str_val.copy_value();
1300 str_val.val_ptr->octets_ptr[octet_pos] = other_value.val_ptr->octets_ptr[0];
1301 return *this;
1302}
1303
1304OCTETSTRING_ELEMENT& OCTETSTRING_ELEMENT::operator=
1305(const OCTETSTRING_ELEMENT& other_value)
1306{
1307 other_value.must_bound("Assignment of an unbound octetstring element.");
1308 if (&other_value != this) {
1309 bound_flag = TRUE;
1310 str_val.copy_value();
1311 str_val.val_ptr->octets_ptr[octet_pos] =
1312 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1313 }
1314 return *this;
1315}
1316
1317boolean OCTETSTRING_ELEMENT::operator==(const OCTETSTRING& other_value) const
1318{
1319 must_bound("Unbound left operand of octetstring element comparison.");
1320 other_value.must_bound("Unbound right operand of octetstring comparison.");
1321 if(other_value.val_ptr->n_octets != 1) return FALSE;
1322 return str_val.val_ptr->octets_ptr[octet_pos] ==
1323 other_value.val_ptr->octets_ptr[0];
1324}
1325
1326boolean OCTETSTRING_ELEMENT::operator==
1327(const OCTETSTRING_ELEMENT& other_value) const
1328{
1329 must_bound("Unbound left operand of octetstring element comparison.");
1330 other_value.must_bound("Unbound right operand of octetstring element "
1331 "comparison.");
1332 return str_val.val_ptr->octets_ptr[octet_pos] ==
1333 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1334}
1335
1336OCTETSTRING OCTETSTRING_ELEMENT::operator+(const OCTETSTRING& other_value) const
1337{
1338 must_bound("Unbound left operand of octetstring element concatenation.");
1339 other_value.must_bound("Unbound right operand of octetstring concatenation.");
1340 OCTETSTRING ret_val(other_value.val_ptr->n_octets + 1);
1341 ret_val.val_ptr->octets_ptr[0] = str_val.val_ptr->octets_ptr[octet_pos];
1342 memcpy(ret_val.val_ptr->octets_ptr + 1,
1343 other_value.val_ptr->octets_ptr, other_value.val_ptr->n_octets);
1344 return ret_val;
1345}
1346
1347OCTETSTRING OCTETSTRING_ELEMENT::operator+
1348(const OCTETSTRING_ELEMENT& other_value) const
1349{
1350 must_bound("Unbound left operand of octetstring element concatenation.");
1351 other_value.must_bound("Unbound right operand of octetstring element "
1352 "concatenation.");
1353 unsigned char result[2];
1354 result[0] = str_val.val_ptr->octets_ptr[octet_pos];
1355 result[1] = other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1356 return OCTETSTRING(2, result);
1357}
1358
1359OCTETSTRING OCTETSTRING_ELEMENT::operator~() const
1360{
1361 must_bound("Unbound octetstring element operand of operator not4b.");
1362 unsigned char result = ~str_val.val_ptr->octets_ptr[octet_pos];
1363 return OCTETSTRING(1, &result);
1364}
1365
1366OCTETSTRING OCTETSTRING_ELEMENT::operator&(const OCTETSTRING& other_value) const
1367{
1368 must_bound("Left operand of operator and4b is an unbound octetstring "
1369 "element.");
1370 other_value.must_bound("Right operand of operator and4b is an unbound "
1371 "octetstring value.");
1372 if (other_value.val_ptr->n_octets != 1)
1373 TTCN_error("The octetstring "
1374 "operands of operator and4b must have the same length.");
1375 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] &
1376 other_value.val_ptr->octets_ptr[0];
1377 return OCTETSTRING(1, &result);
1378}
1379
1380OCTETSTRING OCTETSTRING_ELEMENT::operator&
1381(const OCTETSTRING_ELEMENT& other_value) const
1382{
1383 must_bound("Left operand of operator and4b is an unbound octetstring "
1384 "element.");
1385 other_value.must_bound("Right operand of operator and4b is an unbound "
1386 "octetstring element.");
1387 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] &
1388 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1389 return OCTETSTRING(1, &result);
1390}
1391
1392OCTETSTRING OCTETSTRING_ELEMENT::operator|(const OCTETSTRING& other_value) const
1393{
1394 must_bound("Left operand of operator or4b is an unbound octetstring "
1395 "element.");
1396 other_value.must_bound("Right operand of operator or4b is an unbound "
1397 "octetstring value.");
1398 if (other_value.val_ptr->n_octets != 1)
1399 TTCN_error("The octetstring "
1400 "operands of operator or4b must have the same length.");
1401 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] |
1402 other_value.val_ptr->octets_ptr[0];
1403 return OCTETSTRING(1, &result);
1404}
1405
1406OCTETSTRING OCTETSTRING_ELEMENT::operator|
1407(const OCTETSTRING_ELEMENT& other_value) const
1408{
1409 must_bound("Left operand of operator or4b is an unbound octetstring "
1410 "element.");
1411 other_value.must_bound("Right operand of operator or4b is an unbound "
1412 "octetstring element.");
1413 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] |
1414 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1415 return OCTETSTRING(1, &result);
1416}
1417
1418OCTETSTRING OCTETSTRING_ELEMENT::operator^(const OCTETSTRING& other_value) const
1419{
1420 must_bound("Left operand of operator xor4b is an unbound octetstring "
1421 "element.");
1422 other_value.must_bound("Right operand of operator xor4b is an unbound "
1423 "octetstring value.");
1424 if (other_value.val_ptr->n_octets != 1)
1425 TTCN_error("The octetstring "
1426 "operands of operator xor4b must have the same length.");
1427 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] ^
1428 other_value.val_ptr->octets_ptr[0];
1429 return OCTETSTRING(1, &result);
1430}
1431
1432OCTETSTRING OCTETSTRING_ELEMENT::operator^
1433(const OCTETSTRING_ELEMENT& other_value) const
1434{
1435 must_bound("Left operand of operator xor4b is an unbound octetstring "
1436 "element.");
1437 other_value.must_bound("Right operand of operator xor4b is an unbound "
1438 "octetstring element.");
1439 unsigned char result = str_val.val_ptr->octets_ptr[octet_pos] ^
1440 other_value.str_val.val_ptr->octets_ptr[other_value.octet_pos];
1441 return OCTETSTRING(1, &result);
1442}
1443
1444unsigned char OCTETSTRING_ELEMENT::get_octet() const
1445{
1446 return str_val.val_ptr->octets_ptr[octet_pos];
1447}
1448
1449void OCTETSTRING_ELEMENT::log() const
1450{
1451 if (bound_flag) {
1452 unsigned char octet = str_val.val_ptr->octets_ptr[octet_pos];
1453 TTCN_Logger::log_char('\'');
1454 TTCN_Logger::log_octet(octet);
1455 TTCN_Logger::log_event_str("'O");
1456 if (TTCN_Logger::is_printable(octet)) {
1457 TTCN_Logger::log_event_str(" (\"");
1458 TTCN_Logger::log_char_escaped(octet);
1459 TTCN_Logger::log_event_str("\")");
1460 }
1461 } else TTCN_Logger::log_event_unbound();
1462}
1463
1464// octetstring template class
1465
1466void OCTETSTRING_template::clean_up()
1467{
1468 switch (template_selection) {
1469 case VALUE_LIST:
1470 case COMPLEMENTED_LIST:
1471 delete [] value_list.list_value;
1472 break;
1473 case STRING_PATTERN:
1474 if (pattern_value->ref_count > 1) pattern_value->ref_count--;
1475 else if (pattern_value->ref_count == 1) Free(pattern_value);
1476 else TTCN_error("Internal error: Invalid reference counter in an "
1477 "octetstring pattern.");
1478 break;
1479 default:
1480 break;
1481 }
1482 template_selection = UNINITIALIZED_TEMPLATE;
1483}
1484
1485void OCTETSTRING_template::copy_template
1486 (const OCTETSTRING_template& other_value)
1487{
1488 switch (other_value.template_selection) {
1489 case SPECIFIC_VALUE:
1490 single_value = other_value.single_value;
1491 break;
1492 case OMIT_VALUE:
1493 case ANY_VALUE:
1494 case ANY_OR_OMIT:
1495 break;
1496 case VALUE_LIST:
1497 case COMPLEMENTED_LIST:
1498 value_list.n_values = other_value.value_list.n_values;
1499 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
1500 for (unsigned int i = 0; i < value_list.n_values; i++)
1501 value_list.list_value[i].copy_template(
1502 other_value.value_list.list_value[i]);
1503 break;
1504 case STRING_PATTERN:
1505 pattern_value = other_value.pattern_value;
1506 pattern_value->ref_count++;
1507 break;
1508 default:
1509 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1510 }
1511 set_selection(other_value);
1512}
1513
1514/*
1515 This is the same algorithm that match_array uses
1516 to match 'record of' types.
1517 The only differences are: how two elements are matched and
1518 how an asterisk or ? is identified in the template
1519*/
1520boolean OCTETSTRING_template::match_pattern(
1521 const octetstring_pattern_struct *string_pattern,
1522 const OCTETSTRING::octetstring_struct *string_value)
1523{
1524 // the empty pattern matches the empty octetstring only
1525 if (string_pattern->n_elements == 0) return string_value->n_octets == 0;
1526
1527 int value_index = 0;
1528 unsigned int template_index = 0;
1529 int last_asterisk = -1;
1530 int last_value_to_asterisk = -1;
1531 //this variable is used to speed up the function
1532 unsigned short pattern_element;
1533
1534 for(;;)
1535 {
1536 pattern_element = string_pattern->elements_ptr[template_index];
1537 if( pattern_element < 256){
1538 if(string_value->octets_ptr[value_index] == pattern_element)
1539 {
1540 value_index++;
1541 template_index++;
1542 }else{
1543 if(last_asterisk == -1) return FALSE;
1544 template_index = last_asterisk +1;
1545 value_index = ++last_value_to_asterisk;
1546 }
1547 } else if(pattern_element == 256)
1548 {//? found
1549 value_index++;
1550 template_index++;
1551 }else if(pattern_element == 257)
1552 {//* found
1553 last_asterisk = template_index++;
1554 last_value_to_asterisk = value_index;
1555 } else TTCN_error("Internal error: invalid element in an octetstring "
1556 "pattern.");
1557
1558 if(value_index == string_value->n_octets
1559 && template_index == string_pattern->n_elements)
1560 {
1561 return TRUE;
1562 }else if (template_index == string_pattern->n_elements)
1563 {
1564 if(string_pattern->elements_ptr[template_index - 1] == 257)
1565 {
1566 return TRUE;
1567 }else if(last_asterisk == -1)
1568 {
1569 return FALSE;
1570 }else{
1571 template_index = last_asterisk+1;
1572 value_index = ++last_value_to_asterisk;
1573 }
1574 }else if(value_index == string_value->n_octets)
1575 {
1576 while(template_index < string_pattern->n_elements
1577 && string_pattern->elements_ptr[template_index] == 257)
1578 template_index++;
1579
1580 return template_index == string_pattern->n_elements;
1581 }
1582 }
1583}
1584
1585OCTETSTRING_template::OCTETSTRING_template()
1586{
1587}
1588
1589OCTETSTRING_template::OCTETSTRING_template(template_sel other_value)
1590 : Restricted_Length_Template(other_value)
1591{
1592 check_single_selection(other_value);
1593}
1594
1595OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING& other_value)
1596 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1597{
1598}
1599
1600OCTETSTRING_template::OCTETSTRING_template
1601 (const OCTETSTRING_ELEMENT& other_value)
1602 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1603{
1604}
1605
1606OCTETSTRING_template::OCTETSTRING_template
1607(const OPTIONAL<OCTETSTRING>& other_value)
1608{
1609 switch (other_value.get_selection()) {
1610 case OPTIONAL_PRESENT:
1611 set_selection(SPECIFIC_VALUE);
1612 single_value = (const OCTETSTRING&)other_value;
1613 break;
1614 case OPTIONAL_OMIT:
1615 set_selection(OMIT_VALUE);
1616 break;
1617 default:
1618 TTCN_error("Creating an octetstring template from an unbound optional "
1619 "field.");
1620 }
1621}
1622
1623OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements,
1624 const unsigned short *pattern_elements)
1625 : Restricted_Length_Template(STRING_PATTERN)
1626{
1627 pattern_value = (octetstring_pattern_struct*)
1628 Malloc(sizeof(octetstring_pattern_struct) +
1629 (n_elements - 1) * sizeof(unsigned short));
1630 pattern_value->ref_count = 1;
1631 pattern_value->n_elements = n_elements;
1632 memcpy(pattern_value->elements_ptr, pattern_elements,
1633 n_elements * sizeof(unsigned short));
1634}
1635
1636OCTETSTRING_template::OCTETSTRING_template
1637 (const OCTETSTRING_template& other_value)
1638: Restricted_Length_Template()
1639{
1640 copy_template(other_value);
1641}
1642
1643OCTETSTRING_template::~OCTETSTRING_template()
1644{
1645 clean_up();
1646}
1647
1648OCTETSTRING_template& OCTETSTRING_template::operator=(template_sel other_value)
1649{
1650 check_single_selection(other_value);
1651 clean_up();
1652 set_selection(other_value);
1653 return *this;
1654}
1655
1656OCTETSTRING_template& OCTETSTRING_template::operator=
1657(const OCTETSTRING& other_value)
1658{
1659 other_value.must_bound("Assignment of an unbound octetstring value to a "
1660 "template.");
1661 clean_up();
1662 set_selection(SPECIFIC_VALUE);
1663 single_value = other_value;
1664 return *this;
1665}
1666
1667OCTETSTRING_template& OCTETSTRING_template::operator=
1668 (const OCTETSTRING_ELEMENT& other_value)
1669{
1670 other_value.must_bound("Assignment of an unbound octetstring element to a "
1671 "template.");
1672 clean_up();
1673 set_selection(SPECIFIC_VALUE);
1674 single_value = other_value;
1675 return *this;
1676}
1677
1678OCTETSTRING_template& OCTETSTRING_template::operator=
1679 (const OPTIONAL<OCTETSTRING>& other_value)
1680{
1681 clean_up();
1682 switch (other_value.get_selection()) {
1683 case OPTIONAL_PRESENT:
1684 set_selection(SPECIFIC_VALUE);
1685 single_value = (const OCTETSTRING&)other_value;
1686 break;
1687 case OPTIONAL_OMIT:
1688 set_selection(OMIT_VALUE);
1689 break;
1690 default:
1691 TTCN_error("Assignment of an unbound optional field to an octetstring "
1692 "template.");
1693 }
1694 return *this;
1695}
1696
1697OCTETSTRING_template& OCTETSTRING_template::operator=
1698(const OCTETSTRING_template& other_value)
1699{
1700 if (&other_value != this) {
1701 clean_up();
1702 copy_template(other_value);
1703 }
1704 return *this;
1705}
1706
1707OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value)
1708{
1709 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1710 TTCN_error("Accessing an octetstring element of a non-specific "
1711 "octetstring template.");
1712 return single_value[index_value];
1713}
1714
1715OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value)
1716{
1717 index_value.must_bound("Indexing a octetstring value with an unbound "
1718 "integer value.");
1719 return (*this)[(int)index_value];
1720}
1721
1722const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](int index_value) const
1723{
1724 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1725 TTCN_error("Accessing an octetstring element of a non-specific "
1726 "octetstring template.");
1727 return single_value[index_value];
1728}
1729
1730const OCTETSTRING_ELEMENT OCTETSTRING_template::operator[](const INTEGER& index_value) const
1731{
1732 index_value.must_bound("Indexing a octetstring template with an unbound "
1733 "integer value.");
1734 return (*this)[(int)index_value];
1735}
1736
1737boolean OCTETSTRING_template::match(const OCTETSTRING& other_value) const
1738{
1739 if (!other_value.is_bound()) return FALSE;
1740 if (!match_length(other_value.val_ptr->n_octets)) return FALSE;
1741 switch (template_selection) {
1742 case SPECIFIC_VALUE:
1743 return single_value == other_value;
1744 case OMIT_VALUE:
1745 return FALSE;
1746 case ANY_VALUE:
1747 case ANY_OR_OMIT:
1748 return TRUE;
1749 case VALUE_LIST:
1750 case COMPLEMENTED_LIST:
1751 for(unsigned int i = 0; i < value_list.n_values; i++)
1752 if (value_list.list_value[i].match(other_value))
1753 return template_selection == VALUE_LIST;
1754 return template_selection == COMPLEMENTED_LIST;
1755 case STRING_PATTERN:
1756 return match_pattern(pattern_value, other_value.val_ptr);
1757 default:
1758 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1759 }
1760 return FALSE;
1761}
1762
1763const OCTETSTRING& OCTETSTRING_template::valueof() const
1764{
1765 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1766 TTCN_error("Performing a valueof or send operation on a non-specific "
1767 "octetstring template.");
1768 return single_value;
1769}
1770
1771int OCTETSTRING_template::lengthof() const
1772{
1773 int min_length;
1774 boolean has_any_or_none;
1775 if (is_ifpresent)
1776 TTCN_error("Performing lengthof() operation on a octetstring template "
1777 "which has an ifpresent attribute.");
1778 switch (template_selection)
1779 {
1780 case SPECIFIC_VALUE:
1781 min_length = single_value.lengthof();
1782 has_any_or_none = FALSE;
1783 break;
1784 case OMIT_VALUE:
1785 TTCN_error("Performing lengthof() operation on an octetstring template "
1786 "containing omit value.");
1787 case ANY_VALUE:
1788 case ANY_OR_OMIT:
1789 min_length = 0;
1790 has_any_or_none = TRUE; // max. length is infinity
1791 break;
1792 case VALUE_LIST:
1793 {
1794 // error if any element does not have length or the lengths differ
1795 if (value_list.n_values<1)
1796 TTCN_error("Internal error: "
1797 "Performing lengthof() operation on an octetstring template "
1798 "containing an empty list.");
1799 int item_length = value_list.list_value[0].lengthof();
1800 for (unsigned int i = 1; i < value_list.n_values; i++) {
1801 if (value_list.list_value[i].lengthof()!=item_length)
1802 TTCN_error("Performing lengthof() operation on an octetstring template "
1803 "containing a value list with different lengths.");
1804 }
1805 min_length = item_length;
1806 has_any_or_none = FALSE;
1807 break;
1808 }
1809 case COMPLEMENTED_LIST:
1810 TTCN_error("Performing lengthof() operation on an octetstring template "
1811 "containing complemented list.");
1812 case STRING_PATTERN:
1813 min_length = 0;
1814 has_any_or_none = FALSE; // TRUE if * chars in the pattern
1815 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
1816 {
1817 if (pattern_value->elements_ptr[i] < 257) min_length++;
1818 else has_any_or_none = TRUE; // case of * character
1819 }
1820 break;
1821 default:
1822 TTCN_error("Performing lengthof() operation on an "
1823 "uninitialized/unsupported octetstring template.");
1824 }
1825 return check_section_is_single(min_length, has_any_or_none,
1826 "length", "an", "octetstring template");
1827}
1828
1829void OCTETSTRING_template::set_type(template_sel template_type,
1830 unsigned int list_length)
1831{
1832 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
1833 TTCN_error("Setting an invalid list type for an octetstring template.");
1834 clean_up();
1835 set_selection(template_type);
1836 value_list.n_values = list_length;
1837 value_list.list_value = new OCTETSTRING_template[list_length];
1838}
1839
1840OCTETSTRING_template& OCTETSTRING_template::list_item(unsigned int list_index)
1841{
1842 if (template_selection != VALUE_LIST &&
1843 template_selection != COMPLEMENTED_LIST)
1844 TTCN_error("Accessing a list element of a non-list octetstring template.");
1845 if (list_index >= value_list.n_values)
1846 TTCN_error("Index overflow in an octetstring value list template.");
1847 return value_list.list_value[list_index];
1848}
1849
1850void OCTETSTRING_template::log() const
1851{
1852 switch (template_selection) {
1853 case SPECIFIC_VALUE:
1854 single_value.log();
1855 break;
1856 case COMPLEMENTED_LIST:
1857 TTCN_Logger::log_event_str("complement ");
1858 // no break
1859 case VALUE_LIST:
1860 TTCN_Logger::log_char('(');
1861 for(unsigned int i = 0; i < value_list.n_values; i++) {
1862 if (i > 0) TTCN_Logger::log_event_str(", ");
1863 value_list.list_value[i].log();
1864 }
1865 TTCN_Logger::log_char(')');
1866 break;
1867 case STRING_PATTERN:
1868 TTCN_Logger::log_char('\'');
1869 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1870 unsigned short pattern = pattern_value->elements_ptr[i];
1871 if (pattern < 256) TTCN_Logger::log_octet(pattern);
1872 else if (pattern == 256) TTCN_Logger::log_char('?');
1873 else if (pattern == 257) TTCN_Logger::log_char('*');
1874 else TTCN_Logger::log_event_str("<unknown>");
1875 }
1876 TTCN_Logger::log_event_str("'O");
1877 break;
1878 default:
1879 log_generic();
1880 break;
1881 }
1882 log_restricted();
1883 log_ifpresent();
1884}
1885
1886void OCTETSTRING_template::log_match(const OCTETSTRING& match_value) const
1887{
1888 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
1889 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1890 TTCN_Logger::print_logmatch_buffer();
1891 TTCN_Logger::log_event_str(" := ");
1892 }
1893 match_value.log();
1894 TTCN_Logger::log_event_str(" with ");
1895 log();
1896 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1897 else TTCN_Logger::log_event_str(" unmatched");
1898}
1899
1900void OCTETSTRING_template::set_param(Module_Param& param) {
1901 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "octetstring template");
1902 switch (param.get_type()) {
1903 case Module_Param::MP_Omit:
1904 *this = OMIT_VALUE;
1905 break;
1906 case Module_Param::MP_Any:
1907 *this = ANY_VALUE;
1908 break;
1909 case Module_Param::MP_AnyOrNone:
1910 *this = ANY_OR_OMIT;
1911 break;
1912 case Module_Param::MP_List_Template:
1913 case Module_Param::MP_ComplementList_Template:
1914 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
1915 for (size_t i=0; i<param.get_size(); i++) {
1916 list_item(i).set_param(*param.get_elem(i));
1917 }
1918 break;
1919 case Module_Param::MP_Octetstring:
1920 *this = OCTETSTRING(param.get_string_size(), (unsigned char*)param.get_string_data());
1921 break;
1922 case Module_Param::MP_Octetstring_Template:
1923 *this = OCTETSTRING_template(param.get_string_size(), (unsigned short*)param.get_string_data());
1924 break;
1925 default:
1926 param.type_error("octetstring template");
1927 }
1928 is_ifpresent = param.get_ifpresent();
1929 set_length_range(param);
1930}
1931
1932void OCTETSTRING_template::encode_text(Text_Buf& text_buf) const
1933{
1934 encode_text_restricted(text_buf);
1935 switch (template_selection) {
1936 case OMIT_VALUE:
1937 case ANY_VALUE:
1938 case ANY_OR_OMIT:
1939 break;
1940 case SPECIFIC_VALUE:
1941 single_value.encode_text(text_buf);
1942 break;
1943 case VALUE_LIST:
1944 case COMPLEMENTED_LIST:
1945 text_buf.push_int(value_list.n_values);
1946 for (unsigned int i = 0; i < value_list.n_values; i++)
1947 value_list.list_value[i].encode_text(text_buf);
1948 break;
1949 case STRING_PATTERN:
1950 text_buf.push_int(pattern_value->n_elements);
1951 for (unsigned int i = 0; i < pattern_value->n_elements; i++)
1952 text_buf.push_int(pattern_value->elements_ptr[i]);
1953 break;
1954 default:
1955 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1956 "octetstring template.");
1957 }
1958}
1959
1960void OCTETSTRING_template::decode_text(Text_Buf& text_buf)
1961{
1962 clean_up();
1963 decode_text_restricted(text_buf);
1964 switch (template_selection) {
1965 case OMIT_VALUE:
1966 case ANY_VALUE:
1967 case ANY_OR_OMIT:
1968 break;
1969 case SPECIFIC_VALUE:
1970 single_value.decode_text(text_buf);
1971 break;
1972 case VALUE_LIST:
1973 case COMPLEMENTED_LIST:
1974 value_list.n_values = text_buf.pull_int().get_val();
1975 value_list.list_value = new OCTETSTRING_template[value_list.n_values];
1976 for (unsigned int i = 0; i < value_list.n_values; i++)
1977 value_list.list_value[i].decode_text(text_buf);
1978 break;
1979 case STRING_PATTERN: {
1980 unsigned int n_elements = text_buf.pull_int().get_val();
1981 pattern_value = (octetstring_pattern_struct*)
1982 Malloc(sizeof(octetstring_pattern_struct) + (n_elements - 1) *
1983 sizeof(unsigned short));
1984 pattern_value->ref_count = 1;
1985 pattern_value->n_elements = n_elements;
1986 for (unsigned int i = 0; i < n_elements; i++)
1987 pattern_value->elements_ptr[i] = text_buf.pull_int().get_val();
1988 break;}
1989 default:
1990 TTCN_error("Text decoder: An unknown/unsupported selection was "
1991 "received for an octetstring template.");
1992 }
1993}
1994
1995boolean OCTETSTRING_template::is_present() const
1996{
1997 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1998 return !match_omit();
1999}
2000
2001boolean OCTETSTRING_template::match_omit() const
2002{
2003 if (is_ifpresent) return TRUE;
2004 switch (template_selection) {
2005 case OMIT_VALUE:
2006 case ANY_OR_OMIT:
2007 return TRUE;
2008 case VALUE_LIST:
2009 case COMPLEMENTED_LIST:
2010 for (unsigned int i=0; i<value_list.n_values; i++)
2011 if (value_list.list_value[i].match_omit())
2012 return template_selection==VALUE_LIST;
2013 return template_selection==COMPLEMENTED_LIST;
2014 default:
2015 return FALSE;
2016 }
2017 return FALSE;
2018}
2019
2020#ifndef TITAN_RUNTIME_2
2021void OCTETSTRING_template::check_restriction(template_res t_res, const char* t_name) const
2022{
2023 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2024 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2025 case TR_VALUE:
2026 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2027 break;
2028 case TR_OMIT:
2029 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2030 template_selection==SPECIFIC_VALUE)) return;
2031 break;
2032 case TR_PRESENT:
2033 if (!match_omit()) return;
2034 break;
2035 default:
2036 return;
2037 }
2038 TTCN_error("Restriction `%s' on template of type %s violated.",
2039 get_res_name(t_res), t_name ? t_name : "octetstring");
2040}
2041#endif
This page took 0.15138 seconds and 5 git commands to generate.