Титульная страница | Пространства имен | Иерархия классов | Алфавитный указатель | Классы | Файлы | Члены пространства имен | Члены классов | Описания | Примеры

test_cfg/main.cpp

/* cls_2: Curl Like Syntax Yauheni A. Akhotnikau (C) 2001-2003 eao197@yahoo.com ------------------------------------------------- Permission is granted to anyone to use this software for any purpose on any computer system, and to redistribute it freely, subject to the following restrictions: 1. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. ------------------------------------------------- */ /* Пример разбора конфигурационного файла следующего вида: {test-cfg {sort on} {rewrite off} {cfg-file {file-name "name-1" } {file-type "txt" } } {cfg-file {file-name "name-2" } {file-type "gif" } } {header-file {name "name-4" } {type "doc" } } {header-file {name "name-3" } {type "jpg" } } } Чтение конфигурации осуществляется со стандартного потока ввода. Пример запуска: sample_test_cfg < sample/test_cfg/sample-1.cls При разборе сначала в ОП строится дерево разобранных тегов, затем осуществляется проход по этому дереву и печать того, что получилось. Данный разбор аналогичен разбору XML-файлов посредством DOM-парсеров. */ #include <iostream> #include <sstream> #include <string> #include <algorithm> // // Необходимые заголовочные файлы cls-2 // // Класс для форматированого отображения значений // тега в синтаксисе CLS. #include <cls_2/h/def_tag_formatter.hpp> // Средства разбора с применением std::istream и std::ostream. #include <cls_2/std_cpp/h/utils.hpp> // Класс cls_2::tag_no_value_t для представления тегов 'test-cfg', // 'cfg-file', 'header-file'. #include <cls_2/h/tag_no_value.hpp> // Класс cls_2::tag_vector_of_tags_t< T > для представления // тегов, которые могут указываться несколько раз: // 'cfg-file', 'header-file'. #include <cls_2/h/tag_vector_of_tags.hpp> // Класс cls_2::tag_scalar_t< T > для представления // тегов с одиночными скалярными значениями. #include <cls_2/scalar/h/tag_scalar.hpp> // Класс, позволяющий интерпритировать значения, указанные // без двойных кавычек, как строки. #include <cls_2/scalar/h/nonspace_format.hpp> /* Класс тега cfg-file. Содержит два обязательных тега: 'file-name', 'file-type'. Поскольку теги cfg-file могут указываться в test-cfg неоднократно, класс для тега cfg-file будет использоваться в качестве параметра шаблона для cls_2::tag_vector_of_tags_t. Поэтому на конструктор tag_cfg_file_t накладываются ограничения. */ class tag_cfg_file_t : public cls_2::tag_no_value_t { typedef cls_2::tag_no_value_t base_type_t; public : // Формат конструктора определяется требованиями // класса cls_2::tag_vector_of_tags_t. tag_cfg_file_t( // Имя тега. const char * name, // Обязательный ли тег? bool is_mandatory ); virtual ~tag_cfg_file_t(); // Определение значения тега file-name. const std::string & query_file_name() const; // Определение значения тега file-type. const std::string & query_file_type() const; private : // Подчиненый тег file-name. cls_2::tag_scalar_t< std::string > m_tag_file_name; // Подчиненый тег file-type. cls_2::tag_scalar_t< std::string > m_tag_file_type; }; tag_cfg_file_t::tag_cfg_file_t( const char * name, bool is_mandatory ) : // Инициализация базового класса... base_type_t( name, is_mandatory, // ... этот параметр роли не играет, т.к. // класс cls_2::tag_vector_of_tags_t на // каждое новое вхождение тега cfg-file // будет создавать новый экземпляр // tag_cfg_file_t. false ), // ... и подчиненных тегов. m_tag_file_name( self_tag(), "file-name", true ), m_tag_file_type( self_tag(), "file-type", true ) { } tag_cfg_file_t::~tag_cfg_file_t() { } // // В следующих методах сделано предположение, что // они будут вызываться только для корректно разобранного // тега cfg-file. Т.е. когда все подчиненные теги // гарантированно определены. // const std::string & tag_cfg_file_t::query_file_name() const { return m_tag_file_name.query_value(); } const std::string & tag_cfg_file_t::query_file_type() const { return m_tag_file_type.query_value(); } /* Класс тега header-file. Содержит два обязательных тега: 'name', 'type'. Поскольку теги header-file могут указываться в test-cfg неоднократно, класс для тега header-file будет использоваться в качестве параметра шаблона для cls_2::tag_vector_of_tags_t. Поэтому на конструктор tag_header_file_t накладываются ограничения. */ class tag_header_file_t : public cls_2::tag_no_value_t { typedef cls_2::tag_no_value_t base_type_t; public : // Формат конструктора определяется требованиями // класса cls_2::tag_vector_of_tags_t. tag_header_file_t( // Имя тега. const char * name, // Обязательный ли тег? bool is_mandatory ); virtual ~tag_header_file_t(); // Определение значения тега name. // Назвать этот метод просто query_name нельзя, // т.к. метод с таким именем уже определен в // базовом классе. const std::string & query_tag_name() const; // Определение значения тега type. const std::string & query_tag_type() const; private : // Подчиненый тег name. cls_2::tag_scalar_t< std::string > m_tag_name; // Подчиненый тег type. cls_2::tag_scalar_t< std::string > m_tag_type; }; tag_header_file_t::tag_header_file_t( const char * name, bool is_mandatory ) : // Инициализация базового класса... base_type_t( name, is_mandatory, // ... этот параметр роли не играет, т.к. // класс cls_2::tag_vector_of_tags_t на // каждое новое вхождение тега header-file // будет создавать новый экземпляр // tag_header_file_t. false ), // ... и подчиненных тегов. m_tag_name( self_tag(), "name", true ), m_tag_type( self_tag(), "type", true ) { } tag_header_file_t::~tag_header_file_t() { } // // В следующих методах сделано предположение, что // они будут вызываться только для корректно разобранного // тега header-file. Т.е. когда все подчиненные теги // гарантированно определены. // const std::string & tag_header_file_t::query_tag_name() const { return m_tag_name.query_value(); } const std::string & tag_header_file_t::query_tag_type() const { return m_tag_type.query_value(); } /* Класс тега test-cfg. Содержит два необязательных тега: 'sort', 'rewrite' Содержит два обязательных тега 'file-name', 'file-type', которые могут указываться по нескольку раз. */ class tag_test_cfg_t : public cls_2::tag_no_value_t { typedef cls_2::tag_no_value_t base_type_t; public : tag_test_cfg_t(); virtual ~tag_test_cfg_t(); // Печать всего, что получилось на стандартный поток вывода. void show() const; private : // Подчиненный тег sort. cls_2::tag_scalar_t< std::string, cls_2::scalar_nonspace_format_t > m_tag_sort; // Подчиненный тег rewrite. cls_2::tag_scalar_t< std::string, cls_2::scalar_nonspace_format_t > m_tag_rewrite; // Вектор подчиненных тегов cfg-file. cls_2::tag_vector_of_tags_t< tag_cfg_file_t > m_tag_cfg_file; // Вектор подчиненных тегов header-file. cls_2::tag_vector_of_tags_t< tag_header_file_t > m_tag_header_file; }; tag_test_cfg_t::tag_test_cfg_t() : // Инициализируем базовый тип. base_type_t( "test-cfg", // обязательный тег, true, // должен присутствовать только в одном экземпляре. true ), // Инициализируем подчиненные теги. m_tag_sort( self_tag(), "sort", false ), m_tag_rewrite( self_tag(), "rewrite", false ), m_tag_cfg_file( self_tag(), "cfg-file", true ), m_tag_header_file( self_tag(), "header-file", true ) { } tag_test_cfg_t::~tag_test_cfg_t() { } void show_cfg_file( const tag_cfg_file_t & t ) { std::cout << "cfg-file: file-name: " << t.query_file_name() << ", file-type: " << t.query_file_type() << std::endl; } void show_header_file( const tag_header_file_t & t ) { std::cout << "header-file: name: " << t.query_tag_name() << ", type: " << t.query_tag_type() << std::endl; } void tag_test_cfg_t::show() const { if( m_tag_sort.is_defined() ) // Значение тега sort определено. std::cout << "sort: " << m_tag_sort.query_value() << std::endl; if( m_tag_rewrite.is_defined() ) // Значение тега rewrite определено. std::cout << "rewrite: " << m_tag_rewrite.query_value() << std::endl; // Печатаем значения тегов cfg-file. std::for_each( m_tag_cfg_file.begin(), m_tag_cfg_file.end(), show_cfg_file ); // Печатаем значения тегов header-file. std::for_each( m_tag_header_file.begin(), m_tag_header_file.end(), show_header_file ); } int main( int argc, char ** argv ) { // Подготовка всего необходимого для разбора. // Главный тег... tag_test_cfg_t tag; // ... список тегов для разбора. cls_2::tag_t * tags[] = { &tag }; // Осуществляем разбор. // Если задано имя файла в командной строке, то разбираем файл. int ret_code; if( 2 == argc ) ret_code = cls_2::std_cpp::parse_file( argv[ 1 ], // Используемые теги. tags, sizeof( tags ) / sizeof( tags[ 0 ] ), // Поток ошибок. &std::cerr ); else ret_code = cls_2::std_cpp::parse_istream( // Входной поток и его имя. std::cin, "stdin", // Используемые теги. tags, sizeof( tags ) / sizeof( tags[ 0 ] ), // Поток ошибок. &std::cerr ); if( cls_2::c_ok == ret_code ) { // Разбор завершился успешно. tag.show(); // Отображаем значение тега в формате CLS. cls_2::def_tag_formatter_t< std::ostream > tag_formatter( std::cout ); tag.format( tag_formatter ); } return ret_code; }
00001 /* 00002 00003 cls_2: Curl Like Syntax 00004 Yauheni A. Akhotnikau (C) 2001-2003 00005 eao197@yahoo.com 00006 ------------------------------------------------- 00007 00008 Permission is granted to anyone to use this software for any purpose on any 00009 computer system, and to redistribute it freely, subject to the following 00010 restrictions: 00011 00012 1. This software is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00015 00016 2. The origin of this software must not be misrepresented, either by 00017 explicit claim or by omission. 00018 00019 3. Altered versions must be plainly marked as such, and must not be 00020 misrepresented as being the original software. 00021 00022 ------------------------------------------------- 00023 00024 */ 00025 /* 00026 Пример разбора конфигурационного файла следующего вида: 00027 00028 {test-cfg 00029 {sort on} 00030 {rewrite off} 00031 {cfg-file 00032 {file-name "name-1" } 00033 {file-type "txt" } 00034 } 00035 {cfg-file 00036 {file-name "name-2" } 00037 {file-type "gif" } 00038 } 00039 {header-file 00040 {name "name-4" } 00041 {type "doc" } 00042 } 00043 {header-file 00044 {name "name-3" } 00045 {type "jpg" } 00046 } 00047 } 00048 00049 Чтение конфигурации осуществляется со стандартного потока 00050 ввода. Пример запуска: 00051 sample_test_cfg < sample/test_cfg/sample-1.cls 00052 00053 При разборе сначала в ОП строится дерево разобранных тегов, 00054 затем осуществляется проход по этому дереву и печать того, 00055 что получилось. Данный разбор аналогичен разбору XML-файлов 00056 посредством DOM-парсеров. 00057 00058 */ 00059 00060 #include <iostream> 00061 #include <sstream> 00062 #include <string> 00063 #include <algorithm> 00064 00065 // 00066 // Необходимые заголовочные файлы cls-2 00067 // 00068 00069 // Класс для форматированого отображения значений 00070 // тега в синтаксисе CLS. 00071 #include <cls_2/h/def_tag_formatter.hpp> 00072 00073 // Средства разбора с применением std::istream и std::ostream. 00074 #include <cls_2/std_cpp/h/utils.hpp> 00075 00076 // Класс cls_2::tag_no_value_t для представления тегов 'test-cfg', 00077 // 'cfg-file', 'header-file'. 00078 #include <cls_2/h/tag_no_value.hpp> 00079 00080 // Класс cls_2::tag_vector_of_tags_t< T > для представления 00081 // тегов, которые могут указываться несколько раз: 00082 // 'cfg-file', 'header-file'. 00083 #include <cls_2/h/tag_vector_of_tags.hpp> 00084 00085 // Класс cls_2::tag_scalar_t< T > для представления 00086 // тегов с одиночными скалярными значениями. 00087 #include <cls_2/scalar/h/tag_scalar.hpp> 00088 00089 // Класс, позволяющий интерпритировать значения, указанные 00090 // без двойных кавычек, как строки. 00091 #include <cls_2/scalar/h/nonspace_format.hpp> 00092 00093 /* 00094 Класс тега cfg-file. 00095 00096 Содержит два обязательных тега: 'file-name', 'file-type'. 00097 00098 Поскольку теги cfg-file могут указываться в test-cfg 00099 неоднократно, класс для тега cfg-file будет использоваться 00100 в качестве параметра шаблона для cls_2::tag_vector_of_tags_t. 00101 Поэтому на конструктор tag_cfg_file_t накладываются 00102 ограничения. 00103 */ 00104 class tag_cfg_file_t : 00105 public cls_2::tag_no_value_t 00106 { 00107 typedef cls_2::tag_no_value_t base_type_t; 00108 public : 00109 // Формат конструктора определяется требованиями 00110 // класса cls_2::tag_vector_of_tags_t. 00111 tag_cfg_file_t( 00112 // Имя тега. 00113 const char * name, 00114 // Обязательный ли тег? 00115 bool is_mandatory ); 00116 virtual ~tag_cfg_file_t(); 00117 00118 // Определение значения тега file-name. 00119 const std::string & 00120 query_file_name() const; 00121 00122 // Определение значения тега file-type. 00123 const std::string & 00124 query_file_type() const; 00125 00126 private : 00127 // Подчиненый тег file-name. 00128 cls_2::tag_scalar_t< std::string > 00129 m_tag_file_name; 00130 00131 // Подчиненый тег file-type. 00132 cls_2::tag_scalar_t< std::string > 00133 m_tag_file_type; 00134 }; 00135 00136 tag_cfg_file_t::tag_cfg_file_t( 00137 const char * name, 00138 bool is_mandatory ) 00139 : 00140 // Инициализация базового класса... 00141 base_type_t( name, is_mandatory, 00142 // ... этот параметр роли не играет, т.к. 00143 // класс cls_2::tag_vector_of_tags_t на 00144 // каждое новое вхождение тега cfg-file 00145 // будет создавать новый экземпляр 00146 // tag_cfg_file_t. 00147 false ), 00148 // ... и подчиненных тегов. 00149 m_tag_file_name( self_tag(), "file-name", true ), 00150 m_tag_file_type( self_tag(), "file-type", true ) 00151 { 00152 } 00153 00154 tag_cfg_file_t::~tag_cfg_file_t() 00155 { 00156 } 00157 00158 // 00159 // В следующих методах сделано предположение, что 00160 // они будут вызываться только для корректно разобранного 00161 // тега cfg-file. Т.е. когда все подчиненные теги 00162 // гарантированно определены. 00163 // 00164 00165 const std::string & 00166 tag_cfg_file_t::query_file_name() const 00167 { 00168 return m_tag_file_name.query_value(); 00169 } 00170 00171 const std::string & 00172 tag_cfg_file_t::query_file_type() const 00173 { 00174 return m_tag_file_type.query_value(); 00175 } 00176 00177 /* 00178 Класс тега header-file. 00179 00180 Содержит два обязательных тега: 'name', 'type'. 00181 00182 Поскольку теги header-file могут указываться в test-cfg 00183 неоднократно, класс для тега header-file будет использоваться 00184 в качестве параметра шаблона для cls_2::tag_vector_of_tags_t. 00185 Поэтому на конструктор tag_header_file_t накладываются 00186 ограничения. 00187 */ 00188 class tag_header_file_t : 00189 public cls_2::tag_no_value_t 00190 { 00191 typedef cls_2::tag_no_value_t base_type_t; 00192 public : 00193 // Формат конструктора определяется требованиями 00194 // класса cls_2::tag_vector_of_tags_t. 00195 tag_header_file_t( 00196 // Имя тега. 00197 const char * name, 00198 // Обязательный ли тег? 00199 bool is_mandatory ); 00200 virtual ~tag_header_file_t(); 00201 00202 // Определение значения тега name. 00203 // Назвать этот метод просто query_name нельзя, 00204 // т.к. метод с таким именем уже определен в 00205 // базовом классе. 00206 const std::string & 00207 query_tag_name() const; 00208 00209 // Определение значения тега type. 00210 const std::string & 00211 query_tag_type() const; 00212 00213 private : 00214 // Подчиненый тег name. 00215 cls_2::tag_scalar_t< std::string > 00216 m_tag_name; 00217 00218 // Подчиненый тег type. 00219 cls_2::tag_scalar_t< std::string > 00220 m_tag_type; 00221 }; 00222 00223 tag_header_file_t::tag_header_file_t( 00224 const char * name, 00225 bool is_mandatory ) 00226 : 00227 // Инициализация базового класса... 00228 base_type_t( name, is_mandatory, 00229 // ... этот параметр роли не играет, т.к. 00230 // класс cls_2::tag_vector_of_tags_t на 00231 // каждое новое вхождение тега header-file 00232 // будет создавать новый экземпляр 00233 // tag_header_file_t. 00234 false ), 00235 // ... и подчиненных тегов. 00236 m_tag_name( self_tag(), "name", true ), 00237 m_tag_type( self_tag(), "type", true ) 00238 { 00239 } 00240 00241 tag_header_file_t::~tag_header_file_t() 00242 { 00243 } 00244 00245 // 00246 // В следующих методах сделано предположение, что 00247 // они будут вызываться только для корректно разобранного 00248 // тега header-file. Т.е. когда все подчиненные теги 00249 // гарантированно определены. 00250 // 00251 00252 const std::string & 00253 tag_header_file_t::query_tag_name() const 00254 { 00255 return m_tag_name.query_value(); 00256 } 00257 00258 const std::string & 00259 tag_header_file_t::query_tag_type() const 00260 { 00261 return m_tag_type.query_value(); 00262 } 00263 00264 /* 00265 Класс тега test-cfg. 00266 00267 Содержит два необязательных тега: 'sort', 'rewrite' 00268 Содержит два обязательных тега 'file-name', 'file-type', 00269 которые могут указываться по нескольку раз. 00270 */ 00271 class tag_test_cfg_t : 00272 public cls_2::tag_no_value_t 00273 { 00274 typedef cls_2::tag_no_value_t base_type_t; 00275 public : 00276 tag_test_cfg_t(); 00277 virtual ~tag_test_cfg_t(); 00278 00279 // Печать всего, что получилось на стандартный поток вывода. 00280 void 00281 show() const; 00282 00283 private : 00284 // Подчиненный тег sort. 00285 cls_2::tag_scalar_t< std::string, 00286 cls_2::scalar_nonspace_format_t > 00287 m_tag_sort; 00288 00289 // Подчиненный тег rewrite. 00290 cls_2::tag_scalar_t< std::string, 00291 cls_2::scalar_nonspace_format_t > 00292 m_tag_rewrite; 00293 00294 // Вектор подчиненных тегов cfg-file. 00295 cls_2::tag_vector_of_tags_t< tag_cfg_file_t > 00296 m_tag_cfg_file; 00297 00298 // Вектор подчиненных тегов header-file. 00299 cls_2::tag_vector_of_tags_t< tag_header_file_t > 00300 m_tag_header_file; 00301 }; 00302 00303 tag_test_cfg_t::tag_test_cfg_t() 00304 : 00305 // Инициализируем базовый тип. 00306 base_type_t( "test-cfg", 00307 // обязательный тег, 00308 true, 00309 // должен присутствовать только в одном экземпляре. 00310 true ), 00311 // Инициализируем подчиненные теги. 00312 m_tag_sort( self_tag(), "sort", false ), 00313 m_tag_rewrite( self_tag(), "rewrite", false ), 00314 m_tag_cfg_file( self_tag(), "cfg-file", true ), 00315 m_tag_header_file( self_tag(), "header-file", true ) 00316 { 00317 } 00318 00319 tag_test_cfg_t::~tag_test_cfg_t() 00320 { 00321 } 00322 00323 void 00324 show_cfg_file( 00325 const tag_cfg_file_t & t ) 00326 { 00327 std::cout << "cfg-file: file-name: " << t.query_file_name() 00328 << ", file-type: " << t.query_file_type() 00329 << std::endl; 00330 } 00331 00332 void 00333 show_header_file( 00334 const tag_header_file_t & t ) 00335 { 00336 std::cout << "header-file: name: " << t.query_tag_name() 00337 << ", type: " << t.query_tag_type() 00338 << std::endl; 00339 } 00340 00341 void 00342 tag_test_cfg_t::show() const 00343 { 00344 if( m_tag_sort.is_defined() ) 00345 // Значение тега sort определено. 00346 std::cout << "sort: " << m_tag_sort.query_value() << std::endl; 00347 if( m_tag_rewrite.is_defined() ) 00348 // Значение тега rewrite определено. 00349 std::cout << "rewrite: " << m_tag_rewrite.query_value() << std::endl; 00350 00351 00352 // Печатаем значения тегов cfg-file. 00353 std::for_each( m_tag_cfg_file.begin(), m_tag_cfg_file.end(), 00354 show_cfg_file ); 00355 00356 // Печатаем значения тегов header-file. 00357 std::for_each( m_tag_header_file.begin(), m_tag_header_file.end(), 00358 show_header_file ); 00359 } 00360 00361 int 00362 main( int argc, char ** argv ) 00363 { 00364 // Подготовка всего необходимого для разбора. 00365 00366 // Главный тег... 00367 tag_test_cfg_t tag; 00368 // ... список тегов для разбора. 00369 cls_2::tag_t * tags[] = { &tag }; 00370 00371 // Осуществляем разбор. 00372 // Если задано имя файла в командной строке, то разбираем файл. 00373 int ret_code; 00374 if( 2 == argc ) 00375 ret_code = cls_2::std_cpp::parse_file( 00376 argv[ 1 ], 00377 // Используемые теги. 00378 tags, sizeof( tags ) / sizeof( tags[ 0 ] ), 00379 // Поток ошибок. 00380 &std::cerr ); 00381 else 00382 ret_code = cls_2::std_cpp::parse_istream( 00383 // Входной поток и его имя. 00384 std::cin, "stdin", 00385 // Используемые теги. 00386 tags, sizeof( tags ) / sizeof( tags[ 0 ] ), 00387 // Поток ошибок. 00388 &std::cerr ); 00389 00390 if( cls_2::c_ok == ret_code ) 00391 { 00392 // Разбор завершился успешно. 00393 tag.show(); 00394 00395 // Отображаем значение тега в формате CLS. 00396 cls_2::def_tag_formatter_t< std::ostream > 00397 tag_formatter( std::cout ); 00398 tag.format( tag_formatter ); 00399 } 00400 00401 return ret_code; 00402 }

Документация по cls_2. Последние изменения: Wed Aug 4 15:13:00 2004. Создано системой doxygen 1.3.7
Hosted by uCoz