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_Config_ImpExp_Base::~ACE_Config_ImpExp_Base (void)
18 ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration
& config
)
19 : ACE_Config_ImpExp_Base (config
)
23 ACE_Registry_ImpExp::~ACE_Registry_ImpExp (void)
27 // Imports the configuration database from filename.
28 // No existing data is removed.
30 ACE_Registry_ImpExp::import_config (const ACE_TCHAR
* filename
)
37 FILE* in
= ACE_OS::fopen (filename
, ACE_TEXT ("r"));
41 u_int buffer_size
= 4096;
43 ACE_TCHAR
*buffer
= 0;
44 #if defined (ACE_HAS_ALLOC_HOOKS)
45 ACE_ALLOCATOR_NORETURN (buffer
, static_cast<ACE_TCHAR
*> (ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR
) * buffer_size
)));
47 ACE_NEW_NORETURN (buffer
, ACE_TCHAR
[buffer_size
]);
48 #endif /* ACE_HAS_ALLOC_HOOKS */
51 ACE_Errno_Guard
guard (errno
);
52 (void) ACE_OS::fclose (in
);
55 ACE_Configuration_Section_Key section
;
58 while (ACE_OS::fgets (buffer
+read_pos
, buffer_size
- read_pos
, in
))
60 // Check if we got all the line.
61 end
= ACE_OS::strrchr (buffer
+ read_pos
,
62 ACE_TEXT ('\n')); // look for end of line
63 if (!end
) // we havn't reach the end of the line yet
65 // allocate a new buffer - double size the previous one
66 ACE_TCHAR
*temp_buffer
;
67 #if defined (ACE_HAS_ALLOC_HOOKS)
68 ACE_ALLOCATOR_NORETURN (temp_buffer
, static_cast<ACE_TCHAR
*> (ACE_Allocator::instance()->malloc(sizeof (ACE_TCHAR
) * buffer_size
* 2)));
70 ACE_NEW_NORETURN (temp_buffer
, ACE_TCHAR
[buffer_size
* 2]);
71 #endif /* ACE_HAS_ALLOC_HOOKS */
74 ACE_Errno_Guard
guard (errno
);
75 #if defined (ACE_HAS_ALLOC_HOOKS)
76 ACE_Allocator::instance()->free(buffer
);
79 #endif /* ACE_HAS_ALLOC_HOOKS */
80 (void) ACE_OS::fclose (in
);
84 // copy the beginnning of the line
85 ACE_OS::memcpy (temp_buffer
, buffer
, buffer_size
);
86 read_pos
= buffer_size
- 1;
88 #if defined (ACE_HAS_ALLOC_HOOKS)
89 ACE_Allocator::instance()->free(buffer
);
92 #endif /* ACE_HAS_ALLOC_HOOKS */
98 // Check for a comment
99 if (buffer
[0] == ACE_TEXT (';') || buffer
[0] == ACE_TEXT ('#'))
102 if (buffer
[0] == ACE_TEXT ('['))
104 // We have a new section here, strip out the section name
105 end
= ACE_OS::strrchr (buffer
, ACE_TEXT (']'));
109 #if defined (ACE_HAS_ALLOC_HOOKS)
110 ACE_Allocator::instance()->free(buffer
);
113 #endif /* ACE_HAS_ALLOC_HOOKS */
118 if (config_
.expand_path (config_
.root_section (), buffer
+ 1, section
, 1))
121 #if defined (ACE_HAS_ALLOC_HOOKS)
122 ACE_Allocator::instance()->free(buffer
);
125 #endif /* ACE_HAS_ALLOC_HOOKS */
129 } // end if firs char is a [
131 if (buffer
[0] == ACE_TEXT ('"'))
134 end
= ACE_OS::strchr (buffer
+1, '"');
135 if (!end
) // no closing quote, not a value so just skip it
138 // null terminate the name
140 ACE_TCHAR
* name
= buffer
+ 1;
142 // determine the type
146 // truncate trailing "
148 ACE_TCHAR
* trailing
= ACE_OS::strrchr (end
, '"');
151 if (config_
.set_string_value (section
, name
, end
))
154 #if defined (ACE_HAS_ALLOC_HOOKS)
155 ACE_Allocator::instance()->free(buffer
);
158 #endif /* ACE_HAS_ALLOC_HOOKS */
162 else if (ACE_OS::strncmp (end
, ACE_TEXT ("dword:"), 6) == 0)
165 ACE_TCHAR
* endptr
= 0;
166 unsigned long value
= ACE_OS::strtoul (end
+ 6, &endptr
, 16);
167 if (config_
.set_integer_value (section
, name
,
168 static_cast<u_int
> (value
)))
171 #if defined (ACE_HAS_ALLOC_HOOKS)
172 ACE_Allocator::instance()->free(buffer
);
175 #endif /* ACE_HAS_ALLOC_HOOKS */
179 else if (ACE_OS::strncmp (end
, ACE_TEXT ("hex:"), 4) == 0)
182 size_t string_length
= ACE_OS::strlen (end
+ 4);
183 // divide by 3 to get the actual buffer length
184 size_t length
= string_length
/ 3;
185 size_t remaining
= length
;
187 #if defined (ACE_HAS_ALLOC_HOOKS)
188 ACE_ALLOCATOR_RETURN (data
,
189 static_cast<u_char
*> (ACE_Allocator::instance()->malloc(sizeof(u_char
) * length
)),
192 ACE_NEW_RETURN (data
,
195 #endif /* ACE_HAS_ALLOC_HOOKS */
197 ACE_TCHAR
* inb
= end
+ 4;
198 ACE_TCHAR
* endptr
= 0;
201 u_char charin
= (u_char
) ACE_OS::strtoul (inb
, &endptr
, 16);
207 if (config_
.set_binary_value (section
, name
, data
, length
))
210 #if defined (ACE_HAS_ALLOC_HOOKS)
211 ACE_Allocator::instance()->free(data
);
212 ACE_Allocator::instance()->free(buffer
);
216 #endif /* ACE_HAS_ALLOC_HOOKS */
220 #if defined (ACE_HAS_ALLOC_HOOKS)
221 ACE_Allocator::instance()->free(data
);
224 #endif /* ACE_HAS_ALLOC_HOOKS */
228 // invalid type, ignore
231 }// end if first char is a "
234 // if the first character is not a ", [, ;, or # we may be
235 // processing a file in the old format.
236 // Try and process the line as such and if it fails,
238 int rc
= process_previous_line_format (buffer
, section
);
242 #if defined (ACE_HAS_ALLOC_HOOKS)
243 ACE_Allocator::instance()->free(buffer
);
246 #endif /* ACE_HAS_ALLOC_HOOKS */
249 } // end if maybe old format
255 #if defined (ACE_HAS_ALLOC_HOOKS)
256 ACE_Allocator::instance()->free(buffer
);
259 #endif /* ACE_HAS_ALLOC_HOOKS */
264 #if defined (ACE_HAS_ALLOC_HOOKS)
265 ACE_Allocator::instance()->free(buffer
);
268 #endif /* ACE_HAS_ALLOC_HOOKS */
272 // This method exports the entire configuration database to <filename>.
273 // Once the file is opened this method calls 'export_section' passing
276 ACE_Registry_ImpExp::export_config (const ACE_TCHAR
* filename
)
285 FILE* out
= ACE_OS::fopen (filename
, ACE_TEXT ("w"));
288 result
= this->export_section (config_
.root_section (),
291 // The data may have been buffered and will be flush on close,
292 // so we need to check that the close succeeds.
293 if (ACE_OS::fclose (out
) < 0)
300 #if !defined ACE_USES_WCHAR && defined ACE_LACKS_FPUTS
301 # define ACE_WRITE_STRING write_string
304 int write_string (const char *string
, FILE *stream
)
306 const size_t count
= ACE_OS::strlen (string
);
307 return (ACE_OS::fwrite (string
, 1, count
, stream
) < count
) ? -1 : 0;
311 # define ACE_WRITE_STRING ACE_OS::fputs
314 // Method provided by derived classes in order to write one section
315 // to the file specified. Called by export_config when exporting
316 // the entire configuration object.
319 ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key
& section
,
320 const ACE_TString
& path
,
323 // don't export the root
326 // Write out the section header
327 ACE_TString header
= ACE_TEXT ("[");
329 header
+= ACE_TEXT ("]");
330 header
+= ACE_TEXT ("\n");
331 if (ACE_WRITE_STRING (header
.fast_rep (), out
) < 0)
333 // Write out each value
336 ACE_Configuration::VALUETYPE type
;
338 ACE_TCHAR int_value
[32];
339 ACE_TCHAR bin_value
[3];
341 size_t binary_length
;
342 ACE_TString string_value
;
343 while (!config_
.enumerate_values (section
, index
, name
, type
))
345 line
= ACE_TEXT ("\"") + name
+ ACE_TEXT ("\"=");
348 case ACE_Configuration::INTEGER
:
351 if (config_
.get_integer_value (section
, name
.fast_rep (), value
))
353 ACE_OS::snprintf (int_value
, 32, ACE_TEXT ("%08x"), value
);
354 line
+= ACE_TEXT ("dword:");
358 case ACE_Configuration::STRING
:
360 if (config_
.get_string_value (section
,
364 line
+= ACE_TEXT ("\"");
365 line
+= string_value
+ ACE_TEXT ("\"");
369 case ACE_Configuration::INVALID
:
372 case ACE_Configuration::BINARY
:
374 // not supported yet - maybe use BASE64 codeing?
375 if (config_
.get_binary_value (section
,
380 line
+= ACE_TEXT ("hex:");
381 unsigned char* ptr
= (unsigned char*)binary_data
;
382 while (binary_length
)
384 if (ptr
!= binary_data
)
386 line
+= ACE_TEXT (",");
388 ACE_OS::snprintf (bin_value
, 3, ACE_TEXT ("%02x"), *ptr
);
393 #if defined (ACE_HAS_ALLOC_HOOKS)
394 ACE_Allocator::instance()->free(binary_data
);
396 delete [] (char*) binary_data
;
397 #endif /* ACE_HAS_ALLOC_HOOKS */
403 line
+= ACE_TEXT ("\n");
404 if (ACE_WRITE_STRING (line
.fast_rep (), out
) < 0)
409 // Export all sub sections
412 ACE_Configuration_Section_Key sub_key
;
413 while (!config_
.enumerate_sections (section
, index
, name
))
415 ACE_TString
sub_section (path
);
417 sub_section
+= ACE_TEXT ("\\");
419 if (config_
.open_section (section
, name
.fast_rep (), 0, sub_key
))
421 if (export_section (sub_key
, sub_section
.fast_rep (), out
))
429 // This method read the line format origionally used in ACE 5.1
432 ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR
* buffer
,
433 ACE_Configuration_Section_Key
& section
)
435 // Chop any cr/lf at the end of the line.
436 ACE_TCHAR
*endp
= ACE_OS::strpbrk (buffer
, ACE_TEXT ("\r\n"));
440 // assume this is a value, read in the value name
441 ACE_TCHAR
* end
= ACE_OS::strchr (buffer
, '=');
442 if (end
) // no =, not a value so just skip it
444 // null terminate the name
447 // determine the type
451 if(config_
.set_string_value (section
, buffer
, end
+ 1))
454 else if (*end
== '#')
457 u_int value
= ACE_OS::atoi (end
+ 1);
458 if (config_
.set_integer_value (section
, buffer
, value
))
463 } // end read_previous_line_format
466 ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration
& config
)
467 : ACE_Config_ImpExp_Base (config
)
471 ACE_Ini_ImpExp::~ACE_Ini_ImpExp (void)
475 // Method to read file and populate object.
477 ACE_Ini_ImpExp::import_config (const ACE_TCHAR
* filename
)
484 FILE* in
= ACE_OS::fopen (filename
, ACE_TEXT ("r"));
488 // @@ Make this a dynamic size!
489 ACE_TCHAR buffer
[4096];
490 ACE_Configuration_Section_Key section
;
491 while (ACE_OS::fgets (buffer
, sizeof buffer
, in
))
493 ACE_TCHAR
*line
= this->squish (buffer
);
494 // Check for a comment and blank line
495 if (line
[0] == ACE_TEXT (';') ||
496 line
[0] == ACE_TEXT ('#') ||
500 if (line
[0] == ACE_TEXT ('['))
502 // We have a new section here, strip out the section name
503 ACE_TCHAR
* end
= ACE_OS::strrchr (line
, ACE_TEXT (']'));
511 if (config_
.expand_path (config_
.root_section (),
523 // We have a line; name ends at equal sign.
524 ACE_TCHAR
*end
= ACE_OS::strchr (line
, ACE_TEXT ('='));
525 if (end
== 0) // No '='
531 ACE_TCHAR
*name
= this->squish (line
);
533 if (ACE_OS::strlen (name
) == 0) // No name; just an '='
539 // Now find the start of the value
540 ACE_TCHAR
*value
= this->squish (end
);
541 size_t value_len
= ACE_OS::strlen (value
);
544 // ACE 5.2 (and maybe earlier) exported strings may be enclosed
545 // in quotes. If string is quote-delimited, strip the quotes.
546 // Newer exported files don't have quote delimiters.
547 if (value
[0] == ACE_TEXT ('"') &&
548 value
[value_len
- 1] == ACE_TEXT ('"'))
550 // Strip quotes off both ends.
551 value
[value_len
- 1] = '\0';
556 if (config_
.set_string_value (section
, name
, value
))
573 // This method exports the entire configuration database to <filename>.
574 // Once the file is opened this method calls 'export_section' passing
577 ACE_Ini_ImpExp::export_config (const ACE_TCHAR
* filename
)
586 FILE* out
= ACE_OS::fopen (filename
, ACE_TEXT ("w"));
589 result
= this->export_section (config_
.root_section (),
592 // The data may have been buffered and will be flush on close,
593 // so we need to check that the close succeeds.
594 if (ACE_OS::fclose (out
) < 0)
600 // Method provided by derived classes in order to write one section to the
601 // file specified. Called by export_config when exporting the entire
602 // configuration objet
605 ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key
& section
,
606 const ACE_TString
& path
,
609 // don't export the root
612 // Write out the section header
613 ACE_TString header
= ACE_TEXT ("[");
615 header
+= ACE_TEXT ("]\n");
616 if (ACE_WRITE_STRING (header
.fast_rep (), out
) < 0)
618 // Write out each value
621 ACE_Configuration::VALUETYPE type
;
623 ACE_TCHAR int_value
[32];
624 ACE_TCHAR bin_value
[3];
626 size_t binary_length
;
627 ACE_TString string_value
;
628 while (!config_
.enumerate_values (section
, index
, name
, type
))
630 line
= name
+ ACE_TEXT ("=");
633 case ACE_Configuration::INTEGER
:
636 if (config_
.get_integer_value (section
, name
.fast_rep (), value
))
638 ACE_OS::snprintf (int_value
, 32, ACE_TEXT ("%08x"), value
);
642 case ACE_Configuration::STRING
:
644 if (config_
.get_string_value (section
,
648 line
+= string_value
;
652 case ACE_Configuration::INVALID
:
653 break; // JDO added break. Otherwise INVALID is processed
654 // like BINARY. If that's correct, please remove the
655 // break and these comments
657 case ACE_Configuration::BINARY
:
659 // not supported yet - maybe use BASE64 codeing?
660 if (config_
.get_binary_value (section
,
665 line
+= ACE_TEXT ("\"");
666 unsigned char* ptr
= (unsigned char*)binary_data
;
667 while (binary_length
)
669 if (ptr
!= binary_data
)
671 line
+= ACE_TEXT (",");
673 ACE_OS::snprintf (bin_value
, 3, ACE_TEXT ("%02x"), *ptr
);
678 line
+= ACE_TEXT ("\"");
679 #if defined (ACE_HAS_ALLOC_HOOKS)
680 ACE_Allocator::instance()->free(binary_data
);
682 delete [] (char *) binary_data
;
683 #endif /* ACE_HAS_ALLOC_HOOKS */
689 }// end switch on type
691 line
+= ACE_TEXT ("\n");
692 if (ACE_WRITE_STRING (line
.fast_rep (), out
) < 0)
695 }// end while enumerating values
697 // Export all sub sections
700 ACE_Configuration_Section_Key sub_key
;
701 while (!config_
.enumerate_sections (section
, index
, name
))
703 ACE_TString
sub_section (path
);
705 sub_section
+= ACE_TEXT ("\\");
707 if (config_
.open_section (section
, name
.fast_rep (), 0, sub_key
))
709 if (export_section (sub_key
, sub_section
.fast_rep (), out
))
717 // Method to squish leading and trailing whitespaces from a string.
718 // Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
719 // (cr/lf). The terminating nul is moved up to expunge trailing
720 // whitespace and the returned pointer points at the first
721 // non-whitespace character in the string, which may be the nul
722 // terminator if the string is all whitespace.
725 ACE_Ini_ImpExp::squish (ACE_TCHAR
*src
)
732 // Start at the end and work backwards over all whitespace.
733 for (cp
= src
+ ACE_OS::strlen (src
) - 1;
736 if (!ACE_OS::ace_isspace (*cp
))
738 cp
[1] = '\0'; // Chop trailing whitespace
740 // Now start at the beginning and move over all whitespace.
741 for (cp
= src
; ACE_OS::ace_isspace (*cp
); ++cp
)
747 ACE_END_VERSIONED_NAMESPACE_DECL