Configuration_Import_Export.cpp

Go to the documentation of this file.
00001 // Configuration_Import_Export.cpp,v 4.33 2006/06/09 10:29:45 jwillemsen Exp
00002 
00003 #include "ace/Configuration_Import_Export.h"
00004 #include "ace/OS_NS_stdio.h"
00005 #include "ace/OS_NS_ctype.h"
00006 #include "ace/OS_NS_string.h"
00007 
00008 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00009 
00010 ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration& config)
00011   : config_ (config)
00012 {
00013 }
00014 
00015 ACE_Config_ImpExp_Base::~ACE_Config_ImpExp_Base (void)
00016 {
00017 }
00018 
00019 ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration& config)
00020     : ACE_Config_ImpExp_Base (config)
00021 {
00022 }
00023 
00024 ACE_Registry_ImpExp::~ACE_Registry_ImpExp (void)
00025 {
00026 }
00027 
00028 // Imports the configuration database from filename.
00029 // No existing data is removed.
00030 int
00031 ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
00032 {
00033   if (0 == filename)
00034     {
00035       errno = EINVAL;
00036       return -1;
00037     }
00038   FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
00039   if (!in)
00040     return -1;
00041 
00042   u_int buffer_size = 4096;
00043   u_int read_pos = 0;
00044   ACE_TCHAR *buffer;
00045   ACE_NEW_RETURN (buffer, ACE_TCHAR[buffer_size], -1);
00046   ACE_Configuration_Section_Key section;
00047   ACE_TCHAR *end = 0;
00048 
00049   while (ACE_OS::fgets (buffer+read_pos, buffer_size - read_pos, in))
00050     {
00051       // Check if we got all the line.
00052       end = ACE_OS::strrchr (buffer + read_pos,
00053                              ACE_LIB_TEXT ('\n')); // look for end of line
00054       if (!end) // we havn't reach the end of the line yet
00055         {
00056           // allocate a new buffer - double size the previous one
00057           ACE_TCHAR *temp_buffer;
00058           ACE_NEW_RETURN (temp_buffer, ACE_TCHAR[buffer_size * 2], -1);
00059 
00060           // copy the beginnning of the line
00061           ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
00062           read_pos = buffer_size - 1;
00063           buffer_size *= 2;
00064           delete [] buffer;
00065           buffer = temp_buffer;
00066           continue;
00067         }
00068       read_pos = 0;
00069 
00070       // Check for a comment
00071       if (buffer[0] == ACE_LIB_TEXT (';') || buffer[0] == ACE_LIB_TEXT ('#'))
00072         continue;
00073 
00074       if (buffer[0] == ACE_LIB_TEXT ('['))
00075         {
00076           // We have a new section here, strip out the section name
00077           end = ACE_OS::strrchr (buffer, ACE_LIB_TEXT (']'));
00078           if (!end)
00079             {
00080               ACE_OS::fclose (in);
00081               delete [] buffer;
00082               return -3;
00083             }
00084           *end = 0;
00085 
00086           if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
00087             {
00088               ACE_OS::fclose (in);
00089               delete [] buffer;
00090               return -3;
00091             }
00092           continue;
00093         }              // end if firs char is a [
00094 
00095       if (buffer[0] == ACE_LIB_TEXT ('"'))
00096         {
00097           // we have a value
00098           end = ACE_OS::strchr (buffer+1, '"');
00099           if (!end)  // no closing quote, not a value so just skip it
00100             continue;
00101 
00102           // null terminate the name
00103           *end = 0;
00104           ACE_TCHAR* name = buffer + 1;
00105           end+=2;
00106           // determine the type
00107           if (*end == '\"')
00108             {
00109               // string type
00110               // truncate trailing "
00111               ++end;
00112               ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
00113               if (trailing)
00114                 *trailing = 0;
00115               if (config_.set_string_value (section, name, end))
00116                 {
00117                   ACE_OS::fclose (in);
00118                   delete [] buffer;
00119                   return -4;
00120                 }
00121             }
00122           else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("dword:"), 6) == 0)
00123             {
00124               // number type
00125               ACE_TCHAR* endptr = 0;
00126               unsigned long value = ACE_OS::strtoul (end + 6, &endptr, 16);
00127               if (config_.set_integer_value (section, name, value))
00128                 {
00129                   ACE_OS::fclose (in);
00130                   delete [] buffer;
00131                   return -4;
00132                 }
00133             }
00134           else if (ACE_OS::strncmp (end, ACE_LIB_TEXT ("hex:"), 4) == 0)
00135             {
00136               // binary type
00137               size_t string_length = ACE_OS::strlen (end + 4);
00138               // divide by 3 to get the actual buffer length
00139               size_t length = string_length / 3;
00140               size_t remaining = length;
00141               u_char* data = 0;
00142               ACE_NEW_RETURN (data,
00143                               u_char[length],
00144                               -1);
00145               u_char* out = data;
00146               ACE_TCHAR* inb = end + 4;
00147               ACE_TCHAR* endptr = 0;
00148               while (remaining)
00149                 {
00150                   u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
00151                   *out = charin;
00152                   ++out;
00153                   --remaining;
00154                   inb += 3;
00155                 }
00156               if (config_.set_binary_value (section, name, data, length))
00157                 {
00158                   ACE_OS::fclose (in);
00159                   delete [] data;
00160                   delete [] buffer;
00161                   return -4;
00162                 }
00163               else
00164                 delete [] data;
00165             }
00166           else
00167             {
00168               // invalid type, ignore
00169               continue;
00170             }
00171         }// end if first char is a "
00172       else
00173         {
00174           // if the first character is not a ", [, ;, or # we may be
00175           // processing a file in the old format.
00176           // Try and process the line as such and if it fails,
00177           // return an error
00178           int rc = process_previous_line_format (buffer, section);
00179           if (rc != 0)
00180             {
00181               ACE_OS::fclose (in);
00182               delete [] buffer;
00183               return rc;
00184             }
00185         }             // end if maybe old format
00186     }                 // end while fgets
00187 
00188   if (ferror (in))
00189     {
00190       ACE_OS::fclose (in);
00191       delete [] buffer;
00192       return -1;
00193     }
00194 
00195   ACE_OS::fclose (in);
00196   delete [] buffer;
00197   return 0;
00198 }
00199 
00200 // This method exports the entire configuration database to <filename>.
00201 // Once the file is opened this method calls 'export_section' passing
00202 // the root section.
00203 int
00204 ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
00205 {
00206   if (0 == filename)
00207     {
00208       errno = EINVAL;
00209       return -1;
00210     }
00211   int result = -1;
00212 
00213   FILE* out = ACE_OS::fopen (filename, ACE_LIB_TEXT ("w"));
00214   if (out)
00215     {
00216       result = this->export_section (config_.root_section (),
00217                                      ACE_LIB_TEXT (""),
00218                                      out);
00219       ACE_OS::fclose (out);
00220     }
00221   return result;
00222 }
00223 
00224 // Method provided by derived classes in order to write one section
00225 // to the file specified.  Called by export_config when exporting
00226 // the entire configuration object.
00227 
00228 int
00229 ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
00230                                      const ACE_TString& path,
00231                                      FILE* out)
00232 {
00233   // don't export the root
00234   if (path.length ())
00235     {
00236       // Write out the section header
00237       ACE_TString header = ACE_LIB_TEXT ("[");
00238       header += path;
00239       header += ACE_LIB_TEXT ("]");
00240       header += ACE_LIB_TEXT (" \n");
00241       if (ACE_OS::fputs (header.fast_rep (), out) < 0)
00242         return -1;
00243       // Write out each value
00244       int index = 0;
00245       ACE_TString name;
00246       ACE_Configuration::VALUETYPE type;
00247       ACE_TString line;
00248       ACE_TCHAR int_value[32];
00249       ACE_TCHAR bin_value[3];
00250       void* binary_data;
00251       size_t binary_length;
00252       ACE_TString string_value;
00253       while (!config_.enumerate_values (section, index, name, type))
00254         {
00255           line = ACE_LIB_TEXT ("\"") + name + ACE_LIB_TEXT ("\"=");
00256           switch (type)
00257             {
00258             case ACE_Configuration::INTEGER:
00259               {
00260                 u_int value;
00261                 if (config_.get_integer_value (section, name.fast_rep (), value))
00262                   return -2;
00263                 ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), value);
00264                 line += ACE_LIB_TEXT ("dword:");
00265                 line += int_value;
00266                 break;
00267               }
00268             case ACE_Configuration::STRING:
00269               {
00270                 if (config_.get_string_value (section,
00271                                               name.fast_rep (),
00272                                               string_value))
00273                   return -2;
00274                 line += ACE_LIB_TEXT ("\"");
00275                 line += string_value + ACE_LIB_TEXT ("\"");
00276                 break;
00277               }
00278 #ifdef _WIN32
00279             case ACE_Configuration::INVALID:
00280               break;  // JDO added break.  Otherwise INVALID is processed
00281               // like BINARY. If that's correct, please remove the
00282               // break and these comments
00283 #endif
00284             case ACE_Configuration::BINARY:
00285               {
00286                 // not supported yet - maybe use BASE64 codeing?
00287                 if (config_.get_binary_value (section,
00288                                               name.fast_rep (),
00289                                               binary_data,
00290                                               binary_length))
00291                   return -2;
00292                 line += ACE_LIB_TEXT ("hex:");
00293                 unsigned char* ptr = (unsigned char*)binary_data;
00294                 while (binary_length)
00295                   {
00296                     if (ptr != binary_data)
00297                       {
00298                         line += ACE_LIB_TEXT (",");
00299                       }
00300                     ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
00301                     line += bin_value;
00302                     --binary_length;
00303                     ++ptr;
00304                   }
00305                 delete [] (char*) binary_data;
00306                 break;
00307               }
00308             default:
00309               return -3;
00310             }
00311           line += ACE_LIB_TEXT ("\n");
00312           if (ACE_OS::fputs (line.fast_rep (), out) < 0)
00313             return -4;
00314           index++;
00315         }
00316     }
00317   // Export all sub sections
00318   int index = 0;
00319   ACE_TString name;
00320   ACE_Configuration_Section_Key sub_key;
00321   ACE_TString sub_section;
00322   while (!config_.enumerate_sections (section, index, name))
00323     {
00324       ACE_TString sub_section (path);
00325       if (path.length ())
00326         sub_section += ACE_LIB_TEXT ("\\");
00327       sub_section += name;
00328       if (config_.open_section (section, name.fast_rep (), 0, sub_key))
00329         return -5;
00330       if (export_section (sub_key, sub_section.fast_rep (), out))
00331         return -6;
00332       index++;
00333     }
00334   return 0;
00335 }
00336 
00337 //
00338 // This method read the line format origionally used in ACE 5.1
00339 //
00340 int
00341 ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR* buffer,
00342                                                    ACE_Configuration_Section_Key& section)
00343 {
00344   // Chop any cr/lf at the end of the line.
00345   ACE_TCHAR *endp = ACE_OS::strpbrk (buffer, ACE_LIB_TEXT ("\r\n"));
00346   if (endp != 0)
00347     *endp = '\0';
00348 
00349   // assume this is a value, read in the value name
00350   ACE_TCHAR* end = ACE_OS::strchr (buffer, '=');
00351   if (end)  // no =, not a value so just skip it
00352     {
00353       // null terminate the name
00354       *end = 0;
00355       end++;
00356       // determine the type
00357       if (*end == '\"')
00358         {
00359           // string type
00360           if(config_.set_string_value (section, buffer, end + 1))
00361             return -4;
00362         }
00363       else if (*end == '#')
00364         {
00365           // number type
00366           u_int value = ACE_OS::atoi (end + 1);
00367           if (config_.set_integer_value (section, buffer, value))
00368             return -4;
00369         }
00370     }
00371   return 0;
00372 }                // end read_previous_line_format
00373 
00374 
00375 ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration& config)
00376     : ACE_Config_ImpExp_Base (config)
00377 {
00378 }
00379 
00380 ACE_Ini_ImpExp::~ACE_Ini_ImpExp (void)
00381 {
00382 }
00383 
00384 // Method to read file and populate object.
00385 int
00386 ACE_Ini_ImpExp::import_config (const ACE_TCHAR* filename)
00387 {
00388   if (0 == filename)
00389     {
00390       errno = EINVAL;
00391       return -1;
00392     }
00393   FILE* in = ACE_OS::fopen (filename, ACE_LIB_TEXT ("r"));
00394   if (!in)
00395     return -1;
00396 
00397   // @@ Make this a dynamic size!
00398   ACE_TCHAR buffer[4096];
00399   ACE_Configuration_Section_Key section;
00400   while (ACE_OS::fgets (buffer, sizeof buffer, in))
00401     {
00402       ACE_TCHAR *line = this->squish (buffer);
00403       // Check for a comment and blank line
00404       if (line[0] == ACE_LIB_TEXT (';')  ||
00405           line[0] == ACE_LIB_TEXT ('#')  ||
00406           line[0] == '\0')
00407         continue;
00408 
00409       if (line[0] == ACE_LIB_TEXT ('['))
00410         {
00411           // We have a new section here, strip out the section name
00412           ACE_TCHAR* end = ACE_OS::strrchr (line, ACE_LIB_TEXT (']'));
00413           if (!end)
00414             {
00415               ACE_OS::fclose (in);
00416               return -3;
00417             }
00418           *end = 0;
00419 
00420           if (config_.expand_path (config_.root_section (),
00421                                    line + 1,
00422                                    section,
00423                                    1))
00424             {
00425               ACE_OS::fclose (in);
00426               return -3;
00427             }
00428 
00429           continue;
00430         }
00431 
00432       // We have a line; name ends at equal sign.
00433       ACE_TCHAR *end = ACE_OS::strchr (line, ACE_LIB_TEXT ('='));
00434       if (end == 0)                            // No '='
00435         {
00436           ACE_OS::fclose (in);
00437           return -3;
00438         }
00439       *end++ = '\0';
00440       ACE_TCHAR *name = this->squish (line);
00441 #if 0
00442       if (ACE_OS::strlen (name) == 0)          // No name; just an '='
00443         {
00444           ACE_OS::fclose (in);
00445           return -3;
00446         }
00447 #endif
00448       // Now find the start of the value
00449       ACE_TCHAR *value = this->squish (end);
00450       size_t value_len = ACE_OS::strlen (value);
00451       if (value_len > 0)
00452         {
00453           // ACE 5.2 (and maybe earlier) exported strings may be enclosed
00454           // in quotes. If string is quote-delimited, strip the quotes.
00455           // Newer exported files don't have quote delimiters.
00456           if (value[0] == ACE_LIB_TEXT ('"') &&
00457               value[value_len - 1] == ACE_LIB_TEXT ('"'))
00458             {
00459               // Strip quotes off both ends.
00460               value[value_len - 1] = '\0';
00461               value++;
00462             }
00463         }
00464 
00465       if (config_.set_string_value (section, name, value))
00466         {
00467           ACE_OS::fclose (in);
00468           return -4;
00469         }
00470     }             // end while fgets
00471 
00472   if (ferror (in))
00473     {
00474       ACE_OS::fclose (in);
00475       return -1;
00476     }
00477 
00478   ACE_OS::fclose (in);
00479   return 0;
00480 }
00481 
00482 // This method exports the entire configuration database to <filename>.
00483 // Once the file is opened this method calls 'export_section' passing
00484 // the root section.
00485 int
00486 ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
00487 {
00488   if (0 == filename)
00489     {
00490       errno = EINVAL;
00491       return -1;
00492     }
00493   int result = -1;
00494 
00495   FILE* out = ACE_OS::fopen (filename, ACE_LIB_TEXT ("w"));
00496   if (out)
00497     {
00498       result = this->export_section (config_.root_section (),
00499                                      ACE_LIB_TEXT (""),
00500                                      out);
00501       ACE_OS::fclose (out);
00502     }
00503   return result;
00504 }
00505 
00506 // Method provided by derived classes in order to write one section to the
00507 // file specified.  Called by export_config when exporting the entire
00508 // configuration objet
00509 
00510 int
00511 ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
00512                                 const ACE_TString& path,
00513                                 FILE* out)
00514 {
00515   // don't export the root
00516   if (path.length ())
00517     {
00518       // Write out the section header
00519       ACE_TString header = ACE_LIB_TEXT ("[");
00520       header += path;
00521       header += ACE_LIB_TEXT ("]\n");
00522       if (ACE_OS::fputs (header.fast_rep (), out) < 0)
00523         return -1;
00524       // Write out each value
00525       int index = 0;
00526       ACE_TString name;
00527       ACE_Configuration::VALUETYPE type;
00528       ACE_TString line;
00529       ACE_TCHAR int_value[32];
00530       ACE_TCHAR bin_value[3];
00531       void* binary_data;
00532       size_t binary_length;
00533       ACE_TString string_value;
00534       while (!config_.enumerate_values (section, index, name, type))
00535         {
00536           line = name + ACE_LIB_TEXT ("=");
00537           switch (type)
00538             {
00539             case ACE_Configuration::INTEGER:
00540               {
00541                 u_int value;
00542                 if (config_.get_integer_value (section, name.fast_rep (), value))
00543                   return -2;
00544                 ACE_OS::sprintf (int_value, ACE_LIB_TEXT ("%08x"), value);
00545                 line += int_value;
00546                 break;
00547               }
00548             case ACE_Configuration::STRING:
00549               {
00550                 if (config_.get_string_value (section,
00551                                               name.fast_rep (),
00552                                               string_value))
00553                   return -2;
00554                 line += string_value;
00555                 break;
00556               }
00557 #ifdef _WIN32
00558             case ACE_Configuration::INVALID:
00559               break;  // JDO added break.  Otherwise INVALID is processed
00560               // like BINARY. If that's correct, please remove the
00561               // break and these comments
00562 #endif
00563             case ACE_Configuration::BINARY:
00564               {
00565                 // not supported yet - maybe use BASE64 codeing?
00566                 if (config_.get_binary_value (section,
00567                                               name.fast_rep (),
00568                                               binary_data,
00569                                               binary_length))
00570                   return -2;
00571                 line += ACE_LIB_TEXT ("\"");
00572                 unsigned char* ptr = (unsigned char*)binary_data;
00573                 while (binary_length)
00574                   {
00575                     if (ptr != binary_data)
00576                       {
00577                         line += ACE_LIB_TEXT (",");
00578                       }
00579                     ACE_OS::sprintf (bin_value, ACE_LIB_TEXT ("%02x"), *ptr);
00580                     line += bin_value;
00581                     --binary_length;
00582                     ++ptr;
00583                   }
00584                 line += ACE_LIB_TEXT ("\"");
00585                 delete [] (char *) binary_data;
00586                 break;
00587               }
00588             default:
00589               return -3;
00590 
00591             }// end switch on type
00592 
00593           line += ACE_LIB_TEXT ("\n");
00594           if (ACE_OS::fputs (line.fast_rep (), out) < 0)
00595             return -4;
00596           index++;
00597         }// end while enumerating values
00598     }
00599   // Export all sub sections
00600   int index = 0;
00601   ACE_TString name;
00602   ACE_Configuration_Section_Key sub_key;
00603   ACE_TString sub_section;
00604   while (!config_.enumerate_sections (section, index, name))
00605     {
00606       ACE_TString sub_section (path);
00607       if (path.length ())
00608         sub_section += ACE_LIB_TEXT ("\\");
00609       sub_section += name;
00610       if (config_.open_section (section, name.fast_rep (), 0, sub_key))
00611         return -5;
00612       if (export_section (sub_key, sub_section.fast_rep (), out))
00613         return -6;
00614       index++;
00615     }
00616   return 0;
00617 
00618 }
00619 
00620 // Method to squish leading and trailing whitespaces from a string.
00621 // Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
00622 // (cr/lf).  The terminating nul is moved up to expunge trailing
00623 // whitespace and the returned pointer points at the first
00624 // non-whitespace character in the string, which may be the nul
00625 // terminator if the string is all whitespace.
00626 
00627 ACE_TCHAR *
00628 ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
00629 {
00630   ACE_TCHAR *cp = 0;
00631 
00632   if (src == 0)
00633     return 0;
00634 
00635   // Start at the end and work backwards over all whitespace.
00636   for (cp = src + ACE_OS::strlen (src) - 1;
00637        cp != src;
00638        --cp)
00639     if (!ACE_OS::ace_isspace (*cp))
00640       break;
00641   cp[1] = '\0';          // Chop trailing whitespace
00642 
00643   // Now start at the beginning and move over all whitespace.
00644   for (cp = src; ACE_OS::ace_isspace (*cp); ++cp)
00645     continue;
00646 
00647   return cp;
00648 }
00649 
00650 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:41:48 2006 for ACE by doxygen 1.3.6