VirtualBox

source: vbox/trunk/include/VBox/xml.h@ 21077

Last change on this file since 21077 was 21077, checked in by vboxsync, 15 years ago

back out r49329, r49331, will start over

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
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 */
82typedef struct _xmlParserInput xmlParserInput;
83typedef xmlParserInput *xmlParserInputPtr;
84typedef struct _xmlParserCtxt xmlParserCtxt;
85typedef xmlParserCtxt *xmlParserCtxtPtr;
86typedef struct _xmlError xmlError;
87typedef xmlError *xmlErrorPtr;
88
89namespace xml
90{
91
92// Little string class for XML only
93//////////////////////////////////////////////////////////////////////////////
94
95class ministring
96{
97public:
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
137private:
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 */
163class VBOXXML_CLASS Error : public std::exception
164{
165public:
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
201private:
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
222class VBOXXML_CLASS LogicError : public Error
223{
224public:
225
226 LogicError(const char *aMsg = NULL)
227 : xml::Error(aMsg)
228 {}
229
230 LogicError(RT_SRC_POS_DECL);
231};
232
233class VBOXXML_CLASS RuntimeError : public Error
234{
235public:
236
237 RuntimeError(const char *aMsg = NULL)
238 : xml::Error(aMsg)
239 {}
240};
241
242class VBOXXML_CLASS XmlError : public RuntimeError
243{
244public:
245 XmlError(xmlErrorPtr aErr);
246
247 static char *Format(xmlErrorPtr aErr);
248};
249
250// Logical errors
251//////////////////////////////////////////////////////////////////////////////
252
253class VBOXXML_CLASS ENotImplemented : public LogicError
254{
255public:
256 ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}
257 ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
258};
259
260class VBOXXML_CLASS EInvalidArg : public LogicError
261{
262public:
263 EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}
264 EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
265};
266
267class VBOXXML_CLASS EDocumentNotEmpty : public LogicError
268{
269public:
270 EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
271 EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
272};
273
274class VBOXXML_CLASS ENodeIsNotElement : public LogicError
275{
276public:
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
284class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
285{
286public:
287 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}
288 virtual ~ENoMemory() throw() {}
289};
290
291class VBOXXML_CLASS EIPRTFailure : public RuntimeError
292{
293public:
294
295 EIPRTFailure (int aRC);
296
297 int rc() const { return mRC; }
298
299private:
300 int mRC;
301};
302
303
304/**
305 * The Stream class is a base class for I/O streams.
306 */
307class VBOXXML_CLASS Stream
308{
309public:
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 */
342class VBOXXML_CLASS Input : virtual public Stream
343{
344public:
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 */
360class VBOXXML_CLASS Output : virtual public Stream
361{
362public:
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 */
397class VBOXXML_CLASS File : public Input, public Output
398{
399public:
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
466private:
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 */
480class VBOXXML_CLASS MemoryBuf : public Input
481{
482public:
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
494private:
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
510typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
511 const char *aID,
512 xmlParserCtxt *aCtxt);
513typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
514
515class VBOXXML_CLASS GlobalLock
516{
517public:
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
527private:
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
553class ElementNode;
554typedef std::list<const ElementNode*> ElementNodesList;
555
556class AttributeNode;
557
558class ContentNode;
559
560class VBOXXML_CLASS Node
561{
562public:
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
579protected:
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
594class VBOXXML_CLASS ElementNode : public Node
595{
596public:
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
612protected:
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
622class VBOXXML_CLASS ContentNode : public Node
623{
624public:
625
626protected:
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
635class VBOXXML_CLASS AttributeNode : public Node
636{
637public:
638
639protected:
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
653class VBOXXML_CLASS NodesLoop
654{
655public:
656 NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);
657 ~NodesLoop();
658 const ElementNode* forAllNodes() const;
659
660private:
661 /* Obscure class data */
662 struct Data;
663 Data *m;
664};
665
666/*
667 * Document
668 *
669 */
670
671class VBOXXML_CLASS Document
672{
673public:
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
684private:
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
700class VBOXXML_CLASS XmlParserBase
701{
702protected:
703 XmlParserBase();
704 ~XmlParserBase();
705
706 xmlParserCtxtPtr m_ctxt;
707};
708
709/*
710 * XmlFileParser
711 *
712 */
713
714class VBOXXML_CLASS XmlFileParser : public XmlParserBase
715{
716public:
717 XmlFileParser();
718 ~XmlFileParser();
719
720 void read(const char *pcszFilename, Document &doc);
721
722private:
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
736class VBOXXML_CLASS XmlFileWriter
737{
738public:
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
747private:
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 TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette