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