VirtualBox

source: vbox/trunk/include/VBox/settings.h@ 14711

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

fix typos

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 49.8 KB
Line 
1/** @file
2 * Settings File Manipulation API.
3 */
4
5/*
6 * Copyright (C) 2007 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_settings_h
31#define ___VBox_settings_h
32
33#include <iprt/cdefs.h>
34#include <iprt/cpputils.h>
35#include <iprt/string.h>
36
37#include <list>
38#include <memory>
39#include <limits>
40
41/* these conflict with numeric_digits<>::min and max */
42#undef min
43#undef max
44
45#include <iprt/assert.h>
46#include <iprt/string.h>
47#include <iprt/mem.h>
48#include <iprt/time.h>
49
50#include <stdarg.h>
51
52
53/** @defgroup grp_settings Settings File Manipulation API
54 * @{
55 *
56 * The Settings File Manipulation API allows to maintain a configuration file
57 * that contains "name-value" pairs grouped under named keys which are in turn
58 * organized in a hierarchical tree-like structure:
59 *
60 * @code
61 * <RootKey>
62 * <Key1 attr1="value" attr2=""/>
63 * <Key2 attr1="value">
64 * <SubKey1>SubKey1_Value</SubKey1>
65 * <SubKey2 attr1="value">SubKey2_Value</SubKey2>
66 * Key2_Value
67 * </Key2>
68 * </RootKey>
69 * @endcode
70 *
71 * All strings this API manipulates with are zero-terminated arrays of @c char
72 * in UTF-8 encoding. Strings returned by the API are owned by the API unless
73 * explicitly stated otherwise. Strings passed to the API are accessed by the
74 * API only during the given API call unless explicitly stated otherwise. If
75 * necessary, the API will make a copy of the supplied string.
76 *
77 * Error reporting is perfomed using C++ exceptions. All exceptions thrown by
78 * this API are derived from settings::Error. This doesn't cover exceptions
79 * that may be thrown by third-party library calls made by this API.
80 *
81 * All public classes represented by this API that support copy operations
82 * (i.e. may be created or assigned from other instsances of the same class),
83 * such as Key and Value classes, implement shallow copies and use this mode by
84 * default. It means two things:
85 *
86 * 1. Instances of these classes can be freely copied around and used as return
87 * values. All copies will share the same internal data block (using the
88 * reference counting technique) so that the copy operation is cheap, both
89 * in terms of memory and speed.
90 *
91 * 2. Since copied instances share the same data, an attempt to change data in
92 * the original will be reflected in all existing copies.
93 *
94 * Making deep copies or detaching the existing shallow copy from its original
95 * is not yet supported.
96 *
97 * Note that the Settings File API is not thread-safe. It means that if you
98 * want to use the same instance of a class from the settings namespace on more
99 * than one thread at a time, you will have to provide necessary access
100 * serialization yourself.
101 *
102 * Due to some (not propely studied) libxml2 limitations, the Settings File
103 * API is not thread-safe. Therefore, the API caller must provide
104 * serialization for threads using this API simultaneously. Note though that
105 * if the libxml2 library is (even imlicitly) used on some other thread which
106 * doesn't use this API (e.g. third-party code), it may lead to resource
107 * conflicts (followed by crashes, memory corruption etc.). A proper solution
108 * for these conflicts is to be found.
109 *
110 * In order to load a settings file the program creates a TreeBackend instance
111 * using one of the specific backends (e.g. XmlTreeBackend) and then passes an
112 * Input stream object (e.g. File or MemoryBuf) to the TreeBackend::read()
113 * method to parse the stream and build the settings tree. On success, the
114 * program uses the TreeBackend::rootKey() method to access the root key of
115 * the settings tree. The root key provides access to the whole tree of
116 * settings through the methods of the Key class which allow to read, change
117 * and create new key values. Below is an example that uses the XML backend to
118 * load the settings tree, then modifies it and then saves the modifications.
119 *
120 * @code
121 using namespace settings;
122
123 try
124 {
125 File file (File::ReadWrite, "myfile.xml");
126 XmlTreeBackend tree;
127
128 // load the tree, parse it and validate using the XML schema
129 tree.read (aFile, "myfile.xsd", XmlTreeBackend::Read_AddDefaults);
130
131 // get the root key
132 Key root = tree.key();
133 printf ("root=%s\n", root.name());
134
135 // enumerate all child keys of the root key named Foo
136 Key::list children = root.keys ("Foo");
137 for (Key::list::const_iterator it = children.begin();
138 it != children.end();
139 ++ it)
140 {
141 // get the "level" attribute
142 int level = (*it).value <int> ("level");
143 if (level > 5)
144 {
145 // if so, create a "Bar" key if it doesn't exist yet
146 Key bar = (*it).createKey ("Bar");
147 // set the "date" attribute
148 RTTIMESPEC now;
149 RTTimeNow (&now);
150 bar.setValue <RTTIMESPEC> ("date", now);
151 }
152 else if (level < 2)
153 {
154 // if its below 2, delete the whole "Foo" key
155 (*it).zap();
156 }
157 }
158
159 // save the tree on success (the second try is to distinguish between
160 // stream load and save errors)
161 try
162 {
163 aTree.write (aFile);
164 }
165 catch (const EIPRTFailure &err)
166 {
167 // this is an expected exception that may happen in case of stream
168 // read or write errors
169 printf ("Could not save the settings file '%s' (%Rrc)");
170 file.uri(), err.rc());
171
172 return FAILURE;
173 }
174
175 return SUCCESS;
176 }
177 catch (const EIPRTFailure &err)
178 {
179 // this is an expected exception that may happen in case of stream
180 // read or write errors
181 printf ("Could not load the settings file '%s' (%Rrc)");
182 file.uri(), err.rc());
183 }
184 catch (const XmlTreeBackend::Error &err)
185 {
186 // this is an XmlTreeBackend specific exception that may
187 // happen in case of XML parse or validation errors
188 printf ("Could not load the settings file '%s'.\n%s"),
189 file.uri(), err.what() ? err.what() : "Unknown error");
190 }
191 catch (const std::exception &err)
192 {
193 // the rest is unexpected (e.g. should not happen unless you
194 // specifically wish so for some reason and therefore allow for a
195 // situation that may throw one of these from within the try block
196 // above)
197 AssertMsgFailed ("Unexpected exception '%s' (%s)\n",
198 typeid (err).name(), err.what());
199 }
200 catch (...)
201 {
202 // this is even more unexpected, and no any useful info here
203 AssertMsgFailed ("Unexpected exception\n");
204 }
205
206 return FAILURE;
207 * @endcode
208 *
209 * Note that you can get a raw (string) value of the attribute using the
210 * Key::stringValue() method but often it's simpler and better to use the
211 * templated Key::value<>() method that can convert the string to a value of
212 * the given type for you (and throw exceptions when the converison is not
213 * possible). Similarly, the Key::setStringValue() method is used to set a raw
214 * string value and there is a templated Key::setValue<>() method to set a
215 * typed value which will implicitly convert it to a string.
216 *
217 * Currently, types supported by Key::value<>() and Key::setValue<>() include
218 * all C and IPRT integer types, bool and RTTIMESPEC (represented as isoDate
219 * in XML). You can always add support for your own types by creating
220 * additional specializations of the FromString<>() and ToString<>() templates
221 * in the settings namespace (see the real examples in this header).
222 *
223 * See individual funciton, class and method descriptions to get more details
224 * on the Settings File Manipulation API.
225 */
226
227#ifndef IN_RING3
228# error "There are no settings APIs available in Ring-0 Context!"
229#else /* IN_RING3 */
230
231/** @def IN_VBOXSETTINGS_R3
232 * Used to indicate whether we're inside the same link module as the
233 * XML Settings File Manipulation API.
234 *
235 * @todo should go to a separate common include together with VBOXXML2_CLASS
236 * once there becomes more than one header in the VBoxXML2 library.
237 */
238#ifdef DOXYGEN_RUNNING
239# define IN_VBOXSETTINGS_R3
240#endif
241
242/** @def VBOXSETTINGS_CLASS
243 * Class export/import wrapper. */
244#ifdef IN_VBOXSETTINGS_R3
245# define VBOXSETTINGS_CLASS DECLEXPORT_CLASS
246#else
247# define VBOXSETTINGS_CLASS DECLIMPORT_CLASS
248#endif
249
250/*
251 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
252 * result of private data member declarations of some classes below) need to
253 * be exported too to in order to be accessible by clients.
254 *
255 * The alternative is to instantiate a template before the data member
256 * declaration with the VBOXSETTINGS_CLASS prefix, but the standard disables
257 * explicit instantiations in a foreign namespace. In other words, a declaration
258 * like:
259 *
260 * template class VBOXSETTINGS_CLASS std::auto_ptr <Data>;
261 *
262 * right before the member declaration makes MSVC happy too, but this is not a
263 * valid C++ construct (and G++ spits it out). So, for now we just disable the
264 * warning and will come back to this problem one day later.
265 *
266 * We also disable another warning (4275) saying that a DLL-exported class
267 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
268 * std::bad_alloc). I can't get how it can harm yet.
269 */
270#if defined(_MSC_VER)
271#pragma warning (disable:4251)
272#pragma warning (disable:4275)
273#endif
274
275/* Forwards */
276typedef struct _xmlParserInput xmlParserInput;
277typedef xmlParserInput *xmlParserInputPtr;
278typedef struct _xmlParserCtxt xmlParserCtxt;
279typedef xmlParserCtxt *xmlParserCtxtPtr;
280typedef struct _xmlError xmlError;
281typedef xmlError *xmlErrorPtr;
282
283/**
284 * Settings File Manipulation API namespace.
285 */
286namespace settings
287{
288
289// Helpers
290//////////////////////////////////////////////////////////////////////////////
291
292/**
293 * Temporary holder for the formatted string.
294 *
295 * Instances of this class are used for passing the formatted string as an
296 * argument to an Error constructor or to another function that takes
297 * <tr>const char *</tr> and makes a copy of the string it points to.
298 */
299class VBOXSETTINGS_CLASS FmtStr
300{
301public:
302
303 /**
304 * Creates a formatted string using the format string and a set of
305 * printf-like arguments.
306 */
307 FmtStr (const char *aFmt, ...)
308 {
309 va_list args;
310 va_start (args, aFmt);
311 RTStrAPrintfV (&mStr, aFmt, args);
312 va_end (args);
313 }
314
315 ~FmtStr() { RTStrFree (mStr); }
316
317 operator const char *() { return mStr; }
318
319private:
320
321 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (FmtStr)
322
323 char *mStr;
324};
325
326// Exceptions
327//////////////////////////////////////////////////////////////////////////////
328
329/**
330 * Base exception class.
331 */
332class VBOXSETTINGS_CLASS Error : public std::exception
333{
334public:
335
336 Error (const char *aMsg = NULL)
337 : m (aMsg ? Str::New (aMsg) : NULL) {}
338
339 virtual ~Error() throw() {}
340
341 void setWhat (const char *aMsg) { m = aMsg ? Str::New (aMsg) : NULL; }
342
343 const char *what() const throw() { return m.is_null() ? NULL : m->str; }
344
345private:
346
347 /** smart string with support for reference counting */
348 struct Str
349 {
350 size_t ref() { return ++ refs; }
351 size_t unref() { return -- refs; }
352
353 size_t refs;
354 char str [1];
355
356 static Str *New (const char *aStr)
357 {
358 Str *that = (Str *) RTMemAllocZ (sizeof (Str) + strlen (aStr));
359 AssertReturn (that, NULL);
360 strcpy (that->str, aStr);
361 return that;
362 }
363
364 void operator delete (void *that, size_t) { RTMemFree (that); }
365 };
366
367 stdx::auto_ref_ptr <Str> m;
368};
369
370class VBOXSETTINGS_CLASS LogicError : public Error
371{
372public:
373
374 LogicError (const char *aMsg = NULL) : Error (aMsg) {}
375
376 LogicError (RT_SRC_POS_DECL)
377 {
378 char *msg = NULL;
379 RTStrAPrintf (&msg, "In '%s', '%s' at #%d",
380 pszFunction, pszFile, iLine);
381 setWhat (msg);
382 RTStrFree (msg);
383 }
384};
385
386class VBOXSETTINGS_CLASS RuntimeError : public Error
387{
388public:
389
390 RuntimeError (const char *aMsg = NULL) : Error (aMsg) {}
391};
392
393// Logical errors
394//////////////////////////////////////////////////////////////////////////////
395
396class VBOXSETTINGS_CLASS ENotImplemented : public LogicError
397{
398public:
399
400 ENotImplemented (const char *aMsg = NULL) : LogicError (aMsg) {}
401 ENotImplemented (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {}
402};
403
404class VBOXSETTINGS_CLASS EInvalidArg : public LogicError
405{
406public:
407
408 EInvalidArg (const char *aMsg = NULL) : LogicError (aMsg) {}
409 EInvalidArg (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {}
410};
411
412class VBOXSETTINGS_CLASS ENoKey : public LogicError
413{
414public:
415
416 ENoKey (const char *aMsg = NULL) : LogicError (aMsg) {}
417};
418
419class VBOXSETTINGS_CLASS ENoValue : public LogicError
420{
421public:
422
423 ENoValue (const char *aMsg = NULL) : LogicError (aMsg) {}
424};
425
426// Runtime errors
427//////////////////////////////////////////////////////////////////////////////
428
429class VBOXSETTINGS_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
430{
431public:
432
433 ENoMemory (const char *aMsg = NULL) : RuntimeError (aMsg) {}
434 virtual ~ENoMemory() throw() {}
435};
436
437class VBOXSETTINGS_CLASS EIPRTFailure : public RuntimeError
438{
439public:
440
441 EIPRTFailure (const char *aMsg = NULL) : RuntimeError (aMsg) {}
442
443 EIPRTFailure (int aRC) : mRC (aRC) {}
444 int rc() const { return mRC; }
445
446private:
447
448 int mRC;
449};
450
451class VBOXSETTINGS_CLASS ENoConversion : public RuntimeError
452{
453public:
454
455 ENoConversion (const char *aMsg = NULL) : RuntimeError (aMsg) {}
456};
457
458// string -> type conversions
459//////////////////////////////////////////////////////////////////////////////
460
461/** @internal
462 * Helper for the FromString() template, doesn't need to be called directly.
463 */
464DECLEXPORT (uint64_t) FromStringInteger (const char *aValue, bool aSigned,
465 int aBits, uint64_t aMin, uint64_t aMax);
466
467/**
468 * Generic template function to perform a conversion of an UTF-8 string to an
469 * arbitrary value of type @a T.
470 *
471 * This generic template is implenented only for 8-, 16-, 32- and 64- bit
472 * signed and unsigned integers where it uses RTStrTo[U]Int64() to perform the
473 * conversion. For all other types it throws an ENotImplemented
474 * exception. Individual template specializations for known types should do
475 * the conversion job.
476 *
477 * If the conversion is not possible (for example the string format is wrong
478 * or meaningless for the given type), this template will throw an
479 * ENoConversion exception. All specializations must do the same.
480 *
481 * If the @a aValue argument is NULL, this method will throw an ENoValue
482 * exception. All specializations must do the same.
483 *
484 * @param aValue Value to convert.
485 *
486 * @return Result of conversion.
487 */
488template <typename T>
489T FromString (const char *aValue)
490{
491 if (std::numeric_limits <T>::is_integer)
492 {
493 bool sign = std::numeric_limits <T>::is_signed;
494 int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
495
496 return (T) FromStringInteger (aValue, sign, bits,
497 (uint64_t) std::numeric_limits <T>::min(),
498 (uint64_t) std::numeric_limits <T>::max());
499 }
500
501 throw ENotImplemented (RT_SRC_POS);
502}
503
504/**
505 * Specialization of FromString for bool.
506 *
507 * Converts "true", "yes", "on" to true and "false", "no", "off" to false.
508 */
509template<> DECLEXPORT (bool) FromString <bool> (const char *aValue);
510
511/**
512 * Specialization of FromString for RTTIMESPEC.
513 *
514 * Converts the date in ISO format (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone])
515 * to a RTTIMESPEC value. Currently, the timezone must always be Z (UTC).
516 */
517template<> DECLEXPORT (RTTIMESPEC) FromString <RTTIMESPEC> (const char *aValue);
518
519/**
520 * Converts a string of hex digits to memory bytes.
521 *
522 * @param aValue String to convert.
523 * @param aLen Where to store the length of the returned memory
524 * block (may be NULL).
525 *
526 * @return Result of conversion (a block of @a aLen bytes).
527 */
528DECLEXPORT (stdx::char_auto_ptr) FromString (const char *aValue, size_t *aLen);
529
530// type -> string conversions
531//////////////////////////////////////////////////////////////////////////////
532
533/** @internal
534 * Helper for the ToString() template, doesn't need to be called directly.
535 */
536DECLEXPORT (stdx::char_auto_ptr)
537ToStringInteger (uint64_t aValue, unsigned int aBase,
538 bool aSigned, int aBits);
539
540/**
541 * Generic template function to perform a conversion of an arbitrary value to
542 * an UTF-8 string.
543 *
544 * This generic template is implemented only for 8-, 16-, 32- and 64- bit
545 * signed and unsigned integers where it uses RTStrFormatNumber() to perform
546 * the conversion. For all other types it throws an ENotImplemented
547 * exception. Individual template specializations for known types should do
548 * the conversion job. If the conversion is not possible (for example the
549 * given value doesn't have a string representation), the relevant
550 * specialization should throw an ENoConversion exception.
551 *
552 * If the @a aValue argument's value would convert to a NULL string, this
553 * method will throw an ENoValue exception. All specializations must do the
554 * same.
555 *
556 * @param aValue Value to convert.
557 * @param aExtra Extra flags to define additional formatting. In case of
558 * integer types, it's the base used for string representation.
559 *
560 * @return Result of conversion.
561 */
562template <typename T>
563stdx::char_auto_ptr ToString (const T &aValue, unsigned int aExtra = 0)
564{
565 if (std::numeric_limits <T>::is_integer)
566 {
567 bool sign = std::numeric_limits <T>::is_signed;
568 int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
569
570 return ToStringInteger (aValue, aExtra, sign, bits);
571 }
572
573 throw ENotImplemented (RT_SRC_POS);
574}
575
576/**
577 * Specialization of ToString for bool.
578 *
579 * Converts true to "true" and false to "false". @a aExtra is not used.
580 */
581template<> DECLEXPORT (stdx::char_auto_ptr)
582ToString <bool> (const bool &aValue, unsigned int aExtra);
583
584/**
585 * Specialization of ToString for RTTIMESPEC.
586 *
587 * Converts the RTTIMESPEC value to the date string in ISO format
588 * (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone]). Currently, the timezone will
589 * always be Z (UTC).
590 *
591 * @a aExtra is not used.
592 */
593template<> DECLEXPORT (stdx::char_auto_ptr)
594ToString <RTTIMESPEC> (const RTTIMESPEC &aValue, unsigned int aExtra);
595
596/**
597 * Converts memory bytes to a null-terminated string of hex values.
598 *
599 * @param aData Pointer to the memory block.
600 * @param aLen Length of the memory block.
601 *
602 * @return Result of conversion.
603 */
604DECLEXPORT (stdx::char_auto_ptr) ToString (const void *aData, size_t aLen);
605
606// the rest
607//////////////////////////////////////////////////////////////////////////////
608
609/**
610 * The Key class represents a settings key.
611 *
612 * Every settings key has a name and zero or more uniquely named values
613 * (attributes). There is a special attribute with a NULL name that is called
614 * a key value.
615 *
616 * Besides values, settings keys may contain other settings keys. This way,
617 * settings keys form a tree-like (or a directory-like) hierarchy of keys. Key
618 * names do not need to be unique even if they belong to the same parent key
619 * which allows to have an array of keys of the same name.
620 *
621 * @note Key and Value objects returned by methods of the Key and TreeBackend
622 * classes are owned by the given TreeBackend instance and may refer to data
623 * that becomes invalid when this TreeBackend instance is destroyed.
624 */
625class VBOXSETTINGS_CLASS Key
626{
627public:
628
629 typedef std::list <Key> List;
630
631 /**
632 * Key backend interface used to perform actual key operations.
633 *
634 * This interface is implemented by backends that provide specific ways of
635 * storing settings keys.
636 */
637 class VBOXSETTINGS_CLASS Backend : public stdx::auto_ref
638 {
639 public:
640
641 /** Performs the Key::name() function. */
642 virtual const char *name() const = 0;
643
644 /** Performs the Key::setName() function. */
645 virtual void setName (const char *aName) = 0;
646
647 /** Performs the Key::stringValue() function. */
648 virtual const char *value (const char *aName) const = 0;
649
650 /** Performs the Key::setStringValue() function. */
651 virtual void setValue (const char *aName, const char *aValue) = 0;
652
653 /** Performs the Key::keys() function. */
654 virtual List keys (const char *aName = NULL) const = 0;
655
656 /** Performs the Key::findKey() function. */
657 virtual Key findKey (const char *aName) const = 0;
658
659 /** Performs the Key::appendKey() function. */
660 virtual Key appendKey (const char *aName) = 0;
661
662 /** Performs the Key::zap() function. */
663 virtual void zap() = 0;
664
665 /**
666 * Returns an opaque value that uniquely represents the position of
667 * this key on the tree which is used to compare two keys. Two or more
668 * keys may return the same value only if they actually represent the
669 * same key (i.e. they have the same list of parents and children).
670 */
671 virtual void *position() const = 0;
672 };
673
674 /**
675 * Creates a new key object. If @a aBackend is @c NULL then a null key is
676 * created.
677 *
678 * Regular API users should never need to call this method with something
679 * other than NULL argument (which is the default).
680 *
681 * @param aBackend Key backend to use.
682 */
683 Key (Backend *aBackend = NULL) : m (aBackend) {}
684
685 /**
686 * Returns @c true if this key is null.
687 */
688 bool isNull() const { return m.is_null(); }
689
690 /**
691 * Makes this object a null key.
692 *
693 * Note that as opposed to #zap(), this methid does not delete the key from
694 * the list of children of its parent key.
695 */
696 void setNull() { m = NULL; }
697
698 /**
699 * Returns the name of this key.
700 * Returns NULL if this object a null (uninitialized) key.
701 */
702 const char *name() const { return m.is_null() ? NULL : m->name(); }
703
704 /**
705 * Sets the name of this key.
706 *
707 * @param aName New key name.
708 */
709 void setName (const char *aName) { if (!m.is_null()) m->setName (aName); }
710
711 /**
712 * Returns the value of the attribute with the given name as an UTF-8
713 * string. Returns @c NULL if there is no attribute with the given name.
714 *
715 * @param aName Name of the attribute. NULL may be used to
716 * get the key value.
717 */
718 const char *stringValue (const char *aName) const
719 {
720 return m.is_null() ? NULL : m->value (aName);
721 }
722
723 /**
724 * Sets the value of the attribute with the given name from an UTF-8
725 * string. This method will do a copy of the supplied @a aValue string.
726 *
727 * @param aName Name of the attribute. NULL may be used to
728 * set the key value.
729 * @param aValue New value of the attribute. NULL may be used to
730 * delete the value instead of setting it.
731 */
732 void setStringValue (const char *aName, const char *aValue)
733 {
734 if (!m.is_null()) m->setValue (aName, aValue);
735 }
736
737 /**
738 * Returns the value of the attribute with the given name as an object of
739 * type @a T. Throws ENoValue if there is no attribute with the given
740 * name.
741 *
742 * This function calls #stringValue() to get the string representation of
743 * the attribute and then calls the FromString() template to convert this
744 * string to a value of the given type.
745 *
746 * @param aName Name of the attribute. NULL may be used to
747 * get the key value.
748 */
749 template <typename T>
750 T value (const char *aName) const
751 {
752 try
753 {
754 return FromString <T> (stringValue (aName));
755 }
756 catch (const ENoValue &)
757 {
758 throw ENoValue (FmtStr ("No such attribute '%s'", aName));
759 }
760 }
761
762 /**
763 * Returns the value of the attribute with the given name as an object of
764 * type @a T. Returns the given default value if there is no attribute
765 * with the given name.
766 *
767 * This function calls #stringValue() to get the string representation of
768 * the attribute and then calls the FromString() template to convert this
769 * string to a value of the given type.
770 *
771 * @param aName Name of the attribute. NULL may be used to
772 * get the key value.
773 * @param aDefault Default value to return for the missing attribute.
774 */
775 template <typename T>
776 T valueOr (const char *aName, const T &aDefault) const
777 {
778 try
779 {
780 return FromString <T> (stringValue (aName));
781 }
782 catch (const ENoValue &)
783 {
784 return aDefault;
785 }
786 }
787
788 /**
789 * Sets the value of the attribute with the given name from an object of
790 * type @a T. This method will do a copy of data represented by @a aValue
791 * when necessary.
792 *
793 * This function converts the given value to a string using the ToString()
794 * template and then calls #setStringValue().
795 *
796 * @param aName Name of the attribute. NULL may be used to
797 * set the key value.
798 * @param aValue New value of the attribute.
799 * @param aExtra Extra field used by some types to specify additional
800 * details for storing the value as a string (such as the
801 * base for decimal numbers).
802 */
803 template <typename T>
804 void setValue (const char *aName, const T &aValue, unsigned int aExtra = 0)
805 {
806 try
807 {
808 stdx::char_auto_ptr value = ToString (aValue, aExtra);
809 setStringValue (aName, value.get());
810 }
811 catch (const ENoValue &)
812 {
813 throw ENoValue (FmtStr ("No value for attribute '%s'", aName));
814 }
815 }
816
817 /**
818 * Sets the value of the attribute with the given name from an object of
819 * type @a T. If the value of the @a aValue object equals to the value of
820 * the given @a aDefault object, then the attribute with the given name
821 * will be deleted instead of setting its value to @a aValue.
822 *
823 * This function converts the given value to a string using the ToString()
824 * template and then calls #setStringValue().
825 *
826 * @param aName Name of the attribute. NULL may be used to
827 * set the key value.
828 * @param aValue New value of the attribute.
829 * @param aDefault Default value to compare @a aValue to.
830 * @param aExtra Extra field used by some types to specify additional
831 * details for storing the value as a string (such as the
832 * base for decimal numbers).
833 */
834 template <typename T>
835 void setValueOr (const char *aName, const T &aValue, const T &aDefault,
836 unsigned int aExtra = 0)
837 {
838 if (aValue == aDefault)
839 zapValue (aName);
840 else
841 setValue <T> (aName, aValue, aExtra);
842 }
843
844 /**
845 * Deletes the value of the attribute with the given name.
846 * Shortcut to <tt>setStringValue(aName, NULL)</tt>.
847 */
848 void zapValue (const char *aName) { setStringValue (aName, NULL); }
849
850 /**
851 * Returns the key value.
852 * Shortcut to <tt>stringValue (NULL)</tt>.
853 */
854 const char *keyStringValue() const { return stringValue (NULL); }
855
856 /**
857 * Sets the key value.
858 * Shortcut to <tt>setStringValue (NULL, aValue)</tt>.
859 */
860 void setKeyStringValue (const char *aValue) { setStringValue (NULL, aValue); }
861
862 /**
863 * Returns the key value.
864 * Shortcut to <tt>value (NULL)</tt>.
865 */
866 template <typename T>
867 T keyValue() const { return value <T> (NULL); }
868
869 /**
870 * Returns the key value or the given default if the key value is NULL.
871 * Shortcut to <tt>value (NULL)</tt>.
872 */
873 template <typename T>
874 T keyValueOr (const T &aDefault) const { return valueOr <T> (NULL, aDefault); }
875
876 /**
877 * Sets the key value.
878 * Shortcut to <tt>setValue (NULL, aValue, aExtra)</tt>.
879 */
880 template <typename T>
881 void setKeyValue (const T &aValue, unsigned int aExtra = 0)
882 {
883 setValue <T> (NULL, aValue, aExtra);
884 }
885
886 /**
887 * Sets the key value.
888 * Shortcut to <tt>setValueOr (NULL, aValue, aDefault)</tt>.
889 */
890 template <typename T>
891 void setKeyValueOr (const T &aValue, const T &aDefault,
892 unsigned int aExtra = 0)
893 {
894 setValueOr <T> (NULL, aValue, aDefault, aExtra);
895 }
896
897 /**
898 * Deletes the key value.
899 * Shortcut to <tt>zapValue (NULL)</tt>.
900 */
901 void zapKeyValue () { zapValue (NULL); }
902
903 /**
904 * Returns a list of all child keys named @a aName.
905 *
906 * If @a aname is @c NULL, returns a list of all child keys.
907 *
908 * @param aName Child key name to list.
909 */
910 List keys (const char *aName = NULL) const
911 {
912 return m.is_null() ? List() : m->keys (aName);
913 };
914
915 /**
916 * Returns the first child key with the given name.
917 *
918 * Throws ENoKey if no child key with the given name exists.
919 *
920 * @param aName Child key name.
921 */
922 Key key (const char *aName) const
923 {
924 Key key = findKey (aName);
925 if (key.isNull())
926 throw ENoKey (FmtStr ("No such key '%s'", aName));
927 return key;
928 }
929
930 /**
931 * Returns the first child key with the given name.
932 *
933 * As opposed to #key(), this method will not throw an exception if no
934 * child key with the given name exists, but return a null key instead.
935 *
936 * @param aName Child key name.
937 */
938 Key findKey (const char *aName) const
939 {
940 return m.is_null() ? Key() : m->findKey (aName);
941 }
942
943 /**
944 * Creates a key with the given name as a child of this key and returns it
945 * to the caller.
946 *
947 * If one or more child keys with the given name already exist, no new key
948 * is created but the first matching child key is returned.
949 *
950 * @param aName Name of the child key to create.
951 */
952 Key createKey (const char *aName)
953 {
954 Key key = findKey (aName);
955 if (key.isNull())
956 key = appendKey (aName);
957 return key;
958 }
959
960 /**
961 * Appends a key with the given name to the list of child keys of this key
962 * and returns the appended key to the caller.
963 *
964 * @param aName Name of the child key to create.
965 */
966 Key appendKey (const char *aName)
967 {
968 return m.is_null() ? Key() : m->appendKey (aName);
969 }
970
971 /**
972 * Deletes this key.
973 *
974 * The deleted key is removed from the list of child keys of its parent
975 * key and becomes a null object.
976 */
977 void zap()
978 {
979 if (!m.is_null())
980 {
981 m->zap();
982 setNull();
983 }
984 }
985
986 /**
987 * Compares this object with the given object and returns @c true if both
988 * represent the same key on the settings tree or if both are null
989 * objects.
990 *
991 * @param that Object to compare this object with.
992 */
993 bool operator== (const Key &that) const
994 {
995 return m == that.m ||
996 (!m.is_null() && !that.m.is_null() &&
997 m->position() == that.m->position());
998 }
999
1000 /**
1001 * Counterpart to operator==().
1002 */
1003 bool operator!= (const Key &that) const { return !operator== (that); }
1004
1005private:
1006
1007 stdx::auto_ref_ptr <Backend> m;
1008
1009 friend class TreeBackend;
1010};
1011
1012/**
1013 * The Stream class is a base class for I/O streams.
1014 */
1015class VBOXSETTINGS_CLASS Stream
1016{
1017public:
1018
1019 virtual ~Stream() {}
1020
1021 virtual const char *uri() const = 0;
1022
1023 /**
1024 * Returns the current read/write position in the stream. The returned
1025 * position is a zero-based byte offset from the beginning of the file.
1026 *
1027 * Throws ENotImplemented if this operation is not implemented for the
1028 * given stream.
1029 */
1030 virtual uint64_t pos() const = 0;
1031
1032 /**
1033 * Sets the current read/write position in the stream.
1034 *
1035 * @param aPos Zero-based byte offset from the beginning of the stream.
1036 *
1037 * Throws ENotImplemented if this operation is not implemented for the
1038 * given stream.
1039 */
1040 virtual void setPos (uint64_t aPos) = 0;
1041};
1042
1043/**
1044 * The Input class represents an input stream.
1045 *
1046 * This input stream is used to read the settings tree from.
1047 * This is an abstract class that must be subclassed in order to fill it with
1048 * useful functionality.
1049 */
1050class VBOXSETTINGS_CLASS Input : virtual public Stream
1051{
1052public:
1053
1054 /**
1055 * Reads from the stream to the supplied buffer.
1056 *
1057 * @param aBuf Buffer to store read data to.
1058 * @param aLen Buffer length.
1059 *
1060 * @return Number of bytes read.
1061 */
1062 virtual int read (char *aBuf, int aLen) = 0;
1063};
1064
1065/**
1066 *
1067 */
1068class VBOXSETTINGS_CLASS Output : virtual public Stream
1069{
1070public:
1071
1072 /**
1073 * Writes to the stream from the supplied buffer.
1074 *
1075 * @param aBuf Buffer to write data from.
1076 * @param aLen Buffer length.
1077 *
1078 * @return Number of bytes written.
1079 */
1080 virtual int write (const char *aBuf, int aLen) = 0;
1081
1082 /**
1083 * Truncates the stream from the current position and upto the end.
1084 * The new file size will become exactly #pos() bytes.
1085 *
1086 * Throws ENotImplemented if this operation is not implemented for the
1087 * given stream.
1088 */
1089 virtual void truncate() = 0;
1090};
1091
1092/**
1093 * The TreeBackend class represents a storage backend used to read a settings
1094 * tree from and write it to a stream.
1095 *
1096 * @note All Key objects returned by any of the TreeBackend methods (and by
1097 * methods of returned Key objects) are owned by the given TreeBackend
1098 * instance. When this instance is destroyed, all Key objects become invalid
1099 * and an attempt to access Key data will cause the program crash.
1100 */
1101class VBOXSETTINGS_CLASS TreeBackend
1102{
1103public:
1104
1105 /**
1106 * Reads and parses the given input stream.
1107 *
1108 * On success, the previous settings tree owned by this backend (if any)
1109 * is deleted.
1110 *
1111 * The optional schema URI argument determines the name of the schema to
1112 * use for input validation. If the schema URI is NULL then the validation
1113 * is not performed. Note that you may set a custom input resolver if you
1114 * want to provide the input stream for the schema file (and for other
1115 * external entities) instead of letting the backend to read the specified
1116 * URI directly.
1117 *
1118 * This method will set the read/write position to the beginning of the
1119 * given stream before reading. After the stream has been successfully
1120 * parsed, the position will be set back to the beginning.
1121 *
1122 * @param aInput Input stream.
1123 * @param aSchema Schema URI to use for input stream validation.
1124 * @param aFlags Optional bit flags.
1125 */
1126 void read (Input &aInput, const char *aSchema = NULL, int aFlags = 0)
1127 {
1128 aInput.setPos (0);
1129 rawRead (aInput, aSchema, aFlags);
1130 aInput.setPos (0);
1131 }
1132
1133 /**
1134 * Reads and parses the given input stream in a raw fashion.
1135 *
1136 * This method doesn't set the stream position to the beginnign before and
1137 * after reading but instead leaves it as is in both cases. It's the
1138 * caller's responsibility to maintain the correct position.
1139 *
1140 * @see read()
1141 */
1142 virtual void rawRead (Input &aInput, const char *aSchema = NULL,
1143 int aFlags = 0) = 0;
1144
1145 /**
1146 * Writes the current settings tree to the given output stream.
1147 *
1148 * This method will set the read/write position to the beginning of the
1149 * given stream before writing. After the settings have been successfully
1150 * written to the stream, the stream will be truncated at the position
1151 * following the last byte written by this method anc ghd position will be
1152 * set back to the beginning.
1153 *
1154 * @param aOutput Output stream.
1155 */
1156 void write (Output &aOutput)
1157 {
1158 aOutput.setPos (0);
1159 rawWrite (aOutput);
1160 aOutput.truncate();
1161 aOutput.setPos (0);
1162 }
1163
1164 /**
1165 * Writes the current settings tree to the given output stream in a raw
1166 * fashion.
1167 *
1168 * This method doesn't set the stream position to the beginnign before and
1169 * after reading and doesn't truncate the stream, but instead leaves it as
1170 * is in both cases. It's the caller's responsibility to maintain the
1171 * correct position and perform truncation.
1172 *
1173 * @see write()
1174 */
1175 virtual void rawWrite (Output &aOutput) = 0;
1176
1177 /**
1178 * Deletes the current settings tree.
1179 */
1180 virtual void reset() = 0;
1181
1182 /**
1183 * Returns the root settings key.
1184 */
1185 virtual Key &rootKey() const = 0;
1186
1187protected:
1188
1189 static Key::Backend *GetKeyBackend (const Key &aKey) { return aKey.m.raw(); }
1190};
1191
1192//////////////////////////////////////////////////////////////////////////////
1193
1194/**
1195 * The File class is a stream implementation that reads from and writes to
1196 * regular files.
1197 *
1198 * The File class uses IPRT File API for file operations. Note that IPRT File
1199 * API is not thread-safe. This means that if you pass the same RTFILE handle to
1200 * different File instances that may be simultaneously used on different
1201 * threads, you should care about serialization; otherwise you will get garbage
1202 * when reading from or writing to such File instances.
1203 */
1204class VBOXSETTINGS_CLASS File : public Input, public Output
1205{
1206public:
1207
1208 /**
1209 * Possible file access modes.
1210 */
1211 enum Mode { Mode_Read, Mode_Write, Mode_ReadWrite };
1212
1213 /**
1214 * Opens a file with the given name in the given mode. If @a aMode is Read
1215 * or ReadWrite, the file must exist. If @a aMode is Write, the file must
1216 * not exist. Otherwise, an EIPRTFailure excetion will be thrown.
1217 *
1218 * @param aMode File mode.
1219 * @param aFileName File name.
1220 */
1221 File (Mode aMode, const char *aFileName);
1222
1223 /**
1224 * Uses the given file handle to perform file operations. This file
1225 * handle must be already open in necessary mode (read, or write, or mixed).
1226 *
1227 * The read/write position of the given handle will be reset to the
1228 * beginning of the file on success.
1229 *
1230 * Note that the given file handle will not be automatically closed upon
1231 * this object destruction.
1232 *
1233 * @note It you pass the same RTFILE handle to more than one File instance,
1234 * please make sure you have provided serialization in case if these
1235 * instasnces are to be simultaneously used by different threads.
1236 * Otherwise you may get garbage when reading or writing.
1237 *
1238 * @param aHandle Open file handle.
1239 * @param aFileName File name (for reference).
1240 */
1241 File (RTFILE aHandle, const char *aFileName = NULL);
1242
1243 /**
1244 * Destrroys the File object. If the object was created from a file name
1245 * the corresponding file will be automatically closed. If the object was
1246 * created from a file handle, it will remain open.
1247 */
1248 virtual ~File();
1249
1250 const char *uri() const;
1251
1252 uint64_t pos() const;
1253 void setPos (uint64_t aPos);
1254
1255 /**
1256 * See Input::read(). If this method is called in wrong file mode,
1257 * LogicError will be thrown.
1258 */
1259 int read (char *aBuf, int aLen);
1260
1261 /**
1262 * See Output::write(). If this method is called in wrong file mode,
1263 * LogicError will be thrown.
1264 */
1265 int write (const char *aBuf, int aLen);
1266
1267 /**
1268 * See Output::truncate(). If this method is called in wrong file mode,
1269 * LogicError will be thrown.
1270 */
1271 void truncate();
1272
1273private:
1274
1275 /* Obscure class data */
1276 struct Data;
1277 std::auto_ptr <Data> m;
1278
1279 /* auto_ptr data doesn't have proper copy semantics */
1280 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)
1281};
1282
1283/**
1284 * The MemoryBuf class represents a stream implementation that reads from the
1285 * memory buffer.
1286 */
1287class VBOXSETTINGS_CLASS MemoryBuf : public Input
1288{
1289public:
1290
1291 MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
1292
1293 virtual ~MemoryBuf();
1294
1295 const char *uri() const;
1296
1297 int read (char *aBuf, int aLen);
1298 uint64_t pos() const;
1299 void setPos (uint64_t aPos);
1300
1301private:
1302
1303 /* Obscure class data */
1304 struct Data;
1305 std::auto_ptr <Data> m;
1306
1307 /* auto_ptr data doesn't have proper copy semantics */
1308 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf)
1309};
1310
1311class XmlKeyBackend;
1312
1313/**
1314 * The XmlTreeBackend class uses XML markup to store settings trees.
1315 *
1316 * @note libxml2 and libxslt libraries used by the XmlTreeBackend are not
1317 * fully reentrant. To "fix" this, the XmlTreeBackend backend serializes access
1318 * to such non-reentrant parts using a global mutex so that only one thread can
1319 * use non-reentrant code at a time. Currently, this relates to the #rawRead()
1320 * method (and to #read() as a consequence). This means that only one thread can
1321 * parse an XML stream at a time; other threads trying to parse same or
1322 * different streams using different XmlTreeBackend and Input instances
1323 * will have to wait.
1324 *
1325 * Keep in mind that the above reentrancy fix does not imply thread-safety: it
1326 * is still the caller's responsibility to provide serialization if the same
1327 * XmlTreeBackend instnace (as well as instances of other classes from the
1328 * settings namespace) needs to be used by more than one thread.
1329 */
1330class VBOXSETTINGS_CLASS XmlTreeBackend : public TreeBackend
1331{
1332public:
1333
1334 /** Flags for TreeBackend::read(). */
1335 enum
1336 {
1337 /**
1338 * Sbstitute default values for missing attributes that have defaults
1339 * in the XML schema. Otherwise, stringValue() will return NULL for
1340 * such attributes.
1341 */
1342 Read_AddDefaults = RT_BIT (0),
1343 };
1344
1345 /**
1346 * The Error class represents errors that may happen when parsing or
1347 * validating the XML document representing the settings tree.
1348 */
1349 class VBOXSETTINGS_CLASS Error : public RuntimeError
1350 {
1351 public:
1352
1353 Error (const char *aMsg = NULL) : RuntimeError (aMsg) {}
1354 };
1355
1356 /**
1357 * The EConversionCycle class represents a conversion cycle detected by the
1358 * AutoConverter::needsConversion() implementation.
1359 */
1360 class VBOXSETTINGS_CLASS EConversionCycle : public Error
1361 {
1362 public:
1363
1364 EConversionCycle (const char *aMsg = NULL) : Error (aMsg) {}
1365 };
1366
1367 /**
1368 * The InputResolver class represents an interface to provide input streams
1369 * for external entities given an URL and entity ID.
1370 */
1371 class VBOXSETTINGS_CLASS InputResolver
1372 {
1373 public:
1374
1375 /**
1376 * Returns a newly allocated input stream for the given arguments. The
1377 * caller will delete the returned object when no more necessary.
1378 *
1379 * @param aURI URI of the external entity.
1380 * @param aID ID of the external entity (may be NULL).
1381 *
1382 * @return Input stream created using @c new or NULL to indicate
1383 * a wrong URI/ID pair.
1384 *
1385 * @todo Return by value after implementing the copy semantics for
1386 * Input subclasses.
1387 */
1388 virtual Input *resolveEntity (const char *aURI, const char *aID) = 0;
1389 };
1390
1391 /**
1392 * The AutoConverter class represents an interface to automatically convert
1393 * old settings trees to a new version when the tree is read from the
1394 * stream.
1395 */
1396 class VBOXSETTINGS_CLASS AutoConverter
1397 {
1398 public:
1399
1400 /**
1401 * Returns @true if the given tree needs to be converted using the XSLT
1402 * template identified by #templateUri(), or @false if no conversion is
1403 * required.
1404 *
1405 * The implementation normally checks for the "version" value of the
1406 * root key to determine if the conversion is necessary. When the
1407 * @a aOldVersion argument is not NULL, the implementation must return a
1408 * non-NULL non-empty string representing the old version (before
1409 * conversion) in it this string is used by XmlTreeBackend::oldVersion()
1410 * and must be non-NULL to indicate that the conversion has been
1411 * performed on the tree. The returned string must be allocated using
1412 * RTStrDup() or such.
1413 *
1414 * This method is called again after the successful transformation to
1415 * let the implementation retry the version check and request another
1416 * transformation if necessary. This may be used to perform multi-step
1417 * conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3)
1418 * which saves from the need to update all previous conversion
1419 * templates to make each of them convert directly to the recent
1420 * version.
1421 *
1422 * @note Multi-step transformations are performed in a loop that exits
1423 * only when this method returns @false. It's up to the
1424 * implementation to detect cycling (repeated requests to convert
1425 * from the same version) wrong version order, etc. and throw an
1426 * EConversionCycle exception to break the loop without returning
1427 * @false (which means the transformation succeeded).
1428 *
1429 * @param aRoot Root settings key.
1430 * @param aOldVersionString Where to store old version string
1431 * pointer. May be NULL. Allocated memory is
1432 * freed by the caller using RTStrFree().
1433 */
1434 virtual bool needsConversion (const Key &aRoot,
1435 char **aOldVersion) const = 0;
1436
1437 /**
1438 * Returns the URI of the XSLT template to perform the conversion.
1439 * This template will be applied to the tree if #needsConversion()
1440 * returns @c true for this tree.
1441 */
1442 virtual const char *templateUri() const = 0;
1443 };
1444
1445 XmlTreeBackend();
1446 ~XmlTreeBackend();
1447
1448 /**
1449 * Sets an external entity resolver used to provide input streams for
1450 * entities referred to by the XML document being parsed.
1451 *
1452 * The given resolver object must exist as long as this instance exists or
1453 * until a different resolver is set using setInputResolver() or reset
1454 * using resetInputResolver().
1455 *
1456 * @param aResolver Resolver to use.
1457 */
1458 void setInputResolver (InputResolver &aResolver);
1459
1460 /**
1461 * Resets the entity resolver to the default resolver. The default
1462 * resolver provides support for 'file:' and 'http:' protocols.
1463 */
1464 void resetInputResolver();
1465
1466 /**
1467 * Sets a settings tree converter and enables the automatic conversion.
1468 *
1469 * The Automatic settings tree conversion is useful for upgrading old
1470 * settings files to the new version transparently during execution of the
1471 * #read() method.
1472 *
1473 * The automatic conversion takes place after reading the document from the
1474 * stream but before validating it. The given converter is asked if the
1475 * conversion is necessary using the AutoConverter::needsConversion() call,
1476 * and if so, the XSLT template specified by AutoConverter::templateUri() is
1477 * applied to the settings tree.
1478 *
1479 * Note that in order to make the result of the conversion permanent, the
1480 * settings tree needs to be exlicitly written back to the stream.
1481 *
1482 * The given converter object must exist as long as this instance exists or
1483 * until a different converter is set using setAutoConverter() or reset
1484 * using resetAutoConverter().
1485 *
1486 * @param aConverter Settings converter to use.
1487 */
1488 void setAutoConverter (AutoConverter &aConverter);
1489
1490 /**
1491 * Disables the automatic settings conversion previously enabled by
1492 * setAutoConverter(). By default automatic conversion it is disabled.
1493 */
1494 void resetAutoConverter();
1495
1496 /**
1497 * Returns a non-NULL string if the automatic settings conversion has been
1498 * performed during the last successful #read() call. Returns @c NULL if
1499 * there was no settings conversion.
1500 *
1501 * If #read() fails, this method will return the version string set by the
1502 * previous successful #read() call or @c NULL if there were no #read()
1503 * calls.
1504 */
1505 const char *oldVersion() const;
1506
1507 void rawRead (Input &aInput, const char *aSchema = NULL, int aFlags = 0);
1508 void rawWrite (Output &aOutput);
1509 void reset();
1510 Key &rootKey() const;
1511
1512private:
1513
1514 class XmlError;
1515
1516 /* Obscure class data */
1517 struct Data;
1518 std::auto_ptr <Data> m;
1519
1520 /* auto_ptr data doesn't have proper copy semantics */
1521 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (XmlTreeBackend)
1522
1523 static int ReadCallback (void *aCtxt, char *aBuf, int aLen);
1524 static int WriteCallback (void *aCtxt, const char *aBuf, int aLen);
1525 static int CloseCallback (void *aCtxt);
1526
1527 static void ValidityErrorCallback (void *aCtxt, const char *aMsg, ...);
1528 static void ValidityWarningCallback (void *aCtxt, const char *aMsg, ...);
1529 static void StructuredErrorCallback (void *aCtxt, xmlErrorPtr aErr);
1530
1531 static xmlParserInput *ExternalEntityLoader (const char *aURI,
1532 const char *aID,
1533 xmlParserCtxt *aCtxt);
1534
1535 static XmlTreeBackend *sThat;
1536
1537 static XmlKeyBackend *GetKeyBackend (const Key &aKey)
1538 { return (XmlKeyBackend *) TreeBackend::GetKeyBackend (aKey); }
1539};
1540
1541} /* namespace settings */
1542
1543#if defined(_MSC_VER)
1544#pragma warning (default:4251)
1545#endif
1546
1547#endif /* IN_RING3 */
1548
1549/** @} */
1550
1551#endif /* ___VBox_settings_h */
Note: See TracBrowser for help on using the repository browser.

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