VirtualBox

source: vbox/trunk/include/iprt/xml_cpp.h@ 22650

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

Main: the big XML settings rework. Move XML reading/writing out of interface implementation code into separate layer so it can handle individual settings versions in the future.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.8 KB
Line 
1/** @file
2 * VirtualBox XML helper APIs.
3 */
4
5/*
6 * Copyright (C) 2007-2009 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#include <list>
38#include <memory>
39
40#include <iprt/ministring_cpp.h>
41
42/* Forwards */
43typedef struct _xmlParserInput xmlParserInput;
44typedef xmlParserInput *xmlParserInputPtr;
45typedef struct _xmlParserCtxt xmlParserCtxt;
46typedef xmlParserCtxt *xmlParserCtxtPtr;
47typedef struct _xmlError xmlError;
48typedef xmlError *xmlErrorPtr;
49
50namespace xml
51{
52
53// Exceptions
54//////////////////////////////////////////////////////////////////////////////
55
56/**
57 * Base exception class.
58 */
59class RT_DECL_CLASS Error : public std::exception
60{
61public:
62
63 Error(const char *pcszMessage)
64 : m_s(pcszMessage)
65 {
66 }
67
68 Error(const Error &s)
69 : std::exception(s),
70 m_s(s.what())
71 {
72 }
73
74 virtual ~Error() throw()
75 {
76 }
77
78 void operator=(const Error &s)
79 {
80 m_s = s.what();
81 }
82
83 void setWhat(const char *pcszMessage)
84 {
85 m_s = pcszMessage;
86 }
87
88 virtual const char* what() const throw()
89 {
90 return m_s.c_str();
91 }
92
93private:
94 // hide the default constructor to make sure the extended one above is always used
95 Error();
96
97 iprt::MiniString m_s;
98};
99
100class RT_DECL_CLASS LogicError : public Error
101{
102public:
103
104 LogicError(const char *aMsg = NULL)
105 : xml::Error(aMsg)
106 {}
107
108 LogicError(RT_SRC_POS_DECL);
109};
110
111class RT_DECL_CLASS RuntimeError : public Error
112{
113public:
114
115 RuntimeError(const char *aMsg = NULL)
116 : xml::Error(aMsg)
117 {}
118};
119
120class RT_DECL_CLASS XmlError : public RuntimeError
121{
122public:
123 XmlError(xmlErrorPtr aErr);
124
125 static char* Format(xmlErrorPtr aErr);
126};
127
128// Logical errors
129//////////////////////////////////////////////////////////////////////////////
130
131class RT_DECL_CLASS ENotImplemented : public LogicError
132{
133public:
134 ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}
135 ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
136};
137
138class RT_DECL_CLASS EInvalidArg : public LogicError
139{
140public:
141 EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}
142 EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
143};
144
145class RT_DECL_CLASS EDocumentNotEmpty : public LogicError
146{
147public:
148 EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
149 EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
150};
151
152class RT_DECL_CLASS ENodeIsNotElement : public LogicError
153{
154public:
155 ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {}
156 ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
157};
158
159// Runtime errors
160//////////////////////////////////////////////////////////////////////////////
161
162class RT_DECL_CLASS EIPRTFailure : public RuntimeError
163{
164public:
165
166 EIPRTFailure (int aRC);
167
168 int rc() const { return mRC; }
169
170private:
171 int mRC;
172};
173
174
175/**
176 * The Stream class is a base class for I/O streams.
177 */
178class RT_DECL_CLASS Stream
179{
180public:
181
182 virtual ~Stream() {}
183
184 virtual const char *uri() const = 0;
185
186 /**
187 * Returns the current read/write position in the stream. The returned
188 * position is a zero-based byte offset from the beginning of the file.
189 *
190 * Throws ENotImplemented if this operation is not implemented for the
191 * given stream.
192 */
193 virtual uint64_t pos() const = 0;
194
195 /**
196 * Sets the current read/write position in the stream.
197 *
198 * @param aPos Zero-based byte offset from the beginning of the stream.
199 *
200 * Throws ENotImplemented if this operation is not implemented for the
201 * given stream.
202 */
203 virtual void setPos (uint64_t aPos) = 0;
204};
205
206/**
207 * The Input class represents an input stream.
208 *
209 * This input stream is used to read the settings tree from.
210 * This is an abstract class that must be subclassed in order to fill it with
211 * useful functionality.
212 */
213class RT_DECL_CLASS Input : virtual public Stream
214{
215public:
216
217 /**
218 * Reads from the stream to the supplied buffer.
219 *
220 * @param aBuf Buffer to store read data to.
221 * @param aLen Buffer length.
222 *
223 * @return Number of bytes read.
224 */
225 virtual int read (char *aBuf, int aLen) = 0;
226};
227
228/**
229 *
230 */
231class RT_DECL_CLASS Output : virtual public Stream
232{
233public:
234
235 /**
236 * Writes to the stream from the supplied buffer.
237 *
238 * @param aBuf Buffer to write data from.
239 * @param aLen Buffer length.
240 *
241 * @return Number of bytes written.
242 */
243 virtual int write (const char *aBuf, int aLen) = 0;
244
245 /**
246 * Truncates the stream from the current position and upto the end.
247 * The new file size will become exactly #pos() bytes.
248 *
249 * Throws ENotImplemented if this operation is not implemented for the
250 * given stream.
251 */
252 virtual void truncate() = 0;
253};
254
255
256//////////////////////////////////////////////////////////////////////////////
257
258/**
259 * The File class is a stream implementation that reads from and writes to
260 * regular files.
261 *
262 * The File class uses IPRT File API for file operations. Note that IPRT File
263 * API is not thread-safe. This means that if you pass the same RTFILE handle to
264 * different File instances that may be simultaneously used on different
265 * threads, you should care about serialization; otherwise you will get garbage
266 * when reading from or writing to such File instances.
267 */
268class RT_DECL_CLASS File : public Input, public Output
269{
270public:
271
272 /**
273 * Possible file access modes.
274 */
275 enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite };
276
277 /**
278 * Opens a file with the given name in the given mode. If @a aMode is Read
279 * or ReadWrite, the file must exist. If @a aMode is Write, the file must
280 * not exist. Otherwise, an EIPRTFailure excetion will be thrown.
281 *
282 * @param aMode File mode.
283 * @param aFileName File name.
284 */
285 File(Mode aMode, const char *aFileName);
286
287 /**
288 * Uses the given file handle to perform file operations. This file
289 * handle must be already open in necessary mode (read, or write, or mixed).
290 *
291 * The read/write position of the given handle will be reset to the
292 * beginning of the file on success.
293 *
294 * Note that the given file handle will not be automatically closed upon
295 * this object destruction.
296 *
297 * @note It you pass the same RTFILE handle to more than one File instance,
298 * please make sure you have provided serialization in case if these
299 * instasnces are to be simultaneously used by different threads.
300 * Otherwise you may get garbage when reading or writing.
301 *
302 * @param aHandle Open file handle.
303 * @param aFileName File name (for reference).
304 */
305 File(RTFILE aHandle, const char *aFileName = NULL);
306
307 /**
308 * Destroys the File object. If the object was created from a file name
309 * the corresponding file will be automatically closed. If the object was
310 * created from a file handle, it will remain open.
311 */
312 virtual ~File();
313
314 const char *uri() const;
315
316 uint64_t pos() const;
317 void setPos(uint64_t aPos);
318
319 /**
320 * See Input::read(). If this method is called in wrong file mode,
321 * LogicError will be thrown.
322 */
323 int read(char *aBuf, int aLen);
324
325 /**
326 * See Output::write(). If this method is called in wrong file mode,
327 * LogicError will be thrown.
328 */
329 int write(const char *aBuf, int aLen);
330
331 /**
332 * See Output::truncate(). If this method is called in wrong file mode,
333 * LogicError will be thrown.
334 */
335 void truncate();
336
337private:
338
339 /* Obscure class data */
340 struct Data;
341 Data *m;
342
343 /* auto_ptr data doesn't have proper copy semantics */
344 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)
345};
346
347/**
348 * The MemoryBuf class represents a stream implementation that reads from the
349 * memory buffer.
350 */
351class RT_DECL_CLASS MemoryBuf : public Input
352{
353public:
354
355 MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
356
357 virtual ~MemoryBuf();
358
359 const char *uri() const;
360
361 int read(char *aBuf, int aLen);
362 uint64_t pos() const;
363 void setPos(uint64_t aPos);
364
365private:
366 /* Obscure class data */
367 struct Data;
368 Data *m;
369
370 /* auto_ptr data doesn't have proper copy semantics */
371 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(MemoryBuf)
372};
373
374
375/*
376 * GlobalLock
377 *
378 *
379 */
380
381typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
382 const char *aID,
383 xmlParserCtxt *aCtxt);
384typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
385
386class RT_DECL_CLASS GlobalLock
387{
388public:
389 GlobalLock();
390 ~GlobalLock();
391
392 void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);
393
394 static xmlParserInput* callDefaultLoader(const char *aURI,
395 const char *aID,
396 xmlParserCtxt *aCtxt);
397
398private:
399 /* Obscure class data. */
400 struct Data;
401 struct Data *m;
402};
403
404/**
405 * Node:
406 * an XML node, which represents either an element or text content
407 * or an attribute.
408 *
409 * For elements, getName() returns the element name, and getValue()
410 * returns the text contents, if any.
411 *
412 * For attributes, getName() returns the attribute name, and getValue()
413 * returns the attribute value, if any.
414 *
415 * Since the default constructor is private, one can create new nodes
416 * only through factory methods provided by the XML classes. These are:
417 *
418 * -- xml::Document::createRootElement()
419 * -- xml::Node::createChild()
420 * -- xml::Node::addContent()
421 * -- xml::Node::setAttribute()
422 */
423
424class ElementNode;
425typedef std::list<const ElementNode*> ElementNodesList;
426
427class AttributeNode;
428
429class ContentNode;
430
431class RT_DECL_CLASS Node
432{
433public:
434 ~Node();
435
436 const char* getName() const;
437 bool nameEquals(const char *pcsz) const;
438
439 const char* getValue() const;
440 bool copyValue(int32_t &i) const;
441 bool copyValue(uint32_t &i) const;
442 bool copyValue(int64_t &i) const;
443 bool copyValue(uint64_t &i) const;
444
445 int getLineNumber() const;
446
447 int isElement()
448 {
449 return mType == IsElement;
450 }
451
452protected:
453 typedef enum {IsElement, IsAttribute, IsContent} EnumType;
454 EnumType mType;
455
456 // hide the default constructor so people use only our factory methods
457 Node(EnumType type);
458 Node(const Node &x); // no copying
459
460 void buildChildren();
461
462 /* Obscure class data */
463 struct Data;
464 Data *m;
465};
466
467class RT_DECL_CLASS ElementNode : public Node
468{
469public:
470 int getChildElements(ElementNodesList &children,
471 const char *pcszMatch = NULL) const;
472
473 const ElementNode* findChildElement(const char *pcszMatch) const;
474 const ElementNode* findChildElementFromId(const char *pcszId) const;
475
476 const AttributeNode* findAttribute(const char *pcszMatch) const;
477 bool getAttributeValue(const char *pcszMatch, const char *&ppcsz) const;
478 bool getAttributeValue(const char *pcszMatch, iprt::MiniString &str) const;
479 bool getAttributeValue(const char *pcszMatch, int32_t &i) const;
480 bool getAttributeValue(const char *pcszMatch, uint32_t &i) const;
481 bool getAttributeValue(const char *pcszMatch, int64_t &i) const;
482 bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;
483 bool getAttributeValue(const char *pcszMatch, bool &f) const;
484
485 ElementNode* createChild(const char *pcszElementName);
486
487 ContentNode* addContent(const char *pcszContent);
488 ContentNode* addContent(const iprt::MiniString &strContent)
489 {
490 return addContent(strContent.c_str());
491 }
492
493 AttributeNode* setAttribute(const char *pcszName, const char *pcszValue);
494 AttributeNode* setAttribute(const char *pcszName, const iprt::MiniString &strValue)
495 {
496 return setAttribute(pcszName, strValue.c_str());
497 }
498 AttributeNode* setAttribute(const char *pcszName, int32_t i);
499 AttributeNode* setAttribute(const char *pcszName, uint32_t i);
500 AttributeNode* setAttribute(const char *pcszName, int64_t i);
501 AttributeNode* setAttribute(const char *pcszName, uint64_t i);
502 AttributeNode* setAttributeHex(const char *pcszName, uint32_t i);
503 AttributeNode* setAttribute(const char *pcszName, bool f);
504
505protected:
506 // hide the default constructor so people use only our factory methods
507 ElementNode();
508 ElementNode(const ElementNode &x); // no copying
509
510 friend class Node;
511 friend class Document;
512 friend class XmlFileParser;
513};
514
515class RT_DECL_CLASS ContentNode : public Node
516{
517public:
518
519protected:
520 // hide the default constructor so people use only our factory methods
521 ContentNode();
522 ContentNode(const ContentNode &x); // no copying
523
524 friend class Node;
525 friend class ElementNode;
526};
527
528class RT_DECL_CLASS AttributeNode : public Node
529{
530public:
531
532protected:
533 // hide the default constructor so people use only our factory methods
534 AttributeNode();
535 AttributeNode(const AttributeNode &x); // no copying
536
537 friend class Node;
538 friend class ElementNode;
539};
540
541/*
542 * NodesLoop
543 *
544 */
545
546class RT_DECL_CLASS NodesLoop
547{
548public:
549 NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);
550 ~NodesLoop();
551 const ElementNode* forAllNodes() const;
552
553private:
554 /* Obscure class data */
555 struct Data;
556 Data *m;
557};
558
559/*
560 * Document
561 *
562 */
563
564class RT_DECL_CLASS Document
565{
566public:
567 Document();
568 ~Document();
569
570 Document(const Document &x);
571 Document& operator=(const Document &x);
572
573 const ElementNode* getRootElement() const;
574 ElementNode* getRootElement();
575
576 ElementNode* createRootElement(const char *pcszRootElementName);
577
578private:
579 friend class XmlFileParser;
580 friend class XmlFileWriter;
581
582 void refreshInternals();
583
584 /* Obscure class data */
585 struct Data;
586 Data *m;
587};
588
589/*
590 * XmlParserBase
591 *
592 */
593
594class RT_DECL_CLASS XmlParserBase
595{
596protected:
597 XmlParserBase();
598 ~XmlParserBase();
599
600 xmlParserCtxtPtr m_ctxt;
601};
602
603/*
604 * XmlFileParser
605 *
606 */
607
608class RT_DECL_CLASS XmlFileParser : public XmlParserBase
609{
610public:
611 XmlFileParser();
612 ~XmlFileParser();
613
614 void read(const iprt::MiniString &strFilename, Document &doc);
615
616private:
617 /* Obscure class data */
618 struct Data;
619 struct Data *m;
620
621 static int ReadCallback(void *aCtxt, char *aBuf, int aLen);
622 static int CloseCallback (void *aCtxt);
623};
624
625/*
626 * XmlFileWriter
627 *
628 */
629
630class RT_DECL_CLASS XmlFileWriter
631{
632public:
633 XmlFileWriter(Document &doc);
634 ~XmlFileWriter();
635
636 void write(const char *pcszFilename);
637
638 static int WriteCallback(void *aCtxt, const char *aBuf, int aLen);
639 static int CloseCallback (void *aCtxt);
640
641private:
642 /* Obscure class data */
643 struct Data;
644 Data *m;
645};
646
647#if defined(_MSC_VER)
648#pragma warning (default:4251)
649#endif
650
651#endif /* IN_RING3 */
652
653/** @} */
654
655} // end namespace xml
656
657#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