1 #include "ace/Configuration_Import_Export.h"
2 #include "ace/OS_Errno.h"
3 #include "ace/OS_NS_stdio.h"
4 #include "ace/OS_NS_ctype.h"
5 #include "ace/OS_NS_string.h"
7 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
9 ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration
& config
)
14 ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration
& config
)
15 : ACE_Config_ImpExp_Base (config
)
19 // Imports the configuration database from filename.
20 // No existing data is removed.
22 ACE_Registry_ImpExp::import_config (const ACE_TCHAR
* filename
)
29 FILE* in
= ACE_OS::fopen (filename
, ACE_TEXT ("r"));
33 u_int buffer_size
= 4096;
35 ACE_TCHAR
*buffer
= 0;
36 #if defined (ACE_HAS_ALLOC_HOOKS)
37 ACE_ALLOCATOR_NORETURN (buffer
, static_cast<ACE_TCHAR
*> (ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR
) * buffer_size
)));
39 ACE_NEW_NORETURN (buffer
, ACE_TCHAR
[buffer_size
]);
40 #endif /* ACE_HAS_ALLOC_HOOKS */
43 ACE_Errno_Guard
guard (errno
);
44 (void) ACE_OS::fclose (in
);
47 ACE_Configuration_Section_Key section
;
50 while (ACE_OS::fgets (buffer
+read_pos
, buffer_size
- read_pos
, in
))
52 // Check if we got all the line.
53 end
= ACE_OS::strrchr (buffer
+ read_pos
,
54 ACE_TEXT ('\n')); // look for end of line
55 if (!end
) // we havn't reach the end of the line yet
57 // allocate a new buffer - double size the previous one
58 ACE_TCHAR
*temp_buffer
;
59 #if defined (ACE_HAS_ALLOC_HOOKS)
60 ACE_ALLOCATOR_NORETURN (temp_buffer
, static_cast<ACE_TCHAR
*> (ACE_Allocator::instance()->malloc(sizeof (ACE_TCHAR
) * buffer_size
* 2)));
62 ACE_NEW_NORETURN (temp_buffer
, ACE_TCHAR
[buffer_size
* 2]);
63 #endif /* ACE_HAS_ALLOC_HOOKS */
66 ACE_Errno_Guard
guard (errno
);
67 #if defined (ACE_HAS_ALLOC_HOOKS)
68 ACE_Allocator::instance()->free(buffer
);
71 #endif /* ACE_HAS_ALLOC_HOOKS */
72 (void) ACE_OS::fclose (in
);
76 // copy the beginnning of the line
77 ACE_OS::memcpy (temp_buffer
, buffer
, buffer_size
);
78 read_pos
= buffer_size
- 1;
80 #if defined (ACE_HAS_ALLOC_HOOKS)
81 ACE_Allocator::instance()->free(buffer
);
84 #endif /* ACE_HAS_ALLOC_HOOKS */
90 // Check for a comment
91 if (buffer
[0] == ACE_TEXT (';') || buffer
[0] == ACE_TEXT ('#'))
94 if (buffer
[0] == ACE_TEXT ('['))
96 // We have a new section here, strip out the section name
97 end
= ACE_OS::strrchr (buffer
, ACE_TEXT (']'));
101 #if defined (ACE_HAS_ALLOC_HOOKS)
102 ACE_Allocator::instance()->free(buffer
);
105 #endif /* ACE_HAS_ALLOC_HOOKS */
110 if (config_
.expand_path (config_
.root_section (), buffer
+ 1, section
, 1))
113 #if defined (ACE_HAS_ALLOC_HOOKS)
114 ACE_Allocator::instance()->free(buffer
);
117 #endif /* ACE_HAS_ALLOC_HOOKS */
121 } // end if firs char is a [
123 if (buffer
[0] == ACE_TEXT ('"'))
126 end
= ACE_OS::strchr (buffer
+1, '"');
127 if (!end
) // no closing quote, not a value so just skip it
130 // null terminate the name
132 ACE_TCHAR
* name
= buffer
+ 1;
134 // determine the type
138 // truncate trailing "
140 ACE_TCHAR
* trailing
= ACE_OS::strrchr (end
, '"');
143 if (config_
.set_string_value (section
, name
, end
))
146 #if defined (ACE_HAS_ALLOC_HOOKS)
147 ACE_Allocator::instance()->free(buffer
);
150 #endif /* ACE_HAS_ALLOC_HOOKS */
154 else if (ACE_OS::strncmp (end
, ACE_TEXT ("dword:"), 6) == 0)
157 ACE_TCHAR
* endptr
= 0;
158 unsigned long value
= ACE_OS::strtoul (end
+ 6, &endptr
, 16);
159 if (config_
.set_integer_value (section
, name
,
160 static_cast<u_int
> (value
)))
163 #if defined (ACE_HAS_ALLOC_HOOKS)
164 ACE_Allocator::instance()->free(buffer
);
167 #endif /* ACE_HAS_ALLOC_HOOKS */
171 else if (ACE_OS::strncmp (end
, ACE_TEXT ("hex:"), 4) == 0)
174 size_t string_length
= ACE_OS::strlen (end
+ 4);
175 // divide by 3 to get the actual buffer length
176 size_t length
= string_length
/ 3;
177 size_t remaining
= length
;
179 #if defined (ACE_HAS_ALLOC_HOOKS)
180 ACE_ALLOCATOR_RETURN (data
,
181 static_cast<u_char
*> (ACE_Allocator::instance()->malloc(sizeof(u_char
) * length
)),
184 ACE_NEW_RETURN (data
,
187 #endif /* ACE_HAS_ALLOC_HOOKS */
189 ACE_TCHAR
* inb
= end
+ 4;
190 ACE_TCHAR
* endptr
= 0;
193 u_char charin
= (u_char
) ACE_OS::strtoul (inb
, &endptr
, 16);
199 if (config_
.set_binary_value (section
, name
, data
, length
))
202 #if defined (ACE_HAS_ALLOC_HOOKS)
203 ACE_Allocator::instance()->free(data
);
204 ACE_Allocator::instance()->free(buffer
);
208 #endif /* ACE_HAS_ALLOC_HOOKS */
212 #if defined (ACE_HAS_ALLOC_HOOKS)
213 ACE_Allocator::instance()->free(data
);
216 #endif /* ACE_HAS_ALLOC_HOOKS */
220 // invalid type, ignore
223 }// end if first char is a "
226 // if the first character is not a ", [, ;, or # we may be
227 // processing a file in the old format.
228 // Try and process the line as such and if it fails,
230 int rc
= process_previous_line_format (buffer
, section
);
234 #if defined (ACE_HAS_ALLOC_HOOKS)
235 ACE_Allocator::instance()->free(buffer
);
238 #endif /* ACE_HAS_ALLOC_HOOKS */
241 } // end if maybe old format
247 #if defined (ACE_HAS_ALLOC_HOOKS)
248 ACE_Allocator::instance()->free(buffer
);
251 #endif /* ACE_HAS_ALLOC_HOOKS */
256 #if defined (ACE_HAS_ALLOC_HOOKS)
257 ACE_Allocator::instance()->free(buffer
);
260 #endif /* ACE_HAS_ALLOC_HOOKS */
264 // This method exports the entire configuration database to <filename>.
265 // Once the file is opened this method calls 'export_section' passing
268 ACE_Registry_ImpExp::export_config (const ACE_TCHAR
* filename
)
277 FILE* out
= ACE_OS::fopen (filename
, ACE_TEXT ("w"));
280 result
= this->export_section (config_
.root_section (),
283 // The data may have been buffered and will be flush on close,
284 // so we need to check that the close succeeds.
285 if (ACE_OS::fclose (out
) < 0)
292 #if !defined ACE_USES_WCHAR && defined ACE_LACKS_FPUTS
293 # define ACE_WRITE_STRING write_string
296 int write_string (const char *string
, FILE *stream
)
298 const size_t count
= ACE_OS::strlen (string
);
299 return (ACE_OS::fwrite (string
, 1, count
, stream
) < count
) ? -1 : 0;
303 # define ACE_WRITE_STRING ACE_OS::fputs
306 // Method provided by derived classes in order to write one section
307 // to the file specified. Called by export_config when exporting
308 // the entire configuration object.
311 ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key
& section
,
312 const ACE_TString
& path
,
315 // don't export the root
318 // Write out the section header
319 ACE_TString header
= ACE_TEXT ("[");
321 header
+= ACE_TEXT ("]");
322 header
+= ACE_TEXT ("\n");
323 if (ACE_WRITE_STRING (header
.fast_rep (), out
) < 0)
325 // Write out each value
328 ACE_Configuration::VALUETYPE type
;
330 ACE_TCHAR int_value
[32];
331 ACE_TCHAR bin_value
[3];
333 size_t binary_length
;
334 ACE_TString string_value
;
335 while (!config_
.enumerate_values (section
, index
, name
, type
))
337 line
= ACE_TEXT ("\"") + name
+ ACE_TEXT ("\"=");
340 case ACE_Configuration::INTEGER
:
343 if (config_
.get_integer_value (section
, name
.fast_rep (), value
))
345 ACE_OS::snprintf (int_value
, 32, ACE_TEXT ("%08x"), value
);
346 line
+= ACE_TEXT ("dword:");
350 case ACE_Configuration::STRING
:
352 if (config_
.get_string_value (section
,
356 line
+= ACE_TEXT ("\"");
357 line
+= string_value
+ ACE_TEXT ("\"");
361 case ACE_Configuration::INVALID
:
364 case ACE_Configuration::BINARY
:
366 // not supported yet - maybe use BASE64 codeing?
367 if (config_
.get_binary_value (section
,
372 line
+= ACE_TEXT ("hex:");
373 unsigned char* ptr
= (unsigned char*)binary_data
;
374 while (binary_length
)
376 if (ptr
!= binary_data
)
378 line
+= ACE_TEXT (",");
380 ACE_OS::snprintf (bin_value
, 3, ACE_TEXT ("%02x"), *ptr
);
385 #if defined (ACE_HAS_ALLOC_HOOKS)
386 ACE_Allocator::instance()->free(binary_data
);
388 delete [] (char*) binary_data
;
389 #endif /* ACE_HAS_ALLOC_HOOKS */
395 line
+= ACE_TEXT ("\n");
396 if (ACE_WRITE_STRING (line
.fast_rep (), out
) < 0)
401 // Export all sub sections
404 ACE_Configuration_Section_Key sub_key
;
405 while (!config_
.enumerate_sections (section
, index
, name
))
407 ACE_TString
sub_section (path
);
409 sub_section
+= ACE_TEXT ("\\");
411 if (config_
.open_section (section
, name
.fast_rep (), 0, sub_key
))
413 if (export_section (sub_key
, sub_section
.fast_rep (), out
))
421 // This method read the line format origionally used in ACE 5.1
424 ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR
* buffer
,
425 ACE_Configuration_Section_Key
& section
)
427 // Chop any cr/lf at the end of the line.
428 ACE_TCHAR
*endp
= ACE_OS::strpbrk (buffer
, ACE_TEXT ("\r\n"));
432 // assume this is a value, read in the value name
433 ACE_TCHAR
* end
= ACE_OS::strchr (buffer
, '=');
434 if (end
) // no =, not a value so just skip it
436 // null terminate the name
439 // determine the type
443 if(config_
.set_string_value (section
, buffer
, end
+ 1))
446 else if (*end
== '#')
449 u_int value
= ACE_OS::atoi (end
+ 1);
450 if (config_
.set_integer_value (section
, buffer
, value
))
455 } // end read_previous_line_format
458 ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration
& config
)
459 : ACE_Config_ImpExp_Base (config
)
463 // Method to read file and populate object.
465 ACE_Ini_ImpExp::import_config (const ACE_TCHAR
* filename
)
472 FILE* in
= ACE_OS::fopen (filename
, ACE_TEXT ("r"));
476 // @@ Make this a dynamic size!
477 ACE_TCHAR buffer
[4096];
478 ACE_Configuration_Section_Key section
;
479 while (ACE_OS::fgets (buffer
, sizeof buffer
, in
))
481 ACE_TCHAR
*line
= this->squish (buffer
);
482 // Check for a comment and blank line
483 if (line
[0] == ACE_TEXT (';') ||
484 line
[0] == ACE_TEXT ('#') ||
488 if (line
[0] == ACE_TEXT ('['))
490 // We have a new section here, strip out the section name
491 ACE_TCHAR
* end
= ACE_OS::strrchr (line
, ACE_TEXT (']'));
499 if (config_
.expand_path (config_
.root_section (),
511 // We have a line; name ends at equal sign.
512 ACE_TCHAR
*end
= ACE_OS::strchr (line
, ACE_TEXT ('='));
513 if (end
== 0) // No '='
519 ACE_TCHAR
*name
= this->squish (line
);
521 if (ACE_OS::strlen (name
) == 0) // No name; just an '='
527 // Now find the start of the value
528 ACE_TCHAR
*value
= this->squish (end
);
529 size_t value_len
= ACE_OS::strlen (value
);
532 // ACE 5.2 (and maybe earlier) exported strings may be enclosed
533 // in quotes. If string is quote-delimited, strip the quotes.
534 // Newer exported files don't have quote delimiters.
535 if (value
[0] == ACE_TEXT ('"') &&
536 value
[value_len
- 1] == ACE_TEXT ('"'))
538 // Strip quotes off both ends.
539 value
[value_len
- 1] = '\0';
544 if (config_
.set_string_value (section
, name
, value
))
561 // This method exports the entire configuration database to <filename>.
562 // Once the file is opened this method calls 'export_section' passing
565 ACE_Ini_ImpExp::export_config (const ACE_TCHAR
* filename
)
574 FILE* out
= ACE_OS::fopen (filename
, ACE_TEXT ("w"));
577 result
= this->export_section (config_
.root_section (),
580 // The data may have been buffered and will be flush on close,
581 // so we need to check that the close succeeds.
582 if (ACE_OS::fclose (out
) < 0)
588 // Method provided by derived classes in order to write one section to the
589 // file specified. Called by export_config when exporting the entire
590 // configuration objet
593 ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key
& section
,
594 const ACE_TString
& path
,
597 // don't export the root
600 // Write out the section header
601 ACE_TString header
= ACE_TEXT ("[");
603 header
+= ACE_TEXT ("]\n");
604 if (ACE_WRITE_STRING (header
.fast_rep (), out
) < 0)
606 // Write out each value
609 ACE_Configuration::VALUETYPE type
;
611 ACE_TCHAR int_value
[32];
612 ACE_TCHAR bin_value
[3];
614 size_t binary_length
;
615 ACE_TString string_value
;
616 while (!config_
.enumerate_values (section
, index
, name
, type
))
618 line
= name
+ ACE_TEXT ("=");
621 case ACE_Configuration::INTEGER
:
624 if (config_
.get_integer_value (section
, name
.fast_rep (), value
))
626 ACE_OS::snprintf (int_value
, 32, ACE_TEXT ("%08x"), value
);
630 case ACE_Configuration::STRING
:
632 if (config_
.get_string_value (section
,
636 line
+= string_value
;
640 case ACE_Configuration::INVALID
:
641 break; // JDO added break. Otherwise INVALID is processed
642 // like BINARY. If that's correct, please remove the
643 // break and these comments
645 case ACE_Configuration::BINARY
:
647 // not supported yet - maybe use BASE64 codeing?
648 if (config_
.get_binary_value (section
,
653 line
+= ACE_TEXT ("\"");
654 unsigned char* ptr
= (unsigned char*)binary_data
;
655 while (binary_length
)
657 if (ptr
!= binary_data
)
659 line
+= ACE_TEXT (",");
661 ACE_OS::snprintf (bin_value
, 3, ACE_TEXT ("%02x"), *ptr
);
666 line
+= ACE_TEXT ("\"");
667 #if defined (ACE_HAS_ALLOC_HOOKS)
668 ACE_Allocator::instance()->free(binary_data
);
670 delete [] (char *) binary_data
;
671 #endif /* ACE_HAS_ALLOC_HOOKS */
676 }// end switch on type
678 line
+= ACE_TEXT ("\n");
679 if (ACE_WRITE_STRING (line
.fast_rep (), out
) < 0)
682 }// end while enumerating values
684 // Export all sub sections
687 ACE_Configuration_Section_Key sub_key
;
688 while (!config_
.enumerate_sections (section
, index
, name
))
690 ACE_TString
sub_section (path
);
692 sub_section
+= ACE_TEXT ("\\");
694 if (config_
.open_section (section
, name
.fast_rep (), 0, sub_key
))
696 if (export_section (sub_key
, sub_section
.fast_rep (), out
))
703 // Method to squish leading and trailing whitespaces from a string.
704 // Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
705 // (cr/lf). The terminating nul is moved up to expunge trailing
706 // whitespace and the returned pointer points at the first
707 // non-whitespace character in the string, which may be the nul
708 // terminator if the string is all whitespace.
711 ACE_Ini_ImpExp::squish (ACE_TCHAR
*src
)
718 // Start at the end and work backwards over all whitespace.
719 for (cp
= src
+ ACE_OS::strlen (src
) - 1;
722 if (!ACE_OS::ace_isspace (*cp
))
724 cp
[1] = '\0'; // Chop trailing whitespace
726 // Now start at the beginning and move over all whitespace.
727 for (cp
= src
; ACE_OS::ace_isspace (*cp
); ++cp
)
733 ACE_END_VERSIONED_NAMESPACE_DECL