1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "SimpleType.hh"
10 #include "GeneralFunctions.hh"
12 #include "TTCN3ModuleInventory.hh"
13 #include "TTCN3Module.hh"
14 #include "ComplexType.hh"
15 #include "FieldType.hh"
18 SimpleType::SimpleType(XMLParser
* a_parser
, TTCN3Module
* a_module
, ConstructType a_construct
)
19 : RootType(a_parser
, a_module
, a_construct
)
26 , element_form_as(notset
)
27 , attribute_form_as(notset
)
33 SimpleType::SimpleType(const SimpleType
& other
)
35 , builtInBase(other
.builtInBase
)
36 , length(other
.length
)
37 , pattern(other
.pattern
)
38 , enumeration(other
.enumeration
)
39 , whitespace(other
.whitespace
)
41 , element_form_as(other
.element_form_as
)
42 , attribute_form_as(other
.attribute_form_as
)
44 , outside_reference(other
.outside_reference
)
45 , in_name_only(other
.in_name_only
)
48 pattern
.parent
= this;
49 enumeration
.parent
= this;
50 whitespace
.p_parent
= this;
54 void SimpleType::loadWithValues()
56 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
58 switch (parser
->getActualTagName())
60 case XMLParser::n_restriction
:
61 type
.upload(atts
.base
);
62 setReference(atts
.base
);
63 mode
= restrictionMode
;
65 case XMLParser::n_list
:
66 type
.upload(atts
.itemType
);
67 setReference(atts
.itemType
);
69 maxOccurs
= ULLONG_MAX
;
73 case XMLParser::n_union
: { // generating complextype from simpletype
74 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagUnion
);
75 new_complextype
->loadWithValues();
77 case XMLParser::n_element
:
78 name
.upload(atts
.name
);
79 type
.upload(atts
.type
);
80 setReference(atts
.type
, true);
81 applyDefaultAttribute(atts
.default_
);
82 applyFixedAttribute(atts
.fixed
);
83 applyNillableAttribute(atts
.nillable
);
85 case XMLParser::n_attribute
:
86 name
.upload(atts
.name
);
87 type
.upload(atts
.type
);
88 setReference(atts
.type
, true);
89 applyDefaultAttribute(atts
.default_
);
90 applyFixedAttribute(atts
.fixed
);
92 case XMLParser::n_simpleType
:
93 name
.upload(atts
.name
);
95 case XMLParser::n_complexType
: { // generating complextype from simpletype
96 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagComplexType
);
97 new_complextype
->loadWithValues();
99 case XMLParser::n_length
:
100 if (mode
== listMode
) {
101 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
102 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
105 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
106 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
107 length
.modified
= true;
109 case XMLParser::n_minLength
:
110 if (mode
== listMode
) {
111 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
114 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
115 length
.modified
= true;
117 case XMLParser::n_maxLength
:
118 if (mode
== listMode
) {
119 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
122 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
123 length
.modified
= true;
125 case XMLParser::n_pattern
:
126 pattern
.facet
= atts
.value
;
127 pattern
.modified
= true;
129 case XMLParser::n_enumeration
:
130 enumeration
.facets
.push_back(atts
.value
);
131 enumeration
.modified
= true;
133 case XMLParser::n_whiteSpace
:
134 whitespace
.facet
= atts
.value
;
135 whitespace
.modified
= true;
137 case XMLParser::n_minInclusive
:
138 if (atts
.value
== "NaN") {}
139 else if (atts
.value
== "-INF") {
140 value
.facet_minInclusive
= -DBL_MAX
;
142 else if (atts
.value
== "INF") {
143 value
.facet_minInclusive
= DBL_MAX
;
146 value
.facet_minInclusive
= stringToLongDouble(atts
.value
.c_str());
148 value
.modified
= true;
150 case XMLParser::n_maxInclusive
:
151 if (atts
.value
== "NaN") {}
152 else if (atts
.value
== "-INF") {
153 value
.facet_maxInclusive
= -DBL_MAX
;
155 else if (atts
.value
== "INF") {
156 value
.facet_maxInclusive
= DBL_MAX
;
159 value
.facet_maxInclusive
= stringToLongDouble(atts
.value
.c_str());
161 value
.modified
= true;
163 case XMLParser::n_minExclusive
:
164 if (atts
.value
== "NaN") {}
165 else if (atts
.value
== "-INF") {
166 value
.facet_minExclusive
= -DBL_MAX
;
168 else if (atts
.value
== "INF") {
169 value
.facet_minExclusive
= DBL_MAX
;
172 value
.facet_minExclusive
= stringToLongDouble(atts
.value
.c_str());
174 value
.modified
= true;
175 value
.lowerExclusive
= true;
177 case XMLParser::n_maxExclusive
:
178 if (atts
.value
== "NaN") {}
179 else if (atts
.value
== "-INF") {
180 value
.facet_maxExclusive
= -DBL_MAX
;
182 else if (atts
.value
== "INF") {
183 value
.facet_maxExclusive
= DBL_MAX
;
186 value
.facet_maxExclusive
= stringToLongDouble(atts
.value
.c_str());
188 value
.modified
= true;
189 value
.upperExclusive
= true;
191 case XMLParser::n_totalDigits
:
192 value
.facet_totalDigits
= strtoul(atts
.value
.c_str(), NULL
, 0);
193 value
.modified
= true;
195 case XMLParser::n_annotation
:
196 case XMLParser::n_documentation
:
198 case XMLParser::n_label
:
199 addComment(Mstring("LABEL:"));
201 case XMLParser::n_definition
:
202 addComment(Mstring("DEFINITION:"));
209 void SimpleType::applyDefaultAttribute(const Mstring
& default_value
)
211 if (!default_value
.empty()) {
212 value
.default_value
= default_value
;
213 addVariant(V_defaultForEmpty
, default_value
);
217 void SimpleType::applyFixedAttribute(const Mstring
& fixed_value
)
219 if (!fixed_value
.empty()) {
220 value
.fixed_value
= fixed_value
;
221 addVariant(V_defaultForEmpty
, fixed_value
);
225 void SimpleType::applyNillableAttribute(bool nillable
)
229 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagNillable
); // generating complextype from simpletype
230 new_complextype
->loadWithValues();
234 void SimpleType::setReference(const Mstring
& ref
, bool only_name_dependency
)
239 if (isBuiltInType(ref
)) {
240 builtInBase
= ref
.getValueWithoutPrefix(':');
244 Mstring refPrefix
= ref
.getPrefix(':');
245 Mstring refValue
= ref
.getValueWithoutPrefix(':');
247 // Find the URI amongst the known namespace URIs
248 List
<NamespaceType
>::iterator declNS
;
249 for (declNS
= module
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
)
251 if (refPrefix
== declNS
->Data
.prefix
) {
252 refUri
= declNS
->Data
.uri
;
257 // FIXME: can this part be moved above the search ?
258 if (refUri
.empty()) { // not found
259 if (refPrefix
== "xml") {
260 refUri
= "http://www.w3.org/XML/1998/namespace";
262 else if (refPrefix
== "xmlns") {
263 refUri
= "http://www.w3.org/2000/xmlns";
265 else if (refPrefix
.empty() && module
->getTargetNamespace() == "NoTargetNamespace") {
266 refUri
= "NoTargetNamespace";
270 if (refUri
.empty()) { // something is incorrect - unable to find the uri to the given prefix
271 if (refPrefix
.empty()) {
272 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
273 Mstring("The absent namespace must be imported because "
274 "it is not the same as the target namespace of the current schema."));
275 parser
->incrNumErrors();
279 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
280 "The value \'" + ref
+ "\' is incorrect: "
281 "A namespace prefix does not denote any URI.");
282 parser
->incrNumErrors();
287 if (only_name_dependency
) {
288 //name_dependency = refUri + "|" + refValue;
292 //reference_for_other = refUri + "|" + refValue;
293 outside_reference
.load(refUri
, refValue
, &declNS
->Data
);
296 void SimpleType::referenceResolving()
298 if (outside_reference
.empty()) return;
299 if (outside_reference
.is_resolved()) return;
301 SimpleType
* found_ST
= static_cast<SimpleType
*>(
302 TTCN3ModuleInventory::getInstance().lookup(this, want_ST
));
303 ComplexType
* found_CT
= static_cast<ComplexType
*>(
304 TTCN3ModuleInventory::getInstance().lookup(this, want_CT
));
305 // It _is_ possible to find both
307 if (found_ST
!= NULL
) {
308 referenceForST(found_ST
);
309 found_ST
->addToNameDepList(this);
311 else if (found_CT
!= NULL
) {
312 referenceForCT(found_CT
);
313 found_CT
->addToNameDepList(this);
316 printError(module
->getSchemaname(), name
.convertedValue
,
317 "Reference for a non-defined type: " + outside_reference
.repr());
318 TTCN3ModuleInventory::getInstance().incrNumErrors();
319 outside_reference
.set_resolved(NULL
);
323 void SimpleType::referenceForST(SimpleType
const * const found_ST
)
325 outside_reference
.set_resolved(found_ST
);
330 if (construct
== c_element
)
333 if (mode
== listMode
)
336 builtInBase
= found_ST
->builtInBase
;
338 length
.applyReference(found_ST
->length
);
339 pattern
.applyReference(found_ST
->pattern
);
340 enumeration
.applyReference(found_ST
->enumeration
);
341 whitespace
.applyReference(found_ST
->whitespace
);
342 value
.applyReference(found_ST
->value
);
344 mode
= found_ST
->mode
;
347 void SimpleType::referenceForCT(ComplexType
const * const found_CT
)
349 outside_reference
.set_resolved(found_CT
);
354 enumeration
.modified
= false;
355 for (List
<Mstring
>::iterator itemMisc
= enumeration
.items_misc
.begin(); itemMisc
; itemMisc
= itemMisc
->Next
)
357 if (isdigit(itemMisc
->Data
[0]))
359 for (List
<FieldType
*>::iterator field
= found_CT
->getFields().begin(); field
; field
= field
->Next
)
361 if (isIntegerType(field
->Data
->getType().convertedValue
))
363 expstring_t tmp_string
= mprintf("{%s:=%d}",
364 field
->Data
->getName().convertedValue
.c_str(), atoi(itemMisc
->Data
.c_str()));
365 value
.items_with_value
.push_back(Mstring(tmp_string
));
367 else if (isFloatType(field
->Data
->getType().convertedValue
))
369 expstring_t tmp_string
= mprintf("{%s:=%f}",
370 field
->Data
->getName().convertedValue
.c_str(), atof(itemMisc
->Data
.c_str()));
371 value
.items_with_value
.push_back(Mstring(tmp_string
));
373 else if (isTimeType(field
->Data
->getType().convertedValue
))
375 expstring_t tmp_string
= mprintf("{%s;=%s}",
376 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
377 value
.items_with_value
.push_back(Mstring(tmp_string
));
382 for (List
<FieldType
*>::iterator field
= found_CT
->getFields().begin(); field
; field
= field
->Next
)
384 if (isStringType(field
->Data
->getType().convertedValue
))
386 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
387 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
388 value
.items_with_value
.push_back(Mstring(tmp_string
));
396 void SimpleType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
)
398 switch (conversion_mode
)
401 nameConversion_names();
404 nameConversion_types(ns
);
411 void SimpleType::nameConversion_names()
413 Mstring res
, var(module
->getTargetNamespace());
414 XSDName2TTCN3Name(name
.convertedValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_name
, res
, var
);
415 name
.convertedValue
= res
;
416 addVariant(V_onlyValue
, var
);
417 for (List
<SimpleType
*>::iterator st
= nameDepList
.begin(); st
; st
= st
->Next
) {
418 st
->Data
->setTypeValue(res
);
422 void SimpleType::nameConversion_types(const List
<NamespaceType
> & ns
)
424 if (type
.convertedValue
== "record" || type
.convertedValue
== "set"
425 ||type
.convertedValue
== "union" || type
.convertedValue
== "enumerated") return;
427 Mstring prefix
= type
.convertedValue
.getPrefix(':');
428 Mstring value_str
= type
.convertedValue
.getValueWithoutPrefix(':');
431 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
)
433 if (prefix
== namesp
->Data
.prefix
) {
434 uri
= namesp
->Data
.uri
;
439 QualifiedName
tmp(uri
, value_str
);
441 QualifiedNames::iterator origTN
= TTCN3ModuleInventory::getInstance().getTypenames().begin();
442 for ( ; origTN
; origTN
= origTN
->Next
)
444 if (tmp
== origTN
->Data
) {
445 QualifiedName
tmp_name(module
->getTargetNamespace(), name
.convertedValue
);
446 if (tmp_name
== origTN
->Data
)
447 continue; // get a new type name
452 if (origTN
!= NULL
) {
453 setTypeValue(origTN
->Data
.name
);
454 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
455 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
456 // otherwise the new value is always the same as the old.
460 XSDName2TTCN3Name(value_str
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
465 void SimpleType::finalModification()
468 length
.applyFacets();
469 pattern
.applyFacet();
470 whitespace
.applyFacet();
471 enumeration
.applyFacets();
473 if (module
->getElementFormDefault() == qualified
&&
474 element_form_as
== unqualified
) {
475 addVariant(V_formAs
, Mstring("unqualified"));
477 if (module
->getAttributeFormDefault() == qualified
&&
478 attribute_form_as
== unqualified
) {
479 addVariant(V_formAs
, Mstring("unqualified"));
483 bool SimpleType::hasUnresolvedReference()
485 if (!outside_reference
.empty() && !outside_reference
.is_resolved())
492 void SimpleType::printToFile(FILE * file
)
494 if (!visible
) return;
498 fputs("type ", file
);
499 if (enumeration
.modified
) {
500 if (isFloatType(builtInBase
)) {
501 fprintf(file
, "%s %s (", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
502 enumeration
.sortFacets();
503 enumeration
.printToFile(file
);
507 fprintf(file
, "enumerated %s\n{\n", name
.convertedValue
.c_str());
508 enumeration
.sortFacets();
509 enumeration
.printToFile(file
);
514 printMinOccursMaxOccurs(file
, false);
516 int multiplicity
= multi(module
, outside_reference
, this);
517 const RootType
*type_ref
= outside_reference
.get_ref();
518 if ((multiplicity
> 1) && type_ref
519 && type_ref
->getModule() != module
) {
520 fprintf(file
, "%s.", type_ref
->getModule()->getModulename().c_str());
523 fprintf(file
, "%s %s",
524 type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
525 pattern
.printToFile(file
);
526 value
.printToFile(file
);
527 length
.printToFile(file
);
530 fputs(";\n\n\n", file
);
533 void SimpleType::dump(unsigned int depth
) const
535 static const char *modes
[] = {
536 "", "restriction", "extension", "list"
538 fprintf(stderr
, "%*s SimpleType '%s' -> '%s' at %p\n", depth
* 2, "",
539 name
.originalValueWoPrefix
.c_str(), name
.convertedValue
.c_str(),
541 fprintf(stderr
, "%*s type '%s' -> '%s'\n", depth
* 2, "",
542 type
.originalValueWoPrefix
.c_str(), type
.convertedValue
.c_str());
544 if (mode
!= noMode
) {
545 fprintf(stderr
, "%*s %s, base='%s'\n", depth
* 2, "", modes
[mode
], builtInBase
.c_str());
548 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
549 // reference_for_other.c_str(), name_dependency.c_str());
552 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
554 LengthType::LengthType(SimpleType
* a_simpleType
)
555 : parent(a_simpleType
)
558 , facet_maxLength(ULLONG_MAX
)
563 void LengthType::applyReference(const LengthType
& other
)
565 if (!modified
) modified
= other
.modified
;
566 if (other
.facet_minLength
> facet_minLength
) facet_minLength
= other
.facet_minLength
;
567 if (other
.facet_maxLength
< facet_maxLength
) facet_maxLength
= other
.facet_maxLength
;
570 void LengthType::applyFacets() // only for string types and list types without QName
572 if (!modified
) return;
574 switch (parent
->getMode())
576 case SimpleType::restrictionMode
: {
577 const Mstring
& base
= parent
->getBuiltInBase();
578 if ((isStringType(base
) || (isSequenceType(base
) && base
!= "QName") || isAnyType(base
)) || base
.empty() )
580 lower
= facet_minLength
;
581 upper
= facet_maxLength
;
585 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
586 Mstring("Length restriction is not supported on type '") + base
+ Mstring("'."));
587 TTCN3ModuleInventory::getInstance().incrNumWarnings();
590 case SimpleType::extensionMode
:
592 case SimpleType::listMode
:
593 lower
= facet_minLength
;
594 upper
= facet_maxLength
;
596 case SimpleType::noMode
:
600 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
601 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
602 TTCN3ModuleInventory::getInstance().incrNumErrors();
607 void LengthType::printToFile(FILE * file
) const
609 if (!modified
) return;
610 if (parent
->getEnumeration().modified
) return;
614 fprintf(file
, " length(%llu)", lower
);
618 fprintf(file
, " length(%llu .. ", lower
);
620 if (upper
== ULLONG_MAX
)
622 fputs("infinity", file
);
626 fprintf(file
, "%llu", upper
);
633 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
635 PatternType::PatternType(SimpleType
* a_simpleType
)
636 : parent(a_simpleType
)
642 void PatternType::applyReference(const PatternType
& other
)
644 if (!modified
) modified
= other
.modified
;
645 if (facet
.empty()) facet
= other
.facet
;
648 void PatternType::applyFacet() // only for time types and string types without hexBinary
650 if (!modified
) return;
652 const Mstring
& base
= parent
->getBuiltInBase();
653 if (((isStringType(base
) && base
!= "hexBinary") || isTimeType(base
) || isAnyType(base
)) || base
.empty())
655 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
656 // FIXME a proper scanner is needed, e.g. from flex
658 for (size_t i
= 0; i
!= facet
.size(); ++i
)
662 case '(': case ')': case '/': case '^':
673 case '.': // any character
676 case '*': // 0 or more
677 value
+= '*'; //#(0,)
680 value
+= '+'; //#(1,)
690 while (facet
[i
+ k
] != '}') {
694 if (s
.isFound(',')) {
706 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
707 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
708 char cn
= facet
[i
+1];
711 value
+= charclass
? "\\w\\d.\\-_:"
715 value
+= charclass
? "^\\w\\d.\\-_:"
719 value
+= charclass
? "^\\d"
723 value
+= charclass
? "\\w\\d:"
727 value
+= charclass
? "^\\w\\d:"
731 value
+= charclass
? "\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
732 : "[\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
735 value
+= charclass
? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
736 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
739 value
+= charclass
? "^\\w"
743 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
744 Mstring("Character categories and blocks are not supported."));
745 TTCN3ModuleInventory::getInstance().incrNumWarnings();
747 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
755 // backslash + another: pass unmodified; this also handles \d and \w
763 if (facet
[i
+ 1] == '#') { // &#....;
766 while (facet
[i
+ k
] != ';') {
770 long long int d
= atoll(s
.c_str());
771 if (d
< 0 || d
> 2147483647) {
772 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
773 Mstring("Invalid unicode character."));
774 TTCN3ModuleInventory::getInstance().incrNumErrors();
776 unsigned char group
= (d
>> 24) & 0xFF;
777 unsigned char plane
= (d
>> 16) & 0xFF;
778 unsigned char row
= (d
>> 8) & 0xFF;
779 unsigned char cell
= d
& 0xFF;
781 expstring_t res
= mprintf("\\q{%d, %d, %d, %d}", group
, plane
, row
, cell
);
787 default: //just_copy:
795 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
796 Mstring("Pattern restriction is not supported on type '") + base
+ Mstring("'."));
797 TTCN3ModuleInventory::getInstance().incrNumWarnings();
801 void PatternType::printToFile(FILE * file
) const
803 if (!modified
|| value
.empty()) return;
804 if (parent
->getEnumeration().modified
) return;
806 fprintf(file
, " (pattern \"%s\")", value
.c_str());
809 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
811 EnumerationType::EnumerationType(SimpleType
* a_simpleType
)
812 : parent(a_simpleType
)
822 void EnumerationType::applyReference(const EnumerationType
& other
)
824 if (!modified
) modified
= other
.modified
;
825 for (List
<Mstring
>::iterator facet
= other
.facets
.begin(); facet
; facet
= facet
->Next
)
827 facets
.push_back(facet
->Data
);
831 void EnumerationType::applyFacets() // string types, integer types, float types, time types
833 if (!modified
) return;
835 const Mstring
& base
= parent
->getBuiltInBase();
837 if (isStringType(base
)) // here length restriction is applicable
839 List
<Mstring
> text_variants
;
840 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
)
842 const LengthType
& length
= parent
->getLength();
843 if (length
.lower
<= facet
->Data
.size() && facet
->Data
.size() <= length
.upper
)
846 XSDName2TTCN3Name(facet
->Data
, items_string
, enum_id_name
, res
, var
);
847 text_variants
.push_back(var
);
850 text_variants
.sort();
851 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
852 parent
->addVariant(V_onlyValue
, var
->Data
);
855 else if (isIntegerType(base
)) // here value restriction is applicable
857 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
)
859 int int_value
= atoi(facet
->Data
.c_str());
860 const ValueType
& value
= parent
->getValue();
861 if (value
.lower
<= int_value
&& int_value
<= value
.upper
)
864 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
)
866 if (int_value
== itemInt
->Data
) {
871 if (!found
) items_int
.push_back(int_value
);
873 if (parent
->getVariant().empty() || parent
->getVariant().back() != "\"useNumber\"") {
874 parent
->addVariant(V_useNumber
);
879 else if (isFloatType(base
)) // here value restriction is applicable
881 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
)
883 double float_value
= atof(facet
->Data
.c_str());
884 const ValueType
& value
= parent
->getValue();
885 if (value
.lower
<= float_value
&& float_value
<= value
.upper
)
888 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
)
890 if (float_value
== itemFloat
->Data
) {
896 items_float
.push_back(float_value
);
902 else if (isTimeType(base
))
904 List
<Mstring
> text_variants
;
905 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
)
908 XSDName2TTCN3Name(facet
->Data
, items_time
, enum_id_name
, res
, var
);
909 text_variants
.push_back(var
);
911 text_variants
.sort();
912 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
913 parent
->addVariant(V_onlyValue
, var
->Data
);
916 else if (isAnyType(base
))
918 else if (base
.empty())
922 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
923 Mstring("Enumeration restriction is not supported on type '") + base
+ Mstring("'."));
924 TTCN3ModuleInventory::getInstance().incrNumWarnings();
925 parent
->setInvisible();
929 void EnumerationType::sortFacets()
937 void EnumerationType::printToFile(FILE * file
, unsigned int indent_level
) const
939 if (!modified
) return;
941 const Mstring
& base
= parent
->getBuiltInBase();
942 if (isStringType(base
))
944 for (QualifiedNames::iterator itemString
= items_string
.begin(); itemString
; itemString
= itemString
->Next
)
946 if (itemString
!= items_string
.begin()) fputs(",\n", file
);
947 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
948 fprintf(file
, "\t%s", itemString
->Data
.name
.c_str());
951 else if (isIntegerType(base
))
953 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
)
955 if (itemInt
!= items_int
.begin()) fputs(",\n", file
);
956 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
957 if (itemInt
->Data
< 0) {
958 fprintf(file
, "\tint_%d(%d)", abs(itemInt
->Data
), itemInt
->Data
);
961 fprintf(file
, "\tint%d(%d)", itemInt
->Data
, itemInt
->Data
);
965 else if (isFloatType(base
))
967 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
)
969 if (itemFloat
!= items_float
.begin()) fputs(", ", file
);
973 fracpart
= modf(itemFloat
->Data
, &intpart
);
975 fprintf(file
, "%lld.0", (long long int)(itemFloat
->Data
));
978 fprintf(file
, "%g", itemFloat
->Data
);
982 else if (isTimeType(base
))
984 for (QualifiedNames::iterator itemTime
= items_time
.begin(); itemTime
; itemTime
= itemTime
->Next
)
986 if (itemTime
!= items_time
.begin()) fputs(",\n", file
);
987 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
988 fprintf(file
, "\t%s", itemTime
->Data
.name
.c_str());
993 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
995 WhitespaceType::WhitespaceType(SimpleType
* a_simpleType
)
996 : p_parent(a_simpleType
)
1002 void WhitespaceType::applyReference(const WhitespaceType
& other
)
1004 if (!modified
) modified
= other
.modified
;
1005 if (facet
.empty()) facet
= other
.facet
;
1008 void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1010 if (!modified
) return;
1012 const Mstring
& base
= p_parent
->getBuiltInBase();
1013 if (base
== "string" || base
== "normalizedString" || base
== "token" || base
== "language" ||
1014 base
== "Name" || base
== "NCName" || isAnyType(base
) || base
.empty())
1016 p_parent
->addVariant(V_whiteSpace
, facet
);
1020 printWarning(p_parent
->getModule()->getSchemaname(), p_parent
->getName().convertedValue
,
1021 Mstring("Facet 'whiteSpace' is not applicable for type '") + base
+ Mstring("'."));
1022 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1026 ValueType::ValueType(SimpleType
* a_simpleType
)
1027 : parent(a_simpleType
)
1029 , facet_minInclusive(-DBL_MAX
)
1030 , facet_maxInclusive(DBL_MAX
)
1031 , facet_minExclusive(-DBL_MAX
)
1032 , facet_maxExclusive(DBL_MAX
)
1033 , facet_totalDigits(0)
1036 , lowerExclusive(false)
1037 , upperExclusive(false)
1040 , items_with_value()
1043 void ValueType::applyReference(const ValueType
& other
)
1045 if (!modified
) modified
= other
.modified
;
1046 if (other
.facet_minInclusive
> facet_minInclusive
) facet_minInclusive
= other
.facet_minInclusive
;
1047 if (other
.facet_maxInclusive
< facet_maxInclusive
) facet_maxInclusive
= other
.facet_maxInclusive
;
1048 if (other
.facet_minExclusive
> facet_minExclusive
) facet_minExclusive
= other
.facet_minExclusive
;
1049 if (other
.facet_maxExclusive
< facet_maxExclusive
) facet_maxExclusive
= other
.facet_maxExclusive
;
1050 if (other
.facet_totalDigits
< facet_totalDigits
) facet_totalDigits
= other
.facet_totalDigits
;
1053 void ValueType::applyFacets() // only for integer and float types
1055 if (!modified
) return;
1057 const Mstring
& base
= parent
->getBuiltInBase();
1059 * Setting of default value range of built-in types
1061 if (base
== "positiveInteger")
1065 else if (base
== "nonPositiveInteger")
1069 else if (base
== "negativeInteger")
1073 else if (base
== "nonNegativeInteger")
1077 else if (base
== "unsignedLong")
1082 else if (base
== "int")
1087 else if (base
== "unsignedInt")
1092 else if (base
== "short")
1097 else if (base
== "unsignedShort")
1102 else if (base
== "byte")
1107 else if (base
== "unsignedByte")
1113 if (isIntegerType(base
))
1115 if (facet_minInclusive
!= -DBL_MAX
&& facet_minInclusive
> lower
) lower
= facet_minInclusive
;
1116 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1117 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1118 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1120 else if (isFloatType(base
))
1122 if (facet_minInclusive
!= -DBL_MAX
&& lower
< facet_minInclusive
) lower
= facet_minInclusive
;
1123 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1124 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1125 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1127 else if (isAnyType(base
))
1129 else if (base
.empty())
1133 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1134 Mstring("Value restriction is not supported on type '") + base
+ Mstring("'."));
1135 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1138 // totalDigits facet is only for integer types and decimal
1139 if (facet_totalDigits
!= 0) // if this facet is used
1141 double r
= pow(10.0, facet_totalDigits
);
1143 if (base
== "integer")
1145 lower
= (int) -(r
-1);
1146 upper
= (int) (r
-1);
1148 else if (base
== "positiveInteger")
1151 upper
= (int) (r
-1);
1153 else if (base
== "nonPositiveInteger")
1155 lower
= (int) -(r
-1);
1158 else if (base
== "negativeInteger")
1160 lower
= (int) -(r
-1);
1163 else if (base
== "nonNegativeInteger")
1166 upper
= (int) (r
-1);
1168 else if (base
== "long" ||
1169 base
== "unsignedLong" ||
1171 base
== "unsignedInt" ||
1173 base
== "unsignedShort" ||
1175 base
== "unsignedByte")
1177 lower
= (int) -(r
-1);
1178 upper
= (int) (r
-1);
1180 else if (base
== "decimal")
1182 lower
= (int) -(r
-1);
1183 upper
= (int) (r
-1);
1186 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1187 Mstring("Facet 'totalDigits' is not applicable for type '") + base
+ Mstring("'."));
1188 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1193 void ValueType::printToFile(FILE * file
) const
1195 if (!modified
) return;
1196 if (parent
->getEnumeration().modified
) return;
1198 if (!fixed_value
.empty())
1200 fprintf(file
, " (\"%s\")", fixed_value
.c_str());
1203 if (!items_with_value
.empty())
1206 for (List
<Mstring
>::iterator itemWithValue
= items_with_value
.begin(); itemWithValue
; itemWithValue
= itemWithValue
->Next
)
1208 if (itemWithValue
!= items_with_value
.begin()) fputs(", ", file
);
1209 fprintf(file
, "%s", itemWithValue
->Data
.c_str());
1215 if (lower
== -DBL_MAX
&& upper
== DBL_MAX
) return;
1219 if (isIntegerType(parent
->getBuiltInBase()))
1221 if (lowerExclusive
) {
1225 if (lower
== -DBL_MAX
)
1227 fputs("-infinity", file
);
1231 long double temp_lower
= -lower
;
1232 fprintf(file
, "-%.0Lf", temp_lower
);
1236 fprintf(file
, "%.0Lf", lower
);
1239 fputs(" .. ", file
);
1240 if (upperExclusive
) {
1244 if (upper
== DBL_MAX
)
1246 fputs("infinity", file
);
1250 long double temp_upper
= -upper
;
1251 fprintf(file
, "-%.0Lf", temp_upper
);
1255 fprintf(file
, "%.0Lf", upper
);
1258 else if (isFloatType(parent
->getBuiltInBase()))
1260 if (lowerExclusive
) {
1264 if (lower
== -DBL_MAX
)
1266 fputs("-infinity", file
);
1271 double fracpart
= 0;
1272 fracpart
= modf(lower
, &intpart
);
1273 if (fracpart
== 0) {
1274 fprintf(file
, "%.1Lf", lower
);
1277 fprintf(file
, "%Lg", lower
);
1281 fputs(" .. ", file
);
1282 if (upperExclusive
) {
1286 if (upper
== DBL_MAX
)
1288 fputs("infinity", file
);
1293 double fracpart
= 0;
1294 fracpart
= modf(upper
, &intpart
);
1295 if (fracpart
== 0) {
1296 fprintf(file
, "%.1Lf", upper
);
1299 fprintf(file
, "%Lg", upper
);