Sync with 5.4.2
[deliverable/titan.core.git] / xsdconvert / SimpleType.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "SimpleType.hh"
9
10 #include "GeneralFunctions.hh"
11
12 #include "TTCN3ModuleInventory.hh"
13 #include "TTCN3Module.hh"
14 #include "ComplexType.hh"
15
16 extern bool g_flag_used;
17 extern bool h_flag_used;
18
19 SimpleType::SimpleType(XMLParser * a_parser, TTCN3Module * a_module, ConstructType a_construct)
20 : RootType(a_parser, a_module, a_construct)
21 , builtInBase()
22 , length(this)
23 , pattern(this)
24 , enumeration(this)
25 , whitespace(this)
26 , value(this)
27 , element_form_as(notset)
28 , attribute_form_as(notset)
29 , mode(noMode)
30 , outside_reference()
31 , in_name_only(false)
32 , fromRef(false)
33 , xsdtype(n_NOTSET)
34 , isOptional(false)
35 , substitutionGroup(empty_string)
36 , subsGroup(NULL)
37 , typeSubsGroup(NULL)
38 , addedToTypeSubstitution(false)
39 , block(not_set)
40 , parent(NULL) {
41 }
42
43 SimpleType::SimpleType(const SimpleType& other)
44 : RootType(other)
45 , builtInBase(other.builtInBase)
46 , length(other.length)
47 , pattern(other.pattern)
48 , enumeration(other.enumeration)
49 , whitespace(other.whitespace)
50 , value(other.value)
51 , element_form_as(other.element_form_as)
52 , attribute_form_as(other.attribute_form_as)
53 , mode(other.mode)
54 , outside_reference(other.outside_reference)
55 , in_name_only(other.in_name_only)
56 , fromRef(other.fromRef)
57 , xsdtype(other.xsdtype)
58 , isOptional(other.isOptional)
59 , substitutionGroup(other.substitutionGroup)
60 , subsGroup(other.subsGroup)
61 , typeSubsGroup(other.typeSubsGroup)
62 , addedToTypeSubstitution(other.addedToTypeSubstitution)
63 , block(other.block)
64 , parent(NULL) {
65 length.parent = this;
66 pattern.parent = this;
67 enumeration.parent = this;
68 whitespace.p_parent = this;
69 value.parent = this;
70 }
71
72 void SimpleType::loadWithValues() {
73 const XMLParser::TagAttributes & atts = parser->getActualTagAttributes();
74 switch (parser->getActualTagName()) {
75 case n_restriction:
76 type.upload(atts.base);
77 setReference(atts.base);
78 mode = restrictionMode;
79 break;
80 case n_list:
81 type.upload(atts.itemType);
82 setReference(atts.itemType);
83 minOccurs = 0;
84 maxOccurs = ULLONG_MAX;
85 addVariant(V_list);
86 mode = listMode;
87 break;
88 case n_union:
89 { // generating complextype from simpletype
90 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagUnion);
91 new_complextype->loadWithValues();
92 break;
93 }
94 case n_element:
95 name.upload(atts.name);
96 type.upload(atts.type);
97 setReference(atts.type, true);
98 if (!atts.nillable) {
99 applyDefaultAttribute(atts.default_);
100 applyFixedAttribute(atts.fixed);
101 }
102 applyAbstractAttribute(atts.abstract);
103 applySubstitionGroupAttribute(atts.substitionGroup);
104 applyBlockAttribute(atts.block);
105 //This shall be the last instruction always
106 applyNillableAttribute(atts.nillable);
107 break;
108 case n_attribute:
109 name.upload(atts.name);
110 type.upload(atts.type);
111 xsdtype = n_attribute;
112 setReference(atts.type, true);
113 applyDefaultAttribute(atts.default_);
114 applyFixedAttribute(atts.fixed);
115 break;
116 case n_simpleType:
117 name.upload(atts.name);
118 break;
119 case n_complexType:
120 { // generating complextype from simpletype
121 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagComplexType);
122 new_complextype->loadWithValues();
123 break;
124 }
125 case n_length:
126 if (mode == listMode) {
127 minOccurs = strtoull(atts.value.c_str(), NULL, 0);
128 maxOccurs = strtoull(atts.value.c_str(), NULL, 0);
129 break;
130 }
131 length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
132 length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
133 length.modified = true;
134 break;
135 case n_minLength:
136 if (mode == listMode) {
137 minOccurs = strtoull(atts.value.c_str(), NULL, 0);
138 break;
139 }
140 length.facet_minLength = strtoull(atts.value.c_str(), NULL, 0);
141 length.modified = true;
142 break;
143 case n_maxLength:
144 if (mode == listMode) {
145 maxOccurs = strtoull(atts.value.c_str(), NULL, 0);
146 break;
147 }
148 length.facet_maxLength = strtoull(atts.value.c_str(), NULL, 0);
149 length.modified = true;
150 break;
151 case n_pattern:
152 pattern.facet = atts.value;
153 pattern.modified = true;
154 break;
155 case n_enumeration:
156 enumeration.facets.push_back(atts.value);
157 enumeration.modified = true;
158 break;
159 case n_whiteSpace:
160 whitespace.facet = atts.value;
161 whitespace.modified = true;
162 break;
163 case n_minInclusive:
164 if (atts.value == "NaN") {
165 value.not_a_number = true;
166 } else if (atts.value == "-INF") {
167 value.facet_minInclusive = -DBL_MAX;
168 } else if (atts.value == "INF") {
169 value.facet_minInclusive = DBL_MAX;
170 } else {
171 value.facet_minInclusive = stringToLongDouble(atts.value.c_str());
172 }
173 value.modified = true;
174 break;
175 case n_maxInclusive:
176 if (atts.value == "NaN") {
177 value.not_a_number = true;
178 } else if (atts.value == "-INF") {
179 value.facet_maxInclusive = -DBL_MAX;
180 } else if (atts.value == "INF") {
181 value.facet_maxInclusive = DBL_MAX;
182 } else {
183 value.facet_maxInclusive = stringToLongDouble(atts.value.c_str());
184 }
185 value.modified = true;
186 break;
187 case n_minExclusive:
188 if (atts.value == "NaN") {
189 setInvisible();
190 } else if (atts.value == "-INF") {
191 value.facet_minExclusive = -DBL_MAX;
192 } else if (atts.value == "INF") {
193 setInvisible();
194 } else {
195 value.facet_minExclusive = stringToLongDouble(atts.value.c_str());
196 }
197 value.modified = true;
198 value.lowerExclusive = true;
199 break;
200 case n_maxExclusive:
201 if (atts.value == "NaN") {
202 setInvisible();
203 } else if (atts.value == "-INF") {
204 setInvisible();
205 } else if (atts.value == "INF") {
206 value.facet_maxExclusive = DBL_MAX;
207 } else {
208 value.facet_maxExclusive = stringToLongDouble(atts.value.c_str());
209 }
210 value.modified = true;
211 value.upperExclusive = true;
212 break;
213 case n_totalDigits:
214 value.facet_totalDigits = strtoul(atts.value.c_str(), NULL, 0);
215 value.modified = true;
216 break;
217 case n_fractionDigits:
218 //addVariant(V_fractionDigits, atts.value);
219 break;
220 case n_label:
221 addComment(Mstring("LABEL:"));
222 break;
223 case n_definition:
224 addComment(Mstring("DEFINITION:"));
225 break;
226 default:
227 break;
228 }
229 }
230
231 void SimpleType::applyDefaultAttribute(const Mstring& default_value) {
232 if (!default_value.empty()) {
233 value.default_value = default_value;
234 const Mstring nameT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
235 //Not supported for hexBinary and base64Binary
236 if (nameT != "hexBinary" && nameT != "base64Binary") {
237 addVariant(V_defaultForEmpty, default_value);
238 }
239 }
240 }
241
242 void SimpleType::applyFixedAttribute(const Mstring& fixed_value) {
243 if (!fixed_value.empty()) {
244 value.fixed_value = fixed_value;
245 value.modified = true;
246 const Mstring nameT = type.originalValueWoPrefix.getValueWithoutPrefix(':');
247 //Not supported for hexBinary and base64Binary
248 if (nameT != "hexBinary" && nameT != "base64Binary") {
249 addVariant(V_defaultForEmpty, fixed_value);
250 }
251 }
252 }
253
254 void SimpleType::applyNillableAttribute(const bool nillable) {
255 if (nillable) {
256 ComplexType * new_complextype = new ComplexType(*this, ComplexType::fromTagNillable); // generating complextype from simpletype
257 new_complextype->loadWithValues();
258 }
259 }
260
261 void SimpleType::applyAbstractAttribute(const bool abstract_value) {
262 if (abstract_value) {
263 addVariant(V_abstract);
264 }
265 }
266
267 void SimpleType::applySubstitionGroupAttribute(const Mstring& substitution_group){
268 if(!substitution_group.empty()){
269 substitutionGroup = substitution_group;
270 }
271 }
272
273 void SimpleType::applyBlockAttribute(const BlockValue block_){
274 if(block_ == not_set){
275 block = getModule()->getBlockDefault();
276 }else {
277 block = block_;
278 }
279 }
280
281 void SimpleType::addToSubstitutions(){
282 if(!g_flag_used || substitutionGroup.empty()){
283 return;
284 }
285 SimpleType * st_ = (SimpleType*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup, want_BOTH);
286 if(st_ == NULL){
287 printError(module->getSchemaname(), name.convertedValue,
288 "Reference for a non-defined type: " + substitutionGroup);
289 TTCN3ModuleInventory::getInstance().incrNumErrors();
290 return;
291 }
292 SimpleType * st = (SimpleType*)st_;
293 if(st->getSubstitution() != NULL){
294 st = st->getSubstitution();
295 }
296
297 st->referenceResolving();
298 substitutionGroup = empty_string;
299 //Simpletype
300 if(st->subsGroup == NULL){
301 ComplexType * head_element = new ComplexType(*st, ComplexType::fromTagSubstitution);
302 for(List<SimpleType*>::iterator simpletype = st->nameDepList.begin(); simpletype; simpletype = simpletype->Next){
303 head_element->getNameDepList().push_back(simpletype->Data);
304 }
305 st->nameDepList.clear();
306 st->getModule()->addMainType(head_element);
307 head_element->addVariant(V_untagged);
308 head_element->addSubstitution(st);
309 head_element->addSubstitution(this);
310 //if st->subsGroup == this, then it is a generated subs group
311 st->subsGroup = head_element;
312 st->setInvisible();
313 }else {
314 st->subsGroup->addSubstitution(this);
315 }
316 }
317
318 void SimpleType::addToTypeSubstitutions() {
319 //If the user did not request type substitution generation or
320 //the type is already added to type substitution
321 if(!h_flag_used || addedToTypeSubstitution){
322 return;
323 }
324 //Only available if it is a restricion or extension
325 if(mode != extensionMode && mode != restrictionMode){
326 return;
327 }
328 //Only top level complexTypes or simpleTypes, ergo no elements
329 if(parent != NULL || hasVariant(Mstring("\"element\""))){
330 return;
331 }
332
333 //It would be nice if here outside_reference.resolved to everything
334 bool newST = false;
335 SimpleType * st = (SimpleType*)outside_reference.get_ref();
336 if(st == NULL && !isBuiltInType(type.convertedValue)){
337 //Not even a reference, and not a built in type
338 return;
339 }else if(st == NULL && isBuiltInType(type.convertedValue)){
340 st = new SimpleType(parser, module, construct);
341 st->type.upload(type.convertedValue);
342 st->name.upload(type.convertedValue);
343 st->typeSubsGroup = findBuiltInTypeInStoredTypeSubstitutions(type.convertedValue);
344 outside_reference.set_resolved(st);
345 //Add this decoy type to the maintypes -> module will free st
346 //st->setInvisible();
347 module->addMainType(st);
348 newST = true;
349 }
350
351 addedToTypeSubstitution = true;
352 st->addToTypeSubstitutions();
353 //If type substitution is NULL then we need to create the union
354 if(st->getTypeSubstitution() == NULL){
355 ComplexType * head_element = new ComplexType(*st, ComplexType::fromTypeSubstitution);
356 head_element->getNameDepList().clear();
357 for(List<SimpleType*>::iterator simpletype = st->nameDepList.begin(), nextST; simpletype; simpletype = nextST){
358 nextST = simpletype->Next;
359 //Don't add if it is in a type substitution
360 if(simpletype->Data->getTypeSubstitution() == NULL){
361 head_element->getNameDepList().push_back(simpletype->Data);
362 st->getNameDepList().remove(simpletype);
363 }
364 }
365
366 st->getModule()->addMainType(head_element);
367 head_element->addVariant(V_useType);
368 //For cascading type substitution
369 if(st->outside_reference.get_ref() != NULL && ((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution() != NULL){
370 head_element->setParentTypeSubsGroup(((ComplexType*)st->outside_reference.get_ref())->getTypeSubstitution());
371 }
372 head_element->addTypeSubstitution(st);
373 head_element->addTypeSubstitution(this);
374 bool found = false;
375 //Check to find if there was already an element reference with this type
376 for(List<typeNameDepList>::iterator str = module->getElementTypes().begin(); str; str = str->Next){
377 Mstring prefix = str->Data.type.getPrefix(':');
378 Mstring value_ = str->Data.type.getValueWithoutPrefix(':');
379
380 if((value_ == st->getName().convertedValue.getValueWithoutPrefix(':') && prefix == module->getTargetNamespaceConnector()) ||
381 (isBuiltInType(value_) && !isBuiltInType(st->getType().convertedValue) && value_ == st->getType().convertedValue && prefix == module->getTargetNamespaceConnector())){
382 //Push the namedeplist
383 for(List<SimpleType*>::iterator simpletype = str->Data.nameDepList.begin(); simpletype; simpletype = simpletype->Next){
384 head_element->getNameDepList().push_back(simpletype->Data);
385 }
386 found = true;
387 str->Data.typeSubsGroup = head_element;
388 break;
389 }
390 }
391 if(!found){
392 head_element->setInvisible();
393 }
394 st->typeSubsGroup = head_element;
395 st->getModule()->addStoredTypeSubstitution(head_element);
396 }else {
397 st->getTypeSubstitution()->addTypeSubstitution(this);
398 }
399 if(newST){
400 //Make the decoy invisible
401 st->setInvisible();
402 }
403 }
404
405 void SimpleType::collectElementTypes(SimpleType* found_ST, ComplexType* found_CT){
406 //Only if type substitution is enabled and it is a top level(simpletype) element or
407 //it is a not top level element(complextype)
408 if(h_flag_used && (hasVariant(Mstring("\"element\"")) || xsdtype == n_element)){
409 SimpleType * st = NULL, *nameDep = NULL;
410 Mstring uri, value_, type_;
411 if(found_ST != NULL || found_CT != NULL){
412 // st := found_ST or found_CT, which is not null
413 st = found_ST != NULL ? found_ST : found_CT;
414 uri = outside_reference.get_uri();
415 value_ = outside_reference.get_val();
416 type_ = value_;
417 }else if(isBuiltInType(type.convertedValue)){
418 st = this;
419 uri = module->getTargetNamespace();
420 value_ = type.convertedValue;
421 if(outside_reference.empty()){
422 type_ = value_;
423 nameDep = this;
424 }else {
425 type_ = outside_reference.get_val();
426 }
427 }else {
428 //It is not possible to reach here (should be)
429 return;
430 }
431 type_ = type_.getValueWithoutPrefix(':');
432 bool found = false;
433 const Mstring typeSubsName = value_ + Mstring("_derivations");
434 //Find if we already have a substitution type to this element reference
435 for(List<ComplexType*>::iterator complex = st->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){
436
437 if(uri == st->getModule()->getTargetNamespace() && typeSubsName == complex->Data->getName().convertedValue){
438 complex->Data->setVisible();
439 if(st->getXsdtype() != n_NOTSET && this == st){ //otherwise records would be renamed too
440 complex->Data->addToNameDepList(st);
441 ((ComplexType*)st)->setNameDep(nameDep);
442 }
443 found = true;
444 break;
445 }
446 }
447 //Add the reference, to future possible type substitution
448 if(!found){
449 Mstring prefix = st->getModule()->getTargetNamespaceConnector();
450 if(prefix != empty_string){
451 prefix += ":";
452 }
453 st->getModule()->addElementType(prefix + type_, nameDep);
454 }
455 }
456 }
457
458 ComplexType * SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring& builtInType){
459 const Mstring typeSubsName = builtInType.getValueWithoutPrefix(':') + Mstring("_derivations");
460 for(List<ComplexType*>::iterator complex = module->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next){
461 if(typeSubsName == complex->Data->getName().convertedValue){
462 return complex->Data;
463 }
464 }
465 return NULL;
466 }
467
468
469 void SimpleType::setReference(const Mstring& ref, bool only_name_dependency) {
470 if (ref.empty()) {
471 return;
472 }
473 if (isBuiltInType(ref)) {
474 builtInBase = ref.getValueWithoutPrefix(':');
475 if (name.convertedValue.empty()) {
476 name.upload(ref);
477 }
478 if (type.convertedValue.empty() || type.convertedValue == "anySimpleType") {
479 type.upload(ref.getValueWithoutPrefix(':'));
480 }
481 fromRef = true;
482 return;
483 }
484
485 Mstring refPrefix = ref.getPrefix(':');
486 Mstring refValue = ref.getValueWithoutPrefix(':');
487 Mstring refUri;
488 // Find the URI amongst the known namespace URIs
489 List<NamespaceType>::iterator declNS;
490 for (declNS = module->getDeclaredNamespaces().begin(); declNS; declNS = declNS->Next) {
491 if (refPrefix == declNS->Data.prefix) {
492 refUri = declNS->Data.uri;
493 break;
494 }
495 }
496
497 // FIXME: can this part be moved above the search ?
498 if (refUri.empty()) { // not found
499 if (refPrefix == "xml") {
500 refUri = "http://www.w3.org/XML/1998/namespace";
501 } else if (refPrefix == "xmlns") {
502 refUri = "http://www.w3.org/2000/xmlns";
503 } else if (refPrefix.empty() && module->getTargetNamespace() == "NoTargetNamespace") {
504 refUri = "NoTargetNamespace";
505 }
506 }
507
508 if (refUri.empty()) { // something is incorrect - unable to find the uri to the given prefix
509 if (refPrefix.empty()) {
510 printError(module->getSchemaname(), parser->getActualLineNumber(),
511 Mstring("The absent namespace must be imported because "
512 "it is not the same as the target namespace of the current schema."));
513 parser->incrNumErrors();
514 return;
515 } else {
516 printError(module->getSchemaname(), parser->getActualLineNumber(),
517 "The value \'" + ref + "\' is incorrect: "
518 "A namespace prefix does not denote any URI.");
519 parser->incrNumErrors();
520 return;
521 }
522 }
523
524 if (only_name_dependency) {
525 in_name_only = true;
526 }
527
528 outside_reference.load(refUri, refValue, &declNS->Data);
529 }
530
531 void SimpleType::referenceResolving() {
532 if (outside_reference.empty() || outside_reference.is_resolved()){
533 addToTypeSubstitutions();
534 collectElementTypes();
535 }
536 if(outside_reference.empty() && substitutionGroup.empty()) return;
537 if (outside_reference.is_resolved()) return;
538
539 if(!outside_reference.empty()){
540 SimpleType * found_ST = static_cast<SimpleType*> (
541 TTCN3ModuleInventory::getInstance().lookup(this, want_ST));
542 ComplexType * found_CT = static_cast<ComplexType*> (
543 TTCN3ModuleInventory::getInstance().lookup(this, want_CT));
544 // It _is_ possible to find both
545 collectElementTypes(found_ST, found_CT);
546 if (found_ST != NULL) {
547 if (!found_ST->outside_reference.empty() && !found_ST->outside_reference.is_resolved() && found_ST != this) {
548 found_ST->referenceResolving();
549 if(!found_ST->outside_reference.is_resolved()){
550 found_ST->outside_reference.set_resolved(NULL);
551 }
552 }
553 referenceForST(found_ST);
554 addToTypeSubstitutions();
555 if (!isBuiltInType(type.convertedValue)) {
556 found_ST->addToNameDepList(this);
557 }
558 } else if (found_CT != NULL) {
559 referenceForCT(found_CT);
560 addToTypeSubstitutions();
561 if (!isBuiltInType(type.convertedValue)) {
562 found_CT->addToNameDepList(this);
563 }
564 }else {
565 printError(module->getSchemaname(), name.convertedValue,
566 "Reference for a non-defined type: " + outside_reference.repr());
567 TTCN3ModuleInventory::getInstance().incrNumErrors();
568 outside_reference.set_resolved(NULL);
569 }
570 addToSubstitutions();
571 }else {
572 addToSubstitutions();
573 }
574 }
575
576 void SimpleType::referenceForST(SimpleType * found_ST) {
577 outside_reference.set_resolved(found_ST);
578
579 if (in_name_only)
580 return;
581
582 if (construct == c_element)
583 return;
584
585 if (mode == listMode)
586 return;
587
588 if (!found_ST->builtInBase.empty()) {
589 builtInBase = found_ST->builtInBase;
590 }
591
592 length.applyReference(found_ST->length);
593 pattern.applyReference(found_ST->pattern);
594 enumeration.applyReference(found_ST->enumeration);
595 whitespace.applyReference(found_ST->whitespace);
596 value.applyReference(found_ST->value);
597
598 mode = found_ST->mode;
599 if (found_ST->mode != listMode) {
600 type.upload(found_ST->getType().convertedValue);
601 }
602 }
603
604 void SimpleType::referenceForCT(ComplexType * found_CT) {
605 outside_reference.set_resolved(found_CT);
606
607 if (in_name_only)
608 return;
609
610 // Section 7.5.3 Example5
611 if (found_CT->getType().convertedValue == Mstring("union") && mode == restrictionMode) {
612 for (List<Mstring>::iterator facet = enumeration.facets.begin(); facet; facet = facet->Next) {
613 enumeration.items_misc.push_back(facet->Data);
614 }
615 }
616 size_t value_size = value.items_with_value.size(); //Used to check changes
617 enumeration.modified = false;
618 for (List<Mstring>::iterator itemMisc = enumeration.items_misc.begin(); itemMisc; itemMisc = itemMisc->Next) {
619 size_t act_size = value.items_with_value.size(); //Used to detect if field did not match any field
620 for (List<ComplexType*>::iterator field = found_CT->complexfields.begin(); field; field = field->Next) {
621 if (isIntegerType(field->Data->getType().convertedValue)) {
622 int read_chars = -1;
623 int val = -1;
624 sscanf(itemMisc->Data.c_str(), "%d%n", &val, &read_chars);
625 if ((size_t) read_chars == itemMisc->Data.size()) {
626 expstring_t tmp_string = mprintf("{%s:=%d}",
627 field->Data->getName().convertedValue.c_str(), val);
628 value.items_with_value.push_back(Mstring(tmp_string));
629 break;
630 }
631 }
632
633 if (isFloatType(field->Data->getType().convertedValue)) {
634 int read_chars = -1;
635 float val = -1.0;
636 sscanf(itemMisc->Data.c_str(), "%f%n", &val, &read_chars);
637 if ((size_t) read_chars == itemMisc->Data.size()) {
638 expstring_t tmp_string = mprintf("{%s:=%f}",
639 field->Data->getName().convertedValue.c_str(), val);
640 value.items_with_value.push_back(Mstring(tmp_string));
641 break;
642 }
643 }
644
645 if (isTimeType(field->Data->getType().convertedValue)) {
646 if (matchDates(itemMisc->Data.c_str(), field->Data->getType().originalValueWoPrefix.c_str())) {
647 expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
648 field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
649 value.items_with_value.push_back(Mstring(tmp_string));
650 break;
651 }
652 }
653
654 if (isStringType(field->Data->getType().convertedValue)) {
655 expstring_t tmp_string = mprintf("{%s:=\"%s\"}",
656 field->Data->getName().convertedValue.c_str(), itemMisc->Data.c_str());
657 value.items_with_value.push_back(Mstring(tmp_string));
658 break;
659 }
660 }
661
662 if (act_size == value.items_with_value.size()) {
663 printWarning(getModule()->getSchemaname(), getName().convertedValue,
664 Mstring("The following enumeration did not match any field: ") + itemMisc->Data + Mstring("."));
665 TTCN3ModuleInventory::getInstance().incrNumWarnings();
666 }
667 }
668
669 if (value_size != value.items_with_value.size()) {
670 value.modified = true;
671 }
672 }
673
674 void SimpleType::nameConversion(NameConversionMode conversion_mode, const List<NamespaceType> & ns) {
675 if(!visible) return;
676 switch (conversion_mode) {
677 case nameMode:
678 nameConversion_names();
679 break;
680 case typeMode:
681 nameConversion_types(ns);
682 break;
683 case fieldMode:
684 break;
685 }
686 }
687
688 void SimpleType::nameConversion_names() {
689 Mstring res, var(module->getTargetNamespace());
690 XSDName2TTCN3Name(name.convertedValue, TTCN3ModuleInventory::getInstance().getTypenames(), type_name, res, var);
691 name.convertedValue = res;
692 addVariant(V_onlyValue, var);
693 for (List<SimpleType*>::iterator st = nameDepList.begin(); st; st = st->Next) {
694 st->Data->setTypeValue(res);
695 }
696 }
697
698 void SimpleType::nameConversion_types(const List<NamespaceType> & ns) {
699 if (type.convertedValue == "record" || type.convertedValue == "set"
700 || type.convertedValue == "union" || type.convertedValue == "enumerated") return;
701
702 Mstring prefix = type.convertedValue.getPrefix(':');
703 Mstring value_str = type.convertedValue.getValueWithoutPrefix(':');
704
705 Mstring uri;
706 for (List<NamespaceType>::iterator namesp = ns.begin(); namesp; namesp = namesp->Next) {
707 if (prefix == namesp->Data.prefix) {
708 uri = namesp->Data.uri;
709 break;
710 }
711 }
712
713 QualifiedName tmp(uri, value_str);
714
715 QualifiedNames::iterator origTN = TTCN3ModuleInventory::getInstance().getTypenames().begin();
716 for (; origTN; origTN = origTN->Next) {
717 if (tmp == origTN->Data) {
718 QualifiedName tmp_name(module->getTargetNamespace(), name.convertedValue);
719 if (tmp_name == origTN->Data)
720 continue; // get a new type name
721 else
722 break;
723 }
724 }
725 if (origTN != NULL) {
726 setTypeValue(origTN->Data.name);
727 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
728 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
729 // otherwise the new value is always the same as the old.
730 } else {
731 Mstring res, var;
732 XSDName2TTCN3Name(value_str, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name, res, var);
733 setTypeValue(res);
734 }
735 }
736
737 void SimpleType::finalModification() {
738 value.applyFacets();
739 length.applyFacets();
740 pattern.applyFacet();
741 whitespace.applyFacet();
742 enumeration.applyFacets();
743
744 if (module->getElementFormDefault() == qualified &&
745 element_form_as == unqualified) {
746 addVariant(V_formAs, Mstring("unqualified"));
747 } else if (module->getElementFormDefault() != qualified &&
748 element_form_as == qualified) {
749 addVariant(V_formAs, Mstring("qualified"));
750 }
751
752 if (module->getAttributeFormDefault() == qualified &&
753 attribute_form_as == unqualified) {
754 addVariant(V_formAs, Mstring("unqualified"));
755 } else if (module->getAttributeFormDefault() != qualified &&
756 attribute_form_as == qualified) {
757 addVariant(V_formAs, Mstring("qualified"));
758 }
759
760 if (type.originalValueWoPrefix == Mstring("boolean")) {
761 addVariant(V_onlyValueHidden, Mstring("\"text 'false' as '0'\""));
762 addVariant(V_onlyValueHidden, Mstring("\"text 'true' as '1'\""));
763 }
764
765 isOptional = isOptional || (minOccurs == 0 && maxOccurs == 0);
766
767 // If the type name is the same as the identifier then we have to prefix it
768 // with the module identifier.
769 if (type.convertedValue == name.convertedValue && !outside_reference.empty()) {
770 List<const TTCN3Module*>::iterator import_module = module->getImportedModules().begin();
771 for (; import_module; import_module = import_module->Next) {
772 if (import_module->Data->getTargetNamespace() == outside_reference.get_uri()) {
773 type.upload(import_module->Data->getModulename() + Mstring(".") + type.convertedValue);
774 break;
775 }
776 }
777 }
778 }
779
780 bool SimpleType::hasUnresolvedReference() {
781 if (!outside_reference.empty() && !outside_reference.is_resolved()) {
782 return true;
783 } else {
784 return false;
785 }
786 }
787
788 void SimpleType::applyRefAttribute(const Mstring& ref_value) {
789 if (!ref_value.empty()) {
790 setReference(ref_value);
791 fromRef = true;
792 }
793 }
794
795 void SimpleType::printToFile(FILE * file) {
796 if (!visible) {
797 return;
798 }
799
800 printComment(file);
801
802 fputs("type ", file);
803 if(enumeration.modified && hasVariant(Mstring("\"list\""))){
804 printMinOccursMaxOccurs(file, false);
805 fprintf(file, "enumerated\n{\n");
806 enumeration.sortFacets();
807 enumeration.printToFile(file);
808 fprintf(file, "\n} %s", name.convertedValue.c_str());
809 } else if (enumeration.modified) {
810 if (isFloatType(builtInBase)) {
811 fprintf(file, "%s %s (", type.convertedValue.c_str(), name.convertedValue.c_str());
812 enumeration.sortFacets();
813 enumeration.printToFile(file);
814 fputc(')', file);
815 } else {
816 fprintf(file, "enumerated %s\n{\n", name.convertedValue.c_str());
817 enumeration.sortFacets();
818 enumeration.printToFile(file);
819 fputs("\n}", file);
820 }
821 } else {
822 printMinOccursMaxOccurs(file, false);
823
824 int multiplicity = multi(module, outside_reference, this);
825 const RootType *type_ref = outside_reference.get_ref();
826 if ((multiplicity > 1) && type_ref
827 && type_ref->getModule() != module) {
828 fprintf(file, "%s.", type_ref->getModule()->getModulename().c_str());
829 }
830
831 fprintf(file, "%s %s",
832 type.convertedValue.c_str(), name.convertedValue.c_str());
833 pattern.printToFile(file);
834 value.printToFile(file);
835 length.printToFile(file);
836 }
837 enumeration.insertVariants();
838 printVariant(file);
839 fputs(";\n\n\n", file);
840 }
841
842 void SimpleType::dump(unsigned int depth) const {
843 static const char *modes[] = {
844 "", "restriction", "extension", "list"
845 };
846 fprintf(stderr, "%*s SimpleType '%s' -> '%s' at %p\n", depth * 2, "",
847 name.originalValueWoPrefix.c_str(), name.convertedValue.c_str(),
848 (const void*) this);
849 fprintf(stderr, "%*s type '%s' -> '%s'\n", depth * 2, "",
850 type.originalValueWoPrefix.c_str(), type.convertedValue.c_str());
851
852 if (mode != noMode) {
853 fprintf(stderr, "%*s %s, base='%s'\n", depth * 2, "", modes[mode], builtInBase.c_str());
854 }
855
856 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
857 // reference_for_other.c_str(), name_dependency.c_str());
858 }
859
860 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
861
862 LengthType::LengthType(SimpleType * a_simpleType)
863 : parent(a_simpleType)
864 , modified(false)
865 , facet_minLength(0)
866 , facet_maxLength(ULLONG_MAX)
867 , lower(0)
868 , upper(ULLONG_MAX) {
869 }
870
871 void LengthType::applyReference(const LengthType & other) {
872 if (!modified) modified = other.modified;
873 if (other.facet_minLength > facet_minLength) facet_minLength = other.facet_minLength;
874 if (other.facet_maxLength < facet_maxLength) facet_maxLength = other.facet_maxLength;
875 }
876
877 void LengthType::applyFacets() // only for string types and list types without QName
878 {
879 if (!modified) return;
880
881 switch (parent->getMode()) {
882 case SimpleType::restrictionMode:
883 {
884 const Mstring & base = parent->getBuiltInBase();
885 if ((isStringType(base) || (isSequenceType(base) && base != "QName") || isAnyType(base)) || base.empty()) {
886 lower = facet_minLength;
887 upper = facet_maxLength;
888 } else {
889 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
890 Mstring("Length restriction is not supported on type '") + base + Mstring("'."));
891 TTCN3ModuleInventory::getInstance().incrNumWarnings();
892 }
893 break;
894 }
895 case SimpleType::extensionMode:
896 case SimpleType::listMode:
897 lower = facet_minLength;
898 upper = facet_maxLength;
899 break;
900 case SimpleType::noMode:
901 break;
902 }
903 if (lower > upper) {
904 printError(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
905 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
906 TTCN3ModuleInventory::getInstance().incrNumErrors();
907 return;
908 }
909 }
910
911 void LengthType::printToFile(FILE * file) const {
912 if (!modified) return;
913 if (parent->getEnumeration().modified) return;
914
915 if (lower == upper) {
916 fprintf(file, " length(%llu)", lower);
917 } else {
918 fprintf(file, " length(%llu .. ", lower);
919
920 if (upper == ULLONG_MAX) {
921 fputs("infinity", file);
922 } else {
923 fprintf(file, "%llu", upper);
924 }
925
926 fputc(')', file);
927 }
928 }
929
930 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
931
932 PatternType::PatternType(SimpleType * a_simpleType)
933 : parent(a_simpleType)
934 , modified(false)
935 , facet()
936 , value() {
937 }
938
939 void PatternType::applyReference(const PatternType & other) {
940 if (!modified) modified = other.modified;
941 if (facet.empty()) facet = other.facet;
942 }
943
944 void PatternType::applyFacet() // only for time types and string types without hexBinary
945 {
946 if (!modified) return;
947
948 const Mstring & base = parent->getBuiltInBase();
949 if (((isStringType(base) && base != "hexBinary") || isTimeType(base) || isAnyType(base)) || base.empty()) {
950 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
951 // FIXME a proper scanner is needed, e.g. from flex
952 int charclass = 0;
953 for (size_t i = 0; i != facet.size(); ++i) {
954 char c = facet[i];
955 switch (c) {
956 case '(':
957 value += charclass ? "\\("
958 : "(";
959 break;
960 case ')':
961 value += charclass ? "\\)"
962 : ")";
963 break;
964 case '/':
965 value += '/';
966 break;
967 case '^':
968 value += charclass ? "\\^"
969 : "^";
970 break;
971 case '[':
972 value += c;
973 ++charclass;
974 break;
975 case ']':
976 value += c;
977 --charclass;
978 break;
979 case '.': // any character
980 value += charclass ? '.'
981 : '?';
982 break;
983 case '*': // 0 or more
984 value += '*'; //#(0,)
985 break;
986 case '+':
987 value += '+'; //#(1,)
988 break;
989 case '?':
990 value += charclass ? "?"
991 : "#(0,1)";
992 break;
993 case '"':
994 value += "\"\"";
995 break;
996 case '{':
997 {
998 if (charclass == 0) {
999 Mstring s;
1000 int k = 1;
1001 while (facet[i + k] != '}') {
1002 s += facet[i + k];
1003 ++k;
1004 }
1005 int a, b, match;
1006 match = sscanf(s.c_str(), "%i,%i", &a, &b);
1007 if (match == 1 || match == 2) {
1008 value += "#(";
1009 value += s;
1010 value += ')';
1011 i = i + k;
1012 } else {
1013 value += "\\{";
1014 }
1015 } else {
1016 value += "\\{";
1017 }
1018 break;
1019 }
1020 case '}':
1021 value += charclass ? "\\}"
1022 : "}";
1023 break;
1024 case '\\':
1025 {
1026 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
1027 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
1028 char cn = facet[i + 1];
1029 switch (cn) {
1030 case 'c':
1031 value += charclass ? "\\w\\d.\\-_:"
1032 : "[\\w\\d.\\-_:]";
1033 break;
1034 case 'C':
1035 value += charclass ? "^\\w\\d.\\-_:"
1036 : "[^\\w\\d.\\-_:]";
1037 break;
1038 case 'D':
1039 value += charclass ? "^\\d"
1040 : "[^\\d]";
1041 break;
1042 case 'i':
1043 value += charclass ? "\\w\\d:"
1044 : "[\\w\\d:]";
1045 break;
1046 case 'I':
1047 value += charclass ? "^\\w\\d:"
1048 : "[^\\w\\d:]";
1049 break;
1050 case 's':
1051 value += charclass ? "\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1052 : "[\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1053 break;
1054 case 'S':
1055 value += charclass ? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1056 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1057 break;
1058 case 'W':
1059 value += charclass ? "^\\w"
1060 : "[^\\w]";
1061 break;
1062 case 'p':
1063 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1064 Mstring("Character categories and blocks are not supported."));
1065 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1066 parent->addComment(
1067 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
1068 value.clear();
1069 return;
1070
1071 case '.':
1072 value += '.';
1073 break;
1074 default:
1075 // backslash + another: pass unmodified; this also handles \d and \w
1076 value += c;
1077 value += cn;
1078 break;
1079 }
1080 ++i;
1081 break;
1082 }
1083 case '&':
1084 if (facet[i + 1] == '#') { // &#....;
1085 Mstring s;
1086 int k = 2;
1087 while (facet[i + k] != ';') {
1088 s += facet[i + k];
1089 ++k;
1090 }
1091 long long int d = atoll(s.c_str());
1092 if (d < 0 || d > 2147483647) {
1093 printError(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1094 Mstring("Invalid unicode character."));
1095 TTCN3ModuleInventory::getInstance().incrNumErrors();
1096 }
1097 unsigned char group = (d >> 24) & 0xFF;
1098 unsigned char plane = (d >> 16) & 0xFF;
1099 unsigned char row = (d >> 8) & 0xFF;
1100 unsigned char cell = d & 0xFF;
1101
1102 expstring_t res = mprintf("\\q{%d, %d, %d, %d}", group, plane, row, cell);
1103 value += res;
1104 Free(res);
1105 i = i + k;
1106 }
1107 // else fall through
1108 default: //just_copy:
1109 value += c;
1110 break;
1111 } // switch(c)
1112 } // next i
1113 } else {
1114 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1115 Mstring("Pattern restriction is not supported on type '") + base + Mstring("'."));
1116 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1117 }
1118 }
1119
1120 void PatternType::printToFile(FILE * file) const {
1121 if (!modified || value.empty()) return;
1122 if (parent->getEnumeration().modified) return;
1123
1124 fprintf(file, " (pattern \"%s\")", value.c_str());
1125 }
1126
1127 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1128
1129 EnumerationType::EnumerationType(SimpleType * a_simpleType)
1130 : parent(a_simpleType)
1131 , modified(false)
1132 , facets()
1133 , items_string()
1134 , items_int()
1135 , items_float()
1136 , items_time()
1137 , items_misc()
1138 , variants() {
1139 }
1140
1141 void EnumerationType::applyReference(const EnumerationType & other) {
1142 if (!modified) modified = other.modified;
1143 for (List<Mstring>::iterator facet = other.facets.begin(); facet; facet = facet->Next) {
1144 facets.push_back(facet->Data);
1145 }
1146 }
1147
1148 void EnumerationType::applyFacets() // string types, integer types, float types, time types
1149 {
1150 if (!modified) return;
1151
1152 facets.remove_dups();
1153
1154 const Mstring & base = parent->getBuiltInBase();
1155
1156 if (isStringType(base)) // here length restriction is applicable
1157 {
1158 List<Mstring> text_variants;
1159 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
1160 const LengthType & length = parent->getLength();
1161 if (length.lower <= facet->Data.size() && facet->Data.size() <= length.upper) {
1162 Mstring res, var;
1163 XSDName2TTCN3Name(facet->Data, items_string, enum_id_name, res, var);
1164 text_variants.push_back(var);
1165 }
1166 }
1167 text_variants.sort();
1168 for (List<Mstring>::iterator var = text_variants.end(); var; var = var->Prev) {
1169 variants.push_back(var->Data);
1170 }
1171 } else if (isIntegerType(base)) // here value restriction is applicable
1172 {
1173 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
1174 int int_value = atoi(facet->Data.c_str());
1175 const ValueType & value = parent->getValue();
1176 if (value.lower <= int_value && int_value <= value.upper) {
1177 bool found = false;
1178 for (List<int>::iterator itemInt = items_int.begin(); itemInt; itemInt = itemInt->Next) {
1179 if (int_value == itemInt->Data) {
1180 found = true;
1181 break;
1182 }
1183 }
1184 if (!found) items_int.push_back(int_value);
1185
1186 if (variants.empty() || variants.back() != "\"useNumber\"") {
1187 variants.push_back(Mstring("\"useNumber\""));
1188 }
1189 }
1190 }
1191 } else if (isFloatType(base)) // here value restriction is applicable
1192 {
1193 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
1194 double float_value = atof(facet->Data.c_str());
1195 const ValueType & value = parent->getValue();
1196 if (value.lower <= float_value && float_value <= value.upper) {
1197 bool found = false;
1198 for (List<double>::iterator itemFloat = items_float.begin(); itemFloat; itemFloat = itemFloat->Next) {
1199 if (float_value == itemFloat->Data) {
1200 found = true;
1201 break;
1202 }
1203 }
1204 if (!found) {
1205 items_float.push_back(float_value);
1206 }
1207 }
1208 }
1209 } else if (isTimeType(base)) {
1210 List<Mstring> text_variants;
1211 for (List<Mstring>::iterator facet = facets.begin(); facet; facet = facet->Next) {
1212 Mstring res, var;
1213 XSDName2TTCN3Name(facet->Data, items_time, enum_id_name, res, var);
1214 text_variants.push_back(var);
1215 }
1216 text_variants.sort();
1217 for (List<Mstring>::iterator var = text_variants.end(); var; var = var->Prev) {
1218 variants.push_back(var->Data);
1219 }
1220 } else if (isAnyType(base)) {
1221 } else if (base.empty()) {
1222 } else {
1223 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1224 Mstring("Enumeration restriction is not supported on type '") + base + Mstring("'."));
1225 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1226 parent->setInvisible();
1227 }
1228 }
1229
1230 void EnumerationType::sortFacets() {
1231 items_string.sort();
1232 items_int.sort();
1233 items_float.sort();
1234 items_time.sort();
1235 }
1236
1237 void EnumerationType::printToFile(FILE * file, unsigned int indent_level) const {
1238 if (!modified) return;
1239
1240 const Mstring & base = parent->getBuiltInBase();
1241 if (isStringType(base)) {
1242 for (QualifiedNames::iterator itemString = items_string.begin(); itemString; itemString = itemString->Next) {
1243 if (itemString != items_string.begin()) fputs(",\n", file);
1244 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1245 fprintf(file, "\t%s", itemString->Data.name.c_str());
1246 }
1247 } else if (isIntegerType(base)) {
1248 for (List<int>::iterator itemInt = items_int.begin(); itemInt; itemInt = itemInt->Next) {
1249 if (itemInt != items_int.begin()) fputs(",\n", file);
1250 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1251 if (itemInt->Data < 0) {
1252 fprintf(file, "\tint_%d(%d)", abs(itemInt->Data), itemInt->Data);
1253 } else {
1254 fprintf(file, "\tint%d(%d)", itemInt->Data, itemInt->Data);
1255 }
1256 }
1257 } else if (isFloatType(base)) {
1258 for (List<double>::iterator itemFloat = items_float.begin(); itemFloat; itemFloat = itemFloat->Next) {
1259 if (itemFloat != items_float.begin()) fputs(", ", file);
1260
1261 double intpart = 0;
1262 double fracpart = 0;
1263 fracpart = modf(itemFloat->Data, &intpart);
1264 if (fracpart == 0) {
1265 fprintf(file, "%lld.0", (long long int) (itemFloat->Data));
1266 } else {
1267 fprintf(file, "%g", itemFloat->Data);
1268 }
1269 }
1270 } else if (isTimeType(base)) {
1271 for (QualifiedNames::iterator itemTime = items_time.begin(); itemTime; itemTime = itemTime->Next) {
1272 if (itemTime != items_time.begin()) fputs(",\n", file);
1273 for (unsigned int l = 0; l != indent_level; ++l) fputs("\t", file);
1274 fprintf(file, "\t%s", itemTime->Data.name.c_str());
1275 }
1276 }
1277 }
1278
1279 void EnumerationType::insertVariants(){
1280 if(!modified) return;
1281
1282 Mstring pre_connector = empty_string;
1283 if(parent->getMinOccurs() == 0 && parent->getMaxOccurs() == ULLONG_MAX){
1284 pre_connector = "([-]) ";
1285 }
1286 for(List<Mstring>::iterator var = variants.begin(); var; var = var->Next){
1287 parent->addVariant(V_onlyValue, pre_connector + var->Data);
1288 }
1289 }
1290
1291 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1292
1293 WhitespaceType::WhitespaceType(SimpleType * a_simpleType)
1294 : p_parent(a_simpleType)
1295 , modified(false)
1296 , facet()
1297 , value() {
1298 }
1299
1300 void WhitespaceType::applyReference(const WhitespaceType & other) {
1301 if (!modified) modified = other.modified;
1302 if (facet.empty()) facet = other.facet;
1303 }
1304
1305 void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1306 {
1307 if (!modified) return;
1308
1309 const Mstring & base = p_parent->getBuiltInBase();
1310 if (base == "string" || base == "normalizedString" || base == "token" || base == "language" ||
1311 base == "Name" || base == "NCName" || isAnyType(base) || base.empty()) {
1312 p_parent->addVariant(V_whiteSpace, facet);
1313 } else {
1314 printWarning(p_parent->getModule()->getSchemaname(), p_parent->getName().convertedValue,
1315 Mstring("Facet 'whiteSpace' is not applicable for type '") + base + Mstring("'."));
1316 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1317 }
1318 }
1319
1320 ValueType::ValueType(SimpleType * a_simpleType)
1321 : parent(a_simpleType)
1322 , modified(false)
1323 , facet_minInclusive(-DBL_MAX)
1324 , facet_maxInclusive(DBL_MAX)
1325 , facet_minExclusive(-DBL_MAX)
1326 , facet_maxExclusive(DBL_MAX)
1327 , facet_totalDigits(-1)
1328 , lower(-DBL_MAX)
1329 , upper(DBL_MAX)
1330 , lowerExclusive(false)
1331 , upperExclusive(false)
1332 , not_a_number(false)
1333 , fixed_value()
1334 , default_value()
1335 , items_with_value() {
1336 }
1337
1338 void ValueType::applyReference(const ValueType & other) {
1339 if (!modified) {
1340 modified = other.modified;
1341 }
1342 if (not_a_number) {
1343 return;
1344 }
1345 if (other.not_a_number) not_a_number = true;
1346 if (other.facet_minInclusive > facet_minInclusive) facet_minInclusive = other.facet_minInclusive;
1347 if (other.facet_maxInclusive < facet_maxInclusive) facet_maxInclusive = other.facet_maxInclusive;
1348 if (other.facet_minExclusive > facet_minExclusive) facet_minExclusive = other.facet_minExclusive;
1349 if (other.facet_maxExclusive < facet_maxExclusive) facet_maxExclusive = other.facet_maxExclusive;
1350 if (other.upperExclusive) upperExclusive = other.upperExclusive;
1351 if (other.lowerExclusive) lowerExclusive = other.lowerExclusive;
1352 //-1 in case when it is not modified
1353 if (other.facet_totalDigits < facet_totalDigits || facet_totalDigits == -1) facet_totalDigits = other.facet_totalDigits;
1354 if (!other.default_value.empty()) {
1355 default_value = other.default_value;
1356 parent->addVariant(V_defaultForEmpty, default_value);
1357 }
1358 if (!other.fixed_value.empty()) {
1359 fixed_value = other.fixed_value;
1360 parent->addVariant(V_defaultForEmpty, fixed_value);
1361 }
1362 }
1363
1364 void ValueType::applyFacets() // only for integer and float types
1365 {
1366 if (!modified) {
1367 return;
1368 }
1369
1370 if (not_a_number) {
1371 return;
1372 }
1373
1374 const Mstring & base = parent->getBuiltInBase();
1375 /*
1376 * Setting of default value range of built-in types
1377 */
1378 if (base == "positiveInteger") {
1379 lower = 1;
1380 } else if (base == "nonPositiveInteger") {
1381 upper = 0;
1382 } else if (base == "negativeInteger") {
1383 upper = -1;
1384 } else if (base == "nonNegativeInteger") {
1385 lower = 0;
1386 } else if (base == "unsignedLong") {
1387 lower = 0;
1388 upper = ULLONG_MAX;
1389 } else if (base == "int") {
1390 lower = INT_MIN;
1391 upper = INT_MAX;
1392 } else if (base == "unsignedInt") {
1393 lower = 0;
1394 upper = UINT_MAX;
1395 } else if (base == "short") {
1396 lower = SHRT_MIN;
1397 upper = SHRT_MAX;
1398 } else if (base == "unsignedShort") {
1399 lower = 0;
1400 upper = USHRT_MAX;
1401 } else if (base == "byte") {
1402 lower = CHAR_MIN;
1403 upper = CHAR_MAX;
1404 } else if (base == "unsignedByte") {
1405 lower = 0;
1406 upper = UCHAR_MAX;
1407 }
1408
1409 if (isIntegerType(base)) {
1410 if (facet_minInclusive != -DBL_MAX && facet_minInclusive > lower) lower = facet_minInclusive;
1411 if (facet_maxInclusive != DBL_MAX && upper > facet_maxInclusive) upper = facet_maxInclusive;
1412 if (facet_minExclusive != -DBL_MAX && lower < facet_minExclusive) lower = facet_minExclusive;
1413 if (facet_maxExclusive != DBL_MAX && upper > facet_maxExclusive) upper = facet_maxExclusive;
1414 } else if (isFloatType(base)) {
1415 if (facet_minInclusive != -DBL_MAX && lower < facet_minInclusive) lower = facet_minInclusive;
1416 if (facet_maxInclusive != DBL_MAX && upper > facet_maxInclusive) upper = facet_maxInclusive;
1417 if (facet_minExclusive != -DBL_MAX && lower < facet_minExclusive) lower = facet_minExclusive;
1418 if (facet_maxExclusive != DBL_MAX && upper > facet_maxExclusive) upper = facet_maxExclusive;
1419 } else if (isAnyType(base) || isTimeType(base) || isBooleanType(base)) {
1420 } else if (isStringType(base) && (
1421 base.getValueWithoutPrefix(':') != "hexBinary" && base.getValueWithoutPrefix(':') != "base64Binary")) {
1422 } else if (base.empty()) {
1423 } else {
1424 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1425 Mstring("Value restriction is not supported on type '") + base + Mstring("'."));
1426 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1427 }
1428
1429 // totalDigits facet is only for integer types and decimal
1430 if (facet_totalDigits > 0) // if this facet is used
1431 {
1432 double r = pow(10.0, facet_totalDigits);
1433
1434 if (base == "integer") {
1435 lower = (int) -(r - 1);
1436 upper = (int) (r - 1);
1437 } else if (base == "positiveInteger") {
1438 lower = 1;
1439 upper = (int) (r - 1);
1440 } else if (base == "nonPositiveInteger") {
1441 lower = (int) -(r - 1);
1442 upper = 0;
1443 } else if (base == "negativeInteger") {
1444 lower = (int) -(r - 1);
1445 upper = -1;
1446 } else if (base == "nonNegativeInteger") {
1447 lower = 0;
1448 upper = (int) (r - 1);
1449 } else if (base == "long" ||
1450 base == "unsignedLong" ||
1451 base == "int" ||
1452 base == "unsignedInt" ||
1453 base == "short" ||
1454 base == "unsignedShort" ||
1455 base == "byte" ||
1456 base == "unsignedByte") {
1457 lower = (int) -(r - 1);
1458 upper = (int) (r - 1);
1459 } else if (base == "decimal") {
1460 lower = (int) -(r - 1);
1461 upper = (int) (r - 1);
1462 } else {
1463 printWarning(parent->getModule()->getSchemaname(), parent->getName().convertedValue,
1464 Mstring("Facet 'totalDigits' is not applicable for type '") + base + Mstring("'."));
1465 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1466 }
1467 }
1468 items_with_value.sort();
1469 }
1470
1471 void ValueType::printToFile(FILE * file) const {
1472 if (!modified) return;
1473 if (parent->getEnumeration().modified) return;
1474
1475 if (not_a_number) {
1476 fprintf(file, " ( not_a_number )");
1477 return;
1478 }
1479 if (!fixed_value.empty()) {
1480 //Base64binary and hexbyte does not supported
1481 Mstring type;
1482 if(isBuiltInType(parent->getType().originalValueWoPrefix)){
1483 type = parent->getType().originalValueWoPrefix;
1484 }else {
1485 type = getPrefixByNameSpace(parent, parent->getReference().get_uri()) + Mstring(":") + parent->getReference().get_val();
1486 }
1487 if(!isBuiltInType(type)){
1488 type = findBuiltInType(parent, type);
1489 }
1490 if (isStringType(type) || isTimeType(type) || isQNameType(type) || isAnyType(type)) {
1491 const Mstring& name = type.getValueWithoutPrefix(':');
1492 if (name != "hexBinary" && name != "base64Binary") {
1493 fprintf(file, " (\"%s\")", fixed_value.c_str());
1494 }
1495 } else if (isBooleanType(type)) {
1496 Mstring val;
1497 if (fixed_value == "1") {
1498 val = "true";
1499 } else if (fixed_value == "0") {
1500 val = "false";
1501 } else {
1502 val = fixed_value;
1503 }
1504 fprintf(file, " (%s)", val.c_str());
1505 } else {
1506 fprintf(file, " (%s)", fixed_value.c_str());
1507 }
1508 return;
1509 }
1510 if (!items_with_value.empty()) {
1511 fputs(" (\n", file);
1512 for (List<Mstring>::iterator itemWithValue = items_with_value.begin(); itemWithValue; itemWithValue = itemWithValue->Next) {
1513 fprintf(file, "\t%s", itemWithValue->Data.c_str());
1514 if (itemWithValue != items_with_value.end()) {
1515 fputs(",\n", file);
1516 } else {
1517 fputs("\n", file);
1518 }
1519 }
1520 fputc(')', file);
1521 return;
1522 }
1523
1524 if (lower == -DBL_MAX && upper == DBL_MAX) return;
1525
1526 fputs(" (", file);
1527
1528 if (isIntegerType(parent->getBuiltInBase())) {
1529 if (lowerExclusive) {
1530 fputc('!', file);
1531 }
1532
1533 if (lower == -DBL_MAX) {
1534 fputs("-infinity", file);
1535 } else if (lower < 0) {
1536 long double temp_lower = -lower;
1537 fprintf(file, "-%.0Lf", temp_lower);
1538 } else {
1539 fprintf(file, "%.0Lf", lower);
1540 }
1541
1542 fputs(" .. ", file);
1543 if (upperExclusive) {
1544 fputc('!', file);
1545 }
1546
1547 if (upper == DBL_MAX) {
1548 fputs("infinity", file);
1549 } else if (upper < 0) {
1550 long double temp_upper = -upper;
1551 fprintf(file, "-%.0Lf", temp_upper);
1552 } else {
1553 fprintf(file, "%.0Lf", upper);
1554 }
1555 } else if (isFloatType(parent->getBuiltInBase())) {
1556 if (lowerExclusive) {
1557 fputc('!', file);
1558 }
1559
1560 if (lower == -DBL_MAX) {
1561 fputs("-infinity", file);
1562 } else {
1563 double intpart = 0;
1564 double fracpart = 0;
1565 fracpart = modf(lower, &intpart);
1566 if (fracpart == 0) {
1567 fprintf(file, "%.1Lf", lower);
1568 } else {
1569 fprintf(file, "%Lg", lower);
1570 }
1571 }
1572
1573 fputs(" .. ", file);
1574 if (upperExclusive) {
1575 fputc('!', file);
1576 }
1577
1578 if (upper == DBL_MAX) {
1579 fputs("infinity", file);
1580 } else {
1581 double intpart = 0;
1582 double fracpart = 0;
1583 fracpart = modf(upper, &intpart);
1584 if (fracpart == 0) {
1585 fprintf(file, "%.1Lf", upper);
1586 } else {
1587 fprintf(file, "%Lg", upper);
1588 }
1589 }
1590 }
1591
1592 fputc(')', file);
1593 }
This page took 0.065224 seconds and 5 git commands to generate.