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