00001 /* 00002 * 00003 * Copyright (C) 1997-2010, OFFIS e.V. 00004 * All rights reserved. See COPYRIGHT file for details. 00005 * 00006 * This software and supporting documentation were developed by 00007 * 00008 * OFFIS e.V. 00009 * R&D Division Health 00010 * Escherweg 2 00011 * D-26121 Oldenburg, Germany 00012 * 00013 * 00014 * Module: ofstd 00015 * 00016 * Author: Marco Eichelberg 00017 * 00018 * Purpose: 00019 * classes: OFConfigFile 00020 * 00021 * Last Update: $Author: joergr $ 00022 * Update Date: $Date: 2010-10-14 13:15:50 $ 00023 * CVS/RCS Revision: $Revision: 1.8 $ 00024 * Status: $State: Exp $ 00025 * 00026 * CVS/RCS Log at end of file 00027 * 00028 */ 00029 00030 #ifndef OFCONFIG_H 00031 #define OFCONFIG_H 00032 00033 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 00034 #include "dcmtk/ofstd/ofstring.h" 00035 #include "dcmtk/ofstd/ofstack.h" 00036 #include "dcmtk/ofstd/ofstream.h" 00037 00038 #define INCLUDE_CSTDIO 00039 #include "dcmtk/ofstd/ofstdinc.h" 00040 00041 /* 00042 * Short description of configuration file structure: 00043 * - The data in a configuration file have a tree structure. 00044 * The tree has a depth defined at instantiation time (by default, OFConfigFile_MaxLevel), 00045 * not including the (imaginary) root node. 00046 * - A level 0 entry (a leaf) has the form: KEYWORD = VALUE, 00047 * where the keyword starts on row one of a line. 00048 * - A level 1 entry has the form [KEYWORD] 00049 * - A level 2 entry has the form [[KEYWORD]] (and so on). 00050 * - Keywords may consist of: 00051 * A..Z, a..z (which are converted to uppercase), 00052 * 0..9, 00053 * '-' 00054 * - Values can be any kind of ASCII text. Values may span multiple lines. 00055 * To continue a value in the next line, the next line MUST start with 00056 * (any amount of) whitespace, which is discarded when reading the value. 00057 * linefeeds (converted to ASCII 10 if necessary) are kept in the 00058 * value string. Empty lines are discarded (and also their linefeed). 00059 * - The data must have a "clean" tree structure. This means that there 00060 * MUST be a level 2 keyword before any level 1 keyword etc. 00061 * - lines starting with the comment char (default is "#") are interpreted 00062 * as comment lines. 00063 * 00064 */ 00065 00066 #define OFConfigFile_MaxLevel 2 00067 #define OFConfigFile_CommentChar '#' 00068 00069 class OFConfigFile; 00070 class OFConfigFileNode; 00071 00072 typedef OFConfigFileNode *OFPConfigFileNode; 00073 00074 00079 class OFConfigFileNode 00080 { 00081 public: 00085 OFConfigFileNode(const char *keyword); 00086 00088 ~OFConfigFileNode(); 00089 00092 const char *getKeyword() const 00093 { 00094 return keyword_.c_str(); 00095 } 00096 00099 const char *getValue() const 00100 { 00101 return value_.c_str(); 00102 } 00103 00107 void setValue(const char *c) 00108 { 00109 value_ = c; 00110 } 00111 00116 OFBool match(const char *c) const 00117 { 00118 return (keyword_ == c); 00119 } 00120 00125 OFBool less(const char *c) const 00126 { 00127 return (keyword_ < c); 00128 } 00129 00133 OFConfigFileNode *getBrother() const 00134 { 00135 return brother_; 00136 } 00137 00141 OFConfigFileNode *getSon() const 00142 { 00143 return son_; 00144 } 00145 00149 void setBrother(OFConfigFileNode *brother) 00150 { 00151 brother_ = brother; 00152 } 00153 00157 void setSon(OFConfigFileNode *son) 00158 { 00159 son_ = son; 00160 } 00161 00166 void print(STD_NAMESPACE ostream& out, unsigned int level); 00167 00168 private: 00170 OFConfigFileNode(const OFConfigFileNode& arg); 00171 00173 OFConfigFileNode &operator=(const OFConfigFileNode& arg); 00174 00176 OFConfigFileNode *brother_; 00177 00179 OFConfigFileNode *son_; 00180 00182 OFString keyword_; 00183 00185 OFString value_; 00186 }; 00187 00189 typedef OFConfigFileNode *OFConfigFileNodePtr; 00190 00194 class OFConfigFileCursor 00195 { 00196 public: 00199 OFConfigFileCursor(unsigned int maxLevel) 00200 : array_(NULL) 00201 , maxLevel_(maxLevel) 00202 { 00203 clear(); 00204 } 00205 00208 OFConfigFileCursor(const OFConfigFileCursor& source); 00209 00212 ~OFConfigFileCursor() 00213 { 00214 delete[] array_; 00215 } 00216 00219 OFConfigFileCursor& operator=(const OFConfigFileCursor& source); 00220 00222 void clear(); 00223 00228 const char *getKeyword(unsigned int level) const 00229 { 00230 if ((level <= maxLevel_) && array_ && array_[level]) return array_[level]->getKeyword(); else return NULL; 00231 } 00232 00237 const char *getValue(unsigned int level) const 00238 { 00239 if ((level <= maxLevel_) && array_ && array_[level]) return array_[level]->getValue(); else return NULL; 00240 } 00241 00247 OFBool section_valid(unsigned int level) const; 00248 00259 void set_section( 00260 unsigned int level, 00261 const char *key, 00262 OFConfigFileNode *anchor); 00263 00273 void first_section( 00274 unsigned int level, 00275 OFConfigFileNode *anchor); 00276 00285 void next_section(unsigned int level); 00286 00294 void insert( 00295 unsigned int level, 00296 OFConfigFileNode *& newnode, 00297 OFConfigFileNode *& anchor, 00298 OFBool orderedMode); 00299 00303 OFBool operator<(const OFConfigFileCursor& /* arg */) const 00304 { 00305 return OFFalse; 00306 } 00307 00311 OFBool operator==(const OFConfigFileCursor& /* arg */) const 00312 { 00313 return OFTrue; 00314 } 00315 00316 private: 00317 00325 void orderedInsert( 00326 OFConfigFileNode *parent, 00327 OFConfigFileNode *&newnode); 00328 00330 OFConfigFileNodePtr *array_; 00331 00333 unsigned int maxLevel_; 00334 }; 00335 00336 00342 class OFConfigFile 00343 { 00344 public: 00345 00353 OFConfigFile( 00354 FILE *infile, 00355 unsigned int maxLevel = OFConfigFile_MaxLevel, 00356 char commentChar = OFConfigFile_CommentChar, 00357 OFBool orderedMode = OFFalse); 00358 00361 virtual ~OFConfigFile(); 00362 00366 void loadFile(FILE *infile); 00367 00373 const char *get_keyword(unsigned int level); 00374 00379 const char *get_value(); 00380 00391 OFBool get_bool_value(OFBool defaultvalue); 00392 00398 OFBool section_valid(unsigned int level) const 00399 { 00400 return cursor_.section_valid(level); 00401 } 00402 00412 void set_section(unsigned int level, const char *key) 00413 { 00414 cursor_.set_section(level, key, anchor_); 00415 } 00416 00425 void first_section(unsigned int level) 00426 { 00427 cursor_.first_section(level, anchor_); 00428 } 00429 00438 void next_section(unsigned int level) 00439 { 00440 cursor_.next_section(level); 00441 } 00442 00445 void save_cursor(); 00446 00449 void restore_cursor(); 00450 00459 void select_section( 00460 const char *key1, 00461 const char *key2=NULL, 00462 const char *key3=NULL); 00463 00469 const char *get_entry(const char *key0); 00470 00474 void print(STD_NAMESPACE ostream& out); 00475 00476 private: 00477 00484 char read_char(FILE *infile); 00485 00491 char read_keywordchar(FILE *infile); 00492 00499 void read_entry(FILE *infile); 00500 00505 void store_char(char c); 00506 00509 OFConfigFile(const OFConfigFile&); 00510 00513 OFConfigFile& operator=(const OFConfigFile&); 00514 00515 00517 OFStack<OFConfigFileCursor> stack_; 00518 00520 OFConfigFileCursor cursor_; 00521 00523 OFConfigFileNode *anchor_; 00524 00526 int isnewline_; 00527 00529 int crfound_; 00530 00532 char *buffer_; 00533 00535 size_t bufptr_; 00536 00538 long bufsize_; 00539 00541 unsigned int maxLevel_; 00542 00544 char commentChar_; 00545 00555 OFBool orderedMode_; 00556 }; 00557 00558 #endif 00559 00560 /* 00561 * $Log: ofconfig.h,v $ 00562 * Revision 1.8 2010-10-14 13:15:50 joergr 00563 * Updated copyright header. Added reference to COPYRIGHT file. 00564 * 00565 * Revision 1.7 2010-04-26 12:22:30 uli 00566 * Fixed a some minor doxygen warnings. 00567 * 00568 * Revision 1.6 2008-04-16 09:37:27 meichel 00569 * class OFConfigFile now supports an ordered mode where multiple 00570 * configuration files can be loaded and can replace entries of other. 00571 * Also added function to print content of configuration in reloadable format. 00572 * 00573 * Revision 1.5 2008-04-15 15:46:30 meichel 00574 * class OFConfigFile now supports flexible tree depths and configurable 00575 * comment characters and can, therefore, fully replace the equivalent 00576 * code in module dcmprint. 00577 * 00578 * Revision 1.4 2005/12/08 16:05:51 meichel 00579 * Changed include path schema for all DCMTK header files 00580 * 00581 * Revision 1.3 2003/06/12 13:15:59 joergr 00582 * Fixed inconsistent API documentation reported by Doxygen. 00583 * 00584 * Revision 1.2 2003/06/04 12:31:44 meichel 00585 * Added dummy comparison operators, needed by MSVC5 with STL 00586 * 00587 * Revision 1.1 2003/04/29 10:14:16 meichel 00588 * Moved configuration file parser from module dcmpstat to ofstd and renamed 00589 * class to OFConfigFile. Cleaned up implementation (no more friend declarations). 00590 * 00591 * 00592 */ 00593