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