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