Correct feature names
[ACE_TAO.git] / ACE / ace / Configuration_Import_Export.cpp
blob3b91d3226adea4d03da1dbbdf5193735ee90be6e
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_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.
29 int
30 ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
32 if (0 == filename)
34 errno = EINVAL;
35 return -1;
37 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
38 if (!in)
39 return -1;
41 u_int buffer_size = 4096;
42 u_int read_pos = 0;
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)));
46 #else
47 ACE_NEW_NORETURN (buffer, ACE_TCHAR[buffer_size]);
48 #endif /* ACE_HAS_ALLOC_HOOKS */
49 if (!buffer)
51 ACE_Errno_Guard guard (errno);
52 (void) ACE_OS::fclose (in);
53 return -1;
55 ACE_Configuration_Section_Key section;
56 ACE_TCHAR *end = 0;
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)));
69 #else
70 ACE_NEW_NORETURN (temp_buffer, ACE_TCHAR[buffer_size * 2]);
71 #endif /* ACE_HAS_ALLOC_HOOKS */
72 if (!temp_buffer)
74 ACE_Errno_Guard guard (errno);
75 #if defined (ACE_HAS_ALLOC_HOOKS)
76 ACE_Allocator::instance()->free(buffer);
77 #else
78 delete [] buffer;
79 #endif /* ACE_HAS_ALLOC_HOOKS */
80 (void) ACE_OS::fclose (in);
81 return -1;
84 // copy the beginnning of the line
85 ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
86 read_pos = buffer_size - 1;
87 buffer_size *= 2;
88 #if defined (ACE_HAS_ALLOC_HOOKS)
89 ACE_Allocator::instance()->free(buffer);
90 #else
91 delete [] buffer;
92 #endif /* ACE_HAS_ALLOC_HOOKS */
93 buffer = temp_buffer;
94 continue;
96 read_pos = 0;
98 // Check for a comment
99 if (buffer[0] == ACE_TEXT (';') || buffer[0] == ACE_TEXT ('#'))
100 continue;
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 (']'));
106 if (!end)
108 ACE_OS::fclose (in);
109 #if defined (ACE_HAS_ALLOC_HOOKS)
110 ACE_Allocator::instance()->free(buffer);
111 #else
112 delete [] buffer;
113 #endif /* ACE_HAS_ALLOC_HOOKS */
114 return -3;
116 *end = 0;
118 if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
120 ACE_OS::fclose (in);
121 #if defined (ACE_HAS_ALLOC_HOOKS)
122 ACE_Allocator::instance()->free(buffer);
123 #else
124 delete [] buffer;
125 #endif /* ACE_HAS_ALLOC_HOOKS */
126 return -3;
128 continue;
129 } // end if firs char is a [
131 if (buffer[0] == ACE_TEXT ('"'))
133 // we have a value
134 end = ACE_OS::strchr (buffer+1, '"');
135 if (!end) // no closing quote, not a value so just skip it
136 continue;
138 // null terminate the name
139 *end = 0;
140 ACE_TCHAR* name = buffer + 1;
141 end+=2;
142 // determine the type
143 if (*end == '\"')
145 // string type
146 // truncate trailing "
147 ++end;
148 ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
149 if (trailing)
150 *trailing = 0;
151 if (config_.set_string_value (section, name, end))
153 ACE_OS::fclose (in);
154 #if defined (ACE_HAS_ALLOC_HOOKS)
155 ACE_Allocator::instance()->free(buffer);
156 #else
157 delete [] buffer;
158 #endif /* ACE_HAS_ALLOC_HOOKS */
159 return -4;
162 else if (ACE_OS::strncmp (end, ACE_TEXT ("dword:"), 6) == 0)
164 // number type
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)))
170 ACE_OS::fclose (in);
171 #if defined (ACE_HAS_ALLOC_HOOKS)
172 ACE_Allocator::instance()->free(buffer);
173 #else
174 delete [] buffer;
175 #endif /* ACE_HAS_ALLOC_HOOKS */
176 return -4;
179 else if (ACE_OS::strncmp (end, ACE_TEXT ("hex:"), 4) == 0)
181 // binary type
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;
186 u_char* data = 0;
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)),
190 -1);
191 #else
192 ACE_NEW_RETURN (data,
193 u_char[length],
194 -1);
195 #endif /* ACE_HAS_ALLOC_HOOKS */
196 u_char* out = data;
197 ACE_TCHAR* inb = end + 4;
198 ACE_TCHAR* endptr = 0;
199 while (remaining)
201 u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
202 *out = charin;
203 ++out;
204 --remaining;
205 inb += 3;
207 if (config_.set_binary_value (section, name, data, length))
209 ACE_OS::fclose (in);
210 #if defined (ACE_HAS_ALLOC_HOOKS)
211 ACE_Allocator::instance()->free(data);
212 ACE_Allocator::instance()->free(buffer);
213 #else
214 delete [] data;
215 delete [] buffer;
216 #endif /* ACE_HAS_ALLOC_HOOKS */
217 return -4;
219 else
220 #if defined (ACE_HAS_ALLOC_HOOKS)
221 ACE_Allocator::instance()->free(data);
222 #else
223 delete [] data;
224 #endif /* ACE_HAS_ALLOC_HOOKS */
226 else
228 // invalid type, ignore
229 continue;
231 }// end if first char is a "
232 else
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,
237 // return an error
238 int rc = process_previous_line_format (buffer, section);
239 if (rc != 0)
241 ACE_OS::fclose (in);
242 #if defined (ACE_HAS_ALLOC_HOOKS)
243 ACE_Allocator::instance()->free(buffer);
244 #else
245 delete [] buffer;
246 #endif /* ACE_HAS_ALLOC_HOOKS */
247 return rc;
249 } // end if maybe old format
250 } // end while fgets
252 if (ferror (in))
254 ACE_OS::fclose (in);
255 #if defined (ACE_HAS_ALLOC_HOOKS)
256 ACE_Allocator::instance()->free(buffer);
257 #else
258 delete [] buffer;
259 #endif /* ACE_HAS_ALLOC_HOOKS */
260 return -1;
263 ACE_OS::fclose (in);
264 #if defined (ACE_HAS_ALLOC_HOOKS)
265 ACE_Allocator::instance()->free(buffer);
266 #else
267 delete [] buffer;
268 #endif /* ACE_HAS_ALLOC_HOOKS */
269 return 0;
272 // This method exports the entire configuration database to <filename>.
273 // Once the file is opened this method calls 'export_section' passing
274 // the root section.
276 ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
278 if (0 == filename)
280 errno = EINVAL;
281 return -1;
283 int result = -1;
285 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
286 if (out)
288 result = this->export_section (config_.root_section (),
289 ACE_TEXT (""),
290 out);
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)
294 result = -7;
296 return result;
300 #if !defined ACE_USES_WCHAR && defined ACE_LACKS_FPUTS
301 # define ACE_WRITE_STRING write_string
302 namespace
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;
310 #else
311 # define ACE_WRITE_STRING ACE_OS::fputs
312 #endif
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,
321 FILE* out)
323 // don't export the root
324 if (path.length ())
326 // Write out the section header
327 ACE_TString header = ACE_TEXT ("[");
328 header += path;
329 header += ACE_TEXT ("]");
330 header += ACE_TEXT ("\n");
331 if (ACE_WRITE_STRING (header.fast_rep (), out) < 0)
332 return -1;
333 // Write out each value
334 int index = 0;
335 ACE_TString name;
336 ACE_Configuration::VALUETYPE type;
337 ACE_TString line;
338 ACE_TCHAR int_value[32];
339 ACE_TCHAR bin_value[3];
340 void* binary_data;
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 ("\"=");
346 switch (type)
348 case ACE_Configuration::INTEGER:
350 u_int value;
351 if (config_.get_integer_value (section, name.fast_rep (), value))
352 return -2;
353 ACE_OS::snprintf (int_value, 32, ACE_TEXT ("%08x"), value);
354 line += ACE_TEXT ("dword:");
355 line += int_value;
356 break;
358 case ACE_Configuration::STRING:
360 if (config_.get_string_value (section,
361 name.fast_rep (),
362 string_value))
363 return -2;
364 line += ACE_TEXT ("\"");
365 line += string_value + ACE_TEXT ("\"");
366 break;
368 #ifdef ACE_WIN32
369 case ACE_Configuration::INVALID:
370 break;
371 #endif
372 case ACE_Configuration::BINARY:
374 // not supported yet - maybe use BASE64 codeing?
375 if (config_.get_binary_value (section,
376 name.fast_rep (),
377 binary_data,
378 binary_length))
379 return -2;
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);
389 line += bin_value;
390 --binary_length;
391 ++ptr;
393 #if defined (ACE_HAS_ALLOC_HOOKS)
394 ACE_Allocator::instance()->free(binary_data);
395 #else
396 delete [] (char*) binary_data;
397 #endif /* ACE_HAS_ALLOC_HOOKS */
398 break;
400 default:
401 return -3;
403 line += ACE_TEXT ("\n");
404 if (ACE_WRITE_STRING (line.fast_rep (), out) < 0)
405 return -4;
406 ++index;
409 // Export all sub sections
410 int index = 0;
411 ACE_TString name;
412 ACE_Configuration_Section_Key sub_key;
413 while (!config_.enumerate_sections (section, index, name))
415 ACE_TString sub_section (path);
416 if (path.length ())
417 sub_section += ACE_TEXT ("\\");
418 sub_section += name;
419 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
420 return -5;
421 if (export_section (sub_key, sub_section.fast_rep (), out))
422 return -6;
423 ++index;
425 return 0;
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"));
437 if (endp != 0)
438 *endp = '\0';
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
445 *end = 0;
446 ++end;
447 // determine the type
448 if (*end == '\"')
450 // string type
451 if(config_.set_string_value (section, buffer, end + 1))
452 return -4;
454 else if (*end == '#')
456 // number type
457 u_int value = ACE_OS::atoi (end + 1);
458 if (config_.set_integer_value (section, buffer, value))
459 return -4;
462 return 0;
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)
479 if (0 == filename)
481 errno = EINVAL;
482 return -1;
484 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
485 if (!in)
486 return -1;
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 ('#') ||
497 line[0] == '\0')
498 continue;
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 (']'));
504 if (!end)
506 ACE_OS::fclose (in);
507 return -3;
509 *end = 0;
511 if (config_.expand_path (config_.root_section (),
512 line + 1,
513 section,
516 ACE_OS::fclose (in);
517 return -3;
520 continue;
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 '='
527 ACE_OS::fclose (in);
528 return -3;
530 *end++ = '\0';
531 ACE_TCHAR *name = this->squish (line);
532 #if 0
533 if (ACE_OS::strlen (name) == 0) // No name; just an '='
535 ACE_OS::fclose (in);
536 return -3;
538 #endif
539 // Now find the start of the value
540 ACE_TCHAR *value = this->squish (end);
541 size_t value_len = ACE_OS::strlen (value);
542 if (value_len > 0)
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';
552 ++value;
556 if (config_.set_string_value (section, name, value))
558 ACE_OS::fclose (in);
559 return -4;
561 } // end while fgets
563 if (ferror (in))
565 ACE_OS::fclose (in);
566 return -1;
569 ACE_OS::fclose (in);
570 return 0;
573 // This method exports the entire configuration database to <filename>.
574 // Once the file is opened this method calls 'export_section' passing
575 // the root section.
577 ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
579 if (0 == filename)
581 errno = EINVAL;
582 return -1;
584 int result = -1;
586 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
587 if (out)
589 result = this->export_section (config_.root_section (),
590 ACE_TEXT (""),
591 out);
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)
595 result = -7;
597 return result;
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,
607 FILE* out)
609 // don't export the root
610 if (path.length ())
612 // Write out the section header
613 ACE_TString header = ACE_TEXT ("[");
614 header += path;
615 header += ACE_TEXT ("]\n");
616 if (ACE_WRITE_STRING (header.fast_rep (), out) < 0)
617 return -1;
618 // Write out each value
619 int index = 0;
620 ACE_TString name;
621 ACE_Configuration::VALUETYPE type;
622 ACE_TString line;
623 ACE_TCHAR int_value[32];
624 ACE_TCHAR bin_value[3];
625 void* binary_data;
626 size_t binary_length;
627 ACE_TString string_value;
628 while (!config_.enumerate_values (section, index, name, type))
630 line = name + ACE_TEXT ("=");
631 switch (type)
633 case ACE_Configuration::INTEGER:
635 u_int value;
636 if (config_.get_integer_value (section, name.fast_rep (), value))
637 return -2;
638 ACE_OS::snprintf (int_value, 32, ACE_TEXT ("%08x"), value);
639 line += int_value;
640 break;
642 case ACE_Configuration::STRING:
644 if (config_.get_string_value (section,
645 name.fast_rep (),
646 string_value))
647 return -2;
648 line += string_value;
649 break;
651 #ifdef _WIN32
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
656 #endif
657 case ACE_Configuration::BINARY:
659 // not supported yet - maybe use BASE64 codeing?
660 if (config_.get_binary_value (section,
661 name.fast_rep (),
662 binary_data,
663 binary_length))
664 return -2;
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);
674 line += bin_value;
675 --binary_length;
676 ++ptr;
678 line += ACE_TEXT ("\"");
679 #if defined (ACE_HAS_ALLOC_HOOKS)
680 ACE_Allocator::instance()->free(binary_data);
681 #else
682 delete [] (char *) binary_data;
683 #endif /* ACE_HAS_ALLOC_HOOKS */
684 break;
686 default:
687 return -3;
689 }// end switch on type
691 line += ACE_TEXT ("\n");
692 if (ACE_WRITE_STRING (line.fast_rep (), out) < 0)
693 return -4;
694 ++index;
695 }// end while enumerating values
697 // Export all sub sections
698 int index = 0;
699 ACE_TString name;
700 ACE_Configuration_Section_Key sub_key;
701 while (!config_.enumerate_sections (section, index, name))
703 ACE_TString sub_section (path);
704 if (path.length ())
705 sub_section += ACE_TEXT ("\\");
706 sub_section += name;
707 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
708 return -5;
709 if (export_section (sub_key, sub_section.fast_rep (), out))
710 return -6;
711 ++index;
713 return 0;
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.
724 ACE_TCHAR *
725 ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
727 ACE_TCHAR *cp = 0;
729 if (src == 0)
730 return 0;
732 // Start at the end and work backwards over all whitespace.
733 for (cp = src + ACE_OS::strlen (src) - 1;
734 cp != src;
735 --cp)
736 if (!ACE_OS::ace_isspace (*cp))
737 break;
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)
742 continue;
744 return cp;
747 ACE_END_VERSIONED_NAMESPACE_DECL