1 /* 2 * simple_actions.h 3 * 4 * 5 * Created by Andreas Vox on 02.06.06. 6 * Copyright 2006 under GPL2. All rights reserved. 7 * 8 */ 9 10 11 12 #ifndef SIMPLE_ACTIONS_H 13 #define SIMPLE_ACTIONS_H 14 15 #include "actions.h" 16 /***** 17 18 Defines the following actions: 19 20 Factory<D>( fun ) - -> D 21 Factory<D>() - -> D 22 Prototype<D>( data ) - -> D 23 Top<O>( 3 ) O x x x -> O x x x O 24 Getter<O,D>( fun ) O -> O D 25 Setter<O,D>( fun ) O D -> O D 26 SetterWithConversion<O,D,S>( fun ) O S -> O S 27 SetAttribute<O,D>( fun, name, default) O -> O 28 SetAttribute<O,D>( fun, name) O -> O 29 SetAttributeWithConversion<O,D>( f, n, c, def) O -> O 30 SetAttributeWithConversion<O,D>( f, n, convert) O -> O 31 SetAttributes<O>( fun ) O -> O 32 SetText<O,D>( fun ) O -> O 33 AddText<O,D>( fun ) O -> O 34 Transform<D,E> ( fun ) D -> E 35 *TransformLater<D,E> ( fun ) D -> E 36 IdRef<O>() O -> O 37 Lookup<D>( name ) - -> D 38 PatchIdRefAttribute<O,D>( fun, name) O -> O 39 Result<O>() O -> O 40 41 *****/ 42 43 44 namespace desaxe { 45 46 using namespace desaxe; 47 48 /** 49 * Pushes a new object of type Obj_Type onto the stack. 50 * Obj_Type needs a default constructor 51 */ 52 template<class Obj_Type> 53 class Factory_body : public Generator_body<Obj_Type> 54 { 55 public: 56 typedef Obj_Type* (*FunType)(); 57 Factory_body()58 Factory_body() 59 : create_(nullptr) 60 {} 61 Factory_body(FunType create)62 Factory_body(FunType create) 63 : create_(create) 64 {} 65 begin(const Xml_string &,Xml_attr)66 void begin(const Xml_string&, Xml_attr) 67 { 68 this->dig->push(create_? create_() : new Obj_Type()); 69 } 70 private: 71 Obj_Type* (*create_)(); 72 }; 73 74 template <class Type> 75 struct Factory : public MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType> 76 { FactoryFactory77 Factory(typename Factory_body<Type>::FunType create) 78 : MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>(create) {} 79 FactoryFactory80 Factory() 81 : MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>() {} 82 }; 83 84 85 /** 86 * Pushes a new object of type Obj_Type onto the stack. 87 */ 88 template<class Obj_Type> 89 class FactoryWithArgs_body : public Generator_body<Obj_Type> 90 { 91 public: 92 typedef Obj_Type* (*FunType)(const Xml_string&, Xml_attr); 93 FactoryWithArgs_body(FunType create)94 FactoryWithArgs_body(FunType create) 95 : create_(create) 96 {} 97 begin(const Xml_string & name,Xml_attr attr)98 void begin(const Xml_string& name, Xml_attr attr) 99 { 100 this->dig->push(create_(name, attr)); 101 } 102 private: 103 Obj_Type* (*create_)(const Xml_string&, Xml_attr); 104 }; 105 106 template <class Type> 107 struct FactoryWithArgs : public MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType> 108 { FactoryWithArgsFactoryWithArgs109 FactoryWithArgs(typename FactoryWithArgs_body<Type>::FunType create) 110 : MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType>::MakeGenerator(create) {} 111 }; 112 113 114 /** 115 * Pushes a new object of type Obj_Type onto the stack which is initialized with the tag name. 116 * If no create method is given, Obj_Type needs a constructor which taks a Xml_string argument 117 */ 118 template<class Obj_Type> 119 class FactoryWithName_body : public Generator_body<Obj_Type> 120 { 121 public: 122 typedef Obj_Type* (*FunType)(const Xml_string&); 123 FactoryWithName_body()124 FactoryWithName_body() 125 : create_(NULL) 126 {} 127 FactoryWithName_body(FunType create)128 FactoryWithName_body(FunType create) 129 : create_(create) 130 {} 131 begin(const Xml_string & tag,Xml_attr)132 void begin(const Xml_string& tag, Xml_attr) 133 { 134 this->dig->push(create_? create_(tag) : new Obj_Type(tag)); 135 } 136 private: 137 FunType create_; 138 }; 139 140 template <class Type> 141 struct FactoryWithName : public MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType> 142 { FactoryWithNameFactoryWithName143 FactoryWithName() 144 : MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator() {} 145 FactoryWithNameFactoryWithName146 FactoryWithName(typename FactoryWithName_body<Type>::FunType create) 147 : MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator(create) {} 148 }; 149 150 151 /** 152 * Pushes a clone of proto onto the stack. Obj_Type needs a copy constructor 153 */ 154 template<class Obj_Type> 155 class Prototype_body : public Generator_body<Obj_Type> 156 { 157 public: Prototype_body(const Obj_Type & proto)158 Prototype_body(const Obj_Type& proto) 159 : proto_(new Obj_Type(proto)) 160 {} 161 ~Prototype_body()162 ~Prototype_body() 163 { 164 delete proto_; 165 } 166 begin(const Xml_string &,Xml_attr)167 void begin(const Xml_string&, Xml_attr) 168 { 169 this->dig->push(new Obj_Type(proto_)); 170 } 171 private: 172 const Obj_Type* proto_; 173 }; 174 175 176 template <class Type> 177 struct Prototype : public MakeGenerator<Prototype_body<Type>, Type, const Type&> 178 { PrototypePrototype179 Prototype(const Type& def) 180 : MakeGenerator<Prototype_body<Type>, Type, const Type&>::MakeGenerator(def) {} 181 }; 182 183 184 185 /** 186 * Pushes a new pointer to the n-th object on the stack. 187 */ 188 template<class Obj_Type> 189 class Top_body : public Generator_body<Obj_Type> 190 { 191 public: Top_body(unsigned int n)192 Top_body(unsigned int n) 193 : distance(n) 194 {} 195 begin(const Xml_string &,Xml_attr)196 void begin(const Xml_string&, Xml_attr) 197 { 198 this->dig->push(this->dig->template top<Obj_Type>(distance)); 199 } 200 private: 201 unsigned int distance; 202 }; 203 204 205 template <class Type> 206 struct Top : public MakeGenerator<Top_body<Type>, Type, unsigned int> 207 { TopTop208 Top(unsigned int distance) 209 : MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(distance) {} TopTop210 Top() 211 : MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(0) {} 212 }; 213 214 215 216 /** 217 * Reads an object of type Data_Type from the object on top of the stack, 218 * then pushes this Data_Type object onto the stack. 219 */ 220 template<class Obj_Type, class Data_Type> 221 class Getter_body : public Generator_body<Data_Type> 222 { 223 public: 224 typedef const Data_Type& (Obj_Type::*FunType)(); 225 Getter_body(FunType get)226 Getter_body(FunType get) 227 : get_(get) 228 {} 229 begin(const Xml_string &,Xml_attr)230 void begin(const Xml_string&, Xml_attr) 231 { 232 Obj_Type* obj = this->dig->template top<Obj_Type>(1); 233 Data_Type* data = (obj->*get_)(); 234 this->dig->push(data); 235 } 236 private: 237 FunType get_; 238 }; 239 240 241 template <class Type, class Data> 242 struct Getter : public MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType> 243 { GetterGetter244 Getter(typename Getter_body<Type, Data>::FunType get) 245 : MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType>::MakeGenerator(get) {} 246 }; 247 248 249 /** 250 * Writes the topmost object to the topmost object but one on the stack, where the set method takes a pointer 251 */ 252 template<class Obj_Type, class Data_Type, class Store_Type> 253 class SetterP_body : public Action_body 254 { 255 public: 256 typedef void (Obj_Type::*FunType)(Data_Type*); 257 SetterP_body(FunType set)258 SetterP_body(FunType set) 259 : set_(set) 260 {} 261 end(const Xml_string &)262 void end(const Xml_string&) 263 { 264 Store_Type* data = this->dig->template top<Store_Type>(); 265 Obj_Type* obj = this->dig->template top<Obj_Type>(1); 266 #ifdef DESAXE_DEBUG 267 std::cerr << "setter(ptr): " << obj << " .= " << data << "\n"; 268 #endif 269 (obj->*set_)( data ); 270 } 271 private: 272 FunType set_; 273 }; 274 275 276 template <class Type, class Data, class Store = Data> 277 struct SetterP : public MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType> 278 { SetterPSetterP279 SetterP(typename SetterP_body<Type, Data, Store>::FunType set) 280 : MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType>(set) {} 281 }; 282 283 284 /** 285 * Writes the topmost object to the topmost object but one on the stack. 286 */ 287 template<class Obj_Type, class Data_Type> 288 class Setter_body : public Action_body 289 { 290 public: 291 typedef void (Obj_Type::*FunType)(Data_Type); 292 Setter_body(FunType set)293 Setter_body(FunType set) 294 : set_(set) 295 {} 296 end(const Xml_string &)297 void end(const Xml_string&) 298 { 299 Data_Type* data = this->dig->template top<Data_Type>(); 300 Obj_Type* obj = this->dig->template top<Obj_Type>(1); 301 #ifdef DESAXE_DEBUG 302 std::cerr << "setter: " << obj << " .= *(" << data << ")\n"; 303 #endif 304 (obj->*set_)( *data ); 305 } 306 private: 307 FunType set_; 308 }; 309 310 311 template <class Type, class Data> 312 struct Setter : public MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType> 313 { SetterSetter314 Setter(typename Setter_body<Type, Data>::FunType set) 315 : MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType>(set) {} 316 }; 317 318 319 /** 320 * Writes the topmost object to the topmost object but one on the stack. 321 */ 322 template<class Obj_Type, class Data_Type, class Store_Type> 323 class SetterWithConversion_body : public Action_body 324 { 325 public: 326 typedef void (Obj_Type::*FunType)(Data_Type); 327 typedef Data_Type (*ConvType)(Store_Type); 328 SetterWithConversion_body(FunType set,ConvType conv)329 SetterWithConversion_body(FunType set, ConvType conv) 330 : set_(set), conv_(conv) 331 {} 332 end(const Xml_string &)333 void end(const Xml_string&) 334 { 335 Store_Type* data = this->dig->template top<Store_Type>(); 336 Obj_Type* obj = this->dig->template top<Obj_Type>(1); 337 #ifdef DESAXE_DEBUG 338 std::cerr << "setter: " << obj << " .= " << conv_ << "(*" << data << ")\n"; 339 #endif 340 if (conv_) 341 (obj->*set_)( conv_(*data) ); 342 else 343 (obj->*set_)( static_cast<Data_Type>(*data) ); 344 } 345 private: 346 FunType set_; 347 ConvType conv_; 348 }; 349 350 351 template <class Type, class Data, class Store> 352 struct SetterWithConversion : public MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType> 353 { 354 typedef SetterWithConversion_body<Type, Data, Store> BodyType; SetterWithConversionSetterWithConversion355 SetterWithConversion(typename SetterWithConversion_body<Type, Data, Store>::FunType set) 356 : MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, NULL) {} SetterWithConversionSetterWithConversion357 SetterWithConversion(typename BodyType::FunType set, typename SetterWithConversion_body<Type, Data, Store>::ConvType conv) 358 : MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, conv) {} 359 }; 360 361 362 /** 363 * Stores all attributes to the topmost object on the stack. 364 */ 365 template<class Obj_Type> 366 class SetAttributes_body : public Action_body 367 { 368 public: 369 typedef void (Obj_Type::*FunType)(const Xml_string&, const Xml_string&) ; 370 SetAttributes_body(FunType set)371 SetAttributes_body(FunType set) : set_(set) 372 {} 373 begin(const Xml_string &,Xml_attr attr)374 void begin(const Xml_string&, Xml_attr attr) 375 { 376 Obj_Type* obj = this->dig->template top<Obj_Type>(); 377 Xml_attr::iterator it; 378 for(it=attr.begin(); it != attr.end(); ++it) 379 (obj->*set_)( Xml_key(it), Xml_data(it) ); 380 } 381 private: 382 FunType set_; 383 }; 384 385 386 template <class Type> 387 struct SetAttributes : public MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType> 388 { SetAttributesSetAttributes389 SetAttributes(typename SetAttributes_body<Type>::FunType set) 390 : MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType>(set) {} 391 }; 392 393 394 395 /** 396 * Stores named attribute to the topmost object on the stack if attribute present, 397 * or stores defauot if present. 398 */ 399 template<class Obj_Type, class Data_Type> 400 class SetAttribute_body : public Action_body 401 { 402 public: 403 typedef void (Obj_Type::*FunType)(Data_Type) ; 404 SetAttribute_body(FunType set,const Xml_string & name)405 SetAttribute_body(FunType set, const Xml_string& name) 406 : set_(set), name_(name), default_(), hasDefault_(false) 407 {} 408 SetAttribute_body(FunType set,const Xml_string & name,Data_Type deflt)409 SetAttribute_body(FunType set, const Xml_string& name, Data_Type deflt) 410 : set_(set), name_(name), default_(deflt), hasDefault_(true) 411 {} 412 begin(const Xml_string &,Xml_attr attr)413 void begin(const Xml_string&, Xml_attr attr) 414 { 415 Obj_Type* obj = this->dig->template top<Obj_Type>(); 416 Xml_attr::iterator it = attr.find(name_); 417 if (it != attr.end() ) 418 (obj->*set_)( Data_Type(Xml_data(it)) ); 419 else if (hasDefault_) 420 (obj->*set_)( default_ ); 421 } 422 private: 423 FunType set_; 424 Xml_string name_; 425 Data_Type default_; 426 bool hasDefault_; 427 }; 428 429 430 template <class Type, class Data> 431 struct SetAttribute : public MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data> 432 { SetAttributeSetAttribute433 SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name) 434 : MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name) {} 435 SetAttributeSetAttribute436 SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name, Data deflt) 437 : MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name,deflt) {} 438 }; 439 440 441 442 /** 443 * Stores named attribute to the topmost object on the stack if attribute present, 444 * or stores default if present. 445 */ 446 template<class Obj_Type, class Data_Type> 447 class SetAttributeWithConversion_body : public Action_body 448 { 449 public: 450 typedef void (Obj_Type::*FunType)(Data_Type) ; 451 typedef Data_Type (*ConvType)(const Xml_string&); 452 SetAttributeWithConversion_body(FunType set,const Xml_string & name,ConvType conv)453 SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv) 454 : set_(set), name_(name), conv_(conv), default_(), hasDefault_(false) 455 {} 456 SetAttributeWithConversion_body(FunType set,const Xml_string & name,ConvType conv,Data_Type deflt)457 SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv, Data_Type deflt) 458 : set_(set), name_(name), conv_(conv), default_(deflt), hasDefault_(true) 459 {} 460 begin(const Xml_string &,Xml_attr attr)461 void begin(const Xml_string&, Xml_attr attr) 462 { 463 Obj_Type* obj = this->dig->template top<Obj_Type>(); 464 Xml_attr::iterator it = attr.find(name_); 465 if (it != attr.end() && conv_) 466 (obj->*set_)( conv_(Xml_data(it)) ); 467 else if (hasDefault_) 468 (obj->*set_)( default_ ); 469 } 470 private: 471 FunType set_; 472 Xml_string name_; 473 ConvType conv_; 474 Data_Type default_; 475 bool hasDefault_; 476 }; 477 478 479 template <class Type, class Data> 480 struct SetAttributeWithConversion : public MakeAction<SetAttributeWithConversion_body<Type,Data>, typename SetAttributeWithConversion_body<Type,Data>::FunType, const Xml_string&, typename SetAttributeWithConversion_body<Type,Data>::ConvType, Data> 481 { 482 typedef SetAttributeWithConversion_body<Type,Data> BodyType; 483 SetAttributeWithConversionSetAttributeWithConversion484 SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv) 485 : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv) {} 486 SetAttributeWithConversionSetAttributeWithConversion487 SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv, Data deflt) 488 : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv,deflt) {} 489 }; 490 491 492 493 /** 494 * Stores text (PCDATA) in the topmost object on the stack. 495 * This might be called more than once. 496 */ 497 template<class Obj_Type> 498 class AddText_body : public Action_body 499 { 500 public: 501 typedef void (Obj_Type::*FunType)(const Xml_string&); 502 AddText_body(FunType add)503 AddText_body(FunType add) : addT(add) 504 {} 505 chars(const Xml_string & txt)506 void chars(const Xml_string& txt) 507 { 508 Obj_Type* obj = this->dig->template top<Obj_Type>(); 509 (obj->*addT)( txt ); 510 } 511 private: 512 FunType addT; 513 }; 514 515 516 517 template <class Type> 518 struct AddText : public MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType> 519 { AddTextAddText520 AddText(typename AddText_body<Type>::FunType set) 521 : MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType>(set) {} 522 }; 523 524 525 526 527 /** 528 * Collects text (PCDATA) chunks and later stores it in the topmost object 529 * on the stack. 530 * This is only called once at the close tag of the current pattern. 531 * WARNING: not safe for nesting 532 */ 533 template<class Obj_Type> 534 class SetText_body : public Action_body 535 { 536 public: 537 typedef void (Obj_Type::*FunType)(const Xml_string&); 538 SetText_body(FunType set)539 SetText_body(FunType set) : setT(set) 540 {} 541 begin(const Xml_string &,Xml_attr)542 void begin(const Xml_string&, Xml_attr) 543 { 544 txt.clear(); 545 } 546 chars(const Xml_string & chunk)547 void chars(const Xml_string& chunk) 548 { 549 txt += chunk; 550 } 551 end(const Xml_string & tag)552 void end(const Xml_string& tag) 553 { 554 Obj_Type* obj = this->dig->template top<Obj_Type>(); 555 (obj->*setT)( txt ); 556 } 557 558 private: 559 FunType setT; 560 Xml_string txt; 561 }; 562 563 564 565 template <class Type> 566 struct SetText : public MakeAction<SetText_body<Type>, typename SetText_body<Type>::FunType> 567 { 568 typedef SetText_body<Type> BodyType; SetTextSetText569 SetText(typename BodyType::FunType set) 570 : MakeAction<BodyType, typename BodyType::FunType>(set) {} 571 }; 572 573 574 575 576 template<class Obj_Type> 577 class Store_body : public Action_body 578 { 579 public: Store_body(const Xml_string & name)580 Store_body(const Xml_string& name) : m_name(name) {} 581 begin(const Xml_string & tag,Xml_attr attr)582 void begin(const Xml_string& tag, Xml_attr attr) 583 { 584 Obj_Type* obj = this->dig->template top<Obj_Type>(); 585 // qDebug() << QString("Store: %1 <- %2").arg(tag).arg(typeid(obj).name()); 586 this->dig->template store<Obj_Type>(m_name, obj); 587 } 588 589 private: 590 Xml_string m_name; 591 }; 592 593 594 template <class Type> 595 struct Store : public MakeAction<Store_body<Type>, const Xml_string& > 596 { StoreStore597 Store(const Xml_string& name) : MakeAction<Store_body<Type>, const Xml_string& >(name) {} 598 }; 599 600 601 602 /** 603 * This applies "id" and "idref" attributes to the object on top of the stack. 604 * In case of an "id" attribute, if there is no entry with this ID in 605 * the digester's storage, the topmost object is stored there. Otherwise the 606 * topmost object is replaced with the stored object. 607 * In case of an "idref" attribute, if there is no entry with this ID in 608 * the digester's storage, the topmost object is also stored there. Then the 609 * trigger "WithinIdRef" is set during begin() and the processing continues 610 * normally. When end() is called, the topmost object is replaced by the 611 * stored one (this will be a no-op if there wasnt an entry in storage before) 612 */ 613 template<class Obj_Type> 614 class IdRef_body : public Action_body 615 { 616 public: IdRef_body()617 IdRef_body() : stack() {} 618 begin(const Xml_string &,Xml_attr attr)619 void begin(const Xml_string&, Xml_attr attr) 620 { 621 Obj_Type* obj = this->dig->template top<Obj_Type>(); 622 Mode mode; 623 Xml_attr::iterator it = attr.find("id"); 624 if (it != attr.end()) 625 { 626 mode.ID = attr["id"]; 627 mode.isIdRef = false; 628 } 629 else { 630 Xml_attr::iterator it = attr.find("idref"); 631 if (it != attr.end()) 632 { 633 mode.ID = attr["idref"]; 634 mode.isIdRef = true; 635 } 636 else { 637 mode.ID.clear(); 638 mode.isIdRef = false; 639 } 640 } 641 if (!mode.ID.isEmpty()) 642 { 643 Obj_Type* storedObj = this->dig->template lookup<Obj_Type>(mode.ID); 644 if ( !storedObj ) 645 { 646 this->dig->store(mode.ID, obj); 647 } 648 else if ( !mode.isIdRef ) 649 { 650 delete (this->dig->template top<Obj_Type>()); 651 this->dig->pop(); 652 this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID)); 653 } 654 else 655 { 656 // NYI: set trigger 657 } 658 } 659 stack.push_back(mode); 660 661 } end(const Xml_string &)662 void end(const Xml_string&) 663 { 664 Mode mode = stack.back(); 665 stack.pop_back(); 666 if (mode.isIdRef) 667 { 668 delete (this->dig->template top<Obj_Type>()); 669 this->dig->pop(); 670 this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID)); 671 // NYI reset trigger 672 } 673 } 674 private: 675 struct Mode { Xml_string ID; bool isIdRef; }; 676 std::vector<Mode> stack; 677 }; 678 679 680 template <class Type> 681 struct IdRef : public MakeAction<IdRef_body<Type> > 682 {}; 683 684 685 /** 686 * Reads an object of type Data_Type from the digesters 687 * storage and pushes it onto the stack. 688 * WARNING: this might be a NULL pointer 689 */ 690 template<class Data_Type> 691 class Lookup_body : public Generator_body<Data_Type> 692 { 693 public: Lookup_body(const Xml_string & ID)694 Lookup_body(const Xml_string& ID) 695 : ID_(ID) 696 {} 697 begin(const Xml_string &,Xml_attr)698 void begin(const Xml_string&, Xml_attr) 699 { 700 Data_Type* data = this->dig->template lookup<Data_Type>(ID_); 701 this->dig->push(data); 702 } 703 private: 704 Xml_string ID_; 705 }; 706 707 708 template <class Data> 709 struct Lookup : public MakeGenerator<Lookup_body<Data>, const Xml_string&> 710 { LookupLookup711 Lookup(Xml_string ID) 712 : MakeGenerator<Lookup_body<Data>, const Xml_string&>::MakeGenerator(ID) {} 713 }; 714 715 716 717 /** 718 * Transforms the topmost object to the topmost object but one on the stack. // FIXME: this should just be a getter... 719 */ 720 template<class Obj_Type, class Arg_Type> 721 class Transform_body : public Action_body 722 { 723 public: 724 typedef Obj_Type (*FunType)(const Arg_Type&); 725 Transform_body(FunType fun)726 Transform_body(FunType fun) 727 : fun_(fun), stack() 728 {} 729 begin(const Xml_string &,Xml_attr)730 void begin(const Xml_string&, Xml_attr) 731 { 732 Cell cell; 733 cell.arg = this->dig->template top<Arg_Type>(); 734 cell.obj = fun_(*cell.arg); 735 #ifdef DESAXE_DEBUG 736 std::cerr << "transform: " << cell.arg << " -> " << cell.obj << ")\n"; 737 #endif 738 stack.push_back(cell); 739 this->dig->pop(); 740 this->dig->push(&cell.obj); 741 } 742 end(const Xml_string &)743 void end(const Xml_string&) 744 { 745 Cell cell = stack.back(); 746 stack.pop_back(); 747 this->dig->pop(); 748 this->dig->push(cell.arg); 749 } 750 private: 751 FunType fun_; 752 struct Cell { Arg_Type* arg; Obj_Type obj; }; 753 std::vector<Cell> stack; 754 }; 755 756 757 template <class Type, class Arg> 758 struct Transform : public MakeAction<Transform_body<Type, Arg>, typename Transform_body<Type, Arg>::FunType> 759 { 760 typedef Transform_body<Type, Arg> BodyType; TransformTransform761 Transform(typename BodyType::FunType f) : MakeAction<BodyType, typename BodyType::FunType>(f) {} 762 }; 763 764 765 766 767 template<class Obj_Type, class Data_Type> 768 class PatchIdRefAttribute_body : public Action_body 769 { 770 public: 771 typedef void (Obj_Type::*FunType)(Data_Type*) ; 772 PatchIdRefAttribute_body(FunType set,const Xml_string & name)773 PatchIdRefAttribute_body(FunType set, const Xml_string& name) 774 : set_(set), name_(name) 775 {} 776 begin(const Xml_string &,Xml_attr attr)777 void begin(const Xml_string&, Xml_attr attr) 778 { 779 Xml_attr::iterator it = attr.find(name_); 780 if (it != attr.end()) 781 { 782 Obj_Type* obj = this->dig->template top<Obj_Type>(); 783 this->dig->template patchInvoke<Obj_Type,Data_Type>(Xml_data(it), obj, set_); 784 } 785 } 786 private: 787 FunType set_; 788 Xml_string name_; 789 }; 790 791 792 template <class Type, class Data> 793 struct PatchIdRefAttribute : public MakeAction<PatchIdRefAttribute_body<Type,Data>, typename PatchIdRefAttribute_body<Type,Data>::FunType, const Xml_string&> 794 { 795 typedef PatchIdRefAttribute_body<Type,Data> BodyType; PatchIdRefAttributePatchIdRefAttribute796 PatchIdRefAttribute(typename BodyType::FunType set, const Xml_string& name) 797 : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&>(set,name) {} 798 }; 799 800 801 802 803 /** 804 * defines the topmost object as the result 805 */ 806 template<class Data_Type> 807 class Result_body : public Action_body 808 { 809 public: Result_body()810 Result_body() 811 {} 812 end(const Xml_string &)813 void end(const Xml_string&) 814 { 815 this->dig->setResult(dig->template top<Data_Type>()); 816 } 817 }; 818 819 820 821 template <class Data> 822 struct Result : public MakeAction<Result_body<Data> > {}; 823 824 825 } // namespace 826 827 #endif 828