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