00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stlib/Character.h>
00025 #include <stlib/OrderedCollection.h>
00026 #include <stlib/String.h>
00027 #include <stlib/tools/Configuration.h>
00028
00029 #include <stlib/tools/HierarchyConfigReader.h>
00030
00031 namespace Tools {
00032
00033
00034 String *HierarchicalConfigurationReader::className(void) const
00035 {
00036 return new String("HierarchicalConfigurationReader");
00037 }
00038
00039
00040 Configuration *HierarchicalConfigurationReader::readConfiguration(Configuration *configuration)
00041 {
00042 stack = new OrderedCollection;
00043 return ConfigurationReader::readConfiguration(configuration);
00044 }
00045
00046 void HierarchicalConfigurationReader::readLine(void)
00047 {
00048 String *line = parseLine();
00049
00050 if (line->isEmpty()) return;
00051
00052
00053 while (line->last()->isEqual(Character::value('\\'))) {
00054 line = dynamic_cast<String *>(
00055 line->copyReplace(line->size()-1, line->size(), parseLine()));
00056 }
00057
00058 if (line->first()->isEqual(Character::value('}'))) {
00059 parseBlockClosing(line);
00060 } else {
00061 long idx;
00062 idx = line->indexOf('{');
00063 if (idx > 0 && idx < line->size()) {
00064 parseBlockOpenning(dynamic_cast<String *>(line->copy(0, idx-1)));
00065 } else {
00066 idx = line->indexOf('=');
00067 if (idx > 0 && idx < line->size()) {
00068 parseAssignment(line);
00069 }
00070 }
00071 }
00072 }
00073
00074 String *HierarchicalConfigurationReader::parseLine(void)
00075 {
00076 String *line;
00077 long idx;
00078
00079 line = dynamic_cast<String *>(_stream->nextLine());
00080 line->replaceAll(Character::tab(), Character::space());
00081
00082
00083 idx = line->indexOf('#');
00084 if (idx > 0) line = dynamic_cast<String *>(line->copy(0, idx));
00085 line = line->trimBlanks();
00086 return line;
00087 }
00088
00089 void HierarchicalConfigurationReader::parseAssignment(String *line)
00090 {
00091 String *path, *item, *value;
00092 Configuration *config;
00093 long idx = line->indexOf('=');
00094
00095 path = dynamic_cast<String *>(line->copy(0, idx))->trimBlanks();
00096 if (path->isEmpty()) return;
00097 value = dynamic_cast<String *>(line->copy(idx + 1, line->size()))->trimBlanks();
00098
00099 idx = path->lastIndexOf('.');
00100 if (idx < 0) {
00101 item = path;
00102 config = _configuration;
00103 } else {
00104 item = dynamic_cast<String *>(path->copy(idx + 1, path->size()));
00105 path = dynamic_cast<String *>(path->copy(0, idx));
00106 config = getConfigurationFor(path);
00107 }
00108 config->put(item, value);
00109 }
00110
00111 void HierarchicalConfigurationReader::parseBlockOpenning(String *line)
00112 {
00113 Configuration *subConfig = new Configuration;
00114 line = line->trimBlanks();
00115 if (line->isEmpty()) {
00116 error(new String("Configration parse error: block must have a name."),
00117 new String(__PRETTY_FUNCTION__), this);
00118 }
00119 put(line, subConfig);
00120 Configuration::instances()->put(line, subConfig);
00121 pushConfiguration();
00122 _configuration = subConfig;
00123 }
00124
00125 void HierarchicalConfigurationReader::parseBlockClosing(String *line)
00126 {
00127 popConfiguration();
00128 }
00129
00130
00131 Configuration *HierarchicalConfigurationReader::getConfigurationFor(String *path)
00132 {
00133 Configuration *config = _configuration;
00134 String *item;
00135 int index;
00136
00137 do {
00138 index = path->indexOf('.');
00139 if (index < 0) item = path;
00140 else {
00141 item = dynamic_cast<String *>(path->copy(0, index));
00142 path = dynamic_cast<String *>(path->copy(index + 1, path->size()));
00143 }
00144 config = dynamic_cast<Configuration *>(config->at(item, nil));
00145 if (config == nil) {
00146 Configuration *subConfig = new Configuration;
00147 put(item, subConfig);
00148 Configuration::instances()->put(item, subConfig);
00149 config = subConfig;
00150 }
00151 } while (item != path);
00152
00153 return config;
00154 }
00155
00156 void HierarchicalConfigurationReader::pushConfiguration(void)
00157 {
00158 stack->addFirst(_configuration);
00159 }
00160
00161 void HierarchicalConfigurationReader::popConfiguration(void)
00162 {
00163 _configuration = dynamic_cast<Configuration *>(stack->removeFirst());
00164 }
00165
00166 };