VirtualBox

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

Last change on this file since 17375 was 17362, checked in by vboxsync, 16 years ago

OVF: partial implementation of write support in XML classes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 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
170// Runtime errors
171//////////////////////////////////////////////////////////////////////////////
172
173class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
174{
175public:
176 ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}
177 virtual ~ENoMemory() throw() {}
178};
179
180class VBOXXML_CLASS EIPRTFailure : public RuntimeError
181{
182public:
183
184 EIPRTFailure (int aRC);
185
186 int rc() const { return mRC; }
187
188private:
189 int mRC;
190};
191
192
193/**
194 * The Stream class is a base class for I/O streams.
195 */
196class VBOXXML_CLASS Stream
197{
198public:
199
200 virtual ~Stream() {}
201
202 virtual const char *uri() const = 0;
203
204 /**
205 * Returns the current read/write position in the stream. The returned
206 * position is a zero-based byte offset from the beginning of the file.
207 *
208 * Throws ENotImplemented if this operation is not implemented for the
209 * given stream.
210 */
211 virtual uint64_t pos() const = 0;
212
213 /**
214 * Sets the current read/write position in the stream.
215 *
216 * @param aPos Zero-based byte offset from the beginning of the stream.
217 *
218 * Throws ENotImplemented if this operation is not implemented for the
219 * given stream.
220 */
221 virtual void setPos (uint64_t aPos) = 0;
222};
223
224/**
225 * The Input class represents an input stream.
226 *
227 * This input stream is used to read the settings tree from.
228 * This is an abstract class that must be subclassed in order to fill it with
229 * useful functionality.
230 */
231class VBOXXML_CLASS Input : virtual public Stream
232{
233public:
234
235 /**
236 * Reads from the stream to the supplied buffer.
237 *
238 * @param aBuf Buffer to store read data to.
239 * @param aLen Buffer length.
240 *
241 * @return Number of bytes read.
242 */
243 virtual int read (char *aBuf, int aLen) = 0;
244};
245
246/**
247 *
248 */
249class VBOXXML_CLASS Output : virtual public Stream
250{
251public:
252
253 /**
254 * Writes to the stream from the supplied buffer.
255 *
256 * @param aBuf Buffer to write data from.
257 * @param aLen Buffer length.
258 *
259 * @return Number of bytes written.
260 */
261 virtual int write (const char *aBuf, int aLen) = 0;
262
263 /**
264 * Truncates the stream from the current position and upto the end.
265 * The new file size will become exactly #pos() bytes.
266 *
267 * Throws ENotImplemented if this operation is not implemented for the
268 * given stream.
269 */
270 virtual void truncate() = 0;
271};
272
273
274//////////////////////////////////////////////////////////////////////////////
275
276/**
277 * The File class is a stream implementation that reads from and writes to
278 * regular files.
279 *
280 * The File class uses IPRT File API for file operations. Note that IPRT File
281 * API is not thread-safe. This means that if you pass the same RTFILE handle to
282 * different File instances that may be simultaneously used on different
283 * threads, you should care about serialization; otherwise you will get garbage
284 * when reading from or writing to such File instances.
285 */
286class VBOXXML_CLASS File : public Input, public Output
287{
288public:
289
290 /**
291 * Possible file access modes.
292 */
293 enum Mode { Mode_Read, Mode_Write, Mode_ReadWrite };
294
295 /**
296 * Opens a file with the given name in the given mode. If @a aMode is Read
297 * or ReadWrite, the file must exist. If @a aMode is Write, the file must
298 * not exist. Otherwise, an EIPRTFailure excetion will be thrown.
299 *
300 * @param aMode File mode.
301 * @param aFileName File name.
302 */
303 File (Mode aMode, const char *aFileName);
304
305 /**
306 * Uses the given file handle to perform file operations. This file
307 * handle must be already open in necessary mode (read, or write, or mixed).
308 *
309 * The read/write position of the given handle will be reset to the
310 * beginning of the file on success.
311 *
312 * Note that the given file handle will not be automatically closed upon
313 * this object destruction.
314 *
315 * @note It you pass the same RTFILE handle to more than one File instance,
316 * please make sure you have provided serialization in case if these
317 * instasnces are to be simultaneously used by different threads.
318 * Otherwise you may get garbage when reading or writing.
319 *
320 * @param aHandle Open file handle.
321 * @param aFileName File name (for reference).
322 */
323 File (RTFILE aHandle, const char *aFileName = NULL);
324
325 /**
326 * Destroys the File object. If the object was created from a file name
327 * the corresponding file will be automatically closed. If the object was
328 * created from a file handle, it will remain open.
329 */
330 virtual ~File();
331
332 const char *uri() const;
333
334 uint64_t pos() const;
335 void setPos (uint64_t aPos);
336
337 /**
338 * See Input::read(). If this method is called in wrong file mode,
339 * LogicError will be thrown.
340 */
341 int read (char *aBuf, int aLen);
342
343 /**
344 * See Output::write(). If this method is called in wrong file mode,
345 * LogicError will be thrown.
346 */
347 int write (const char *aBuf, int aLen);
348
349 /**
350 * See Output::truncate(). If this method is called in wrong file mode,
351 * LogicError will be thrown.
352 */
353 void truncate();
354
355private:
356
357 /* Obscure class data */
358 struct Data;
359 std::auto_ptr <Data> m;
360
361 /* auto_ptr data doesn't have proper copy semantics */
362 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)
363};
364
365/**
366 * The MemoryBuf class represents a stream implementation that reads from the
367 * memory buffer.
368 */
369class VBOXXML_CLASS MemoryBuf : public Input
370{
371public:
372
373 MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
374
375 virtual ~MemoryBuf();
376
377 const char *uri() const;
378
379 int read (char *aBuf, int aLen);
380 uint64_t pos() const;
381 void setPos (uint64_t aPos);
382
383private:
384 /* Obscure class data */
385 struct Data;
386 std::auto_ptr <Data> m;
387
388 /* auto_ptr data doesn't have proper copy semantics */
389 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf)
390};
391
392
393/*
394 * GlobalLock
395 *
396 *
397 */
398
399typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
400 const char *aID,
401 xmlParserCtxt *aCtxt);
402typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
403
404class VBOXXML_CLASS GlobalLock
405{
406public:
407 GlobalLock();
408 ~GlobalLock();
409
410 void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);
411
412 static xmlParserInput* callDefaultLoader(const char *aURI,
413 const char *aID,
414 xmlParserCtxt *aCtxt);
415
416private:
417 /* Obscure class data */
418 struct Data;
419 std::auto_ptr<Data> m;
420};
421
422/*
423 * Node:
424 * an XML node, which represents either an element or an attribute.
425 *
426 * For elements, getName() returns the element name, and getValue()
427 * returns the text contents, if any.
428 *
429 * For attributes, getName() returns the attribute name, and getValue()
430 * returns the attribute value, if any.
431 *
432 * Since the default constructor is private, one can create new nodes
433 * only through factory methods provided by the XML classes. These are:
434 *
435 * -- xml::Document::createRootElement()
436 * -- xml::Node::createChild()
437 * -- xml::Node::setAttribute()
438 */
439
440class Node;
441typedef std::list<const Node*> NodesList;
442
443class VBOXXML_CLASS Node
444{
445public:
446 ~Node();
447
448 const char* getName() const;
449 const char* getValue() const;
450 bool copyValue(int32_t &i) const;
451 bool copyValue(uint32_t &i) const;
452 bool copyValue(int64_t &i) const;
453 bool copyValue(uint64_t &i) const;
454
455 int getLineNumber() const;
456
457 int getChildElements(NodesList &children,
458 const char *pcszMatch = NULL) const;
459
460 const Node* findChildElement(const char *pcszMatch) const;
461 const Node* findChildElementFromId(const char *pcszId) const;
462
463 const Node* findAttribute(const char *pcszMatch) const;
464 bool getAttributeValue(const char *pcszMatch, com::Utf8Str &str) const;
465 bool getAttributeValue(const char *pcszMatch, int64_t &i) const;
466 bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;
467
468 Node* createChild(const char *pcszElementName);
469 Node* setAttribute(const char *pcszName, const char *pcszValue);
470
471private:
472 // hide the default constructor so people use only our factory methods
473 Node();
474
475 friend class Document;
476 friend class XmlFileParser;
477
478 Node(const Node &x); // no copying
479
480 void buildChildren();
481
482 /* Obscure class data */
483 struct Data;
484 Data *m;
485};
486
487/*
488 * NodesLoop
489 *
490 */
491
492class VBOXXML_CLASS NodesLoop
493{
494public:
495 NodesLoop(const Node &node, const char *pcszMatch = NULL);
496 ~NodesLoop();
497 const Node* forAllNodes() const;
498
499private:
500 /* Obscure class data */
501 struct Data;
502 Data *m;
503};
504
505/*
506 * Document
507 *
508 */
509
510class VBOXXML_CLASS Document
511{
512public:
513 Document();
514 ~Document();
515
516 Document(const Document &x);
517 Document& operator=(const Document &x);
518
519 const Node* getRootElement() const;
520
521 Node* createRootElement(const char *pcszRootElementName);
522
523private:
524 friend class XmlFileParser;
525 friend class XmlFileWriter;
526
527 void refreshInternals();
528
529 /* Obscure class data */
530 struct Data;
531 Data *m;
532};
533
534/*
535 * XmlParserBase
536 *
537 */
538
539class VBOXXML_CLASS XmlParserBase
540{
541protected:
542 XmlParserBase();
543 ~XmlParserBase();
544
545 xmlParserCtxtPtr m_ctxt;
546};
547
548/*
549 * XmlFileParser
550 *
551 */
552
553class VBOXXML_CLASS XmlFileParser : public XmlParserBase
554{
555public:
556 XmlFileParser();
557 ~XmlFileParser();
558
559 void read(const char *pcszFilename, Document &doc);
560
561private:
562 /* Obscure class data */
563 struct Data;
564 std::auto_ptr<Data> m;
565
566 static int ReadCallback(void *aCtxt, char *aBuf, int aLen);
567 static int CloseCallback (void *aCtxt);
568};
569
570/*
571 * XmlFileWriter
572 *
573 */
574
575class VBOXXML_CLASS XmlFileWriter
576{
577public:
578 XmlFileWriter(Document &doc);
579 ~XmlFileWriter();
580
581 void write(const char *pcszFilename);
582
583 static int WriteCallback(void *aCtxt, const char *aBuf, int aLen);
584 static int CloseCallback (void *aCtxt);
585
586private:
587 /* Obscure class data */
588 struct Data;
589 Data *m;
590};
591
592#if defined(_MSC_VER)
593#pragma warning (default:4251)
594#endif
595
596#endif /* IN_RING3 */
597
598/** @} */
599
600} // end namespace xml
601
602#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