Sync with 5.4.0
[deliverable/titan.core.git] / core / Array.hh
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #ifndef ARRAY_HH
9 #define ARRAY_HH
10
11 #include "Types.h"
12 #include "Param_Types.hh"
13 #include "Error.hh"
14 #include "Logger.hh"
15 #include "Basetype.hh"
16 #include "Template.hh"
17 #include "Optional.hh"
18 #include "Parameters.h"
19 #include "Integer.hh"
20 #include "Struct_of.hh"
21 #include "memory.h"
22
23 class INTEGER;
24
25 extern unsigned int get_timer_array_index(int index_value,
26 unsigned int array_size, int index_offset);
27 extern unsigned int get_timer_array_index(const INTEGER& index_value,
28 unsigned int array_size, int index_offset);
29
30 /** @brief Runtime implementation of timer arrays.
31 *
32 * @param T_type the type of the array element. This can be \c TIMER_ARRAY
33 * for multi-dimensional arrays.
34 * @param array_size the number of elements in the array
35 * @param index_offset the lowest index
36 *
37 * */
38 template <typename T_type, unsigned int array_size, int index_offset>
39 class TIMER_ARRAY
40 #ifdef TITAN_RUNTIME_2
41 : public RefdIndexInterface
42 #endif
43 {
44 T_type array_elements[array_size];
45 char * names[array_size];
46
47 /// Copy constructor disallowed.
48 TIMER_ARRAY(const TIMER_ARRAY& other_value);
49 /// Assignment disallowed.
50 TIMER_ARRAY& operator=(const TIMER_ARRAY& other_value);
51
52 public:
53 TIMER_ARRAY() { }
54
55 ~TIMER_ARRAY() {
56 for (size_t i = 0; i < array_size; ++i) {
57 Free(names[i]);
58 }
59 }
60
61 T_type& operator[](int index_value) { return array_elements[
62 get_timer_array_index(index_value, array_size, index_offset)]; }
63 T_type& operator[](const INTEGER& index_value) { return array_elements[
64 get_timer_array_index(index_value, array_size, index_offset)]; }
65
66 int n_elem() const { return array_size; }
67 int size_of() const { return array_size; }
68 int lengthof() const { return array_size; }
69
70 T_type& array_element(unsigned int index_value)
71 { return array_elements[index_value]; }
72
73 void set_name(const char * name_string)
74 {
75 for (int i = 0; i < (int)array_size; ++i) {
76 // index_offset may be negative, hence i must be int (not size_t)
77 // to ensure that signed arithmetic is used.
78 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
79 array_elements[i].set_name(names[i]);
80 }
81 }
82
83 void log() const
84 {
85 TTCN_Logger::log_event_str("{ ");
86 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
87 if (v_index > 0) TTCN_Logger::log_event_str(", ");
88 array_elements[v_index].log();
89 }
90 TTCN_Logger::log_event_str(" }");
91 }
92 };
93
94 extern unsigned int get_port_array_index(int index_value,
95 unsigned int array_size, int index_offset);
96 extern unsigned int get_port_array_index(const INTEGER& index_value,
97 unsigned int array_size, int index_offset);
98
99 template <typename T_type, unsigned int array_size, int index_offset>
100 class PORT_ARRAY
101 #ifdef TITAN_RUNTIME_2
102 : public RefdIndexInterface
103 #endif
104 {
105 T_type array_elements[array_size];
106 char * names[array_size];
107
108 /// Copy constructor disallowed.
109 PORT_ARRAY(const PORT_ARRAY& other_value);
110 /// Assignment disallowed.
111 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
112
113 public:
114 PORT_ARRAY() { }
115
116 ~PORT_ARRAY() {
117 for (size_t i = 0; i < array_size; ++i) {
118 Free(names[i]);
119 }
120 }
121
122 T_type& operator[](int index_value) { return array_elements[
123 get_port_array_index(index_value, array_size, index_offset)]; }
124 T_type& operator[](const INTEGER& index_value) { return array_elements[
125 get_port_array_index(index_value, array_size, index_offset)]; }
126
127 int n_elem() const { return array_size; }
128 int size_of() const { return array_size; }
129 int lengthof()const { return array_size; }
130
131 void set_name(const char * name_string)
132 {
133 for (int i = 0; i < (int)array_size; ++i) {
134 // i must be int, see comment in TIMER_ARRAY::set_name
135 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
136 array_elements[i].set_name(names[i]);
137 }
138 }
139
140 void activate_port()
141 {
142 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
143 array_elements[v_index].activate_port();
144 }
145 }
146
147 void log() const
148 {
149 TTCN_Logger::log_event_str("{ ");
150 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
151 if (v_index > 0) TTCN_Logger::log_event_str(", ");
152 array_elements[v_index].log();
153 }
154 TTCN_Logger::log_event_str(" }");
155 }
156 };
157
158 ////////////////////////////////////////////////////////////////////////////////
159
160 extern unsigned int get_array_index(int index_value,
161 unsigned int array_size, int index_offset);
162 extern unsigned int get_array_index(const INTEGER& index_value,
163 unsigned int array_size, int index_offset);
164
165 template <typename T_type, unsigned int array_size, int index_offset>
166 class VALUE_ARRAY : public Base_Type
167 #ifdef TITAN_RUNTIME_2
168 , public RefdIndexInterface
169 #endif
170 {
171 T_type array_elements[array_size];
172 public:
173 // This class use the compiler-generated copy constructor and
174 // copy assignment.
175
176 boolean operator==(const VALUE_ARRAY& other_value) const;
177 inline boolean operator!=(const VALUE_ARRAY& other_value) const
178 { return !(*this == other_value); }
179
180 T_type& operator[](int index_value) { return array_elements[
181 get_array_index(index_value, array_size, index_offset)]; }
182 T_type& operator[](const INTEGER& index_value) { return array_elements[
183 get_array_index(index_value, array_size, index_offset)]; }
184 const T_type& operator[](int index_value) const { return array_elements[
185 get_array_index(index_value, array_size, index_offset)]; }
186 const T_type& operator[](const INTEGER& index_value) const {
187 return array_elements[
188 get_array_index(index_value, array_size, index_offset)];
189 }
190
191 // rotation
192 VALUE_ARRAY operator<<=(int rotate_count) const;
193 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
194 VALUE_ARRAY operator>>=(int rotate_count) const;
195 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
196
197 T_type& array_element(unsigned int index_value)
198 { return array_elements[index_value]; }
199 const T_type& array_element(unsigned int index_value) const
200 { return array_elements[index_value]; }
201
202 void set_implicit_omit();
203
204 boolean is_bound() const;
205 boolean is_value() const;
206 void clean_up();
207 void log() const;
208
209 inline int n_elem() const { return array_size; }
210 inline int size_of() const { return array_size; }
211 int lengthof() const;
212
213 void set_param(Module_Param& param);
214 Module_Param* get_param(Module_Param_Name& param_name) const;
215
216 #ifdef TITAN_RUNTIME_2
217 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
218 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
219 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
220 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
221 #else
222 inline boolean is_present() const { return is_bound(); }
223 #endif
224
225 void encode_text(Text_Buf& text_buf) const;
226 void decode_text(Text_Buf& text_buf);
227
228 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
229 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
230
231 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
232 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
233
234 /** Encodes accordingly to the JSON encoding rules.
235 * Returns the length of the encoded data. */
236 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
237
238 /** Decodes accordingly to the JSON encoding rules.
239 * Returns the length of the decoded data. */
240 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
241 };
242
243 template <typename T_type, unsigned int array_size, int index_offset>
244 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
245 (const VALUE_ARRAY& other_value) const
246 {
247 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
248 if (array_elements[elem_count] != other_value.array_elements[elem_count])
249 return FALSE;
250 return TRUE;
251 }
252
253 template <typename T_type, unsigned int array_size, int index_offset>
254 VALUE_ARRAY<T_type,array_size,index_offset>
255 VALUE_ARRAY<T_type,array_size,index_offset>::
256 operator<<=(int rotate_count) const {
257 return *this >>= (-rotate_count);
258 }
259
260 template <typename T_type, unsigned int array_size, int index_offset>
261 VALUE_ARRAY<T_type,array_size,index_offset>
262 VALUE_ARRAY<T_type,array_size,index_offset>::
263 operator<<=(const INTEGER& rotate_count) const {
264 rotate_count.must_bound("Unbound integer operand of rotate left "
265 "operator.");
266 return *this >>= (int)(-rotate_count);
267 }
268
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 unsigned int rc;
274 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
275 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
276 if (rc == 0) return *this;
277 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
278 for (unsigned int i=0; i<array_size; i++) {
279 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
280 }
281 return ret_val;
282 }
283
284 template <typename T_type, unsigned int array_size, int index_offset>
285 VALUE_ARRAY<T_type,array_size,index_offset>
286 VALUE_ARRAY<T_type,array_size,index_offset>::
287 operator>>=(const INTEGER& rotate_count) const {
288 rotate_count.must_bound("Unbound integer operand of rotate right "
289 "operator.");
290 return *this >>= (int)rotate_count;
291 }
292
293 template <typename T_type, unsigned int array_size, int index_offset>
294 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
295 {
296 for (unsigned int i = 0; i < array_size; ++i) {
297 if (array_elements[i].is_bound())
298 array_elements[i].set_implicit_omit();
299 }
300 }
301
302 template <typename T_type, unsigned int array_size, int index_offset>
303 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
304 {
305 for (unsigned int i = 0; i < array_size; ++i) {
306 if (!array_elements[i].is_bound()) {
307 return false;
308 }
309 }
310 return true;
311 }
312
313 template <typename T_type, unsigned int array_size, int index_offset>
314 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
315 {
316 for (unsigned int i = 0; i < array_size; ++i) {
317 if (!array_elements[i].is_value()) {
318 return false;
319 }
320 }
321 return true;
322 }
323
324 template <typename T_type, unsigned int array_size, int index_offset>
325 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
326 {
327 for (unsigned int i = 0; i < array_size; ++i) {
328 array_elements[i].clean_up();
329 }
330 }
331
332 template <typename T_type, unsigned int array_size, int index_offset>
333 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
334 {
335 TTCN_Logger::log_event_str("{ ");
336 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
337 {
338 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
339 array_elements[elem_count].log();
340 }
341 TTCN_Logger::log_event_str(" }");
342 }
343
344 template <typename T_type, unsigned int array_size, int index_offset>
345 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
346 {
347
348 for (unsigned int my_length=array_size; my_length>0; my_length--)
349 {
350 if (array_elements[my_length-1].is_bound()) return my_length;
351 }
352 return 0;
353 }
354
355 template <typename T_type, unsigned int array_size, int index_offset>
356 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
357 Module_Param& param)
358 {
359 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
360 param.get_id()->next_name()) {
361 // Haven't reached the end of the module parameter name
362 // => the name refers to one of the elements, not to the whole array
363 char* param_field = param.get_id()->get_current_name();
364 if (param_field[0] < '0' || param_field[0] > '9') {
365 param.error("Unexpected record field name in module parameter, expected a valid"
366 " array index");
367 }
368 unsigned int param_index = -1;
369 sscanf(param_field, "%u", &param_index);
370 if (param_index >= array_size) {
371 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
372 }
373 array_elements[param_index].set_param(param);
374 return;
375 }
376
377 param.basic_check(Module_Param::BC_VALUE, "array value");
378 Module_Param_Ptr mp = &param;
379 if (param.get_type() == Module_Param::MP_Reference) {
380 mp = param.get_referenced_param();
381 }
382 switch (mp->get_type()) {
383 case Module_Param::MP_Value_List:
384 if (mp->get_size()!=array_size) {
385 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);
386 }
387 for (size_t i=0; i<mp->get_size(); ++i) {
388 Module_Param* const curr = mp->get_elem(i);
389 if (curr->get_type()!=Module_Param::MP_NotUsed) {
390 array_elements[i].set_param(*curr);
391 }
392 }
393 break;
394 case Module_Param::MP_Indexed_List:
395 for (size_t i=0; i<mp->get_size(); ++i) {
396 Module_Param* const curr = mp->get_elem(i);
397 array_elements[curr->get_id()->get_index()].set_param(*curr);
398 }
399 break;
400 default:
401 param.type_error("array value");
402 }
403 }
404
405 template <typename T_type, unsigned int array_size, int index_offset>
406 Module_Param* VALUE_ARRAY<T_type,array_size,index_offset>::get_param
407 (Module_Param_Name& param_name) const
408 {
409 if (!is_bound()) {
410 return new Module_Param_Unbound();
411 }
412 if (param_name.next_name()) {
413 // Haven't reached the end of the module parameter name
414 // => the name refers to one of the elements, not to the whole array
415 char* param_field = param_name.get_current_name();
416 if (param_field[0] < '0' || param_field[0] > '9') {
417 TTCN_error("Unexpected record field name in module parameter reference, "
418 "expected a valid array index");
419 }
420 unsigned int param_index = -1;
421 sscanf(param_field, "%u", &param_index);
422 if (param_index >= array_size) {
423 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
424 }
425 return array_elements[param_index].get_param(param_name);
426 }
427 Vector<Module_Param*> values;
428 for (int i = 0; i < array_size; ++i) {
429 values.push_back(array_elements[i].get_param(param_name));
430 }
431 Module_Param_Value_List* mp = new Module_Param_Value_List();
432 mp->add_list_with_implicit_ids(&values);
433 values.clear();
434 return mp;
435 }
436
437 template <typename T_type, unsigned int array_size, int index_offset>
438 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
439 (Text_Buf& text_buf) const
440 {
441 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
442 array_elements[elem_count].encode_text(text_buf);
443 }
444
445 template <typename T_type, unsigned int array_size, int index_offset>
446 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
447 (Text_Buf& text_buf)
448 {
449 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
450 array_elements[elem_count].decode_text(text_buf);
451 }
452
453 template <typename T_type, unsigned int array_size, int index_offset>
454 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
455 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
456 {
457 va_list pvar;
458 va_start(pvar, p_coding);
459 switch(p_coding) {
460 case TTCN_EncDec::CT_JSON: {
461 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
462 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
463 ("No JSON descriptor available for type '%s'.", p_td.name);
464 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
465 JSON_encode(p_td, tok);
466 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
467 break;}
468 default:
469 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
470 }
471 va_end(pvar);
472 }
473
474 template <typename T_type, unsigned int array_size, int index_offset>
475 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
476 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
477 {
478 switch(p_coding) {
479 case TTCN_EncDec::CT_JSON: {
480 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
481 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
482 ("No JSON descriptor available for type '%s'.", p_td.name);
483 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
484 if(JSON_decode(p_td, tok, false)<0)
485 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
486 "because invalid or incomplete message was received", p_td.name);
487 p_buf.set_pos(tok.get_buf_pos());
488 break;}
489 default:
490 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
491 }
492 }
493
494 template <typename T_type, unsigned int array_size, int index_offset>
495 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
496 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
497 {
498 if (!is_bound()) {
499 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
500 "Encoding an unbound array value.");
501 return -1;
502 }
503
504 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
505
506 for(unsigned int i = 0; i < array_size; ++i) {
507 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
508 if (0 > ret_val) break;
509 enc_len += ret_val;
510 }
511
512 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
513 return enc_len;
514 }
515
516 template <typename T_type, unsigned int array_size, int index_offset>
517 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
518 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)
519 {
520 json_token_t token = JSON_TOKEN_NONE;
521 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
522 if (JSON_TOKEN_ERROR == token) {
523 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
524 return JSON_ERROR_FATAL;
525 }
526 else if (JSON_TOKEN_ARRAY_START != token) {
527 return JSON_ERROR_INVALID_TOKEN;
528 }
529
530 for(unsigned int i = 0; i < array_size; ++i) {
531 int ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
532 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
533 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
534 array_size - i, (array_size - i > 1) ? "s" : "");
535 return JSON_ERROR_FATAL;
536 }
537 else if (JSON_ERROR_FATAL == ret_val) {
538 if (p_silent) {
539 clean_up();
540 }
541 return JSON_ERROR_FATAL;
542 }
543 dec_len += ret_val;
544 }
545
546 dec_len += p_tok.get_next_token(&token, NULL, NULL);
547 if (JSON_TOKEN_ARRAY_END != token) {
548 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
549 if (p_silent) {
550 clean_up();
551 }
552 return JSON_ERROR_FATAL;
553 }
554
555 return dec_len;
556 }
557
558
559 template <typename T_value_type, typename T_template_type,
560 unsigned int array_size, int index_offset>
561 class TEMPLATE_ARRAY : public Restricted_Length_Template
562 {
563 private:
564 union {
565 struct {
566 int n_elements;
567 T_template_type **value_elements;
568 } single_value;
569 struct {
570 unsigned int n_values;
571 TEMPLATE_ARRAY *list_value;
572 } value_list;
573 };
574
575 struct Pair_of_elements;
576 Pair_of_elements *permutation_intervals;
577 unsigned int number_of_permutations;
578
579 void clean_up_intervals();
580 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
581 other_value);
582 void copy_template(const TEMPLATE_ARRAY& other_value);
583 void set_selection(template_sel new_selection);
584 void set_selection(const TEMPLATE_ARRAY& other_value);
585 void encode_text_permutation(Text_Buf& text_buf) const;
586 void decode_text_permutation(Text_Buf& text_buf);
587
588 public:
589 TEMPLATE_ARRAY()
590 {
591 number_of_permutations = 0;
592 permutation_intervals = NULL;
593 }
594 TEMPLATE_ARRAY(template_sel other_value)
595 : Restricted_Length_Template(other_value)
596 {
597 check_single_selection(other_value);
598 number_of_permutations = 0;
599 permutation_intervals = NULL;
600 }
601 TEMPLATE_ARRAY(null_type other_value);
602 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
603 other_value)
604 {
605 number_of_permutations = 0;
606 permutation_intervals = NULL;
607 copy_value(other_value);
608 }
609 TEMPLATE_ARRAY(const
610 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
611 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
612 : Restricted_Length_Template()
613 {
614 number_of_permutations = 0;
615 permutation_intervals = NULL;
616 copy_template(other_value);
617 }
618
619 ~TEMPLATE_ARRAY()
620 {
621 clean_up_intervals();
622 clean_up();
623 }
624 void clean_up();
625
626 TEMPLATE_ARRAY& operator=(template_sel other_value);
627 TEMPLATE_ARRAY& operator=(null_type other_value);
628 TEMPLATE_ARRAY& operator=(const
629 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
630 TEMPLATE_ARRAY& operator=(const
631 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
632 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
633
634 T_template_type& operator[](int index_value);
635 T_template_type& operator[](const INTEGER& index_value);
636 const T_template_type& operator[](int index_value) const;
637 const T_template_type& operator[](const INTEGER& index_value) const;
638
639 void set_size(int new_size);
640
641 int n_elem() const;
642 int size_of(boolean is_size) const;
643 inline int size_of() const { return size_of(TRUE); }
644 inline int lengthof() const { return size_of(FALSE); }
645
646 void add_permutation(unsigned int start_index, unsigned int end_index);
647
648 /** Removes all permutations set on this template, used when template variables
649 * are given new values. */
650 void remove_all_permutations() { clean_up_intervals(); }
651
652 unsigned int get_number_of_permutations() const;
653 unsigned int get_permutation_start(unsigned int index_value) const;
654 unsigned int get_permutation_end(unsigned int index_value) const;
655 unsigned int get_permutation_size(unsigned int index_value) const;
656 boolean permutation_starts_at(unsigned int index_value) const;
657 boolean permutation_ends_at(unsigned int index_value) const;
658
659 private:
660 static boolean match_function_specific(
661 const Base_Type *value_ptr, int value_index,
662 const Restricted_Length_Template *template_ptr, int template_index,
663 boolean legacy);
664 public:
665 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
666 other_value, boolean legacy = FALSE) const;
667
668 boolean is_value() const;
669 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
670
671 void set_type(template_sel template_type, unsigned int list_length);
672 TEMPLATE_ARRAY& list_item(unsigned int list_index);
673
674 void log() const;
675 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
676 match_value, boolean legacy = FALSE) const;
677
678 void set_param(Module_Param& param);
679 Module_Param* get_param(Module_Param_Name& param_name) const;
680
681 void encode_text(Text_Buf& text_buf) const;
682 void decode_text(Text_Buf& text_buf);
683
684 boolean is_present(boolean legacy = FALSE) const;
685 boolean match_omit(boolean legacy = FALSE) const;
686
687 #ifdef TITAN_RUNTIME_2
688 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
689 void set_value(template_sel other_value) { *this = other_value; }
690 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
691 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
692 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
693 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); }
694 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); }
695 #else
696 void check_restriction(template_res t_res, const char* t_name=NULL, boolean legacy = FALSE) const;
697 #endif
698 };
699
700 template <typename T_value_type, typename T_template_type,
701 unsigned int array_size, int index_offset>
702 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
703 Pair_of_elements{
704 unsigned int start_index, end_index; //beginning and ending index
705 };
706
707 template <typename T_value_type, typename T_template_type,
708 unsigned int array_size, int index_offset>
709 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
710 clean_up()
711 {
712 switch (template_selection)
713 {
714 case SPECIFIC_VALUE:
715 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
716 delete single_value.value_elements[elem_count];
717 free_pointers((void**)single_value.value_elements);
718 break;
719 case VALUE_LIST:
720 case COMPLEMENTED_LIST:
721 delete [] value_list.list_value;
722 break;
723 default:
724 break;
725 }
726 template_selection = UNINITIALIZED_TEMPLATE;
727 }
728
729 template <typename T_value_type, typename T_template_type,
730 unsigned int array_size, int index_offset>
731 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
732 clean_up_intervals()
733 {
734 number_of_permutations = 0;
735 Free(permutation_intervals);
736 permutation_intervals = NULL;
737 }
738
739 template <typename T_value_type, typename T_template_type,
740 unsigned int array_size, int index_offset>
741 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
742 set_selection(template_sel other_value)
743 {
744 Restricted_Length_Template::set_selection(other_value);
745 clean_up_intervals();
746 }
747
748 template <typename T_value_type, typename T_template_type,
749 unsigned int array_size, int index_offset>
750 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
751 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
752 {
753 Restricted_Length_Template::set_selection(other_value);
754 clean_up_intervals();
755 if(other_value.template_selection == SPECIFIC_VALUE)
756 {
757 number_of_permutations = other_value.number_of_permutations;
758 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
759 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
760 }
761 }
762
763 template <typename T_value_type, typename T_template_type,
764 unsigned int array_size, int index_offset>
765 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
766 encode_text_permutation(Text_Buf& text_buf) const
767 {
768 encode_text_restricted(text_buf);
769 text_buf.push_int(number_of_permutations);
770
771 for(unsigned int i = 0; i < number_of_permutations; i++)
772 {
773 text_buf.push_int(permutation_intervals[i].start_index);
774 text_buf.push_int(permutation_intervals[i].end_index);
775 }
776 }
777
778 template <typename T_value_type, typename T_template_type,
779 unsigned int array_size, int index_offset>
780 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
781 decode_text_permutation(Text_Buf& text_buf)
782 {
783 decode_text_restricted(text_buf);
784
785 number_of_permutations = text_buf.pull_int().get_val();
786 permutation_intervals = (Pair_of_elements *)Malloc
787 (number_of_permutations * sizeof(Pair_of_elements));
788
789 for (unsigned int i = 0; i < number_of_permutations; i++)
790 {
791 permutation_intervals[i].start_index =
792 text_buf.pull_int().get_val();
793 permutation_intervals[i].end_index =
794 text_buf.pull_int().get_val();
795 }
796 }
797
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 add_permutation(unsigned int start_index, unsigned int end_index)
802 {
803 if(start_index > end_index)
804 TTCN_error("wrong permutation interval settings start (%d)"
805 "can not be greater than end (%d)",start_index, end_index);
806
807 if(number_of_permutations > 0 &&
808 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
809 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
810
811 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
812 permutation_intervals[number_of_permutations].start_index = start_index;
813 permutation_intervals[number_of_permutations].end_index = end_index;
814 number_of_permutations++;
815 }
816
817 template <typename T_value_type, typename T_template_type,
818 unsigned int array_size, int index_offset>
819 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
820 get_number_of_permutations(void) const
821 {
822 return number_of_permutations;
823 }
824
825 template <typename T_value_type, typename T_template_type,
826 unsigned int array_size, int index_offset>
827 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
828 get_permutation_start(unsigned int index_value) const
829 {
830 if(index_value >= number_of_permutations)
831 TTCN_error("Index overflow (%d)", index_value);
832
833 return permutation_intervals[index_value].start_index;
834 }
835
836 template <typename T_value_type, typename T_template_type,
837 unsigned int array_size, int index_offset>
838 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
839 get_permutation_end(unsigned int index_value) const
840 {
841 if(index_value >= number_of_permutations)
842 TTCN_error("Index overflow (%d)", index_value);
843
844 return permutation_intervals[index_value].end_index;
845 }
846
847 template <typename T_value_type, typename T_template_type,
848 unsigned int array_size, int index_offset>
849 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
850 get_permutation_size(unsigned int index_value) const
851 {
852 if(index_value >= number_of_permutations)
853 TTCN_error("Index overflow (%d)", index_value);
854
855 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
856 }
857
858 template <typename T_value_type, typename T_template_type,
859 unsigned int array_size, int index_offset>
860 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
861 permutation_starts_at(unsigned int index_value) const
862 {
863 for(unsigned int i = 0; i < number_of_permutations; i++)
864 {
865 if(permutation_intervals[i].start_index == index_value)
866 return TRUE;
867 }
868
869 return FALSE;
870 }
871
872 template <typename T_value_type, typename T_template_type,
873 unsigned int array_size, int index_offset>
874 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
875 permutation_ends_at(unsigned int index_value) const
876 {
877 for(unsigned int i = 0; i < number_of_permutations; i++)
878 {
879 if(permutation_intervals[i].end_index == index_value)
880 return TRUE;
881 }
882
883 return FALSE;
884 }
885
886 template <typename T_value_type, typename T_template_type,
887 unsigned int array_size, int index_offset>
888 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
889 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
890 other_value)
891 {
892 single_value.n_elements = array_size;
893 single_value.value_elements =
894 (T_template_type**)allocate_pointers(array_size);
895 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
896 single_value.value_elements[elem_count] =
897 new T_template_type(other_value.array_element(elem_count));
898 set_selection(SPECIFIC_VALUE);
899 }
900
901 template <typename T_value_type, typename T_template_type,
902 unsigned int array_size, int index_offset>
903 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
904 copy_template(const TEMPLATE_ARRAY& other_value)
905 {
906 switch (other_value.template_selection)
907 {
908 case SPECIFIC_VALUE:
909 single_value.n_elements = other_value.single_value.n_elements;
910 single_value.value_elements =
911 (T_template_type**)allocate_pointers(single_value.n_elements);
912 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
913 single_value.value_elements[elem_count] = new
914 T_template_type(*other_value.single_value.value_elements[elem_count]);
915 break;
916 case OMIT_VALUE:
917 case ANY_VALUE:
918 case ANY_OR_OMIT:
919 break;
920 case VALUE_LIST:
921 case COMPLEMENTED_LIST:
922 value_list.n_values = other_value.value_list.n_values;
923 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
924 for (unsigned int list_count = 0; list_count < value_list.n_values;
925 list_count++)
926 value_list.list_value[list_count].copy_template(
927 other_value.value_list.list_value[list_count]);
928 break;
929 default:
930 TTCN_error("Copying an uninitialized/unsupported array template.");
931 }
932 set_selection(other_value);
933 }
934
935 template <typename T_value_type, typename T_template_type,
936 unsigned int array_size, int index_offset>
937 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
938 TEMPLATE_ARRAY(null_type)
939 : Restricted_Length_Template(SPECIFIC_VALUE)
940 {
941 single_value.n_elements = 0;
942 single_value.value_elements = NULL;
943 number_of_permutations = 0;
944 permutation_intervals = NULL;
945 }
946
947 template <typename T_value_type, typename T_template_type,
948 unsigned int array_size, int index_offset>
949 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
950 TEMPLATE_ARRAY(const
951 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
952 {
953 number_of_permutations = 0;
954 permutation_intervals = NULL;
955 switch (other_value.get_selection()) {
956 case OPTIONAL_PRESENT:
957 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
958 other_value);
959 break;
960 case OPTIONAL_OMIT:
961 set_selection(OMIT_VALUE);
962 break;
963 default:
964 TTCN_error("Creating an array template from an unbound optional field.");
965 }
966 }
967
968 template <typename T_value_type, typename T_template_type,
969 unsigned int array_size, int index_offset>
970 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
971 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
972 operator=(template_sel other_value)
973 {
974 check_single_selection(other_value);
975 clean_up();
976 set_selection(other_value);
977 return *this;
978 }
979
980 template <typename T_value_type, typename T_template_type,
981 unsigned int array_size, int index_offset>
982 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
983 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
984 operator=(null_type)
985 {
986 clean_up();
987 set_selection(SPECIFIC_VALUE);
988 single_value.n_elements = 0;
989 single_value.value_elements = NULL;
990 return *this;
991 }
992
993 template <typename T_value_type, typename T_template_type,
994 unsigned int array_size, int index_offset>
995 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
996 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
997 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
998 {
999 clean_up();
1000 copy_value(other_value);
1001 return *this;
1002 }
1003
1004 template <typename T_value_type, typename T_template_type,
1005 unsigned int array_size, int index_offset>
1006 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1007 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1008 operator=(const
1009 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1010 {
1011 clean_up();
1012 switch (other_value.get_selection()) {
1013 case OPTIONAL_PRESENT:
1014 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1015 other_value);
1016 break;
1017 case OPTIONAL_OMIT:
1018 set_selection(OMIT_VALUE);
1019 break;
1020 default:
1021 TTCN_error("Assignment of an unbound optional field to an array template.");
1022 }
1023 return *this;
1024 }
1025
1026 template <typename T_value_type, typename T_template_type,
1027 unsigned int array_size, int index_offset>
1028 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1029 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1030 operator=(const
1031 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1032 other_value)
1033 {
1034 if (&other_value != this)
1035 {
1036 clean_up();
1037 copy_template(other_value);
1038 }
1039 return *this;
1040 }
1041
1042 template <typename T_value_type, typename T_template_type,
1043 unsigned int array_size, int index_offset>
1044 T_template_type&
1045 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1046 (int index_value)
1047 {
1048 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1049 TTCN_error(
1050 "Accessing an element of an array template using invalid index: %d. "
1051 "Index range is [%d,%d].",
1052 index_value, index_offset, index_offset+(int)array_size);
1053 // transform index value according to given offset
1054 index_value -= index_offset;
1055 // the template of an array is not restricted to array_size, allow any length
1056 // in case of * or ? expand to full size to avoid uninitialized values
1057 switch (template_selection)
1058 {
1059 case SPECIFIC_VALUE:
1060 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1061 break;
1062 case ANY_VALUE:
1063 case ANY_OR_OMIT:
1064 set_size(array_size);
1065 break;
1066 default:
1067 set_size(index_value + 1);
1068 }
1069 return *single_value.value_elements[index_value];
1070 }
1071
1072 template <typename T_value_type, typename T_template_type,
1073 unsigned int array_size, int index_offset>
1074 T_template_type&
1075 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1076 (const INTEGER& index_value)
1077 {
1078 index_value.must_bound(
1079 "Using an unbound integer value for indexing an array template.");
1080 return (*this)[(int)index_value];
1081 }
1082
1083 template <typename T_value_type, typename T_template_type,
1084 unsigned int array_size, int index_offset>
1085 const T_template_type&
1086 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1087 (int index_value) const
1088 {
1089 if (index_value < index_offset)
1090 TTCN_error(
1091 "Accessing an element of an array template using invalid index: %d. "
1092 "Index range starts at %d.",
1093 index_value, index_offset);
1094 // transform index value according to given offset
1095 index_value -= index_offset;
1096 // const is specific template
1097 if (template_selection != SPECIFIC_VALUE)
1098 TTCN_error("Accessing an element of a non-specific array template.");
1099 if (index_value >= single_value.n_elements)
1100 TTCN_error("Index overflow in an array template: "
1101 "The index is %d (starting at %d),"
1102 " but the template has only %d elements.",
1103 index_value+index_offset, index_offset, single_value.n_elements);
1104 return *single_value.value_elements[index_value];
1105 }
1106
1107 template <typename T_value_type, typename T_template_type,
1108 unsigned int array_size, int index_offset>
1109 const T_template_type&
1110 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1111 (const INTEGER& index_value) const
1112 {
1113 index_value.must_bound(
1114 "Using an unbound integer value for indexing an array template.");
1115 return (*this)[(int)index_value];
1116 }
1117
1118 template <typename T_value_type, typename T_template_type,
1119 unsigned int array_size, int index_offset>
1120 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1121 set_size(int new_size)
1122 {
1123 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1124 "for an array template.");
1125 template_sel old_selection = template_selection;
1126 if (old_selection != SPECIFIC_VALUE)
1127 {
1128 clean_up();
1129 set_selection(SPECIFIC_VALUE);
1130 single_value.n_elements = 0;
1131 single_value.value_elements = NULL;
1132 }
1133 if (new_size > single_value.n_elements)
1134 {
1135 single_value.value_elements =
1136 (T_template_type**)reallocate_pointers(
1137 (void**)single_value.value_elements, single_value.n_elements, new_size);
1138 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1139 {
1140 for (int elem_count = single_value.n_elements;
1141 elem_count < new_size; elem_count++)
1142 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1143 }
1144 else
1145 {
1146 for (int elem_count = single_value.n_elements;
1147 elem_count < new_size; elem_count++)
1148 single_value.value_elements[elem_count] = new T_template_type;
1149 }
1150 single_value.n_elements = new_size;
1151 }
1152 else if (new_size < single_value.n_elements)
1153 {
1154 for (int elem_count = new_size; elem_count < single_value.n_elements;
1155 elem_count++)
1156 delete single_value.value_elements[elem_count];
1157 single_value.value_elements =
1158 (T_template_type**)reallocate_pointers(
1159 (void**)single_value.value_elements, single_value.n_elements, new_size);
1160 single_value.n_elements = new_size;
1161 }
1162 }
1163
1164 template <typename T_value_type, typename T_template_type,
1165 unsigned int array_size, int index_offset>
1166 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1167 n_elem() const
1168 {
1169 switch (template_selection) {
1170 case SPECIFIC_VALUE:
1171 return single_value.n_elements;
1172 case VALUE_LIST:
1173 return value_list.n_values;
1174 default:
1175 TTCN_error("Performing n_elem");
1176 }
1177 }
1178
1179 template <typename T_value_type, typename T_template_type,
1180 unsigned int array_size, int index_offset>
1181 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1182 size_of(boolean is_size) const
1183 {
1184 const char* op_name = is_size ? "size" : "length";
1185 int min_size;
1186 boolean has_any_or_none;
1187 if (is_ifpresent)
1188 TTCN_error("Performing %sof() operation on an array template "
1189 "which has an ifpresent attribute.", op_name);
1190 switch (template_selection)
1191 {
1192 case SPECIFIC_VALUE: {
1193 min_size = 0;
1194 has_any_or_none = FALSE;
1195 int elem_count = single_value.n_elements;
1196 if (!is_size) { // lengthof()
1197 while (elem_count>0 &&
1198 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1199 }
1200 for (int i=0; i<elem_count; i++)
1201 {
1202 switch (single_value.value_elements[i]->get_selection())
1203 {
1204 case OMIT_VALUE:
1205 TTCN_error("Performing %sof() operation on an array template "
1206 "containing omit element.", op_name);
1207 case ANY_OR_OMIT:
1208 has_any_or_none = TRUE;
1209 break;
1210 default:
1211 min_size++;
1212 break;
1213 }
1214 }
1215 } break;
1216 case OMIT_VALUE:
1217 TTCN_error("Performing %sof() operation on an array template "
1218 "containing omit value.", op_name);
1219 case ANY_VALUE:
1220 case ANY_OR_OMIT:
1221 min_size = 0;
1222 has_any_or_none = TRUE; // max. size is infinity
1223 break;
1224 case VALUE_LIST: {
1225 // error if any element does not have size or the sizes differ
1226 if (value_list.n_values<1)
1227 TTCN_error("Performing %sof() operation on an array template "
1228 "containing an empty list.", op_name);
1229 int item_size = value_list.list_value[0].size_of(is_size);
1230 for (unsigned int i = 1; i < value_list.n_values; i++) {
1231 if (value_list.list_value[i].size_of(is_size)!=item_size)
1232 TTCN_error("Performing %sof() operation on an array template "
1233 "containing a value list with different sizes.", op_name);
1234 }
1235 min_size = item_size;
1236 has_any_or_none = FALSE;
1237 } break;
1238 case COMPLEMENTED_LIST:
1239 TTCN_error("Performing %sof() operation on an array template "
1240 "containing complemented list.", op_name);
1241 default:
1242 TTCN_error("Performing %sof() operation on an "
1243 "uninitialized/unsupported array template.", op_name);
1244 }
1245 return check_section_is_single(min_size, has_any_or_none,
1246 op_name, "an", "array template");
1247 }
1248
1249 template <typename T_value_type, typename T_template_type,
1250 unsigned int array_size, int index_offset>
1251 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1252 match_function_specific(const Base_Type *value_ptr, int value_index,
1253 const Restricted_Length_Template *template_ptr,
1254 int template_index, boolean legacy)
1255 {
1256 if (value_index >= 0)
1257 return ((const TEMPLATE_ARRAY*)template_ptr)->
1258 single_value.value_elements[template_index]->
1259 match(
1260 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1261 ->array_element(value_index), legacy);
1262 else
1263 return ((const TEMPLATE_ARRAY*)template_ptr)->
1264 single_value.value_elements[template_index]->is_any_or_omit();
1265 }
1266
1267 template <typename T_value_type, typename T_template_type,
1268 unsigned int array_size, int index_offset>
1269 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1270 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1271 other_value, boolean legacy) const
1272 {
1273 if (!match_length(array_size)) return FALSE;
1274 switch (template_selection)
1275 {
1276 case SPECIFIC_VALUE:
1277 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1278 match_function_specific, legacy);
1279 case OMIT_VALUE:
1280 return FALSE;
1281 case ANY_VALUE:
1282 case ANY_OR_OMIT:
1283 return TRUE;
1284 case VALUE_LIST:
1285 case COMPLEMENTED_LIST:
1286 for (unsigned int list_count = 0; list_count < value_list.n_values;
1287 list_count++)
1288 if (value_list.list_value[list_count].match(other_value, legacy))
1289 return template_selection == VALUE_LIST;
1290 return template_selection == COMPLEMENTED_LIST;
1291 default:
1292 TTCN_error("Matching with an uninitialized/unsupported array template.");
1293 }
1294 return FALSE;
1295 }
1296
1297 template <typename T_value_type, typename T_template_type,
1298 unsigned int array_size, int index_offset>
1299 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1300 is_value() const
1301 {
1302 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1303 for (int i=0; i<single_value.n_elements; i++)
1304 if (!single_value.value_elements[i]->is_value()) return FALSE;
1305 return TRUE;
1306 }
1307
1308 template <typename T_value_type, typename T_template_type,
1309 unsigned int array_size, int index_offset>
1310 VALUE_ARRAY<T_value_type, array_size, index_offset>
1311 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1312 valueof() const
1313 {
1314 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1315 TTCN_error("Performing a valueof or send operation on a "
1316 "non-specific array template.");
1317 // the size of the template must be the size of the value
1318 if (single_value.n_elements!=array_size)
1319 TTCN_error("Performing a valueof or send operation on a "
1320 "specific array template with invalid size.");
1321 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1322 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1323 ret_val.array_element(elem_count) =
1324 single_value.value_elements[elem_count]->valueof();
1325 return ret_val;
1326 }
1327
1328 template <typename T_value_type, typename T_template_type,
1329 unsigned int array_size, int index_offset>
1330 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1331 set_type(template_sel template_type, unsigned int list_length)
1332 {
1333 clean_up();
1334 switch (template_type) {
1335 case VALUE_LIST:
1336 case COMPLEMENTED_LIST:
1337 value_list.n_values = list_length;
1338 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1339 break;
1340 default:
1341 TTCN_error(
1342 "Internal error: Setting an invalid type for an array template.");
1343 }
1344 set_selection(template_type);
1345 }
1346
1347 template <typename T_value_type, typename T_template_type,
1348 unsigned int array_size, int index_offset>
1349 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1350 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1351 list_item(unsigned int list_index)
1352 {
1353 if (template_selection != VALUE_LIST &&
1354 template_selection != COMPLEMENTED_LIST)
1355 TTCN_error("Internal error: Accessing a list element of a non-list "
1356 "array template.");
1357 if (list_index >= value_list.n_values)
1358 TTCN_error("Internal error: Index overflow in a value list "
1359 "array template.");
1360 return value_list.list_value[list_index];
1361 }
1362
1363 template <typename T_value_type, typename T_template_type,
1364 unsigned int array_size, int index_offset>
1365 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1366 log() const
1367 {
1368 switch (template_selection)
1369 {
1370 case SPECIFIC_VALUE:
1371 if (single_value.n_elements > 0)
1372 {
1373 TTCN_Logger::log_event_str("{ ");
1374 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1375 {
1376 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1377 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1378 single_value.value_elements[elem_count]->log();
1379 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1380 }
1381 TTCN_Logger::log_event_str(" }");
1382 }
1383 else
1384 TTCN_Logger::log_event_str("{ }");
1385 break;
1386 case COMPLEMENTED_LIST:
1387 TTCN_Logger::log_event_str("complement");
1388 case VALUE_LIST:
1389 TTCN_Logger::log_char('(');
1390 for (unsigned int list_count = 0; list_count < value_list.n_values;
1391 list_count++)
1392 {
1393 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1394 value_list.list_value[list_count].log();
1395 }
1396 TTCN_Logger::log_char(')');
1397 break;
1398 default:
1399 log_generic();
1400 break;
1401 }
1402 log_restricted();
1403 log_ifpresent();
1404 }
1405
1406 template <typename T_value_type, typename T_template_type,
1407 unsigned int array_size, int index_offset>
1408 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1409 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1410 match_value, boolean legacy) const
1411 {
1412 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1413 if(match(match_value, legacy)){
1414 TTCN_Logger::print_logmatch_buffer();
1415 TTCN_Logger::log_event_str(" matched");
1416 }else{
1417 if (template_selection == SPECIFIC_VALUE &&
1418 single_value.n_elements == array_size) {
1419 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1420 for (unsigned int elem_count = 0; elem_count < array_size;
1421 elem_count++) {
1422 if(!single_value.value_elements[elem_count]->
1423 match(match_value.array_element(elem_count), legacy)){
1424 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1425 single_value.value_elements[elem_count]->
1426 log_match(match_value.array_element(elem_count), legacy);
1427 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1428 }
1429 }
1430 log_match_length(array_size);
1431 } else {
1432 TTCN_Logger::print_logmatch_buffer();
1433 match_value.log();
1434 TTCN_Logger::log_event_str(" with ");
1435 log();
1436 TTCN_Logger::log_event_str(" unmatched");
1437 }
1438 }
1439 return;
1440 }
1441 if (template_selection == SPECIFIC_VALUE &&
1442 single_value.n_elements == array_size) {
1443 TTCN_Logger::log_event_str("{ ");
1444 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1445 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1446 single_value.value_elements[elem_count]->log_match(
1447 match_value.array_element(elem_count), legacy);
1448 }
1449 TTCN_Logger::log_event_str(" }");
1450 log_match_length(array_size);
1451 } else {
1452 match_value.log();
1453 TTCN_Logger::log_event_str(" with ");
1454 log();
1455 if (match(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1456 else TTCN_Logger::log_event_str(" unmatched");
1457 }
1458 }
1459
1460 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1461 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1462 {
1463 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1464 param.get_id()->next_name()) {
1465 // Haven't reached the end of the module parameter name
1466 // => the name refers to one of the elements, not to the whole array
1467 char* param_field = param.get_id()->get_current_name();
1468 if (param_field[0] < '0' || param_field[0] > '9') {
1469 param.error("Unexpected record field name in module parameter, expected a valid"
1470 " array template index");
1471 }
1472 unsigned int param_index = -1;
1473 sscanf(param_field, "%u", &param_index);
1474 if (param_index >= array_size) {
1475 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1476 }
1477 (*this)[param_index].set_param(param);
1478 return;
1479 }
1480
1481 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1482
1483 Module_Param_Ptr mp = &param;
1484 if (param.get_type() == Module_Param::MP_Reference) {
1485 mp = param.get_referenced_param();
1486 }
1487
1488 switch (mp->get_type()) {
1489 case Module_Param::MP_Omit:
1490 *this = OMIT_VALUE;
1491 break;
1492 case Module_Param::MP_Any:
1493 *this = ANY_VALUE;
1494 break;
1495 case Module_Param::MP_AnyOrNone:
1496 *this = ANY_OR_OMIT;
1497 break;
1498 case Module_Param::MP_List_Template:
1499 case Module_Param::MP_ComplementList_Template: {
1500 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset> temp;
1501 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1502 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1503 for (size_t i=0; i<mp->get_size(); i++) {
1504 temp.list_item(i).set_param(*mp->get_elem(i));
1505 }
1506 *this = temp;
1507 break; }
1508 case Module_Param::MP_Value_List:
1509 set_size(mp->get_size());
1510 for (size_t i=0; i<mp->get_size(); ++i) {
1511 Module_Param* const curr = mp->get_elem(i);
1512 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1513 (*this)[(int)i+index_offset].set_param(*curr);
1514 }
1515 }
1516 break;
1517 case Module_Param::MP_Indexed_List:
1518 for (size_t i=0; i<mp->get_size(); ++i) {
1519 Module_Param* const curr = mp->get_elem(i);
1520 (*this)[curr->get_id()->get_index()].set_param(*curr);
1521 }
1522 break;
1523 default:
1524 param.type_error("array template");
1525 }
1526 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1527 }
1528
1529 template <typename T_value_type, typename T_template_type,
1530 unsigned int array_size, int index_offset>
1531 Module_Param* TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1532 get_param(Module_Param_Name& param_name) const
1533 {
1534 if (param_name.next_name()) {
1535 // Haven't reached the end of the module parameter name
1536 // => the name refers to one of the elements, not to the whole record of
1537 char* param_field = param_name.get_current_name();
1538 if (param_field[0] < '0' || param_field[0] > '9') {
1539 TTCN_error("Unexpected record field name in module parameter reference, "
1540 "expected a valid array index");
1541 }
1542 unsigned int param_index = -1;
1543 sscanf(param_field, "%u", &param_index);
1544 if (param_index >= array_size) {
1545 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1546 }
1547 return single_value.value_elements[param_index]->get_param(param_name);
1548 }
1549 Module_Param* mp = NULL;
1550 switch (template_selection) {
1551 case UNINITIALIZED_TEMPLATE:
1552 mp = new Module_Param_Unbound();
1553 break;
1554 case OMIT_VALUE:
1555 mp = new Module_Param_Omit();
1556 break;
1557 case ANY_VALUE:
1558 mp = new Module_Param_Any();
1559 break;
1560 case ANY_OR_OMIT:
1561 mp = new Module_Param_AnyOrNone();
1562 break;
1563 case SPECIFIC_VALUE: {
1564 Vector<Module_Param*> values;
1565 for (int i = 0; i < array_size; ++i) {
1566 values.push_back(single_value.value_elements[i]->get_param(param_name));
1567 }
1568 mp = new Module_Param_Value_List();
1569 mp->add_list_with_implicit_ids(&values);
1570 values.clear();
1571 break; }
1572 case VALUE_LIST:
1573 case COMPLEMENTED_LIST: {
1574 if (template_selection == VALUE_LIST) {
1575 mp = new Module_Param_List_Template();
1576 }
1577 else {
1578 mp = new Module_Param_ComplementList_Template();
1579 }
1580 for (size_t i = 0; i < value_list.n_values; ++i) {
1581 mp->add_elem(value_list.list_value[i].get_param(param_name));
1582 }
1583 break; }
1584 default:
1585 break;
1586 }
1587 if (is_ifpresent) {
1588 mp->set_ifpresent();
1589 }
1590 return mp;
1591 }
1592
1593 template <typename T_value_type, typename T_template_type,
1594 unsigned int array_size, int index_offset>
1595 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1596 encode_text(Text_Buf& text_buf) const
1597 {
1598 encode_text_restricted(text_buf);
1599 switch (template_selection)
1600 {
1601 case SPECIFIC_VALUE:
1602 text_buf.push_int(single_value.n_elements);
1603 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1604 single_value.value_elements[elem_count]->encode_text(text_buf);
1605 break;
1606 case OMIT_VALUE:
1607 case ANY_VALUE:
1608 case ANY_OR_OMIT:
1609 break;
1610 case VALUE_LIST:
1611 case COMPLEMENTED_LIST:
1612 text_buf.push_int(value_list.n_values);
1613 for (unsigned int list_count = 0; list_count < value_list.n_values;
1614 list_count++)
1615 value_list.list_value[list_count].encode_text(text_buf);
1616 break;
1617 default:
1618 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1619 "array template.");
1620 }
1621 }
1622
1623 template <typename T_value_type, typename T_template_type,
1624 unsigned int array_size, int index_offset>
1625 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1626 decode_text(Text_Buf& text_buf)
1627 {
1628 clean_up();
1629 decode_text_restricted(text_buf);
1630 switch (template_selection)
1631 {
1632 case SPECIFIC_VALUE:
1633 single_value.n_elements = text_buf.pull_int().get_val();
1634 if (single_value.n_elements < 0)
1635 TTCN_error("Text decoder: Negative size was received for an "
1636 "array template.");
1637 single_value.value_elements =
1638 (T_template_type**)allocate_pointers(single_value.n_elements);
1639 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1640 {
1641 single_value.value_elements[elem_count] = new T_template_type;
1642 single_value.value_elements[elem_count]->decode_text(text_buf);
1643 }
1644 break;
1645 case OMIT_VALUE:
1646 case ANY_VALUE:
1647 case ANY_OR_OMIT:
1648 break;
1649 case VALUE_LIST:
1650 case COMPLEMENTED_LIST:
1651 value_list.n_values = text_buf.pull_int().get_val();
1652 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1653 for (unsigned int list_count = 0; list_count < value_list.n_values;
1654 list_count++)
1655 value_list.list_value[list_count].decode_text(text_buf);
1656 break;
1657 default:
1658 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1659 "for an array template.");
1660 }
1661 }
1662
1663 template <typename T_value_type, typename T_template_type,
1664 unsigned int array_size, int index_offset>
1665 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1666 is_present(boolean legacy /* = FALSE */) const
1667 {
1668 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1669 return !match_omit(legacy);
1670 }
1671
1672 template <typename T_value_type, typename T_template_type,
1673 unsigned int array_size, int index_offset>
1674 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1675 match_omit(boolean legacy /* = FALSE */) const
1676 {
1677 if (is_ifpresent) return TRUE;
1678 switch (template_selection) {
1679 case OMIT_VALUE:
1680 case ANY_OR_OMIT:
1681 return TRUE;
1682 case VALUE_LIST:
1683 case COMPLEMENTED_LIST:
1684 for (unsigned int i=0; i<value_list.n_values; i++)
1685 if (value_list.list_value[i].match_omit())
1686 return template_selection==VALUE_LIST;
1687 return template_selection==COMPLEMENTED_LIST;
1688 default:
1689 return FALSE;
1690 }
1691 return FALSE;
1692 }
1693
1694 #ifndef TITAN_RUNTIME_2
1695 template <typename T_value_type, typename T_template_type,
1696 unsigned int array_size, int index_offset>
1697 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1698 check_restriction(template_res t_res, const char* t_name, boolean legacy /* = FALSE */) const
1699 {
1700 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1701 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1702 case TR_OMIT:
1703 if (template_selection==OMIT_VALUE) return;
1704 case TR_VALUE:
1705 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1706 for (int i=0; i<single_value.n_elements; i++)
1707 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1708 return;
1709 case TR_PRESENT:
1710 if (!match_omit(legacy)) return;
1711 break;
1712 default:
1713 return;
1714 }
1715 TTCN_error("Restriction `%s' on template of type %s violated.",
1716 get_res_name(t_res), t_name ? t_name : "array");
1717 }
1718 #endif
1719
1720 template <typename T_value_type, typename T_template_type,
1721 unsigned int array_size, int index_offset>
1722 answer recursive_permutation_match(const Base_Type *value_ptr,
1723 unsigned int value_start_index,
1724 unsigned int value_size,
1725 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1726 unsigned int template_start_index,
1727 unsigned int template_size,
1728 unsigned int permutation_index,
1729 match_function_t match_function,
1730 unsigned int& shift_size,
1731 boolean legacy)
1732 {
1733 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1734 if (permutation_index > nof_permutations)
1735 TTCN_error("Internal error: recursive_permutation_match: "
1736 "invalid argument.");
1737
1738 if (permutation_index < nof_permutations &&
1739 template_ptr->get_permutation_end(permutation_index) >
1740 template_start_index + template_size)
1741 TTCN_error("Internal error: recursive_permutation_match: wrong "
1742 "permutation interval settings for permutation %d.",
1743 permutation_index);
1744
1745 shift_size = 0;
1746
1747 //trivial cases
1748 if(template_size == 0)
1749 {
1750 //reached the end of templates
1751 // if we reached the end of values => good
1752 // else => bad
1753 if(value_size == 0)
1754 return SUCCESS;
1755 else
1756 return FAILURE;
1757 }
1758
1759 //are we at an asterisk or at the beginning of a permutation interval
1760 boolean is_asterisk;
1761 boolean permutation_begins = permutation_index < nof_permutations &&
1762 template_start_index ==
1763 template_ptr->get_permutation_start(permutation_index);
1764
1765 if (permutation_begins ||
1766 match_function(value_ptr, -1, template_ptr, template_start_index, legacy))
1767 {
1768 unsigned int smallest_possible_size;
1769 unsigned int largest_possible_size;
1770 boolean has_asterisk;
1771 boolean already_superset;
1772 unsigned int permutation_size;
1773
1774 //check how many values might be associated with this permutation
1775 //if we are at a permutation start
1776 if (permutation_begins)
1777 {
1778 is_asterisk = FALSE;
1779 permutation_size =
1780 template_ptr->get_permutation_size(permutation_index);
1781 smallest_possible_size = 0;
1782 has_asterisk = FALSE;
1783
1784 //count how many non asterisk elements are in the permutation
1785 for(unsigned int i = 0; i < permutation_size; i++)
1786 {
1787 if(match_function(value_ptr, -1, template_ptr,
1788 i + template_start_index, legacy))
1789 {
1790 has_asterisk = TRUE;
1791 }else{
1792 smallest_possible_size++;
1793 }
1794 }
1795
1796 //the real permutation size is bigger then the value size
1797 if(smallest_possible_size > value_size)
1798 return NO_CHANCE;
1799
1800 //if the permutation has an asterisk then it can grow
1801 if(has_asterisk)
1802 {
1803 largest_possible_size = value_size;
1804
1805 //if there are only asterisks in the permutation
1806 if(smallest_possible_size == 0)
1807 already_superset = TRUE;
1808 else
1809 already_superset = FALSE;
1810 }else{
1811 //without asterisks its size is fixed
1812 largest_possible_size = smallest_possible_size;
1813 already_superset = FALSE;
1814 }
1815 }else{
1816 //or at an asterisk
1817 is_asterisk = TRUE;
1818 already_superset = TRUE;
1819 permutation_size = 1;
1820 smallest_possible_size = 0;
1821 largest_possible_size = value_size;
1822 has_asterisk = TRUE;
1823 }
1824
1825 unsigned int temp_size = smallest_possible_size;
1826
1827 {
1828 //this is to make match_set_of incremental,
1829 // we store the already found pairs in this vector
1830 // so we wouldn't try to find a pair for those templates again
1831 // and we can set the covered state of values too
1832 // to not waste memory it is only created if needed
1833 int* pair_list = NULL;
1834 unsigned int old_temp_size = 0;
1835
1836 if(!already_superset)
1837 {
1838 pair_list = new int[permutation_size];
1839 for(unsigned int i = 0 ; i < permutation_size; i++)
1840 {
1841 //in the beginning we haven't found a template to any values
1842 pair_list[i] = -1;
1843 }
1844 }
1845
1846 while(!already_superset)
1847 {
1848 //must be a permutation having other values than asterisks
1849
1850 int x = 0;
1851
1852 //our set matching is extended with 2 more parameters
1853 // giving back how many templates
1854 // (other than asterisk) couldn't be matched
1855 // and setting / giving back the value-template pairs
1856
1857 boolean found = match_set_of_internal(value_ptr, value_start_index,
1858 temp_size, template_ptr,
1859 template_start_index, permutation_size,
1860 match_function, SUPERSET, &x, pair_list, old_temp_size, legacy);
1861
1862 if(found)
1863 {
1864 already_superset = TRUE;
1865 }else{
1866 //as we didn't found a match we have to try
1867 // a larger set of values
1868 //x is the number of templates we couldn't find
1869 // a matching pair for
1870 // the next must be at least this big to fully cover
1871 // on the other side if it would be bigger than it might miss
1872 // the smallest possible match.
1873
1874 //if we can match with more values
1875 if(has_asterisk && temp_size + x <= largest_possible_size)
1876 {
1877 old_temp_size = temp_size;
1878 temp_size += x;
1879 }else{
1880 delete[] pair_list;
1881 return FAILURE; //else we failed
1882 }
1883 }
1884 }
1885
1886 delete[] pair_list;
1887 }
1888
1889 //we reach here only if we found a match
1890
1891 //can only go on recursively if we haven't reached the end
1892
1893 //reached the end of templates
1894 if(permutation_size == template_size)
1895 {
1896 if(has_asterisk || value_size == temp_size)
1897 return SUCCESS;
1898 else
1899 return FAILURE;
1900 }
1901
1902 for(unsigned int i = temp_size; i <= largest_possible_size;)
1903 {
1904 answer result;
1905
1906 if(is_asterisk)
1907 {
1908 //don't step the permutation index
1909 result = recursive_permutation_match(value_ptr,value_start_index+i,
1910 value_size - i, template_ptr,
1911 template_start_index +
1912 permutation_size,
1913 template_size -
1914 permutation_size,
1915 permutation_index,
1916 match_function, shift_size, legacy);
1917 }else{
1918 //try with the next permutation
1919 result = recursive_permutation_match(value_ptr,value_start_index+i,
1920 value_size - i, template_ptr,
1921 template_start_index +
1922 permutation_size,
1923 template_size - permutation_size,
1924 permutation_index + 1,
1925 match_function, shift_size, legacy);
1926 }
1927
1928 if(result == SUCCESS)
1929 return SUCCESS; //we finished
1930 else if(result == NO_CHANCE)
1931 return NO_CHANCE; //matching is not possible
1932 else if(i == value_size) //we failed
1933 {
1934 //if there is no chance of matching
1935 return NO_CHANCE;
1936 }else{
1937 i += shift_size > 1 ? shift_size : 1;
1938
1939 if(i > largest_possible_size)
1940 shift_size = i - largest_possible_size;
1941 else
1942 shift_size = 0;
1943 }
1944 }
1945
1946 //this level failed;
1947 return FAILURE;
1948 }else{
1949 //we are at the beginning of a non permutation, non asterisk interval
1950
1951 //the distance to the next permutation or the end of templates
1952 // so the longest possible match
1953 unsigned int distance;
1954
1955 if (permutation_index < nof_permutations)
1956 {
1957 distance = template_ptr->get_permutation_start(permutation_index)
1958 - template_start_index;
1959 }else{
1960 distance = template_size;
1961 }
1962
1963 //if there are no more values, but we still have templates
1964 // and the template is not an asterisk or a permutation start
1965 if(value_size == 0)
1966 return FAILURE;
1967
1968 //we try to match as many values as possible
1969 //an asterisk is handled like a 0 length permutation
1970 boolean good;
1971 unsigned int i = 0;
1972 do{
1973 good = match_function(value_ptr, value_start_index + i,
1974 template_ptr, template_start_index + i, legacy);
1975 i++;
1976 //bad stop: something can't be matched
1977 //half bad half good stop: the end of values is reached
1978 //good stop: matching on the full distance or till an asterisk
1979 }while(good && i < value_size && i < distance &&
1980 !match_function(value_ptr, -1, template_ptr,
1981 template_start_index + i, legacy));
1982
1983 //if we matched on the full distance or till an asterisk
1984 if(good && (i == distance ||
1985 match_function(value_ptr, -1, template_ptr,
1986 template_start_index + i, legacy)))
1987 {
1988 //reached the end of the templates
1989 if(i == template_size)
1990 {
1991 if(i < value_size)
1992 {
1993 //the next level would return FAILURE so we don't step it
1994 return FAILURE;
1995 }else{
1996 //i == value_size, so we matched everything
1997 return SUCCESS;
1998 }
1999 }else{
2000 //we reached the next asterisk or permutation,
2001 // so step to the next level
2002 return recursive_permutation_match(value_ptr,value_start_index + i,
2003 value_size - i,
2004 template_ptr,
2005 template_start_index + i,
2006 template_size - i,
2007 permutation_index,
2008 match_function, shift_size, legacy);
2009 }
2010 }else{
2011 //something bad happened, so we have to check how bad the situation is
2012 if( i == value_size)
2013 {
2014 //the aren't values left, meaning that the match is not possible
2015 return NO_CHANCE;
2016 }else{
2017 //we couldn't match, but there is still a chance of matching
2018
2019 //try to find a matching value for the last checked (and failed)
2020 // template.
2021 // smaller jumps would fail so we skip them
2022 shift_size = 0;
2023 i--;
2024 do{
2025 good = match_function(value_ptr,
2026 value_start_index + i + shift_size,
2027 template_ptr, template_start_index + i, legacy);
2028 shift_size++;
2029 }while(!good && i + shift_size < value_size);
2030
2031 if(good)
2032 {
2033 shift_size--;
2034 return FAILURE;
2035 }else{
2036 // the template can not be matched later
2037 return NO_CHANCE;
2038 }
2039 }
2040 }
2041 }
2042 }
2043
2044 template <typename T_value_type, typename T_template_type,
2045 unsigned int array_size, int index_offset>
2046 boolean match_permutation_array(const Base_Type *value_ptr,
2047 int value_size,
2048 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
2049 int template_size,
2050 match_function_t match_function,
2051 boolean legacy)
2052 {
2053 if (value_ptr == NULL || value_size < 0 ||
2054 template_ptr == NULL || template_size < 0 ||
2055 template_ptr->get_selection() != SPECIFIC_VALUE)
2056 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
2057
2058 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
2059 // use the simplified algorithm if the template does not contain permutation
2060 if (nof_permutations == 0)
2061 return match_array(value_ptr, value_size,
2062 template_ptr, template_size, match_function, legacy);
2063 // use 'set of' matching if all template elements are grouped into one
2064 // permutation
2065 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
2066 template_ptr->get_permutation_end(0) ==
2067 (unsigned int)(template_size - 1))
2068 return match_set_of(value_ptr, value_size, template_ptr, template_size,
2069 match_function, legacy);
2070
2071 unsigned int shift_size = 0;
2072 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
2073 0, template_size, 0, match_function, shift_size, legacy) == SUCCESS;
2074 }
2075
2076 #endif
This page took 0.144662 seconds and 5 git commands to generate.