/* -*- C++ -*- */ //============================================================================= /** * @file Configuration.h * * @author Chris Hafey * * The ACE configuration API provides a portable abstraction for * program configuration similar to the Microsoft Windows registry. * The API supports a tree based hierarchy of configuration sections. Each * section contains other sections or values. Values may contain string, * unsigned integer and binary data. * * @note These classes are not thread safe, if multiple threads use these * classes, you are responsible for serializing access. * * For examples of using this class, see: * -# The test code in ACE_wrappers/test * -# wxConfigViewer, a Windows like Registry Editor for ACE_Configuration * -# TAO's IFR, it makes extensive use of ACE_Configuration * * @todo Templatize this class with an ACE_LOCK to provide thread safety */ //============================================================================= #ifndef ACE_CONFIGURATION_H #define ACE_CONFIGURATION_H #include /**/ "ace/pre.h" #include "ace/SStringfwd.h" #include "ace/Hash_Map_With_Allocator_T.h" #include "ace/Malloc_T.h" #include "ace/MMAP_Memory_Pool.h" #include "ace/Local_Memory_Pool.h" #include "ace/Synch_Traits.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ // configurable parameters #if !defined (ACE_CONFIG_SECTION_INDEX) # define ACE_CONFIG_SECTION_INDEX "Config_Section_Index" #endif /* ! ACE_CONFIG_SECTION_INDEX */ #if !defined (ACE_DEFAULT_CONFIG_SECTION_SIZE) #define ACE_DEFAULT_CONFIG_SECTION_SIZE 16 #endif /* ACE_DEFAULT_CONFIG_SECTION_SIZE */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL /** * @class ACE_Section_Key_Internal * * @internal * * @brief A base class for internal handles to section keys for * configuration implementations * * Implementations subclass this base class to represent a * section key. */ class ACE_Export ACE_Section_Key_Internal { public: /// Virtual destructor, make sure descendants are virtual! virtual ~ACE_Section_Key_Internal () = default; /// Increment reference count virtual int add_ref (); /// Decrement reference count. Will delete this if count gets to 0 virtual int dec_ref (); protected: ACE_Section_Key_Internal () = default; ACE_Section_Key_Internal (const ACE_Section_Key_Internal& rhs); ACE_Section_Key_Internal& operator= (ACE_Section_Key_Internal& rhs); u_int ref_count_ {}; }; /** * @class ACE_Configuration_Section_Key * * @brief Reference counted wrapper for ACE_Section_Key_Internal. * * Reference counted wrapper class for the abstract internal * section key. A user gets one of these to represent a section * in the configuration database. */ class ACE_Export ACE_Configuration_Section_Key { friend class ACE_Configuration; public: /// Default constructor. ACE_Configuration_Section_Key () = default; /// Constructor that initializes to a pointer to a concrete internal key. /** * @param key The section key to reference. Calls add_ref() with @a key. */ explicit ACE_Configuration_Section_Key (ACE_Section_Key_Internal *key); /// Copy constructor, increments the reference count on the key. ACE_Configuration_Section_Key (const ACE_Configuration_Section_Key &rhs); /// Destructor, decrements reference count on the referenced key. ~ACE_Configuration_Section_Key (); /// Assignment operator, increments reference count for this object /// and decrements it on @a rhs. ACE_Configuration_Section_Key &operator= (const ACE_Configuration_Section_Key &rhs); private: ACE_Section_Key_Internal *key_ {}; }; /** * @class ACE_Configuration * * @internal * * @brief Base class for configuration databases * * This class provides an interface for configuration databases. A concrete * class is required that implements the interface. * * @sa ACE_Configuration_Heap * @sa ACE_Configuration_Win32Registry */ class ACE_Export ACE_Configuration { public: /// Enumeration for the various types of values we can store. enum VALUETYPE { STRING, INTEGER, BINARY, INVALID }; /// Destructor virtual ~ACE_Configuration () = default; /// Obtain a reference to the root section of this configuration. /* * @return Reference to the configuration's root section. Note that * it is a const reference. */ virtual const ACE_Configuration_Section_Key& root_section () const; /** * Opens a named section in an existing section. * * @param base Existing section in which to open the named section. * @param sub_section Name of the section to open. * @param create If false, the named section must exist, otherwise * the named section will be created if it does not exist. * @param result Reference; receives the section key for the new * section. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int open_section (const ACE_Configuration_Section_Key &base, const ACE_TCHAR *sub_section, bool create, ACE_Configuration_Section_Key& result) = 0; /// Removes a named section. /** * @param key Section key to remove the named section from. * @param sub_section Name of the section to remove. * @param recursive If true, any subkeys below @a sub_section are * removed as well. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int remove_section (const ACE_Configuration_Section_Key &key, const ACE_TCHAR *sub_section, bool recursive) = 0; /** * Enumerates through the values in a section. * * @param key Section key to iterate through. * @param index Iteration position. Must be zero on the first call to * iterate through @a key. Increment @a index by one on each * successive call to this method. * @param name Receives the value's name. * @param type Receives the value's data type. * * @note You may not delete or add values while enumerating. If the * section is modified during enumeration, results are undefined; * you must restart the enumeration from index 0. * * @retval 0 for success, @a name and @a type are valid. * @retval 1 there are no more values in the section. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int enumerate_values (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name, VALUETYPE& type) = 0; /** * Enumerates through the subsections in a section. * * @param key Section key to iterate through. * @param index Iteration position. Must be zero on the first call to * iterate through @a key. Increment @a index by one on each * successive call to this method. * @param name Receives the subsection's name. * * @note You may not modify the @a key section while enumerating. If the * section is modified during enumeration, results are undefined; * you must restart the enumeration from index 0. * * @retval 0 for success, @a name has a valid name. * @retval 1 there are no more subsections in the section. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int enumerate_sections (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name) = 0; /// Sets a string-typed value. /** * @param key Configuration section to set the value in. * @param name Name of the configuration value to set. If a value with * the specified name exists, it is replaced. * @param value The string to set the configuration value to. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int set_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const ACE_TString& value) = 0; /// Sets a integer-typed value. /** * @param key Configuration section to set the value in. * @param name Name of the configuration value to set. If a value with * the specified name exists, it is replaced. * @param value The integer to set the configuration value to. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int set_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int value) = 0; /// Sets a binary-typed value. /** * @param key Configuration section to set the value in. * @param name Name of the configuration value to set. If a value with * the specified name exists, it is replaced. * @param data Pointer to the binary data for the value. * @param length Number of bytes for the new value. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int set_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const void* data, size_t length) = 0; /// Gets a string-typed value. /** * @param key Configuration section to get the value from. * @param name Name of the configuration value to get. * @param value Receives the configuration value if it exists and * has type STRING. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int get_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, ACE_TString& value) = 0; /// Gets an integer-typed value. /** * @param key Configuration section to get the value from. * @param name Name of the configuration value to get. * @param value Receives the configuration value if it exists and * has type INTEGER. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int get_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int& value) = 0; /// Gets a binary-typed value. /** * @param key Configuration section to get the value from. * @param name Name of the configuration value to get. * @param data Receives a pointer to memory holding the binary data * for the value. This method allocates the memory pointed * to using operator new[]. The caller is responsible for * freeing the memory using operator delete[]. * @param length Receives the number of bytes in the value. * * @retval 0 for success; caller is responsible for freeing the * returned memory. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int get_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, void*& data, size_t& length) = 0; /** * Retrieves the type of a named configuration value. * * @param key Configuration section to look up the name in. * @param name Name of the configuration value to get the type of. * @param type Receives the data type of the named value, if it exists. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int find_value(const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, VALUETYPE& type) = 0; /// Removes a named value. /** * @param key Configuration section to remove the named value from. * @param name Name of the configuration value to remove. * * @retval 0 for success. * @retval -1 for error; ACE_OS::last_error() retrieves error code. */ virtual int remove_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name) = 0; /** * Expands @a path_in to @a key_out from @a key. If create is true, * the subsections are created. Returns 0 on success, non zero on * error The path consists of sections separated by the backslash * '\' or forward slash '/'. * Returns 0 on success, -1 if virtual ~ACE_Section_Key_Win32 (); // Not used ACE_Section_Key_Win32 (const ACE_Section_Key_Win32& rhs); ACE_Section_Key_Win32& operator= (const ACE_Section_Key_Win32& rhs); }; /** * @class ACE_Configuration_Win32Registry * * @brief The win32 registry implementation of a configuration database * * The win32 implementation basically makes calls through to the * registry functions. The API is very similar so very little * work must be done */ class ACE_Export ACE_Configuration_Win32Registry : public ACE_Configuration { public: /** * Constructor for registry configuration database. hKey is the * base registry key to attach to. This class takes ownership of * hKey, it will invoke on it upon destruction. */ explicit ACE_Configuration_Win32Registry (HKEY hKey, u_long security_access = KEY_ALL_ACCESS); /// Destructor virtual ~ACE_Configuration_Win32Registry (); virtual int open_section (const ACE_Configuration_Section_Key& base, const ACE_TCHAR* sub_section, bool create, ACE_Configuration_Section_Key& result); virtual int remove_section (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* sub_section, bool recursive); virtual int enumerate_values (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name, VALUETYPE& type); virtual int enumerate_sections (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name); virtual int set_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const ACE_TString& value); virtual int set_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int value); virtual int set_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const void* data, size_t length); virtual int get_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, ACE_TString& value); virtual int get_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int& value); virtual int get_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, void*& data, size_t& length); virtual int find_value(const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, VALUETYPE& type); /// Removes the the value @a name from @a key. returns non zero on error virtual int remove_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name); /** * This method traverses through . It is useful when * you want the HKEY for a specific registry key, especially when * initializing this implementation. Caller is responsible for * closeing this key when it is no longer used. If create is 1 * (default) the keys are create if they don't already exist. * Returns 0 on error */ static HKEY resolve_key (HKEY hKey, const ACE_TCHAR* path, bool create = true, u_long security_access = KEY_ALL_ACCESS); virtual bool operator== (const ACE_Configuration_Win32Registry &rhs) const; virtual bool operator!= (const ACE_Configuration_Win32Registry &rhs) const; protected: /// Gets the HKEY for a configuration section int load_key (const ACE_Configuration_Section_Key& key, HKEY& hKey); // Not used ACE_Configuration_Win32Registry (); ACE_Configuration_Win32Registry (const ACE_Configuration_Win32Registry& rhs); ACE_Configuration_Win32Registry& operator= (const ACE_Configuration_Win32Registry& rhs); const u_long security_access_; }; #endif /* ACE_WIN32 */ // ACE_Allocator version typedef ACE_Allocator_Adapter > PERSISTENT_ALLOCATOR; typedef ACE_Allocator_Adapter > HEAP_ALLOCATOR; /** * @class ACE_Configuration_ExtId * * @brief External ID for the section and value hash * * Contains a pointer to the section or value name. */ class ACE_Export ACE_Configuration_ExtId { public: /// Defeault ctor ACE_Configuration_ExtId () = default; /// Named constructor explicit ACE_Configuration_ExtId (const ACE_TCHAR* name); /// Copy ctor ACE_Configuration_ExtId (const ACE_Configuration_ExtId& rhs); /// destructor ~ACE_Configuration_ExtId () = default; /// Assignment operator ACE_Configuration_ExtId& operator= (const ACE_Configuration_ExtId& rhs); /// Equality comparison operator (must match name_). bool operator== (const ACE_Configuration_ExtId &rhs) const; /// Inequality comparison operator. bool operator!= (const ACE_Configuration_ExtId &rhs) const; /// Frees the name of the value. needed since we don't know the /// allocator name_ was created in void free (ACE_Allocator *alloc); /// hash function is required in order for this class to be usable by /// ACE_Hash_Map_Manager. u_long hash () const; // = Data members. const ACE_TCHAR * name_ {}; // Accessors const ACE_TCHAR *name (); }; typedef ACE_Hash_Map_With_Allocator SUBSECTION_MAP; typedef ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> SUBSECTION_HASH; /** * @class ACE_Configuration_Value_IntId * * @brief The section hash table internal value class * * This class is present as the internal portion of a section's * value hash table It may store string, integer or binary data. */ class ACE_Export ACE_Configuration_Value_IntId { public: /// Default constructor ACE_Configuration_Value_IntId (); /// String constructor, takes ownership of string explicit ACE_Configuration_Value_IntId (ACE_TCHAR* string); /// Integer constructor explicit ACE_Configuration_Value_IntId (u_int integer); /// Binary constructor, takes ownership of data ACE_Configuration_Value_IntId (void* data, size_t length); /// Copy ctor ACE_Configuration_Value_IntId (const ACE_Configuration_Value_IntId& rhs); /// Destructor ~ACE_Configuration_Value_IntId (); /// Assignment operator ACE_Configuration_Value_IntId& operator= ( const ACE_Configuration_Value_IntId& rhs); void free (ACE_Allocator *alloc); // = Data members. /** * Points to the string value or binary data or IS the integer * Length is only used when type_ == BINARY */ ACE_Configuration::VALUETYPE type_; union { void * ptr_; u_int int_; } data_; size_t length_; }; typedef ACE_Hash_Map_With_Allocator VALUE_MAP; typedef ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> VALUE_HASH; // Deprecated typedef. Use the VALUE_HASH::ENTRY trait instead. typedef VALUE_HASH::ENTRY VALUE_ENTRY; /** * @class ACE_Configuration_Section_IntId * * @brief The internal ID for a section hash table * * Contains a hash table containing value name/values */ class ACE_Export ACE_Configuration_Section_IntId { public: /// Default ctor ACE_Configuration_Section_IntId (); /// Named ctor ACE_Configuration_Section_IntId (VALUE_MAP* value_hash_map, SUBSECTION_MAP* section_hash_map); /// Copy ctor ACE_Configuration_Section_IntId (const ACE_Configuration_Section_IntId& rhs); /// Destructor ~ACE_Configuration_Section_IntId (); /// Assignment operator ACE_Configuration_Section_IntId& operator= ( const ACE_Configuration_Section_IntId& rhs); /// Frees the hash table and all its values void free (ACE_Allocator *alloc); // = Data Members. VALUE_MAP* value_hash_map_; SUBSECTION_MAP* section_hash_map_; }; typedef ACE_Hash_Map_With_Allocator SECTION_MAP; typedef ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> SECTION_HASH; // Deprecated typedef. Use the SECTION_HASH::ENTRY trait instead. typedef SECTION_HASH::ENTRY SECTION_ENTRY; /** * @class ACE_Configuration_Section_Key_Heap * * @brief Internal section key class for heap based configuration * database. * * Contains a value iterator and full path name of section. */ class ACE_Export ACE_Configuration_Section_Key_Heap : public ACE_Section_Key_Internal { public: /// Constructor based on the full path of the section ACE_Configuration_Section_Key_Heap (const ACE_TCHAR* path); /// The path itself ACE_TCHAR* path_; /// The value iterator VALUE_HASH::ITERATOR* value_iter_; /// The sub section iterator SUBSECTION_HASH::ITERATOR* section_iter_; ACE_ALLOC_HOOK_DECLARE; protected: /// Destructor - will delete the iterators virtual ~ACE_Configuration_Section_Key_Heap (); // Not used ACE_Configuration_Section_Key_Heap (const ACE_Configuration_Section_Key_Heap& rhs); ACE_Configuration_Section_Key_Heap& operator= (const ACE_Configuration_Section_Key_Heap& rhs); }; /** * @class ACE_Configuration_Heap * * @brief The concrete implementation of a allocator based * configuration database * * This class uses ACE's Allocators to manage a memory * representation of a configuration database. A persistent heap * may be used to store configurations persistently * * @note Before using this class you must call one of the open methods. * * @todo * - Need to investigate what happens if memory mapped file gets mapped to * a location different than it was created with. */ class ACE_Export ACE_Configuration_Heap : public ACE_Configuration { public: /// Default ctor ACE_Configuration_Heap (); /// Destructor virtual ~ACE_Configuration_Heap (); /** * Opens a configuration that allocates its memory from a memory-mapped file. * This makes it possible to persist a configuration to permanent storage. * This is not the same as exporting the configuration to a file; the * memory-mapped file is not likely to be very readable by humans. * * @param file_name Name of the file to map into memory. * * @param base_address Address to map the base of @a file_name to. * * @param default_map_size Starting size for the internal hash tables that * contain configuration information. * * @retval 0 for success. * @retval -1 for error, with errno set to indicate the cause. If open() * is called multiple times, errno will be @c EBUSY. */ int open (const ACE_TCHAR* file_name, void* base_address = ACE_DEFAULT_BASE_ADDR, size_t default_map_size = ACE_DEFAULT_CONFIG_SECTION_SIZE); /** * Opens a configuration that allocates memory from the heap. * * @param default_map_size Starting size for the internal hash tables that * contain configuration information. * * @retval 0 for success. * @retval -1 for error, with errno set to indicate the cause. If open() * is called multiple times, errno will be @c EBUSY. */ int open (size_t default_map_size = ACE_DEFAULT_CONFIG_SECTION_SIZE); virtual int open_section (const ACE_Configuration_Section_Key& base, const ACE_TCHAR* sub_section, bool create, ACE_Configuration_Section_Key& result); virtual int remove_section (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* sub_section, bool recursive); virtual int enumerate_values (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name, VALUETYPE& type); virtual int enumerate_sections (const ACE_Configuration_Section_Key& key, int index, ACE_TString& name); virtual int set_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const ACE_TString& value); virtual int set_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int value); virtual int set_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, const void* data, size_t length); virtual int get_string_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, ACE_TString& value); virtual int get_integer_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, u_int& value); virtual int get_binary_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, void* &data, size_t &length); virtual int find_value(const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name, VALUETYPE& type); /// Removes the the value @a name from @a key. returns non zero on error virtual int remove_value (const ACE_Configuration_Section_Key& key, const ACE_TCHAR* name); private: /// @a sub_section may not contain path separators int open_simple_section (const ACE_Configuration_Section_Key &base, const ACE_TCHAR *sub_section, bool create, ACE_Configuration_Section_Key &result); /// Adds a new section int add_section (const ACE_Configuration_Section_Key &base, const ACE_TCHAR *sub_section, ACE_Configuration_Section_Key &result); /// Helper for the method. int create_index (); /// Helper for create_index() method: places hash table into an /// allocated space. int create_index_helper (void *buffer); int value_open_helper (size_t hash_table_size, void *buffer); int section_open_helper (size_t hash_table_size, void *buffer); int load_key (const ACE_Configuration_Section_Key& key, ACE_TString& name); int new_section (const ACE_TString& section, ACE_Configuration_Section_Key& result); ACE_Configuration_Heap (const ACE_Configuration_Heap& rhs); ACE_Configuration_Heap& operator= (const ACE_Configuration_Heap& rhs); ACE_Allocator *allocator_; SECTION_MAP *index_; size_t default_map_size_; }; ACE_END_VERSIONED_NAMESPACE_DECL #if defined (__ACE_INLINE__) #include "ace/Configuration.inl" #endif /* __ACE_INLINE__ */ #include /**/ "ace/post.h" #endif /* ACE_CONFIGURATION_H */