Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Configuration_Import_Export.cpp

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

Generated on Mon Jun 16 11:19:24 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002