[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / Configuration_Import_Export.cpp
blob88e6d66f2b99d19ff48065e82197b0b15d89fc33
1 // $Id: Configuration_Import_Export.cpp 80826 2008-03-04 14:51:23Z wotte $
3 #include "ace/Configuration_Import_Export.h"
4 #include "ace/OS_Errno.h"
5 #include "ace/OS_NS_stdio.h"
6 #include "ace/OS_NS_ctype.h"
7 #include "ace/OS_NS_string.h"
9 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
11 ACE_Config_ImpExp_Base::ACE_Config_ImpExp_Base (ACE_Configuration& config)
12 : config_ (config)
16 ACE_Config_ImpExp_Base::~ACE_Config_ImpExp_Base (void)
20 ACE_Registry_ImpExp::ACE_Registry_ImpExp (ACE_Configuration& config)
21 : ACE_Config_ImpExp_Base (config)
25 ACE_Registry_ImpExp::~ACE_Registry_ImpExp (void)
29 // Imports the configuration database from filename.
30 // No existing data is removed.
31 int
32 ACE_Registry_ImpExp::import_config (const ACE_TCHAR* filename)
34 if (0 == filename)
36 errno = EINVAL;
37 return -1;
39 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
40 if (!in)
41 return -1;
43 u_int buffer_size = 4096;
44 u_int read_pos = 0;
45 ACE_TCHAR *buffer = 0;
46 ACE_NEW_NORETURN (buffer, ACE_TCHAR[buffer_size]);
47 if (!buffer)
49 ACE_Errno_Guard guard (errno);
50 (void) ACE_OS::fclose (in);
51 return -1;
53 ACE_Configuration_Section_Key section;
54 ACE_TCHAR *end = 0;
56 while (ACE_OS::fgets (buffer+read_pos, buffer_size - read_pos, in))
58 // Check if we got all the line.
59 end = ACE_OS::strrchr (buffer + read_pos,
60 ACE_TEXT ('\n')); // look for end of line
61 if (!end) // we havn't reach the end of the line yet
63 // allocate a new buffer - double size the previous one
64 ACE_TCHAR *temp_buffer;
65 ACE_NEW_NORETURN (temp_buffer, ACE_TCHAR[buffer_size * 2]);
66 if (!temp_buffer)
68 ACE_Errno_Guard guard (errno);
69 delete [] buffer;
70 (void) ACE_OS::fclose (in);
71 return -1;
74 // copy the beginnning of the line
75 ACE_OS::memcpy (temp_buffer, buffer, buffer_size);
76 read_pos = buffer_size - 1;
77 buffer_size *= 2;
78 delete [] buffer;
79 buffer = temp_buffer;
80 continue;
82 read_pos = 0;
84 // Check for a comment
85 if (buffer[0] == ACE_TEXT (';') || buffer[0] == ACE_TEXT ('#'))
86 continue;
88 if (buffer[0] == ACE_TEXT ('['))
90 // We have a new section here, strip out the section name
91 end = ACE_OS::strrchr (buffer, ACE_TEXT (']'));
92 if (!end)
94 ACE_OS::fclose (in);
95 delete [] buffer;
96 return -3;
98 *end = 0;
100 if (config_.expand_path (config_.root_section (), buffer + 1, section, 1))
102 ACE_OS::fclose (in);
103 delete [] buffer;
104 return -3;
106 continue;
107 } // end if firs char is a [
109 if (buffer[0] == ACE_TEXT ('"'))
111 // we have a value
112 end = ACE_OS::strchr (buffer+1, '"');
113 if (!end) // no closing quote, not a value so just skip it
114 continue;
116 // null terminate the name
117 *end = 0;
118 ACE_TCHAR* name = buffer + 1;
119 end+=2;
120 // determine the type
121 if (*end == '\"')
123 // string type
124 // truncate trailing "
125 ++end;
126 ACE_TCHAR* trailing = ACE_OS::strrchr (end, '"');
127 if (trailing)
128 *trailing = 0;
129 if (config_.set_string_value (section, name, end))
131 ACE_OS::fclose (in);
132 delete [] buffer;
133 return -4;
136 else if (ACE_OS::strncmp (end, ACE_TEXT ("dword:"), 6) == 0)
138 // number type
139 ACE_TCHAR* endptr = 0;
140 unsigned long value = ACE_OS::strtoul (end + 6, &endptr, 16);
141 if (config_.set_integer_value (section, name, value))
143 ACE_OS::fclose (in);
144 delete [] buffer;
145 return -4;
148 else if (ACE_OS::strncmp (end, ACE_TEXT ("hex:"), 4) == 0)
150 // binary type
151 size_t string_length = ACE_OS::strlen (end + 4);
152 // divide by 3 to get the actual buffer length
153 size_t length = string_length / 3;
154 size_t remaining = length;
155 u_char* data = 0;
156 ACE_NEW_RETURN (data,
157 u_char[length],
158 -1);
159 u_char* out = data;
160 ACE_TCHAR* inb = end + 4;
161 ACE_TCHAR* endptr = 0;
162 while (remaining)
164 u_char charin = (u_char) ACE_OS::strtoul (inb, &endptr, 16);
165 *out = charin;
166 ++out;
167 --remaining;
168 inb += 3;
170 if (config_.set_binary_value (section, name, data, length))
172 ACE_OS::fclose (in);
173 delete [] data;
174 delete [] buffer;
175 return -4;
177 else
178 delete [] data;
180 else
182 // invalid type, ignore
183 continue;
185 }// end if first char is a "
186 else
188 // if the first character is not a ", [, ;, or # we may be
189 // processing a file in the old format.
190 // Try and process the line as such and if it fails,
191 // return an error
192 int rc = process_previous_line_format (buffer, section);
193 if (rc != 0)
195 ACE_OS::fclose (in);
196 delete [] buffer;
197 return rc;
199 } // end if maybe old format
200 } // end while fgets
202 if (ferror (in))
204 ACE_OS::fclose (in);
205 delete [] buffer;
206 return -1;
209 ACE_OS::fclose (in);
210 delete [] buffer;
211 return 0;
214 // This method exports the entire configuration database to <filename>.
215 // Once the file is opened this method calls 'export_section' passing
216 // the root section.
218 ACE_Registry_ImpExp::export_config (const ACE_TCHAR* filename)
220 if (0 == filename)
222 errno = EINVAL;
223 return -1;
225 int result = -1;
227 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
228 if (out)
230 result = this->export_section (config_.root_section (),
231 ACE_TEXT (""),
232 out);
233 // The data may have been buffered and will be flush on close,
234 // so we need to check that the close succeeds.
235 if (ACE_OS::fclose (out) < 0)
236 result = -7;
238 return result;
241 // Method provided by derived classes in order to write one section
242 // to the file specified. Called by export_config when exporting
243 // the entire configuration object.
246 ACE_Registry_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
247 const ACE_TString& path,
248 FILE* out)
250 // don't export the root
251 if (path.length ())
253 // Write out the section header
254 ACE_TString header = ACE_TEXT ("[");
255 header += path;
256 header += ACE_TEXT ("]");
257 header += ACE_TEXT (" \n");
258 if (ACE_OS::fputs (header.fast_rep (), out) < 0)
259 return -1;
260 // Write out each value
261 int index = 0;
262 ACE_TString name;
263 ACE_Configuration::VALUETYPE type;
264 ACE_TString line;
265 ACE_TCHAR int_value[32];
266 ACE_TCHAR bin_value[3];
267 void* binary_data;
268 size_t binary_length;
269 ACE_TString string_value;
270 while (!config_.enumerate_values (section, index, name, type))
272 line = ACE_TEXT ("\"") + name + ACE_TEXT ("\"=");
273 switch (type)
275 case ACE_Configuration::INTEGER:
277 u_int value;
278 if (config_.get_integer_value (section, name.fast_rep (), value))
279 return -2;
280 ACE_OS::sprintf (int_value, ACE_TEXT ("%08x"), value);
281 line += ACE_TEXT ("dword:");
282 line += int_value;
283 break;
285 case ACE_Configuration::STRING:
287 if (config_.get_string_value (section,
288 name.fast_rep (),
289 string_value))
290 return -2;
291 line += ACE_TEXT ("\"");
292 line += string_value + ACE_TEXT ("\"");
293 break;
295 #ifdef _WIN32
296 case ACE_Configuration::INVALID:
297 break; // JDO added break. Otherwise INVALID is processed
298 // like BINARY. If that's correct, please remove the
299 // break and these comments
300 #endif
301 case ACE_Configuration::BINARY:
303 // not supported yet - maybe use BASE64 codeing?
304 if (config_.get_binary_value (section,
305 name.fast_rep (),
306 binary_data,
307 binary_length))
308 return -2;
309 line += ACE_TEXT ("hex:");
310 unsigned char* ptr = (unsigned char*)binary_data;
311 while (binary_length)
313 if (ptr != binary_data)
315 line += ACE_TEXT (",");
317 ACE_OS::sprintf (bin_value, ACE_TEXT ("%02x"), *ptr);
318 line += bin_value;
319 --binary_length;
320 ++ptr;
322 delete [] (char*) binary_data;
323 break;
325 default:
326 return -3;
328 line += ACE_TEXT ("\n");
329 if (ACE_OS::fputs (line.fast_rep (), out) < 0)
330 return -4;
331 ++index;
334 // Export all sub sections
335 int index = 0;
336 ACE_TString name;
337 ACE_Configuration_Section_Key sub_key;
338 ACE_TString sub_section;
339 while (!config_.enumerate_sections (section, index, name))
341 ACE_TString sub_section (path);
342 if (path.length ())
343 sub_section += ACE_TEXT ("\\");
344 sub_section += name;
345 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
346 return -5;
347 if (export_section (sub_key, sub_section.fast_rep (), out))
348 return -6;
349 ++index;
351 return 0;
355 // This method read the line format origionally used in ACE 5.1
358 ACE_Registry_ImpExp::process_previous_line_format (ACE_TCHAR* buffer,
359 ACE_Configuration_Section_Key& section)
361 // Chop any cr/lf at the end of the line.
362 ACE_TCHAR *endp = ACE_OS::strpbrk (buffer, ACE_TEXT ("\r\n"));
363 if (endp != 0)
364 *endp = '\0';
366 // assume this is a value, read in the value name
367 ACE_TCHAR* end = ACE_OS::strchr (buffer, '=');
368 if (end) // no =, not a value so just skip it
370 // null terminate the name
371 *end = 0;
372 ++end;
373 // determine the type
374 if (*end == '\"')
376 // string type
377 if(config_.set_string_value (section, buffer, end + 1))
378 return -4;
380 else if (*end == '#')
382 // number type
383 u_int value = ACE_OS::atoi (end + 1);
384 if (config_.set_integer_value (section, buffer, value))
385 return -4;
388 return 0;
389 } // end read_previous_line_format
392 ACE_Ini_ImpExp::ACE_Ini_ImpExp (ACE_Configuration& config)
393 : ACE_Config_ImpExp_Base (config)
397 ACE_Ini_ImpExp::~ACE_Ini_ImpExp (void)
401 // Method to read file and populate object.
403 ACE_Ini_ImpExp::import_config (const ACE_TCHAR* filename)
405 if (0 == filename)
407 errno = EINVAL;
408 return -1;
410 FILE* in = ACE_OS::fopen (filename, ACE_TEXT ("r"));
411 if (!in)
412 return -1;
414 // @@ Make this a dynamic size!
415 ACE_TCHAR buffer[4096];
416 ACE_Configuration_Section_Key section;
417 while (ACE_OS::fgets (buffer, sizeof buffer, in))
419 ACE_TCHAR *line = this->squish (buffer);
420 // Check for a comment and blank line
421 if (line[0] == ACE_TEXT (';') ||
422 line[0] == ACE_TEXT ('#') ||
423 line[0] == '\0')
424 continue;
426 if (line[0] == ACE_TEXT ('['))
428 // We have a new section here, strip out the section name
429 ACE_TCHAR* end = ACE_OS::strrchr (line, ACE_TEXT (']'));
430 if (!end)
432 ACE_OS::fclose (in);
433 return -3;
435 *end = 0;
437 if (config_.expand_path (config_.root_section (),
438 line + 1,
439 section,
442 ACE_OS::fclose (in);
443 return -3;
446 continue;
449 // We have a line; name ends at equal sign.
450 ACE_TCHAR *end = ACE_OS::strchr (line, ACE_TEXT ('='));
451 if (end == 0) // No '='
453 ACE_OS::fclose (in);
454 return -3;
456 *end++ = '\0';
457 ACE_TCHAR *name = this->squish (line);
458 #if 0
459 if (ACE_OS::strlen (name) == 0) // No name; just an '='
461 ACE_OS::fclose (in);
462 return -3;
464 #endif
465 // Now find the start of the value
466 ACE_TCHAR *value = this->squish (end);
467 size_t value_len = ACE_OS::strlen (value);
468 if (value_len > 0)
470 // ACE 5.2 (and maybe earlier) exported strings may be enclosed
471 // in quotes. If string is quote-delimited, strip the quotes.
472 // Newer exported files don't have quote delimiters.
473 if (value[0] == ACE_TEXT ('"') &&
474 value[value_len - 1] == ACE_TEXT ('"'))
476 // Strip quotes off both ends.
477 value[value_len - 1] = '\0';
478 ++value;
482 if (config_.set_string_value (section, name, value))
484 ACE_OS::fclose (in);
485 return -4;
487 } // end while fgets
489 if (ferror (in))
491 ACE_OS::fclose (in);
492 return -1;
495 ACE_OS::fclose (in);
496 return 0;
499 // This method exports the entire configuration database to <filename>.
500 // Once the file is opened this method calls 'export_section' passing
501 // the root section.
503 ACE_Ini_ImpExp::export_config (const ACE_TCHAR* filename)
505 if (0 == filename)
507 errno = EINVAL;
508 return -1;
510 int result = -1;
512 FILE* out = ACE_OS::fopen (filename, ACE_TEXT ("w"));
513 if (out)
515 result = this->export_section (config_.root_section (),
516 ACE_TEXT (""),
517 out);
518 // The data may have been buffered and will be flush on close,
519 // so we need to check that the close succeeds.
520 if (ACE_OS::fclose (out) < 0)
521 result = -7;
523 return result;
526 // Method provided by derived classes in order to write one section to the
527 // file specified. Called by export_config when exporting the entire
528 // configuration objet
531 ACE_Ini_ImpExp::export_section (const ACE_Configuration_Section_Key& section,
532 const ACE_TString& path,
533 FILE* out)
535 // don't export the root
536 if (path.length ())
538 // Write out the section header
539 ACE_TString header = ACE_TEXT ("[");
540 header += path;
541 header += ACE_TEXT ("]\n");
542 if (ACE_OS::fputs (header.fast_rep (), out) < 0)
543 return -1;
544 // Write out each value
545 int index = 0;
546 ACE_TString name;
547 ACE_Configuration::VALUETYPE type;
548 ACE_TString line;
549 ACE_TCHAR int_value[32];
550 ACE_TCHAR bin_value[3];
551 void* binary_data;
552 size_t binary_length;
553 ACE_TString string_value;
554 while (!config_.enumerate_values (section, index, name, type))
556 line = name + ACE_TEXT ("=");
557 switch (type)
559 case ACE_Configuration::INTEGER:
561 u_int value;
562 if (config_.get_integer_value (section, name.fast_rep (), value))
563 return -2;
564 ACE_OS::sprintf (int_value, ACE_TEXT ("%08x"), value);
565 line += int_value;
566 break;
568 case ACE_Configuration::STRING:
570 if (config_.get_string_value (section,
571 name.fast_rep (),
572 string_value))
573 return -2;
574 line += string_value;
575 break;
577 #ifdef _WIN32
578 case ACE_Configuration::INVALID:
579 break; // JDO added break. Otherwise INVALID is processed
580 // like BINARY. If that's correct, please remove the
581 // break and these comments
582 #endif
583 case ACE_Configuration::BINARY:
585 // not supported yet - maybe use BASE64 codeing?
586 if (config_.get_binary_value (section,
587 name.fast_rep (),
588 binary_data,
589 binary_length))
590 return -2;
591 line += ACE_TEXT ("\"");
592 unsigned char* ptr = (unsigned char*)binary_data;
593 while (binary_length)
595 if (ptr != binary_data)
597 line += ACE_TEXT (",");
599 ACE_OS::sprintf (bin_value, ACE_TEXT ("%02x"), *ptr);
600 line += bin_value;
601 --binary_length;
602 ++ptr;
604 line += ACE_TEXT ("\"");
605 delete [] (char *) binary_data;
606 break;
608 default:
609 return -3;
611 }// end switch on type
613 line += ACE_TEXT ("\n");
614 if (ACE_OS::fputs (line.fast_rep (), out) < 0)
615 return -4;
616 ++index;
617 }// end while enumerating values
619 // Export all sub sections
620 int index = 0;
621 ACE_TString name;
622 ACE_Configuration_Section_Key sub_key;
623 ACE_TString sub_section;
624 while (!config_.enumerate_sections (section, index, name))
626 ACE_TString sub_section (path);
627 if (path.length ())
628 sub_section += ACE_TEXT ("\\");
629 sub_section += name;
630 if (config_.open_section (section, name.fast_rep (), 0, sub_key))
631 return -5;
632 if (export_section (sub_key, sub_section.fast_rep (), out))
633 return -6;
634 ++index;
636 return 0;
640 // Method to squish leading and trailing whitespaces from a string.
641 // Whitespace is defined as: spaces (' '), tabs ('\t') or end-of-line
642 // (cr/lf). The terminating nul is moved up to expunge trailing
643 // whitespace and the returned pointer points at the first
644 // non-whitespace character in the string, which may be the nul
645 // terminator if the string is all whitespace.
647 ACE_TCHAR *
648 ACE_Ini_ImpExp::squish (ACE_TCHAR *src)
650 ACE_TCHAR *cp = 0;
652 if (src == 0)
653 return 0;
655 // Start at the end and work backwards over all whitespace.
656 for (cp = src + ACE_OS::strlen (src) - 1;
657 cp != src;
658 --cp)
659 if (!ACE_OS::ace_isspace (*cp))
660 break;
661 cp[1] = '\0'; // Chop trailing whitespace
663 // Now start at the beginning and move over all whitespace.
664 for (cp = src; ACE_OS::ace_isspace (*cp); ++cp)
665 continue;
667 return cp;
670 ACE_END_VERSIONED_NAMESPACE_DECL