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, because with clang the text2ttcn test
190 VALUE_ARRAY() : array_elements(){};
191 boolean operator==(const VALUE_ARRAY& other_value) const;
192 inline boolean operator!=(const VALUE_ARRAY& other_value) const
193 { return !(*this == other_value); }
195 T_type& operator[](int index_value) { return array_elements[
196 get_array_index(index_value, array_size, index_offset)]; }
197 T_type& operator[](const INTEGER& index_value) { return array_elements[
198 get_array_index(index_value, array_size, index_offset)]; }
199 const T_type& operator[](int index_value) const { return array_elements[
200 get_array_index(index_value, array_size, index_offset)]; }
201 const T_type& operator[](const INTEGER& index_value) const {
202 return array_elements[
203 get_array_index(index_value, array_size, index_offset)];
207 VALUE_ARRAY operator<<=(int rotate_count) const;
208 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
209 VALUE_ARRAY operator>>=(int rotate_count) const;
210 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
212 T_type& array_element(unsigned int index_value)
213 { return array_elements[index_value]; }
214 const T_type& array_element(unsigned int index_value) const
215 { return array_elements[index_value]; }
217 void set_implicit_omit();
219 boolean is_bound() const;
220 boolean is_value() const;
224 inline int n_elem() const { return array_size; }
225 inline int size_of() const { return array_size; }
226 int lengthof() const;
228 void set_param(Module_Param& param);
229 Module_Param* get_param(Module_Param_Name& param_name) const;
231 #ifdef TITAN_RUNTIME_2
232 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
233 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
234 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
235 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
237 inline boolean is_present() const { return is_bound(); }
240 void encode_text(Text_Buf& text_buf) const;
241 void decode_text(Text_Buf& text_buf);
243 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
244 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
246 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
247 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
249 virtual ~VALUE_ARRAY() { } // just to avoid warnings
251 /** Encodes accordingly to the JSON encoding rules.
252 * Returns the length of the encoded data. */
253 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
255 /** Decodes accordingly to the JSON encoding rules.
256 * Returns the length of the decoded data. */
257 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
260 template <typename T_type, unsigned int array_size, int index_offset>
261 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
262 (const VALUE_ARRAY& other_value) const
264 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
265 if (array_elements[elem_count] != other_value.array_elements[elem_count])
270 template <typename T_type, unsigned int array_size, int index_offset>
271 VALUE_ARRAY<T_type,array_size,index_offset>
272 VALUE_ARRAY<T_type,array_size,index_offset>::
273 operator<<=(int rotate_count) const {
274 return *this >>= (-rotate_count);
277 template <typename T_type, unsigned int array_size, int index_offset>
278 VALUE_ARRAY<T_type,array_size,index_offset>
279 VALUE_ARRAY<T_type,array_size,index_offset>::
280 operator<<=(const INTEGER& rotate_count) const {
281 rotate_count.must_bound("Unbound integer operand of rotate left "
283 return *this >>= (int)(-rotate_count);
286 template <typename T_type, unsigned int array_size, int index_offset>
287 VALUE_ARRAY<T_type,array_size,index_offset>
288 VALUE_ARRAY<T_type,array_size,index_offset>::
289 operator>>=(int rotate_count) const {
291 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
292 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
293 if (rc == 0) return *this;
294 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
295 for (unsigned int i=0; i<array_size; i++) {
296 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
301 template <typename T_type, unsigned int array_size, int index_offset>
302 VALUE_ARRAY<T_type,array_size,index_offset>
303 VALUE_ARRAY<T_type,array_size,index_offset>::
304 operator>>=(const INTEGER& rotate_count) const {
305 rotate_count.must_bound("Unbound integer operand of rotate right "
307 return *this >>= (int)rotate_count;
310 template <typename T_type, unsigned int array_size, int index_offset>
311 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
313 for (unsigned int i = 0; i < array_size; ++i) {
314 if (array_elements[i].is_bound())
315 array_elements[i].set_implicit_omit();
319 template <typename T_type, unsigned int array_size, int index_offset>
320 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
322 for (unsigned int i = 0; i < array_size; ++i) {
323 if (!array_elements[i].is_bound()) {
330 template <typename T_type, unsigned int array_size, int index_offset>
331 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
333 for (unsigned int i = 0; i < array_size; ++i) {
334 if (!array_elements[i].is_value()) {
341 template <typename T_type, unsigned int array_size, int index_offset>
342 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
344 for (unsigned int i = 0; i < array_size; ++i) {
345 array_elements[i].clean_up();
349 template <typename T_type, unsigned int array_size, int index_offset>
350 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
352 TTCN_Logger::log_event_str("{ ");
353 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
355 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
356 array_elements[elem_count].log();
358 TTCN_Logger::log_event_str(" }");
361 template <typename T_type, unsigned int array_size, int index_offset>
362 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
365 for (unsigned int my_length=array_size; my_length>0; my_length--)
367 if (array_elements[my_length-1].is_bound()) return my_length;
372 template <typename T_type, unsigned int array_size, int index_offset>
373 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
376 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
377 param.get_id()->next_name()) {
378 // Haven't reached the end of the module parameter name
379 // => the name refers to one of the elements, not to the whole array
380 char* param_field = param.get_id()->get_current_name();
381 if (param_field[0] < '0' || param_field[0] > '9') {
382 param.error("Unexpected record field name in module parameter, expected a valid"
385 unsigned int param_index = -1;
386 sscanf(param_field, "%u", ¶m_index);
387 if (param_index >= array_size) {
388 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
390 array_elements[param_index].set_param(param);
394 param.basic_check(Module_Param::BC_VALUE, "array value");
395 Module_Param_Ptr mp = ¶m;
396 if (param.get_type() == Module_Param::MP_Reference) {
397 mp = param.get_referenced_param();
399 switch (mp->get_type()) {
400 case Module_Param::MP_Value_List:
401 if (mp->get_size()!=array_size) {
402 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);
404 for (size_t i=0; i<mp->get_size(); ++i) {
405 Module_Param* const curr = mp->get_elem(i);
406 if (curr->get_type()!=Module_Param::MP_NotUsed) {
407 array_elements[i].set_param(*curr);
411 case Module_Param::MP_Indexed_List:
412 for (size_t i=0; i<mp->get_size(); ++i) {
413 Module_Param* const curr = mp->get_elem(i);
414 array_elements[curr->get_id()->get_index()].set_param(*curr);
418 param.type_error("array value");
422 template <typename T_type, unsigned int array_size, int index_offset>
423 Module_Param* VALUE_ARRAY<T_type,array_size,index_offset>::get_param
424 (Module_Param_Name& param_name) const
427 return new Module_Param_Unbound();
429 if (param_name.next_name()) {
430 // Haven't reached the end of the module parameter name
431 // => the name refers to one of the elements, not to the whole array
432 char* param_field = param_name.get_current_name();
433 if (param_field[0] < '0' || param_field[0] > '9') {
434 TTCN_error("Unexpected record field name in module parameter reference, "
435 "expected a valid array index");
437 unsigned int param_index = -1;
438 sscanf(param_field, "%u", ¶m_index);
439 if (param_index >= array_size) {
440 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
442 return array_elements[param_index].get_param(param_name);
444 Vector<Module_Param*> values;
445 for (unsigned int i = 0; i < array_size; ++i) {
446 values.push_back(array_elements[i].get_param(param_name));
448 Module_Param_Value_List* mp = new Module_Param_Value_List();
449 mp->add_list_with_implicit_ids(&values);
454 template <typename T_type, unsigned int array_size, int index_offset>
455 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
456 (Text_Buf& text_buf) const
458 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
459 array_elements[elem_count].encode_text(text_buf);
462 template <typename T_type, unsigned int array_size, int index_offset>
463 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
466 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
467 array_elements[elem_count].decode_text(text_buf);
470 template <typename T_type, unsigned int array_size, int index_offset>
471 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
472 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
475 va_start(pvar, p_coding);
477 case TTCN_EncDec::CT_JSON: {
478 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
479 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
480 ("No JSON descriptor available for type '%s'.", p_td.name);
481 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
482 JSON_encode(p_td, tok);
483 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
486 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
491 template <typename T_type, unsigned int array_size, int index_offset>
492 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
493 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
496 case TTCN_EncDec::CT_JSON: {
497 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
498 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
499 ("No JSON descriptor available for type '%s'.", p_td.name);
500 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
501 if(JSON_decode(p_td, tok, false)<0)
502 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
503 "because invalid or incomplete message was received", p_td.name);
504 p_buf.set_pos(tok.get_buf_pos());
507 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
511 template <typename T_type, unsigned int array_size, int index_offset>
512 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
513 const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
515 if (!is_bound() && (NULL == p_td.json || !p_td.json->metainfo_unbound)) {
516 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
517 "Encoding an unbound array value.");
521 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
523 for (unsigned int i = 0; i < array_size; ++i) {
524 if (NULL != p_td.json && p_td.json->metainfo_unbound && !array_elements[i].is_bound()) {
525 // unbound elements are encoded as { "metainfo []" : "unbound" }
526 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
527 enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
528 enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
529 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
532 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
533 if (0 > ret_val) break;
538 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
542 template <typename T_type, unsigned int array_size, int index_offset>
543 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
544 const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
546 json_token_t token = JSON_TOKEN_NONE;
547 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
548 if (JSON_TOKEN_ERROR == token) {
549 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
550 return JSON_ERROR_FATAL;
552 else if (JSON_TOKEN_ARRAY_START != token) {
553 return JSON_ERROR_INVALID_TOKEN;
556 for (unsigned int i = 0; i < array_size; ++i) {
557 size_t buf_pos = p_tok.get_buf_pos();
559 if (NULL != p_td.json && p_td.json->metainfo_unbound) {
560 // check for metainfo object
561 ret_val = p_tok.get_next_token(&token, NULL, NULL);
562 if (JSON_TOKEN_OBJECT_START == token) {
564 size_t value_len = 0;
565 ret_val += p_tok.get_next_token(&token, &value, &value_len);
566 if (JSON_TOKEN_NAME == token && 11 == value_len &&
567 0 == strncmp(value, "metainfo []", 11)) {
568 ret_val += p_tok.get_next_token(&token, &value, &value_len);
569 if (JSON_TOKEN_STRING == token && 9 == value_len &&
570 0 == strncmp(value, "\"unbound\"", 9)) {
571 ret_val = p_tok.get_next_token(&token, NULL, NULL);
572 if (JSON_TOKEN_OBJECT_END == token) {
579 // metainfo object not found, jump back and let the element type decode it
580 p_tok.set_buf_pos(buf_pos);
582 ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
583 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
584 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
585 array_size - i, (array_size - i > 1) ? "s" : "");
586 return JSON_ERROR_FATAL;
588 else if (JSON_ERROR_FATAL == ret_val) {
592 return JSON_ERROR_FATAL;
597 dec_len += p_tok.get_next_token(&token, NULL, NULL);
598 if (JSON_TOKEN_ARRAY_END != token) {
599 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
603 return JSON_ERROR_FATAL;
610 template <typename T_value_type, typename T_template_type,
611 unsigned int array_size, int index_offset>
612 class TEMPLATE_ARRAY : public Restricted_Length_Template
618 T_template_type **value_elements;
621 unsigned int n_values;
622 TEMPLATE_ARRAY *list_value;
626 struct Pair_of_elements;
627 Pair_of_elements *permutation_intervals;
628 unsigned int number_of_permutations;
630 void clean_up_intervals();
631 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
633 void copy_template(const TEMPLATE_ARRAY& other_value);
634 void set_selection(template_sel new_selection);
635 void set_selection(const TEMPLATE_ARRAY& other_value);
636 void encode_text_permutation(Text_Buf& text_buf) const;
637 void decode_text_permutation(Text_Buf& text_buf);
642 number_of_permutations = 0;
643 permutation_intervals = NULL;
645 TEMPLATE_ARRAY(template_sel other_value)
646 : Restricted_Length_Template(other_value)
648 check_single_selection(other_value);
649 number_of_permutations = 0;
650 permutation_intervals = NULL;
652 TEMPLATE_ARRAY(null_type other_value);
653 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
656 number_of_permutations = 0;
657 permutation_intervals = NULL;
658 copy_value(other_value);
661 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
662 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
663 : Restricted_Length_Template()
665 number_of_permutations = 0;
666 permutation_intervals = NULL;
667 copy_template(other_value);
672 clean_up_intervals();
677 TEMPLATE_ARRAY& operator=(template_sel other_value);
678 TEMPLATE_ARRAY& operator=(null_type other_value);
679 TEMPLATE_ARRAY& operator=(const
680 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
681 TEMPLATE_ARRAY& operator=(const
682 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
683 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
685 T_template_type& operator[](int index_value);
686 T_template_type& operator[](const INTEGER& index_value);
687 const T_template_type& operator[](int index_value) const;
688 const T_template_type& operator[](const INTEGER& index_value) const;
690 void set_size(int new_size);
693 int size_of(boolean is_size) const;
694 inline int size_of() const { return size_of(TRUE); }
695 inline int lengthof() const { return size_of(FALSE); }
697 void add_permutation(unsigned int start_index, unsigned int end_index);
699 /** Removes all permutations set on this template, used when template variables
700 * are given new values. */
701 void remove_all_permutations() { clean_up_intervals(); }
703 unsigned int get_number_of_permutations() const;
704 unsigned int get_permutation_start(unsigned int index_value) const;
705 unsigned int get_permutation_end(unsigned int index_value) const;
706 unsigned int get_permutation_size(unsigned int index_value) const;
707 boolean permutation_starts_at(unsigned int index_value) const;
708 boolean permutation_ends_at(unsigned int index_value) const;
711 static boolean match_function_specific(
712 const Base_Type *value_ptr, int value_index,
713 const Restricted_Length_Template *template_ptr, int template_index,
716 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
717 other_value, boolean legacy = FALSE) const;
719 boolean is_value() const;
720 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
722 void set_type(template_sel template_type, unsigned int list_length);
723 TEMPLATE_ARRAY& list_item(unsigned int list_index);
726 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
727 match_value, boolean legacy = FALSE) const;
729 void set_param(Module_Param& param);
730 Module_Param* get_param(Module_Param_Name& param_name) const;
732 void encode_text(Text_Buf& text_buf) const;
733 void decode_text(Text_Buf& text_buf);
735 boolean is_present(boolean legacy = FALSE) const;
736 boolean match_omit(boolean legacy = FALSE) const;
738 #ifdef TITAN_RUNTIME_2
739 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
740 void set_value(template_sel other_value) { *this = other_value; }
741 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
742 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
743 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
744 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); }
745 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); }
747 void check_restriction(template_res t_res, const char* t_name=NULL, boolean legacy = FALSE) const;
751 template <typename T_value_type, typename T_template_type,
752 unsigned int array_size, int index_offset>
753 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
755 unsigned int start_index, end_index; //beginning and ending index
758 template <typename T_value_type, typename T_template_type,
759 unsigned int array_size, int index_offset>
760 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
763 switch (template_selection)
766 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
767 delete single_value.value_elements[elem_count];
768 free_pointers((void**)single_value.value_elements);
771 case COMPLEMENTED_LIST:
772 delete [] value_list.list_value;
777 template_selection = UNINITIALIZED_TEMPLATE;
780 template <typename T_value_type, typename T_template_type,
781 unsigned int array_size, int index_offset>
782 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
785 number_of_permutations = 0;
786 Free(permutation_intervals);
787 permutation_intervals = NULL;
790 template <typename T_value_type, typename T_template_type,
791 unsigned int array_size, int index_offset>
792 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
793 set_selection(template_sel other_value)
795 Restricted_Length_Template::set_selection(other_value);
796 clean_up_intervals();
799 template <typename T_value_type, typename T_template_type,
800 unsigned int array_size, int index_offset>
801 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
802 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
804 Restricted_Length_Template::set_selection(other_value);
805 clean_up_intervals();
806 if(other_value.template_selection == SPECIFIC_VALUE)
808 number_of_permutations = other_value.number_of_permutations;
809 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
810 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
814 template <typename T_value_type, typename T_template_type,
815 unsigned int array_size, int index_offset>
816 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
817 encode_text_permutation(Text_Buf& text_buf) const
819 encode_text_restricted(text_buf);
820 text_buf.push_int(number_of_permutations);
822 for(unsigned int i = 0; i < number_of_permutations; i++)
824 text_buf.push_int(permutation_intervals[i].start_index);
825 text_buf.push_int(permutation_intervals[i].end_index);
829 template <typename T_value_type, typename T_template_type,
830 unsigned int array_size, int index_offset>
831 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
832 decode_text_permutation(Text_Buf& text_buf)
834 decode_text_restricted(text_buf);
836 number_of_permutations = text_buf.pull_int().get_val();
837 permutation_intervals = (Pair_of_elements *)Malloc
838 (number_of_permutations * sizeof(Pair_of_elements));
840 for (unsigned int i = 0; i < number_of_permutations; i++)
842 permutation_intervals[i].start_index =
843 text_buf.pull_int().get_val();
844 permutation_intervals[i].end_index =
845 text_buf.pull_int().get_val();
849 template <typename T_value_type, typename T_template_type,
850 unsigned int array_size, int index_offset>
851 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
852 add_permutation(unsigned int start_index, unsigned int end_index)
854 if(start_index > end_index)
855 TTCN_error("wrong permutation interval settings start (%d)"
856 "can not be greater than end (%d)",start_index, end_index);
858 if(number_of_permutations > 0 &&
859 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
860 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
862 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
863 permutation_intervals[number_of_permutations].start_index = start_index;
864 permutation_intervals[number_of_permutations].end_index = end_index;
865 number_of_permutations++;
868 template <typename T_value_type, typename T_template_type,
869 unsigned int array_size, int index_offset>
870 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
871 get_number_of_permutations(void) const
873 return number_of_permutations;
876 template <typename T_value_type, typename T_template_type,
877 unsigned int array_size, int index_offset>
878 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
879 get_permutation_start(unsigned int index_value) const
881 if(index_value >= number_of_permutations)
882 TTCN_error("Index overflow (%d)", index_value);
884 return permutation_intervals[index_value].start_index;
887 template <typename T_value_type, typename T_template_type,
888 unsigned int array_size, int index_offset>
889 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
890 get_permutation_end(unsigned int index_value) const
892 if(index_value >= number_of_permutations)
893 TTCN_error("Index overflow (%d)", index_value);
895 return permutation_intervals[index_value].end_index;
898 template <typename T_value_type, typename T_template_type,
899 unsigned int array_size, int index_offset>
900 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
901 get_permutation_size(unsigned int index_value) const
903 if(index_value >= number_of_permutations)
904 TTCN_error("Index overflow (%d)", index_value);
906 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
909 template <typename T_value_type, typename T_template_type,
910 unsigned int array_size, int index_offset>
911 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
912 permutation_starts_at(unsigned int index_value) const
914 for(unsigned int i = 0; i < number_of_permutations; i++)
916 if(permutation_intervals[i].start_index == index_value)
923 template <typename T_value_type, typename T_template_type,
924 unsigned int array_size, int index_offset>
925 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
926 permutation_ends_at(unsigned int index_value) const
928 for(unsigned int i = 0; i < number_of_permutations; i++)
930 if(permutation_intervals[i].end_index == index_value)
937 template <typename T_value_type, typename T_template_type,
938 unsigned int array_size, int index_offset>
939 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
940 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
943 single_value.n_elements = array_size;
944 single_value.value_elements =
945 (T_template_type**)allocate_pointers(array_size);
946 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
947 single_value.value_elements[elem_count] =
948 new T_template_type(other_value.array_element(elem_count));
949 set_selection(SPECIFIC_VALUE);
952 template <typename T_value_type, typename T_template_type,
953 unsigned int array_size, int index_offset>
954 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
955 copy_template(const TEMPLATE_ARRAY& other_value)
957 switch (other_value.template_selection)
960 single_value.n_elements = other_value.single_value.n_elements;
961 single_value.value_elements =
962 (T_template_type**)allocate_pointers(single_value.n_elements);
963 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
964 single_value.value_elements[elem_count] = new
965 T_template_type(*other_value.single_value.value_elements[elem_count]);
972 case COMPLEMENTED_LIST:
973 value_list.n_values = other_value.value_list.n_values;
974 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
975 for (unsigned int list_count = 0; list_count < value_list.n_values;
977 value_list.list_value[list_count].copy_template(
978 other_value.value_list.list_value[list_count]);
981 TTCN_error("Copying an uninitialized/unsupported array template.");
983 set_selection(other_value);
986 template <typename T_value_type, typename T_template_type,
987 unsigned int array_size, int index_offset>
988 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
989 TEMPLATE_ARRAY(null_type)
990 : Restricted_Length_Template(SPECIFIC_VALUE)
992 single_value.n_elements = 0;
993 single_value.value_elements = NULL;
994 number_of_permutations = 0;
995 permutation_intervals = NULL;
998 template <typename T_value_type, typename T_template_type,
999 unsigned int array_size, int index_offset>
1000 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1001 TEMPLATE_ARRAY(const
1002 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1004 number_of_permutations = 0;
1005 permutation_intervals = NULL;
1006 switch (other_value.get_selection()) {
1007 case OPTIONAL_PRESENT:
1008 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1012 set_selection(OMIT_VALUE);
1015 TTCN_error("Creating an array template from an unbound optional field.");
1019 template <typename T_value_type, typename T_template_type,
1020 unsigned int array_size, int index_offset>
1021 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1022 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1023 operator=(template_sel other_value)
1025 check_single_selection(other_value);
1027 set_selection(other_value);
1031 template <typename T_value_type, typename T_template_type,
1032 unsigned int array_size, int index_offset>
1033 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1034 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1035 operator=(null_type)
1038 set_selection(SPECIFIC_VALUE);
1039 single_value.n_elements = 0;
1040 single_value.value_elements = NULL;
1044 template <typename T_value_type, typename T_template_type,
1045 unsigned int array_size, int index_offset>
1046 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1047 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
1048 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
1051 copy_value(other_value);
1055 template <typename T_value_type, typename T_template_type,
1056 unsigned int array_size, int index_offset>
1057 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1058 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1060 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1063 switch (other_value.get_selection()) {
1064 case OPTIONAL_PRESENT:
1065 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1069 set_selection(OMIT_VALUE);
1072 TTCN_error("Assignment of an unbound optional field to an array template.");
1077 template <typename T_value_type, typename T_template_type,
1078 unsigned int array_size, int index_offset>
1079 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1080 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1082 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1085 if (&other_value != this)
1088 copy_template(other_value);
1093 template <typename T_value_type, typename T_template_type,
1094 unsigned int array_size, int index_offset>
1096 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1099 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1101 "Accessing an element of an array template using invalid index: %d. "
1102 "Index range is [%d,%d].",
1103 index_value, index_offset, index_offset+(int)array_size);
1104 // transform index value according to given offset
1105 index_value -= index_offset;
1106 // the template of an array is not restricted to array_size, allow any length
1107 // in case of * or ? expand to full size to avoid uninitialized values
1108 switch (template_selection)
1110 case SPECIFIC_VALUE:
1111 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1115 set_size(array_size);
1118 set_size(index_value + 1);
1120 return *single_value.value_elements[index_value];
1123 template <typename T_value_type, typename T_template_type,
1124 unsigned int array_size, int index_offset>
1126 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1127 (const INTEGER& index_value)
1129 index_value.must_bound(
1130 "Using an unbound integer value for indexing an array template.");
1131 return (*this)[(int)index_value];
1134 template <typename T_value_type, typename T_template_type,
1135 unsigned int array_size, int index_offset>
1136 const T_template_type&
1137 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1138 (int index_value) const
1140 if (index_value < index_offset)
1142 "Accessing an element of an array template using invalid index: %d. "
1143 "Index range starts at %d.",
1144 index_value, index_offset);
1145 // transform index value according to given offset
1146 index_value -= index_offset;
1147 // const is specific template
1148 if (template_selection != SPECIFIC_VALUE)
1149 TTCN_error("Accessing an element of a non-specific array template.");
1150 if (index_value >= single_value.n_elements)
1151 TTCN_error("Index overflow in an array template: "
1152 "The index is %d (starting at %d),"
1153 " but the template has only %d elements.",
1154 index_value+index_offset, index_offset, single_value.n_elements);
1155 return *single_value.value_elements[index_value];
1158 template <typename T_value_type, typename T_template_type,
1159 unsigned int array_size, int index_offset>
1160 const T_template_type&
1161 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1162 (const INTEGER& index_value) const
1164 index_value.must_bound(
1165 "Using an unbound integer value for indexing an array template.");
1166 return (*this)[(int)index_value];
1169 template <typename T_value_type, typename T_template_type,
1170 unsigned int array_size, int index_offset>
1171 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1172 set_size(int new_size)
1174 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1175 "for an array template.");
1176 template_sel old_selection = template_selection;
1177 if (old_selection != SPECIFIC_VALUE)
1180 set_selection(SPECIFIC_VALUE);
1181 single_value.n_elements = 0;
1182 single_value.value_elements = NULL;
1184 if (new_size > single_value.n_elements)
1186 single_value.value_elements =
1187 (T_template_type**)reallocate_pointers(
1188 (void**)single_value.value_elements, single_value.n_elements, new_size);
1189 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1191 for (int elem_count = single_value.n_elements;
1192 elem_count < new_size; elem_count++)
1193 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1197 for (int elem_count = single_value.n_elements;
1198 elem_count < new_size; elem_count++)
1199 single_value.value_elements[elem_count] = new T_template_type;
1201 single_value.n_elements = new_size;
1203 else if (new_size < single_value.n_elements)
1205 for (int elem_count = new_size; elem_count < single_value.n_elements;
1207 delete single_value.value_elements[elem_count];
1208 single_value.value_elements =
1209 (T_template_type**)reallocate_pointers(
1210 (void**)single_value.value_elements, single_value.n_elements, new_size);
1211 single_value.n_elements = new_size;
1215 template <typename T_value_type, typename T_template_type,
1216 unsigned int array_size, int index_offset>
1217 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1220 switch (template_selection) {
1221 case SPECIFIC_VALUE:
1222 return single_value.n_elements;
1224 return value_list.n_values;
1226 TTCN_error("Performing n_elem");
1230 template <typename T_value_type, typename T_template_type,
1231 unsigned int array_size, int index_offset>
1232 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1233 size_of(boolean is_size) const
1235 const char* op_name = is_size ? "size" : "length";
1237 boolean has_any_or_none;
1239 TTCN_error("Performing %sof() operation on an array template "
1240 "which has an ifpresent attribute.", op_name);
1241 switch (template_selection)
1243 case SPECIFIC_VALUE: {
1245 has_any_or_none = FALSE;
1246 int elem_count = single_value.n_elements;
1247 if (!is_size) { // lengthof()
1248 while (elem_count>0 &&
1249 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1251 for (int i=0; i<elem_count; i++)
1253 switch (single_value.value_elements[i]->get_selection())
1256 TTCN_error("Performing %sof() operation on an array template "
1257 "containing omit element.", op_name);
1259 has_any_or_none = TRUE;
1268 TTCN_error("Performing %sof() operation on an array template "
1269 "containing omit value.", op_name);
1273 has_any_or_none = TRUE; // max. size is infinity
1276 // error if any element does not have size or the sizes differ
1277 if (value_list.n_values<1)
1278 TTCN_error("Performing %sof() operation on an array template "
1279 "containing an empty list.", op_name);
1280 int item_size = value_list.list_value[0].size_of(is_size);
1281 for (unsigned int i = 1; i < value_list.n_values; i++) {
1282 if (value_list.list_value[i].size_of(is_size)!=item_size)
1283 TTCN_error("Performing %sof() operation on an array template "
1284 "containing a value list with different sizes.", op_name);
1286 min_size = item_size;
1287 has_any_or_none = FALSE;
1289 case COMPLEMENTED_LIST:
1290 TTCN_error("Performing %sof() operation on an array template "
1291 "containing complemented list.", op_name);
1293 TTCN_error("Performing %sof() operation on an "
1294 "uninitialized/unsupported array template.", op_name);
1296 return check_section_is_single(min_size, has_any_or_none,
1297 op_name, "an", "array template");
1300 template <typename T_value_type, typename T_template_type,
1301 unsigned int array_size, int index_offset>
1302 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1303 match_function_specific(const Base_Type *value_ptr, int value_index,
1304 const Restricted_Length_Template *template_ptr,
1305 int template_index, boolean legacy)
1307 if (value_index >= 0)
1308 return ((const TEMPLATE_ARRAY*)template_ptr)->
1309 single_value.value_elements[template_index]->
1311 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1312 ->array_element(value_index), legacy);
1314 return ((const TEMPLATE_ARRAY*)template_ptr)->
1315 single_value.value_elements[template_index]->is_any_or_omit();
1318 template <typename T_value_type, typename T_template_type,
1319 unsigned int array_size, int index_offset>
1320 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1321 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1322 other_value, boolean legacy) const
1324 if (!match_length(array_size)) return FALSE;
1325 switch (template_selection)
1327 case SPECIFIC_VALUE:
1328 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1329 match_function_specific, legacy);
1336 case COMPLEMENTED_LIST:
1337 for (unsigned int list_count = 0; list_count < value_list.n_values;
1339 if (value_list.list_value[list_count].match(other_value, legacy))
1340 return template_selection == VALUE_LIST;
1341 return template_selection == COMPLEMENTED_LIST;
1343 TTCN_error("Matching with an uninitialized/unsupported array template.");
1348 template <typename T_value_type, typename T_template_type,
1349 unsigned int array_size, int index_offset>
1350 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1353 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1354 for (int i=0; i<single_value.n_elements; i++)
1355 if (!single_value.value_elements[i]->is_value()) return FALSE;
1359 template <typename T_value_type, typename T_template_type,
1360 unsigned int array_size, int index_offset>
1361 VALUE_ARRAY<T_value_type, array_size, index_offset>
1362 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1365 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1366 TTCN_error("Performing a valueof or send operation on a "
1367 "non-specific array template.");
1368 // the size of the template must be the size of the value
1369 if (single_value.n_elements!=array_size)
1370 TTCN_error("Performing a valueof or send operation on a "
1371 "specific array template with invalid size.");
1372 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1373 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1374 ret_val.array_element(elem_count) =
1375 single_value.value_elements[elem_count]->valueof();
1379 template <typename T_value_type, typename T_template_type,
1380 unsigned int array_size, int index_offset>
1381 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1382 set_type(template_sel template_type, unsigned int list_length)
1385 switch (template_type) {
1387 case COMPLEMENTED_LIST:
1388 value_list.n_values = list_length;
1389 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1393 "Internal error: Setting an invalid type for an array template.");
1395 set_selection(template_type);
1398 template <typename T_value_type, typename T_template_type,
1399 unsigned int array_size, int index_offset>
1400 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1401 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1402 list_item(unsigned int list_index)
1404 if (template_selection != VALUE_LIST &&
1405 template_selection != COMPLEMENTED_LIST)
1406 TTCN_error("Internal error: Accessing a list element of a non-list "
1408 if (list_index >= value_list.n_values)
1409 TTCN_error("Internal error: Index overflow in a value list "
1411 return value_list.list_value[list_index];
1414 template <typename T_value_type, typename T_template_type,
1415 unsigned int array_size, int index_offset>
1416 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1419 switch (template_selection)
1421 case SPECIFIC_VALUE:
1422 if (single_value.n_elements > 0)
1424 TTCN_Logger::log_event_str("{ ");
1425 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1427 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1428 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1429 single_value.value_elements[elem_count]->log();
1430 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1432 TTCN_Logger::log_event_str(" }");
1435 TTCN_Logger::log_event_str("{ }");
1437 case COMPLEMENTED_LIST:
1438 TTCN_Logger::log_event_str("complement");
1440 TTCN_Logger::log_char('(');
1441 for (unsigned int list_count = 0; list_count < value_list.n_values;
1444 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1445 value_list.list_value[list_count].log();
1447 TTCN_Logger::log_char(')');
1457 template <typename T_value_type, typename T_template_type,
1458 unsigned int array_size, int index_offset>
1459 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1460 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1461 match_value, boolean legacy) const
1463 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1464 if(match(match_value, legacy)){
1465 TTCN_Logger::print_logmatch_buffer();
1466 TTCN_Logger::log_event_str(" matched");
1468 if (template_selection == SPECIFIC_VALUE &&
1469 single_value.n_elements == array_size) {
1470 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1471 for (unsigned int elem_count = 0; elem_count < array_size;
1473 if(!single_value.value_elements[elem_count]->
1474 match(match_value.array_element(elem_count), legacy)){
1475 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1476 single_value.value_elements[elem_count]->
1477 log_match(match_value.array_element(elem_count), legacy);
1478 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1481 log_match_length(array_size);
1483 TTCN_Logger::print_logmatch_buffer();
1485 TTCN_Logger::log_event_str(" with ");
1487 TTCN_Logger::log_event_str(" unmatched");
1492 if (template_selection == SPECIFIC_VALUE &&
1493 single_value.n_elements == array_size) {
1494 TTCN_Logger::log_event_str("{ ");
1495 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1496 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1497 single_value.value_elements[elem_count]->log_match(
1498 match_value.array_element(elem_count), legacy);
1500 TTCN_Logger::log_event_str(" }");
1501 log_match_length(array_size);
1504 TTCN_Logger::log_event_str(" with ");
1506 if (match(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1507 else TTCN_Logger::log_event_str(" unmatched");
1511 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1512 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1514 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1515 param.get_id()->next_name()) {
1516 // Haven't reached the end of the module parameter name
1517 // => the name refers to one of the elements, not to the whole array
1518 char* param_field = param.get_id()->get_current_name();
1519 if (param_field[0] < '0' || param_field[0] > '9') {
1520 param.error("Unexpected record field name in module parameter, expected a valid"
1521 " array template index");
1523 unsigned int param_index = -1;
1524 sscanf(param_field, "%u", ¶m_index);
1525 if (param_index >= array_size) {
1526 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1528 (*this)[param_index].set_param(param);
1532 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1534 Module_Param_Ptr mp = ¶m;
1535 if (param.get_type() == Module_Param::MP_Reference) {
1536 mp = param.get_referenced_param();
1539 switch (mp->get_type()) {
1540 case Module_Param::MP_Omit:
1543 case Module_Param::MP_Any:
1546 case Module_Param::MP_AnyOrNone:
1547 *this = ANY_OR_OMIT;
1549 case Module_Param::MP_List_Template:
1550 case Module_Param::MP_ComplementList_Template: {
1551 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset> temp;
1552 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1553 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1554 for (size_t i=0; i<mp->get_size(); i++) {
1555 temp.list_item(i).set_param(*mp->get_elem(i));
1559 case Module_Param::MP_Value_List:
1560 set_size(mp->get_size());
1561 for (size_t i=0; i<mp->get_size(); ++i) {
1562 Module_Param* const curr = mp->get_elem(i);
1563 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1564 (*this)[(int)i+index_offset].set_param(*curr);
1568 case Module_Param::MP_Indexed_List:
1569 for (size_t i=0; i<mp->get_size(); ++i) {
1570 Module_Param* const curr = mp->get_elem(i);
1571 (*this)[curr->get_id()->get_index()].set_param(*curr);
1575 param.type_error("array template");
1577 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1580 template <typename T_value_type, typename T_template_type,
1581 unsigned int array_size, int index_offset>
1582 Module_Param* TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1583 get_param(Module_Param_Name& param_name) const
1585 if (param_name.next_name()) {
1586 // Haven't reached the end of the module parameter name
1587 // => the name refers to one of the elements, not to the whole record of
1588 char* param_field = param_name.get_current_name();
1589 if (param_field[0] < '0' || param_field[0] > '9') {
1590 TTCN_error("Unexpected record field name in module parameter reference, "
1591 "expected a valid array index");
1593 unsigned int param_index = -1;
1594 sscanf(param_field, "%u", ¶m_index);
1595 if (param_index >= array_size) {
1596 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1598 return single_value.value_elements[param_index]->get_param(param_name);
1600 Module_Param* mp = NULL;
1601 switch (template_selection) {
1602 case UNINITIALIZED_TEMPLATE:
1603 mp = new Module_Param_Unbound();
1606 mp = new Module_Param_Omit();
1609 mp = new Module_Param_Any();
1612 mp = new Module_Param_AnyOrNone();
1614 case SPECIFIC_VALUE: {
1615 Vector<Module_Param*> values;
1616 for (unsigned int i = 0; i < array_size; ++i) {
1617 values.push_back(single_value.value_elements[i]->get_param(param_name));
1619 mp = new Module_Param_Value_List();
1620 mp->add_list_with_implicit_ids(&values);
1624 case COMPLEMENTED_LIST: {
1625 if (template_selection == VALUE_LIST) {
1626 mp = new Module_Param_List_Template();
1629 mp = new Module_Param_ComplementList_Template();
1631 for (size_t i = 0; i < value_list.n_values; ++i) {
1632 mp->add_elem(value_list.list_value[i].get_param(param_name));
1639 mp->set_ifpresent();
1644 template <typename T_value_type, typename T_template_type,
1645 unsigned int array_size, int index_offset>
1646 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1647 encode_text(Text_Buf& text_buf) const
1649 encode_text_restricted(text_buf);
1650 switch (template_selection)
1652 case SPECIFIC_VALUE:
1653 text_buf.push_int(single_value.n_elements);
1654 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1655 single_value.value_elements[elem_count]->encode_text(text_buf);
1662 case COMPLEMENTED_LIST:
1663 text_buf.push_int(value_list.n_values);
1664 for (unsigned int list_count = 0; list_count < value_list.n_values;
1666 value_list.list_value[list_count].encode_text(text_buf);
1669 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1674 template <typename T_value_type, typename T_template_type,
1675 unsigned int array_size, int index_offset>
1676 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1677 decode_text(Text_Buf& text_buf)
1680 decode_text_restricted(text_buf);
1681 switch (template_selection)
1683 case SPECIFIC_VALUE:
1684 single_value.n_elements = text_buf.pull_int().get_val();
1685 if (single_value.n_elements < 0)
1686 TTCN_error("Text decoder: Negative size was received for an "
1688 single_value.value_elements =
1689 (T_template_type**)allocate_pointers(single_value.n_elements);
1690 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1692 single_value.value_elements[elem_count] = new T_template_type;
1693 single_value.value_elements[elem_count]->decode_text(text_buf);
1701 case COMPLEMENTED_LIST:
1702 value_list.n_values = text_buf.pull_int().get_val();
1703 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1704 for (unsigned int list_count = 0; list_count < value_list.n_values;
1706 value_list.list_value[list_count].decode_text(text_buf);
1709 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1710 "for an array template.");
1714 template <typename T_value_type, typename T_template_type,
1715 unsigned int array_size, int index_offset>
1716 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1717 is_present(boolean legacy /* = FALSE */) const
1719 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1720 return !match_omit(legacy);
1723 template <typename T_value_type, typename T_template_type,
1724 unsigned int array_size, int index_offset>
1725 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1726 match_omit(boolean legacy /* = FALSE */) const
1728 if (is_ifpresent) return TRUE;
1729 switch (template_selection) {
1734 case COMPLEMENTED_LIST:
1736 // legacy behavior: 'omit' can appear in the value/complement list
1737 for (unsigned int i=0; i<value_list.n_values; i++)
1738 if (value_list.list_value[i].match_omit())
1739 return template_selection==VALUE_LIST;
1740 return template_selection==COMPLEMENTED_LIST;
1742 // else fall through
1749 #ifndef TITAN_RUNTIME_2
1750 template <typename T_value_type, typename T_template_type,
1751 unsigned int array_size, int index_offset>
1752 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1753 check_restriction(template_res t_res, const char* t_name, boolean legacy /* = FALSE */) const
1755 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1756 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1758 if (template_selection==OMIT_VALUE) return;
1760 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1761 for (int i=0; i<single_value.n_elements; i++)
1762 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1765 if (!match_omit(legacy)) return;
1770 TTCN_error("Restriction `%s' on template of type %s violated.",
1771 get_res_name(t_res), t_name ? t_name : "array");
1775 template <typename T_value_type, typename T_template_type,
1776 unsigned int array_size, int index_offset>
1777 answer recursive_permutation_match(const Base_Type *value_ptr,
1778 unsigned int value_start_index,
1779 unsigned int value_size,
1780 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1781 unsigned int template_start_index,
1782 unsigned int template_size,
1783 unsigned int permutation_index,
1784 match_function_t match_function,
1785 unsigned int& shift_size,
1788 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1789 if (permutation_index > nof_permutations)
1790 TTCN_error("Internal error: recursive_permutation_match: "
1791 "invalid argument.");
1793 if (permutation_index < nof_permutations &&
1794 template_ptr->get_permutation_end(permutation_index) >
1795 template_start_index + template_size)
1796 TTCN_error("Internal error: recursive_permutation_match: wrong "
1797 "permutation interval settings for permutation %d.",
1803 if(template_size == 0)
1805 //reached the end of templates
1806 // if we reached the end of values => good
1814 //are we at an asterisk or at the beginning of a permutation interval
1815 boolean is_asterisk;
1816 boolean permutation_begins = permutation_index < nof_permutations &&
1817 template_start_index ==
1818 template_ptr->get_permutation_start(permutation_index);
1820 if (permutation_begins ||
1821 match_function(value_ptr, -1, template_ptr, template_start_index, legacy))
1823 unsigned int smallest_possible_size;
1824 unsigned int largest_possible_size;
1825 boolean has_asterisk;
1826 boolean already_superset;
1827 unsigned int permutation_size;
1829 //check how many values might be associated with this permutation
1830 //if we are at a permutation start
1831 if (permutation_begins)
1833 is_asterisk = FALSE;
1835 template_ptr->get_permutation_size(permutation_index);
1836 smallest_possible_size = 0;
1837 has_asterisk = FALSE;
1839 //count how many non asterisk elements are in the permutation
1840 for(unsigned int i = 0; i < permutation_size; i++)
1842 if(match_function(value_ptr, -1, template_ptr,
1843 i + template_start_index, legacy))
1845 has_asterisk = TRUE;
1847 smallest_possible_size++;
1851 //the real permutation size is bigger then the value size
1852 if(smallest_possible_size > value_size)
1855 //if the permutation has an asterisk then it can grow
1858 largest_possible_size = value_size;
1860 //if there are only asterisks in the permutation
1861 if(smallest_possible_size == 0)
1862 already_superset = TRUE;
1864 already_superset = FALSE;
1866 //without asterisks its size is fixed
1867 largest_possible_size = smallest_possible_size;
1868 already_superset = FALSE;
1873 already_superset = TRUE;
1874 permutation_size = 1;
1875 smallest_possible_size = 0;
1876 largest_possible_size = value_size;
1877 has_asterisk = TRUE;
1880 unsigned int temp_size = smallest_possible_size;
1883 //this is to make match_set_of incremental,
1884 // we store the already found pairs in this vector
1885 // so we wouldn't try to find a pair for those templates again
1886 // and we can set the covered state of values too
1887 // to not waste memory it is only created if needed
1888 int* pair_list = NULL;
1889 unsigned int old_temp_size = 0;
1891 if(!already_superset)
1893 pair_list = new int[permutation_size];
1894 for(unsigned int i = 0 ; i < permutation_size; i++)
1896 //in the beginning we haven't found a template to any values
1901 while(!already_superset)
1903 //must be a permutation having other values than asterisks
1907 //our set matching is extended with 2 more parameters
1908 // giving back how many templates
1909 // (other than asterisk) couldn't be matched
1910 // and setting / giving back the value-template pairs
1912 boolean found = match_set_of_internal(value_ptr, value_start_index,
1913 temp_size, template_ptr,
1914 template_start_index, permutation_size,
1915 match_function, SUPERSET, &x, pair_list, old_temp_size, legacy);
1919 already_superset = TRUE;
1921 //as we didn't found a match we have to try
1922 // a larger set of values
1923 //x is the number of templates we couldn't find
1924 // a matching pair for
1925 // the next must be at least this big to fully cover
1926 // on the other side if it would be bigger than it might miss
1927 // the smallest possible match.
1929 //if we can match with more values
1930 if(has_asterisk && temp_size + x <= largest_possible_size)
1932 old_temp_size = temp_size;
1936 return FAILURE; //else we failed
1944 //we reach here only if we found a match
1946 //can only go on recursively if we haven't reached the end
1948 //reached the end of templates
1949 if(permutation_size == template_size)
1951 if(has_asterisk || value_size == temp_size)
1957 for(unsigned int i = temp_size; i <= largest_possible_size;)
1963 //don't step the permutation index
1964 result = recursive_permutation_match(value_ptr,value_start_index+i,
1965 value_size - i, template_ptr,
1966 template_start_index +
1971 match_function, shift_size, legacy);
1973 //try with the next permutation
1974 result = recursive_permutation_match(value_ptr,value_start_index+i,
1975 value_size - i, template_ptr,
1976 template_start_index +
1978 template_size - permutation_size,
1979 permutation_index + 1,
1980 match_function, shift_size, legacy);
1983 if(result == SUCCESS)
1984 return SUCCESS; //we finished
1985 else if(result == NO_CHANCE)
1986 return NO_CHANCE; //matching is not possible
1987 else if(i == value_size) //we failed
1989 //if there is no chance of matching
1992 i += shift_size > 1 ? shift_size : 1;
1994 if(i > largest_possible_size)
1995 shift_size = i - largest_possible_size;
2001 //this level failed;
2004 //we are at the beginning of a non permutation, non asterisk interval
2006 //the distance to the next permutation or the end of templates
2007 // so the longest possible match
2008 unsigned int distance;
2010 if (permutation_index < nof_permutations)
2012 distance = template_ptr->get_permutation_start(permutation_index)
2013 - template_start_index;
2015 distance = template_size;
2018 //if there are no more values, but we still have templates
2019 // and the template is not an asterisk or a permutation start
2023 //we try to match as many values as possible
2024 //an asterisk is handled like a 0 length permutation
2028 good = match_function(value_ptr, value_start_index + i,
2029 template_ptr, template_start_index + i, legacy);
2031 //bad stop: something can't be matched
2032 //half bad half good stop: the end of values is reached
2033 //good stop: matching on the full distance or till an asterisk
2034 }while(good && i < value_size && i < distance &&
2035 !match_function(value_ptr, -1, template_ptr,
2036 template_start_index + i, legacy));
2038 //if we matched on the full distance or till an asterisk
2039 if(good && (i == distance ||
2040 match_function(value_ptr, -1, template_ptr,
2041 template_start_index + i, legacy)))
2043 //reached the end of the templates
2044 if(i == template_size)
2048 //the next level would return FAILURE so we don't step it
2051 //i == value_size, so we matched everything
2055 //we reached the next asterisk or permutation,
2056 // so step to the next level
2057 return recursive_permutation_match(value_ptr,value_start_index + i,
2060 template_start_index + i,
2063 match_function, shift_size, legacy);
2066 //something bad happened, so we have to check how bad the situation is
2067 if( i == value_size)
2069 //the aren't values left, meaning that the match is not possible
2072 //we couldn't match, but there is still a chance of matching
2074 //try to find a matching value for the last checked (and failed)
2076 // smaller jumps would fail so we skip them
2080 good = match_function(value_ptr,
2081 value_start_index + i + shift_size,
2082 template_ptr, template_start_index + i, legacy);
2084 }while(!good && i + shift_size < value_size);
2091 // the template can not be matched later
2099 template <typename T_value_type, typename T_template_type,
2100 unsigned int array_size, int index_offset>
2101 boolean match_permutation_array(const Base_Type *value_ptr,
2103 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
2105 match_function_t match_function,
2108 if (value_ptr == NULL || value_size < 0 ||
2109 template_ptr == NULL || template_size < 0 ||
2110 template_ptr->get_selection() != SPECIFIC_VALUE)
2111 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
2113 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
2114 // use the simplified algorithm if the template does not contain permutation
2115 if (nof_permutations == 0)
2116 return match_array(value_ptr, value_size,
2117 template_ptr, template_size, match_function, legacy);
2118 // use 'set of' matching if all template elements are grouped into one
2120 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
2121 template_ptr->get_permutation_end(0) ==
2122 (unsigned int)(template_size - 1))
2123 return match_set_of(value_ptr, value_size, template_ptr, template_size,
2124 match_function, legacy);
2126 unsigned int shift_size = 0;
2127 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
2128 0, template_size, 0, match_function, shift_size, legacy) == SUCCESS;