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