Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Configuration_Import_Export.cpp
blobd2b1d5767e3cc0aaa12c8c7fd3f2b830f4ea904b
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)
10 : config_ (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.
21 int
22 ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
24 if (0 == filename)
26 errno = EINVAL;
27 return -1;
29 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
30 if (!in)
31 return -1;
33 u_int buffer_size = 4096;
34 u_int read_pos = 0;
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)));
38 #else
39 ACE_NEW_NORETURN (buffer, ACE_TCHAR[buffer_size]);
40 #endif /* ACE_HAS_ALLOC_HOOKS */
41 if (!buffer)
43 ACE_Errno_Guard guard (errno);
44 (void) ACE_OS::fclose (in);
45 return -1;
47 ACE_Configuration_Section_Key section;
48 ACE_TCHAR *end = 0;
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)));
61 #else
62 ACE_NEW_NORETURN (temp_buffer, ACE_TCHAR[buffer_size * 2]);
63 #endif /* ACE_HAS_ALLOC_HOOKS */
64 if (!temp_buffer)
66 ACE_Errno_Guard guard (errno);
67 #if defined (ACE_HAS_ALLOC_HOOKS)
68 ACE_Allocator::instance()->free(buffer);
69 #else
70 delete [] buffer;
71 #endif /* ACE_HAS_ALLOC_HOOKS */
72 (void) ACE_OS::fclose (in);
73 return -1;
76 // copy the beginnning of the line
77 ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
78 read_pos = buffer_size - 1;
79 buffer_size *= 2;
80 #if defined (ACE_HAS_ALLOC_HOOKS)
81 ACE_Allocator::instance()->free(buffer);
82 #else
83 delete [] buffer;
84 #endif /* ACE_HAS_ALLOC_HOOKS */
85 buffer = temp_buffer;
86 continue;
88 read_pos = 0;
90 // Check for a comment
91 if (buffer[0] == ACE_TEXT (';') || buffer[0] == ACE_TEXT ('#'))
92 continue;
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 (']'));
98 if (!end)
100 ACE_OS::fclose (in);
101 #if defined (ACE_HAS_ALLOC_HOOKS)
102 ACE_Allocator::instance()->free(buffer);
103 #else
104 delete [] buffer;
105 #endif /* ACE_HAS_ALLOC_HOOKS */
106 return -3;
108 *end = 0;
110 if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
112 ACE_OS::fclose (in);
113 #if defined (ACE_HAS_ALLOC_HOOKS)
114 ACE_Allocator::instance()->free(buffer);
115 #else
116 delete [] buffer;
117 #endif /* ACE_HAS_ALLOC_HOOKS */
118 return -3;
120 continue;
121 } // end if firs char is a [
123 if (buffer[0] == ACE_TEXT ('"'))
125 // we have a value
126 end = ACE_OS::strchr (buffer+1, '"');
127 if (!end) // no closing quote, not a value so just skip it
128 continue;
130 // null terminate the name
131 *end = 0;
132 ACE_TCHAR* name = buffer + 1;
133 end+=2;
134 // determine the type
135 if (*end == '\"')
137 // string type
138 // truncate trailing "
139 ++end;
140 ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
141 if (trailing)
142 *trailing = 0;
143 if (config_.set_string_value (section, name, end))
145 ACE_OS::fclose (in);
146 #if defined (ACE_HAS_ALLOC_HOOKS)
147 ACE_Allocator::instance()->free(buffer);
148 #else
149 delete [] buffer;
150 #endif /* ACE_HAS_ALLOC_HOOKS */
151 return -4;
154 else if (ACE_OS::strncmp (end, ACE_TEXT ("dword:"), 6) == 0)
156 // number type
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)))
162 ACE_OS::fclose (in);
163 #if defined (ACE_HAS_ALLOC_HOOKS)
164 ACE_Allocator::instance()->free(buffer);
165 #else
166 delete [] buffer;
167 #endif /* ACE_HAS_ALLOC_HOOKS */
168 return -4;
171 else if (ACE_OS::strncmp (end, ACE_TEXT ("hex:"), 4) == 0)
173 // binary type
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;
178 u_char* data = 0;
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)),
182 -1);
183 #else
184 ACE_NEW_RETURN (data,
185 u_char[length],
186 -1);
187 #endif /* ACE_HAS_ALLOC_HOOKS */
188 u_char* out = data;
189 ACE_TCHAR* inb = end + 4;
190 ACE_TCHAR* endptr = 0;
191 while (remaining)
193 u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
194 *out = charin;
195 ++out;
196 --remaining;
197 inb += 3;
199 if (config_.set_binary_value (section, name, data, length))
201 ACE_OS::fclose (in);
202 #if defined (ACE_HAS_ALLOC_HOOKS)
203 ACE_Allocator::instance()->free(data);
204 ACE_Allocator::instance()->free(buffer);
205 #else
206 delete [] data;
207 delete [] buffer;
208 #endif /* ACE_HAS_ALLOC_HOOKS */
209 return -4;
211 else
212 #if defined (ACE_HAS_ALLOC_HOOKS)
213 ACE_Allocator::instance()->free(data);
214 #else
215 delete [] data;
216 #endif /* ACE_HAS_ALLOC_HOOKS */
218 else
220 // invalid type, ignore
221 continue;
223 }// end if first char is a "
224 else
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,
229 // return an error
230 int rc = process_previous_line_format (buffer, section);
231 if (rc != 0)
233 ACE_OS::fclose (in);
234 #if defined (ACE_HAS_ALLOC_HOOKS)
235 ACE_Allocator::instance()->free(buffer);
236 #else
237 delete [] buffer;
238 #endif /* ACE_HAS_ALLOC_HOOKS */
239 return rc;
241 } // end if maybe old format
242 } // end while fgets
244 if (ferror (in))
246 ACE_OS::fclose (in);
247 #if defined (ACE_HAS_ALLOC_HOOKS)
248 ACE_Allocator::instance()->free(buffer);
249 #else
250 delete [] buffer;
251 #endif /* ACE_HAS_ALLOC_HOOKS */
252 return -1;
255 ACE_OS::fclose (in);
256 #if defined (ACE_HAS_ALLOC_HOOKS)
257 ACE_Allocator::instance()->free(buffer);
258 #else
259 delete [] buffer;
260 #endif /* ACE_HAS_ALLOC_HOOKS */
261 return 0;
264 // This method exports the entire configuration database to <filename>.
265 // Once the file is opened this method calls 'export_section' passing
266 // the root section.
268 ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
270 if (0 == filename)
272 errno = EINVAL;
273 return -1;
275 int result = -1;
277 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
278 if (out)
280 result = this->export_section (config_.root_section (),
281 ACE_TEXT (""),
282 out);
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)
286 result = -7;
288 return result;
292 #if !defined ACE_USES_WCHAR && defined ACE_LACKS_FPUTS
293 # define ACE_WRITE_STRING write_string
294 namespace
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;
302 #else
303 # define ACE_WRITE_STRING ACE_OS::fputs
304 #endif
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,
313 FILE* out)
315 // don't export the root
316 if (path.length ())
318 // Write out the section header
319 ACE_TString header = ACE_TEXT ("[");
320 header += path;
321 header += ACE_TEXT ("]");
322 header += ACE_TEXT ("\n");
323 if (ACE_WRITE_STRING (header.fast_rep (), out) < 0)
324 return -1;
325 // Write out each value
326 int index = 0;
327 ACE_TString name;
328 ACE_Configuration::VALUETYPE type;
329 ACE_TString line;
330 ACE_TCHAR int_value[32];
331 ACE_TCHAR bin_value[3];
332 void* binary_data;
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 ("\"=");
338 switch (type)
340 case ACE_Configuration::INTEGER:
342 u_int value;
343 if (config_.get_integer_value (section, name.fast_rep (), value))
344 return -2;
345 ACE_OS::snprintf (int_value, 32, ACE_TEXT ("%08x"), value);
346 line += ACE_TEXT ("dword:");
347 line += int_value;
348 break;
350 case ACE_Configuration::STRING:
352 if (config_.get_string_value (section,
353 name.fast_rep (),
354 string_value))
355 return -2;
356 line += ACE_TEXT ("\"");
357 line += string_value + ACE_TEXT ("\"");
358 break;
360 #ifdef ACE_WIN32
361 case ACE_Configuration::INVALID:
362 break;
363 #endif
364 case ACE_Configuration::BINARY:
366 // not supported yet - maybe use BASE64 codeing?
367 if (config_.get_binary_value (section,
368 name.fast_rep (),
369 binary_data,
370 binary_length))
371 return -2;
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);
381 line += bin_value;
382 --binary_length;
383 ++ptr;
385 #if defined (ACE_HAS_ALLOC_HOOKS)
386 ACE_Allocator::instance()->free(binary_data);
387 #else
388 delete [] (char*) binary_data;
389 #endif /* ACE_HAS_ALLOC_HOOKS */
390 break;
392 default:
393 return -3;
395 line += ACE_TEXT ("\n");
396 if (ACE_WRITE_STRING (line.fast_rep (), out) < 0)
397 return -4;
398 ++index;
401 // Export all sub sections
402 int index = 0;
403 ACE_TString name;
404 ACE_Configuration_Section_Key sub_key;
405 while (!config_.enumerate_sections (section, index, name))
407 ACE_TString sub_section (path);
408 if (path.length ())
409 sub_section += ACE_TEXT ("\\");
410 sub_section += name;
411 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
412 return -5;
413 if (export_section (sub_key, sub_section.fast_rep (), out))
414 return -6;
415 ++index;
417 return 0;
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"));
429 if (endp != 0)
430 *endp = '\0';
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
437 *end = 0;
438 ++end;
439 // determine the type
440 if (*end == '\"')
442 // string type
443 if(config_.set_string_value (section, buffer, end + 1))
444 return -4;
446 else if (*end == '#')
448 // number type
449 u_int value = ACE_OS::atoi (end + 1);
450 if (config_.set_integer_value (section, buffer, value))
451 return -4;
454 return 0;
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)
467 if (0 == filename)
469 errno = EINVAL;
470 return -1;
472 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
473 if (!in)
474 return -1;
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 ('#') ||
485 line[0] == '\0')
486 continue;
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 (']'));
492 if (!end)
494 ACE_OS::fclose (in);
495 return -3;
497 *end = 0;
499 if (config_.expand_path (config_.root_section (),
500 line + 1,
501 section,
504 ACE_OS::fclose (in);
505 return -3;
508 continue;
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 '='
515 ACE_OS::fclose (in);
516 return -3;
518 *end++ = '\0';
519 ACE_TCHAR *name = this->squish (line);
520 #if 0
521 if (ACE_OS::strlen (name) == 0) // No name; just an '='
523 ACE_OS::fclose (in);
524 return -3;
526 #endif
527 // Now find the start of the value
528 ACE_TCHAR *value = this->squish (end);
529 size_t value_len = ACE_OS::strlen (value);
530 if (value_len > 0)
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';
540 ++value;
544 if (config_.set_string_value (section, name, value))
546 ACE_OS::fclose (in);
547 return -4;
549 } // end while fgets
551 if (ferror (in))
553 ACE_OS::fclose (in);
554 return -1;
557 ACE_OS::fclose (in);
558 return 0;
561 // This method exports the entire configuration database to <filename>.
562 // Once the file is opened this method calls 'export_section' passing
563 // the root section.
565 ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
567 if (0 == filename)
569 errno = EINVAL;
570 return -1;
572 int result = -1;
574 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
575 if (out)
577 result = this->export_section (config_.root_section (),
578 ACE_TEXT (""),
579 out);
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)
583 result = -7;
585 return result;
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,
595 FILE* out)
597 // don't export the root
598 if (path.length ())
600 // Write out the section header
601 ACE_TString header = ACE_TEXT ("[");
602 header += path;
603 header += ACE_TEXT ("]\n");
604 if (ACE_WRITE_STRING (header.fast_rep (), out) < 0)
605 return -1;
606 // Write out each value
607 int index = 0;
608 ACE_TString name;
609 ACE_Configuration::VALUETYPE type;
610 ACE_TString line;
611 ACE_TCHAR int_value[32];
612 ACE_TCHAR bin_value[3];
613 void* binary_data;
614 size_t binary_length;
615 ACE_TString string_value;
616 while (!config_.enumerate_values (section, index, name, type))
618 line = name + ACE_TEXT ("=");
619 switch (type)
621 case ACE_Configuration::INTEGER:
623 u_int value;
624 if (config_.get_integer_value (section, name.fast_rep (), value))
625 return -2;
626 ACE_OS::snprintf (int_value, 32, ACE_TEXT ("%08x"), value);
627 line += int_value;
628 break;
630 case ACE_Configuration::STRING:
632 if (config_.get_string_value (section,
633 name.fast_rep (),
634 string_value))
635 return -2;
636 line += string_value;
637 break;
639 #ifdef _WIN32
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
644 #endif
645 case ACE_Configuration::BINARY:
647 // not supported yet - maybe use BASE64 codeing?
648 if (config_.get_binary_value (section,
649 name.fast_rep (),
650 binary_data,
651 binary_length))
652 return -2;
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);
662 line += bin_value;
663 --binary_length;
664 ++ptr;
666 line += ACE_TEXT ("\"");
667 #if defined (ACE_HAS_ALLOC_HOOKS)
668 ACE_Allocator::instance()->free(binary_data);
669 #else
670 delete [] (char *) binary_data;
671 #endif /* ACE_HAS_ALLOC_HOOKS */
672 break;
674 default:
675 return -3;
676 }// end switch on type
678 line += ACE_TEXT ("\n");
679 if (ACE_WRITE_STRING (line.fast_rep (), out) < 0)
680 return -4;
681 ++index;
682 }// end while enumerating values
684 // Export all sub sections
685 int index = 0;
686 ACE_TString name;
687 ACE_Configuration_Section_Key sub_key;
688 while (!config_.enumerate_sections (section, index, name))
690 ACE_TString sub_section (path);
691 if (path.length ())
692 sub_section += ACE_TEXT ("\\");
693 sub_section += name;
694 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
695 return -5;
696 if (export_section (sub_key, sub_section.fast_rep (), out))
697 return -6;
698 ++index;
700 return 0;
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.
710 ACE_TCHAR *
711 ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
713 ACE_TCHAR *cp = 0;
715 if (src == 0)
716 return 0;
718 // Start at the end and work backwards over all whitespace.
719 for (cp = src + ACE_OS::strlen (src) - 1;
720 cp != src;
721 --cp)
722 if (!ACE_OS::ace_isspace (*cp))
723 break;
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)
728 continue;
730 return cp;
733 ACE_END_VERSIONED_NAMESPACE_DECL