VirtualBox

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

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

Main/Settigs: Redone semi-faulty r29679: When reading from settings files, reopen them instead of reusing the existing hande to allow for concurrent multithreaded reads. Provided libxml2/libxslt reentrance (using global serialization) when parsing settings files.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use