30
39
#ifndef ___VBox_settings_h
31
40
#define ___VBox_settings_h
33
#include <iprt/cdefs.h>
34
#include <iprt/cpputils.h>
35
#include <iprt/string.h>
41
42
#include <iprt/time.h>
44
#include "VBox/com/VirtualBox.h"
43
46
#include <VBox/com/Guid.h>
47
// #include <stdarg.h>
49
/* these conflict with numeric_digits<>::min and max */
54
/** @defgroup grp_settings Settings File Manipulation API
57
* The Settings File Manipulation API allows to maintain a configuration file
58
* that contains "name-value" pairs grouped under named keys which are in turn
59
* organized in a hierarchical tree-like structure:
63
* <Key1 attr1="value" attr2=""/>
64
* <Key2 attr1="value">
65
* <SubKey1>SubKey1_Value</SubKey1>
66
* <SubKey2 attr1="value">SubKey2_Value</SubKey2>
72
* All strings this API manipulates with are zero-terminated arrays of @c char
73
* in UTF-8 encoding. Strings returned by the API are owned by the API unless
74
* explicitly stated otherwise. Strings passed to the API are accessed by the
75
* API only during the given API call unless explicitly stated otherwise. If
76
* necessary, the API will make a copy of the supplied string.
78
* Error reporting is perfomed using C++ exceptions. All exceptions thrown by
79
* this API are derived from settings::Error. This doesn't cover exceptions
80
* that may be thrown by third-party library calls made by this API.
82
* All public classes represented by this API that support copy operations
83
* (i.e. may be created or assigned from other instsances of the same class),
84
* such as Key and Value classes, implement shallow copies and use this mode by
85
* default. It means two things:
87
* 1. Instances of these classes can be freely copied around and used as return
88
* values. All copies will share the same internal data block (using the
89
* reference counting technique) so that the copy operation is cheap, both
90
* in terms of memory and speed.
92
* 2. Since copied instances share the same data, an attempt to change data in
93
* the original will be reflected in all existing copies.
95
* Making deep copies or detaching the existing shallow copy from its original
96
* is not yet supported.
98
* Note that the Settings File API is not thread-safe. It means that if you
99
* want to use the same instance of a class from the settings namespace on more
100
* than one thread at a time, you will have to provide necessary access
101
* serialization yourself.
103
* Due to some (not propely studied) libxml2 limitations, the Settings File
104
* API is not thread-safe. Therefore, the API caller must provide
105
* serialization for threads using this API simultaneously. Note though that
106
* if the libxml2 library is (even imlicitly) used on some other thread which
107
* doesn't use this API (e.g. third-party code), it may lead to resource
108
* conflicts (followed by crashes, memory corruption etc.). A proper solution
109
* for these conflicts is to be found.
111
* In order to load a settings file the program creates a TreeBackend instance
112
* using one of the specific backends (e.g. XmlTreeBackend) and then passes an
113
* Input stream object (e.g. File or MemoryBuf) to the TreeBackend::read()
114
* method to parse the stream and build the settings tree. On success, the
115
* program uses the TreeBackend::rootKey() method to access the root key of
116
* the settings tree. The root key provides access to the whole tree of
117
* settings through the methods of the Key class which allow to read, change
118
* and create new key values. Below is an example that uses the XML backend to
119
* load the settings tree, then modifies it and then saves the modifications.
122
using namespace settings;
126
File file (File::ReadWrite, "myfile.xml");
129
// load the tree, parse it and validate using the XML schema
130
tree.read (aFile, "myfile.xsd", XmlTreeBackend::Read_AddDefaults);
133
Key root = tree.key();
134
printf ("root=%s\n", root.name());
136
// enumerate all child keys of the root key named Foo
137
Key::list children = root.keys ("Foo");
138
for (Key::list::const_iterator it = children.begin();
139
it != children.end();
142
// get the "level" attribute
143
int level = (*it).value <int> ("level");
146
// if so, create a "Bar" key if it doesn't exist yet
147
Key bar = (*it).createKey ("Bar");
148
// set the "date" attribute
151
bar.setValue <RTTIMESPEC> ("date", now);
155
// if its below 2, delete the whole "Foo" key
160
// save the tree on success (the second try is to distinguish between
161
// stream load and save errors)
166
catch (const EIPRTFailure &err)
168
// this is an expected exception that may happen in case of stream
169
// read or write errors
170
printf ("Could not save the settings file '%s' (%Rrc)");
171
file.uri(), err.rc());
178
catch (const EIPRTFailure &err)
180
// this is an expected exception that may happen in case of stream
181
// read or write errors
182
printf ("Could not load the settings file '%s' (%Rrc)");
183
file.uri(), err.rc());
185
catch (const XmlTreeBackend::Error &err)
187
// this is an XmlTreeBackend specific exception that may
188
// happen in case of XML parse or validation errors
189
printf ("Could not load the settings file '%s'.\n%s"),
190
file.uri(), err.what() ? err.what() : "Unknown error");
192
catch (const std::exception &err)
194
// the rest is unexpected (e.g. should not happen unless you
195
// specifically wish so for some reason and therefore allow for a
196
// situation that may throw one of these from within the try block
198
AssertMsgFailed ("Unexpected exception '%s' (%s)\n",
199
typeid (err).name(), err.what());
203
// this is even more unexpected, and no any useful info here
204
AssertMsgFailed ("Unexpected exception\n");
210
* Note that you can get a raw (string) value of the attribute using the
211
* Key::stringValue() method but often it's simpler and better to use the
212
* templated Key::value<>() method that can convert the string to a value of
213
* the given type for you (and throw exceptions when the converison is not
214
* possible). Similarly, the Key::setStringValue() method is used to set a raw
215
* string value and there is a templated Key::setValue<>() method to set a
216
* typed value which will implicitly convert it to a string.
218
* Currently, types supported by Key::value<>() and Key::setValue<>() include
219
* all C and IPRT integer types, bool and RTTIMESPEC (represented as isoDate
220
* in XML). You can always add support for your own types by creating
221
* additional specializations of the FromString<>() and ToString<>() templates
222
* in the settings namespace (see the real examples in this header).
224
* See individual funciton, class and method descriptions to get more details
225
* on the Settings File Manipulation API.
229
* Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
230
* result of private data member declarations of some classes below) need to
231
* be exported too to in order to be accessible by clients.
233
* The alternative is to instantiate a template before the data member
234
* declaration with the VBOXXML_CLASS prefix, but the standard disables
235
* explicit instantiations in a foreign namespace. In other words, a declaration
238
* template class VBOXXML_CLASS std::auto_ptr <Data>;
240
* right before the member declaration makes MSVC happy too, but this is not a
241
* valid C++ construct (and G++ spits it out). So, for now we just disable the
242
* warning and will come back to this problem one day later.
244
* We also disable another warning (4275) saying that a DLL-exported class
245
* inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
246
* std::bad_alloc). I can't get how it can harm yet.
248
#if defined(_MSC_VER)
249
#pragma warning (disable:4251)
250
#pragma warning (disable:4275)
254
typedef struct _xmlParserInput xmlParserInput;
255
typedef xmlParserInput *xmlParserInputPtr;
256
typedef struct _xmlParserCtxt xmlParserCtxt;
257
typedef xmlParserCtxt *xmlParserCtxtPtr;
258
typedef struct _xmlError xmlError;
259
typedef xmlError *xmlErrorPtr;
263
* Settings File Manipulation API namespace.
47
#include <VBox/com/string.h>
265
58
namespace settings
268
// Exceptions (on top of vboxxml exceptions)
269
//////////////////////////////////////////////////////////////////////////////
271
class VBOXXML_CLASS ENoKey : public xml::LogicError
275
ENoKey (const char *aMsg = NULL) : xml::LogicError (aMsg) {}
278
class VBOXXML_CLASS ENoValue : public xml::LogicError
282
ENoValue (const char *aMsg = NULL) : xml::LogicError (aMsg) {}
285
class VBOXXML_CLASS ENoConversion : public xml::RuntimeError
289
ENoConversion (const char *aMsg = NULL) : RuntimeError (aMsg) {}
294
//////////////////////////////////////////////////////////////////////////////
296
// string -> type conversions
297
//////////////////////////////////////////////////////////////////////////////
300
* Helper for the FromString() template, doesn't need to be called directly.
302
DECLEXPORT (uint64_t) FromStringInteger (const char *aValue, bool aSigned,
303
int aBits, uint64_t aMin, uint64_t aMax);
306
* Generic template function to perform a conversion of an UTF-8 string to an
307
* arbitrary value of type @a T.
309
* This generic template is implenented only for 8-, 16-, 32- and 64- bit
310
* signed and unsigned integers where it uses RTStrTo[U]Int64() to perform the
311
* conversion. For all other types it throws an ENotImplemented
312
* exception. Individual template specializations for known types should do
313
* the conversion job.
315
* If the conversion is not possible (for example the string format is wrong
316
* or meaningless for the given type), this template will throw an
317
* ENoConversion exception. All specializations must do the same.
319
* If the @a aValue argument is NULL, this method will throw an ENoValue
320
* exception. All specializations must do the same.
322
* @param aValue Value to convert.
324
* @return Result of conversion.
326
template <typename T>
327
T FromString (const char *aValue)
329
if (std::numeric_limits <T>::is_integer)
331
bool sign = std::numeric_limits <T>::is_signed;
332
int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
334
return (T) FromStringInteger (aValue, sign, bits,
335
(uint64_t) std::numeric_limits <T>::min(),
336
(uint64_t) std::numeric_limits <T>::max());
339
throw xml::ENotImplemented (RT_SRC_POS);
343
* Specialization of FromString for bool.
345
* Converts "true", "yes", "on" to true and "false", "no", "off" to false.
347
template<> DECLEXPORT (bool) FromString <bool> (const char *aValue);
350
* Specialization of FromString for RTTIMESPEC.
352
* Converts the date in ISO format (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone])
353
* to a RTTIMESPEC value. Currently, the timezone must always be Z (UTC).
355
template<> DECLEXPORT (RTTIMESPEC) FromString <RTTIMESPEC> (const char *aValue);
358
* Converts a string of hex digits to memory bytes.
360
* @param aValue String to convert.
361
* @param aLen Where to store the length of the returned memory
362
* block (may be NULL).
364
* @return Result of conversion (a block of @a aLen bytes).
366
DECLEXPORT (stdx::char_auto_ptr) FromString (const char *aValue, size_t *aLen);
368
// type -> string conversions
369
//////////////////////////////////////////////////////////////////////////////
372
* Helper for the ToString() template, doesn't need to be called directly.
374
DECLEXPORT (stdx::char_auto_ptr)
375
ToStringInteger (uint64_t aValue, unsigned int aBase,
376
bool aSigned, int aBits);
379
* Generic template function to perform a conversion of an arbitrary value to
382
* This generic template is implemented only for 8-, 16-, 32- and 64- bit
383
* signed and unsigned integers where it uses RTStrFormatNumber() to perform
384
* the conversion. For all other types it throws an ENotImplemented
385
* exception. Individual template specializations for known types should do
386
* the conversion job. If the conversion is not possible (for example the
387
* given value doesn't have a string representation), the relevant
388
* specialization should throw an ENoConversion exception.
390
* If the @a aValue argument's value would convert to a NULL string, this
391
* method will throw an ENoValue exception. All specializations must do the
394
* @param aValue Value to convert.
395
* @param aExtra Extra flags to define additional formatting. In case of
396
* integer types, it's the base used for string representation.
398
* @return Result of conversion.
400
template <typename T>
401
stdx::char_auto_ptr ToString (const T &aValue, unsigned int aExtra = 0)
403
if (std::numeric_limits <T>::is_integer)
405
bool sign = std::numeric_limits <T>::is_signed;
406
int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
408
return ToStringInteger (aValue, aExtra, sign, bits);
411
throw xml::ENotImplemented (RT_SRC_POS);
415
* Specialization of ToString for bool.
417
* Converts true to "true" and false to "false". @a aExtra is not used.
419
template<> DECLEXPORT (stdx::char_auto_ptr)
420
ToString <bool> (const bool &aValue, unsigned int aExtra);
423
* Specialization of ToString for RTTIMESPEC.
425
* Converts the RTTIMESPEC value to the date string in ISO format
426
* (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone]). Currently, the timezone will
429
* @a aExtra is not used.
431
template<> DECLEXPORT (stdx::char_auto_ptr)
432
ToString <RTTIMESPEC> (const RTTIMESPEC &aValue, unsigned int aExtra);
435
* Converts memory bytes to a null-terminated string of hex values.
437
* @param aData Pointer to the memory block.
438
* @param aLen Length of the memory block.
440
* @return Result of conversion.
442
DECLEXPORT (stdx::char_auto_ptr) ToString (const void *aData, size_t aLen);
444
#if defined VBOX_MAIN_SETTINGS_ADDONS
446
/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
451
/** Specialization of FromString for Bstr. */
452
template<> com::Bstr FromString <com::Bstr> (const char *aValue);
456
/** Specialization of ToString for Bstr. */
457
template<> stdx::char_auto_ptr
458
ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
460
/** Specialization of FromString for Guid. */
461
template<> com::Guid FromString <com::Guid> (const char *aValue);
463
/** Specialization of ToString for Guid. */
464
template<> stdx::char_auto_ptr
465
ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
467
#endif // VBOX_MAIN_SETTINGS_ADDONS
470
//////////////////////////////////////////////////////////////////////////////
473
* The Key class represents a settings key.
475
* Every settings key has a name and zero or more uniquely named values
476
* (attributes). There is a special attribute with a NULL name that is called
479
* Besides values, settings keys may contain other settings keys. This way,
480
* settings keys form a tree-like (or a directory-like) hierarchy of keys. Key
481
* names do not need to be unique even if they belong to the same parent key
482
* which allows to have an array of keys of the same name.
484
* @note Key and Value objects returned by methods of the Key and TreeBackend
485
* classes are owned by the given TreeBackend instance and may refer to data
486
* that becomes invalid when this TreeBackend instance is destroyed.
488
class VBOXXML_CLASS Key
492
typedef std::list <Key> List;
495
* Key backend interface used to perform actual key operations.
497
* This interface is implemented by backends that provide specific ways of
498
* storing settings keys.
500
class VBOXXML_CLASS Backend : public stdx::auto_ref
504
/** Performs the Key::name() function. */
505
virtual const char *name() const = 0;
507
/** Performs the Key::setName() function. */
508
virtual void setName (const char *aName) = 0;
510
/** Performs the Key::stringValue() function. */
511
virtual const char *value (const char *aName) const = 0;
513
/** Performs the Key::setStringValue() function. */
514
virtual void setValue (const char *aName, const char *aValue) = 0;
516
/** Performs the Key::keys() function. */
517
virtual List keys (const char *aName = NULL) const = 0;
519
/** Performs the Key::findKey() function. */
520
virtual Key findKey (const char *aName) const = 0;
522
/** Performs the Key::appendKey() function. */
523
virtual Key appendKey (const char *aName) = 0;
525
/** Performs the Key::zap() function. */
526
virtual void zap() = 0;
529
* Returns an opaque value that uniquely represents the position of
530
* this key on the tree which is used to compare two keys. Two or more
531
* keys may return the same value only if they actually represent the
532
* same key (i.e. they have the same list of parents and children).
534
virtual void *position() const = 0;
538
* Creates a new key object. If @a aBackend is @c NULL then a null key is
541
* Regular API users should never need to call this method with something
542
* other than NULL argument (which is the default).
544
* @param aBackend Key backend to use.
546
Key (Backend *aBackend = NULL) : m (aBackend) {}
549
* Returns @c true if this key is null.
551
bool isNull() const { return m.is_null(); }
554
* Makes this object a null key.
556
* Note that as opposed to #zap(), this methid does not delete the key from
557
* the list of children of its parent key.
559
void setNull() { m = NULL; }
562
* Returns the name of this key.
563
* Returns NULL if this object a null (uninitialized) key.
565
const char *name() const { return m.is_null() ? NULL : m->name(); }
568
* Sets the name of this key.
570
* @param aName New key name.
572
void setName (const char *aName) { if (!m.is_null()) m->setName (aName); }
575
* Returns the value of the attribute with the given name as an UTF-8
576
* string. Returns @c NULL if there is no attribute with the given name.
578
* @param aName Name of the attribute. NULL may be used to
581
const char *stringValue (const char *aName) const
583
return m.is_null() ? NULL : m->value (aName);
587
* Sets the value of the attribute with the given name from an UTF-8
588
* string. This method will do a copy of the supplied @a aValue string.
590
* @param aName Name of the attribute. NULL may be used to
592
* @param aValue New value of the attribute. NULL may be used to
593
* delete the value instead of setting it.
595
void setStringValue (const char *aName, const char *aValue)
597
if (!m.is_null()) m->setValue (aName, aValue);
601
* Returns the value of the attribute with the given name as an object of
602
* type @a T. Throws ENoValue if there is no attribute with the given
605
* This function calls #stringValue() to get the string representation of
606
* the attribute and then calls the FromString() template to convert this
607
* string to a value of the given type.
609
* @param aName Name of the attribute. NULL may be used to
612
template <typename T>
613
T value (const char *aName) const
617
return FromString <T> (stringValue (aName));
619
catch (const ENoValue &)
621
throw ENoValue(com::Utf8StrFmt("No such attribute '%s'", aName));
626
* Returns the value of the attribute with the given name as an object of
627
* type @a T. Returns the given default value if there is no attribute
628
* with the given name.
630
* This function calls #stringValue() to get the string representation of
631
* the attribute and then calls the FromString() template to convert this
632
* string to a value of the given type.
634
* @param aName Name of the attribute. NULL may be used to
636
* @param aDefault Default value to return for the missing attribute.
638
template <typename T>
639
T valueOr (const char *aName, const T &aDefault) const
643
return FromString <T> (stringValue (aName));
645
catch (const ENoValue &)
652
* Sets the value of the attribute with the given name from an object of
653
* type @a T. This method will do a copy of data represented by @a aValue
656
* This function converts the given value to a string using the ToString()
657
* template and then calls #setStringValue().
659
* @param aName Name of the attribute. NULL may be used to
661
* @param aValue New value of the attribute.
662
* @param aExtra Extra field used by some types to specify additional
663
* details for storing the value as a string (such as the
664
* base for decimal numbers).
666
template <typename T>
667
void setValue (const char *aName, const T &aValue, unsigned int aExtra = 0)
671
stdx::char_auto_ptr value = ToString (aValue, aExtra);
672
setStringValue (aName, value.get());
674
catch (const ENoValue &)
676
throw ENoValue(com::Utf8StrFmt("No value for attribute '%s'", aName));
681
* Sets the value of the attribute with the given name from an object of
682
* type @a T. If the value of the @a aValue object equals to the value of
683
* the given @a aDefault object, then the attribute with the given name
684
* will be deleted instead of setting its value to @a aValue.
686
* This function converts the given value to a string using the ToString()
687
* template and then calls #setStringValue().
689
* @param aName Name of the attribute. NULL may be used to
691
* @param aValue New value of the attribute.
692
* @param aDefault Default value to compare @a aValue to.
693
* @param aExtra Extra field used by some types to specify additional
694
* details for storing the value as a string (such as the
695
* base for decimal numbers).
697
template <typename T>
698
void setValueOr (const char *aName, const T &aValue, const T &aDefault,
699
unsigned int aExtra = 0)
701
if (aValue == aDefault)
704
setValue <T> (aName, aValue, aExtra);
708
* Deletes the value of the attribute with the given name.
709
* Shortcut to <tt>setStringValue(aName, NULL)</tt>.
711
void zapValue (const char *aName) { setStringValue (aName, NULL); }
714
* Returns the key value.
715
* Shortcut to <tt>stringValue (NULL)</tt>.
717
const char *keyStringValue() const { return stringValue (NULL); }
720
* Sets the key value.
721
* Shortcut to <tt>setStringValue (NULL, aValue)</tt>.
723
void setKeyStringValue (const char *aValue) { setStringValue (NULL, aValue); }
726
* Returns the key value.
727
* Shortcut to <tt>value (NULL)</tt>.
729
template <typename T>
730
T keyValue() const { return value <T> (NULL); }
733
* Returns the key value or the given default if the key value is NULL.
734
* Shortcut to <tt>value (NULL)</tt>.
736
template <typename T>
737
T keyValueOr (const T &aDefault) const { return valueOr <T> (NULL, aDefault); }
740
* Sets the key value.
741
* Shortcut to <tt>setValue (NULL, aValue, aExtra)</tt>.
743
template <typename T>
744
void setKeyValue (const T &aValue, unsigned int aExtra = 0)
746
setValue <T> (NULL, aValue, aExtra);
750
* Sets the key value.
751
* Shortcut to <tt>setValueOr (NULL, aValue, aDefault)</tt>.
753
template <typename T>
754
void setKeyValueOr (const T &aValue, const T &aDefault,
755
unsigned int aExtra = 0)
757
setValueOr <T> (NULL, aValue, aDefault, aExtra);
761
* Deletes the key value.
762
* Shortcut to <tt>zapValue (NULL)</tt>.
764
void zapKeyValue () { zapValue (NULL); }
767
* Returns a list of all child keys named @a aName.
769
* If @a aname is @c NULL, returns a list of all child keys.
771
* @param aName Child key name to list.
773
List keys (const char *aName = NULL) const
775
return m.is_null() ? List() : m->keys (aName);
779
* Returns the first child key with the given name.
781
* Throws ENoKey if no child key with the given name exists.
783
* @param aName Child key name.
785
Key key (const char *aName) const
787
Key key = findKey (aName);
790
throw ENoKey(com::Utf8StrFmt("No such key '%s'", aName));
796
* Returns the first child key with the given name.
798
* As opposed to #key(), this method will not throw an exception if no
799
* child key with the given name exists, but return a null key instead.
801
* @param aName Child key name.
803
Key findKey (const char *aName) const
805
return m.is_null() ? Key() : m->findKey (aName);
809
* Creates a key with the given name as a child of this key and returns it
812
* If one or more child keys with the given name already exist, no new key
813
* is created but the first matching child key is returned.
815
* @param aName Name of the child key to create.
817
Key createKey (const char *aName)
819
Key key = findKey (aName);
821
key = appendKey (aName);
826
* Appends a key with the given name to the list of child keys of this key
827
* and returns the appended key to the caller.
829
* @param aName Name of the child key to create.
831
Key appendKey (const char *aName)
833
return m.is_null() ? Key() : m->appendKey (aName);
839
* The deleted key is removed from the list of child keys of its parent
840
* key and becomes a null object.
852
* Compares this object with the given object and returns @c true if both
853
* represent the same key on the settings tree or if both are null
856
* @param that Object to compare this object with.
858
bool operator== (const Key &that) const
860
return m == that.m ||
861
(!m.is_null() && !that.m.is_null() &&
862
m->position() == that.m->position());
866
* Counterpart to operator==().
868
bool operator!= (const Key &that) const { return !operator== (that); }
872
stdx::auto_ref_ptr <Backend> m;
874
friend class TreeBackend;
878
* The TreeBackend class represents a storage backend used to read a settings
879
* tree from and write it to a stream.
881
* @note All Key objects returned by any of the TreeBackend methods (and by
882
* methods of returned Key objects) are owned by the given TreeBackend
883
* instance. When this instance is destroyed, all Key objects become invalid
884
* and an attempt to access Key data will cause the program crash.
886
class VBOXXML_CLASS TreeBackend
891
* Reads and parses the given input stream.
893
* On success, the previous settings tree owned by this backend (if any)
896
* The optional schema URI argument determines the name of the schema to
897
* use for input validation. If the schema URI is NULL then the validation
898
* is not performed. Note that you may set a custom input resolver if you
899
* want to provide the input stream for the schema file (and for other
900
* external entities) instead of letting the backend to read the specified
903
* This method will set the read/write position to the beginning of the
904
* given stream before reading. After the stream has been successfully
905
* parsed, the position will be set back to the beginning.
907
* @param aInput Input stream.
908
* @param aSchema Schema URI to use for input stream validation.
909
* @param aFlags Optional bit flags.
911
void read (xml::Input &aInput, const char *aSchema = NULL, int aFlags = 0)
914
rawRead (aInput, aSchema, aFlags);
919
* Reads and parses the given input stream in a raw fashion.
921
* This method doesn't set the stream position to the beginnign before and
922
* after reading but instead leaves it as is in both cases. It's the
923
* caller's responsibility to maintain the correct position.
927
virtual void rawRead (xml::Input &aInput, const char *aSchema = NULL,
931
* Writes the current settings tree to the given output stream.
933
* This method will set the read/write position to the beginning of the
934
* given stream before writing. After the settings have been successfully
935
* written to the stream, the stream will be truncated at the position
936
* following the last byte written by this method anc ghd position will be
937
* set back to the beginning.
939
* @param aOutput Output stream.
941
void write (xml::Output &aOutput)
950
* Writes the current settings tree to the given output stream in a raw
953
* This method doesn't set the stream position to the beginnign before and
954
* after reading and doesn't truncate the stream, but instead leaves it as
955
* is in both cases. It's the caller's responsibility to maintain the
956
* correct position and perform truncation.
960
virtual void rawWrite (xml::Output &aOutput) = 0;
963
* Deletes the current settings tree.
965
virtual void reset() = 0;
968
* Returns the root settings key.
970
virtual Key &rootKey() const = 0;
61
class ConfigFileError;
63
////////////////////////////////////////////////////////////////////////////////
67
////////////////////////////////////////////////////////////////////////////////
69
// ExtraDataItem (used by both VirtualBox.xml and machines XML)
70
typedef std::map<com::Utf8Str, com::Utf8Str> ExtraDataItemsMap;
71
struct USBDeviceFilter;
72
typedef std::list<USBDeviceFilter> USBDeviceFiltersList;
75
* Common base class for both MainConfigFile and MachineConfigFile
76
* which contains some common logic for both.
974
static Key::Backend *GetKeyBackend (const Key &aKey) { return aKey.m.raw(); }
980
* The XmlTreeBackend class uses XML markup to store settings trees.
982
* @note libxml2 and libxslt libraries used by the XmlTreeBackend are not
983
* fully reentrant. To "fix" this, the XmlTreeBackend backend serializes access
984
* to such non-reentrant parts using a global mutex so that only one thread can
985
* use non-reentrant code at a time. Currently, this relates to the #rawRead()
986
* method (and to #read() as a consequence). This means that only one thread can
987
* parse an XML stream at a time; other threads trying to parse same or
988
* different streams using different XmlTreeBackend and Input instances
991
* Keep in mind that the above reentrancy fix does not imply thread-safety: it
992
* is still the caller's responsibility to provide serialization if the same
993
* XmlTreeBackend instnace (as well as instances of other classes from the
994
* settings namespace) needs to be used by more than one thread.
996
class VBOXXML_CLASS XmlTreeBackend : public TreeBackend
1000
/** Flags for TreeBackend::read(). */
1004
* Sbstitute default values for missing attributes that have defaults
1005
* in the XML schema. Otherwise, stringValue() will return NULL for
1008
Read_AddDefaults = RT_BIT (0),
1012
* The EConversionCycle class represents a conversion cycle detected by the
1013
* AutoConverter::needsConversion() implementation.
1015
class VBOXXML_CLASS EConversionCycle : public xml::RuntimeError
1019
EConversionCycle (const char *aMsg = NULL) : RuntimeError (aMsg) {}
1023
* The InputResolver class represents an interface to provide input streams
1024
* for external entities given an URL and entity ID.
1026
class VBOXXML_CLASS InputResolver
1031
* Returns a newly allocated input stream for the given arguments. The
1032
* caller will delete the returned object when no more necessary.
1034
* @param aURI URI of the external entity.
1035
* @param aID ID of the external entity (may be NULL).
1037
* @return Input stream created using @c new or NULL to indicate
1038
* a wrong URI/ID pair.
1040
* @todo Return by value after implementing the copy semantics for
1043
virtual xml::Input *resolveEntity (const char *aURI, const char *aID) = 0;
1047
* The AutoConverter class represents an interface to automatically convert
1048
* old settings trees to a new version when the tree is read from the
1051
class VBOXXML_CLASS AutoConverter
1056
* Returns @true if the given tree needs to be converted using the XSLT
1057
* template identified by #templateUri(), or @false if no conversion is
1060
* The implementation normally checks for the "version" value of the
1061
* root key to determine if the conversion is necessary. When the
1062
* @a aOldVersion argument is not NULL, the implementation must return a
1063
* non-NULL non-empty string representing the old version (before
1064
* conversion) in it this string is used by XmlTreeBackend::oldVersion()
1065
* and must be non-NULL to indicate that the conversion has been
1066
* performed on the tree. The returned string must be allocated using
1067
* RTStrDup() or such.
1069
* This method is called again after the successful transformation to
1070
* let the implementation retry the version check and request another
1071
* transformation if necessary. This may be used to perform multi-step
1072
* conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3)
1073
* which saves from the need to update all previous conversion
1074
* templates to make each of them convert directly to the recent
1077
* @note Multi-step transformations are performed in a loop that exits
1078
* only when this method returns @false. It's up to the
1079
* implementation to detect cycling (repeated requests to convert
1080
* from the same version) wrong version order, etc. and throw an
1081
* EConversionCycle exception to break the loop without returning
1082
* @false (which means the transformation succeeded).
1084
* @param aRoot Root settings key.
1085
* @param aOldVersionString Where to store old version string
1086
* pointer. May be NULL. Allocated memory is
1087
* freed by the caller using RTStrFree().
1089
virtual bool needsConversion (const Key &aRoot,
1090
char **aOldVersion) const = 0;
1093
* Returns the URI of the XSLT template to perform the conversion.
1094
* This template will be applied to the tree if #needsConversion()
1095
* returns @c true for this tree.
1097
virtual const char *templateUri() const = 0;
1104
* Sets an external entity resolver used to provide input streams for
1105
* entities referred to by the XML document being parsed.
1107
* The given resolver object must exist as long as this instance exists or
1108
* until a different resolver is set using setInputResolver() or reset
1109
* using resetInputResolver().
1111
* @param aResolver Resolver to use.
1113
void setInputResolver (InputResolver &aResolver);
1116
* Resets the entity resolver to the default resolver. The default
1117
* resolver provides support for 'file:' and 'http:' protocols.
1119
void resetInputResolver();
1122
* Sets a settings tree converter and enables the automatic conversion.
1124
* The Automatic settings tree conversion is useful for upgrading old
1125
* settings files to the new version transparently during execution of the
1128
* The automatic conversion takes place after reading the document from the
1129
* stream but before validating it. The given converter is asked if the
1130
* conversion is necessary using the AutoConverter::needsConversion() call,
1131
* and if so, the XSLT template specified by AutoConverter::templateUri() is
1132
* applied to the settings tree.
1134
* Note that in order to make the result of the conversion permanent, the
1135
* settings tree needs to be exlicitly written back to the stream.
1137
* The given converter object must exist as long as this instance exists or
1138
* until a different converter is set using setAutoConverter() or reset
1139
* using resetAutoConverter().
1141
* @param aConverter Settings converter to use.
1143
void setAutoConverter (AutoConverter &aConverter);
1146
* Disables the automatic settings conversion previously enabled by
1147
* setAutoConverter(). By default automatic conversion it is disabled.
1149
void resetAutoConverter();
1152
* Returns a non-NULL string if the automatic settings conversion has been
1153
* performed during the last successful #read() call. Returns @c NULL if
1154
* there was no settings conversion.
1156
* If #read() fails, this method will return the version string set by the
1157
* previous successful #read() call or @c NULL if there were no #read()
1160
const char *oldVersion() const;
1162
void rawRead (xml::Input &aInput, const char *aSchema = NULL, int aFlags = 0);
1163
void rawWrite (xml::Output &aOutput);
1165
Key &rootKey() const;
1169
/* Obscure class data */
84
ConfigFileBase(const com::Utf8Str *pstrFilename);
87
void parseUUID(com::Guid &guid,
88
const com::Utf8Str &strUUID) const;
89
void parseTimestamp(RTTIMESPEC ×tamp,
90
const com::Utf8Str &str) const;
92
com::Utf8Str makeString(const RTTIMESPEC &tm);
93
com::Utf8Str makeString(const com::Guid &guid);
95
void readExtraData(const xml::ElementNode &elmExtraData,
96
ExtraDataItemsMap &map);
97
void readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters,
98
USBDeviceFiltersList &ll);
100
void createStubDocument();
102
void writeExtraData(xml::ElementNode &elmParent, const ExtraDataItemsMap &me);
103
void writeUSBDeviceFilters(xml::ElementNode &elmParent,
104
const USBDeviceFiltersList &ll,
107
void clearDocument();
1171
std::auto_ptr <Data> m;
1173
/* auto_ptr data doesn't have proper copy semantics */
1174
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (XmlTreeBackend)
1176
static int ReadCallback (void *aCtxt, char *aBuf, int aLen);
1177
static int WriteCallback (void *aCtxt, const char *aBuf, int aLen);
1178
static int CloseCallback (void *aCtxt);
1180
static void ValidityErrorCallback (void *aCtxt, const char *aMsg, ...);
1181
static void ValidityWarningCallback (void *aCtxt, const char *aMsg, ...);
1182
static void StructuredErrorCallback (void *aCtxt, xmlErrorPtr aErr);
1184
static xmlParserInput *ExternalEntityLoader (const char *aURI,
1186
xmlParserCtxt *aCtxt);
1188
static XmlTreeBackend *sThat;
1190
static XmlKeyBackend *GetKeyBackend (const Key &aKey)
1191
{ return (XmlKeyBackend *) TreeBackend::GetKeyBackend (aKey); }
1194
} /* namespace settings */
112
friend class ConfigFileError;
115
////////////////////////////////////////////////////////////////////////////////
117
// VirtualBox.xml structures
119
////////////////////////////////////////////////////////////////////////////////
121
struct USBDeviceFilter
125
action(USBDeviceFilterAction_Null),
126
ulMaskedInterfaces(0)
129
com::Utf8Str strName;
131
com::Utf8Str strVendorId,
138
USBDeviceFilterAction_T action; // only used with host USB filters
139
com::Utf8Str strRemote; // irrelevant for host USB objects
140
uint32_t ulMaskedInterfaces; // irrelevant for host USB objects
145
USBDeviceFiltersList llUSBDeviceFilters;
148
struct SystemProperties
151
: ulLogHistoryCount(3)
154
com::Utf8Str strDefaultMachineFolder;
155
com::Utf8Str strDefaultHardDiskFolder;
156
com::Utf8Str strDefaultHardDiskFormat;
157
com::Utf8Str strRemoteDisplayAuthLibrary;
158
com::Utf8Str strWebServiceAuthLibrary;
159
uint32_t ulLogHistoryCount;
162
typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap;
165
typedef std::list<Medium> MediaList;
170
com::Utf8Str strLocation;
171
com::Utf8Str strDescription;
173
// the following are for hard disks only:
174
com::Utf8Str strFormat;
175
bool fAutoReset; // optional, only for diffs, default is false
176
PropertiesMap properties;
179
MediaList llChildren; // only used with hard disks
182
struct MachineRegistryEntry
185
com::Utf8Str strSettingsFile;
187
typedef std::list<MachineRegistryEntry> MachinesRegistry;
191
com::Utf8Str strNetworkName,
198
typedef std::list<DHCPServer> DHCPServersList;
200
class MainConfigFile : public ConfigFileBase
203
MainConfigFile(const com::Utf8Str *pstrFilename);
205
typedef enum {Error, HardDisk, DVDImage, FloppyImage} MediaType;
206
void readMedium(MediaType t, const xml::ElementNode &elmMedium, MediaList &llMedia);
207
void readMediaRegistry(const xml::ElementNode &elmMediaRegistry);
208
void readMachineRegistry(const xml::ElementNode &elmMachineRegistry);
209
void readDHCPServers(const xml::ElementNode &elmDHCPServers);
211
void writeHardDisk(xml::ElementNode &elmMedium,
214
void write(const com::Utf8Str strFilename);
217
SystemProperties systemProperties;
218
MediaList llHardDisks,
221
MachinesRegistry llMachines;
222
DHCPServersList llDhcpServers;
223
ExtraDataItemsMap mapExtraDataItems;
226
////////////////////////////////////////////////////////////////////////////////
228
// Machine XML structures
230
////////////////////////////////////////////////////////////////////////////////
236
authType(VRDPAuthType_Null),
238
fAllowMultiConnection(false),
239
fReuseSingleConnection(false)
243
com::Utf8Str strPort;
244
com::Utf8Str strNetAddress;
245
VRDPAuthType_T authType;
246
uint32_t ulAuthTimeout;
247
bool fAllowMultiConnection,
248
fReuseSingleConnection;
254
: fACPIEnabled(true),
255
fIOAPICEnabled(false),
258
ulLogoDisplayTime(0),
259
biosBootMenuMode(BIOSBootMenuMode_MessageAndMenu),
260
fPXEDebugEnabled(false),
268
uint32_t ulLogoDisplayTime;
269
com::Utf8Str strLogoImagePath;
270
BIOSBootMenuMode_T biosBootMenuMode;
271
bool fPXEDebugEnabled;
272
int64_t llTimeOffset;
284
USBDeviceFiltersList llDeviceFilters;
287
struct NetworkAdapter
291
type(NetworkAdapterType_Am79C970A),
293
fCableConnected(false),
295
fTraceEnabled(false),
296
mode(NetworkAttachmentType_Null)
301
NetworkAdapterType_T type;
303
com::Utf8Str strMACAddress;
304
bool fCableConnected;
305
uint32_t ulLineSpeed;
307
com::Utf8Str strTraceFile;
309
NetworkAttachmentType_T mode;
310
com::Utf8Str strName; // with NAT: nat network or empty;
311
// with bridged: host interface or empty;
312
// otherwise: network name (required)
314
typedef std::list<NetworkAdapter> NetworkAdaptersList;
322
portMode(PortMode_Disconnected),
332
com::Utf8Str strPath;
335
typedef std::list<SerialPort> SerialPortsList;
350
com::Utf8Str strPath;
352
typedef std::list<ParallelPort> ParallelPortsList;
358
controllerType(AudioControllerType_AC97),
359
driverType(AudioDriverType_Null)
363
AudioControllerType_T controllerType;
364
AudioDriverType_T driverType;
373
com::Utf8Str strName,
377
typedef std::list<SharedFolder> SharedFoldersList;
385
com::Utf8Str strName,
388
com::Utf8Str strFlags;
390
typedef std::list<GuestProperty> GuestPropertiesList;
392
typedef std::map<uint32_t, DeviceType_T> BootOrderMap;
410
typedef std::list<CpuIdLeaf> CpuIdLeafsList;
416
com::Utf8Str strVersion; // hardware version, optional
417
com::Guid uuid; // hardware uuid, optional (null).
420
fHardwareVirtExclusive,
426
CpuIdLeafsList llCpuIdLeafs;
428
uint32_t ulMemorySizeMB;
430
BootOrderMap mapBootOrder; // item 0 has highest priority
432
uint32_t ulVRAMSizeMB;
435
fAccelerate2DVideo; // requires settings version 1.8 (VirtualBox 3.1)
436
FirmwareType_T firmwareType; // requires settings version 1.9 (VirtualBox 3.1)
438
VRDPSettings vrdpSettings;
440
BIOSSettings biosSettings;
441
USBController usbController;
442
NetworkAdaptersList llNetworkAdapters;
443
SerialPortsList llSerialPorts;
444
ParallelPortsList llParallelPorts;
445
AudioAdapter audioAdapter;
447
// technically these two have no business in the hardware section, but for some
448
// clever reason <Hardware> is where they are in the XML....
449
SharedFoldersList llSharedFolders;
450
ClipboardMode_T clipboardMode;
452
uint32_t ulMemoryBalloonSize;
453
uint32_t ulStatisticsUpdateInterval;
455
GuestPropertiesList llGuestProperties;
456
com::Utf8Str strNotificationPatterns;
460
* A device attached to a storage controller. This can either be a
461
* hard disk or a DVD drive or a floppy drive and also specifies
462
* which medium is "in" the drive; as a result, this is a combination
463
* of the Main IMedium and IMediumAttachment interfaces.
1211
xmlParserCtxtPtr m_ctxt;
1214
class VBoxXmlFile : public VBoxXmlBase
465
struct AttachedDevice
468
: deviceType(DeviceType_Null),
474
DeviceType_T deviceType; // only HardDisk, DVD or Floppy are allowed
476
// DVDs can be in pass-through mode:
482
// if an image file is attached to the device (ISO, RAW, or hard disk image such as VDI),
483
// this is its UUID; it depends on deviceType which media registry this then needs to
484
// be looked up in. If no image file (only permitted for DVDs and floppies), then the UUID is NULL
487
// for DVDs and floppies, the attachment can also be a host device:
488
com::Utf8Str strHostDriveSrc; // if != NULL, value of <HostDrive>/@src
490
typedef std::list<AttachedDevice> AttachedDevicesList;
492
struct StorageController
495
: storageBus(StorageBus_IDE),
496
controllerType(StorageControllerType_PIIX3),
499
lIDE0MasterEmulationPort(0),
500
lIDE0SlaveEmulationPort(0),
501
lIDE1MasterEmulationPort(0),
502
lIDE1SlaveEmulationPort(0)
505
com::Utf8Str strName;
506
StorageBus_T storageBus; // _SATA, _SCSI, _IDE
507
StorageControllerType_T controllerType;
508
uint32_t ulPortCount;
511
// only for when controllerType == StorageControllerType_IntelAhci:
512
int32_t lIDE0MasterEmulationPort,
513
lIDE0SlaveEmulationPort,
514
lIDE1MasterEmulationPort,
515
lIDE1SlaveEmulationPort;
517
AttachedDevicesList llAttachedDevices;
519
typedef std::list<StorageController> StorageControllersList;
521
// wrap the list into an extra struct so we can use the struct without
522
// having to define the typedef above in headers
525
StorageControllersList llStorageControllers;
529
typedef std::list<Snapshot> SnapshotsList;
534
com::Utf8Str strName,
535
strDescription; // optional
536
RTTIMESPEC timestamp;
538
com::Utf8Str strStateFile; // for online snapshots only
543
SnapshotsList llChildSnapshots;
547
class MachineConfigFile : public ConfigFileBase
550
MachineConfigFile(const com::Utf8Str *pstrFilename);
552
void readNetworkAdapters(const xml::ElementNode &elmHardware, NetworkAdaptersList &ll);
553
void readCpuIdTree(const xml::ElementNode &elmCpuid, CpuIdLeafsList &ll);
554
void readSerialPorts(const xml::ElementNode &elmUART, SerialPortsList &ll);
555
void readParallelPorts(const xml::ElementNode &elmLPT, ParallelPortsList &ll);
556
void readGuestProperties(const xml::ElementNode &elmGuestProperties, Hardware &hw);
557
void readStorageControllerAttributes(const xml::ElementNode &elmStorageController, StorageController &sctl);
558
void readHardware(const xml::ElementNode &elmHardware, Hardware &hw, Storage &strg);
559
void readHardDiskAttachments_pre1_7(const xml::ElementNode &elmHardDiskAttachments, Storage &strg);
560
void readStorageControllers(const xml::ElementNode &elmStorageControllers, Storage &strg);
561
void readDVDAndFloppies_pre1_9(const xml::ElementNode &elmHardware, Storage &strg);
562
void readSnapshot(const xml::ElementNode &elmSnapshot, Snapshot &snap);
563
void convertOldOSType_pre1_5(com::Utf8Str &str);
564
void readMachine(const xml::ElementNode &elmMachine);
566
void writeHardware(xml::ElementNode &elmParent, const Hardware &hw, const Storage &strg);
567
void writeStorageControllers(xml::ElementNode &elmParent, const Storage &st);
568
void writeSnapshot(xml::ElementNode &elmParent, const Snapshot &snap);
569
void bumpSettingsVersionIfNeeded();
570
void write(const com::Utf8Str &strFilename);
573
com::Utf8Str strName;
575
com::Utf8Str strDescription;
576
com::Utf8Str strOsType;
577
com::Utf8Str strStateFile;
578
com::Guid uuidCurrentSnapshot;
579
com::Utf8Str strSnapshotFolder;
580
bool fTeleporterEnabled;
581
uint32_t uTeleporterPort;
582
com::Utf8Str strTeleporterAddress;
583
com::Utf8Str strTeleporterPassword;
585
bool fCurrentStateModified; // optional, default is true
586
RTTIMESPEC timeLastStateChange; // optional, defaults to now
587
bool fAborted; // optional, default is false
589
Hardware hardwareMachine;
590
Storage storageMachine;
592
ExtraDataItemsMap mapExtraDataItems;
594
SnapshotsList llFirstSnapshot; // first snapshot or empty list if there's none
1223
#if defined(_MSC_VER)
1224
#pragma warning (default:4251)
597
} // namespace settings
1229
600
#endif /* ___VBox_settings_h */