1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
17 * Szabo, Janos Zoltan – initial implementation
19 ******************************************************************************/
24 #include "Param_Types.hh"
27 #include "Basetype.hh"
28 #include "Template.hh"
29 #include "Optional.hh"
30 #include "Parameters.h"
32 #include "Struct_of.hh"
37 extern unsigned int get_timer_array_index(int index_value,
38 unsigned int array_size, int index_offset);
39 extern unsigned int get_timer_array_index(const INTEGER& index_value,
40 unsigned int array_size, int index_offset);
42 /** @brief Runtime implementation of timer arrays.
44 * @param T_type the type of the array element. This can be \c TIMER_ARRAY
45 * for multi-dimensional arrays.
46 * @param array_size the number of elements in the array
47 * @param index_offset the lowest index
50 template <typename T_type, unsigned int array_size, int index_offset>
52 #ifdef TITAN_RUNTIME_2
53 : public RefdIndexInterface
56 T_type array_elements[array_size];
57 char * names[array_size];
59 /// Copy constructor disallowed.
60 TIMER_ARRAY(const TIMER_ARRAY& other_value);
61 /// Assignment disallowed.
62 TIMER_ARRAY& operator=(const TIMER_ARRAY& other_value);
68 for (unsigned int i = 0; i < array_size; ++i) {
73 T_type& operator[](int index_value) { return array_elements[
74 get_timer_array_index(index_value, array_size, index_offset)]; }
75 T_type& operator[](const INTEGER& index_value) { return array_elements[
76 get_timer_array_index(index_value, array_size, index_offset)]; }
78 int n_elem() const { return array_size; }
79 int size_of() const { return array_size; }
80 int lengthof() const { return array_size; }
82 T_type& array_element(unsigned int index_value)
83 { return array_elements[index_value]; }
85 void set_name(const char * name_string)
87 for (int i = 0; i < (int)array_size; ++i) {
88 // index_offset may be negative, hence i must be int (not size_t)
89 // to ensure that signed arithmetic is used.
90 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
91 array_elements[i].set_name(names[i]);
97 TTCN_Logger::log_event_str("{ ");
98 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
99 if (v_index > 0) TTCN_Logger::log_event_str(", ");
100 array_elements[v_index].log();
102 TTCN_Logger::log_event_str(" }");
106 extern unsigned int get_port_array_index(int index_value,
107 unsigned int array_size, int index_offset);
108 extern unsigned int get_port_array_index(const INTEGER& index_value,
109 unsigned int array_size, int index_offset);
111 template <typename T_type, unsigned int array_size, int index_offset>
113 #ifdef TITAN_RUNTIME_2
114 : public RefdIndexInterface
117 T_type array_elements[array_size];
118 char * names[array_size];
120 /// Copy constructor disallowed.
121 PORT_ARRAY(const PORT_ARRAY& other_value);
122 /// Assignment disallowed.
123 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
129 for (unsigned int i = 0; i < array_size; ++i) {
134 T_type& operator[](int index_value) { return array_elements[
135 get_port_array_index(index_value, array_size, index_offset)]; }
136 T_type& operator[](const INTEGER& index_value) { return array_elements[
137 get_port_array_index(index_value, array_size, index_offset)]; }
139 int n_elem() const { return array_size; }
140 int size_of() const { return array_size; }
141 int lengthof()const { return array_size; }
143 void set_name(const char * name_string)
145 for (int i = 0; i < (int)array_size; ++i) {
146 // i must be int, see comment in TIMER_ARRAY::set_name
147 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
148 array_elements[i].set_name(names[i]);
154 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
155 array_elements[v_index].activate_port();
161 TTCN_Logger::log_event_str("{ ");
162 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
163 if (v_index > 0) TTCN_Logger::log_event_str(", ");
164 array_elements[v_index].log();
166 TTCN_Logger::log_event_str(" }");
170 ////////////////////////////////////////////////////////////////////////////////
172 extern unsigned int get_array_index(int index_value,
173 unsigned int array_size, int index_offset);
174 extern unsigned int get_array_index(const INTEGER& index_value,
175 unsigned int array_size, int index_offset);
177 template <typename T_type, unsigned int array_size, int index_offset>
178 class VALUE_ARRAY : public Base_Type
179 #ifdef TITAN_RUNTIME_2
180 , public RefdIndexInterface
183 T_type array_elements[array_size];
185 // This class use the compiler-generated copy constructor and
188 // User defined default constructor
189 VALUE_ARRAY() : array_elements(){};
190 boolean operator==(const VALUE_ARRAY& other_value) const;
191 inline boolean operator!=(const VALUE_ARRAY& other_value) const
192 { return !(*this == other_value); }
194 T_type& operator[](int index_value) { return array_elements[
195 get_array_index(index_value, array_size, index_offset)]; }
196 T_type& operator[](const INTEGER& index_value) { return array_elements[
197 get_array_index(index_value, array_size, index_offset)]; }
198 const T_type& operator[](int index_value) const { return array_elements[
199 get_array_index(index_value, array_size, index_offset)]; }
200 const T_type& operator[](const INTEGER& index_value) const {
201 return array_elements[
202 get_array_index(index_value, array_size, index_offset)];
206 VALUE_ARRAY operator<<=(int rotate_count) const;
207 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
208 VALUE_ARRAY operator>>=(int rotate_count) const;
209 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
211 T_type& array_element(unsigned int index_value)
212 { return array_elements[index_value]; }
213 const T_type& array_element(unsigned int index_value) const
214 { return array_elements[index_value]; }
216 void set_implicit_omit();
218 boolean is_bound() const;
219 boolean is_value() const;
223 inline int n_elem() const { return array_size; }
224 inline int size_of() const { return array_size; }
225 int lengthof() const;
227 void set_param(Module_Param& param);
228 Module_Param* get_param(Module_Param_Name& param_name) const;
230 #ifdef TITAN_RUNTIME_2
231 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
232 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
233 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
234 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
236 inline boolean is_present() const { return is_bound(); }
239 void encode_text(Text_Buf& text_buf) const;
240 void decode_text(Text_Buf& text_buf);
242 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
243 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
245 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
246 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
248 virtual ~VALUE_ARRAY() { } // just to avoid warnings
250 /** Encodes accordingly to the JSON encoding rules.
251 * Returns the length of the encoded data. */
252 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
254 /** Decodes accordingly to the JSON encoding rules.
255 * Returns the length of the decoded data. */
256 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
259 template <typename T_type, unsigned int array_size, int index_offset>
260 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
261 (const VALUE_ARRAY& other_value) const
263 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
264 if (array_elements[elem_count] != other_value.array_elements[elem_count])
269 template <typename T_type, unsigned int array_size, int index_offset>
270 VALUE_ARRAY<T_type,array_size,index_offset>
271 VALUE_ARRAY<T_type,array_size,index_offset>::
272 operator<<=(int rotate_count) const {
273 return *this >>= (-rotate_count);
276 template <typename T_type, unsigned int array_size, int index_offset>
277 VALUE_ARRAY<T_type,array_size,index_offset>
278 VALUE_ARRAY<T_type,array_size,index_offset>::
279 operator<<=(const INTEGER& rotate_count) const {
280 rotate_count.must_bound("Unbound integer operand of rotate left "
282 return *this >>= (int)(-rotate_count);
285 template <typename T_type, unsigned int array_size, int index_offset>
286 VALUE_ARRAY<T_type,array_size,index_offset>
287 VALUE_ARRAY<T_type,array_size,index_offset>::
288 operator>>=(int rotate_count) const {
290 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
291 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
292 if (rc == 0) return *this;
293 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
294 for (unsigned int i=0; i<array_size; i++) {
295 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
300 template <typename T_type, unsigned int array_size, int index_offset>
301 VALUE_ARRAY<T_type,array_size,index_offset>
302 VALUE_ARRAY<T_type,array_size,index_offset>::
303 operator>>=(const INTEGER& rotate_count) const {
304 rotate_count.must_bound("Unbound integer operand of rotate right "
306 return *this >>= (int)rotate_count;
309 template <typename T_type, unsigned int array_size, int index_offset>
310 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
312 for (unsigned int i = 0; i < array_size; ++i) {
313 if (array_elements[i].is_bound())
314 array_elements[i].set_implicit_omit();
318 template <typename T_type, unsigned int array_size, int index_offset>
319 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
321 for (unsigned int i = 0; i < array_size; ++i) {
322 if (!array_elements[i].is_bound()) {
329 template <typename T_type, unsigned int array_size, int index_offset>
330 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
332 for (unsigned int i = 0; i < array_size; ++i) {
333 if (!array_elements[i].is_value()) {
340 template <typename T_type, unsigned int array_size, int index_offset>
341 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
343 for (unsigned int i = 0; i < array_size; ++i) {
344 array_elements[i].clean_up();
348 template <typename T_type, unsigned int array_size, int index_offset>
349 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
351 TTCN_Logger::log_event_str("{ ");
352 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
354 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
355 array_elements[elem_count].log();
357 TTCN_Logger::log_event_str(" }");
360 template <typename T_type, unsigned int array_size, int index_offset>
361 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
364 for (unsigned int my_length=array_size; my_length>0; my_length--)
366 if (array_elements[my_length-1].is_bound()) return my_length;
371 template <typename T_type, unsigned int array_size, int index_offset>
372 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
375 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
376 param.get_id()->next_name()) {
377 // Haven't reached the end of the module parameter name
378 // => the name refers to one of the elements, not to the whole array
379 char* param_field = param.get_id()->get_current_name();
380 if (param_field[0] < '0' || param_field[0] > '9') {
381 param.error("Unexpected record field name in module parameter, expected a valid"
384 unsigned int param_index = -1;
385 sscanf(param_field, "%u", ¶m_index);
386 if (param_index >= array_size) {
387 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
389 array_elements[param_index].set_param(param);
393 param.basic_check(Module_Param::BC_VALUE, "array value");
394 Module_Param_Ptr mp = ¶m;
395 if (param.get_type() == Module_Param::MP_Reference) {
396 mp = param.get_referenced_param();
398 switch (mp->get_type()) {
399 case Module_Param::MP_Value_List:
400 if (mp->get_size()!=array_size) {
401 param.error("The array value has incorrect number of elements: %lu was expected instead of %lu.", (unsigned long)mp->get_size(), (unsigned long)array_size);
403 for (size_t i=0; i<mp->get_size(); ++i) {
404 Module_Param* const curr = mp->get_elem(i);
405 if (curr->get_type()!=Module_Param::MP_NotUsed) {
406 array_elements[i].set_param(*curr);
410 case Module_Param::MP_Indexed_List:
411 for (size_t i=0; i<mp->get_size(); ++i) {
412 Module_Param* const curr = mp->get_elem(i);
413 array_elements[curr->get_id()->get_index()].set_param(*curr);
417 param.type_error("array value");
421 template <typename T_type, unsigned int array_size, int index_offset>
422 Module_Param* VALUE_ARRAY<T_type,array_size,index_offset>::get_param
423 (Module_Param_Name& param_name) const
426 return new Module_Param_Unbound();
428 if (param_name.next_name()) {
429 // Haven't reached the end of the module parameter name
430 // => the name refers to one of the elements, not to the whole array
431 char* param_field = param_name.get_current_name();
432 if (param_field[0] < '0' || param_field[0] > '9') {
433 TTCN_error("Unexpected record field name in module parameter reference, "
434 "expected a valid array index");
436 unsigned int param_index = -1;
437 sscanf(param_field, "%u", ¶m_index);
438 if (param_index >= array_size) {
439 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
441 return array_elements[param_index].get_param(param_name);
443 Vector<Module_Param*> values;
444 for (unsigned int i = 0; i < array_size; ++i) {
445 values.push_back(array_elements[i].get_param(param_name));
447 Module_Param_Value_List* mp = new Module_Param_Value_List();
448 mp->add_list_with_implicit_ids(&values);
453 template <typename T_type, unsigned int array_size, int index_offset>
454 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
455 (Text_Buf& text_buf) const
457 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
458 array_elements[elem_count].encode_text(text_buf);
461 template <typename T_type, unsigned int array_size, int index_offset>
462 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
465 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
466 array_elements[elem_count].decode_text(text_buf);
469 template <typename T_type, unsigned int array_size, int index_offset>
470 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
471 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
474 va_start(pvar, p_coding);
476 case TTCN_EncDec::CT_JSON: {
477 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
478 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
479 ("No JSON descriptor available for type '%s'.", p_td.name);
480 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
481 JSON_encode(p_td, tok);
482 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
485 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
490 template <typename T_type, unsigned int array_size, int index_offset>
491 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
492 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
495 case TTCN_EncDec::CT_JSON: {
496 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
497 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
498 ("No JSON descriptor available for type '%s'.", p_td.name);
499 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
500 if(JSON_decode(p_td, tok, false)<0)
501 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
502 "because invalid or incomplete message was received", p_td.name);
503 p_buf.set_pos(tok.get_buf_pos());
506 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
510 template <typename T_type, unsigned int array_size, int index_offset>
511 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
512 const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
514 if (!is_bound() && (NULL == p_td.json || !p_td.json->metainfo_unbound)) {
515 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
516 "Encoding an unbound array value.");
520 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
522 for (unsigned int i = 0; i < array_size; ++i) {
523 if (NULL != p_td.json && p_td.json->metainfo_unbound && !array_elements[i].is_bound()) {
524 // unbound elements are encoded as { "metainfo []" : "unbound" }
525 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
526 enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
527 enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
528 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
531 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
532 if (0 > ret_val) break;
537 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
541 template <typename T_type, unsigned int array_size, int index_offset>
542 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
543 const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
545 json_token_t token = JSON_TOKEN_NONE;
546 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
547 if (JSON_TOKEN_ERROR == token) {
548 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
549 return JSON_ERROR_FATAL;
551 else if (JSON_TOKEN_ARRAY_START != token) {
552 return JSON_ERROR_INVALID_TOKEN;
555 for (unsigned int i = 0; i < array_size; ++i) {
556 size_t buf_pos = p_tok.get_buf_pos();
558 if (NULL != p_td.json && p_td.json->metainfo_unbound) {
559 // check for metainfo object
560 ret_val = p_tok.get_next_token(&token, NULL, NULL);
561 if (JSON_TOKEN_OBJECT_START == token) {
563 size_t value_len = 0;
564 ret_val += p_tok.get_next_token(&token, &value, &value_len);
565 if (JSON_TOKEN_NAME == token && 11 == value_len &&
566 0 == strncmp(value, "metainfo []", 11)) {
567 ret_val += p_tok.get_next_token(&token, &value, &value_len);
568 if (JSON_TOKEN_STRING == token && 9 == value_len &&
569 0 == strncmp(value, "\"unbound\"", 9)) {
570 ret_val = p_tok.get_next_token(&token, NULL, NULL);
571 if (JSON_TOKEN_OBJECT_END == token) {
578 // metainfo object not found, jump back and let the element type decode it
579 p_tok.set_buf_pos(buf_pos);
581 ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
582 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
583 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
584 array_size - i, (array_size - i > 1) ? "s" : "");
585 return JSON_ERROR_FATAL;
587 else if (JSON_ERROR_FATAL == ret_val) {
591 return JSON_ERROR_FATAL;
596 dec_len += p_tok.get_next_token(&token, NULL, NULL);
597 if (JSON_TOKEN_ARRAY_END != token) {
598 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
602 return JSON_ERROR_FATAL;
609 template <typename T_value_type, typename T_template_type,
610 unsigned int array_size, int index_offset>
611 class TEMPLATE_ARRAY : public Restricted_Length_Template
617 T_template_type **value_elements;
620 unsigned int n_values;
621 TEMPLATE_ARRAY *list_value;
625 struct Pair_of_elements;
626 Pair_of_elements *permutation_intervals;
627 unsigned int number_of_permutations;
629 void clean_up_intervals();
630 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
632 void copy_template(const TEMPLATE_ARRAY& other_value);
633 void set_selection(template_sel new_selection);
634 void set_selection(const TEMPLATE_ARRAY& other_value);
635 void encode_text_permutation(Text_Buf& text_buf) const;
636 void decode_text_permutation(Text_Buf& text_buf);
641 number_of_permutations = 0;
642 permutation_intervals = NULL;
644 TEMPLATE_ARRAY(template_sel other_value)
645 : Restricted_Length_Template(other_value)
647 check_single_selection(other_value);
648 number_of_permutations = 0;
649 permutation_intervals = NULL;
651 TEMPLATE_ARRAY(null_type other_value);
652 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
655 number_of_permutations = 0;
656 permutation_intervals = NULL;
657 copy_value(other_value);
660 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
661 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
662 : Restricted_Length_Template()
664 number_of_permutations = 0;
665 permutation_intervals = NULL;
666 copy_template(other_value);
671 clean_up_intervals();
676 TEMPLATE_ARRAY& operator=(template_sel other_value);
677 TEMPLATE_ARRAY& operator=(null_type other_value);
678 TEMPLATE_ARRAY& operator=(const
679 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
680 TEMPLATE_ARRAY& operator=(const
681 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
682 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
684 T_template_type& operator[](int index_value);
685 T_template_type& operator[](const INTEGER& index_value);
686 const T_template_type& operator[](int index_value) const;
687 const T_template_type& operator[](const INTEGER& index_value) const;
689 void set_size(int new_size);
692 int size_of(boolean is_size) const;
693 inline int size_of() const { return size_of(TRUE); }
694 inline int lengthof() const { return size_of(FALSE); }
696 void add_permutation(unsigned int start_index, unsigned int end_index);
698 /** Removes all permutations set on this template, used when template variables
699 * are given new values. */
700 void remove_all_permutations() { clean_up_intervals(); }
702 unsigned int get_number_of_permutations() const;
703 unsigned int get_permutation_start(unsigned int index_value) const;
704 unsigned int get_permutation_end(unsigned int index_value) const;
705 unsigned int get_permutation_size(unsigned int index_value) const;
706 boolean permutation_starts_at(unsigned int index_value) const;
707 boolean permutation_ends_at(unsigned int index_value) const;
710 static boolean match_function_specific(
711 const Base_Type *value_ptr, int value_index,
712 const Restricted_Length_Template *template_ptr, int template_index,
715 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
716 other_value, boolean legacy = FALSE) const;
718 boolean is_value() const;
719 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
721 void set_type(template_sel template_type, unsigned int list_length);
722 TEMPLATE_ARRAY& list_item(unsigned int list_index);
725 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
726 match_value, boolean legacy = FALSE) const;
728 void set_param(Module_Param& param);
729 Module_Param* get_param(Module_Param_Name& param_name) const;
731 void encode_text(Text_Buf& text_buf) const;
732 void decode_text(Text_Buf& text_buf);
734 boolean is_present(boolean legacy = FALSE) const;
735 boolean match_omit(boolean legacy = FALSE) const;
737 #ifdef TITAN_RUNTIME_2
738 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
739 void set_value(template_sel other_value) { *this = other_value; }
740 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
741 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
742 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
743 boolean matchv(const Base_Type* other_value, boolean legacy) const { return match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)), legacy); }
744 void log_matchv(const Base_Type* match_value, boolean legacy) const { log_match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(match_value)), legacy); }
746 void check_restriction(template_res t_res, const char* t_name=NULL, boolean legacy = FALSE) const;
750 template <typename T_value_type, typename T_template_type,
751 unsigned int array_size, int index_offset>
752 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
754 unsigned int start_index, end_index; //beginning and ending index
757 template <typename T_value_type, typename T_template_type,
758 unsigned int array_size, int index_offset>
759 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
762 switch (template_selection)
765 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
766 delete single_value.value_elements[elem_count];
767 free_pointers((void**)single_value.value_elements);
770 case COMPLEMENTED_LIST:
771 delete [] value_list.list_value;
776 template_selection = UNINITIALIZED_TEMPLATE;
779 template <typename T_value_type, typename T_template_type,
780 unsigned int array_size, int index_offset>
781 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
784 number_of_permutations = 0;
785 Free(permutation_intervals);
786 permutation_intervals = NULL;
789 template <typename T_value_type, typename T_template_type,
790 unsigned int array_size, int index_offset>
791 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
792 set_selection(template_sel other_value)
794 Restricted_Length_Template::set_selection(other_value);
795 clean_up_intervals();
798 template <typename T_value_type, typename T_template_type,
799 unsigned int array_size, int index_offset>
800 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
801 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
803 Restricted_Length_Template::set_selection(other_value);
804 clean_up_intervals();
805 if(other_value.template_selection == SPECIFIC_VALUE)
807 number_of_permutations = other_value.number_of_permutations;
808 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
809 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
813 template <typename T_value_type, typename T_template_type,
814 unsigned int array_size, int index_offset>
815 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
816 encode_text_permutation(Text_Buf& text_buf) const
818 encode_text_restricted(text_buf);
819 text_buf.push_int(number_of_permutations);
821 for(unsigned int i = 0; i < number_of_permutations; i++)
823 text_buf.push_int(permutation_intervals[i].start_index);
824 text_buf.push_int(permutation_intervals[i].end_index);
828 template <typename T_value_type, typename T_template_type,
829 unsigned int array_size, int index_offset>
830 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
831 decode_text_permutation(Text_Buf& text_buf)
833 decode_text_restricted(text_buf);
835 number_of_permutations = text_buf.pull_int().get_val();
836 permutation_intervals = (Pair_of_elements *)Malloc
837 (number_of_permutations * sizeof(Pair_of_elements));
839 for (unsigned int i = 0; i < number_of_permutations; i++)
841 permutation_intervals[i].start_index =
842 text_buf.pull_int().get_val();
843 permutation_intervals[i].end_index =
844 text_buf.pull_int().get_val();
848 template <typename T_value_type, typename T_template_type,
849 unsigned int array_size, int index_offset>
850 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
851 add_permutation(unsigned int start_index, unsigned int end_index)
853 if(start_index > end_index)
854 TTCN_error("wrong permutation interval settings start (%d)"
855 "can not be greater than end (%d)",start_index, end_index);
857 if(number_of_permutations > 0 &&
858 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
859 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
861 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
862 permutation_intervals[number_of_permutations].start_index = start_index;
863 permutation_intervals[number_of_permutations].end_index = end_index;
864 number_of_permutations++;
867 template <typename T_value_type, typename T_template_type,
868 unsigned int array_size, int index_offset>
869 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
870 get_number_of_permutations(void) const
872 return number_of_permutations;
875 template <typename T_value_type, typename T_template_type,
876 unsigned int array_size, int index_offset>
877 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
878 get_permutation_start(unsigned int index_value) const
880 if(index_value >= number_of_permutations)
881 TTCN_error("Index overflow (%d)", index_value);
883 return permutation_intervals[index_value].start_index;
886 template <typename T_value_type, typename T_template_type,
887 unsigned int array_size, int index_offset>
888 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
889 get_permutation_end(unsigned int index_value) const
891 if(index_value >= number_of_permutations)
892 TTCN_error("Index overflow (%d)", index_value);
894 return permutation_intervals[index_value].end_index;
897 template <typename T_value_type, typename T_template_type,
898 unsigned int array_size, int index_offset>
899 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
900 get_permutation_size(unsigned int index_value) const
902 if(index_value >= number_of_permutations)
903 TTCN_error("Index overflow (%d)", index_value);
905 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
908 template <typename T_value_type, typename T_template_type,
909 unsigned int array_size, int index_offset>
910 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
911 permutation_starts_at(unsigned int index_value) const
913 for(unsigned int i = 0; i < number_of_permutations; i++)
915 if(permutation_intervals[i].start_index == index_value)
922 template <typename T_value_type, typename T_template_type,
923 unsigned int array_size, int index_offset>
924 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
925 permutation_ends_at(unsigned int index_value) const
927 for(unsigned int i = 0; i < number_of_permutations; i++)
929 if(permutation_intervals[i].end_index == index_value)
936 template <typename T_value_type, typename T_template_type,
937 unsigned int array_size, int index_offset>
938 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
939 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
942 single_value.n_elements = array_size;
943 single_value.value_elements =
944 (T_template_type**)allocate_pointers(array_size);
945 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
946 single_value.value_elements[elem_count] =
947 new T_template_type(other_value.array_element(elem_count));
948 set_selection(SPECIFIC_VALUE);
951 template <typename T_value_type, typename T_template_type,
952 unsigned int array_size, int index_offset>
953 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
954 copy_template(const TEMPLATE_ARRAY& other_value)
956 switch (other_value.template_selection)
959 single_value.n_elements = other_value.single_value.n_elements;
960 single_value.value_elements =
961 (T_template_type**)allocate_pointers(single_value.n_elements);
962 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
963 single_value.value_elements[elem_count] = new
964 T_template_type(*other_value.single_value.value_elements[elem_count]);
971 case COMPLEMENTED_LIST:
972 value_list.n_values = other_value.value_list.n_values;
973 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
974 for (unsigned int list_count = 0; list_count < value_list.n_values;
976 value_list.list_value[list_count].copy_template(
977 other_value.value_list.list_value[list_count]);
980 TTCN_error("Copying an uninitialized/unsupported array template.");
982 set_selection(other_value);
985 template <typename T_value_type, typename T_template_type,
986 unsigned int array_size, int index_offset>
987 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
988 TEMPLATE_ARRAY(null_type)
989 : Restricted_Length_Template(SPECIFIC_VALUE)
991 single_value.n_elements = 0;
992 single_value.value_elements = NULL;
993 number_of_permutations = 0;
994 permutation_intervals = NULL;
997 template <typename T_value_type, typename T_template_type,
998 unsigned int array_size, int index_offset>
999 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1000 TEMPLATE_ARRAY(const
1001 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1003 number_of_permutations = 0;
1004 permutation_intervals = NULL;
1005 switch (other_value.get_selection()) {
1006 case OPTIONAL_PRESENT:
1007 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1011 set_selection(OMIT_VALUE);
1014 TTCN_error("Creating an array template from an unbound optional field.");
1018 template <typename T_value_type, typename T_template_type,
1019 unsigned int array_size, int index_offset>
1020 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1021 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1022 operator=(template_sel other_value)
1024 check_single_selection(other_value);
1026 set_selection(other_value);
1030 template <typename T_value_type, typename T_template_type,
1031 unsigned int array_size, int index_offset>
1032 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1033 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1034 operator=(null_type)
1037 set_selection(SPECIFIC_VALUE);
1038 single_value.n_elements = 0;
1039 single_value.value_elements = NULL;
1043 template <typename T_value_type, typename T_template_type,
1044 unsigned int array_size, int index_offset>
1045 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1046 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
1047 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
1050 copy_value(other_value);
1054 template <typename T_value_type, typename T_template_type,
1055 unsigned int array_size, int index_offset>
1056 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1057 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1059 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1062 switch (other_value.get_selection()) {
1063 case OPTIONAL_PRESENT:
1064 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1068 set_selection(OMIT_VALUE);
1071 TTCN_error("Assignment of an unbound optional field to an array template.");
1076 template <typename T_value_type, typename T_template_type,
1077 unsigned int array_size, int index_offset>
1078 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1079 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1081 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1084 if (&other_value != this)
1087 copy_template(other_value);
1092 template <typename T_value_type, typename T_template_type,
1093 unsigned int array_size, int index_offset>
1095 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1098 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1100 "Accessing an element of an array template using invalid index: %d. "
1101 "Index range is [%d,%d].",
1102 index_value, index_offset, index_offset+(int)array_size);
1103 // transform index value according to given offset
1104 index_value -= index_offset;
1105 // the template of an array is not restricted to array_size, allow any length
1106 // in case of * or ? expand to full size to avoid uninitialized values
1107 switch (template_selection)
1109 case SPECIFIC_VALUE:
1110 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1114 set_size(array_size);
1117 set_size(index_value + 1);
1119 return *single_value.value_elements[index_value];
1122 template <typename T_value_type, typename T_template_type,
1123 unsigned int array_size, int index_offset>
1125 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1126 (const INTEGER& index_value)
1128 index_value.must_bound(
1129 "Using an unbound integer value for indexing an array template.");
1130 return (*this)[(int)index_value];
1133 template <typename T_value_type, typename T_template_type,
1134 unsigned int array_size, int index_offset>
1135 const T_template_type&
1136 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1137 (int index_value) const
1139 if (index_value < index_offset)
1141 "Accessing an element of an array template using invalid index: %d. "
1142 "Index range starts at %d.",
1143 index_value, index_offset);
1144 // transform index value according to given offset
1145 index_value -= index_offset;
1146 // const is specific template
1147 if (template_selection != SPECIFIC_VALUE)
1148 TTCN_error("Accessing an element of a non-specific array template.");
1149 if (index_value >= single_value.n_elements)
1150 TTCN_error("Index overflow in an array template: "
1151 "The index is %d (starting at %d),"
1152 " but the template has only %d elements.",
1153 index_value+index_offset, index_offset, single_value.n_elements);
1154 return *single_value.value_elements[index_value];
1157 template <typename T_value_type, typename T_template_type,
1158 unsigned int array_size, int index_offset>
1159 const T_template_type&
1160 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1161 (const INTEGER& index_value) const
1163 index_value.must_bound(
1164 "Using an unbound integer value for indexing an array template.");
1165 return (*this)[(int)index_value];
1168 template <typename T_value_type, typename T_template_type,
1169 unsigned int array_size, int index_offset>
1170 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1171 set_size(int new_size)
1173 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1174 "for an array template.");
1175 template_sel old_selection = template_selection;
1176 if (old_selection != SPECIFIC_VALUE)
1179 set_selection(SPECIFIC_VALUE);
1180 single_value.n_elements = 0;
1181 single_value.value_elements = NULL;
1183 if (new_size > single_value.n_elements)
1185 single_value.value_elements =
1186 (T_template_type**)reallocate_pointers(
1187 (void**)single_value.value_elements, single_value.n_elements, new_size);
1188 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1190 for (int elem_count = single_value.n_elements;
1191 elem_count < new_size; elem_count++)
1192 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1196 for (int elem_count = single_value.n_elements;
1197 elem_count < new_size; elem_count++)
1198 single_value.value_elements[elem_count] = new T_template_type;
1200 single_value.n_elements = new_size;
1202 else if (new_size < single_value.n_elements)
1204 for (int elem_count = new_size; elem_count < single_value.n_elements;
1206 delete single_value.value_elements[elem_count];
1207 single_value.value_elements =
1208 (T_template_type**)reallocate_pointers(
1209 (void**)single_value.value_elements, single_value.n_elements, new_size);
1210 single_value.n_elements = new_size;
1214 template <typename T_value_type, typename T_template_type,
1215 unsigned int array_size, int index_offset>
1216 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1219 switch (template_selection) {
1220 case SPECIFIC_VALUE:
1221 return single_value.n_elements;
1223 return value_list.n_values;
1225 TTCN_error("Performing n_elem");
1229 template <typename T_value_type, typename T_template_type,
1230 unsigned int array_size, int index_offset>
1231 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1232 size_of(boolean is_size) const
1234 const char* op_name = is_size ? "size" : "length";
1236 boolean has_any_or_none;
1238 TTCN_error("Performing %sof() operation on an array template "
1239 "which has an ifpresent attribute.", op_name);
1240 switch (template_selection)
1242 case SPECIFIC_VALUE: {
1244 has_any_or_none = FALSE;
1245 int elem_count = single_value.n_elements;
1246 if (!is_size) { // lengthof()
1247 while (elem_count>0 &&
1248 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1250 for (int i=0; i<elem_count; i++)
1252 switch (single_value.value_elements[i]->get_selection())
1255 TTCN_error("Performing %sof() operation on an array template "
1256 "containing omit element.", op_name);
1258 has_any_or_none = TRUE;
1267 TTCN_error("Performing %sof() operation on an array template "
1268 "containing omit value.", op_name);
1272 has_any_or_none = TRUE; // max. size is infinity
1275 // error if any element does not have size or the sizes differ
1276 if (value_list.n_values<1)
1277 TTCN_error("Performing %sof() operation on an array template "
1278 "containing an empty list.", op_name);
1279 int item_size = value_list.list_value[0].size_of(is_size);
1280 for (unsigned int i = 1; i < value_list.n_values; i++) {
1281 if (value_list.list_value[i].size_of(is_size)!=item_size)
1282 TTCN_error("Performing %sof() operation on an array template "
1283 "containing a value list with different sizes.", op_name);
1285 min_size = item_size;
1286 has_any_or_none = FALSE;
1288 case COMPLEMENTED_LIST:
1289 TTCN_error("Performing %sof() operation on an array template "
1290 "containing complemented list.", op_name);
1292 TTCN_error("Performing %sof() operation on an "
1293 "uninitialized/unsupported array template.", op_name);
1295 return check_section_is_single(min_size, has_any_or_none,
1296 op_name, "an", "array template");
1299 template <typename T_value_type, typename T_template_type,
1300 unsigned int array_size, int index_offset>
1301 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1302 match_function_specific(const Base_Type *value_ptr, int value_index,
1303 const Restricted_Length_Template *template_ptr,
1304 int template_index, boolean legacy)
1306 if (value_index >= 0)
1307 return ((const TEMPLATE_ARRAY*)template_ptr)->
1308 single_value.value_elements[template_index]->
1310 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1311 ->array_element(value_index), legacy);
1313 return ((const TEMPLATE_ARRAY*)template_ptr)->
1314 single_value.value_elements[template_index]->is_any_or_omit();
1317 template <typename T_value_type, typename T_template_type,
1318 unsigned int array_size, int index_offset>
1319 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1320 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1321 other_value, boolean legacy) const
1323 if (!match_length(array_size)) return FALSE;
1324 switch (template_selection)
1326 case SPECIFIC_VALUE:
1327 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1328 match_function_specific, legacy);
1335 case COMPLEMENTED_LIST:
1336 for (unsigned int list_count = 0; list_count < value_list.n_values;
1338 if (value_list.list_value[list_count].match(other_value, legacy))
1339 return template_selection == VALUE_LIST;
1340 return template_selection == COMPLEMENTED_LIST;
1342 TTCN_error("Matching with an uninitialized/unsupported array template.");
1347 template <typename T_value_type, typename T_template_type,
1348 unsigned int array_size, int index_offset>
1349 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1352 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1353 for (int i=0; i<single_value.n_elements; i++)
1354 if (!single_value.value_elements[i]->is_value()) return FALSE;
1358 template <typename T_value_type, typename T_template_type,
1359 unsigned int array_size, int index_offset>
1360 VALUE_ARRAY<T_value_type, array_size, index_offset>
1361 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1364 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1365 TTCN_error("Performing a valueof or send operation on a "
1366 "non-specific array template.");
1367 // the size of the template must be the size of the value
1368 if (single_value.n_elements!=array_size)
1369 TTCN_error("Performing a valueof or send operation on a "
1370 "specific array template with invalid size.");
1371 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1372 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1373 ret_val.array_element(elem_count) =
1374 single_value.value_elements[elem_count]->valueof();
1378 template <typename T_value_type, typename T_template_type,
1379 unsigned int array_size, int index_offset>
1380 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1381 set_type(template_sel template_type, unsigned int list_length)
1384 switch (template_type) {
1386 case COMPLEMENTED_LIST:
1387 value_list.n_values = list_length;
1388 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1392 "Internal error: Setting an invalid type for an array template.");
1394 set_selection(template_type);
1397 template <typename T_value_type, typename T_template_type,
1398 unsigned int array_size, int index_offset>
1399 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1400 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1401 list_item(unsigned int list_index)
1403 if (template_selection != VALUE_LIST &&
1404 template_selection != COMPLEMENTED_LIST)
1405 TTCN_error("Internal error: Accessing a list element of a non-list "
1407 if (list_index >= value_list.n_values)
1408 TTCN_error("Internal error: Index overflow in a value list "
1410 return value_list.list_value[list_index];
1413 template <typename T_value_type, typename T_template_type,
1414 unsigned int array_size, int index_offset>
1415 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1418 switch (template_selection)
1420 case SPECIFIC_VALUE:
1421 if (single_value.n_elements > 0)
1423 TTCN_Logger::log_event_str("{ ");
1424 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1426 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1427 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1428 single_value.value_elements[elem_count]->log();
1429 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1431 TTCN_Logger::log_event_str(" }");
1434 TTCN_Logger::log_event_str("{ }");
1436 case COMPLEMENTED_LIST:
1437 TTCN_Logger::log_event_str("complement");
1439 TTCN_Logger::log_char('(');
1440 for (unsigned int list_count = 0; list_count < value_list.n_values;
1443 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1444 value_list.list_value[list_count].log();
1446 TTCN_Logger::log_char(')');
1456 template <typename T_value_type, typename T_template_type,
1457 unsigned int array_size, int index_offset>
1458 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1459 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1460 match_value, boolean legacy) const
1462 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1463 if(match(match_value, legacy)){
1464 TTCN_Logger::print_logmatch_buffer();
1465 TTCN_Logger::log_event_str(" matched");
1467 if (template_selection == SPECIFIC_VALUE &&
1468 single_value.n_elements == array_size) {
1469 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1470 for (unsigned int elem_count = 0; elem_count < array_size;
1472 if(!single_value.value_elements[elem_count]->
1473 match(match_value.array_element(elem_count), legacy)){
1474 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1475 single_value.value_elements[elem_count]->
1476 log_match(match_value.array_element(elem_count), legacy);
1477 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1480 log_match_length(array_size);
1482 TTCN_Logger::print_logmatch_buffer();
1484 TTCN_Logger::log_event_str(" with ");
1486 TTCN_Logger::log_event_str(" unmatched");
1491 if (template_selection == SPECIFIC_VALUE &&
1492 single_value.n_elements == array_size) {
1493 TTCN_Logger::log_event_str("{ ");
1494 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1495 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1496 single_value.value_elements[elem_count]->log_match(
1497 match_value.array_element(elem_count), legacy);
1499 TTCN_Logger::log_event_str(" }");
1500 log_match_length(array_size);
1503 TTCN_Logger::log_event_str(" with ");
1505 if (match(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1506 else TTCN_Logger::log_event_str(" unmatched");
1510 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1511 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1513 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1514 param.get_id()->next_name()) {
1515 // Haven't reached the end of the module parameter name
1516 // => the name refers to one of the elements, not to the whole array
1517 char* param_field = param.get_id()->get_current_name();
1518 if (param_field[0] < '0' || param_field[0] > '9') {
1519 param.error("Unexpected record field name in module parameter, expected a valid"
1520 " array template index");
1522 unsigned int param_index = -1;
1523 sscanf(param_field, "%u", ¶m_index);
1524 if (param_index >= array_size) {
1525 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1527 (*this)[param_index].set_param(param);
1531 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1533 Module_Param_Ptr mp = ¶m;
1534 if (param.get_type() == Module_Param::MP_Reference) {
1535 mp = param.get_referenced_param();
1538 switch (mp->get_type()) {
1539 case Module_Param::MP_Omit:
1542 case Module_Param::MP_Any:
1545 case Module_Param::MP_AnyOrNone:
1546 *this = ANY_OR_OMIT;
1548 case Module_Param::MP_List_Template:
1549 case Module_Param::MP_ComplementList_Template: {
1550 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset> temp;
1551 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1552 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1553 for (size_t i=0; i<mp->get_size(); i++) {
1554 temp.list_item(i).set_param(*mp->get_elem(i));
1558 case Module_Param::MP_Value_List:
1559 set_size(mp->get_size());
1560 for (size_t i=0; i<mp->get_size(); ++i) {
1561 Module_Param* const curr = mp->get_elem(i);
1562 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1563 (*this)[(int)i+index_offset].set_param(*curr);
1567 case Module_Param::MP_Indexed_List:
1568 for (size_t i=0; i<mp->get_size(); ++i) {
1569 Module_Param* const curr = mp->get_elem(i);
1570 (*this)[curr->get_id()->get_index()].set_param(*curr);
1574 param.type_error("array template");
1576 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1579 template <typename T_value_type, typename T_template_type,
1580 unsigned int array_size, int index_offset>
1581 Module_Param* TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1582 get_param(Module_Param_Name& param_name) const
1584 if (param_name.next_name()) {
1585 // Haven't reached the end of the module parameter name
1586 // => the name refers to one of the elements, not to the whole record of
1587 char* param_field = param_name.get_current_name();
1588 if (param_field[0] < '0' || param_field[0] > '9') {
1589 TTCN_error("Unexpected record field name in module parameter reference, "
1590 "expected a valid array index");
1592 unsigned int param_index = -1;
1593 sscanf(param_field, "%u", ¶m_index);
1594 if (param_index >= array_size) {
1595 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1597 return single_value.value_elements[param_index]->get_param(param_name);
1599 Module_Param* mp = NULL;
1600 switch (template_selection) {
1601 case UNINITIALIZED_TEMPLATE:
1602 mp = new Module_Param_Unbound();
1605 mp = new Module_Param_Omit();
1608 mp = new Module_Param_Any();
1611 mp = new Module_Param_AnyOrNone();
1613 case SPECIFIC_VALUE: {
1614 Vector<Module_Param*> values;
1615 for (unsigned int i = 0; i < array_size; ++i) {
1616 values.push_back(single_value.value_elements[i]->get_param(param_name));
1618 mp = new Module_Param_Value_List();
1619 mp->add_list_with_implicit_ids(&values);
1623 case COMPLEMENTED_LIST: {
1624 if (template_selection == VALUE_LIST) {
1625 mp = new Module_Param_List_Template();
1628 mp = new Module_Param_ComplementList_Template();
1630 for (size_t i = 0; i < value_list.n_values; ++i) {
1631 mp->add_elem(value_list.list_value[i].get_param(param_name));
1638 mp->set_ifpresent();
1643 template <typename T_value_type, typename T_template_type,
1644 unsigned int array_size, int index_offset>
1645 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1646 encode_text(Text_Buf& text_buf) const
1648 encode_text_restricted(text_buf);
1649 switch (template_selection)
1651 case SPECIFIC_VALUE:
1652 text_buf.push_int(single_value.n_elements);
1653 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1654 single_value.value_elements[elem_count]->encode_text(text_buf);
1661 case COMPLEMENTED_LIST:
1662 text_buf.push_int(value_list.n_values);
1663 for (unsigned int list_count = 0; list_count < value_list.n_values;
1665 value_list.list_value[list_count].encode_text(text_buf);
1668 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1673 template <typename T_value_type, typename T_template_type,
1674 unsigned int array_size, int index_offset>
1675 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1676 decode_text(Text_Buf& text_buf)
1679 decode_text_restricted(text_buf);
1680 switch (template_selection)
1682 case SPECIFIC_VALUE:
1683 single_value.n_elements = text_buf.pull_int().get_val();
1684 if (single_value.n_elements < 0)
1685 TTCN_error("Text decoder: Negative size was received for an "
1687 single_value.value_elements =
1688 (T_template_type**)allocate_pointers(single_value.n_elements);
1689 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1691 single_value.value_elements[elem_count] = new T_template_type;
1692 single_value.value_elements[elem_count]->decode_text(text_buf);
1700 case COMPLEMENTED_LIST:
1701 value_list.n_values = text_buf.pull_int().get_val();
1702 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1703 for (unsigned int list_count = 0; list_count < value_list.n_values;
1705 value_list.list_value[list_count].decode_text(text_buf);
1708 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1709 "for an array template.");
1713 template <typename T_value_type, typename T_template_type,
1714 unsigned int array_size, int index_offset>
1715 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1716 is_present(boolean legacy /* = FALSE */) const
1718 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1719 return !match_omit(legacy);
1722 template <typename T_value_type, typename T_template_type,
1723 unsigned int array_size, int index_offset>
1724 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1725 match_omit(boolean legacy /* = FALSE */) const
1727 if (is_ifpresent) return TRUE;
1728 switch (template_selection) {
1733 case COMPLEMENTED_LIST:
1735 // legacy behavior: 'omit' can appear in the value/complement list
1736 for (unsigned int i=0; i<value_list.n_values; i++)
1737 if (value_list.list_value[i].match_omit())
1738 return template_selection==VALUE_LIST;
1739 return template_selection==COMPLEMENTED_LIST;
1741 // else fall through
1748 #ifndef TITAN_RUNTIME_2
1749 template <typename T_value_type, typename T_template_type,
1750 unsigned int array_size, int index_offset>
1751 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1752 check_restriction(template_res t_res, const char* t_name, boolean legacy /* = FALSE */) const
1754 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1755 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1757 if (template_selection==OMIT_VALUE) return;
1759 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1760 for (int i=0; i<single_value.n_elements; i++)
1761 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1764 if (!match_omit(legacy)) return;
1769 TTCN_error("Restriction `%s' on template of type %s violated.",
1770 get_res_name(t_res), t_name ? t_name : "array");
1774 template <typename T_value_type, typename T_template_type,
1775 unsigned int array_size, int index_offset>
1776 answer recursive_permutation_match(const Base_Type *value_ptr,
1777 unsigned int value_start_index,
1778 unsigned int value_size,
1779 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1780 unsigned int template_start_index,
1781 unsigned int template_size,
1782 unsigned int permutation_index,
1783 match_function_t match_function,
1784 unsigned int& shift_size,
1787 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1788 if (permutation_index > nof_permutations)
1789 TTCN_error("Internal error: recursive_permutation_match: "
1790 "invalid argument.");
1792 if (permutation_index < nof_permutations &&
1793 template_ptr->get_permutation_end(permutation_index) >
1794 template_start_index + template_size)
1795 TTCN_error("Internal error: recursive_permutation_match: wrong "
1796 "permutation interval settings for permutation %d.",
1802 if(template_size == 0)
1804 //reached the end of templates
1805 // if we reached the end of values => good
1813 //are we at an asterisk or at the beginning of a permutation interval
1814 boolean is_asterisk;
1815 boolean permutation_begins = permutation_index < nof_permutations &&
1816 template_start_index ==
1817 template_ptr->get_permutation_start(permutation_index);
1819 if (permutation_begins ||
1820 match_function(value_ptr, -1, template_ptr, template_start_index, legacy))
1822 unsigned int smallest_possible_size;
1823 unsigned int largest_possible_size;
1824 boolean has_asterisk;
1825 boolean already_superset;
1826 unsigned int permutation_size;
1828 //check how many values might be associated with this permutation
1829 //if we are at a permutation start
1830 if (permutation_begins)
1832 is_asterisk = FALSE;
1834 template_ptr->get_permutation_size(permutation_index);
1835 smallest_possible_size = 0;
1836 has_asterisk = FALSE;
1838 //count how many non asterisk elements are in the permutation
1839 for(unsigned int i = 0; i < permutation_size; i++)
1841 if(match_function(value_ptr, -1, template_ptr,
1842 i + template_start_index, legacy))
1844 has_asterisk = TRUE;
1846 smallest_possible_size++;
1850 //the real permutation size is bigger then the value size
1851 if(smallest_possible_size > value_size)
1854 //if the permutation has an asterisk then it can grow
1857 largest_possible_size = value_size;
1859 //if there are only asterisks in the permutation
1860 if(smallest_possible_size == 0)
1861 already_superset = TRUE;
1863 already_superset = FALSE;
1865 //without asterisks its size is fixed
1866 largest_possible_size = smallest_possible_size;
1867 already_superset = FALSE;
1872 already_superset = TRUE;
1873 permutation_size = 1;
1874 smallest_possible_size = 0;
1875 largest_possible_size = value_size;
1876 has_asterisk = TRUE;
1879 unsigned int temp_size = smallest_possible_size;
1882 //this is to make match_set_of incremental,
1883 // we store the already found pairs in this vector
1884 // so we wouldn't try to find a pair for those templates again
1885 // and we can set the covered state of values too
1886 // to not waste memory it is only created if needed
1887 int* pair_list = NULL;
1888 unsigned int old_temp_size = 0;
1890 if(!already_superset)
1892 pair_list = new int[permutation_size];
1893 for(unsigned int i = 0 ; i < permutation_size; i++)
1895 //in the beginning we haven't found a template to any values
1900 while(!already_superset)
1902 //must be a permutation having other values than asterisks
1906 //our set matching is extended with 2 more parameters
1907 // giving back how many templates
1908 // (other than asterisk) couldn't be matched
1909 // and setting / giving back the value-template pairs
1911 boolean found = match_set_of_internal(value_ptr, value_start_index,
1912 temp_size, template_ptr,
1913 template_start_index, permutation_size,
1914 match_function, SUPERSET, &x, pair_list, old_temp_size, legacy);
1918 already_superset = TRUE;
1920 //as we didn't found a match we have to try
1921 // a larger set of values
1922 //x is the number of templates we couldn't find
1923 // a matching pair for
1924 // the next must be at least this big to fully cover
1925 // on the other side if it would be bigger than it might miss
1926 // the smallest possible match.
1928 //if we can match with more values
1929 if(has_asterisk && temp_size + x <= largest_possible_size)
1931 old_temp_size = temp_size;
1935 return FAILURE; //else we failed
1943 //we reach here only if we found a match
1945 //can only go on recursively if we haven't reached the end
1947 //reached the end of templates
1948 if(permutation_size == template_size)
1950 if(has_asterisk || value_size == temp_size)
1956 for(unsigned int i = temp_size; i <= largest_possible_size;)
1962 //don't step the permutation index
1963 result = recursive_permutation_match(value_ptr,value_start_index+i,
1964 value_size - i, template_ptr,
1965 template_start_index +
1970 match_function, shift_size, legacy);
1972 //try with the next permutation
1973 result = recursive_permutation_match(value_ptr,value_start_index+i,
1974 value_size - i, template_ptr,
1975 template_start_index +
1977 template_size - permutation_size,
1978 permutation_index + 1,
1979 match_function, shift_size, legacy);
1982 if(result == SUCCESS)
1983 return SUCCESS; //we finished
1984 else if(result == NO_CHANCE)
1985 return NO_CHANCE; //matching is not possible
1986 else if(i == value_size) //we failed
1988 //if there is no chance of matching
1991 i += shift_size > 1 ? shift_size : 1;
1993 if(i > largest_possible_size)
1994 shift_size = i - largest_possible_size;
2000 //this level failed;
2003 //we are at the beginning of a non permutation, non asterisk interval
2005 //the distance to the next permutation or the end of templates
2006 // so the longest possible match
2007 unsigned int distance;
2009 if (permutation_index < nof_permutations)
2011 distance = template_ptr->get_permutation_start(permutation_index)
2012 - template_start_index;
2014 distance = template_size;
2017 //if there are no more values, but we still have templates
2018 // and the template is not an asterisk or a permutation start
2022 //we try to match as many values as possible
2023 //an asterisk is handled like a 0 length permutation
2027 good = match_function(value_ptr, value_start_index + i,
2028 template_ptr, template_start_index + i, legacy);
2030 //bad stop: something can't be matched
2031 //half bad half good stop: the end of values is reached
2032 //good stop: matching on the full distance or till an asterisk
2033 }while(good && i < value_size && i < distance &&
2034 !match_function(value_ptr, -1, template_ptr,
2035 template_start_index + i, legacy));
2037 //if we matched on the full distance or till an asterisk
2038 if(good && (i == distance ||
2039 match_function(value_ptr, -1, template_ptr,
2040 template_start_index + i, legacy)))
2042 //reached the end of the templates
2043 if(i == template_size)
2047 //the next level would return FAILURE so we don't step it
2050 //i == value_size, so we matched everything
2054 //we reached the next asterisk or permutation,
2055 // so step to the next level
2056 return recursive_permutation_match(value_ptr,value_start_index + i,
2059 template_start_index + i,
2062 match_function, shift_size, legacy);
2065 //something bad happened, so we have to check how bad the situation is
2066 if( i == value_size)
2068 //the aren't values left, meaning that the match is not possible
2071 //we couldn't match, but there is still a chance of matching
2073 //try to find a matching value for the last checked (and failed)
2075 // smaller jumps would fail so we skip them
2079 good = match_function(value_ptr,
2080 value_start_index + i + shift_size,
2081 template_ptr, template_start_index + i, legacy);
2083 }while(!good && i + shift_size < value_size);
2090 // the template can not be matched later
2098 template <typename T_value_type, typename T_template_type,
2099 unsigned int array_size, int index_offset>
2100 boolean match_permutation_array(const Base_Type *value_ptr,
2102 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
2104 match_function_t match_function,
2107 if (value_ptr == NULL || value_size < 0 ||
2108 template_ptr == NULL || template_size < 0 ||
2109 template_ptr->get_selection() != SPECIFIC_VALUE)
2110 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
2112 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
2113 // use the simplified algorithm if the template does not contain permutation
2114 if (nof_permutations == 0)
2115 return match_array(value_ptr, value_size,
2116 template_ptr, template_size, match_function, legacy);
2117 // use 'set of' matching if all template elements are grouped into one
2119 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
2120 template_ptr->get_permutation_end(0) ==
2121 (unsigned int)(template_size - 1))
2122 return match_set_of(value_ptr, value_size, template_ptr, template_size,
2123 match_function, legacy);
2125 unsigned int shift_size = 0;
2126 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
2127 0, template_size, 0, match_function, shift_size, legacy) == SUCCESS;