1 // file : xsd/cxx/tree/serialization-source.cxx 2 // copyright : Copyright (c) 2005-2017 Code Synthesis Tools CC 3 // license : GNU GPL v2 + exceptions; see accompanying LICENSE file 4 5 #include <cxx/tree/serialization-source.hxx> 6 7 #include <xsd-frontend/semantic-graph.hxx> 8 #include <xsd-frontend/traversal.hxx> 9 10 namespace CXX 11 { 12 namespace Tree 13 { 14 namespace 15 { 16 enum schema_type 17 { 18 st_other, 19 st_double, 20 st_decimal 21 }; 22 23 enum schema_type schema_type(SemanticGraph::Type & t)24 schema_type (SemanticGraph::Type& t) 25 { 26 if (t.is_a<SemanticGraph::Fundamental::Double> ()) 27 return st_double; 28 else if (t.is_a<SemanticGraph::Fundamental::Decimal> ()) 29 return st_decimal; 30 else 31 return st_other; 32 } 33 34 35 // 36 // 37 struct List: Traversal::List, Context 38 { ListCXX::Tree::__anon7e6bba720111::List39 List (Context& c) 40 : Context (c) 41 { 42 } 43 44 virtual void traverseCXX::Tree::__anon7e6bba720111::List45 traverse (Type& l) 46 { 47 String name (ename (l)); 48 49 // If renamed name is empty then we do not need to generate 50 // anything for this type. 51 // 52 if (renamed_type (l, name) && !name) 53 return; 54 55 SemanticGraph::Type& item_type (l.argumented ().type ()); 56 String base (L"::xsd::cxx::tree::list< " + 57 item_type_name (item_type) + L", " + char_type); 58 59 if (item_type.is_a<SemanticGraph::Fundamental::Double> ()) 60 base += L", ::xsd::cxx::tree::schema_type::double_"; 61 else if (item_type.is_a<SemanticGraph::Fundamental::Decimal> ()) 62 base += L", ::xsd::cxx::tree::schema_type::decimal"; 63 64 base += L" >"; 65 66 // operator<< (xercesc::DOMElement) 67 // 68 os << "void" << endl 69 << "operator<< (" << xerces_ns << "::DOMElement& e, " << 70 "const " << name << "& i)" 71 << "{" 72 << "e << static_cast< const " << base << "& > (i);" 73 << "}"; 74 75 // operator<< (xercesc::DOMAttr) 76 // 77 os << "void" << endl 78 << "operator<< (" << xerces_ns << "::DOMAttr& a, " << 79 "const " << name << "& i)" 80 << "{" 81 << "a << static_cast< const " << base << "& > (i);" 82 << "}"; 83 84 // operator<< (list_stream) 85 // 86 os << "void" << endl 87 << "operator<< (" << list_stream_type << "& l," << endl 88 << "const " << name << "& i)" 89 << "{" 90 << "l << static_cast< const " << base << "& > (i);" 91 << "}"; 92 93 // Register with type factory map. If this type is anonymous 94 // but substitutes, then it will be registered as part of the 95 // substitution registration. 96 // 97 if (polymorphic && polymorphic_p (l) && !anonymous_p (l)) 98 { 99 // Note that we are using the original type name. 100 // 101 String const& name (ename (l)); 102 103 os << "static" << endl 104 << "const ::xsd::cxx::tree::type_serializer_initializer< " << 105 poly_plate << ", " << char_type << ", " << name << " >" << endl 106 << "_xsd_" << name << "_type_serializer_init (" << endl 107 << strlit (l.name ()) << "," << endl 108 << strlit (xml_ns_name (l)) << ");" 109 << endl 110 << endl; 111 } 112 } 113 114 private: 115 String item_type_nameCXX::Tree::__anon7e6bba720111::List116 item_type_name (SemanticGraph::Type& t) 117 { 118 std::wostringstream o; 119 120 MemberTypeName type (*this, o); 121 type.dispatch (t); 122 123 return o.str (); 124 } 125 }; 126 127 128 struct Union: Traversal::Union, Context 129 { UnionCXX::Tree::__anon7e6bba720111::Union130 Union (Context& c) 131 : Context (c) 132 { 133 } 134 135 virtual void traverseCXX::Tree::__anon7e6bba720111::Union136 traverse (Type& u) 137 { 138 String name (ename (u)); 139 140 // If renamed name is empty then we do not need to generate 141 // anything for this type. 142 // 143 if (renamed_type (u, name) && !name) 144 return; 145 146 String const& base (xs_string_type); 147 148 // operator<< (xercesc::DOMElement) 149 // 150 os << "void" << endl 151 << "operator<< (" << xerces_ns << "::DOMElement& e, " << 152 "const " << name << "& i)" 153 << "{" 154 << "e << static_cast< const " << base << "& > (i);" 155 << "}"; 156 157 // operator<< (xercesc::DOMAttr) 158 // 159 os << "void" << endl 160 << "operator<< (" << xerces_ns << "::DOMAttr& a, " << 161 "const " << name << "& i)" 162 << "{" 163 << "a << static_cast< const " << base << "& > (i);" 164 << "}"; 165 166 // operator<< (list_stream) 167 // 168 os << "void" << endl 169 << "operator<< (" << list_stream_type << "& l," << endl 170 << "const " << name << "& i)" 171 << "{" 172 << "l << static_cast< const " << base << "& > (i);" 173 << "}"; 174 175 // Register with type factory map. If this type is anonymous 176 // but substitutes, then it will be registered as part of the 177 // substitution registration. 178 // 179 if (polymorphic && polymorphic_p (u) && !anonymous_p (u)) 180 { 181 // Note that we are using the original type name. 182 // 183 String const& name (ename (u)); 184 185 os << "static" << endl 186 << "const ::xsd::cxx::tree::type_serializer_initializer< " << 187 poly_plate << ", " << char_type << ", " << name << " >" << endl 188 << "_xsd_" << name << "_type_serializer_init (" << endl 189 << strlit (u.name ()) << "," << endl 190 << strlit (xml_ns_name (u)) << ");" 191 << endl 192 << endl; 193 } 194 } 195 }; 196 197 198 struct Enumeration: Traversal::Enumeration, Context 199 { EnumerationCXX::Tree::__anon7e6bba720111::Enumeration200 Enumeration (Context& c) 201 : Context (c), base_ (c) 202 { 203 inherits_base_ >> base_; 204 } 205 206 virtual void traverseCXX::Tree::__anon7e6bba720111::Enumeration207 traverse (Type& e) 208 { 209 String name (ename (e)); 210 211 // If renamed name is empty then we do not need to generate 212 // anything for this type. 213 // 214 if (renamed_type (e, name) && !name) 215 return; 216 217 // operator<< (xercesc::DOMElement) 218 // 219 os << "void" << endl 220 << "operator<< (" << xerces_ns << "::DOMElement& e, " << 221 "const " << name << "& i)" 222 << "{" 223 << "e << static_cast< const "; 224 225 inherits (e, inherits_base_); 226 227 os << "& > (i);" 228 << "}"; 229 230 231 // operator<< (xercesc::DOMAttr) 232 // 233 os << "void" << endl 234 << "operator<< (" << xerces_ns << "::DOMAttr& a, " << 235 "const " << name << "& i)" 236 << "{" 237 << "a << static_cast< const "; 238 239 inherits (e, inherits_base_); 240 241 os << "& > (i);" 242 << "}"; 243 244 245 // operator<< (list_stream) 246 // 247 os << "void" << endl 248 << "operator<< (" << list_stream_type << "& l," << endl 249 << "const " << name << "& i)" 250 << "{" 251 << "l << static_cast< const "; 252 253 inherits (e, inherits_base_); 254 255 os << "& > (i);" 256 << "}"; 257 258 259 // Register with type factory map. If this type is anonymous 260 // but substitutes, then it will be registered as part of the 261 // substitution registration. 262 // 263 if (polymorphic && polymorphic_p (e) && !anonymous_p (e)) 264 { 265 // Note that we are using the original type name. 266 // 267 String const& name (ename (e)); 268 269 os << "static" << endl 270 << "const ::xsd::cxx::tree::type_serializer_initializer< " << 271 poly_plate << ", " << char_type << ", " << name << " >" << endl 272 << "_xsd_" << name << "_type_serializer_init (" << endl 273 << strlit (e.name ()) << "," << endl 274 << strlit (xml_ns_name (e)) << ");" 275 << endl 276 << endl; 277 } 278 } 279 280 private: 281 Traversal::Inherits inherits_base_; 282 BaseTypeName base_; 283 }; 284 285 struct Element: Traversal::Element, Context 286 { ElementCXX::Tree::__anon7e6bba720111::Element287 Element (Context& c, String const& scope_) 288 : Context (c), scope (scope_) 289 { 290 } 291 292 virtual void traverseCXX::Tree::__anon7e6bba720111::Element293 traverse (Type& e) 294 { 295 if (skip (e)) 296 return; 297 298 SemanticGraph::Complex& c ( 299 dynamic_cast<SemanticGraph::Complex&> (e.scope ())); 300 301 bool ordered (ordered_p (c)); 302 303 String const& aname (eaname (e)); 304 String ns (e.qualified_p () ? e.namespace_ ().name () : ""); 305 String type (scope + L"::" + etype (e)); 306 307 // Check if we need to handle xsi:type and substitution groups. 308 // If this element's type is anonymous then we don't need to do 309 // anything. Note that if the type is anonymous then it can't be 310 // derived from which makes it impossible to substitute or 311 // dynamically-type with xsi:type. 312 // 313 SemanticGraph::Type& t (e.type ()); 314 bool poly (polymorphic && polymorphic_p (t) && !anonymous_p (t)); 315 316 os << "// " << comment (e.name ()) << endl 317 << "//" << endl; 318 319 if (ordered) 320 os << "case " << scope << "::" << 321 e.context ().get<String> ("ordered-id-name") << ":" 322 << "{"; 323 324 if (poly) 325 { 326 os << (ordered ? "" : "{") 327 << "::xsd::cxx::tree::type_serializer_map< " << char_type 328 << " >& tsm (" << endl 329 << "::xsd::cxx::tree::type_serializer_map_instance< " << 330 poly_plate << ", " << char_type << " > ());" 331 << endl; 332 } 333 334 if (max (e) != 1) 335 { 336 // sequence 337 // 338 if (ordered) 339 os << "const " << type << "& x (i." << aname << 340 " ()[b->index]);" 341 << endl; 342 else 343 os << "for (" << scope << "::" << econst_iterator (e) << endl 344 << "b (i." << aname << " ().begin ()), " << 345 "n (i." << aname << " ().end ());" << endl 346 << "b != n; ++b)" 347 << "{"; 348 349 char const* x (ordered ? "x" : "*b"); 350 351 if (poly) 352 { 353 os << "if (typeid (" << type << ") == typeid (" << x << "))" 354 << "{" 355 << xerces_ns << "::DOMElement& s (" << endl 356 << "::xsd::cxx::xml::dom::create_element (" << endl 357 << strlit (e.name ()) << "," << endl 358 << (ns ? strlit (ns) + L",\n" : L"") 359 << "e));" 360 << endl 361 << "s << " << x << ";" 362 << "}" 363 << "else" << endl 364 << "tsm.serialize (" << endl 365 << strlit (e.name ()) << "," << endl 366 << strlit (ns) << "," << endl 367 << (e.global_p () ? "true" : "false") << ", " << 368 (e.qualified_p () ? "true" : "false") << ", e, " << x << ");"; 369 } 370 else 371 { 372 os << xerces_ns << "::DOMElement& s (" << endl 373 << "::xsd::cxx::xml::dom::create_element (" << endl 374 << strlit (e.name ()) << "," << endl 375 << (ns ? strlit (ns) + L",\n" : L"") 376 << "e));" 377 << endl; 378 379 switch (schema_type (t)) 380 { 381 case st_other: 382 { 383 os << "s << " << x << ";"; 384 break; 385 } 386 case st_double: 387 { 388 os << "s << " << as_double_type << " (" << x << ");"; 389 break; 390 } 391 case st_decimal: 392 { 393 os << "s << " << as_decimal_type << " (" << x << ");"; 394 break; 395 } 396 } 397 } 398 } 399 else if (min (e) == 0) 400 { 401 // optional 402 // 403 if (!ordered) 404 os << "if (i." << aname << " ())" 405 << "{"; 406 407 if (poly) 408 { 409 os << "const " << type << "& x (*i." << aname << " ());" 410 << "if (typeid (" << type << ") == typeid (x))" 411 << "{" 412 << xerces_ns << "::DOMElement& s (" << endl 413 << "::xsd::cxx::xml::dom::create_element (" << endl 414 << strlit (e.name ()) << "," << endl 415 << (ns ? strlit (ns) + L",\n" : L"") 416 << "e));" 417 << endl 418 << "s << x;" 419 << "}" 420 << "else" << endl 421 << "tsm.serialize (" << endl 422 << strlit (e.name ()) << "," << endl 423 << strlit (ns) << "," << endl 424 << (e.global_p () ? "true" : "false") << ", " << 425 (e.qualified_p () ? "true" : "false") << ", e, x);"; 426 } 427 else 428 { 429 os << xerces_ns << "::DOMElement& s (" << endl 430 << "::xsd::cxx::xml::dom::create_element (" << endl 431 << strlit (e.name ()) << "," << endl 432 << (ns ? strlit (ns) + L",\n" : L"") 433 << "e));" 434 << endl; 435 436 switch (schema_type (t)) 437 { 438 case st_other: 439 { 440 os << "s << *i." << aname << " ();"; 441 break; 442 } 443 case st_double: 444 { 445 os << "s << " << as_double_type << "(*i." << aname << " ());"; 446 break; 447 } 448 case st_decimal: 449 { 450 os << "s << " << as_decimal_type << "(*i." << aname << " ());"; 451 break; 452 } 453 } 454 } 455 } 456 else 457 { 458 // one 459 // 460 if (poly) 461 { 462 os << "const " << type << "& x (i." << aname << " ());" 463 << "if (typeid (" << type << ") == typeid (x))" 464 << "{" 465 << xerces_ns << "::DOMElement& s (" << endl 466 << "::xsd::cxx::xml::dom::create_element (" << endl 467 << strlit (e.name ()) << "," << endl 468 << (ns ? strlit (ns) + L",\n" : L"") 469 << "e));" 470 << endl 471 << "s << x;" 472 << "}" 473 << "else" << endl 474 << "tsm.serialize (" << endl 475 << strlit (e.name ()) << "," << endl 476 << strlit (ns) << "," << endl 477 << (e.global_p () ? "true" : "false") << ", " << 478 (e.qualified_p () ? "true" : "false") << ", e, x);"; 479 } 480 else 481 { 482 if (!ordered) 483 os << "{"; 484 485 os << xerces_ns << "::DOMElement& s (" << endl 486 << "::xsd::cxx::xml::dom::create_element (" << endl 487 << strlit (e.name ()) << "," << endl 488 << (ns ? strlit (ns) + L",\n" : L"") 489 << "e));" 490 << endl; 491 492 switch (schema_type (t)) 493 { 494 case st_other: 495 { 496 os << "s << i." << aname << " ();"; 497 break; 498 } 499 case st_double: 500 { 501 os << "s << " << as_double_type << "(i." << aname << " ());"; 502 break; 503 } 504 case st_decimal: 505 { 506 os << "s << " << as_decimal_type << "(i." << aname << " ());"; 507 break; 508 } 509 } 510 } 511 } 512 513 if (ordered) 514 { 515 // See comment for bool text (false); below. 516 // 517 if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) 518 os << "text = true;"; 519 520 os << "continue;" 521 << "}"; 522 } 523 else 524 { 525 os << "}"; 526 527 if (poly && (max (e) != 1 || min (e) == 0)) 528 os << "}"; // There is no extra block for poly one. 529 } 530 } 531 532 private: 533 String scope; 534 }; 535 536 struct Any: Traversal::Any, Context 537 { AnyCXX::Tree::__anon7e6bba720111::Any538 Any (Context& c, String const& scope_) 539 : Context (c), scope (scope_) 540 { 541 } 542 543 virtual void traverseCXX::Tree::__anon7e6bba720111::Any544 traverse (Type& a) 545 { 546 SemanticGraph::Complex& c ( 547 dynamic_cast<SemanticGraph::Complex&> (a.scope ())); 548 549 bool ordered (ordered_p (c)); 550 551 String const& aname (eaname (a)); 552 553 os << "// " << ename (a) << endl 554 << "//" << endl; 555 556 if (ordered) 557 os << "case " << scope << "::" << 558 a.context ().get<String> ("ordered-id-name") << ":"; 559 560 if (max (a) != 1) 561 { 562 // sequence 563 // 564 if (!ordered) 565 os << "for (" << scope << "::" << econst_iterator (a) << endl 566 << "b (i." << aname << " ().begin ()), " << 567 "n (i." << aname << " ().end ());" << endl 568 << "b != n; ++b)"; 569 570 os << "{" 571 << "e.appendChild (" << endl 572 << "e.getOwnerDocument ()->importNode (" << endl 573 << "const_cast< " << xerces_ns << 574 "::DOMElement* > (&(" << 575 (ordered ? (L"i." + aname + L" ()[b->index]") : L"*b") << 576 ")), true));"; 577 } 578 else if (min (a) == 0) 579 { 580 // optional 581 // 582 if (!ordered) 583 os << "if (i." << aname << " ())"; 584 585 os << "{" 586 << "e.appendChild (" << endl 587 << "e.getOwnerDocument ()->importNode (" << endl 588 << "const_cast< " << xerces_ns << "::DOMElement* > (&(*i." << 589 aname << " ())), true));"; 590 } 591 else 592 { 593 // one 594 // 595 if (ordered) 596 os << "{"; 597 598 os << "e.appendChild (" << endl 599 << "e.getOwnerDocument ()->importNode (" << endl 600 << "const_cast< " << xerces_ns << "::DOMElement* > (&(i." << 601 aname << " ())), true));" 602 << endl; 603 } 604 605 if (ordered) 606 { 607 // See comment for bool text (false); below. 608 // 609 if (mixed_p (c) && c.context ().get<size_t> ("ordered-start") != 1) 610 os << "text = true;"; 611 612 os << "continue;"; 613 } 614 615 if (ordered || max (a) != 1 || min (a) == 0) 616 os << "}"; 617 } 618 619 private: 620 String scope; 621 }; 622 623 struct Attribute: Traversal::Attribute, Context 624 { AttributeCXX::Tree::__anon7e6bba720111::Attribute625 Attribute (Context& c, String const& scope_) 626 : Context (c), scope (scope_) 627 { 628 } 629 630 virtual void traverseCXX::Tree::__anon7e6bba720111::Attribute631 traverse (Type& a) 632 { 633 String const& aname (eaname (a)); 634 String ns (a.qualified_p () ? a.namespace_ ().name () : ""); 635 636 os << "// " << comment (a.name ()) << endl 637 << "//" << endl; 638 639 if (a.optional_p () && !a.default_p ()) 640 { 641 os << "if (i." << aname << " ())" 642 << "{" 643 << xerces_ns << "::DOMAttr& a (" << endl 644 << "::xsd::cxx::xml::dom::create_attribute (" << endl 645 << strlit (a.name ()) << "," << endl 646 << (ns ? strlit (ns) + L",\n" : L"") 647 << "e));" 648 << endl; 649 650 switch (schema_type (a.type ())) 651 { 652 case st_other: 653 { 654 os << "a << *i." << aname << " ();"; 655 break; 656 } 657 case st_double: 658 { 659 os << "a << " << as_double_type << "(*i." << aname << " ());"; 660 break; 661 } 662 case st_decimal: 663 { 664 os << "a << " << as_decimal_type << "(*i." << aname << " ());"; 665 break; 666 } 667 } 668 669 os << "}"; 670 } 671 else 672 { 673 // Make sure we serialize required fixed attributes. 674 // 675 if (a.optional_p () && options.omit_default_attributes ()) 676 { 677 os << "if (i." << aname << " () != " << scope << 678 "::" << edefault_value (a) << " ())"; 679 } 680 681 os << "{" 682 << xerces_ns << "::DOMAttr& a (" << endl 683 << "::xsd::cxx::xml::dom::create_attribute (" << endl 684 << strlit (a.name ()) << "," << endl 685 << (ns ? strlit (ns) + L",\n" : L"") 686 << "e));" 687 << endl; 688 689 switch (schema_type (a.type ())) 690 { 691 case st_other: 692 { 693 os << "a << i." << aname << " ();"; 694 break; 695 } 696 case st_double: 697 { 698 os << "a << " << as_double_type << "(i." << aname << " ());"; 699 break; 700 } 701 case st_decimal: 702 { 703 os << "a << " << as_decimal_type << "(i." << aname << " ());"; 704 break; 705 } 706 } 707 708 os << "}"; 709 } 710 } 711 712 private: 713 String scope; 714 }; 715 716 struct AnyAttribute: Traversal::AnyAttribute, Context 717 { AnyAttributeCXX::Tree::__anon7e6bba720111::AnyAttribute718 AnyAttribute (Context& c, String const& scope_) 719 : Context (c), scope (scope_) 720 { 721 } 722 723 virtual void traverseCXX::Tree::__anon7e6bba720111::AnyAttribute724 traverse (Type& a) 725 { 726 String const& aname (eaname (a)); 727 728 os << "// " << ename (a) << endl 729 << "//" << endl; 730 731 os << "for (" << scope << "::" << econst_iterator (a) << endl 732 << "b (i." << aname << " ().begin ()), " << 733 "n (i." << aname << " ().end ());" << endl 734 << "b != n; ++b)" 735 << "{" 736 << xerces_ns << "::DOMAttr* a (" << endl 737 << "static_cast< " << xerces_ns << "::DOMAttr* > (" << endl 738 << "e.getOwnerDocument ()->importNode (" << endl 739 << "const_cast< " << xerces_ns << "::DOMAttr* > (&(*b)), true)));" 740 << endl 741 << "if (a->getLocalName () == 0)" << endl 742 << "e.setAttributeNode (a);" 743 << "else" << endl 744 << "e.setAttributeNodeNS (a);" 745 << "}"; 746 } 747 748 private: 749 String scope; 750 }; 751 752 struct Complex: Traversal::Complex, Context 753 { ComplexCXX::Tree::__anon7e6bba720111::Complex754 Complex (Context& c) 755 : Context (c), base_ (c) 756 { 757 inherits_ >> base_; 758 } 759 760 virtual void traverseCXX::Tree::__anon7e6bba720111::Complex761 traverse (Type& c) 762 { 763 SemanticGraph::Context& ctx (c.context ()); 764 765 String name (ename (c)); 766 767 // If renamed name is empty then we do not need to generate 768 // anything for this type. 769 // 770 if (renamed_type (c, name) && !name) 771 return; 772 773 // operator<< (xercesc::DOMElement) 774 // 775 os << "void" << endl 776 << "operator<< (" << xerces_ns << "::DOMElement& e, " << 777 "const " << name << "& i)" 778 << "{"; 779 780 if (c.inherits_p ()) 781 { 782 os << "e << static_cast< const "; 783 inherits (c, inherits_); 784 os << "& > (i);" 785 << endl; 786 } 787 else 788 os << "e << static_cast< const " << any_type << "& > (i);" 789 << endl; 790 791 // Serialize anyAttribute content first so that is gets 792 // overriden by schema-defined attributes. 793 // 794 if (options.generate_wildcard ()) 795 { 796 AnyAttribute any_attribute (*this, name); 797 Traversal::Names names (any_attribute); 798 799 Complex::names (c, names); 800 } 801 802 { 803 bool o (ordered_p (c)); 804 size_t start, count; 805 806 if (o) 807 { 808 start = ctx.get<size_t> ("ordered-start"); 809 count = ctx.get<size_t> ("ordered-count"); 810 811 if (start != count) 812 { 813 String const& ci (ctx.get<String> ("order-const-iterator")); 814 String const& an (ctx.get<String> ("order-aname")); 815 816 // If we have mixed content and a base, then we have to 817 // skip the text content until we serialize one of "our" 818 // elements. 819 // 820 if (mixed_p (c) && start != 1) 821 os << "bool text (false);" 822 << endl; 823 824 os << "for (" << name << "::" << ci << endl 825 << "b (i." << an << " ().begin ()), n (i." << an << 826 " ().end ());" << endl 827 << "b != n; ++b)" 828 << "{" 829 << "switch (b->id)" 830 << "{"; 831 } 832 } 833 834 Traversal::Names names; 835 Any any (*this, name); 836 Element element (*this, name); 837 838 names >> element; 839 840 if (options.generate_wildcard ()) 841 names >> any; 842 843 Complex::names (c, names); 844 845 if (o) 846 { 847 if (start != count) 848 { 849 if (mixed_p (c)) 850 { 851 //@@ propagate mixed-ordered-id to derived 852 853 os << "// text_content" << endl 854 << "//" << endl 855 << "case " << name << "::" << 856 ctx.get<String> ("mixed-ordered-id-name") << ":" 857 << "{"; 858 859 // See the comment above. 860 // 861 if (start != 1) 862 os << "if (text)" << endl; 863 864 os << "e.appendChild (" << endl 865 << "e.getOwnerDocument ()->createTextNode (" << endl 866 << "::xsd::cxx::xml::string (" << endl 867 << "i." << ctx.get<String> ("mixed-aname") << 868 " ()[b->index].c_str ()).c_str ()));"; 869 870 // os << "e << i." << ctx.get<String> ("mixed-aname") << 871 // " ()[b->index];"; 872 873 os << "continue;" 874 << "}"; 875 } 876 877 // Ignore content before our id range and stop serializing 878 // if we see anything past. This handles inheritance. 879 // 880 os << "default:" 881 << "{"; 882 883 if (start != 1) 884 os << "if (b->id < " << start << "UL)" << endl 885 << "continue;"; 886 887 os << "break;" // Stop (see break below). 888 << "}"; 889 890 os << "}" // switch 891 << "break;" // Unknown element past our elements. 892 << "}"; // for 893 } 894 } 895 } 896 897 { 898 Attribute attribute (*this, name); 899 Traversal::Names names (attribute); 900 Complex::names (c, names); 901 } 902 903 os << "}"; 904 905 bool simple (true); 906 { 907 IsSimpleType t (simple); 908 t.dispatch (c); 909 } 910 911 if (simple) 912 { 913 bool hb (c.inherits_p ()); 914 915 // operator<< (xercesc::DOMAttr) 916 // 917 os << "void" << endl 918 << "operator<< (" << xerces_ns << "::DOMAttr&" << 919 (hb ? " a" : "") << ", " << 920 "const " << name << "&" << (hb ? " i" : "") << ")" 921 << "{"; 922 923 if (hb) 924 { 925 os << "a << static_cast< const "; 926 927 inherits (c, inherits_); 928 929 os << "& > (i);"; 930 } 931 932 os << "}"; 933 934 935 // operator<< (list_stream) 936 // 937 os << "void" << endl 938 << "operator<< (" << list_stream_type << "&" << 939 (hb ? " l" : "") << "," << endl 940 << "const " << name << "&" << (hb ? " i" : "") << ")" 941 << "{"; 942 943 if (hb) 944 { 945 os << "l << static_cast< const "; 946 947 inherits (c, inherits_); 948 949 os << "& > (i);"; 950 } 951 952 os << "}"; 953 } 954 955 // Register with type factory map. If this type is anonymous 956 // but substitutes, then it will be registered as part of the 957 // substitution registration. 958 // 959 if (polymorphic && 960 polymorphic_p (c) && 961 !c.abstract_p () && 962 !anonymous_p (c)) 963 { 964 // Note that we are using the original type name. 965 // 966 String const& name (ename (c)); 967 968 os << "static" << endl 969 << "const ::xsd::cxx::tree::type_serializer_initializer< " << 970 poly_plate << ", " << char_type << ", " << name << " >" << endl 971 << "_xsd_" << name << "_type_serializer_init (" << endl 972 << strlit (c.name ()) << "," << endl 973 << strlit (xml_ns_name (c)) << ");" 974 << endl 975 << endl; 976 } 977 } 978 979 private: 980 Traversal::Inherits inherits_; 981 BaseTypeName base_; 982 }; 983 984 985 // Generate substitution group map entry. 986 // 987 struct GlobalElement: Traversal::Element, 988 GlobalElementBase, 989 Context 990 { GlobalElementCXX::Tree::__anon7e6bba720111::GlobalElement991 GlobalElement (Context& c) 992 : GlobalElementBase (c), Context (c), type_name_ (c) 993 { 994 belongs_ >> type_name_; 995 } 996 997 virtual void traverseCXX::Tree::__anon7e6bba720111::GlobalElement998 traverse (Type& e) 999 { 1000 if (polymorphic && e.substitutes_p ()) 1001 { 1002 Type& r (e.substitutes ().root ()); 1003 1004 String const& name (ename (e)); 1005 1006 os << "static" << endl 1007 << "const ::xsd::cxx::tree::element_serializer_initializer< " << 1008 poly_plate << ", " << char_type << ", "; 1009 1010 belongs (e, belongs_); 1011 1012 os << " >" << endl 1013 << "_xsd_" << name << "_element_serializer_init (" << endl 1014 << strlit (r.name ()) << "," << endl 1015 << strlit (r.namespace_ ().name ()) << "," << endl 1016 << strlit (e.name ()) << "," << endl 1017 << strlit (e.namespace_ ().name ()) << ");" 1018 << endl 1019 << endl; 1020 } 1021 } 1022 1023 private: 1024 Traversal::Belongs belongs_; 1025 MemberTypeName type_name_; 1026 1027 }; 1028 1029 struct ElementType: Traversal::Element, 1030 GlobalElementBase, 1031 Context 1032 { ElementTypeCXX::Tree::__anon7e6bba720111::ElementType1033 ElementType (Context& c) 1034 : GlobalElementBase (c), 1035 Context (c), 1036 element_map_ (c.options.generate_element_map ()) 1037 { 1038 } 1039 1040 virtual void traverseCXX::Tree::__anon7e6bba720111::ElementType1041 traverse (Type& e) 1042 { 1043 if (doc_root_p (e)) 1044 { 1045 String const& name (ename (e)); 1046 1047 // operator<< (xercesc::DOMElement) 1048 // 1049 os << "void" << endl 1050 << "operator<< (" << xerces_ns << "::DOMElement& e, " << 1051 "const " << name << "& i)" 1052 << "{" 1053 << "e << i." << eaname (e) << " ();" 1054 << "}"; 1055 1056 // Element map registration. 1057 // 1058 if (element_map_) 1059 { 1060 SemanticGraph::Context& ec (e.context ()); 1061 String const& aname (ec.get<String> ("element-name")); 1062 String const& ans (ec.get<String> ("element-ns")); 1063 1064 os << "static " << endl 1065 << "const ::xsd::cxx::tree::serializer_init< " << 1066 name << ", " << char_type << ", " << any_type << " >" << endl 1067 << "_xsd_" << name << "_serializer_init (" << 1068 name << "::" << aname << " (), " << 1069 name << "::" << ans << " ());" 1070 << endl; 1071 } 1072 } 1073 } 1074 1075 private: 1076 bool element_map_; 1077 }; 1078 1079 struct ElementFunction: Traversal::Element, 1080 GlobalElementBase, 1081 Context 1082 { ElementFunctionCXX::Tree::__anon7e6bba720111::ElementFunction1083 ElementFunction (Context& c) 1084 : GlobalElementBase (c), Context (c) 1085 { 1086 } 1087 1088 virtual void traverseCXX::Tree::__anon7e6bba720111::ElementFunction1089 traverse (Type& e) 1090 { 1091 if (!doc_root_p (e)) 1092 return; 1093 1094 String const& name (eserializer (e)); 1095 String ns (e.namespace_ ().name ()); 1096 String const& error_handler (error_handler_type); 1097 String const& namespace_infomap (namespace_infomap_type); 1098 1099 SemanticGraph::Type& type (e.type ()); 1100 1101 // Note that I am using fq-name in function calls because g++ gets 1102 // confused if the name is 'type'. (see tests/schema/anonymous) 1103 // 1104 1105 // Check if we need to handle xsi:type and substitution groups. 1106 // If this element's type is anonymous then we don't need to do 1107 // anything. 1108 // 1109 bool poly (polymorphic && 1110 polymorphic_p (type) && 1111 !anonymous_p (type)); 1112 1113 // To std::ostream. 1114 // 1115 os << "void" << endl 1116 << name << " (::std::ostream& o," << endl 1117 << "const " << type_name (e) << "& s," << endl 1118 << "const " << namespace_infomap << "& m," << endl 1119 << "const " << string_type << "& e," << endl 1120 << flags_type << " f)" 1121 << "{" 1122 << "::xsd::cxx::xml::auto_initializer i (" << endl 1123 << "(f & " << flags_type << "::dont_initialize) == 0);" 1124 << endl 1125 << dom_auto_ptr << "< " << xerces_ns << 1126 "::DOMDocument > d (" << endl 1127 << fq_name (e, "serializer") << " (s, m, f));" 1128 << endl 1129 << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" 1130 << endl 1131 << "::xsd::cxx::xml::dom::ostream_format_target t (o);" 1132 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1133 << "{" 1134 << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << 1135 char_type << " > > ();" 1136 << "}" 1137 << "}"; 1138 1139 os << "void" << endl 1140 << name << " (::std::ostream& o," << endl 1141 << "const " << type_name (e) << "& s," << endl 1142 << error_handler << "& h," << endl 1143 << "const " << namespace_infomap << "& m," << endl 1144 << "const " << string_type << "& e," << endl 1145 << flags_type << " f)" 1146 << "{" 1147 << "::xsd::cxx::xml::auto_initializer i (" << endl 1148 << "(f & " << flags_type << "::dont_initialize) == 0);" 1149 << endl 1150 << dom_auto_ptr << "< " << xerces_ns << 1151 "::DOMDocument > d (" << endl 1152 << fq_name (e, "serializer") << " (s, m, f));" 1153 << "::xsd::cxx::xml::dom::ostream_format_target t (o);" 1154 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1155 << "{" 1156 << "throw ::xsd::cxx::tree::serialization< " << 1157 char_type << " > ();" 1158 << "}" 1159 << "}"; 1160 1161 os << "void" << endl 1162 << name << " (::std::ostream& o," << endl 1163 << "const " << type_name (e) << "& s," << endl 1164 << xerces_ns << "::DOMErrorHandler& h," << endl 1165 << "const " << namespace_infomap << "& m," << endl 1166 << "const " << string_type << "& e," << endl 1167 << flags_type << " f)" 1168 << "{" 1169 << dom_auto_ptr << "< " << xerces_ns << 1170 "::DOMDocument > d (" << endl 1171 << fq_name (e, "serializer") << " (s, m, f));" 1172 << "::xsd::cxx::xml::dom::ostream_format_target t (o);" 1173 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1174 << "{" 1175 << "throw ::xsd::cxx::tree::serialization< " << 1176 char_type << " > ();" 1177 << "}" 1178 << "}"; 1179 1180 // To XMLFormatTarget. 1181 // 1182 os << "void" << endl 1183 << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl 1184 << "const " << type_name (e) << "& s," << endl 1185 << "const " << namespace_infomap << "& m," << endl 1186 << "const " << string_type << "& e," << endl 1187 << flags_type << " f)" 1188 << "{" 1189 << dom_auto_ptr << "< " << xerces_ns << 1190 "::DOMDocument > d (" << endl 1191 << fq_name (e, "serializer") << " (s, m, f));" 1192 << endl 1193 << "::xsd::cxx::tree::error_handler< " << char_type << " > h;" 1194 << endl 1195 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1196 << "{" 1197 << "h.throw_if_failed< ::xsd::cxx::tree::serialization< " << 1198 char_type << " > > ();" 1199 << "}" 1200 << "}"; 1201 1202 os << "void" << endl 1203 << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl 1204 << "const " << type_name (e) << "& s," << endl 1205 << error_handler << "& h," << endl 1206 << "const " << namespace_infomap << "& m," << endl 1207 << "const " << string_type << "& e," << endl 1208 << flags_type << " f)" 1209 << "{" 1210 << dom_auto_ptr << "< " << xerces_ns << 1211 "::DOMDocument > d (" << endl 1212 << fq_name (e, "serializer") << " (s, m, f));" 1213 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1214 << "{" 1215 << "throw ::xsd::cxx::tree::serialization< " << 1216 char_type << " > ();" 1217 << "}" 1218 << "}"; 1219 1220 os << "void" << endl 1221 << name << " (" << xerces_ns << "::XMLFormatTarget& t," << endl 1222 << "const " << type_name (e) << "& s," << endl 1223 << xerces_ns << "::DOMErrorHandler& h," << endl 1224 << "const " << namespace_infomap << "& m," << endl 1225 << "const " << string_type << "& e," << endl 1226 << flags_type << " f)" 1227 << "{" 1228 << dom_auto_ptr << "< " << xerces_ns << 1229 "::DOMDocument > d (" << endl 1230 << fq_name (e, "serializer") << " (s, m, f));" 1231 << "if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f))" 1232 << "{" 1233 << "throw ::xsd::cxx::tree::serialization< " << 1234 char_type << " > ();" 1235 << "}" 1236 << "}"; 1237 1238 // To an existing DOM instance. 1239 // 1240 os << "void" << endl 1241 << name << " (" << xerces_ns << "::DOMDocument& d," << endl 1242 << "const " << type_name (e) << "& s," << endl 1243 << flags_type << ")" 1244 << "{" 1245 << xerces_ns << "::DOMElement& e (*d.getDocumentElement ());" 1246 << "const " << qname_type << " n (" << endl 1247 << "::xsd::cxx::xml::dom::name< " << char_type << " > (e));" 1248 << endl; 1249 1250 if (poly) 1251 { 1252 os << "if (typeid (" << type_name (e) << ") == typeid (s))" 1253 << "{"; 1254 } 1255 1256 os << "if (n.name () == " << strlit (e.name ()) << " &&" << endl 1257 << "n.namespace_ () == " << strlit (ns) << ")" 1258 << "{"; 1259 1260 switch (schema_type (type)) 1261 { 1262 case st_other: 1263 { 1264 os << "e << s;"; 1265 break; 1266 } 1267 case st_double: 1268 { 1269 os << "e << " << as_double_type << "(s);"; 1270 break; 1271 } 1272 case st_decimal: 1273 { 1274 os << "e << " << as_decimal_type << "(s);"; 1275 break; 1276 } 1277 } 1278 1279 os << "}" 1280 << "else" 1281 << "{" 1282 << "throw ::xsd::cxx::tree::unexpected_element < " << 1283 char_type << " > (" << endl 1284 << "n.name ()," << endl 1285 << "n.namespace_ ()," << endl 1286 << strlit (e.name ()) << "," << endl 1287 << strlit (ns) << ");" 1288 << "}"; 1289 1290 if (poly) 1291 { 1292 os << "}" 1293 << "else" 1294 << "{" 1295 << "::xsd::cxx::tree::type_serializer_map_instance< " << 1296 poly_plate << ", " << char_type << " > ().serialize (" << endl 1297 << strlit (e.name ()) << "," << endl 1298 << strlit (e.namespace_().name ()) << "," << endl 1299 << "e, n, s);" 1300 << "}"; 1301 } 1302 1303 os << "}"; 1304 1305 1306 // To a new DOM instance. 1307 // 1308 os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument >" << endl 1309 << name << " (const " << type_name (e) << "& s," << endl 1310 << "const " << namespace_infomap << "& m," << endl 1311 << flags_type << " f)" 1312 << "{"; 1313 1314 if (poly) 1315 { 1316 os << dom_auto_ptr << "< " << xerces_ns << "::DOMDocument > d;" 1317 << endl 1318 << "if (typeid (" << type_name (e) << ") == typeid (s))" 1319 << "{" 1320 << "d = ::xsd::cxx::xml::dom::serialize< " << 1321 char_type << " > (" << endl 1322 << strlit (e.name ()) << "," << endl 1323 << strlit (ns) << "," << endl 1324 << "m, f);" 1325 << "}" 1326 << "else" 1327 << "{" 1328 << "d = ::xsd::cxx::tree::type_serializer_map_instance< " << 1329 poly_plate << ", " << char_type << " > ().serialize (" << endl 1330 << strlit (e.name ()) << "," << endl 1331 << strlit (e.namespace_().name ()) << "," << endl 1332 << "m, s, f);" 1333 << "}"; 1334 } 1335 else 1336 { 1337 os << dom_auto_ptr << "< " << xerces_ns << 1338 "::DOMDocument > d (" << endl 1339 << "::xsd::cxx::xml::dom::serialize< " << 1340 char_type << " > (" << endl 1341 << strlit (e.name ()) << "," << endl 1342 << strlit (ns) << "," << endl 1343 << "m, f));" 1344 << endl; 1345 } 1346 1347 os << fq_name (e, "serializer") << " (*d, s, f);" 1348 << "return d;" 1349 << "}"; 1350 1351 } 1352 1353 private: 1354 String type_nameCXX::Tree::__anon7e6bba720111::ElementFunction1355 type_name (Type& e) 1356 { 1357 std::wostringstream o; 1358 1359 MemberTypeName type (*this, o); 1360 type.dispatch (e.type ()); 1361 1362 return o.str (); 1363 } 1364 }; 1365 } 1366 1367 void generate_serialization_source(Context & ctx,size_t first,size_t last)1368 generate_serialization_source (Context& ctx, size_t first, size_t last) 1369 { 1370 bool elemen_type (ctx.options.generate_element_type ()); 1371 1372 if (!elemen_type) 1373 ctx.os << "#include <ostream>" << endl 1374 << "#include <xsd/cxx/tree/error-handler.hxx>" << endl; 1375 1376 ctx.os << "#include <xsd/cxx/xml/dom/serialization-source.hxx>" << endl 1377 << endl; 1378 1379 if (ctx.polymorphic) 1380 { 1381 ctx.os << "#include <xsd/cxx/tree/type-serializer-map.hxx>" << endl 1382 << endl; 1383 1384 bool import_maps (ctx.options.import_maps ()); 1385 bool export_maps (ctx.options.export_maps ()); 1386 1387 if (import_maps || export_maps) 1388 { 1389 ctx.os << "#ifndef XSD_NO_EXPORT" << endl 1390 << endl 1391 << "namespace xsd" 1392 << "{" 1393 << "namespace cxx" 1394 << "{" 1395 << "namespace tree" 1396 << "{" 1397 << "#ifdef _MSC_VER" << endl; 1398 1399 if (export_maps) 1400 ctx.os << "template struct __declspec (dllexport) " << 1401 "type_serializer_plate< " << ctx.poly_plate << ", " << 1402 ctx.char_type << " >;"; 1403 1404 if (import_maps) 1405 ctx.os << "template struct __declspec (dllimport) " << 1406 "type_serializer_plate< " << ctx.poly_plate << ", " << 1407 ctx.char_type << " >;"; 1408 1409 ctx.os << "#elif defined(__GNUC__) && __GNUC__ >= 4" << endl 1410 << "template struct __attribute__ ((visibility(\"default\"))) " << 1411 "type_serializer_plate< " << ctx.poly_plate << ", " << 1412 ctx.char_type << " >;"; 1413 1414 ctx.os << "#elif defined(XSD_MAP_VISIBILITY)" << endl 1415 << "template struct XSD_MAP_VISIBILITY " << 1416 "type_serializer_plate< " << ctx.poly_plate << ", " << 1417 ctx.char_type << " >;"; 1418 1419 ctx.os << "#endif" << endl 1420 << "}" // tree 1421 << "}" // cxx 1422 << "}" // xsd 1423 << "#endif // XSD_NO_EXPORT" << endl 1424 << endl; 1425 } 1426 1427 ctx.os << "namespace _xsd" 1428 << "{" 1429 << "static" << endl 1430 << "const ::xsd::cxx::tree::type_serializer_plate< " << 1431 ctx.poly_plate << ", " << ctx.char_type << " >" << endl 1432 << "type_serializer_plate_init;" 1433 << "}"; 1434 } 1435 1436 Traversal::Schema schema; 1437 1438 Sources sources; 1439 Traversal::Names names_ns, names; 1440 1441 Namespace ns (ctx, first, last); 1442 1443 List list (ctx); 1444 Union union_ (ctx); 1445 Complex complex (ctx); 1446 Enumeration enumeration (ctx); 1447 GlobalElement element (ctx); 1448 ElementType element_type (ctx); 1449 ElementFunction element_function (ctx); 1450 1451 1452 schema >> sources >> schema; 1453 schema >> names_ns >> ns >> names; 1454 1455 names >> list; 1456 names >> union_; 1457 names >> complex; 1458 names >> enumeration; 1459 names >> element; 1460 1461 if (elemen_type) 1462 names >> element_type; 1463 else 1464 names >> element_function; 1465 1466 schema.dispatch (ctx.schema_root); 1467 } 1468 } 1469 } 1470