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