Changeset 21077 in vbox for trunk/include/VBox/xml.h
- Timestamp:
- Jun 30, 2009 3:19:12 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/xml.h
r21073 r21077 1 /** @file 2 * VirtualBox XML helper APIs. 3 */ 4 5 /* 6 * Copyright (C) 2007-2008 Sun Microsystems, Inc. 7 * 8 * This file is part of VirtualBox Open Source Edition (OSE), as 9 * available from http://www.virtualbox.org. This file is free software; 10 * you can redistribute it and/or modify it under the terms of the GNU 11 * General Public License (GPL) as published by the Free Software 12 * Foundation, in version 2 as it comes in the "COPYING" file of the 13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 15 * 16 * The contents of this file may alternatively be used under the terms 17 * of the Common Development and Distribution License Version 1.0 18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 19 * VirtualBox OSE distribution, in which case the provisions of the 20 * CDDL are applicable instead of those of the GPL. 21 * 22 * You may elect to license modified versions of this file under the 23 * terms and conditions of either the GPL or the CDDL or both. 24 * 25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 26 * Clara, CA 95054 USA or visit http://www.sun.com if you need 27 * additional information or have any questions. 28 */ 29 30 #ifndef ___VBox_vboxxml_h 31 #define ___VBox_vboxxml_h 32 33 #ifndef IN_RING3 34 # error "There are no XML APIs available in Ring-0 Context!" 35 #else /* IN_RING3 */ 36 37 /** @def IN_VBOXXML_R3 38 * Used to indicate whether we're inside the same link module as the 39 * XML Settings File Manipulation API. 40 * 41 * @todo should go to a separate common include together with VBOXXML2_CLASS 42 * once there becomes more than one header in the VBoxXML2 library. 43 */ 44 #ifdef DOXYGEN_RUNNING 45 # define IN_VBOXXML_R3 46 #endif 47 48 /** @def VBOXXML_CLASS 49 * Class export/import wrapper. */ 50 #ifdef IN_VBOXXML_R3 51 # define VBOXXML_CLASS DECLEXPORT_CLASS 52 #else 53 # define VBOXXML_CLASS DECLIMPORT_CLASS 54 #endif 55 56 /* 57 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a 58 * result of private data member declarations of some classes below) need to 59 * be exported too to in order to be accessible by clients. 60 * 61 * The alternative is to instantiate a template before the data member 62 * declaration with the VBOXXML_CLASS prefix, but the standard disables 63 * explicit instantiations in a foreign namespace. In other words, a declaration 64 * like: 65 * 66 * template class VBOXXML_CLASS std::auto_ptr <Data>; 67 * 68 * right before the member declaration makes MSVC happy too, but this is not a 69 * valid C++ construct (and G++ spits it out). So, for now we just disable the 70 * warning and will come back to this problem one day later. 71 * 72 * We also disable another warning (4275) saying that a DLL-exported class 73 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory -> 74 * std::bad_alloc). I can't get how it can harm yet. 75 */ 76 #if defined(_MSC_VER) 77 #pragma warning (disable:4251) 78 #pragma warning (disable:4275) 79 #endif 80 81 /* Forwards */ 82 typedef struct _xmlParserInput xmlParserInput; 83 typedef xmlParserInput *xmlParserInputPtr; 84 typedef struct _xmlParserCtxt xmlParserCtxt; 85 typedef xmlParserCtxt *xmlParserCtxtPtr; 86 typedef struct _xmlError xmlError; 87 typedef xmlError *xmlErrorPtr; 88 89 namespace xml 90 { 91 92 // Little string class for XML only 93 ////////////////////////////////////////////////////////////////////////////// 94 95 class ministring 96 { 97 public: 98 ministring() 99 : m_psz(NULL) 100 { 101 } 102 103 ministring(const ministring &s) 104 : m_psz(NULL) 105 { 106 copyFrom(s.c_str()); 107 } 108 109 ministring(const char *pcsz) 110 : m_psz(NULL) 111 { 112 copyFrom(pcsz); 113 } 114 115 ~ministring() 116 { 117 cleanup(); 118 } 119 120 void operator=(const char *pcsz) 121 { 122 cleanup(); 123 copyFrom(pcsz); 124 } 125 126 void operator=(const ministring &s) 127 { 128 cleanup(); 129 copyFrom(s.c_str()); 130 } 131 132 const char* c_str() const 133 { 134 return m_psz; 135 } 136 137 private: 138 void cleanup() 139 { 140 if (m_psz) 141 { 142 RTStrFree(m_psz); 143 m_psz = NULL; 144 } 145 } 146 147 void copyFrom(const char *pcsz) 148 { 149 if (pcsz) 150 m_psz = RTStrDup(pcsz); 151 } 152 153 154 char *m_psz; 155 }; 156 157 // Exceptions 158 ////////////////////////////////////////////////////////////////////////////// 159 160 /** 161 * Base exception class. 162 */ 163 class VBOXXML_CLASS Error : public std::exception 164 { 165 public: 166 167 Error(const char *pcszMessage) 168 : m_pcsz(NULL) 169 { 170 copyFrom(pcszMessage); 171 } 172 173 Error(const Error &s) 174 : std::exception(s) 175 { 176 copyFrom(s.what()); 177 } 178 179 virtual ~Error() throw() 180 { 181 cleanup(); 182 } 183 184 void operator=(const Error &s) 185 { 186 cleanup(); 187 copyFrom(s.what()); 188 } 189 190 void setWhat(const char *pcszMessage) 191 { 192 cleanup(); 193 copyFrom(pcszMessage); 194 } 195 196 virtual const char* what() const throw() 197 { 198 return m_pcsz; 199 } 200 201 private: 202 Error() {}; // hide the default constructor to make sure the extended one above is always used 203 204 void cleanup() 205 { 206 if (m_pcsz) 207 { 208 RTStrFree(m_pcsz); 209 m_pcsz = NULL; 210 } 211 } 212 213 void copyFrom(const char *pcszMessage) 214 { 215 if (pcszMessage) 216 m_pcsz = RTStrDup(pcszMessage); 217 } 218 219 char *m_pcsz; 220 }; 221 222 class VBOXXML_CLASS LogicError : public Error 223 { 224 public: 225 226 LogicError(const char *aMsg = NULL) 227 : xml::Error(aMsg) 228 {} 229 230 LogicError(RT_SRC_POS_DECL); 231 }; 232 233 class VBOXXML_CLASS RuntimeError : public Error 234 { 235 public: 236 237 RuntimeError(const char *aMsg = NULL) 238 : xml::Error(aMsg) 239 {} 240 }; 241 242 class VBOXXML_CLASS XmlError : public RuntimeError 243 { 244 public: 245 XmlError(xmlErrorPtr aErr); 246 247 static char *Format(xmlErrorPtr aErr); 248 }; 249 250 // Logical errors 251 ////////////////////////////////////////////////////////////////////////////// 252 253 class VBOXXML_CLASS ENotImplemented : public LogicError 254 { 255 public: 256 ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {} 257 ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 258 }; 259 260 class VBOXXML_CLASS EInvalidArg : public LogicError 261 { 262 public: 263 EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {} 264 EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 265 }; 266 267 class VBOXXML_CLASS EDocumentNotEmpty : public LogicError 268 { 269 public: 270 EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {} 271 EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 272 }; 273 274 class VBOXXML_CLASS ENodeIsNotElement : public LogicError 275 { 276 public: 277 ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {} 278 ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {} 279 }; 280 281 // Runtime errors 282 ////////////////////////////////////////////////////////////////////////////// 283 284 class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc 285 { 286 public: 287 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {} 288 virtual ~ENoMemory() throw() {} 289 }; 290 291 class VBOXXML_CLASS EIPRTFailure : public RuntimeError 292 { 293 public: 294 295 EIPRTFailure (int aRC); 296 297 int rc() const { return mRC; } 298 299 private: 300 int mRC; 301 }; 302 303 304 /** 305 * The Stream class is a base class for I/O streams. 306 */ 307 class VBOXXML_CLASS Stream 308 { 309 public: 310 311 virtual ~Stream() {} 312 313 virtual const char *uri() const = 0; 314 315 /** 316 * Returns the current read/write position in the stream. The returned 317 * position is a zero-based byte offset from the beginning of the file. 318 * 319 * Throws ENotImplemented if this operation is not implemented for the 320 * given stream. 321 */ 322 virtual uint64_t pos() const = 0; 323 324 /** 325 * Sets the current read/write position in the stream. 326 * 327 * @param aPos Zero-based byte offset from the beginning of the stream. 328 * 329 * Throws ENotImplemented if this operation is not implemented for the 330 * given stream. 331 */ 332 virtual void setPos (uint64_t aPos) = 0; 333 }; 334 335 /** 336 * The Input class represents an input stream. 337 * 338 * This input stream is used to read the settings tree from. 339 * This is an abstract class that must be subclassed in order to fill it with 340 * useful functionality. 341 */ 342 class VBOXXML_CLASS Input : virtual public Stream 343 { 344 public: 345 346 /** 347 * Reads from the stream to the supplied buffer. 348 * 349 * @param aBuf Buffer to store read data to. 350 * @param aLen Buffer length. 351 * 352 * @return Number of bytes read. 353 */ 354 virtual int read (char *aBuf, int aLen) = 0; 355 }; 356 357 /** 358 * 359 */ 360 class VBOXXML_CLASS Output : virtual public Stream 361 { 362 public: 363 364 /** 365 * Writes to the stream from the supplied buffer. 366 * 367 * @param aBuf Buffer to write data from. 368 * @param aLen Buffer length. 369 * 370 * @return Number of bytes written. 371 */ 372 virtual int write (const char *aBuf, int aLen) = 0; 373 374 /** 375 * Truncates the stream from the current position and upto the end. 376 * The new file size will become exactly #pos() bytes. 377 * 378 * Throws ENotImplemented if this operation is not implemented for the 379 * given stream. 380 */ 381 virtual void truncate() = 0; 382 }; 383 384 385 ////////////////////////////////////////////////////////////////////////////// 386 387 /** 388 * The File class is a stream implementation that reads from and writes to 389 * regular files. 390 * 391 * The File class uses IPRT File API for file operations. Note that IPRT File 392 * API is not thread-safe. This means that if you pass the same RTFILE handle to 393 * different File instances that may be simultaneously used on different 394 * threads, you should care about serialization; otherwise you will get garbage 395 * when reading from or writing to such File instances. 396 */ 397 class VBOXXML_CLASS File : public Input, public Output 398 { 399 public: 400 401 /** 402 * Possible file access modes. 403 */ 404 enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite }; 405 406 /** 407 * Opens a file with the given name in the given mode. If @a aMode is Read 408 * or ReadWrite, the file must exist. If @a aMode is Write, the file must 409 * not exist. Otherwise, an EIPRTFailure excetion will be thrown. 410 * 411 * @param aMode File mode. 412 * @param aFileName File name. 413 */ 414 File (Mode aMode, const char *aFileName); 415 416 /** 417 * Uses the given file handle to perform file operations. This file 418 * handle must be already open in necessary mode (read, or write, or mixed). 419 * 420 * The read/write position of the given handle will be reset to the 421 * beginning of the file on success. 422 * 423 * Note that the given file handle will not be automatically closed upon 424 * this object destruction. 425 * 426 * @note It you pass the same RTFILE handle to more than one File instance, 427 * please make sure you have provided serialization in case if these 428 * instasnces are to be simultaneously used by different threads. 429 * Otherwise you may get garbage when reading or writing. 430 * 431 * @param aHandle Open file handle. 432 * @param aFileName File name (for reference). 433 */ 434 File (RTFILE aHandle, const char *aFileName = NULL); 435 436 /** 437 * Destroys the File object. If the object was created from a file name 438 * the corresponding file will be automatically closed. If the object was 439 * created from a file handle, it will remain open. 440 */ 441 virtual ~File(); 442 443 const char *uri() const; 444 445 uint64_t pos() const; 446 void setPos (uint64_t aPos); 447 448 /** 449 * See Input::read(). If this method is called in wrong file mode, 450 * LogicError will be thrown. 451 */ 452 int read (char *aBuf, int aLen); 453 454 /** 455 * See Output::write(). If this method is called in wrong file mode, 456 * LogicError will be thrown. 457 */ 458 int write (const char *aBuf, int aLen); 459 460 /** 461 * See Output::truncate(). If this method is called in wrong file mode, 462 * LogicError will be thrown. 463 */ 464 void truncate(); 465 466 private: 467 468 /* Obscure class data */ 469 struct Data; 470 std::auto_ptr <Data> m; 471 472 /* auto_ptr data doesn't have proper copy semantics */ 473 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File) 474 }; 475 476 /** 477 * The MemoryBuf class represents a stream implementation that reads from the 478 * memory buffer. 479 */ 480 class VBOXXML_CLASS MemoryBuf : public Input 481 { 482 public: 483 484 MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL); 485 486 virtual ~MemoryBuf(); 487 488 const char *uri() const; 489 490 int read (char *aBuf, int aLen); 491 uint64_t pos() const; 492 void setPos (uint64_t aPos); 493 494 private: 495 /* Obscure class data */ 496 struct Data; 497 std::auto_ptr <Data> m; 498 499 /* auto_ptr data doesn't have proper copy semantics */ 500 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf) 501 }; 502 503 504 /* 505 * GlobalLock 506 * 507 * 508 */ 509 510 typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI, 511 const char *aID, 512 xmlParserCtxt *aCtxt); 513 typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER; 514 515 class VBOXXML_CLASS GlobalLock 516 { 517 public: 518 GlobalLock(); 519 ~GlobalLock(); 520 521 void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc); 522 523 static xmlParserInput* callDefaultLoader(const char *aURI, 524 const char *aID, 525 xmlParserCtxt *aCtxt); 526 527 private: 528 /* Obscure class data. */ 529 struct Data; 530 struct Data *m; 531 }; 532 533 /** 534 * Node: 535 * an XML node, which represents either an element or text content 536 * or an attribute. 537 * 538 * For elements, getName() returns the element name, and getValue() 539 * returns the text contents, if any. 540 * 541 * For attributes, getName() returns the attribute name, and getValue() 542 * returns the attribute value, if any. 543 * 544 * Since the default constructor is private, one can create new nodes 545 * only through factory methods provided by the XML classes. These are: 546 * 547 * -- xml::Document::createRootElement() 548 * -- xml::Node::createChild() 549 * -- xml::Node::addContent() 550 * -- xml::Node::setAttribute() 551 */ 552 553 class ElementNode; 554 typedef std::list<const ElementNode*> ElementNodesList; 555 556 class AttributeNode; 557 558 class ContentNode; 559 560 class VBOXXML_CLASS Node 561 { 562 public: 563 ~Node(); 564 565 const char* getName() const; 566 const char* getValue() const; 567 bool copyValue(int32_t &i) const; 568 bool copyValue(uint32_t &i) const; 569 bool copyValue(int64_t &i) const; 570 bool copyValue(uint64_t &i) const; 571 572 int getLineNumber() const; 573 574 int isElement() 575 { 576 return mType == IsElement; 577 } 578 579 protected: 580 typedef enum {IsElement, IsAttribute, IsContent} EnumType; 581 EnumType mType; 582 583 // hide the default constructor so people use only our factory methods 584 Node(EnumType type); 585 Node(const Node &x); // no copying 586 587 void buildChildren(); 588 589 /* Obscure class data */ 590 struct Data; 591 Data *m; 592 }; 593 594 class VBOXXML_CLASS ElementNode : public Node 595 { 596 public: 597 int getChildElements(ElementNodesList &children, 598 const char *pcszMatch = NULL) const; 599 600 const ElementNode* findChildElement(const char *pcszMatch) const; 601 const ElementNode* findChildElementFromId(const char *pcszId) const; 602 603 const AttributeNode* findAttribute(const char *pcszMatch) const; 604 bool getAttributeValue(const char *pcszMatch, const char *&ppcsz) const; 605 bool getAttributeValue(const char *pcszMatch, int64_t &i) const; 606 bool getAttributeValue(const char *pcszMatch, uint64_t &i) const; 607 608 ElementNode* createChild(const char *pcszElementName); 609 ContentNode* addContent(const char *pcszContent); 610 AttributeNode* setAttribute(const char *pcszName, const char *pcszValue); 611 612 protected: 613 // hide the default constructor so people use only our factory methods 614 ElementNode(); 615 ElementNode(const ElementNode &x); // no copying 616 617 friend class Node; 618 friend class Document; 619 friend class XmlFileParser; 620 }; 621 622 class VBOXXML_CLASS ContentNode : public Node 623 { 624 public: 625 626 protected: 627 // hide the default constructor so people use only our factory methods 628 ContentNode(); 629 ContentNode(const ContentNode &x); // no copying 630 631 friend class Node; 632 friend class ElementNode; 633 }; 634 635 class VBOXXML_CLASS AttributeNode : public Node 636 { 637 public: 638 639 protected: 640 // hide the default constructor so people use only our factory methods 641 AttributeNode(); 642 AttributeNode(const AttributeNode &x); // no copying 643 644 friend class Node; 645 friend class ElementNode; 646 }; 647 648 /* 649 * NodesLoop 650 * 651 */ 652 653 class VBOXXML_CLASS NodesLoop 654 { 655 public: 656 NodesLoop(const ElementNode &node, const char *pcszMatch = NULL); 657 ~NodesLoop(); 658 const ElementNode* forAllNodes() const; 659 660 private: 661 /* Obscure class data */ 662 struct Data; 663 Data *m; 664 }; 665 666 /* 667 * Document 668 * 669 */ 670 671 class VBOXXML_CLASS Document 672 { 673 public: 674 Document(); 675 ~Document(); 676 677 Document(const Document &x); 678 Document& operator=(const Document &x); 679 680 const ElementNode* getRootElement() const; 681 682 ElementNode* createRootElement(const char *pcszRootElementName); 683 684 private: 685 friend class XmlFileParser; 686 friend class XmlFileWriter; 687 688 void refreshInternals(); 689 690 /* Obscure class data */ 691 struct Data; 692 Data *m; 693 }; 694 695 /* 696 * XmlParserBase 697 * 698 */ 699 700 class VBOXXML_CLASS XmlParserBase 701 { 702 protected: 703 XmlParserBase(); 704 ~XmlParserBase(); 705 706 xmlParserCtxtPtr m_ctxt; 707 }; 708 709 /* 710 * XmlFileParser 711 * 712 */ 713 714 class VBOXXML_CLASS XmlFileParser : public XmlParserBase 715 { 716 public: 717 XmlFileParser(); 718 ~XmlFileParser(); 719 720 void read(const char *pcszFilename, Document &doc); 721 722 private: 723 /* Obscure class data */ 724 struct Data; 725 struct Data *m; 726 727 static int ReadCallback(void *aCtxt, char *aBuf, int aLen); 728 static int CloseCallback (void *aCtxt); 729 }; 730 731 /* 732 * XmlFileWriter 733 * 734 */ 735 736 class VBOXXML_CLASS XmlFileWriter 737 { 738 public: 739 XmlFileWriter(Document &doc); 740 ~XmlFileWriter(); 741 742 void write(const char *pcszFilename); 743 744 static int WriteCallback(void *aCtxt, const char *aBuf, int aLen); 745 static int CloseCallback (void *aCtxt); 746 747 private: 748 /* Obscure class data */ 749 struct Data; 750 Data *m; 751 }; 752 753 #if defined(_MSC_VER) 754 #pragma warning (default:4251) 755 #endif 756 757 #endif /* IN_RING3 */ 758 759 /** @} */ 760 761 } // end namespace xml 762 763 #endif /* ___VBox_vboxxml_h */
Note:
See TracChangeset
for help on using the changeset viewer.