00001 /* 00002 * 00003 * Copyright (C) 1997-2005, OFFIS 00004 * 00005 * This software and supporting documentation were developed by 00006 * 00007 * Kuratorium OFFIS e.V. 00008 * Healthcare Information and Communication Systems 00009 * Escherweg 2 00010 * D-26121 Oldenburg, Germany 00011 * 00012 * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY 00013 * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR 00014 * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR 00015 * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND 00016 * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. 00017 * 00018 * Module: ofstd 00019 * 00020 * Author: Marco Eichelberg 00021 * 00022 * Purpose: 00023 * classes: OFConfigFile 00024 * 00025 * Last Update: $Author: meichel $ 00026 * Update Date: $Date: 2005/12/08 16:05:51 $ 00027 * CVS/RCS Revision: $Revision: 1.4 $ 00028 * Status: $State: Exp $ 00029 * 00030 * CVS/RCS Log at end of file 00031 * 00032 */ 00033 00034 #ifndef OFCONFIG_H 00035 #define OFCONFIG_H 00036 00037 #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ 00038 #include "dcmtk/ofstd/ofstring.h" 00039 #include "dcmtk/ofstd/ofstack.h" 00040 00041 #define INCLUDE_CSTDIO 00042 #include "dcmtk/ofstd/ofstdinc.h" 00043 00044 /* 00045 * Short description of configuration file structure: 00046 * - The data in a configuration file have a tree structure. 00047 * The tree has a fixed depth of (OFConfigFile_MaxLevel), not including 00048 * the (imaginary) root node. 00049 * - A level 0 entry (a leaf) has the form: KEYWORD = VALUE, 00050 * where the keyword starts on row one of a line. 00051 * - A level 1 entry has the form [KEYWORD] 00052 * - A level 2 entry has the form [[KEYWORD]] (and so on). 00053 * - Keywords may consist of: 00054 * A..Z, a..z (which are converted to uppercase), 00055 * 0..9, 00056 * '-' 00057 * - Values can be any kind of ASCII text. Values may span multiple lines. 00058 * To continue a value in the next line, the next line MUST start with 00059 * (any amount of) whitespace, which is discarded when reading the value. 00060 * linefeeds (converted to ASCII 10 if necessary) are kept in the 00061 * value string. Empty lines are discarded (and also their linefeed). 00062 * - The data must have a "clean" tree structure. This means that there 00063 * MUST be a level 2 keyword before any level 1 keyword etc. 00064 * - lines starting with "#" are interpreted as comment lines. 00065 * 00066 */ 00067 00068 #define OFConfigFile_MaxLevel 2 00069 00070 class OFConfigFile; 00071 class OFConfigFileNode; 00072 00073 typedef OFConfigFileNode *OFPConfigFileNode; 00074 00075 00080 class OFConfigFileNode 00081 { 00082 public: 00086 OFConfigFileNode(const char *keyword); 00087 00089 ~OFConfigFileNode(); 00090 00093 const char *getKeyword() const 00094 { 00095 return keyword_.c_str(); 00096 } 00097 00100 const char *getValue() const 00101 { 00102 return value_.c_str(); 00103 } 00104 00108 void setValue(const char *c) 00109 { 00110 value_ = c; 00111 } 00112 00117 OFBool match(const char *c) const 00118 { 00119 return (keyword_ == c); 00120 } 00121 00125 OFConfigFileNode *getBrother() const 00126 { 00127 return brother_; 00128 } 00129 00133 OFConfigFileNode *getSon() const 00134 { 00135 return son_; 00136 } 00137 00141 void setBrother(OFConfigFileNode *brother) 00142 { 00143 brother_ = brother; 00144 } 00145 00149 void setSon(OFConfigFileNode *son) 00150 { 00151 son_ = son; 00152 } 00153 00154 private: 00156 OFConfigFileNode(const OFConfigFileNode& arg); 00157 00159 OFConfigFileNode &operator=(const OFConfigFileNode& arg); 00160 00162 OFConfigFileNode *brother_; 00163 00165 OFConfigFileNode *son_; 00166 00168 OFString keyword_; 00169 00171 OFString value_; 00172 }; 00173 00174 00178 class OFConfigFileCursor 00179 { 00180 public: 00183 OFConfigFileCursor() { clear(); } 00184 00187 OFConfigFileCursor(const OFConfigFileCursor& source); 00188 00191 ~OFConfigFileCursor() {} 00192 00195 OFConfigFileCursor& operator=(const OFConfigFileCursor& source); 00196 00198 void clear(); 00199 00204 const char *getKeyword(unsigned int level) const 00205 { 00206 return ptr[level]->getKeyword(); 00207 } 00208 00213 const char *getValue(unsigned int level) const 00214 { 00215 return ptr[level]->getValue(); 00216 } 00217 00223 OFBool section_valid(unsigned int level) const; 00224 00235 void set_section( 00236 unsigned int level, 00237 const char *key, 00238 OFConfigFileNode *anchor); 00239 00249 void first_section( 00250 unsigned int level, 00251 OFConfigFileNode *anchor); 00252 00261 void next_section(unsigned int level); 00262 00268 void insert( 00269 unsigned int level, 00270 OFConfigFileNode *newnode, 00271 OFConfigFileNode *& anchor); 00272 00276 OFBool operator<(const OFConfigFileCursor& /* arg */) const 00277 { 00278 return OFFalse; 00279 } 00280 00284 OFBool operator==(const OFConfigFileCursor& /* arg */) const 00285 { 00286 return OFTrue; 00287 } 00288 00289 private: 00291 OFPConfigFileNode ptr[OFConfigFile_MaxLevel +1]; 00292 00293 }; 00294 00295 00301 class OFConfigFile 00302 { 00303 public: 00304 00308 OFConfigFile(FILE *infile); 00309 00312 virtual ~OFConfigFile(); 00313 00319 const char *get_keyword(unsigned int level); 00320 00325 const char *get_value(); 00326 00337 OFBool get_bool_value(OFBool defaultvalue); 00338 00344 OFBool section_valid(unsigned int level) const 00345 { 00346 return cursor.section_valid(level); 00347 } 00348 00358 void set_section(unsigned int level, const char *key) 00359 { 00360 cursor.set_section(level, key, anchor); 00361 } 00362 00371 void first_section(unsigned int level) 00372 { 00373 cursor.first_section(level, anchor); 00374 } 00375 00384 void next_section(unsigned int level) 00385 { 00386 cursor.next_section(level); 00387 } 00388 00391 void save_cursor(); 00392 00395 void restore_cursor(); 00396 00403 void select_section( 00404 const char *key1, 00405 const char *key2=NULL); 00406 00412 const char *get_entry(const char *key0); 00413 00414 private: 00415 00422 char read_char(FILE *infile); 00423 00429 char read_keywordchar(FILE *infile); 00430 00437 void read_entry(FILE *infile); 00438 00443 void store_char(char c); 00444 00447 OFConfigFile(const OFConfigFile&); 00448 00451 OFConfigFile& operator=(const OFConfigFile&); 00452 00453 00455 OFStack<OFConfigFileCursor> stack; 00456 00458 OFConfigFileCursor cursor; 00459 00461 OFConfigFileNode *anchor; 00462 00464 int isnewline; 00465 00467 int crfound; 00468 00470 char *buffer; 00471 00473 size_t bufptr; 00474 00476 long bufsize; 00477 00478 }; 00479 00480 #endif 00481 00482 /* 00483 * $Log: ofconfig.h,v $ 00484 * Revision 1.4 2005/12/08 16:05:51 meichel 00485 * Changed include path schema for all DCMTK header files 00486 * 00487 * Revision 1.3 2003/06/12 13:15:59 joergr 00488 * Fixed inconsistent API documentation reported by Doxygen. 00489 * 00490 * Revision 1.2 2003/06/04 12:31:44 meichel 00491 * Added dummy comparison operators, needed by MSVC5 with STL 00492 * 00493 * Revision 1.1 2003/04/29 10:14:16 meichel 00494 * Moved configuration file parser from module dcmpstat to ofstd and renamed 00495 * class to OFConfigFile. Cleaned up implementation (no more friend declarations). 00496 * 00497 * 00498 */ 00499