settings.h revision 62ce496afaf36bcde8d08da57a9444739d67f426
* and create new key values. Below is an example that uses the XML backend to * load the settings tree, then modifies it and then saves the modifications. using namespace settings; // load the tree, parse it and validate using the XML schema tree.read (aFile, "myfile.xsd", XmlTreeBackend::Read_AddDefaults); printf ("root=%s\n", root.name()); // enumerate all child keys of the root key named Foo Key::list children = root.keys ("Foo"); for (Key::list::const_iterator it = children.begin(); // get the "level" attribute int level = (*it).value <int> ("level"); // if so, create a "Bar" key if it doesn't exist yet Key bar = (*it).createKey ("Bar"); // set the "date" attribute bar.setValue <RTTIMESPEC> ("date", now); // if its below 2, delete the whole "Foo" key // save the tree on success (the second try is to distinguish between // stream load and save errors) catch (const EIPRTFailure &err) // this is an expected exception that may happen in case of stream printf ("Could not save the settings file '%s' (%Rrc)"); catch (const EIPRTFailure &err) // this is an expected exception that may happen in case of stream printf ("Could not load the settings file '%s' (%Rrc)"); catch (const XmlTreeBackend::Error &err) // this is an XmlTreeBackend specific exception that may // happen in case of XML parse or validation errors printf ("Could not load the settings file '%s'.\n%s"), file.uri(), err.what() ? err.what() : "Unknown error"); catch (const std::exception &err) // the rest is unexpected (e.g. should not happen unless you // specifically wish so for some reason and therefore allow for a // situation that may throw one of these from within the try block AssertMsgFailed ("Unexpected exception '%s' (%s)\n", typeid (err).name(), err.what()); // this is even more unexpected, and no any useful info here AssertMsgFailed ("Unexpected exception\n"); * Note that you can get a raw (string) value of the attribute using the * Key::stringValue() method but often it's simpler and better to use the * templated Key::value<>() method that can convert the string to a value of * the given type for you (and throw exceptions when the converison is not * possible). Similarly, the Key::setStringValue() method is used to set a raw * string value and there is a templated Key::setValue<>() method to set a * typed value which will implicitly convert it to a string. * Currently, types supported by Key::value<>() and Key::setValue<>() include * all C and IPRT integer types, bool and RTTIMESPEC (represented as isoDate * in XML). You can always add support for your own types by creating * additional specializations of the FromString<>() and ToString<>() templates * in the settings namespace (see the real examples in this header). * See individual funciton, class and method descriptions to get more details * on the Settings File Manipulation API. * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a * result of private data member declarations of some classes below) need to * be exported too to in order to be accessible by clients. * The alternative is to instantiate a template before the data member * declaration with the VBOXXML_CLASS prefix, but the standard disables * explicit instantiations in a foreign namespace. In other words, a declaration * template class VBOXXML_CLASS std::auto_ptr <Data>; * right before the member declaration makes MSVC happy too, but this is not a * valid C++ construct (and G++ spits it out). So, for now we just disable the * warning and will come back to this problem one day later. * We also disable another warning (4275) saying that a DLL-exported class * inherits form a non-DLL-exported one (e.g. settings::ENoMemory -> * std::bad_alloc). I can't get how it can harm yet. * Settings File Manipulation API namespace. // Exceptions (on top of vboxxml exceptions) ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // string -> type conversions ////////////////////////////////////////////////////////////////////////////// * Helper for the FromString() template, doesn't need to be called directly. * Generic template function to perform a conversion of an UTF-8 string to an * arbitrary value of type @a T. * This generic template is implenented only for 8-, 16-, 32- and 64- bit * signed and unsigned integers where it uses RTStrTo[U]Int64() to perform the * conversion. For all other types it throws an ENotImplemented * exception. Individual template specializations for known types should do * If the conversion is not possible (for example the string format is wrong * or meaningless for the given type), this template will throw an * ENoConversion exception. All specializations must do the same. * If the @a aValue argument is NULL, this method will throw an ENoValue * exception. All specializations must do the same. * @param aValue Value to convert. * @return Result of conversion. * Specialization of FromString for bool. * Converts "true", "yes", "on" to true and "false", "no", "off" to false. * Specialization of FromString for RTTIMESPEC. * Converts the date in ISO format (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone]) * to a RTTIMESPEC value. Currently, the timezone must always be Z (UTC). * Converts a string of hex digits to memory bytes. * @param aValue String to convert. * @param aLen Where to store the length of the returned memory * @return Result of conversion (a block of @a aLen bytes). // type -> string conversions ////////////////////////////////////////////////////////////////////////////// * Helper for the ToString() template, doesn't need to be called directly. * Generic template function to perform a conversion of an arbitrary value to * This generic template is implemented only for 8-, 16-, 32- and 64- bit * signed and unsigned integers where it uses RTStrFormatNumber() to perform * the conversion. For all other types it throws an ENotImplemented * exception. Individual template specializations for known types should do * the conversion job. If the conversion is not possible (for example the * given value doesn't have a string representation), the relevant * specialization should throw an ENoConversion exception. * If the @a aValue argument's value would convert to a NULL string, this * method will throw an ENoValue exception. All specializations must do the * @param aValue Value to convert. * @param aExtra Extra flags to define additional formatting. In case of * integer types, it's the base used for string representation. * @return Result of conversion. * Specialization of ToString for bool. * Converts true to "true" and false to "false". @a aExtra is not used. * Specialization of ToString for RTTIMESPEC. * Converts the RTTIMESPEC value to the date string in ISO format * (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone]). Currently, the timezone will * Converts memory bytes to a null-terminated string of hex values. * @param aData Pointer to the memory block. * @param aLen Length of the memory block. * @return Result of conversion. ////////////////////////////////////////////////////////////////////////////// * The Key class represents a settings key. * Every settings key has a name and zero or more uniquely named values * (attributes). There is a special attribute with a NULL name that is called * Besides values, settings keys may contain other settings keys. This way, * settings keys form a tree-like (or a directory-like) hierarchy of keys. Key * names do not need to be unique even if they belong to the same parent key * which allows to have an array of keys of the same name. * @note Key and Value objects returned by methods of the Key and TreeBackend * classes are owned by the given TreeBackend instance and may refer to data * that becomes invalid when this TreeBackend instance is destroyed. * Key backend interface used to perform actual key operations. * This interface is implemented by backends that provide specific ways of /** Performs the Key::name() function. */ /** Performs the Key::setName() function. */ /** Performs the Key::stringValue() function. */ /** Performs the Key::setStringValue() function. */ /** Performs the Key::keys() function. */ /** Performs the Key::findKey() function. */ /** Performs the Key::appendKey() function. */ /** Performs the Key::zap() function. */ * Returns an opaque value that uniquely represents the position of * this key on the tree which is used to compare two keys. Two or more * keys may return the same value only if they actually represent the * same key (i.e. they have the same list of parents and children). * Creates a new key object. If @a aBackend is @c NULL then a null key is * Regular API users should never need to call this method with something * other than NULL argument (which is the default). * @param aBackend Key backend to use. * Returns @c true if this key is null. * Makes this object a null key. * Note that as opposed to #zap(), this methid does not delete the key from * the list of children of its parent key. * Returns the name of this key. * Returns NULL if this object a null (uninitialized) key. * Sets the name of this key. * @param aName New key name. * Returns the value of the attribute with the given name as an UTF-8 * string. Returns @c NULL if there is no attribute with the given name. * @param aName Name of the attribute. NULL may be used to * Sets the value of the attribute with the given name from an UTF-8 * string. This method will do a copy of the supplied @a aValue string. * @param aName Name of the attribute. NULL may be used to * @param aValue New value of the attribute. NULL may be used to * delete the value instead of setting it. * Returns the value of the attribute with the given name as an object of * type @a T. Throws ENoValue if there is no attribute with the given * This function calls #stringValue() to get the string representation of * the attribute and then calls the FromString() template to convert this * string to a value of the given type. * @param aName Name of the attribute. NULL may be used to * Returns the value of the attribute with the given name as an object of * type @a T. Returns the given default value if there is no attribute * This function calls #stringValue() to get the string representation of * the attribute and then calls the FromString() template to convert this * string to a value of the given type. * @param aName Name of the attribute. NULL may be used to * @param aDefault Default value to return for the missing attribute. * Sets the value of the attribute with the given name from an object of * type @a T. This method will do a copy of data represented by @a aValue * This function converts the given value to a string using the ToString() * template and then calls #setStringValue(). * @param aName Name of the attribute. NULL may be used to * @param aValue New value of the attribute. * @param aExtra Extra field used by some types to specify additional * details for storing the value as a string (such as the * base for decimal numbers). * Sets the value of the attribute with the given name from an object of * type @a T. If the value of the @a aValue object equals to the value of * the given @a aDefault object, then the attribute with the given name * will be deleted instead of setting its value to @a aValue. * This function converts the given value to a string using the ToString() * template and then calls #setStringValue(). * @param aName Name of the attribute. NULL may be used to * @param aValue New value of the attribute. * @param aDefault Default value to compare @a aValue to. * @param aExtra Extra field used by some types to specify additional * details for storing the value as a string (such as the * base for decimal numbers). * Deletes the value of the attribute with the given name. * Shortcut to <tt>setStringValue(aName, NULL)</tt>. * Shortcut to <tt>stringValue (NULL)</tt>. * Shortcut to <tt>setStringValue (NULL, aValue)</tt>. * Shortcut to <tt>value (NULL)</tt>. * Returns the key value or the given default if the key value is NULL. * Shortcut to <tt>value (NULL)</tt>. * Shortcut to <tt>setValue (NULL, aValue, aExtra)</tt>. * Shortcut to <tt>setValueOr (NULL, aValue, aDefault)</tt>. * Shortcut to <tt>zapValue (NULL)</tt>. * Returns a list of all child keys named @a aName. * If @a aname is @c NULL, returns a list of all child keys. * @param aName Child key name to list. * Returns the first child key with the given name. * Throws ENoKey if no child key with the given name exists. * @param aName Child key name. * Returns the first child key with the given name. * As opposed to #key(), this method will not throw an exception if no * child key with the given name exists, but return a null key instead. * @param aName Child key name. * Creates a key with the given name as a child of this key and returns it * If one or more child keys with the given name already exist, no new key * is created but the first matching child key is returned. * @param aName Name of the child key to create. * Appends a key with the given name to the list of child keys of this key * and returns the appended key to the caller. * @param aName Name of the child key to create. * The deleted key is removed from the list of child keys of its parent * key and becomes a null object. * Compares this object with the given object and returns @c true if both * represent the same key on the settings tree or if both are null * @param that Object to compare this object with. * Counterpart to operator==(). * The TreeBackend class represents a storage backend used to read a settings * tree from and write it to a stream. * @note All Key objects returned by any of the TreeBackend methods (and by * methods of returned Key objects) are owned by the given TreeBackend * instance. When this instance is destroyed, all Key objects become invalid * and an attempt to access Key data will cause the program crash. * Reads and parses the given input stream. * On success, the previous settings tree owned by this backend (if any) * The optional schema URI argument determines the name of the schema to * use for input validation. If the schema URI is NULL then the validation * is not performed. Note that you may set a custom input resolver if you * want to provide the input stream for the schema file (and for other * external entities) instead of letting the backend to read the specified * This method will set the read/write position to the beginning of the * given stream before reading. After the stream has been successfully * parsed, the position will be set back to the beginning. * @param aInput Input stream. * @param aSchema Schema URI to use for input stream validation. * @param aFlags Optional bit flags. * Reads and parses the given input stream in a raw fashion. * This method doesn't set the stream position to the beginnign before and * after reading but instead leaves it as is in both cases. It's the * caller's responsibility to maintain the correct position. * Writes the current settings tree to the given output stream. * This method will set the read/write position to the beginning of the * given stream before writing. After the settings have been successfully * written to the stream, the stream will be truncated at the position * following the last byte written by this method anc ghd position will be * set back to the beginning. * @param aOutput Output stream. * Writes the current settings tree to the given output stream in a raw * This method doesn't set the stream position to the beginnign before and * after reading and doesn't truncate the stream, but instead leaves it as * is in both cases. It's the caller's responsibility to maintain the * correct position and perform truncation. * Deletes the current settings tree. * Returns the root settings key. * The XmlTreeBackend class uses XML markup to store settings trees. * @note libxml2 and libxslt libraries used by the XmlTreeBackend are not * fully reentrant. To "fix" this, the XmlTreeBackend backend serializes access * to such non-reentrant parts using a global mutex so that only one thread can * use non-reentrant code at a time. Currently, this relates to the #rawRead() * method (and to #read() as a consequence). This means that only one thread can * parse an XML stream at a time; other threads trying to parse same or * different streams using different XmlTreeBackend and Input instances * Keep in mind that the above reentrancy fix does not imply thread-safety: it * is still the caller's responsibility to provide serialization if the same * XmlTreeBackend instnace (as well as instances of other classes from the * settings namespace) needs to be used by more than one thread. /** Flags for TreeBackend::read(). */ * Sbstitute default values for missing attributes that have defaults * in the XML schema. Otherwise, stringValue() will return NULL for * The EConversionCycle class represents a conversion cycle detected by the * AutoConverter::needsConversion() implementation. * The InputResolver class represents an interface to provide input streams * for external entities given an URL and entity ID. * Returns a newly allocated input stream for the given arguments. The * caller will delete the returned object when no more necessary. * @param aURI URI of the external entity. * @param aID ID of the external entity (may be NULL). * @return Input stream created using @c new or NULL to indicate * @todo Return by value after implementing the copy semantics for * The AutoConverter class represents an interface to automatically convert * old settings trees to a new version when the tree is read from the * Returns @true if the given tree needs to be converted using the XSLT * template identified by #templateUri(), or @false if no conversion is * The implementation normally checks for the "version" value of the * root key to determine if the conversion is necessary. When the * @a aOldVersion argument is not NULL, the implementation must return a * non-NULL non-empty string representing the old version (before * conversion) in it this string is used by XmlTreeBackend::oldVersion() * and must be non-NULL to indicate that the conversion has been * performed on the tree. The returned string must be allocated using * This method is called again after the successful transformation to * let the implementation retry the version check and request another * transformation if necessary. This may be used to perform multi-step * conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3) * which saves from the need to update all previous conversion * templates to make each of them convert directly to the recent * @note Multi-step transformations are performed in a loop that exits * only when this method returns @false. It's up to the * implementation to detect cycling (repeated requests to convert * from the same version) wrong version order, etc. and throw an * EConversionCycle exception to break the loop without returning * @false (which means the transformation succeeded). * @param aRoot Root settings key. * @param aOldVersionString Where to store old version string * pointer. May be NULL. Allocated memory is * freed by the caller using RTStrFree(). * Returns the URI of the XSLT template to perform the conversion. * This template will be applied to the tree if #needsConversion() * returns @c true for this tree. * Sets an external entity resolver used to provide input streams for * entities referred to by the XML document being parsed. * The given resolver object must exist as long as this instance exists or * until a different resolver is set using setInputResolver() or reset * using resetInputResolver(). * @param aResolver Resolver to use. * Resets the entity resolver to the default resolver. The default * resolver provides support for 'file:' and 'http:' protocols. * Sets a settings tree converter and enables the automatic conversion. * The Automatic settings tree conversion is useful for upgrading old * settings files to the new version transparently during execution of the * The automatic conversion takes place after reading the document from the * stream but before validating it. The given converter is asked if the * conversion is necessary using the AutoConverter::needsConversion() call, * and if so, the XSLT template specified by AutoConverter::templateUri() is * applied to the settings tree. * Note that in order to make the result of the conversion permanent, the * settings tree needs to be exlicitly written back to the stream. * The given converter object must exist as long as this instance exists or * until a different converter is set using setAutoConverter() or reset * using resetAutoConverter(). * @param aConverter Settings converter to use. * Disables the automatic settings conversion previously enabled by * setAutoConverter(). By default automatic conversion it is disabled. * Returns a non-NULL string if the automatic settings conversion has been * performed during the last successful #read() call. Returns @c NULL if * there was no settings conversion. * If #read() fails, this method will return the version string set by the * previous successful #read() call or @c NULL if there were no #read() /* auto_ptr data doesn't have proper copy semantics */ }
/* namespace settings */#
endif /* ___VBox_settings_h */