00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00023
00024 #include <assert.h>
00025 #include <ctype.h>
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029
00030 #ifdef _SYSTEM_WIN32_
00031 #include <direct.h>
00032 #endif
00033
00034 #include "icl_core/os_string.h"
00035 #include "icl_core_config/AttributeTree.h"
00036
00037 using namespace std;
00038
00039 #define LOCAL_PRINTF printf
00040
00041 namespace icl_core {
00042 namespace config {
00043
00044 #ifdef _SYSTEM_WIN32_
00045 const char DSEP = '\\';
00046 const char DSEP_OTHER = '/';
00047 #else
00048 const char DSEP = '/';
00049 const char DSEP_OTHER = '\\';
00050 #endif
00051
00052 const char *comment_end_str = "}_COMMENT_";
00053 const char *comment_str = comment_end_str + 1;
00054 const char *include_str = "_INCLUDE_";
00055 const char *AttributeTree::m_file_path_str = "_ATTRIBUTE_TREE_FILE_PATH_";
00056 const char *AttributeTree::m_file_name_str = "_ATTRIBUTE_TREE_FILE_NAME_";
00057 int file_path_str_len = 0;
00058 int file_name_str_len = 0;
00059 const int INCLUDE_OFFSET = 10;
00060
00061 static char buffer[2000];
00062
00063 void readNextLineInBuffer(istream &in)
00064 {
00065 in.getline(buffer, 1998);
00066
00067 int line_length=strlen(buffer);
00068 if (line_length > 0 && buffer[line_length-1]=='\r')
00069 {
00070 buffer[line_length-1]=0;
00071 }
00072 }
00073
00074
00075
00076
00077
00078 icl_core::String FilePath::absolutePath(const icl_core::String& filename) const
00079 {
00080 if (isRelativePath(filename))
00081 {
00082 return normalizePath(currentDir() + DSEP + filename);
00083 }
00084 else
00085 {
00086 return normalizePath(filename);
00087 }
00088 }
00089
00090 bool FilePath::isRelativePath(const icl_core::String& filename)
00091 {
00092 if (filename.empty())
00093 {
00094 return true;
00095 }
00096 #ifdef _SYSTEM_WIN32_
00097
00098 return (filename.length() < 2 || filename[1] != ':');
00099 #else
00100 return filename[0] != DSEP;
00101 #endif
00102 }
00103
00104 icl_core::String FilePath::normalizePath(const icl_core::String& _filename)
00105 {
00106 if (_filename.empty())
00107 {
00108 return _filename;
00109 }
00110 string filename(_filename);
00111
00112
00113
00114
00115 string::size_type slash_before_dot;
00116 string::size_type dot_start = 0;
00117
00118 dot_start = filename.find(DSEP_OTHER, 0);
00119 while (dot_start != string::npos)
00120 {
00121 filename[dot_start] = DSEP;
00122
00123 dot_start = filename.find(DSEP_OTHER, dot_start);
00124 }
00125 dot_start = 0;
00126
00127
00128
00129
00130 while (!filename.find(string(".") + DSEP))
00131 {
00132
00133
00134 string temp_filename(filename, 2, string::npos);
00135 temp_filename.swap(filename);
00136 }
00137 #ifdef _SYSTEM_WIN32_
00138
00139 if (filename.find(string(":.") + DSEP) == 1)
00140 {
00141 string temp_filename;
00142 temp_filename.append(filename, 0, 2);
00143 dot_start += 3;
00144 temp_filename.append(filename, dot_start, filename.length() - dot_start);
00145 temp_filename.swap(filename);
00146 dot_start = 0;
00147 }
00148 #endif
00149
00150
00151
00152 dot_start = filename.find(string(1, DSEP) + "." + DSEP, 0);
00153 while (dot_start != string::npos)
00154 {
00155
00156
00157 string temp_filename(filename, 0, dot_start);
00158 temp_filename.append(filename, dot_start + 2, filename.length() - dot_start - 2);
00159 temp_filename.swap(filename);
00160
00161 dot_start = filename.find(string(1, DSEP) + "." + DSEP, dot_start);
00162 }
00163
00164
00165
00166 dot_start = filename.find(string(1, DSEP) + ".." + DSEP, 0);
00167 while (dot_start != string::npos)
00168 {
00169
00170
00171
00172
00173 slash_before_dot = filename.rfind(DSEP, dot_start - 1);
00174 if (slash_before_dot != string::npos)
00175 {
00176
00177 if (filename[slash_before_dot+1] != DSEP && filename[slash_before_dot+1] != '.' &&
00178 (slash_before_dot >= 1) ? filename[slash_before_dot-1] != ':' : 1)
00179 {
00180 dot_start += 3;
00181 string temp_filename(filename, 0, slash_before_dot);
00182 temp_filename.append(filename, dot_start, filename.length() - dot_start);
00183 temp_filename.swap(filename);
00184 }
00185 else
00186 {
00187 break;
00188 }
00189
00190 dot_start = slash_before_dot;
00191 }
00192 else if (dot_start > 0)
00193 {
00194 string temp_filename;
00195
00196 #ifdef _SYSTEM_WIN32_
00197
00198 if (filename[1] = ':')
00199 {
00200 temp_filename.append(filename, 0, 2);
00201 }
00202 #endif
00203
00204 dot_start += 2;
00205 temp_filename.append(filename, dot_start, filename.length() - dot_start);
00206 temp_filename.swap(filename);
00207 dot_start = 0;
00208 }
00209 else
00210 {
00211 break;
00212 }
00213
00214 dot_start = filename.find(string(1, DSEP) + ".." + DSEP, dot_start);
00215 }
00216
00217
00218 while (!filename.find(string(".") + DSEP))
00219 {
00220
00221
00222 string temp_filename(filename, 2, string::npos);
00223 temp_filename.swap(filename);
00224 }
00225 #ifdef _SYSTEM_WIN32_
00226 dot_start = 0;
00227
00228
00229 if ((filename.find(string(":.") + DSEP) == 1))
00230 {
00231 string temp_filename;
00232 temp_filename.append(filename, 0, 2);
00233 dot_start += 3;
00234 temp_filename.append(filename, dot_start, filename.length() - dot_start);
00235 temp_filename.swap(filename);
00236 dot_start = 0;
00237 }
00238 #endif
00239
00240 return filename;
00241 }
00242
00243 icl_core::String FilePath::exchangeSeparators(const icl_core::String& _filename)
00244 {
00245 if (_filename.empty())
00246 {
00247 return _filename;
00248 }
00249 string filename(_filename);
00250
00251
00252
00253 for (unsigned i = 0;i < filename.length();++i)
00254 {
00255 if (filename[i] == DSEP_OTHER)
00256 {
00257 filename[i] = DSEP;
00258 }
00259 }
00260
00261 return filename;
00262 }
00263
00264 icl_core::String FilePath::getEnvironment(const icl_core::String& var_name)
00265 {
00266 const char* get_env = getenv(var_name.c_str());
00267 if (get_env == NULL)
00268 {
00269 return var_name;
00270 }
00271 else
00272 {
00273 return string(get_env);
00274 }
00275 }
00276
00277 icl_core::String FilePath::replaceEnvironment(const icl_core::String& _filename)
00278 {
00279 if (_filename.empty())
00280 {
00281 return _filename;
00282 }
00283 string filename(_filename);
00284
00285
00286
00287 string::size_type dot_start = filename.find("${");
00288 while (dot_start != string::npos)
00289 {
00290 dot_start += 2;
00291 string::size_type dot_end = filename.find("}", dot_start);
00292 if (dot_end == string::npos)
00293 {
00294 printf("tFilePath::replaceEnvironment(%s)>> Failure on matching closing bracket "
00295 "'}' in substring '%s'\n", (const char*) _filename.c_str(),
00296 (const char*) string(filename, dot_start, string::npos).c_str());
00297 return _filename;
00298 }
00299 string var_name(filename, dot_start, dot_end - dot_start);
00300 string temp_filename(filename, 0, dot_start - 2);
00301 temp_filename += getEnvironment(var_name);
00302 temp_filename += string(filename, dot_end + 1, string::npos);
00303 filename.swap(temp_filename);
00304
00305 dot_start = filename.find("${");
00306 }
00307
00308
00309
00310 return filename;
00311 }
00312
00313 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00314
00318 icl_core::String FilePath::Path() const
00319 {
00320 return path();
00321 }
00322
00326 icl_core::String FilePath::Name() const
00327 {
00328 return name();
00329 }
00330
00334 icl_core::String FilePath::AbsoluteName() const
00335 {
00336 return absoluteName();
00337 }
00338
00342 icl_core::String FilePath::CurrentDir() const
00343 {
00344 return currentDir();
00345 }
00346
00350 icl_core::String FilePath::Extension() const
00351 {
00352 return extension();
00353 }
00354
00358 icl_core::String FilePath::AbsolutePath(const icl_core::String& filename) const
00359 {
00360 return absolutePath(filename);
00361 }
00362
00366 bool FilePath::IsRelativePath(const icl_core::String& filename)
00367 {
00368 return isRelativePath(filename);
00369 }
00370
00374 bool FilePath::IsRelativePath() const
00375 {
00376 return isRelativePath();
00377 }
00378
00382 icl_core::String FilePath::NormalizePath(const icl_core::String& filename)
00383 {
00384 return normalizePath(filename);
00385 }
00386
00392 icl_core::String FilePath::ExchangeSeparators(const icl_core::String& filename)
00393 {
00394 return exchangeSeparators(filename);
00395 }
00396
00400 icl_core::String FilePath::GetEnvironment(const icl_core::String& var_name)
00401 {
00402 return getEnvironment(var_name);
00403 }
00404
00408 icl_core::String FilePath::ReplaceEnvironment(const icl_core::String& filename)
00409 {
00410 return replaceEnvironment(filename);
00411 }
00412
00413 #endif
00414
00415
00416
00417 void FilePath::init(const char* filename)
00418 {
00419
00420 #ifdef _SYSTEM_WIN32_
00421 {
00422 char* buffer = new char[1000];
00423 if (_getcwd(buffer, 1000) != NULL)
00424 {
00425 buffer[999] = 0;
00426 m_pwd = buffer;
00427 }
00428 else
00429 {
00430 m_pwd = "";
00431 }
00432 delete[] buffer;
00433 }
00434 #else
00435 char* tmp;
00436 tmp = getenv("PWD");
00437 if (tmp != NULL)
00438 {
00439 m_pwd = tmp;
00440 }
00441 else
00442 {
00443 m_pwd = "";
00444 }
00445 #endif
00446 m_pwd = normalizePath(m_pwd);
00447
00448 m_file = normalizePath(absolutePath(exchangeSeparators(string(filename))));
00449
00450
00451 string::size_type last_directory_separator = m_file.rfind(DSEP);
00452 if (last_directory_separator < m_file.length())
00453 {
00454 m_file_path_name_split = last_directory_separator + 1;
00455 }
00456
00457 else
00458 {
00459 m_file_path_name_split = 0;
00460 }
00461
00462 m_file_name_extension_split = m_file.rfind('.');
00463 }
00464
00465
00466
00467
00468
00469 SubTreeList::SubTreeList(AttributeTree *sub_tree, SubTreeList *next)
00470 : m_next(next),
00471 m_sub_tree(sub_tree)
00472 {
00473 }
00474
00475 SubTreeList::~SubTreeList()
00476 {
00477 if (m_sub_tree)
00478 {
00479
00480 m_sub_tree->m_parent = 0;
00481 delete m_sub_tree;
00482 }
00483 delete m_next;
00484 }
00485
00486 void SubTreeList::copy(AttributeTree *parent)
00487 {
00488 assert(parent != NULL
00489 && "SubTreeList::copy() called with NULL parent! Allocated attribute tree would be lost!");
00490
00491 SubTreeList *loop = this;
00492 while (loop)
00493 {
00494 new AttributeTree(*loop->m_sub_tree, parent);
00495 loop = loop->m_next;
00496 }
00497 }
00498
00499 void SubTreeList::unlinkParent()
00500 {
00501 SubTreeList *loop = this;
00502 while (loop)
00503 {
00504 if (loop->m_sub_tree)
00505 {
00506 loop->m_sub_tree->m_parent = 0;
00507 }
00508 loop = loop->m_next;
00509 }
00510 }
00511
00512 void SubTreeList::unlink(AttributeTree *obsolete_tree)
00513 {
00514 SubTreeList *loop = this;
00515 SubTreeList *prev = 0;
00516 while (loop)
00517 {
00518 if (loop->m_sub_tree == obsolete_tree)
00519 {
00520 if (prev)
00521 {
00522 prev->m_next = loop->m_next;
00523 }
00524 loop->m_next = 0;
00525 loop->m_sub_tree = 0;
00526 delete loop;
00527 return;
00528 }
00529 prev = loop;
00530 loop = loop->m_next;
00531 }
00532
00533 }
00534
00535 AttributeTree* SubTreeList::subTree(const char *description)
00536 {
00537 SubTreeList *loop = this;
00538 while (loop)
00539 {
00540 if (loop->m_sub_tree && loop->m_sub_tree->getDescription()
00541 && !strcmp(loop->m_sub_tree->getDescription(), description))
00542 {
00543 return loop->m_sub_tree;
00544 }
00545 loop = loop->m_next;
00546 }
00547 return 0;
00548 }
00549
00550 int SubTreeList::contains()
00551 {
00552 int ret = 0;
00553 SubTreeList *loop = this;
00554 while (loop)
00555 {
00556 ret += loop->m_sub_tree->contains();
00557 loop = loop->m_next;
00558 }
00559 return ret;
00560 }
00561
00562 void SubTreeList::printSubTree(ostream& out, int change_style_depth, char *upper_description)
00563 {
00564 SubTreeList *loop = this;
00565 while (loop)
00566 {
00567 loop->m_sub_tree->printSubTree(out, change_style_depth, upper_description);
00568 loop = loop->m_next;
00569 }
00570 }
00571
00572 AttributeTree* SubTreeList::search(const char *description, const char *attribute)
00573 {
00574 SubTreeList *loop = this;
00575 while (loop)
00576 {
00577 AttributeTree* search = loop->m_sub_tree->search(description, attribute);
00578 if (search)
00579 {
00580 return search;
00581 }
00582 loop = loop->m_next;
00583 }
00584 return NULL;
00585 }
00586
00587 bool SubTreeList::changed()
00588 {
00589 SubTreeList *loop = this;
00590 while (loop)
00591 {
00592 if (loop->m_sub_tree->changed())
00593 {
00594 return true;
00595 }
00596 loop = loop->m_next;
00597 }
00598 return false;
00599 }
00600
00601 AttributeTree* SubTreeList::next(AttributeTree *prev)
00602 {
00603 SubTreeList *loop = this;
00604 while (loop)
00605 {
00606 if (loop->m_sub_tree == prev)
00607 {
00608 if (loop->m_next)
00609 {
00610 return loop->m_next->m_sub_tree;
00611 }
00612 }
00613 loop = loop->m_next;
00614 }
00615 return 0;
00616 }
00617
00618 void SubTreeList::unmarkChanges()
00619 {
00620 SubTreeList *loop = this;
00621 while (loop)
00622 {
00623 loop->m_sub_tree->unmarkChanges();
00624 loop = loop->m_next;
00625 }
00626 }
00627
00628 SubTreeList* SubTreeList::revertOrder(SubTreeList *new_next)
00629 {
00630 SubTreeList* ret = this;
00631 if (m_sub_tree)
00632 {
00633 m_sub_tree->revertOrder();
00634 }
00635 if (m_next)
00636 {
00637 ret = m_next->revertOrder(this);
00638 }
00639 m_next = new_next;
00640 return ret;
00641 }
00642
00643 void SubTreeList::newSubTreeList(AttributeTree *new_tree, AttributeTree* after)
00644 {
00645 SubTreeList *loop;
00646
00647 for (loop = this; loop->m_next && loop->m_sub_tree != after; loop = loop->m_next)
00648 { }
00649
00650 loop->m_next = new SubTreeList(new_tree, loop->m_next);
00651 }
00652
00654 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
00655
00659 SubTreeList *SubTreeList::RevertOrder(SubTreeList *new_next)
00660 {
00661 return revertOrder(new_next);
00662 }
00663
00668 void SubTreeList::NewSubTreeList(AttributeTree *new_tree, AttributeTree *after)
00669 {
00670 return newSubTreeList(new_tree, after);
00671 }
00672
00673 #endif
00674
00675
00676
00677
00678
00679
00680 AttributeTree::AttributeTree(const char *description, AttributeTree *parent)
00681 : m_parent(parent),
00682 m_subtree_list(NULL)
00683 {
00684 file_path_str_len = strlen(m_file_path_str);
00685 file_name_str_len = strlen(m_file_name_str);
00686 if (description)
00687 {
00688 m_this_description = icl_core::os::strdup(description);
00689 }
00690 else
00691 {
00692 m_this_description = 0;
00693 }
00694 m_this_attribute = 0;
00695 m_changed = false;
00696
00697
00698 if (m_parent)
00699 {
00700 m_parent->m_subtree_list = new SubTreeList(this, m_parent->m_subtree_list);
00701 }
00702 }
00703
00704 AttributeTree::AttributeTree(const AttributeTree& tree)
00705 : m_parent(NULL),
00706 m_subtree_list(NULL)
00707 {
00708 file_path_str_len = strlen(m_file_path_str);
00709 file_name_str_len = strlen(m_file_name_str);
00710
00711 if (&tree)
00712 {
00713 if (tree.m_this_description)
00714 {
00715 m_this_description = icl_core::os::strdup(tree.m_this_description);
00716 }
00717 else
00718 {
00719 m_this_description = 0;
00720 }
00721 if (tree.m_this_attribute)
00722 {
00723 m_this_attribute = icl_core::os::strdup(tree.m_this_attribute);
00724 }
00725 else
00726 {
00727 m_this_attribute = 0;
00728 }
00729 if (tree.m_subtree_list)
00730 {
00731 tree.m_subtree_list->copy(this);
00732 }
00733 }
00734 else
00735 {
00736 m_this_description = 0;
00737 m_this_attribute = 0;
00738 }
00739
00740 m_changed = false;
00741 }
00742
00743 AttributeTree::AttributeTree(const AttributeTree &tree, AttributeTree *parent)
00744 : m_parent(parent),
00745 m_subtree_list(NULL)
00746 {
00747 file_path_str_len = strlen(m_file_path_str);
00748 file_name_str_len = strlen(m_file_name_str);
00749
00750 if (&tree)
00751 {
00752 if (tree.m_this_description)
00753 {
00754 m_this_description = icl_core::os::strdup(tree.m_this_description);
00755 }
00756 else
00757 {
00758 m_this_description = 0;
00759 }
00760 if (tree.m_this_attribute)
00761 {
00762 m_this_attribute = icl_core::os::strdup(tree.m_this_attribute);
00763 }
00764 else
00765 {
00766 m_this_attribute = 0;
00767 }
00768 if (tree.m_subtree_list)
00769 {
00770 tree.m_subtree_list->copy(this);
00771 }
00772 }
00773 else
00774 {
00775 m_this_description = 0;
00776 m_this_attribute = 0;
00777 }
00778
00779 if (m_parent)
00780 {
00781 m_parent->m_subtree_list = new SubTreeList(this, m_parent->m_subtree_list);
00782 }
00783
00784 m_changed = false;
00785 }
00786
00787 AttributeTree::~AttributeTree()
00788 {
00789
00790 if (m_this_description)
00791 {
00792
00793 free(m_this_description);
00794 m_this_description = 0;
00795 }
00796 if (m_this_attribute)
00797 {
00798
00799 free(m_this_attribute);
00800 m_this_attribute = 0;
00801 }
00802
00803 if (m_subtree_list)
00804 {
00805
00806 delete m_subtree_list;
00807 m_subtree_list = 0;
00808
00809 }
00810
00811 unlink();
00812 }
00813
00814 void AttributeTree::unlinkSub()
00815 {
00816 if (m_subtree_list)
00817 {
00818
00819 m_subtree_list->unlinkParent();
00820
00821 m_subtree_list = 0;
00822 }
00823 }
00824
00825 void AttributeTree::unlink()
00826 {
00827 if (m_parent)
00828 {
00829 SubTreeList *first_entry = m_parent->m_subtree_list;
00830 if (first_entry->m_sub_tree == this)
00831 {
00832 m_parent->m_subtree_list = first_entry->m_next;
00833 }
00834
00835 first_entry->unlink(this);
00836 m_parent->m_changed = true;
00837 }
00838 m_parent = 0;
00839 }
00840
00841
00842 void AttributeTree::setDescription(const char *description)
00843 {
00844 free(m_this_description);
00845 if (description)
00846 {
00847 m_this_description = icl_core::os::strdup(description);
00848 }
00849 else
00850 {
00851 m_this_description = 0;
00852 }
00853 }
00854
00855 void AttributeTree::setAttribute(const char *attribute)
00856 {
00857
00858 if (!m_this_attribute || !attribute || strcmp(attribute, m_this_attribute))
00859 {
00860 free(m_this_attribute);
00861 if (attribute)
00862 {
00863 m_this_attribute = icl_core::os::strdup(attribute);
00864 }
00865 else
00866 {
00867 m_this_attribute = 0;
00868 }
00869 m_changed = true;
00870 }
00871 }
00872
00873
00874 AttributeTree* AttributeTree::subTree(const char *description)
00875 {
00876 AttributeTree *m_sub_tree = getSubTree(description);
00877 if (m_sub_tree != NULL)
00878 {
00879
00880 return m_sub_tree;
00881 }
00882 else
00883 {
00884
00885 return new AttributeTree(description, this);
00886 }
00887 }
00888
00889 AttributeTree* AttributeTree::getSubTree(const char *description)
00890 {
00891 AttributeTree *m_sub_tree;
00892
00893 if (m_subtree_list)
00894 {
00895 m_sub_tree = m_subtree_list->subTree(description);
00896 if (m_sub_tree)
00897 {
00898 return m_sub_tree;
00899 }
00900 }
00901
00902 return NULL;
00903 }
00904
00905
00906 AttributeTree *AttributeTree::setAttribute(const char *param_description, const char *attribute)
00907 {
00908 if (param_description)
00909 {
00910 char *description = icl_core::os::strdup(param_description);
00911
00912 char *subdescription;
00913 split(description, subdescription);
00914
00915 AttributeTree *ret = setAttribute(description, subdescription, attribute);
00916 free(description);
00917
00918 return ret;
00919 }
00920 setAttribute(attribute);
00921 return this;
00922 }
00923
00924 AttributeTree* AttributeTree::setAttribute(const char *description, const char *subdescription,
00925 const char *attribute)
00926 {
00927
00928 if (!description || !*description)
00929 {
00930
00931
00932 setAttribute(attribute);
00933
00934 return this;
00935 }
00936
00937
00938
00939 AttributeTree *subtree = 0;
00940 if (m_subtree_list)
00941 {
00942 subtree = m_subtree_list->subTree(description);
00943 }
00944
00945
00946 if (subtree)
00947 {
00948 return subtree->setAttribute(subdescription, attribute);
00949 }
00950
00951
00952 AttributeTree *new_subtree = new AttributeTree(description, this);
00953
00954
00955 return new_subtree->setAttribute(subdescription, attribute);
00956 }
00957
00958
00959 char *AttributeTree::getSpecialAttribute(const char *description, AttributeTree **subtree)
00960 {
00961
00962 AttributeTree *at_path_parent = this;
00963 AttributeTree *at_path = at_path_parent->m_subtree_list->subTree(description);
00964 while (at_path_parent && at_path == NULL)
00965 {
00966 at_path = at_path_parent->m_subtree_list->subTree(description);
00967 at_path_parent = at_path_parent->parentTree();
00968 }
00969
00970
00971 if (at_path && at_path->m_this_attribute)
00972 {
00973
00974
00975 if (subtree)
00976 {
00977 (*subtree) = at_path;
00978 }
00979 return at_path->m_this_attribute;
00980 }
00981 return NULL;
00982 }
00983
00984 char *AttributeTree::getAttribute(const char *param_description, const char *default_attribute,
00985 AttributeTree **subtree)
00986 {
00987 char*ret = 0;
00988 if (param_description)
00989 {
00990 char *description = icl_core::os::strdup(param_description);
00991 if (description)
00992 {
00993 AttributeTree* at = this;
00994
00995 int len = strlen(description);
00996 if (len >= file_path_str_len
00997 && !strncmp(description + (len - file_path_str_len), m_file_path_str, file_path_str_len))
00998 {
00999 ret = getSpecialAttribute(m_file_path_str, subtree);
01000 }
01001 else if (len >= file_name_str_len
01002 && !strncmp(description + (len - file_name_str_len), m_file_name_str, file_name_str_len))
01003 {
01004 ret = getSpecialAttribute(m_file_name_str, subtree);
01005 }
01006
01007
01008 if (!ret)
01009 {
01010 char *description_part = description;
01011
01012 for (; at && description_part;)
01013 {
01014
01015 char *next_description = description_part;
01016
01017 description_part = strchr(description_part, '.');
01018 if (description_part)
01019 {
01020 *description_part = 0;
01021 description_part++;
01022 }
01023 at = at->m_subtree_list->subTree(next_description);
01024 }
01025
01026
01027 if (at && at->m_this_attribute)
01028 {
01029
01030 if (subtree)
01031 {
01032 (*subtree) = at;
01033 }
01034 ret = at->m_this_attribute;
01035 }
01036 }
01037 free(description);
01038 }
01039 }
01040
01041 if (!ret)
01042 {
01043 if (subtree)
01044 {
01045 (*subtree) = 0;
01046 }
01047
01048
01049 ret = const_cast<char*>(default_attribute);
01050 }
01051
01052 return ret;
01053 }
01054
01055 char* AttributeTree::getOrSetDefault(const char *description, const char *default_attribute)
01056 {
01057 char *attribute = getAttribute(description, 0);
01058 if (!attribute)
01059 {
01060 setAttribute(description, default_attribute);
01061 attribute = const_cast<char*>(default_attribute);
01062 }
01063 return attribute;
01064 }
01065
01066 char *AttributeTree::newSubNodeDescription(const char *base_description)
01067 {
01068 int base_len = strlen(base_description);
01069 char *description = (char*)malloc(base_len + 6);
01070 assert(description != NULL);
01071 strcpy(description, base_description);
01072 int i = 1;
01073 int j = 0;
01074
01075
01076 if (base_len>0)
01077 {
01078 while (base_len>=j-1 &&
01079 sscanf(description+base_len-j-1, "%i", &i)==1)
01080 {
01081 j++;
01082 }
01083 if (j!=0)
01084 {
01085 i++;
01086 }
01087 }
01088
01089 sprintf(description + base_len - j, "%i", i);
01090
01091 while (m_subtree_list->subTree(description) && i < 100000)
01092 {
01093 i++;
01094 sprintf(description + base_len - j, "%i", i);
01095 }
01096 return description;
01097 }
01098
01099
01100 AttributeTree *AttributeTree::addNewSubTree()
01101 {
01102 char *name = newSubNodeDescription();
01103 AttributeTree *ret = setAttribute(name, 0);
01104 free(name);
01105 return ret;
01106 }
01107
01108
01109 AttributeTree *AttributeTree::addSubTree(AttributeTree *tree, AttributeTree *after)
01110 {
01111 if (tree)
01112 {
01113 if (m_subtree_list->subTree(tree->m_this_description))
01114 {
01115 char *new_description = newSubNodeDescription(tree->m_this_description);
01116 free(tree->m_this_description);
01117 tree->m_this_description = new_description;
01118 }
01119
01120 if (after == NULL)
01121 {
01122 m_subtree_list = new SubTreeList(tree, m_subtree_list);
01123 }
01124 else
01125 {
01126 m_subtree_list->newSubTreeList(tree, after);
01127 }
01128
01129 tree->m_parent = this;
01130 return tree;
01131 }
01132 else
01133 {
01134 return NULL;
01135 }
01136 }
01137
01138 void AttributeTree::printSubTree(ostream& out, int change_style_depth, const char *upper_description)
01139 {
01140
01141 if (m_this_description && (!strcmp(m_this_description, m_file_path_str)
01142 || !strcmp(m_this_description, m_file_name_str)))
01143 {
01144 return;
01145 }
01146
01147 char *the_upper_description = strdup(upper_description ? upper_description : "");
01148 char *t_description = strdup(m_this_description ? m_this_description : "");
01149 assert(the_upper_description != NULL);
01150 assert(t_description != NULL);
01151
01152
01153 if (isMultilineComment())
01154 {
01155 out << the_upper_description << comment_str << '{' << endl;
01156 out << m_this_attribute << endl;
01157 out << the_upper_description << '}' << comment_str << endl;
01158
01159 free(the_upper_description);
01160 free(t_description);
01161
01162 return;
01163 }
01164
01165 int contents = contains();
01166 if (contents >= change_style_depth || hasMultilineComment())
01167 {
01168 out << the_upper_description << t_description << '{' << endl;
01169 if (m_this_attribute && strcmp(m_this_attribute, ""))
01170 {
01171 out << the_upper_description << ':' << m_this_attribute << endl;
01172 }
01173
01174 if (m_subtree_list)
01175 {
01176 char *tab = (char*)malloc(strlen(the_upper_description) + 2);
01177 assert(tab != NULL);
01178 strcat(strcpy(tab, the_upper_description), " ");
01179 m_subtree_list->printSubTree(out, change_style_depth, tab);
01180 free(tab);
01181 }
01182
01183 out << the_upper_description << '}' << t_description << endl;
01184 }
01185 else
01186 {
01187 size_t tud_len = strlen(the_upper_description);
01188 size_t len = strlen(t_description) + tud_len + 1;
01189 char *description = static_cast<char*>(malloc(len + 1));
01190 assert(description != NULL);
01191 memset(description, 0, len + 1);
01192
01193 if ((tud_len > 0) && (the_upper_description[tud_len-1] == ' '))
01194 {
01195 strcat(strcpy(description, the_upper_description), t_description);
01196 }
01197 else
01198 {
01199 strcat(strcat(strcpy(description, the_upper_description), "."), t_description);
01200 }
01201
01202 if (m_this_attribute)
01203 {
01204 out << description << ':' << m_this_attribute << endl;
01205 }
01206
01207 if (m_subtree_list)
01208 {
01209 m_subtree_list->printSubTree(out, change_style_depth, description);
01210 }
01211 free(description);
01212 }
01213
01214 free(the_upper_description);
01215 free(t_description);
01216 }
01217
01218 int AttributeTree::save(const char *filename, int change_style_depth, bool unmark_changes)
01219 {
01220
01221
01222
01223
01224 ofstream out(filename);
01225 if (!out)
01226 {
01227 return eFILE_SAVE_ERROR;
01228 }
01229 printSubTree(out, change_style_depth, "");
01230
01231 if (unmark_changes)
01232 {
01233 unmarkChanges();
01234 }
01235
01236 return eOK;
01237 }
01238
01239 int AttributeTree::load(const char *filename, bool unmark_changes, bool process_include,
01240 bool load_comments, bool preserve_order)
01241 {
01242 if (filename == NULL || strcmp(filename, "") == 0)
01243 {
01244 printf("tAttributeTree >> Trying to load an empty configuration file.\n");
01245 return eFILE_LOAD_ERROR;
01246 }
01247
01248 icl_core::config::FilePath at_file(filename);
01249
01250 if (this == root() && !getAttribute(m_file_path_str))
01251 {
01252
01253
01254 setAttribute(m_file_path_str, at_file.path().c_str());
01255 setAttribute(m_file_name_str, at_file.name().c_str());
01256 }
01257
01258 int error;
01259 ifstream in(at_file.absoluteName().c_str());
01260 if (!in)
01261 {
01262 printf("tAttributeTree >> Could not open file '%s'\n", (const char*)at_file.absoluteName().c_str());
01263 return eFILE_LOAD_ERROR;
01264 }
01265
01266 error = get(in, process_include, load_comments, &at_file);
01267 if (error >= 0)
01268 {
01269 printf("Error in line %i while reading AttributeTree %s\n", error,
01270 (const char*) at_file.absoluteName().c_str());
01271 return eFILE_LOAD_ERROR;
01272 }
01273
01274
01275 if (unmark_changes)
01276 {
01277 unmarkChanges();
01278 }
01279 if (preserve_order)
01280 {
01281 revertOrder();
01282 }
01283
01284
01285 return eOK;
01286 }
01287
01288 int AttributeTree::get(istream &in, bool process_include, bool load_comments,
01289 const class FilePath *file_path)
01290 {
01291
01292
01293 buffer[1999] = 0;
01294 char *attribute, *line;
01295 AttributeTree *at = this;
01296 int lineno = 1;
01297
01298 readNextLineInBuffer(in);
01299
01300 do
01301 {
01302
01303 lineno++;
01304 line = buffer;
01305 while (isspace(*line))
01306 {
01307 line++;
01308 }
01309
01310 if (line[0] != '#')
01311 {
01312 attribute = strchr(line, ':');
01313 if (attribute)
01314 {
01315 *attribute = 0;
01316 if (!line[0])
01317 {
01318
01319 at->setAttribute(attribute + 1);
01320 }
01321 else
01322 {
01323 if (!strcmp(line, include_str))
01324 {
01325 if (process_include)
01326 {
01327 string include_filename(line + INCLUDE_OFFSET);
01328 include_filename = FilePath::exchangeSeparators(FilePath::replaceEnvironment(include_filename));
01329 if (FilePath::isRelativePath(include_filename))
01330 {
01331 string absolute_include_filename(file_path ? file_path->path() : getFilePath());
01332 absolute_include_filename += include_filename;
01333 include_filename = FilePath::normalizePath(absolute_include_filename);
01334 }
01335 if (at->load(include_filename.c_str(), false, process_include, load_comments) != eOK)
01336 {
01337 printf("error loading include file %s\n", (const char*)include_filename.c_str());
01338 }
01339 }
01340 else
01341 {
01342
01343 (new AttributeTree(include_str, at))->setAttribute(line + INCLUDE_OFFSET);
01344 }
01345 }
01346 else if (!strstr(line, comment_str) || load_comments)
01347 {
01348
01349 at->setAttribute(line, attribute + 1);
01350 }
01351 }
01352 }
01353 else
01354 {
01355 attribute = strchr(line, '{');
01356 if (attribute)
01357 {
01358 *attribute = 0;
01359
01360
01361 if (!strcmp(line, comment_str))
01362 {
01363 AttributeTree *at_c = 0;
01364 bool comment_end = false;
01365 if (load_comments)
01366 {
01367 at_c = new AttributeTree(comment_str, at);
01368 }
01369 do
01370 {
01371 lineno++;
01372 readNextLineInBuffer(in);
01373 line = buffer;
01374 char *line_end = buffer + strlen(buffer);
01375 line_end--;
01376 while (isspace(*line))
01377 {
01378 line++;
01379 }
01380 while (line_end >= buffer && isspace(*line_end))
01381 {
01382 line_end--;
01383 }
01384 *(line_end + 1) = 0;
01385 comment_end = (strstr(line, comment_end_str) != NULL);
01386
01387 if (load_comments && !comment_end)
01388 {
01389 at_c->appendAttribute(line, "\n");
01390 }
01391 }
01392 while (!comment_end);
01393 }
01394 else
01395 {
01396 at = at->setAttribute(line, 0);
01397 }
01398 }
01399 else
01400 {
01401 attribute = strchr(line, '}');
01402 if (attribute)
01403 {
01404 if (at == this)
01405 {
01406
01407 return -1;
01408 }
01409 else
01410 {
01411
01412 if (!at->parentTree())
01413 {
01414 return lineno;
01415 }
01416 at = at->parentTree();
01417 }
01418 }
01419 else
01420 {
01421 if (!in.eof() && line[0])
01422 {
01423
01424 return lineno;
01425 }
01426 }
01427 }
01428 }
01429 }
01430 readNextLineInBuffer(in);
01431 }
01432 while (!in.eof());
01433 return -1;
01434 }
01435
01436 void AttributeTree::split(char *&description, char *&subdescription)
01437 {
01438 subdescription = strchr(description, '.');
01439 if (subdescription)
01440 {
01441 *subdescription = 0;
01442 subdescription++;
01443 }
01444 }
01445
01446 AttributeTree* AttributeTree::search(const char *description, const char *attribute)
01447 {
01448 if (description)
01449 {
01450 if ((m_this_description && (!strcmp(description, m_this_description))) &&
01451 (attribute == 0 || (m_this_attribute && (!strcmp(attribute, m_this_attribute)))))
01452 {
01453 return this;
01454 }
01455 if (m_subtree_list)
01456 {
01457 return m_subtree_list->search(description, attribute);
01458 }
01459 }
01460 return NULL;
01461 }
01462
01463 bool AttributeTree::isAttribute(const char *description, const char *attribute)
01464 {
01465 char *content = getAttribute(description, 0);
01466
01467 if (attribute)
01468 {
01469 if (content)
01470 {
01471 return !strcmp(content, attribute);
01472 }
01473 return false;
01474 }
01475 else
01476 {
01477 return content != NULL;
01478 }
01479 }
01480
01481 bool AttributeTree::changed()
01482 {
01483 if (m_changed)
01484 {
01485 return true;
01486 }
01487 if (m_subtree_list)
01488 {
01489 return m_subtree_list->changed();
01490 }
01491 return false;
01492 }
01493
01494 void AttributeTree::unmarkChanges()
01495 {
01496 m_changed = false;
01497 if (m_subtree_list)
01498 {
01499 m_subtree_list->unmarkChanges();
01500 }
01501 }
01502
01503 int AttributeTree::contains()
01504 {
01505 int ret = 0;
01506 if (m_this_attribute)
01507 {
01508 ret++;
01509 }
01510 if (m_subtree_list)
01511 {
01512 ret += m_subtree_list->contains();
01513 }
01514 return ret;
01515 }
01516
01517 void AttributeTree::appendString(char *& dest, const char *src, const char *additional_separator)
01518 {
01519 if (!src)
01520 {
01521 return;
01522 }
01523 if (!additional_separator)
01524 {
01525 additional_separator = "";
01526 }
01527 if (dest)
01528 {
01529 int old_len = strlen(dest);
01530 int additional_len = strlen(additional_separator);
01531 int whole_len = old_len + additional_len + strlen(src);
01532 char *new_attr = static_cast<char*>(malloc(whole_len + 1));
01533 assert(new_attr != NULL);
01534 strcpy(new_attr, dest);
01535 strcpy(new_attr + old_len, additional_separator);
01536 strcpy(new_attr + old_len + additional_len, src);
01537 free(dest);
01538 dest = new_attr;
01539 }
01540 else
01541 {
01542 dest = icl_core::os::strdup(src);
01543 }
01544 m_changed = true;
01545 }
01546
01547 AttributeTree* AttributeTree::commentAttributeTree()
01548 {
01549 AttributeTree *loop = firstSubTree();
01550 while (loop)
01551 {
01552 if (loop->isComment() && loop->attribute())
01553 {
01554 return loop;
01555 }
01556 loop = nextSubTree(loop);
01557 }
01558 return NULL;
01559 }
01560
01561 bool AttributeTree::isComment()
01562 {
01563 return m_this_description && !strcmp(m_this_description, comment_str);
01564 }
01565
01566 bool AttributeTree::isMultilineComment()
01567 {
01568 return isComment() && (strchr(attribute(), '\n') != NULL);
01569 }
01570
01571 const char* AttributeTree::comment()
01572 {
01573 AttributeTree* sub_comment = commentAttributeTree();
01574 if (sub_comment)
01575 {
01576 return sub_comment->attribute();
01577 }
01578 else
01579 {
01580 return "";
01581 }
01582 }
01583
01584 bool AttributeTree::hasMultilineComment()
01585 {
01586 return strchr(comment(), '\n') != NULL;
01587 }
01588
01589 void AttributeTree::setComment(const char *comment)
01590 {
01591 setAttribute(comment_str, comment);
01592 }
01593
01595 #ifdef _IC_BUILDER_DEPRECATED_STYLE_
01596
01600 void AttributeTree::Unlink()
01601 {
01602 unlink();
01603 }
01604
01608 void AttributeTree::UnlinkSub()
01609 {
01610 unlinkSub();
01611 }
01612
01616 AttributeTree *AttributeTree::SetAttribute(const char *description,
01617 const char *attribute)
01618 {
01619 return setAttribute(description, attribute);
01620 }
01621
01626 AttributeTree *AttributeTree::SetAttribute(const char *description,
01627 const char *subdescription,
01628 const char *attribute)
01629 {
01630 return setAttribute(description, subdescription, attribute);
01631 }
01632
01636 char *AttributeTree::GetAttribute()
01637 {
01638 return getAttribute();
01639 }
01640
01644 char *AttributeTree::GetAttribute(const char *description,
01645 const char *default_attribute,
01646 AttributeTree **subtree)
01647 {
01648 return getAttribute(description, default_attribute, subtree);
01649 }
01650
01654 char *AttributeTree::GetOrSetDefault(const char *description,
01655 const char *default_attribute)
01656 {
01657 return getOrSetDefault(description, default_attribute);
01658 }
01659
01663 int AttributeTree::Save(const char *filename, int change_style_depth,
01664 bool unmark_changes)
01665 {
01666 return save(filename, change_style_depth, unmark_changes);
01667 }
01668
01672 int AttributeTree::Load(const char *filename, bool unmark_changes,
01673 bool process_include, bool load_comments,
01674 bool preserve_order)
01675 {
01676 return load(filename, unmark_changes, process_include, load_comments, preserve_order);
01677 }
01678
01682 int AttributeTree::Get(std::istream &in, bool process_include,
01683 bool load_comments, const FilePath *file_path)
01684 {
01685 return get(in, process_include, load_comments, file_path);
01686 }
01687
01691 char *AttributeTree::NewSubNodeDescription(const char *base_description)
01692 {
01693 return newSubNodeDescription(base_description);
01694 }
01695
01699 AttributeTree *AttributeTree::AddNewSubTree()
01700 {
01701 return addNewSubTree();
01702 }
01703
01707 void AttributeTree::PrintSubTree(std::ostream &out,
01708 int change_style_depth,
01709 const char *upper_description)
01710 {
01711 printSubTree(out, change_style_depth, upper_description);
01712 }
01713
01717 const char *AttributeTree::Description() const
01718 {
01719 return getDescription();
01720 }
01721
01725 const char *AttributeTree::Attribute() const
01726 {
01727 return attribute();
01728 }
01729
01733 void AttributeTree::SetDescription(const char *description)
01734 {
01735 setDescription(description);
01736 }
01737
01741 void AttributeTree::SetAttribute(const char *attribute)
01742 {
01743 setAttribute(attribute);
01744 }
01745
01749 void AttributeTree::SetComment(const char *comment)
01750 {
01751 setComment(comment);
01752 }
01753
01757 AttributeTree *AttributeTree::SubTree(const char *description)
01758 {
01759 return subTree(description);
01760 }
01761
01765 AttributeTree *AttributeTree::GetSubTree(const char *description)
01766 {
01767 return getSubTree(description);
01768 }
01769
01773 AttributeTree *AttributeTree::FirstSubTree()
01774 {
01775 return firstSubTree();
01776 }
01777
01781 AttributeTree *AttributeTree::NextSubTree(AttributeTree *subtree)
01782 {
01783 return nextSubTree(subtree);
01784 }
01785
01789 AttributeTree *AttributeTree::ParentTree()
01790 {
01791 return parentTree();
01792 }
01793
01797 AttributeTree *AttributeTree::AddSubTree(AttributeTree *subtree)
01798 {
01799 return addSubTree(subtree);
01800 }
01801
01805 AttributeTree *AttributeTree::AddNextTree(AttributeTree *nexttree)
01806 {
01807 return addNextTree(nexttree);
01808 }
01809
01815 AttributeTree *AttributeTree::Search(const char *description, const char *attribute)
01816 {
01817 return search(description, attribute);
01818 }
01819
01824 bool AttributeTree::IsAttribute(const char *description, const char *attribute)
01825 {
01826 return isAttribute(description, attribute);
01827 }
01828
01833 bool AttributeTree::Changed()
01834 {
01835 return changed();
01836 }
01837
01841 void AttributeTree::UnmarkChanges()
01842 {
01843 return unmarkChanges();
01844 }
01845
01849 int AttributeTree::Contains()
01850 {
01851 return contains();
01852 }
01853
01857 AttributeTree *AttributeTree::Parent()
01858 {
01859 return parent();
01860 }
01861
01865 AttributeTree *AttributeTree::Root()
01866 {
01867 return root();
01868 }
01869
01873 const char *AttributeTree::Comment()
01874 {
01875 return comment();
01876 }
01877
01881 bool AttributeTree::HasComment()
01882 {
01883 return hasComment();
01884 }
01885
01889 bool AttributeTree::IsComment()
01890 {
01891 return isComment();
01892 }
01893
01897 bool AttributeTree::HasMultilineComment()
01898 {
01899 return hasMultilineComment();
01900 }
01901
01905 bool AttributeTree::IsMultilineComment()
01906 {
01907 return isMultilineComment();
01908 }
01909
01913 AttributeTree *AttributeTree::CommentAttributeTree()
01914 {
01915 return commentAttributeTree();
01916 }
01917
01921 void AttributeTree::AppendAttribute(const char *attribute, const char *separator)
01922 {
01923 appendAttribute(attribute, separator);
01924 }
01925
01929 void AttributeTree::AppendDescription(const char *description, const char *separator)
01930 {
01931 appendDescription(description, separator);
01932 }
01933
01937 void AttributeTree::RevertOrder()
01938 {
01939 revertOrder();
01940 }
01941
01946 const char *AttributeTree::GetFilePath()
01947 {
01948 return getFilePath();
01949 }
01950
01955 const char *AttributeTree::FileName()
01956 {
01957 return fileName();
01958 }
01959
01960 #endif
01961
01962
01963 }
01964 }