VirtualBox

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

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

Main: replace redundant xml::FmtStr with com::Utf8StrFmt

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