summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>2001-04-14 23:36:59 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>2001-04-14 23:36:59 +0000
commite4c8f52beb46ca2d0c00158f8ec72735b792db6c (patch)
treeceec871cef7a5eab4acb6dc6cac0b54671463e33
parentc43c12c2fde446ac6a7976114b7e80df99ae2045 (diff)
downloadATCD-e4c8f52beb46ca2d0c00158f8ec72735b792db6c.tar.gz
ChangeLogTag:Sat Apr 14 18:31:15 2001 Douglas C. Schmidt <schmidt@tango.doc.wustl.edu>
-rw-r--r--ace/Configuration.cpp769
-rw-r--r--ace/Configuration.h115
-rw-r--r--ace/Configuration_Import_Export.cpp552
-rw-r--r--ace/Configuration_Import_Export.h225
-rw-r--r--ace/Makefile1
-rw-r--r--tests/Config_Test.cpp942
-rw-r--r--tests/Config_Test.h66
7 files changed, 1993 insertions, 677 deletions
diff --git a/ace/Configuration.cpp b/ace/Configuration.cpp
index dcf05dd12a2..5574b8dc936 100644
--- a/ace/Configuration.cpp
+++ b/ace/Configuration.cpp
@@ -165,305 +165,289 @@ ACE_Configuration::expand_path (const ACE_Configuration_Section_Key& key,
ACE_Configuration_Section_Key& key_out,
int create)
{
+ const ACE_TCHAR* begin = path_in.fast_rep ();
+ const ACE_TCHAR* end = 0;
+
// Make a copy of key
ACE_Configuration_Section_Key current_section = key;
- ACE_TString data (path_in);
- ACE_TCHAR *pData = (ACE_TCHAR *) data.c_str ();
- ACE_Tokenizer parser (pData);
- parser.delimiter_replace ('\\', '\0');
- parser.delimiter_replace ('/', '\0');
-
- for (ACE_TCHAR *temp = parser.next ();
- temp != 0;
- temp = parser.next ())
+
+ // recurse through the path
+ while (1)
{
+ // Detmine the begin/ending of the key name
+ end = ACE_OS::strchr (begin, ACE_LIB_TEXT ('\\'));
+ size_t length = end ? (size_t)(end-begin) : ACE_OS::strlen (begin);
+
+ // Make sure length is not 0
+ if (!length)
+ return -1;
+
+ ACE_TString section (begin, length);
+
// Open the section
+ ACE_Configuration_Section_Key child_section;
if (open_section (current_section,
- temp,
+ section.fast_rep (),
create,
- key_out))
+ child_section))
return -1;
- current_section = key_out;
- }
-
- return 0;
-}
-int
-ACE_Configuration::validate_name (const ACE_TCHAR *name)
-{
- const ACE_TCHAR *pos;
-
- for (pos = name;
- // Make sure it doesn't contain any invalid characters
- *pos != '\0';
- pos++)
- if (ACE_OS::strchr (ACE_LIB_TEXT ("\\]["), *pos))
- return -1;
+ current_section = child_section;
- // Make sure its not too long.
- if (pos - name > ACE_Configuration::MAX_NAME_LEN)
- return -2;
+ // If end is NULL, we are done, return the result
+ if (!end)
+ {
+ key_out = current_section;
+ break;
+ }
+ begin = end + 1;
+ }
return 0;
}
int
-ACE_Configuration::export_section (const ACE_Configuration_Section_Key& section,
- const ACE_TString& path,
- FILE* out)
+ACE_Configuration::validate_name (const ACE_TCHAR* name)
{
- // don't export the root
- if (path.length ())
+ const ACE_TCHAR* pos = name;
+ // make sure it doesn't contain any invalid characters
+ while (*pos)
{
- // Write out the section header
- ACE_TString header = ACE_LIB_TEXT ("[");
- header += path;
- header += ACE_LIB_TEXT ("]");
- header += ACE_LIB_TEXT (" \n");
- if (ACE_OS::fputs (header.fast_rep (), out) < 0)
+ if (ACE_OS::strchr (ACE_LIB_TEXT ("\\]["), *pos))
return -1;
- // Write out each value
- int index = 0;
- ACE_TString name;
- VALUETYPE type;
- ACE_TString line;
- ACE_TCHAR int_value[32];
- ACE_TCHAR bin_value[3];
- void* binary_data;
- u_int binary_length;
- ACE_TString string_value;
-
- while (!enumerate_values (section, index, name, type))
- {
- line = ACE_LIB_TEXT ("\"") + name + ACE_LIB_TEXT ("\"=");
- switch (type)
- {
- case INTEGER:
- {
- u_int value;
- if (get_integer_value (section, name.fast_rep (), value))
- return -2;
-
- ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), value);
- line += ACE_LIB_TEXT ("dword:");
- line += int_value;
- break;
- }
- case STRING:
- {
- if (get_string_value (section,
- name.fast_rep (),
- string_value))
- return -2;
-
- line += ACE_LIB_TEXT ("\"");
- line += string_value + ACE_LIB_TEXT ("\"");
- break;
- }
-#if defined (ACE_WIN32)
- case INVALID:
-#endif /* ACE_WIN32 */
- case BINARY:
- {
- // not supported yet - maybe use BASE64 codeing?
- if (get_binary_value (section,
- name.fast_rep (),
- binary_data,
- binary_length))
- return -2;
-
- line += ACE_LIB_TEXT ("hex:");
-
- u_char *ptr = (u_char *) binary_data;
- while (binary_length)
- {
- if (ptr != binary_data)
- line += ACE_LIB_TEXT (",");
-
- ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
- line += bin_value;
- --binary_length;
- ++ptr;
- }
- delete (char *) binary_data;
- break;
- }
- default:
- return -3;
- }
-
- line += ACE_LIB_TEXT ("\n");
- if (ACE_OS::fputs (line.fast_rep (), out) < 0)
- return -4;
-
- index++;
- }
+ pos++;
}
- // Export all sub sections
- int index = 0;
- ACE_TString name;
- ACE_Configuration_Section_Key sub_key;
- ACE_TString sub_section;
-
- while (!enumerate_sections (section, index, name))
- {
- ACE_TString sub_section (path);
- if (path.length ())
- sub_section += ACE_LIB_TEXT ("\\");
-
- sub_section += name;
- if (open_section (section, name.fast_rep (), 0, sub_key))
- return -5;
-
- if (export_section (sub_key, sub_section.fast_rep (), out))
- return -6;
-
- index++;
- }
+ // Make sure its not too long
+ if (pos - name > 255)
+ return -2;
return 0;
}
-int
-ACE_Configuration::export_config (const ACE_TCHAR* filename)
-{
- FILE *out = ACE_OS::fopen (filename, ACE_LIB_TEXT ("w"));
- if (!out)
- return -1;
- int result = export_section (root_, ACE_LIB_TEXT (""), out);
- ACE_OS::fclose (out);
- return result;
+const ACE_Configuration_Section_Key&
+ACE_Configuration::root_section (void)
+{
+ return root_;
}
-int
-ACE_Configuration::import_config (const ACE_TCHAR* filename)
+/**
+ * Determine if the contents of this object is the same as the
+ * contents of the object on the right hand side.
+ * Returns 1 (True) if they are equal and 0 (False) if they are not equal
+ */
+int ACE_Configuration::operator==(const ACE_Configuration& rhs) const
{
- FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
- if (!in)
- return -1;
+ int rc = true;
+ int sectionIndex = 0;
+ ACE_TString sectionName;
- // @@ XXX - change this to a dynamic buffer
- ACE_TCHAR buffer[4096];
- ACE_Configuration_Section_Key section;
- while (ACE_OS::fgets (buffer, 4096, in))
- {
- // Check for a comment
- if (buffer[0] == ACE_LIB_TEXT (';') || buffer[0] == ACE_LIB_TEXT ('#'))
- continue;
+ const ACE_Configuration_Section_Key& rhsRoot = const_cast<ACE_Configuration&>(rhs).root_section();
+ ACE_Configuration_Section_Key rhsSection;
+ ACE_Configuration_Section_Key thisSection;
- if (buffer[0] == ACE_LIB_TEXT ('['))
+ // loop through each section in this object
+ while( (rc) &&
+ (!const_cast<ACE_Configuration*>(this)->enumerate_sections(this->root_,
+ sectionIndex,
+ sectionName)) )
+ {
+ // find that section in the rhs object
+ if(const_cast<ACE_Configuration&>(rhs).open_section(rhsRoot,
+ sectionName.c_str(),
+ 0,
+ rhsSection) != 0)
{
- // We have a new section here, strip out the section name
- ACE_TCHAR* end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
- if (!end)
- {
- ACE_OS::fclose (in);
- return -3;
- }
- *end = 0;
-
- if (expand_path (root_, buffer + 1, section, 1))
- {
- ACE_OS::fclose (in);
- return -3;
- }
-
- continue;
+ // If the rhs object does not contain the section then we are not equal.
+ rc = false;
}
-
- if (buffer[0] == ACE_LIB_TEXT ('"'))
+ else if(const_cast<ACE_Configuration*>(this)->open_section(this->root_,
+ sectionName.c_str(),
+ 0,
+ thisSection) != 0)
{
- // we have a value
- ACE_TCHAR* end = ACE_OS::strchr (buffer+1, '"');
- if (!end) // no closing quote, not a value so just skip it
- continue;
-
- // null terminate the name
- *end = 0;
- ACE_TCHAR* name = buffer + 1;
- end+=2;
- // determine the type
- if (*end == '\"')
+ // if there is some error opening the section in this object
+ rc = false;
+ }
+ else
+ {
+ // Well the sections match
+ int valueIndex = 0;
+ ACE_TString valueName;
+ VALUETYPE valueType;
+ VALUETYPE rhsType;
+
+ // Enumerate each value in this section
+ while((rc) &&
+ (!const_cast<ACE_Configuration*>(this)->enumerate_values(thisSection,
+ valueIndex,
+ valueName,
+ valueType)))
{
- // string type
- // truncate trailing "
- ++end;
- ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
- if (trailing)
- *trailing = 0;
- if (set_string_value (section, name, end))
+ // look for the same value in the rhs section
+ if(const_cast<ACE_Configuration&>(rhs).find_value(rhsSection,
+ valueName.c_str(),
+ rhsType) != 0)
{
- ACE_OS::fclose (in);
- return -4;
+ // We're not equal if the same value cannot
+ // be found in the rhs object.
+ rc = false;
}
- }
- else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("dword:"), 6) == 0)
- {
- // number type
- ACE_TCHAR* endptr = 0;
- u_int value = ACE_OS::strtoul (end + 6, &endptr, 16);
- if (set_integer_value (section, name, value))
+ else if (valueType != rhsType)
{
- ACE_OS::fclose (in);
- return -4;
+ // we're not equal if the types do not match.
+ rc = false;
}
- }
- else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("hex:"), 4) == 0)
- {
- // binary type
- u_int string_length = ACE_OS::strlen (end + 4);
- // divide by 3 to get the actual buffer length
- u_int length = string_length / 3;
- u_int remaining = length;
- u_char* data = new u_char[length];
- u_char* out = data;
- ACE_TCHAR* inb = end + 4;
- ACE_TCHAR* endptr = 0;
- while (remaining)
+ else
{
- u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
- *out = charin;
- ++out;
- --remaining;
- inb += 3;
- }
- if (set_binary_value (section, name, data, length))
+ // finally compare values.
+ if(valueType == STRING)
+ {
+ ACE_TString thisString, rhsString;
+ if(const_cast<ACE_Configuration*>(this)->get_string_value(thisSection,
+ valueName.c_str(),
+ thisString) != 0)
+ {
+ // we're not equal if we cannot get this string
+ rc = false;
+ }
+ else if(const_cast<ACE_Configuration&>(rhs).get_string_value(rhsSection,
+ valueName.c_str(),
+ rhsString) != 0)
+ {
+ // we're not equal if we cannot get rhs string
+ rc = false;
+ }
+ rc = thisString == rhsString;
+ }
+ else if (valueType == INTEGER)
+ {
+ u_int thisInt, rhsInt;
+ if(const_cast<ACE_Configuration*>(this)->get_integer_value(thisSection,
+ valueName.c_str(),
+ thisInt) != 0)
+ {
+ // we're not equal if we cannot get this int
+ rc = false;
+ }
+ else if(const_cast<ACE_Configuration&>(rhs).get_integer_value(rhsSection,
+ valueName.c_str(),
+ rhsInt) != 0)
+ {
+ // we're not equal if we cannot get rhs int
+ rc = false;
+ }
+ rc = thisInt == rhsInt;
+ }
+ else if(valueType == BINARY)
+ {
+
+ void* thisData;
+ void* rhsData;
+ u_int thisLength, rhsLength;
+ if(const_cast<ACE_Configuration*>(this)->get_binary_value(thisSection,
+ valueName.c_str(),
+ thisData,
+ thisLength) != 0)
+ {
+ // we're not equal if we cannot get this data
+ rc = false;
+ }
+ else if(const_cast<ACE_Configuration&>(rhs).get_binary_value(rhsSection,
+ valueName.c_str(),
+ rhsData,
+ rhsLength) != 0)
+ {
+ // we're not equal if we cannot get this data
+ rc = false;
+ }
+
+ // are the length's the same?
+ if(rc = (thisLength == rhsLength))
+ {
+ unsigned char* thisCharData = (unsigned char*)thisData;
+ unsigned char* rhsCharData = (unsigned char*)rhsData;
+ // yes, then check each element
+ for(u_int count = 0; (rc) && (count < thisLength); count++)
+ {
+ rc = (*(thisCharData + count) == *(rhsCharData + count));
+ }
+ }// end if the length's match
+ }
+ // We should never have valueTypes of INVALID, therefore
+ // we're not comparing them. How would we since we have
+ // no get operation for invalid types.
+ // So, if we have them, we guess they are equal.
+
+ }// end else if values match.
+
+ valueIndex++;
+
+ }// end value while loop
+
+ // look in the rhs for values not in this
+ valueIndex = 0;
+ while((rc) &&
+ (!const_cast<ACE_Configuration&>(rhs).enumerate_values(rhsSection,
+ valueIndex,
+ valueName,
+ rhsType)))
+ {
+ // look for the same value in this section
+ if(const_cast<ACE_Configuration*>(this)->find_value(thisSection,
+ valueName.c_str(),
+ valueType) != 0)
{
- ACE_OS::fclose (in);
- return -4;
+ // We're not equal if the same value cannot
+ // be found in the rhs object.
+ rc = false;
}
- }
- else
- // invalid type, ignore
- continue;
- }
- }
+ valueIndex++;
+ }// end while for rhs values not in this.
+
+ }// end else if sections match.
+
+ sectionIndex++;
- if (ferror (in))
+ }// end section while loop
+
+ // Finally, make sure that there are no sections in rhs that do not exist in this
+ sectionIndex = 0;
+ while( (rc) &&
+ (!const_cast<ACE_Configuration&>(rhs).enumerate_sections(rhsRoot,
+ sectionIndex,
+ sectionName)) )
{
- ACE_OS::fclose (in);
- return -1;
+ // find the section in this
+ if(const_cast<ACE_Configuration*>(this)->open_section(this->root_,
+ sectionName.c_str(),
+ 0,
+ thisSection) != 0)
+ {
+ // if there is some error opening the section in this object
+ rc = false;
+ }
+ else if(const_cast<ACE_Configuration&>(rhs).open_section(rhsRoot,
+ sectionName.c_str(),
+ 0,
+ rhsSection) != 0)
+ {
+ // If the rhs object does not contain the section then we are not equal.
+ rc = false;
+ }
+ sectionIndex++;
}
-
- ACE_OS::fclose (in);
- return 0;
+ return rc;
}
-const ACE_Configuration_Section_Key&
-ACE_Configuration::root_section (void)
-{
- return root_;
-}
//////////////////////////////////////////////////////////////////////////////
#if defined (WIN32)
-static const int ACE_DEFAULT_BUFSIZE = ACE_Configuration::MAX_NAME_LEN + 1;
+static const int ACE_DEFAULT_BUFSIZE = 256;
ACE_Section_Key_Win32::ACE_Section_Key_Win32 (HKEY hKey)
: hKey_ (hKey)
@@ -666,7 +650,7 @@ ACE_Configuration_Win32Registry::set_string_value (const ACE_Configuration_Secti
name,
0,
REG_SZ,
- (BYTE *) value.fast_rep (),
+ (BYTE *) value.fast_rep (),
value.length () + 1) != ERROR_SUCCESS)
return -2;
@@ -689,7 +673,7 @@ ACE_Configuration_Win32Registry::set_integer_value (const ACE_Configuration_Sect
name,
0,
REG_DWORD,
- (BYTE *) &value,
+ (BYTE *) &value,
sizeof (value)) != ERROR_SUCCESS)
return -2;
@@ -713,7 +697,7 @@ ACE_Configuration_Win32Registry::set_binary_value (const ACE_Configuration_Secti
name,
0,
REG_BINARY,
- (BYTE*)data,
+ (BYTE*)data,
length) != ERROR_SUCCESS)
return -2;
@@ -732,36 +716,21 @@ ACE_Configuration_Win32Registry::get_string_value (const ACE_Configuration_Secti
if (load_key (key, base_key))
return -1;
- // Get the size of the binary data from windows
- DWORD buffer_length = 0;
+ ACE_TCHAR buffer[ACE_DEFAULT_BUFSIZE];
+ DWORD length = ACE_DEFAULT_BUFSIZE;
DWORD type;
if (ACE_TEXT_RegQueryValueEx (base_key,
- name,
- NULL,
- &type,
- (BYTE*)0,
- &buffer_length) != ERROR_SUCCESS)
+ name,
+ NULL,
+ &type,
+ (BYTE*)buffer,
+ &length) != ERROR_SUCCESS)
return -2;
if (type != REG_SZ)
return -3;
- ACE_TCHAR* buffer;
- ACE_NEW_RETURN (buffer, ACE_TCHAR[buffer_length], -4);
-
- if (ACE_TEXT_RegQueryValueEx (base_key,
- name,
- NULL,
- &type,
- (BYTE*)buffer,
- &buffer_length) != ERROR_SUCCESS)
- {
- delete[] buffer;
- return -5;
- }
-
value = buffer;
- delete[] buffer;
return 0;
}
@@ -783,7 +752,7 @@ ACE_Configuration_Win32Registry::get_integer_value (const ACE_Configuration_Sect
name,
NULL,
&type,
- (BYTE*)&value,
+ (BYTE*)&value,
&length) != ERROR_SUCCESS)
return -2;
@@ -813,7 +782,7 @@ ACE_Configuration_Win32Registry::get_binary_value (const ACE_Configuration_Secti
name,
NULL,
&type,
- (BYTE*)0,
+ (BYTE*)0,
&buffer_length) != ERROR_SUCCESS)
return -2;
@@ -822,16 +791,16 @@ ACE_Configuration_Win32Registry::get_binary_value (const ACE_Configuration_Secti
length = buffer_length;
- ACE_NEW_RETURN (data, u_char[length], -4);
+ ACE_NEW_RETURN (data, unsigned char[length], -4);
if (ACE_TEXT_RegQueryValueEx (base_key,
name,
NULL,
&type,
- (BYTE*)data,
+ (BYTE*)data,
&buffer_length) != ERROR_SUCCESS)
{
- delete[] data;
+ delete data;
data = 0;
return -5;
}
@@ -839,7 +808,7 @@ ACE_Configuration_Win32Registry::get_binary_value (const ACE_Configuration_Secti
return 0;
}
-int ACE_Configuration_Win32Registry::find_value (const ACE_Configuration_Section_Key& key,
+int ACE_Configuration_Win32Registry::find_value(const ACE_Configuration_Section_Key& key,
const ACE_TCHAR* name,
VALUETYPE& type_out)
{
@@ -850,20 +819,18 @@ int ACE_Configuration_Win32Registry::find_value (const ACE_Configuration_Section
if (load_key (key, base_key))
return -1;
- DWORD buffer_length=0;
+ unsigned char buffer[ACE_DEFAULT_BUFSIZE];
+ DWORD buffer_length = ACE_DEFAULT_BUFSIZE;
DWORD type;
- int result=ACE_TEXT_RegQueryValueEx (base_key,
+ if (ACE_TEXT_RegQueryValueEx (base_key,
name,
NULL,
&type,
- NULL,
- &buffer_length);
- if (result != ERROR_SUCCESS)
- {
+ (BYTE*)&buffer,
+ &buffer_length) != ERROR_SUCCESS)
return -1;
- }
- switch (type)
+ switch(type)
{
case REG_SZ:
type_out = STRING;
@@ -930,7 +897,7 @@ ACE_Configuration_Win32Registry::resolve_key (HKEY hKey,
{
// Detmine the begin/ending of the key name
end = ACE_OS::strchr (begin, ACE_LIB_TEXT ('\\'));
- size_t length = end ? (size_t) (end-begin) : ACE_OS::strlen (begin);
+ size_t length = end ? (size_t)(end-begin) : ACE_OS::strlen (begin);
// Make sure length is not 0
if (!length)
@@ -969,13 +936,17 @@ ACE_Configuration_Win32Registry::resolve_key (HKEY hKey,
begin = end + 1;
}
-#if !defined (ghs)
+
return 0;
-#endif // ghs
}
+
+
#endif // WIN_32
+
+
+
///////////////////////////////////////////////////////////////
ACE_Configuration_Value_IntId::ACE_Configuration_Value_IntId (void)
@@ -1139,8 +1110,8 @@ ACE_Configuration_Section_IntId::operator= (const ACE_Configuration_Section_IntI
void
ACE_Configuration_Section_IntId::free (ACE_Allocator* allocator)
{
- allocator->free ((void *) (value_hash_map_));
- allocator->free ((void *) (section_hash_map_));
+ allocator->free ((void *)(value_hash_map_));
+ allocator->free ((void *)(section_hash_map_));
}
ACE_Configuration_Section_Key_Heap::ACE_Configuration_Section_Key_Heap (const ACE_TCHAR* path)
@@ -1163,8 +1134,7 @@ ACE_Configuration_Section_Key_Heap::~ACE_Configuration_Section_Key_Heap ()
ACE_Configuration_Heap::ACE_Configuration_Heap (void)
: allocator_ (0),
index_ (0),
- default_map_size_ (0),
- persistent_ (0)
+ default_map_size_ (0)
{
ACE_Configuration_Section_Key_Heap *temp = 0;
@@ -1175,11 +1145,8 @@ ACE_Configuration_Heap::ACE_Configuration_Heap (void)
ACE_Configuration_Heap::~ACE_Configuration_Heap (void)
{
if (allocator_)
- {
allocator_->sync ();
- if (!persistent_)
- allocator_->remove ();
- }
+
delete allocator_;
}
@@ -1193,7 +1160,6 @@ ACE_Configuration_Heap::open (int default_map_size)
ACE_NEW_RETURN (this->allocator_,
HEAP_ALLOCATOR (),
-1);
- persistent_ = 0;
return create_index ();
}
@@ -1203,7 +1169,6 @@ ACE_Configuration_Heap::open (const ACE_TCHAR* file_name,
void* base_address,
int default_map_size)
{
- persistent_ = 1;
default_map_size_ = default_map_size;
// Make sure that the file name is of the legal length.
@@ -1280,7 +1245,7 @@ int
ACE_Configuration_Heap::create_index_helper (void *buffer)
{
ACE_NEW_RETURN (this->index_,
- (buffer) SECTION_MAP (this->allocator_),
+ (buffer) SECTION_MAP (this->allocator_),
-1);
return 0;
}
@@ -1351,7 +1316,7 @@ ACE_Configuration_Heap::new_section (const ACE_TString& section,
// Allocate memory for items to be stored in the table.
size_t section_len = section.length () + 1;
- ACE_TCHAR *ptr = (ACE_TCHAR*) this->allocator_->malloc (section_len * sizeof (ACE_TCHAR));
+ ACE_TCHAR *ptr = (ACE_TCHAR*) this->allocator_->malloc (section_len * sizeof(ACE_TCHAR));
int return_value = -1;
@@ -1396,7 +1361,7 @@ ACE_Configuration_Heap::new_section (const ACE_TString& section,
ACE_Configuration_ExtId name (ptr);
ACE_Configuration_Section_IntId entry ((VALUE_MAP*)value_hash_map ,
- (SUBSECTION_MAP*)section_hash_map);
+ (SUBSECTION_MAP*)section_hash_map);
// Do a normal bind. This will fail if there's already an
// entry with the same name.
@@ -1414,7 +1379,7 @@ ACE_Configuration_Heap::new_section (const ACE_TString& section,
// Free our dynamically allocated memory.
this->allocator_->free ((void *) ptr);
else
- // If bind () succeed, it will automatically sync
+ // If bind() succeed, it will automatically sync
// up the map manager entry. However, we must sync up our
// name/value memory.
this->allocator_->sync (ptr, section_len);
@@ -1433,7 +1398,7 @@ ACE_Configuration_Heap::value_open_helper (size_t hash_table_size,
void *buffer)
{
ACE_NEW_RETURN (buffer,
- (buffer) VALUE_MAP (hash_table_size, this->allocator_),
+ (buffer) VALUE_MAP (hash_table_size, this->allocator_),
-1);
return 0;
}
@@ -1443,7 +1408,7 @@ ACE_Configuration_Heap::section_open_helper (size_t hash_table_size,
void *buffer)
{
ACE_NEW_RETURN (buffer,
- (buffer) SUBSECTION_MAP (hash_table_size, this->allocator_),
+ (buffer) SUBSECTION_MAP (hash_table_size, this->allocator_),
-1);
return 0;
}
@@ -1539,7 +1504,7 @@ ACE_Configuration_Heap::remove_section (const ACE_Configuration_Section_Key& key
// Now remove subkey from parent key
ACE_Configuration_ExtId SubSExtId (sub_section);
SUBSECTION_ENTRY* subsection_entry;
- if (( (SUBSECTION_HASH*)ParentIntId.section_hash_map_)->
+ if (((SUBSECTION_HASH*)ParentIntId.section_hash_map_)->
find (SubSExtId, subsection_entry))
return -4;
@@ -1555,7 +1520,6 @@ ACE_Configuration_Heap::remove_section (const ACE_Configuration_Section_Key& key
// iterate over all values and free memory
VALUE_HASH* value_hash_map = section_entry->int_id_.value_hash_map_;
VALUE_HASH::ITERATOR value_iter = value_hash_map->begin ();
-
while (!value_iter.done ())
{
VALUE_ENTRY* value_entry;
@@ -1602,14 +1566,12 @@ ACE_Configuration_Heap::enumerate_values (const ACE_Configuration_Section_Key& k
// Handle iterator resets
if (index == 0)
{
- ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId ,
- ACE_Configuration_Value_IntId,
- ACE_Hash<ACE_Configuration_ExtId>,
- ACE_Equal_To<ACE_Configuration_ExtId>,
- ACE_Null_Mutex>* hash_map = IntId.value_hash_map_;
+ ACE_Hash_Map_Manager_Ex<ACE_Configuration_ExtId , ACE_Configuration_Value_IntId, ACE_Hash<ACE_Configuration_ExtId>, ACE_Equal_To<ACE_Configuration_ExtId>, ACE_Null_Mutex>* hash_map = IntId.value_hash_map_;
+ // @@ This zero pointer check is redundant -Ossama
+ // if (pKey->value_iter_)
delete pKey->value_iter_;
- ACE_NEW_RETURN (pKey->value_iter_, VALUE_HASH::ITERATOR (hash_map->begin ()), -3);
+ ACE_NEW_RETURN (pKey->value_iter_, VALUE_HASH::ITERATOR(hash_map->begin()), -3);
}
// Get the next entry
@@ -1646,11 +1608,10 @@ ACE_Configuration_Heap::enumerate_sections (const ACE_Configuration_Section_Key&
// Handle iterator resets
if (index == 0)
{
- delete pKey->section_iter_;
+ if (pKey->section_iter_)
+ delete pKey->section_iter_;
- ACE_NEW_RETURN (pKey->section_iter_,
- SUBSECTION_HASH::ITERATOR (IntId.section_hash_map_->begin ()),
- -3);
+ ACE_NEW_RETURN (pKey->section_iter_, SUBSECTION_HASH::ITERATOR (IntId.section_hash_map_->begin ()), -3);
}
// Get the next entry
@@ -1684,30 +1645,27 @@ ACE_Configuration_Heap::set_string_value (const ACE_Configuration_Section_Key& k
// Get the entry for this item (if it exists)
VALUE_ENTRY* entry;
- ACE_Configuration_ExtId item_name (name);
- if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ ACE_Configuration_ExtId item_name(name);
+ if(section_int.value_hash_map_->VALUE_HASH::find(item_name, entry) == 0)
{
// found item, replace it
// Free the old value
- entry->int_id_.free (allocator_);
+ entry->int_id_.free(allocator_);
// Allocate the new value in this heap
- ACE_TCHAR* pers_value =
- (ACE_TCHAR*) allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
- ACE_OS::strcpy (pers_value, value.fast_rep ());
- ACE_Configuration_Value_IntId new_value_int (pers_value);
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
+ ACE_OS::strcpy (pers_value, value.fast_rep());
+ ACE_Configuration_Value_IntId new_value_int(pers_value);
entry->int_id_ = new_value_int;
}
else
{
// it doesn't exist, bind it
- ACE_TCHAR* pers_name =
- (ACE_TCHAR*) allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
+ ACE_TCHAR* pers_name = (ACE_TCHAR*)allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
ACE_OS::strcpy (pers_name, name);
- ACE_TCHAR* pers_value =
- (ACE_TCHAR*) allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc ((value.length () + 1) * sizeof (ACE_TCHAR));
ACE_OS::strcpy (pers_value, value.fast_rep ());
- ACE_Configuration_ExtId item_name (pers_name);
- ACE_Configuration_Value_IntId item_value (pers_value);
+ ACE_Configuration_ExtId item_name(pers_name);
+ ACE_Configuration_Value_IntId item_value(pers_value);
if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
{
allocator_->free (pers_value);
@@ -1734,28 +1692,27 @@ ACE_Configuration_Heap::set_integer_value (const ACE_Configuration_Section_Key&
return -1;
// Find this section
- ACE_Configuration_ExtId section_ext (section.fast_rep ());
+ ACE_Configuration_ExtId section_ext(section.fast_rep ());
ACE_Configuration_Section_IntId section_int;
if (index_->find (section_ext, section_int, allocator_))
return -2; // section does not exist
// Get the entry for this item (if it exists)
VALUE_ENTRY* entry;
- ACE_Configuration_ExtId item_name (name);
- if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ ACE_Configuration_ExtId item_name(name);
+ if(section_int.value_hash_map_->VALUE_HASH::find(item_name, entry) == 0)
{
// found item, replace it
- ACE_Configuration_Value_IntId new_value_int (value);
+ ACE_Configuration_Value_IntId new_value_int(value);
entry->int_id_ = new_value_int;
}
else
{
// it doesn't exist, bind it
- ACE_TCHAR* pers_name =
- (ACE_TCHAR*) allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
+ ACE_TCHAR* pers_name = (ACE_TCHAR*)allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
ACE_OS::strcpy (pers_name, name);
- ACE_Configuration_ExtId item_name (pers_name);
- ACE_Configuration_Value_IntId item_value (value);
+ ACE_Configuration_ExtId item_name(pers_name);
+ ACE_Configuration_Value_IntId item_value(value);
if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
{
allocator_->free (pers_name);
@@ -1789,28 +1746,27 @@ ACE_Configuration_Heap::set_binary_value (const ACE_Configuration_Section_Key& k
// Get the entry for this item (if it exists)
VALUE_ENTRY* entry;
- ACE_Configuration_ExtId item_name (name);
- if (section_int.value_hash_map_->VALUE_HASH::find (item_name, entry) == 0)
+ ACE_Configuration_ExtId item_name(name);
+ if(section_int.value_hash_map_->VALUE_HASH::find(item_name, entry) == 0)
{
// found item, replace it
// Free the old value
- entry->int_id_.free (allocator_);
+ entry->int_id_.free(allocator_);
// Allocate the new value in this heap
- ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
ACE_OS::memcpy (pers_value, data, length);
- ACE_Configuration_Value_IntId new_value_int (pers_value, length);
+ ACE_Configuration_Value_IntId new_value_int(pers_value, length);
entry->int_id_ = new_value_int;
}
else
{
// it doesn't exist, bind it
- ACE_TCHAR* pers_name =
- (ACE_TCHAR*) allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
+ ACE_TCHAR* pers_name = (ACE_TCHAR*)allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
ACE_OS::strcpy (pers_name, name);
- ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
ACE_OS::memcpy (pers_value, data, length);
- ACE_Configuration_ExtId item_name (pers_name);
- ACE_Configuration_Value_IntId item_value (pers_value, length);
+ ACE_Configuration_ExtId item_name(pers_name);
+ ACE_Configuration_Value_IntId item_value(pers_value, length);
if (section_int.value_hash_map_->bind (item_name, item_value, allocator_))
{
allocator_->free (pers_value);
@@ -1833,10 +1789,9 @@ ACE_Configuration_Heap::set_binary_value (const ACE_Configuration_Section_Key& k
if (IntId.value_hash_map_->find (VExtIdFind, VIntIdFind, allocator_))
{
// it doesn't exist, bind it
- ACE_TCHAR* pers_name =
- (ACE_TCHAR*) allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
+ ACE_TCHAR* pers_name = (ACE_TCHAR*)allocator_->malloc ((ACE_OS::strlen (name) + 1) * sizeof (ACE_TCHAR));
ACE_OS::strcpy (pers_name, name);
- ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
ACE_OS::memcpy (pers_value, data, length);
ACE_Configuration_ExtId VExtId (pers_name);
ACE_Configuration_Value_IntId VIntId (pers_value, length);
@@ -1853,7 +1808,7 @@ ACE_Configuration_Heap::set_binary_value (const ACE_Configuration_Section_Key& k
// it does exist, free the old value memory
VIntIdFind.free (allocator_);
// Assign a new value
- ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
+ ACE_TCHAR* pers_value = (ACE_TCHAR*)allocator_->malloc (length);
ACE_OS::memcpy (pers_value, data, length);
VIntIdFind = ACE_Configuration_Value_IntId (pers_value, length);
}
@@ -1926,7 +1881,7 @@ ACE_Configuration_Heap::get_integer_value (const ACE_Configuration_Section_Key&
return -4;
// Everythings ok, return the data
- value = (u_int) ((long)VIntId.data_);
+ value = (u_int)((long)VIntId.data_);
return 0;
}
@@ -1968,7 +1923,7 @@ ACE_Configuration_Heap::get_binary_value (const ACE_Configuration_Section_Key& k
}
int
-ACE_Configuration_Heap::find_value (const ACE_Configuration_Section_Key& key,
+ACE_Configuration_Heap::find_value(const ACE_Configuration_Section_Key& key,
const ACE_TCHAR* name,
VALUETYPE& type_out)
{
@@ -1989,7 +1944,7 @@ ACE_Configuration_Heap::find_value (const ACE_Configuration_Section_Key& key,
// Find it
ACE_Configuration_ExtId ValueExtId (name);
VALUE_ENTRY* value_entry;
- if (( (VALUE_HASH*)IntId.value_hash_map_)->find (ValueExtId, value_entry))
+ if (((VALUE_HASH*)IntId.value_hash_map_)->find (ValueExtId, value_entry))
return -1; // value does not exist
type_out = value_entry->int_id_.type_;
@@ -2018,7 +1973,7 @@ ACE_Configuration_Heap::remove_value (const ACE_Configuration_Section_Key& key,
// Find it
ACE_Configuration_ExtId ValueExtId (name);
VALUE_ENTRY* value_entry;
- if (( (VALUE_HASH*)IntId.value_hash_map_)->find (ValueExtId, value_entry))
+ if (((VALUE_HASH*)IntId.value_hash_map_)->find (ValueExtId, value_entry))
return -4;
// free it
@@ -2031,103 +1986,3 @@ ACE_Configuration_Heap::remove_value (const ACE_Configuration_Section_Key& key,
return 0;
}
-
-int
-ACE_Configuration::import_config_as_strings (const ACE_TCHAR* filename)
-{
- FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
- if (!in)
- return -1;
-
- // @@ Make this a dynamic size!
- ACE_TCHAR buffer[4096];
- ACE_Configuration_Section_Key section;
- while (ACE_OS::fgets (buffer, sizeof buffer, in))
- {
- // Check for a comment and blank line
- if (buffer[0] == ACE_LIB_TEXT (';')
- || buffer[0] == ACE_LIB_TEXT ('#')
- || buffer[0] == ACE_LIB_TEXT ('\r')
- || buffer[0] == ACE_LIB_TEXT ('\n'))
- continue;
-
- if (buffer[0] == ACE_LIB_TEXT ('['))
- {
- // We have a new section here, strip out the section name
- ACE_TCHAR* end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
- if (!end)
- {
- ACE_OS::fclose (in);
- return -3;
- }
- *end = 0;
-
- if (expand_path (root_, buffer + 1, section, 1))
- {
- ACE_OS::fclose (in);
- return -3;
- }
-
- continue;
- }
-
- // we have a line
- const ACE_TCHAR *name = this->skip_whitespace (buffer);
- if (name)
- {
- ACE_TCHAR *end = (ACE_TCHAR *) ACE_OS::strpbrk (name, ACE_LIB_TEXT ("= \t\n\r"));
-
- // locate equal sign after name and retrieve value
- const ACE_TCHAR *value = ACE_OS::strrchr (name, ACE_LIB_TEXT ('='));
- if (value)
- {
- value++; // jump over equal sign
- value = this->skip_whitespace (value);
- ACE_TCHAR *value_end;
- if (value[0] != ACE_LIB_TEXT ('"'))
- value_end = (ACE_TCHAR *) ACE_OS::strpbrk (value, ACE_LIB_TEXT (" \t\n\r"));
- else
- {
- // double quote delimited allows spaces and tabs in string
- value++;
- value_end = (ACE_TCHAR *) ACE_OS::strpbrk (value, ACE_LIB_TEXT ("\"\n\r"));
- }
- if (value_end)
- *value_end = '\0'; // terminate value
- }
- else
- value = ACE_LIB_TEXT ("");
-
- if (end)
- *end = '\0'; // terminate name now
-
- if (set_string_value (section, name, value))
- {
- ACE_OS::fclose (in);
- return -4;
- }
- }
- }
-
- if (ferror (in))
- {
- ACE_OS::fclose (in);
- return -1;
- }
-
- ACE_OS::fclose (in);
- return 0;
-}
-
-const ACE_TCHAR *
-ACE_Configuration::skip_whitespace (const ACE_TCHAR *src)
-{
- const ACE_TCHAR *cp;
-
- for (cp = src;
- (*cp != '\0') && ((*cp == ' ') || (*cp == '\t'));
- cp++)
- continue;
-
- return cp;
-}
diff --git a/ace/Configuration.h b/ace/Configuration.h
index ce57eb228c3..f08dc87b96a 100644
--- a/ace/Configuration.h
+++ b/ace/Configuration.h
@@ -6,7 +6,7 @@
*
* $Id$
*
- * @author Chris Hafey <chafey@stentor.com>
+ * @author Chris Hafey <chris@stentorsoft.com>
*
* The ACE configuration API provides a portable abstraction for
* program configuration. The API supports a tree based hierarchy
@@ -14,15 +14,6 @@
* or values. Values may contain string, unsigned integer and
* binary data.
*
- * @todo
- * - Redo the import/export mechanism to support different file formats
- * - Add locking for thread safety.
- * - Need to investigate what happens if memory mapped file gets mapped to
- * a location different than it was created with.
- * - Add dynamic buffer when importing. currently it will not allow
- * importing of values greater than a fixed ammount (4096 bytes)
- * - Replace unsigned int with a type that is fixed accross platforms.
- *
*/
//=============================================================================
@@ -59,6 +50,11 @@
* Implementations subclass this base class to represent a
* section key.
*
+ * @todo
+ * - Add locking for thread safety.
+ * - Need to investigate what happens if memory mapped file gets mapped to
+ * a location different than it was created with.
+ * - Replace unsigned int with a type that is fixed accross platforms.
*
*/
class ACE_Export ACE_Section_Key_Internal
@@ -80,15 +76,15 @@ protected:
u_int ref_count_;
};
- /**
- * @class ACE_Configuration_Section_Key
- *
- * @brief Referenced 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_Configuration_Section_Key
+ *
+ * @brief Referenced 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;
@@ -133,11 +129,6 @@ public:
INVALID
};
- enum {
- /// Max size of name.
- MAX_NAME_LEN = 255
- };
-
/// destructor
virtual ~ACE_Configuration (void);
@@ -233,9 +224,10 @@ public:
* data type in <type>. Returns 0 on success (entry is found),
* -1 on error
*/
- virtual int find_value (const ACE_Configuration_Section_Key& key,
- const ACE_TCHAR* name,
- VALUETYPE& type) = 0;
+ virtual int find_value(const ACE_Configuration_Section_Key& key,
+ const ACE_TCHAR* name,
+ VALUETYPE& type) = 0;
+
/// Removes the the value <name> from <key>. returns non zero on
/// error.
@@ -253,76 +245,41 @@ public:
ACE_Configuration_Section_Key& key_out,
int create = 1);
+ /**
+ * Determine if the contents of this object is the same as the
+ * contents of the object on the right hand side.
+ * Returns 1 (True) if they are equal and 0 (False) if they are not equal
+ */
+ int operator==(const ACE_Configuration& rhs) const;
- /// Exports the configuration database to filename. If <filename> is
- /// alredy present, it is overwritten. * See note below
- virtual int export_config (const ACE_TCHAR* filename);
-
- /// Imports the configuration database from filename. Any existing
- /// data is not removed. * See note below
- virtual int import_config (const ACE_TCHAR* filename);
-
- /// Imports the configuration database from filename as strings.
- /// Allows non-typed values. (no #, dword: hex:, etc. prefixes) and
- /// skips whitespace (tabs and spaces) as in standard .ini and .conf
- /// files. Values (to right of equal sign) can be double quote
- /// delimited to embed tabs and spaces in the string.
- /// Caller must convert string to type.
- /// A corresponding export_config is not supported.
- ///
- /// This method allows for lines in the .ini or .conf file like this:
- ///
- /// TimeToLive = 100
- /// Delay = FALSE
- /// Flags = FF34
- /// Heading = "ACE - Adaptive Communication Environment"
- ///
- /// (note leading whitespace (tabs) in examples below)
- ///
- /// SeekIndex = 14
- /// TraceLevel = 6 # Can comment lines like this
- /// Justification = left_justified
- ///
- /// The caller can then retrieve the string with the regular
- /// <get_string_value> function and convert the string to the
- /// desired data type.
-
- virtual int import_config_as_strings (const ACE_TCHAR *filename);
-
- // Note - The above import/export routines have the following bugs/limitations
- // 1) Strings with embedded newlines cause the import to fail
- // 2) Strings with embedded quotes " cause the import to fail
- // 3) Importing/exporting for values in the root section does not work
- // If you are interested in working on this, please let me know and we can
- // discuss the details. chafey@stentor.com
+ /**
+ * Determine if the contents of this object are different from the
+ * contents of the object on the right hand side.
+ * Returns 0 (False) if they are equal and 1 (True) if they are not equal
+ */
+ int operator!=(const ACE_Configuration& rhs) const {return !(*this == rhs);}
protected:
/// Default ctor
ACE_Configuration (void);
- /// Skips whitespace
- const ACE_TCHAR *skip_whitespace (const ACE_TCHAR *src);
-
/// resolves the internal key from a section key
ACE_Section_Key_Internal* get_internal_key
(const ACE_Configuration_Section_Key& key);
/**
- * tests to see if <name> is valid. <name> must be < MAX_NAME_LEN characters
+ * tests to see if <name> is valid. <name> must be < 255 characters
* and not contain the path separator '\', brackets [] or = (maybe
* just restrict to alphanumeric?) returns non zero if name is not
* valid
*/
int validate_name (const ACE_TCHAR* name);
- /// Used when exporting a configuration to a file
- int export_section (const ACE_Configuration_Section_Key& section,
- const ACE_TString& path,
- FILE* out);
-
// Not used
ACE_Configuration (const ACE_Configuration& rhs);
ACE_Configuration& operator= (const ACE_Configuration& rhs);
+
+
ACE_Configuration_Section_Key root_;
};
@@ -439,6 +396,9 @@ public:
const ACE_TCHAR* path,
int create = 1);
+ virtual int operator==(const ACE_Configuration_Win32Registry& rhs) const{return true;}
+ virtual int operator!=(const ACE_Configuration_Win32Registry& rhs) const{return true;}
+
protected:
/// Gets the HKEY for a configuration section
@@ -766,7 +726,6 @@ private:
ACE_Allocator *allocator_;
SECTION_MAP *index_;
int default_map_size_;
- int persistent_;
};
#include "ace/post.h"
diff --git a/ace/Configuration_Import_Export.cpp b/ace/Configuration_Import_Export.cpp
new file mode 100644
index 00000000000..dd0329e3108
--- /dev/null
+++ b/ace/Configuration_Import_Export.cpp
@@ -0,0 +1,552 @@
+// $Id$
+
+#include "ConfigImpExpFiles.h"
+
+ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration& config)
+ : config_ (config)
+{
+}
+
+ACE_Config_ImpExp_Base::~ACE_Config_ImpExp_Base ()
+{
+}
+
+ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration& config)
+ : ACE_Config_ImpExp_Base (config)
+{
+}
+
+ACE_Registry_ImpExp::~ACE_Registry_ImpExp ()
+{
+}
+
+// Imports the configuration database from filename.
+// No existing data is removed.
+// Since the open method relies on this method, this method
+// acts as open if an open has not already occurred.
+
+int
+ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
+{
+ FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
+ if (!in)
+ return -1;
+
+ // @@ XXX - change this to a dynamic buffer
+ ACE_TCHAR buffer[4096];
+ ACE_Configuration_Section_Key section;
+ while (ACE_OS::fgets (buffer, 4096, in))
+ {
+ // Check for a comment
+ if (buffer[0] == ACE_LIB_TEXT (';') || buffer[0] == ACE_LIB_TEXT ('#'))
+ continue;
+
+ if (buffer[0] == ACE_LIB_TEXT ('['))
+ {
+ // We have a new section here, strip out the section name
+ ACE_TCHAR* end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ continue;
+ }
+
+ if (buffer[0] == ACE_LIB_TEXT ('"'))
+ {
+ // we have a value
+ ACE_TCHAR* end = ACE_OS::strchr (buffer+1, '"');
+ if (!end) // no closing quote, not a value so just skip it
+ continue;
+
+ // null terminate the name
+ *end = 0;
+ ACE_TCHAR* name = buffer + 1;
+ end+=2;
+ // determine the type
+ if (*end == '\"')
+ {
+ // string type
+ // truncate trailing "
+ ++end;
+ ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
+ if (trailing)
+ *trailing = 0;
+ if (config_.set_string_value (section, name, end))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("dword:"), 6) == 0)
+ {
+ // number type
+ ACE_TCHAR* endptr = 0;
+ u_int value = ACE_OS::strtoul (end + 6, &endptr, 16);
+ if (config_.set_integer_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("hex:"), 4) == 0)
+ {
+ // binary type
+ u_int string_length = ACE_OS::strlen (end + 4);
+ // divide by 3 to get the actual buffer length
+ u_int length = string_length / 3;
+ u_int remaining = length;
+ u_char* data = new u_char[length];
+ u_char* out = data;
+ ACE_TCHAR* inb = end + 4;
+ ACE_TCHAR* endptr = 0;
+ while (remaining)
+ {
+ u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
+ *out = charin;
+ ++out;
+ --remaining;
+ inb += 3;
+ }
+ if (config_.set_binary_value (section, name, data, length))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ }
+ else
+ {
+ // invalid type, ignore
+ continue;
+ }
+ }
+ }
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ return 0;
+}
+
+// This method exports the entire configuration database to <filename>. If
+// <filename> is NULL (the default), data is persisted to the <filename>
+// provided to 'open'. If the internal filename is empty this method
+// returns -1. Once the file is opened this method calls 'export_section'
+// passing the root section.
+
+int
+ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ int result = -1;
+
+ FILE* out = ACE_OS::fopen (filename, ACE_LIB_TEXT ("w"));
+ if (out)
+ {
+ result = this->export_section (config_.root_section (),
+ ACE_LIB_TEXT (""),
+ out);
+ ACE_OS::fclose (out);
+ }
+ return result;
+}
+
+// Method provided by derived classes in order to write one section
+// to the file specified. Called by export_config when exporting
+// the entire configuration object.
+
+int
+ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out)
+{
+ // don't export the root
+ if (path.length ())
+ {
+ // Write out the section header
+ ACE_TString header = ACE_LIB_TEXT ("[");
+ header += path;
+ header += ACE_LIB_TEXT ("]");
+ header += ACE_LIB_TEXT (" \n");
+ if (ACE_OS::fputs (header.fast_rep (), out) < 0)
+ return -1;
+ // Write out each value
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration::VALUETYPE type;
+ ACE_TString line;
+ ACE_TCHAR int_value[32];
+ ACE_TCHAR bin_value[3];
+ void* binary_data;
+ u_int binary_length;
+ ACE_TString string_value;
+ while (!config_.enumerate_values (section, index, name, type))
+ {
+ line = ACE_LIB_TEXT ("\"") + name + ACE_LIB_TEXT ("\"=");
+ switch (type)
+ {
+ case ACE_Configuration::INTEGER:
+ {
+ u_int value;
+ if (config_.get_integer_value (section, name.fast_rep (), value))
+ return -2;
+ ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), value);
+ line += ACE_LIB_TEXT ("dword:");
+ line += int_value;
+ break;
+ }
+ case ACE_Configuration::STRING:
+ {
+ if (config_.get_string_value (section,
+ name.fast_rep (),
+ string_value))
+ return -2;
+ line += ACE_LIB_TEXT ("\"");
+ line += string_value + ACE_LIB_TEXT ("\"");
+ break;
+ }
+#ifdef _WIN32
+ case ACE_Configuration::INVALID:
+ break; // JDO added break. Otherwise INVALID is processed
+ // like BINARY. If that's correct, please remove the
+ // break and these comments
+#endif
+ case ACE_Configuration::BINARY:
+ {
+ // not supported yet - maybe use BASE64 codeing?
+ if (config_.get_binary_value (section,
+ name.fast_rep (),
+ binary_data,
+ binary_length))
+ return -2;
+ line += ACE_LIB_TEXT ("hex:");
+ unsigned char* ptr = (unsigned char*)binary_data;
+ while (binary_length)
+ {
+ if (ptr != binary_data)
+ {
+ line += ACE_LIB_TEXT (",");
+ }
+ ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
+ line += bin_value;
+ --binary_length;
+ ++ptr;
+ }
+ delete (char *)binary_data;
+ break;
+ }
+ default:
+ return -3;
+ }
+ line += ACE_LIB_TEXT ("\n");
+ if (ACE_OS::fputs (line.fast_rep (), out) < 0)
+ return -4;
+ index++;
+ }
+ }
+ // Export all sub sections
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration_Section_Key sub_key;
+ ACE_TString sub_section;
+ while (!config_.enumerate_sections (section, index, name))
+ {
+ ACE_TString sub_section (path);
+ if (path.length ())
+ sub_section += ACE_LIB_TEXT ("\\");
+ sub_section += name;
+ if (config_.open_section (section, name.fast_rep (), 0, sub_key))
+ return -5;
+ if (export_section (sub_key, sub_section.fast_rep (), out))
+ return -6;
+ index++;
+ }
+ return 0;
+}
+
+ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration& config)
+ : ACE_Config_ImpExp_Base (config)
+{
+}
+
+ACE_Ini_ImpExp::~ACE_Ini_ImpExp (void)
+{
+}
+
+// Method to read file and populate object.
+int
+ACE_Ini_ImpExp::import_config (const ACE_TCHAR* fileName)
+{
+ FILE* in = ACE_OS::fopen (fileName, ACE_LIB_TEXT ("r"));
+ if (!in)
+ return -1;
+
+ // @@ Make this a dynamic size!
+ ACE_TCHAR buffer[4096];
+ ACE_Configuration_Section_Key section;
+ while (ACE_OS::fgets (buffer, sizeof buffer, in))
+ {
+ // Check for a comment and blank line
+ if (buffer[0] == ACE_LIB_TEXT (';') ||
+ buffer[0] == ACE_LIB_TEXT ('#') ||
+ buffer[0] == ACE_LIB_TEXT ('\r') ||
+ buffer[0] == ACE_LIB_TEXT ('\n'))
+ continue;
+
+ if (buffer[0] == ACE_LIB_TEXT ('['))
+ {
+ // We have a new section here, strip out the section name
+ ACE_TCHAR* end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+
+ continue;
+ }
+
+ // we have a line
+ const ACE_TCHAR *name = this->skip_whitespace (buffer);
+ if (name)
+ {
+ ACE_TCHAR *end = (ACE_TCHAR *) ACE_OS::strpbrk (name, ACE_LIB_TEXT ("= \t\n\r"));
+
+ // locate equal sign after name and retrieve value
+ const ACE_TCHAR *value = ACE_OS::strrchr (name, ACE_LIB_TEXT ('='));
+ if (value)
+ {
+ value++; // jump over equal sign
+ value = this->skip_whitespace (value);
+ ACE_TCHAR *value_end;
+ if (value[0] != ACE_LIB_TEXT ('"'))
+ value_end = (ACE_TCHAR *) ACE_OS::strpbrk (value, ACE_LIB_TEXT (" \t\n\r"));
+ else
+ {
+ // double quote delimited allows spaces and tabs in string
+ value++;
+ value_end = (ACE_TCHAR *) ACE_OS::strpbrk (value, ACE_LIB_TEXT ("\"\n\r"));
+ }
+ if (value_end)
+ *value_end = '\0'; // terminate value
+ }
+ else
+ value = ACE_LIB_TEXT ("");
+
+ if (end)
+ *end = '\0'; // terminate name now
+
+ if (config_.set_string_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ }
+ }
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ return 0;
+}
+
+// This method exports the entire configuration database to
+// <filename>. If <filename> is NULL (the default), data is persisted
+// to the <filename> provided to 'open'. If the internal filename is
+// empty this method returns -1. Once the file is opened this method
+// calls 'export_section' passing the root section.
+
+int
+ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ int result = -1;
+
+ FILE* out = ACE_OS::fopen (filename, ACE_LIB_TEXT ("w"));
+ if (out)
+ {
+ result = this->export_section (config_.root_section (), ACE_LIB_TEXT (""), out);
+ ACE_OS::fclose (out);
+ }
+ return result;
+}
+
+// Method provided by derived classes in order to write one section to the
+// file specified. Called by export_config when exporting the entire
+// configuration objet
+
+int
+ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out)
+{
+ // don't export the root
+ if (path.length ())
+ {
+ // Write out the section header
+ ACE_TString header = ACE_LIB_TEXT ("[");
+ header += path;
+ header += ACE_LIB_TEXT ("]");
+ header += ACE_LIB_TEXT (" \n");
+ if (ACE_OS::fputs (header.fast_rep (), out) < 0)
+ return -1;
+ // Write out each value
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration::VALUETYPE type;
+ ACE_TString line;
+ ACE_TCHAR int_value[32];
+ ACE_TCHAR bin_value[3];
+ void* binary_data;
+ u_int binary_length;
+ ACE_TString string_value;
+ while (!config_.enumerate_values (section, index, name, type))
+ {
+ line = name + ACE_LIB_TEXT ("=");
+ switch (type)
+ {
+ case ACE_Configuration::INTEGER:
+ {
+ u_int value;
+ if (config_.get_integer_value (section, name.fast_rep (), value))
+ return -2;
+ ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), value);
+ line += int_value;
+ break;
+ }
+ case ACE_Configuration::STRING:
+ {
+ if (config_.get_string_value (section,
+ name.fast_rep (),
+ string_value))
+ return -2;
+ if (string_has_white_space (string_value.c_str ()))
+ {
+ line += ACE_LIB_TEXT ("\"");
+ line += string_value + ACE_LIB_TEXT ("\"");
+ }
+ else
+ {
+ line += string_value;
+ }
+ break;
+ }
+#ifdef _WIN32
+ case ACE_Configuration::INVALID:
+ break; // JDO added break. Otherwise INVALID is processed
+ // like BINARY. If that's correct, please remove the
+ // break and these comments
+#endif
+ case ACE_Configuration::BINARY:
+ {
+ // not supported yet - maybe use BASE64 codeing?
+ if (config_.get_binary_value (section,
+ name.fast_rep (),
+ binary_data,
+ binary_length))
+ return -2;
+ line += ACE_LIB_TEXT ("\"");
+ unsigned char* ptr = (unsigned char*)binary_data;
+ while (binary_length)
+ {
+ if (ptr != binary_data)
+ {
+ line += ACE_LIB_TEXT (",");
+ }
+ ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
+ line += bin_value;
+ --binary_length;
+ ++ptr;
+ }
+ line += ACE_LIB_TEXT ("\"");
+ delete (char *)binary_data;
+ break;
+ }
+ default:
+ return -3;
+
+ }// end switch on type
+
+ line += ACE_LIB_TEXT ("\n");
+ if (ACE_OS::fputs (line.fast_rep (), out) < 0)
+ return -4;
+ index++;
+ }// end while enumerating values
+ }
+ // Export all sub sections
+ int index = 0;
+ ACE_TString name;
+ ACE_Configuration_Section_Key sub_key;
+ ACE_TString sub_section;
+ while (!config_.enumerate_sections (section, index, name))
+ {
+ ACE_TString sub_section (path);
+ if (path.length ())
+ sub_section += ACE_LIB_TEXT ("\\");
+ sub_section += name;
+ if (config_.open_section (section, name.fast_rep (), 0, sub_key))
+ return -5;
+ if (export_section (sub_key, sub_section.fast_rep (), out))
+ return -6;
+ index++;
+ }
+ return 0;
+
+}
+
+// Method to skip whitespaces in a string. Whitespace is defined as:
+// spaces (' ') and tabs ('\t'). Returns a pointer to the first
+// non-whitespace character in the buffer provided. It does return
+// null ('\0') if it is reached
+
+const ACE_TCHAR *
+ACE_Ini_ImpExp::skip_whitespace (const ACE_TCHAR *src)
+{
+ const ACE_TCHAR *cp;
+
+ for (cp = src;
+ (*cp != '\0') && ((*cp == ' ') || (*cp == '\t'));
+ cp++)
+ continue;
+
+ return cp;
+}
+
+// Looks in provided string for whitespace. Whitespace is defined as
+// spaces (' ') and tabs ('\t'). Returns true if found and false if
+// not found
+
+int
+ACE_Ini_ImpExp::string_has_white_space (const ACE_TCHAR *string_value)
+{
+ bool rc = false;
+ while ((!rc) && (*string_value != '\0'))
+ {
+ if ((*string_value == ' ') || (*string_value == '\t'))
+ rc = true;
+
+ string_value++;
+ }
+ return rc;
+}
diff --git a/ace/Configuration_Import_Export.h b/ace/Configuration_Import_Export.h
new file mode 100644
index 00000000000..460bb2bc30c
--- /dev/null
+++ b/ace/Configuration_Import_Export.h
@@ -0,0 +1,225 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file: Configuration_Import_Export.h
+ *
+ * $Id$
+ *
+ * @author Jerry D. Odenwelder Jr. <jerry.o@mindspring.com>
+ * Chris Hafey <chris@stentorsoft.com>
+ *
+ * Classes defined in this file provide the ability to import and export
+ * ACE Configuration objects to/from disk files. The base class
+ * ACE_Config_ImpExp_Base provides the common functionality and the derived
+ * classes implement the import/export functionality for the specific format.
+ *
+ * @todo
+ * - Add locking for thread safety.
+ * - Provide ability to read file in one format and write in another.
+ * - See todo's in each class
+ */
+//=============================================================================
+
+#ifndef ACE_CONFIGURATION_IMPORT_EXPORT_H
+#define ACE_CONFIGURATION_IMPORT_EXPORT_H
+#include "ace/pre.h"
+
+#include "ace/Configuration.h"
+#include "ace/SString.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/**
+ * @class ACE_Config_ImpExp_Base
+ *
+ * @brief Base class for file import/export configuration.
+ *
+ * This class provides base functionality for configuration objects
+ * that are persisted in files. It takes an ACE_Configuration
+ * object that it populates with the data read.
+ *
+ */
+class ACE_Export ACE_Config_ImpExp_Base
+{
+public:
+ /// ctor taking the ACE_Configuration to import/export to
+ ACE_Config_ImpExp_Base(ACE_Configuration& config);
+
+ /**
+ * Destructor
+ */
+ virtual ~ACE_Config_ImpExp_Base();
+
+ /**
+ * Imports the configuration database from filename.
+ * No existing data is removed.
+ * Since the open method relies on this method, this method
+ * acts as open if an open has not already occurred.
+ */
+ virtual int import_config(const ACE_TCHAR* filename) = 0;
+
+ /**
+ * This method exports the entire configuration database to <filename>.
+ * If <filename> is NULL (the default), data is persisted to the
+ * <filename> provided to 'open'. If the internal filename is empty
+ * this method returns -1. Once the file is opened this method calls
+ * 'export_section' passing the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename) = 0;
+
+protected:
+ ACE_Configuration& config_;
+
+private:
+ ACE_Config_ImpExp_Base (const ACE_Config_ImpExp_Base&);
+ ACE_Config_ImpExp_Base& operator= (const ACE_Config_ImpExp_Base&);
+};
+
+/**
+ * @class ACE_Registry_ImpExp
+ *
+ * @brief Configuration object that imports/exports data to a file formatted
+ * using the Win32 Registry file export format. This format looks like
+ * [Section]
+ * "key"="String Data"
+ * "key"=dword: numeric data
+ * "key"=hex: binary data
+ *
+ * @todo
+ * - Add dynamic buffer when importing. currently it will not allow
+ * importing of values greater than a fixed ammount (4096 bytes)
+ *
+ */
+class ACE_Export ACE_Registry_ImpExp : public ACE_Config_ImpExp_Base
+{
+public:
+ /// Construction
+ ACE_Registry_ImpExp(ACE_Configuration&);
+
+ /// Destruction.
+ virtual ~ACE_Registry_ImpExp(void);
+
+ /**
+ * Imports the configuration database from filename.
+ * No existing data is removed.
+ * Since the open method relies on this method, this method
+ * acts as open if an open has not already occurred.
+ */
+ virtual int import_config(const ACE_TCHAR* filename);
+
+ /**
+ * This method exports the entire configuration database to <filename>.
+ * If <filename> is NULL (the default), data is persisted to the
+ * <filename> provided to 'open'. If the internal filename is empty
+ * this method returns -1. Once the file is opened this method calls
+ * 'export_section' passing the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename);
+
+private:
+ int export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out);
+
+ ACE_Registry_ImpExp( const ACE_Registry_ImpExp&);
+ ACE_Registry_ImpExp& operator=( const ACE_Registry_ImpExp&);
+};
+
+/**
+ * @class ACE_Ini_ImpExp
+ *
+ * @brief Imports the configuration database from filename as strings.
+ * Allows non-typed values. (no #, dword: hex:, etc. prefixes) and
+ * skips whitespace (tabs and spaces) as in standard .ini and .conf
+ * files. Values (to right of equal sign) can be double quote
+ * delimited to embed tabs and spaces in the string.
+ * Caller must convert string to type.
+ *
+ * This method allows for lines in the .ini or .conf file like this:
+ *
+ * TimeToLive = 100
+ * Delay = FALSE
+ * Flags = FF34
+ * Heading = "ACE - Adaptive Communication Environment"
+ *
+ * (note leading whitespace (tabs) in examples below)
+ *
+ * SeekIndex = 14
+ * TraceLevel = 6 # Can comment lines like this
+ * Justification = left_justified
+ *
+ * The caller can then retrieve the string with the regular
+ * <get_string_value> function and convert the string to the
+ * desired data type.
+ *
+ * @todo
+ * - Strings with embedded newlines cause the import to fail
+ * - Strings with embedded quotes " cause the import to fail
+ * - Importing/exporting for values in the root section does not work
+ * - Add dynamic buffer when importing. currently it will not allow
+ * importing of values greater than a fixed ammount (4096 bytes)
+*/
+class ACE_Export ACE_Ini_ImpExp : public ACE_Config_ImpExp_Base
+{
+public:
+ /**
+ * Construction
+ */
+ ACE_Ini_ImpExp(ACE_Configuration&);
+
+ /**
+ * Destructor
+ */
+ virtual ~ACE_Ini_ImpExp(void);
+
+ /**
+ * Imports the configuration database from filename.
+ * No existing data is removed.
+ * Since the open method relies on this method, this method
+ * acts as open if an open has not already occurred.
+ */
+ virtual int import_config(const ACE_TCHAR* filename);
+
+ /**
+ * This method exports the entire configuration database to <filename>.
+ * If <filename> is NULL (the default), data is persisted to the
+ * <filename> provided to 'open'. If the internal filename is empty
+ * this method returns -1. Once the file is opened this method calls
+ * 'export_section' passing the root section.
+ */
+ virtual int export_config (const ACE_TCHAR* filename);
+
+private:
+ /**
+ * Method provided by derived classes in order to write one section
+ * to the file specified. Called by export_config when exporting
+ * the entire configuration object.
+ */
+ int export_section (const ACE_Configuration_Section_Key& section,
+ const ACE_TString& path,
+ FILE* out);
+
+ /**
+ * Method to skip whitespaces in a string. Whitespace is defined as:
+ * spaces(' ') and tabs('\t').
+ * Returns a pointer to the first non-whitespace character in the
+ * buffer provided. It does return null ('\0') if it is reached
+ */
+ const ACE_TCHAR *skip_whitespace (const ACE_TCHAR *src);
+
+ /**
+ * Looks in provided string for whitespace. Whitespace is defined as
+ * spaces(' ') and tabs('\t').
+ * Returns true if found and false if not found
+ */
+ int string_has_white_space (const ACE_TCHAR *string_value);
+
+ ACE_Ini_ImpExp (const ACE_Ini_ImpExp&);
+ ACE_Ini_ImpExp& operator= (const ACE_Ini_ImpExp&);
+};
+
+#include "ace/post.h"
+#endif /* ACE_CONFIGURATION_IMPORT_EXPORT_H */
diff --git a/ace/Makefile b/ace/Makefile
index 6a7b3692ea1..9532a44f509 100644
--- a/ace/Makefile
+++ b/ace/Makefile
@@ -35,6 +35,7 @@ UTILS_FILES = \
Capabilities \
Containers \
Configuration \
+ Configuration_Import_Export \
Dirent \
Dynamic \
Dynamic_Service_Base \
diff --git a/tests/Config_Test.cpp b/tests/Config_Test.cpp
index 8d0b2ece0c5..a57c241555f 100644
--- a/tests/Config_Test.cpp
+++ b/tests/Config_Test.cpp
@@ -13,12 +13,15 @@
// <ACE_Configuration> work correctly.
//
// = AUTHOR
-// Michael Searles <msearles@base16.com> and Chris Hafey <chafey@stentor.com>
+// Michael Searles <msearles@base16.com>,
+// Chris Hafey <chafey@stentor.com>, and
+// Jerry D. Odenwelder Jr. <jerry.o@mindspring.com>
//
// ============================================================================
-#include "tests/test_config.h"
+#include "test_config.h"
#include "Config_Test.h"
+#include "ace/Configuration_Import_Export.h"
ACE_RCSID(tests, Config_Test, "$Id$")
@@ -59,7 +62,7 @@ test (ACE_Configuration *config)
u_char data[80];
- for(int i = 0; i < 80; i++)
+ for (int i = 0; i < 80; i++)
data[i] = i + 128;
if (config->set_binary_value (testsection,
@@ -92,12 +95,12 @@ test (ACE_Configuration *config)
if (config->get_binary_value (testsection,
ACE_TEXT ("binvalue"),
- (void*&) data_out,
+ (void*&) data_out,
length))
return -10;
// compare em
- for(int j = 0; j < 80; j++)
+ for (int j = 0; j < 80; j++)
if (data_out[j] != data[j])
return -11;
@@ -231,7 +234,7 @@ test_io (ACE_Configuration *config)
config->root_section ();
ACE_Configuration_Section_Key test;
- if (config->open_section(root,
+ if (config->open_section (root,
ACE_TEXT ("test"),
1,
test))
@@ -272,14 +275,6 @@ test_io (ACE_Configuration *config)
42))
return -8;
- // Export it to a file
- if(config->export_config (ACE_TEXT ("config.ini")))
- return -9;
- // reimport
-
- if (config->import_config (ACE_TEXT ("config.ini")))
- return -10;
-
return 0;
}
@@ -334,107 +329,815 @@ run_tests (void)
-1);
}
- // Test file i/o using a transient heap
- ACE_Configuration_Heap io_config;
- if (io_config.open ())
+ ACE_DEBUG ((LM_DEBUG, "Test passed\n"));
+ return 0;
+}
+
+static int
+build_config_object (ACE_Configuration& cfg)
+{
+ ACE_Configuration_Section_Key root = cfg.root_section ();
+ ACE_Configuration_Section_Key NetworkSection;
+ ACE_Configuration_Section_Key LoggerSection;
+ ACE_Configuration_Section_Key BinarySection;
+
+ if (cfg.open_section (root,
+ ACE_TEXT ("network"),
+ 1,
+ NetworkSection))
+ return -1;
+
+ if (cfg.set_integer_value (NetworkSection,
+ ACE_TEXT ("TimeToLive"),
+ 100))
return -2;
+ else if (cfg.set_string_value (NetworkSection,
+ ACE_TEXT ("Delay"),
+ ACE_TString ("FALSE")))
+ return -3;
+ else if (cfg.set_string_value (NetworkSection,
+ ACE_TEXT ("DestIPAddress"),
+ ACE_TString ("localhost")))
+ return -4;
+ else if (cfg.set_integer_value (NetworkSection,
+ ACE_TEXT ("DestPort"),
+ 12670))
+ return -5;
+ else if (cfg.set_integer_value (NetworkSection,
+ ACE_TEXT ("ReconnectInterval"),
+ 3))
+ return -6;
- int result = test_io (&io_config);
- if (result)
- ACE_ERROR_RETURN ((LM_ERROR,
- "IO Test Failed (%d)\n",
- result),
- -3);
+ if (cfg.open_section (root,
+ ACE_TEXT ("logger"),
+ 1,
+ LoggerSection))
+ return -7;
+
+
+ if (cfg.set_string_value (LoggerSection,
+ ACE_TEXT ("Heading"),
+ ACE_TString ("ACE - Adaptive Communication Environment")))
+ return -8;
+ else if (cfg.set_integer_value (LoggerSection,
+ ACE_TEXT ("SeekIndex"),
+ 14))
+ return -9;
+ else if (cfg.set_integer_value (LoggerSection,
+ ACE_TEXT ("TraceLevel"),
+ 6))
+ return -10;
+ else if (cfg.set_string_value (LoggerSection,
+ ACE_TEXT ("Justification"),
+ ACE_TString ("left_justified")))
+ return -11;
+ else if (cfg.set_string_value (LoggerSection,
+ ACE_TEXT ("LogFilePath"),
+ ACE_TString ("log/")))
+ return -12;
+ else if (cfg.set_string_value (LoggerSection,
+ ACE_TEXT ("TransactionFilePath"),
+ ACE_TString ("data/")))
+ return -13;
+
+ if (cfg.open_section (root,
+ ACE_TEXT ("binary"),
+ 1,
+ BinarySection))
+ return -14;
+
+ u_char data[80];
+
+ for (int i = 0; i < 80; i++)
+ data[i] = i + 128;
+
+ if (cfg.set_binary_value (BinarySection,
+ ACE_TEXT ("data"),
+ data,
+ 80))
+ return -15;
- ACE_DEBUG ((LM_DEBUG,
- "Test passed\n"));
return 0;
}
-void
-Config_Test::read_config (void)
+/*
+ * Test ACE_Configuration::operator==
+ */
+int
+Config_Test::testEquality ()
{
- if (m_ConfigurationHeap.open () == 0)
+ // create and open 2 ACE_Configuration objects.
+ ACE_Configuration_Heap heap1;
+ ACE_Configuration_Heap heap2;
+ if ((heap1.open ()) != 0)
{
- if (m_ConfigurationHeap.import_config_as_strings (ACE_TEXT ("Config_Test.ini")) == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open heap1\n"),
+ -1);
+
+ }
+ else if ((heap2.open ()) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open heap2\n"),
+ -1);
+ }
+
+ // populate them equally
+ build_config_object (heap1);
+ build_config_object (heap2);
+
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they do ;-)\n"));
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "And they do not :- (\nThe Equality Operator Failed when objects equal\n"),
+ -1);
+ }
+
+ // add a section and value to heap1
+ ACE_Configuration_Section_Key root1 = heap1.root_section ();
+ ACE_Configuration_Section_Key NewSection;
+ if (heap1.open_section (root1,
+ ACE_TEXT ("NewSection"),
+ 1,
+ NewSection))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding section to heap1\n"),
+ -1);
+ }
+ else if (heap1.set_integer_value (NewSection,
+ ACE_TEXT ("TestIntValue"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding value to heap1\n"),
+ -2);
+ }
+
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should NOT equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "They Do :- (\nThe Equality Operator Failed when lhs contains data not in rhs\n"),
+ -1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they do not ;-)\n"));
+ }
+
+ //
+ // add same section to heap2
+ //
+ ACE_Configuration_Section_Key root2 = heap2.root_section ();
+ ACE_Configuration_Section_Key NewSection2;
+ if (heap2.open_section (root2,
+ ACE_TEXT ("NewSection"),
+ 1,
+ NewSection2))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding section to heap2\n"),
+ -1);
+ }
+ else if (heap2.set_integer_value (NewSection2,
+ ACE_TEXT ("TestIntValue"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding value to heap2\n"),
+ -2);
+ }
+ else if (heap2.set_integer_value (NewSection2,
+ ACE_TEXT ("TestIntValue2"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding second value to heap2\n"),
+ -2);
+
+ }
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should NOT equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "And They Do :- (\nThe Equality Operator Failed when rhs contains value not in lhs\n"),
+ -1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they do not ;-)\n"));
+ }
+
+ // add new value in heap 1
+ if (heap1.set_integer_value (NewSection,
+ ACE_TEXT ("TestIntValue2"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding second value to heap1\n"),
+ -2);
+ }
+
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should be equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they are ;-)\n"));
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "And they are not :- (\nThe Equality Operator Failed\n"),
+ -1);
+ }
+
+ // Add a new section to heap2
+ ACE_Configuration_Section_Key AnotherNewSection2;
+ if (heap2.open_section (root2,
+ ACE_TEXT ("AnotherNewSection"),
+ 1,
+ AnotherNewSection2))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding second section to heap2\n"),
+ -1);
+ }
+ else if (heap2.set_integer_value (AnotherNewSection2,
+ ACE_TEXT ("TestIntValue"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding value in second section to heap2\n"),
+ -2);
+ }
+
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should NOT equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "And they do :- (\nThe Equality Operator Failed when rhs contains data not in lhs\n"),
+ -1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they do not :-)\n"));
+ }
+
+ // add section back to heap1
+ ACE_Configuration_Section_Key AnotherNewSection1;
+ if (heap1.open_section (root1,
+ ACE_TEXT ("AnotherNewSection"),
+ 1,
+ AnotherNewSection1))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding second section to heap1\n"),
+ -1);
+ }
+ else if (heap1.set_integer_value (AnotherNewSection1,
+ ACE_TEXT ("TestIntValue"),
+ 100))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error adding second value to second section in heap1\n"),
+ -2);
+ }
+
+ // test equality
+ ACE_DEBUG ((LM_DEBUG, "The objects should be equal...\n"));
+ if (heap1 == heap2)
+ {
+ ACE_DEBUG ((LM_DEBUG, "And they are ;-)\n"));
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "And they are not :-)\nThe Equality Operator Failed\n"),
+ -1);
+ }
+
+ this->equality_tested_ = 1;
+ return 0;
+}
+
+/*
+ * Compare INI import data in fromFile to origional data exported (in origional)
+ *
+ * This compare is destructive to the origional object.
+ * I realize that normally you would not do such an obscene thing but
+ * this funciton has a special purpose and I know my origional is not needed
+ * after calling this routine.
+ * This is done because configuration objects that are imported using the INI
+ * import store all data as strings. My origional has type information and I need to
+ * know if the import worked.
+*/
+static int
+iniCompare (ACE_Configuration_Heap& fromFile, ACE_Configuration_Heap& original)
+{
+ int rc = 1; // start by guessing they are equal
+
+ int sectionIndex = 0;
+ ACE_TString sectionName;
+
+ const ACE_Configuration_Section_Key& fromFileRoot = fromFile.root_section ();
+ const ACE_Configuration_Section_Key& originalRoot = original.root_section ();
+ ACE_Configuration_Section_Key originalSection;
+ ACE_Configuration_Section_Key fromFileSection;
+
+ // loop through each section in the fromFile object
+ while ((rc) &&
+ (!fromFile.enumerate_sections (fromFileRoot,
+ sectionIndex,
+ sectionName)) )
+ {
+ // find that section in the original object
+ if (original.open_section (originalRoot,
+ sectionName.c_str (),
+ 0,
+ originalSection) != 0)
+ {
+ // If the original object does not contain the section then we are not equal.
+ rc = 0;
+ }
+ else if (fromFile.open_section (fromFileRoot,
+ sectionName.c_str (),
+ 0,
+ fromFileSection) != 0)
{
- ACE_Configuration_Section_Key root = m_ConfigurationHeap.root_section ();
- // Process [network] section
- ACE_Configuration_Section_Key NetworkSection;
- if (m_ConfigurationHeap.open_section (root,
- ACE_TEXT ("network"),
- 1,
- NetworkSection) == 0)
+ // if there is some error opening the section in the fromFile
+ rc = 0;
+ }
+ else
+ {
+ // Well the sections match
+ int valueIndex = 0;
+ ACE_TString valueName;
+ ACE_Configuration::VALUETYPE valueType;
+ ACE_Configuration::VALUETYPE originalType;
+
+ // Enumerate each value in the fromFile section
+ while ((rc) &&
+ (!fromFile.enumerate_values (fromFileSection,
+ valueIndex,
+ valueName,
+ valueType)))
{
- this->get_section_integer (NetworkSection,
- ACE_TEXT ("TimeToLive"),
- &m_nTimeToLive,
- 1,
- 20);
- this->get_section_boolean (NetworkSection,
- ACE_TEXT ("Delay"),
- &m_bDelay);
- this->get_section_string (NetworkSection,
- ACE_TEXT ("DestIPAddress"),
- m_pszDestIPAddress,
- TEST_MAX_STRING);
- this->get_section_integer (NetworkSection,
- ACE_TEXT ("DestPort"),
- &m_nDestPort,
- 0,
- 65535);
- this->get_section_integer (NetworkSection,
- ACE_TEXT ("ReconnectInterval"),
- &m_nReconnectInterval,
- 0,
- 65535);
- }
-
- // Process [logger] section
- ACE_Configuration_Section_Key LoggerSection;
-
- if (m_ConfigurationHeap.open_section (root,
- ACE_TEXT ("logger"),
- 1,
- LoggerSection) == 0)
+ // look for the same value in the original section
+ if (original.find_value (originalSection,
+ valueName.c_str (),
+ originalType) != 0)
+ {
+ // We're not equal if the same value cannot
+ // be found in the original object.
+ rc = 0;
+ }
+ else
+ {
+ ACE_TString fromFileString, originalString;
+
+
+ if (fromFile.get_string_value (fromFileSection,
+ valueName.c_str (),
+ fromFileString) != 0)
+ {
+ // we're not equal if we cannot get this string
+ rc = 0;
+ }
+ else if (originalType != ACE_Configuration::STRING) // If the original type is not a string
+ {
+ // convert original data to a string.
+
+ if (originalType == ACE_Configuration::INTEGER)
+ {
+ u_int intValue;
+ ACE_TCHAR int_value[32];
+
+ if (original.get_integer_value (originalSection,
+ valueName.c_str (),
+ intValue) != 0)
+ {
+ // we're not equal if we cannot get rhs int
+ rc = 0;
+ }
+ ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), intValue);
+ originalString = int_value;
+ }
+ else if (originalType == ACE_Configuration::BINARY)
+ {
+
+ void* binary_data;
+ u_int binary_length;
+
+ if (original.get_binary_value (originalSection,
+ valueName.c_str (),
+ binary_data,
+ binary_length))
+ {
+ // we're not equal if we cannot get this string
+ rc = 0;
+ }
+ else
+ {
+ ACE_TCHAR bin_value[3];
+
+ unsigned char* ptr = (unsigned char*)binary_data;
+ while (binary_length)
+ {
+ if (ptr != binary_data)
+ {
+ originalString += ACE_LIB_TEXT (",");
+ }
+ ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
+ originalString += bin_value;
+ --binary_length;
+ ++ptr;
+ }
+ delete (char *)binary_data;
+ }// end successful binary read
+ }// end if originalType was binary
+ else
+ {
+ // if the type is invalid, then go ahead and fail it.
+ rc = 0;
+ }
+
+ }// end if the original type was not a string.
+ else
+ {
+ if (original.get_string_value (originalSection,
+ valueName.c_str (),
+ originalString) != 0)
+ {
+ // we're not equal if we cannot get rhs string
+ rc = 0;
+ }
+
+ }
+
+ rc &= fromFileString == originalString;
+
+ if (rc)
+ {
+ // before we move on remove this value from the original.
+ original.remove_value (originalSection,
+ valueName.c_str ());
+ }
+
+ }// end else if values match.
+
+ valueIndex++;
+
+ }// end value while loop
+
+ // at this point the original should have no values.
+ // look for values in the original section
+ valueIndex = 0;
+ while ((rc) &&
+ (!original.enumerate_values (originalSection,
+ valueIndex,
+ valueName,
+ originalType)))
{
- this->get_section_string (LoggerSection,
- ACE_TEXT ("Heading"),
- m_pszHeading,
- TEST_MAX_STRING);
- this->get_section_integer (LoggerSection,
- ACE_TEXT ("TraceLevel"),
- &m_nTraceLevel,
- 1,
- 20);
- this->get_section_string (LoggerSection,
- ACE_TEXT ("Justification"),
- m_pszJustification,
- TEST_MAX_STRING);
- this->get_section_string (LoggerSection,
- ACE_TEXT ("LogFilePath"),
- m_pszLogFilePath,
- TEST_MAX_STRING);
- this->get_section_string (LoggerSection,
- ACE_TEXT ("TransactionFilePath"),
- m_pszTransactionFilePath,
- TEST_MAX_STRING);
- }
+ valueIndex++;
+ }// end while for rhs values not in this.
+
+ // having a value indicates a mismatch
+ rc = valueIndex == 0;
+
+ }// end else if sections match.
+
+ if (rc)
+ {
+ // before we move on remove the section from the original.
+ original.remove_section (originalRoot,
+ sectionName.c_str (),
+ 0); // do not remove subsections.
+ }
+
+ sectionIndex++;
+
+ }// end section while loop
+
+ // Finally, if the original has any sections, then we're not equal
+ sectionIndex = 0;
+ while ((rc) &&
+ (!original.enumerate_sections (originalRoot,
+ sectionIndex,
+ sectionName)) )
+ {
+ sectionIndex++;
+ }
+
+ rc = sectionIndex == 0;
+
+ return rc;
+}
+
+// Used to test INI Import Export class
+
+int
+Config_Test::testIniFormat ()
+{
+ int rc = 0;
+ if (!this->equality_tested_)
+ {
+ if ((rc = this->testEquality ()) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Equality Test Failed\n"));
+ return rc;
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG, "Testing INI Format Import/Export\n"));
+ ACE_Configuration_Heap fromFile;
+
+ // 1. Creates an ACE_Configuration_Heap object
+ ACE_Configuration_Heap original;
+
+ if ((rc = original.open ()) == 0)
+ {
+ // 2. Calls build_config_object to populate
+ if ((rc = build_config_object (original)) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error populating original config object (%d)\n",
+ rc),
+ -1);
+ }
+
+ // 3. Export
+ ACE_Ini_ImpExp importExport (original);
+
+ if ((rc = importExport.export_config ("testConfig.ini")) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error Exporting (%d)\n",
+ rc),
+ -1);
+ }
+
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Could not open original object (%d)\n",
+ rc),
+ -1);
+ }
+
+
+ // At this point we've successfully created, populated and written
+ // the configuration object
+ // 5. Creates a new ACE_Configuration_Heap object
+ if ((rc = fromFile.open ()) == 0)
+ {
+ // 6. Imports
+ ACE_Ini_ImpExp importExport (fromFile);
+
+ if ((rc = importExport.import_config ("testConfig.ini")) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error Exporting (%d)\n",
+ rc),
+ -1);
+ }
+
+ // 7. Compares to original.
+ // This is a special compare since files imported using the
+ // INI file import do not contain type information
+ //
+ // NOTE: After this call the original object will be invalid!!!
+ //
+ if (!iniCompare (fromFile, original))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Object read from file does not equal original (%d)\n",
+ rc),
+ -1);
+
+ }
+ }// end if heap could not be opened.
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Could not open fromFile object (%d)\n",
+ rc),
+ -1);
+ }
+
+ // 8. Calls old "read_config" methods on the new object
+
+ int nTimeToLive;
+ int bDelay;
+ int nDestPort;
+ int nReconnectInterval;
+ int nTraceLevel;
+
+ ACE_TCHAR pszDestIPAddress[TEST_MAX_STRING];
+ ACE_TCHAR pszLogFilePath[TEST_MAX_STRING];
+ ACE_TCHAR pszTransactionFilePath[TEST_MAX_STRING];
+ ACE_TCHAR pszHeading[TEST_MAX_STRING];
+ ACE_TCHAR pszJustification[TEST_MAX_STRING];
+
+ ACE_Configuration_Section_Key root = fromFile.root_section ();
+
+ // Process [network] section
+ ACE_Configuration_Section_Key NetworkSection;
+ if (fromFile.open_section (root,
+ ACE_TEXT ("network"),
+ 1,
+ NetworkSection) == 0)
+ {
+ this->get_section_integer (fromFile,
+ NetworkSection,
+ ACE_TEXT ("TimeToLive"),
+ &nTimeToLive,
+ 1,
+ 20);
+
+ this->get_section_boolean (fromFile,
+ NetworkSection,
+ ACE_TEXT ("Delay"),
+ &bDelay);
+
+ this->get_section_string (fromFile,
+ NetworkSection,
+ ACE_TEXT ("DestIPAddress"),
+ pszDestIPAddress,
+ TEST_MAX_STRING);
+
+ this->get_section_integer (fromFile,
+ NetworkSection,
+ ACE_TEXT ("DestPort"),
+ &nDestPort,
+ 0,
+ 65535);
+
+ this->get_section_integer (fromFile,
+ NetworkSection,
+ ACE_TEXT ("ReconnectInterval"),
+ &nReconnectInterval,
+ 0,
+ 65535);
+ }// end of "network" section
+
+ // Process [logger] section
+ ACE_Configuration_Section_Key LoggerSection;
+ if (fromFile.open_section (root,
+ ACE_TEXT ("logger"),
+ 1,
+ LoggerSection) == 0)
+ {
+ this->get_section_string (fromFile,
+ LoggerSection,
+ ACE_TEXT ("Heading"),
+ pszHeading,
+ TEST_MAX_STRING);
+ this->get_section_integer (fromFile,
+ LoggerSection,
+ ACE_TEXT ("TraceLevel"),
+ &nTraceLevel,
+ 1,
+ 20);
+ this->get_section_string (fromFile,
+ LoggerSection,
+ ACE_TEXT ("Justification"),
+ pszJustification,
+ TEST_MAX_STRING);
+ this->get_section_string (fromFile,
+ LoggerSection,
+ ACE_TEXT ("LogFilePath"),
+ pszLogFilePath,
+ TEST_MAX_STRING);
+ this->get_section_string (fromFile,
+ LoggerSection,
+ ACE_TEXT ("TransactionFilePath"),
+ pszTransactionFilePath,
+ TEST_MAX_STRING);
+ }// end of "logger" section
+
+ if (!rc)
+ ACE_DEBUG ((LM_DEBUG, "INI Format Import/Export Works ;-)\n"));
+ return rc;
+}
+
+// Used to test registry Import Export class
+
+int
+Config_Test::testRegFormat ()
+{
+ int rc = 0;
+ if (!this->equality_tested_)
+ {
+ if ((rc = this->testEquality ()) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Equality Test Failed\n"));
+ return rc;
+ }
+
+ }
+ ACE_DEBUG ((LM_DEBUG, "Testing Registry Format Import/Export\n"));
+ ACE_Configuration_Heap fromFile;
+
+ // 1. Creates an ACE_Configuration_Heap object
+ ACE_Configuration_Heap original;
+
+ if ((rc = original.open ()) == 0)
+ {
+ // 2. Calls build_config_object to populate
+ if ((rc = build_config_object (original)) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error populating original config object (%d)\n",
+ rc),
+ -1);
+ }
+
+ // 3. Export
+ ACE_Registry_ImpExp importExport (original);
+
+ if ((rc = importExport.export_config ("testConfig.ini")) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error Exporting (%d)\n",
+ rc),
+ -1);
}
+
+ }
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Could not open original object (%d)\n",
+ rc),
+ -1);
}
+
+
+ // At this point we've successfully created, populated and written
+ // the configuration object
+ // 5. Creates a new ACE_Configuration_Heap object
+ if ((rc = fromFile.open ()) == 0)
+ {
+ // 6. Imports
+ ACE_Registry_ImpExp importExport (fromFile);
+
+ if ((rc = importExport.import_config ("testConfig.ini")) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error Exporting (%d)\n",
+ rc),
+ -1);
+ }
+
+ // 7. Compares to original.
+ if (fromFile != original)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Object read from file does not equal original (%d)\n",
+ rc),
+ -1);
+
+ }
+ }// end if heap could not be opened.
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Could not open fromFile object (%d)\n",
+ rc),
+ -1);
+ }
+
+ if (!rc)
+ ACE_DEBUG ((LM_DEBUG, "Registry Format Import/Export Works ;-)\n"));
+ return rc;
}
+
+// Reads a string value from a configuration object.
+
void
-Config_Test::get_section_string (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR *pszName,
- ACE_TCHAR *pszVariable,
- int nMaxLength)
+Config_Test::get_section_string (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ ACE_TCHAR* pszVariable,
+ int nMaxLength)
{
ACE_TString StringValue;
- if (m_ConfigurationHeap.get_string_value (SectionKey,
- pszName,
- StringValue) == 0)
+ if (config.get_string_value (SectionKey,
+ pszName,
+ StringValue) == 0)
{
ACE_OS::strncpy (pszVariable,
StringValue.c_str (),
@@ -446,21 +1149,23 @@ Config_Test::get_section_string (ACE_Configuration_Section_Key& SectionKey,
}
}
+// Reads an integer value from a congifuration object (when it's stored as a string)
void
-Config_Test::get_section_integer (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR *pszName,
- int *nVariable,
- int nMinValue,
- int nMaxValue)
+Config_Test::get_section_integer (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ int* nVariable,
+ int nMinValue,
+ int nMaxValue)
{
ACE_TString StringValue;
ACE_TCHAR pszString[30];
- ACE_OS::strcpy(pszString, ACE_TEXT ("0"));
+ ACE_OS::strcpy (pszString, ACE_TEXT ("0"));
int IntegerValue = 0;
- if (m_ConfigurationHeap.get_string_value (SectionKey,
- pszName,
- StringValue) == 0)
+ if (config.get_string_value (SectionKey,
+ pszName,
+ StringValue) == 0)
{
ACE_OS::strncpy (pszString,
StringValue.c_str (),
@@ -473,25 +1178,26 @@ Config_Test::get_section_integer (ACE_Configuration_Section_Key& SectionKey,
// convert to integer
IntegerValue = ACE_OS::atoi (pszString);
-
IntegerValue = (IntegerValue < nMinValue) ? nMinValue : IntegerValue;
IntegerValue = (IntegerValue > nMaxValue) ? nMaxValue : IntegerValue;
-
*nVariable = IntegerValue;
}
+// Reads a boolean value from a configuration object (when it's stored as a string).
+
void
-Config_Test::get_section_boolean (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR* pszName,
- int* pVariable)
+Config_Test::get_section_boolean (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ int* pVariable)
{
ACE_TString StringValue;
ACE_TCHAR pszString[10];
ACE_OS::strcpy (pszString, ACE_TEXT ("0"));
- if (m_ConfigurationHeap.get_string_value (SectionKey,
- pszName,
- StringValue) == 0)
+ if (config.get_string_value (SectionKey,
+ pszName,
+ StringValue) == 0)
{
ACE_OS::strncpy (pszString,
StringValue.c_str (),
@@ -523,8 +1229,16 @@ main (int, ACE_TCHAR *[])
ACE_START_TEST (ACE_TEXT ("Config_Test"));
Config_Test manager;
- manager.read_config ();
+ if (manager.testEquality () != 0)
+ ACE_DEBUG ((LM_DEBUG, "Failed the equality Test\n"));
+
+ if (manager.testRegFormat () != 0)
+ ACE_DEBUG ((LM_DEBUG, "Failed the REG Format Test\n"));
+
+ if (manager.testIniFormat () != 0)
+ ACE_DEBUG ((LM_DEBUG, "Failed the INI Format Test\n"));
+
run_tests ();
ACE_END_TEST;
diff --git a/tests/Config_Test.h b/tests/Config_Test.h
index c46d141b21f..4736d93575e 100644
--- a/tests/Config_Test.h
+++ b/tests/Config_Test.h
@@ -13,7 +13,8 @@
// <ACE_Configuration_Heap> class works correctly.
//
// = AUTHOR
-// Michael Searles <msearles@base16.com>
+// Michael Searles <msearles@base16.com> and
+// Jerry D. Odenwelder Jr. <jerry.o@mindspring.com>
//
// ============================================================================
@@ -26,38 +27,47 @@ const int TEST_MAX_STRING = 256;
class Config_Test
{
- ACE_Configuration_Heap m_ConfigurationHeap;
+public:
+ Config_Test (void): equality_tested_ (0) { }
+ ~Config_Test (void) { }
- int m_nTimeToLive;
- int m_bDelay;
- ACE_TCHAR m_pszDestIPAddress[TEST_MAX_STRING];
- int m_nDestPort;
- int m_nReconnectInterval;
+ // Used to test the equality and inequality operations.
+ int testEquality ();
- ACE_TCHAR m_pszLogFilePath[TEST_MAX_STRING];
- ACE_TCHAR m_pszTransactionFilePath[TEST_MAX_STRING];
- ACE_TCHAR m_pszHeading[TEST_MAX_STRING];
- int m_nTraceLevel;
- ACE_TCHAR m_pszJustification[TEST_MAX_STRING];
+ // Used to test INI Import Export class
+ int testIniFormat ();
-public:
- Config_Test (void) { }
- ~Config_Test (void) { }
- void read_config (void);
+ // Used to test Regiastry Import Export class
+ // 1. Creates an ACE_Configuration_Heap object
+ // 2. Calls buildConfigObject to populate
+ // 3. Exports
+ // 5. Creates a new ACE_Configuration_Heap object
+ // 6. Imports
+ // 7. Compares to origional.
+ // 8. Clean-up
+ int testRegFormat ();
+
+private:
+ void get_section_string (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ ACE_TCHAR* pszVariable,
+ int nMaxLength);
+
+ void get_section_integer (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ int* nVariable,
+ int nMinValue,
+ int nMaxValue);
+
+ void get_section_boolean (ACE_Configuration& config,
+ ACE_Configuration_Section_Key& SectionKey,
+ const ACE_TCHAR* pszName,
+ int* pVariable);
private:
- void get_section_string (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR *pszName,
- ACE_TCHAR *pszVariable,
- int nMaxLength);
- void get_section_integer (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR *pszName,
- int *nVariable,
- int nMinValue,
- int nMaxValue);
- void get_section_boolean (ACE_Configuration_Section_Key& SectionKey,
- const ACE_TCHAR *pszName,
- int *pVariable);
+ int equality_tested_; // make sure the equality operator works before proceeding.
};
#endif /* __CONFIG_TEST_H */