VirtualBox

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

Last change on this file since 18190 was 18052, checked in by vboxsync, 16 years ago

OVF: use AnnotationSection for VM description, don't fail on export if XML file exists

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