summaryrefslogtreecommitdiff
path: root/ACE/ace/Configuration_Import_Export.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Configuration_Import_Export.cpp')
-rw-r--r--ACE/ace/Configuration_Import_Export.cpp664
1 files changed, 664 insertions, 0 deletions
diff --git a/ACE/ace/Configuration_Import_Export.cpp b/ACE/ace/Configuration_Import_Export.cpp
new file mode 100644
index 00000000000..335be965247
--- /dev/null
+++ b/ACE/ace/Configuration_Import_Export.cpp
@@ -0,0 +1,664 @@
+// $Id$
+
+#include "ace/Configuration_Import_Export.h"
+#include "ace/OS_Errno.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_string.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration& config)
+ : config_ (config)
+{
+}
+
+ACE_Config_ImpExp_Base::~ACE_Config_ImpExp_Base (void)
+{
+}
+
+ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration& config)
+ : ACE_Config_ImpExp_Base (config)
+{
+}
+
+ACE_Registry_ImpExp::~ACE_Registry_ImpExp (void)
+{
+}
+
+// Imports the configuration database from filename.
+// No existing data is removed.
+int
+ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
+ if (!in)
+ return -1;
+
+ u_int buffer_size = 4096;
+ u_int read_pos = 0;
+ ACE_TCHAR *buffer = 0;
+ ACE_NEW_NORETURN (buffer, ACE_TCHAR[buffer_size]);
+ if (!buffer)
+ {
+ ACE_Errno_Guard guard (errno);
+ (void) ACE_OS::fclose (in);
+ return -1;
+ }
+ ACE_Configuration_Section_Key section;
+ ACE_TCHAR *end = 0;
+
+ while (ACE_OS::fgets (buffer+read_pos, buffer_size - read_pos, in))
+ {
+ // Check if we got all the line.
+ end = ACE_OS::strrchr (buffer + read_pos,
+ ACE_LIB_TEXT ('\n')); // look for end of line
+ if (!end) // we havn't reach the end of the line yet
+ {
+ // allocate a new buffer - double size the previous one
+ ACE_TCHAR *temp_buffer;
+ ACE_NEW_NORETURN (temp_buffer, ACE_TCHAR[buffer_size * 2]);
+ if (!temp_buffer)
+ {
+ ACE_Errno_Guard guard (errno);
+ delete [] buffer;
+ (void) ACE_OS::fclose (in);
+ return -1;
+ }
+
+ // copy the beginnning of the line
+ ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
+ read_pos = buffer_size - 1;
+ buffer_size *= 2;
+ delete [] buffer;
+ buffer = temp_buffer;
+ continue;
+ }
+ read_pos = 0;
+
+ // 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
+ end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -3;
+ }
+ continue;
+ } // end if firs char is a [
+
+ if (buffer[0] == ACE_LIB_TEXT ('"'))
+ {
+ // we have a value
+ 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);
+ delete [] buffer;
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("dword:"), 6) == 0)
+ {
+ // number type
+ ACE_TCHAR* endptr = 0;
+ unsigned long value = ACE_OS::strtoul (end + 6, &endptr, 16);
+ if (config_.set_integer_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -4;
+ }
+ }
+ else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("hex:"), 4) == 0)
+ {
+ // binary type
+ size_t string_length = ACE_OS::strlen (end + 4);
+ // divide by 3 to get the actual buffer length
+ size_t length = string_length / 3;
+ size_t remaining = length;
+ u_char* data = 0;
+ ACE_NEW_RETURN (data,
+ u_char[length],
+ -1);
+ 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);
+ delete [] data;
+ delete [] buffer;
+ return -4;
+ }
+ else
+ delete [] data;
+ }
+ else
+ {
+ // invalid type, ignore
+ continue;
+ }
+ }// end if first char is a "
+ else
+ {
+ // if the first character is not a ", [, ;, or # we may be
+ // processing a file in the old format.
+ // Try and process the line as such and if it fails,
+ // return an error
+ int rc = process_previous_line_format (buffer, section);
+ if (rc != 0)
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return rc;
+ }
+ } // end if maybe old format
+ } // end while fgets
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ delete [] buffer;
+ return 0;
+}
+
+// This method exports the entire configuration database to <filename>.
+// Once the file is opened this method calls 'export_section' passing
+// the root section.
+int
+ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ 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;
+ size_t 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;
+}
+
+//
+// This method read the line format origionally used in ACE 5.1
+//
+int
+ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR* buffer,
+ ACE_Configuration_Section_Key& section)
+{
+ // Chop any cr/lf at the end of the line.
+ ACE_TCHAR *endp = ACE_OS::strpbrk (buffer, ACE_LIB_TEXT ("\r\n"));
+ if (endp != 0)
+ *endp = '\0';
+
+ // assume this is a value, read in the value name
+ ACE_TCHAR* end = ACE_OS::strchr (buffer, '=');
+ if (end) // no =, not a value so just skip it
+ {
+ // null terminate the name
+ *end = 0;
+ end++;
+ // determine the type
+ if (*end == '\"')
+ {
+ // string type
+ if(config_.set_string_value (section, buffer, end + 1))
+ return -4;
+ }
+ else if (*end == '#')
+ {
+ // number type
+ u_int value = ACE_OS::atoi (end + 1);
+ if (config_.set_integer_value (section, buffer, value))
+ return -4;
+ }
+ }
+ return 0;
+} // end read_previous_line_format
+
+
+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)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ 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))
+ {
+ ACE_TCHAR *line = this->squish (buffer);
+ // Check for a comment and blank line
+ if (line[0] == ACE_LIB_TEXT (';') ||
+ line[0] == ACE_LIB_TEXT ('#') ||
+ line[0] == '\0')
+ continue;
+
+ if (line[0] == ACE_LIB_TEXT ('['))
+ {
+ // We have a new section here, strip out the section name
+ ACE_TCHAR* end = ACE_OS::strrchr (line, ACE_LIB_TEXT (']'));
+ if (!end)
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end = 0;
+
+ if (config_.expand_path (config_.root_section (),
+ line + 1,
+ section,
+ 1))
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+
+ continue;
+ }
+
+ // We have a line; name ends at equal sign.
+ ACE_TCHAR *end = ACE_OS::strchr (line, ACE_LIB_TEXT ('='));
+ if (end == 0) // No '='
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+ *end++ = '\0';
+ ACE_TCHAR *name = this->squish (line);
+#if 0
+ if (ACE_OS::strlen (name) == 0) // No name; just an '='
+ {
+ ACE_OS::fclose (in);
+ return -3;
+ }
+#endif
+ // Now find the start of the value
+ ACE_TCHAR *value = this->squish (end);
+ size_t value_len = ACE_OS::strlen (value);
+ if (value_len > 0)
+ {
+ // ACE 5.2 (and maybe earlier) exported strings may be enclosed
+ // in quotes. If string is quote-delimited, strip the quotes.
+ // Newer exported files don't have quote delimiters.
+ if (value[0] == ACE_LIB_TEXT ('"') &&
+ value[value_len - 1] == ACE_LIB_TEXT ('"'))
+ {
+ // Strip quotes off both ends.
+ value[value_len - 1] = '\0';
+ value++;
+ }
+ }
+
+ if (config_.set_string_value (section, name, value))
+ {
+ ACE_OS::fclose (in);
+ return -4;
+ }
+ } // end while fgets
+
+ if (ferror (in))
+ {
+ ACE_OS::fclose (in);
+ return -1;
+ }
+
+ ACE_OS::fclose (in);
+ return 0;
+}
+
+// This method exports the entire configuration database to <filename>.
+// Once the file is opened this method calls 'export_section' passing
+// the root section.
+int
+ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
+{
+ if (0 == filename)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ 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 ("]\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;
+ size_t 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;
+ 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 squish leading and trailing whitespaces from a string.
+// Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
+// (cr/lf). The terminating nul is moved up to expunge trailing
+// whitespace and the returned pointer points at the first
+// non-whitespace character in the string, which may be the nul
+// terminator if the string is all whitespace.
+
+ACE_TCHAR *
+ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
+{
+ ACE_TCHAR *cp = 0;
+
+ if (src == 0)
+ return 0;
+
+ // Start at the end and work backwards over all whitespace.
+ for (cp = src + ACE_OS::strlen (src) - 1;
+ cp != src;
+ --cp)
+ if (!ACE_OS::ace_isspace (*cp))
+ break;
+ cp[1] = '\0'; // Chop trailing whitespace
+
+ // Now start at the beginning and move over all whitespace.
+ for (cp = src; ACE_OS::ace_isspace (*cp); ++cp)
+ continue;
+
+ return cp;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL