Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

HierarchyConfigReader.cc

Go to the documentation of this file.
00001 /*
00002  * HierarchyConfigReader.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Hierarchical configuration file reader.
00006  *
00007  * Copyright (c) 2004 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /* Class-accessing protocol */
00034 String *HierarchicalConfigurationReader::className(void) const
00035 {
00036     return new String("HierarchicalConfigurationReader");
00037 }
00038 
00039 /* Processing protocol */
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     /* On backslash concatenate next line */
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     /* Remove comments */
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 /* Private protocol */
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 };

Generated on Mon Nov 27 09:47:55 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2