1 // 2 // keyval.h 3 // 4 // Copyright (C) 1996 Limit Point Systems, Inc. 5 // 6 // Author: Curtis Janssen <cljanss@limitpt.com> 7 // Maintainer: LPS 8 // 9 // This file is part of the SC Toolkit. 10 // 11 // The SC Toolkit is free software; you can redistribute it and/or modify 12 // it under the terms of the GNU Library General Public License as published by 13 // the Free Software Foundation; either version 2, or (at your option) 14 // any later version. 15 // 16 // The SC Toolkit is distributed in the hope that it will be useful, 17 // but WITHOUT ANY WARRANTY; without even the implied warranty of 18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 // GNU Library General Public License for more details. 20 // 21 // You should have received a copy of the GNU Library General Public License 22 // along with the SC Toolkit; see the file COPYING.LIB. If not, write to 23 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 24 // 25 // The U.S. Government is granted a limited license as per AL 91-7. 26 // 27 28 #ifndef _util_keyval_keyval_h 29 #define _util_keyval_keyval_h 30 #ifdef __GNUG__ 31 #pragma interface 32 #endif 33 34 #include <iostream> 35 #include <string> 36 #include <map> 37 38 #include <string.h> 39 #include <stdlib.h> 40 #include <stdarg.h> 41 42 #include <util/class/class.h> 43 #include <util/keyval/keyvalval.h> 44 45 namespace sc { 46 47 /** 48 The KeyVal class is designed to simplify the process of allowing 49 a user to specify keyword/value associations to a C++ program. A 50 flexible input style and ease of use for the programmer is achieved with 51 this method. Keywords are represented by null terminated character arrays. 52 The keywords are organized hierarchially, in a manner similar to the way 53 that many file systems are organized. One character is special, 54 ":", which is used to separate the various hierarchial labels, 55 which are referred to as "segments", in the keyword. 56 57 A convention for specifying arrays is provided by KeyVal. Each 58 index of the array is given by appending a segment containing the 59 character representation of the index. Thus, "array:3:4" would be 60 a the keyword corresponding to fourth row and fifth column of 61 "array", since indexing starts at zero. 62 63 To allow the KeyVal class to have associations that can represent 64 data for classes, the keyword can be associated with a class as well as 65 a value. This permits polymorphic data to be unambiguously represented 66 by keyword/value associations. Most use of KeyVal need not be 67 concerned with this. 68 */ 69 class KeyVal: public RefCount { 70 // these classes need to directly access the key_value member 71 friend class AggregateKeyVal; 72 friend class PrefixKeyVal; 73 public: 74 enum {MaxKeywordLength = 256}; 75 enum KeyValError { OK, HasNoValue, WrongType, 76 UnknownKeyword, OperationFailed }; 77 private: 78 KeyValError errcod; 79 // do not allow a copy constructor or assignment 80 KeyVal(const KeyVal&); 81 void operator=(const KeyVal&); 82 protected: 83 int verbose_; 84 85 KeyVal(); 86 87 /// Set the current error condition. 88 void seterror(KeyValError err); 89 /// Set the current error condition. 90 void seterror(KeyValValue::KeyValValueError err); 91 92 /// Ultimately called by exists. 93 virtual int key_exists(const char*) = 0; 94 /// Ultimately called by count. 95 virtual int key_count(const char* =0); 96 /// Ultimately called by value. 97 virtual Ref<KeyValValue> key_value(const char*, 98 const KeyValValue& def) = 0; 99 /// Ultimately called by booleanvalue. 100 virtual int key_booleanvalue(const char*,const KeyValValue& def); 101 /// Ultimately called by doublevalue. 102 virtual double key_doublevalue(const char* key,const KeyValValue& def); 103 /// Ultimately called by floatvalue. 104 virtual float key_floatvalue(const char* key,const KeyValValue& def); 105 /// Ultimately called by charvalue. 106 virtual char key_charvalue(const char* key,const KeyValValue& def); 107 /// Ultimately called by intvalue. 108 virtual int key_intvalue(const char* key,const KeyValValue& def); 109 /// Ultimately called by sizevalue. 110 virtual size_t key_sizevalue(const char* key,const KeyValValue& def); 111 /// Ultimately called by pcharvalue. 112 virtual char* key_pcharvalue(const char* key,const KeyValValue& def); 113 /// Ultimately called by stringvalue. 114 virtual std::string key_stringvalue(const char* key, 115 const KeyValValue& def); 116 /// Ultimately called by describedclassvalue. 117 virtual Ref<DescribedClass> key_describedclassvalue(const char* key, 118 const KeyValValue& def); 119 120 public: 121 virtual ~KeyVal(); 122 123 // For nonindexed things. If a subclass defines one of these, 124 // then the overloaded functions will be hidden. The key_... functions 125 // should be overridden instead. 126 127 /** This takes as its only argument a keyword. 128 Returns 1 if the keyword has a value and 0 otherwise. */ 129 int exists(const char*); 130 /** If the value of a keyword is an array, then return its length. 131 If no arguments are given then the top level will be checked to 132 see if it is an array and, if so, the number of elements will be 133 counted. */ 134 int count(const char* =0); 135 /// Return the value associated with the keyword. 136 Ref<KeyValValue> value(const char* = 0, 137 const KeyValValue& def=KeyValValue()); 138 /// Returns the boolean value (0 = false, 1 = true) of key. 139 int booleanvalue(const char* key = 0, 140 const KeyValValue& def=KeyValValueboolean()); 141 /// Returns the double value of key. 142 double doublevalue(const char* key = 0, 143 const KeyValValue& def=KeyValValuedouble()); 144 /// Returns the float value of key. 145 float floatvalue(const char* key = 0, 146 const KeyValValue& def=KeyValValuefloat()); 147 /// Returns the char value of key. 148 char charvalue(const char* key = 0, 149 const KeyValValue& def=KeyValValuechar()); 150 /// Returns the int value of key. 151 int intvalue(const char* key = 0, 152 const KeyValValue& def=KeyValValueint()); 153 /// Returns the size_t value of key. 154 size_t sizevalue(const char* key = 0, 155 const KeyValValue& def=KeyValValuesize()); 156 /** Returns a copy of the string representation of the key's 157 value. Storage for the copy is obtained with new. */ 158 char* pcharvalue(const char* key = 0, 159 const KeyValValue& def=KeyValValuepchar()); 160 /** Returns a string representation of the key's value. */ 161 std::string stringvalue(const char* key = 0, 162 const KeyValValue& def=KeyValValuestring()); 163 /// Returns a reference to an object of type DescribedClass. 164 Ref<DescribedClass> describedclassvalue(const char* key = 0, 165 const KeyValValue& def=KeyValValueRefDescribedClass()); 166 167 /** @name Reading Vectors. 168 These members correspond to the above members, but take 169 an additional integer argument, i, which is a vector index. 170 This is equivalent to getting a value for a keyword named 171 "<i>key</i>:<i>i</i>". The routines that do not take 172 key arguments get the value for the keyword named "<i>i</i>". 173 */ 174 //@{ 175 int exists(const char* key,int i); 176 int count(const char* key,int i); 177 int booleanvalue(const char* key,int i, 178 const KeyValValue& def=KeyValValueboolean()); 179 double doublevalue(const char* key,int i, 180 const KeyValValue& def=KeyValValuedouble()); 181 float floatvalue(const char* key,int i, 182 const KeyValValue& def=KeyValValuefloat()); 183 char charvalue(const char* key,int i, 184 const KeyValValue& def=KeyValValuechar()); 185 int intvalue(const char* key,int i, 186 const KeyValValue& def=KeyValValueint()); 187 size_t sizevalue(const char* key,int i, 188 const KeyValValue& def=KeyValValuesize()); 189 char* pcharvalue(const char* key,int i, 190 const KeyValValue& def=KeyValValuepchar()); 191 std::string stringvalue(const char* key,int i, 192 const KeyValValue& def=KeyValValuestring()); 193 Ref<DescribedClass> describedclassvalue(const char* key,int, 194 const KeyValValue& def=KeyValValueRefDescribedClass()); 195 196 int exists(int i); 197 int count(int i); 198 int booleanvalue(int i, 199 const KeyValValue& def=KeyValValueboolean()); 200 double doublevalue(int i, 201 const KeyValValue& def=KeyValValuedouble()); 202 float floatvalue(int i, 203 const KeyValValue& def=KeyValValuefloat()); 204 char charvalue(int i, 205 const KeyValValue& def=KeyValValuechar()); 206 int intvalue(int i, 207 const KeyValValue& def=KeyValValueint()); 208 size_t sizevalue(int i, 209 const KeyValValue& def=KeyValValuesize()); 210 char* pcharvalue(int i, 211 const KeyValValue& def=KeyValValuepchar()); 212 std::string stringvalue(int i, 213 const KeyValValue& def=KeyValValuestring()); 214 Ref<DescribedClass> describedclassvalue(int i, 215 const KeyValValue& def=KeyValValueRefDescribedClass()); 216 //@} 217 218 /** @name Reading 2D Arrays. 219 These members correspond to the above members, but take additional 220 integer arguments, i and j, which is an array index. This is 221 equivalent to getting a value for a keyword named 222 "<i>key</i>:<i>i</i>:<i>j</i>". The routines that do not take key 223 arguments get the value for the keyword named "<i>i</i>:<i>j</i>". */ 224 //@{ 225 int exists(const char*,int,int); 226 int count(const char*,int,int); 227 int booleanvalue(const char*,int,int, 228 const KeyValValue& def=KeyValValueboolean()); 229 double doublevalue(const char* key,int,int, 230 const KeyValValue& def=KeyValValuedouble()); 231 float floatvalue(const char* key,int,int, 232 const KeyValValue& def=KeyValValuefloat()); 233 char charvalue(const char* key,int,int, 234 const KeyValValue& def=KeyValValuechar()); 235 int intvalue(const char* key,int,int, 236 const KeyValValue& def=KeyValValueint()); 237 size_t sizevalue(const char* key,int,int, 238 const KeyValValue& def=KeyValValuesize()); 239 char* pcharvalue(const char* key,int,int, 240 const KeyValValue& def=KeyValValuepchar()); 241 std::string stringvalue(const char* key,int,int, 242 const KeyValValue& def=KeyValValuestring()); 243 Ref<DescribedClass> describedclassvalue(const char* key,int,int, 244 const KeyValValue& def=KeyValValueRefDescribedClass()); 245 246 int exists(int i,int j); 247 int count(int i,int j); 248 int booleanvalue(int i,int j, 249 const KeyValValue& def=KeyValValueboolean()); 250 double doublevalue(int i,int j, 251 const KeyValValue& def=KeyValValuedouble()); 252 float floatvalue(int i,int j, 253 const KeyValValue& def=KeyValValuefloat()); 254 char charvalue(int i,int j, 255 const KeyValValue& def=KeyValValuechar()); 256 int intvalue(int i,int j, 257 const KeyValValue& def=KeyValValueint()); 258 size_t sizevalue(int i,int j, 259 const KeyValValue& def=KeyValValuesize()); 260 char* pcharvalue(int i,int j, 261 const KeyValValue& def=KeyValValuepchar()); 262 std::string stringvalue(int i,int j, 263 const KeyValValue& def=KeyValValuestring()); 264 Ref<DescribedClass> describedclassvalue(int i,int j, 265 const KeyValValue& def=KeyValValueRefDescribedClass()); 266 //@} 267 268 /** @name Reading 3D Arrays. 269 These members correspond to the above members, but can be used 270 to read in arrays with more than two dimensions. The nindex 271 argument is the number of indices in the array. It is followed 272 by an int giving the value of each index. */ 273 //@{ 274 int Va_exists(const char* key,int nindex,...); 275 int Va_count(const char* key,int nindex,...); 276 int Va_booleanvalue(const char* key,int nindex,...); 277 double Va_doublevalue(const char* key,int nindex,...); 278 float Va_floatvalue(const char* key,int nindex,...); 279 char Va_charvalue(const char* key,int nindex,...); 280 int Va_intvalue(const char* key,int nindex,...); 281 size_t Va_sizevalue(const char* key,int nindex,...); 282 char* Va_pcharvalue(const char* key,int nindex,...); 283 std::string Va_stringvalue(const char* key,int nindex,...); 284 Ref<DescribedClass> Va_describedclassvalue(const char* key,int nindex,...); 285 //@} 286 287 /// Return the current error condition. 288 KeyValError error(); 289 /// Return a textual representation of err. 290 const char* errormsg(KeyValError err); 291 /// Return a textual representation of the current error. 292 const char* errormsg(); 293 /// Write a message to fp describing the error. 294 virtual void errortrace(std::ostream&fp=ExEnv::err0()); 295 /// Write a message to fp describing the error. 296 virtual void dump(std::ostream&fp=ExEnv::err0()); 297 298 /// Print keywords that were never looked at, if possible. 299 virtual void print_unseen(std::ostream&fp=ExEnv::out0()); 300 /** Return 1 if there were unseen keywords, 0 if there are 301 none, or -1 this keyval doesn't keep track of unseen 302 keywords. */ 303 virtual int have_unseen(); 304 305 /// Control printing of assignments. verbose(int v)306 void verbose(int v) { verbose_ = v; } 307 /// Returns nonzero if assignments are printed. verbose()308 int verbose() const { return verbose_; } 309 }; 310 311 312 313 /** This class allows keyval associations to be set up by the program, 314 rather than determined by an external file. */ 315 class AssignedKeyVal: public KeyVal { 316 private: 317 std::map<std::string,Ref<KeyValValue> > _map; 318 // do not allow a copy constructor or assignment 319 AssignedKeyVal(const AssignedKeyVal&); 320 void operator=(const AssignedKeyVal&); 321 protected: 322 int key_exists(const char*); 323 Ref<KeyValValue> key_value(const char*, 324 const KeyValValue& def); 325 public: 326 AssignedKeyVal(); 327 ~AssignedKeyVal(); 328 329 /** @name Assignments. 330 Each of this routines assigns key to val. */ 331 //@{ 332 void assign(const char* key, const Ref<KeyValValue>& val); 333 void assign(const char* key, double val); 334 void assignboolean(const char* key, int val); 335 void assign(const char* key, float val); 336 void assign(const char* key, char val); 337 void assign(const char* key, int val); 338 void assign(const char* key, const char* val); 339 void assign(const char* key, const Ref<DescribedClass>& val); 340 //@} 341 342 /// Erase all of the stored assignments. 343 void clear(); 344 }; 345 346 347 348 /** StringKeyVal is a base class for KeyVal implementations 349 that store all values in a string format. These are 350 converted to other data types through KeyValValue. 351 */ 352 class StringKeyVal: public KeyVal { 353 private: 354 // once a described class is found it is kept here so 355 // multiple references to it return the same instance 356 std::map<std::string,Ref<KeyValValue> > _map; 357 // do not allow a copy constructor or assignment 358 StringKeyVal(const StringKeyVal&); 359 void operator=(const StringKeyVal&); 360 protected: 361 StringKeyVal(); 362 int key_exists(const char*); 363 Ref<KeyValValue> key_value(const char*, 364 const KeyValValue& def); 365 public: 366 virtual ~StringKeyVal(); 367 /// Returns the string representation of the value assigned to key. 368 virtual const char* stringrep(const char *key) = 0; 369 /** Returns the name of the exact class of the object at the keyword. 370 If no classname is assigned then 0 is returned. */ 371 virtual const char* classname(const char*); 372 /** Returns a string which is the actual keyword if some sort 373 of variable substitution takes place (needed to make multiple 374 references to the same object work in input files). */ 375 virtual const char* truekeyword(const char*); 376 377 /** @name Debugging. 378 See the parent class documentation for descriptions of these functions. 379 */ 380 //@{ 381 virtual void errortrace(std::ostream&fp=ExEnv::err0()); 382 virtual void dump(std::ostream&fp=ExEnv::err0()); 383 //@} 384 }; 385 386 /** This takes several KeyVal objects and makes them look like 387 one KeyVal object. When a key is sought first KeyVal, then 388 the next, and so on is searched until the keyword is found. 389 */ 390 class AggregateKeyVal : public KeyVal { 391 private: 392 enum { MaxKeyVal = 4 }; 393 Ref<KeyVal> kv[MaxKeyVal]; 394 Ref<KeyVal> getkeyval(const char*key); 395 // do not allow a copy constructor or assignment 396 AggregateKeyVal(const AggregateKeyVal&); 397 void operator=(const AggregateKeyVal&); 398 protected: 399 int key_exists(const char*); 400 Ref<KeyValValue> key_value(const char*, 401 const KeyValValue& def); 402 public: 403 /** @name Constructors. 404 These contructors create an AggregateKeyVal that is formed from 405 several other KeyVal objects. The search order is keyval1, 406 keyval2, and so on. All KeyVal objects including and after the 407 first null KeyVal will be ignored. 408 */ 409 //@{ 410 AggregateKeyVal(const Ref<KeyVal>& keyval1); 411 AggregateKeyVal(const Ref<KeyVal>& keyval1,const Ref<KeyVal>& keyval2); 412 AggregateKeyVal(const Ref<KeyVal>& keyval1,const Ref<KeyVal>& keyval2, 413 const Ref<KeyVal>& keyval3); 414 AggregateKeyVal(const Ref<KeyVal>& keyval1,const Ref<KeyVal>& keyval2, 415 const Ref<KeyVal>& keyval3, const Ref<KeyVal>& keyval4); 416 //@} 417 ~AggregateKeyVal(); 418 void errortrace(std::ostream&fp=ExEnv::err0()); 419 void dump(std::ostream&fp=ExEnv::err0()); 420 }; 421 422 /** PrefixKeyVal is a KeyVal that searches a different KeyVal using 423 modified keys. This is convenient for reading keys grouped together 424 with a common prefix. Consider the following code: 425 <pre> 426 sc::Ref<sc::KeyVal> keyval = new sc::PrefixKeyVal("A",original_keyval); 427 int r = keyval->intvalue("x"); 428 </pre> 429 This code will assign to r the value associated with "x" in keyval. 430 keyval will search for "x" by searching for "A::x" in original_keyval. 431 432 This class is important for implementing constructors that take 433 KeyVal arguments. When an object is being constructed from a KeyVal, 434 it may contain another object that must be constructed from a KeyVal. 435 In order to let the sub-object read the correct keywords from the 436 KeyVal, without knowledge of the containing objects keyword prefix, 437 a PrefixKeyVal can be constructed. For example, the code 438 \code 439 class A: public DescribedClass { 440 double f0_; 441 public: 442 A(const Ref<KeyVal> &keyval): f0_(keyval->doublevalue("f0")) {} 443 } 444 class B: public DescribedClass { 445 double f1_; 446 Ref<A> a_; 447 public: 448 B(const Ref<KeyVal> &keyval): 449 f1_(keyval->doublevalue("f1")), 450 a_(new PrefixKeyVal(keyval,"a")) 451 {} 452 }; 453 \endcode 454 can be used to read ParsedKeyVal input that looks like 455 <pre> 456 b\<B>: ( 457 f1 = 1.0 458 a\<A>: ( 459 f0 = 2.0 460 ) 461 ) 462 </pre> 463 */ 464 class PrefixKeyVal : public KeyVal { 465 private: 466 char* prefix; 467 Ref<KeyVal> keyval; 468 void setup(const char*,int,int,int,int,int); 469 int getnewprefixkey(const char*key,char*newkey); 470 // do not allow a copy constructor or assignment 471 PrefixKeyVal(const PrefixKeyVal&); 472 void operator=(const PrefixKeyVal&); 473 int key_exists(const char*); 474 Ref<KeyValValue> key_value(const char*, 475 const KeyValValue& def); 476 public: 477 /** @name Constructors. 478 Construct a PrefixKeyVal, using the given prefix and indices. */ 479 //@{ 480 PrefixKeyVal(const Ref<KeyVal>&,int i); 481 PrefixKeyVal(const Ref<KeyVal>&,int i,int j); 482 PrefixKeyVal(const Ref<KeyVal>&,int i,int j,int k); 483 PrefixKeyVal(const Ref<KeyVal>&,int i,int j,int k,int l); 484 PrefixKeyVal(const Ref<KeyVal>&,const char*prefix); 485 PrefixKeyVal(const Ref<KeyVal>&,const char*prefix,int i); 486 PrefixKeyVal(const Ref<KeyVal>&,const char*prefix,int i,int j); 487 PrefixKeyVal(const Ref<KeyVal>&,const char*prefix,int i,int j,int k); 488 PrefixKeyVal(const Ref<KeyVal>&,const char*prefix,int i,int j,int k,int l); 489 //@} 490 ~PrefixKeyVal(); 491 void errortrace(std::ostream&fp=ExEnv::err0()); 492 void dump(std::ostream&fp=ExEnv::err0()); 493 }; 494 495 class IPV2; 496 /** Converts textual information into keyword/value assocations. The 497 parsing is done with an IPV2 object. The \ref keyval for more 498 information on the input format. */ 499 class ParsedKeyVal : public StringKeyVal { 500 private: 501 int nfile; 502 char**file; 503 int nfp; 504 IPV2* ipv2; 505 // do not allow a copy constructor or assignment 506 ParsedKeyVal(const ParsedKeyVal&); 507 void operator=(const ParsedKeyVal&); 508 public: 509 /// Create an empty ParsedKeyVal. 510 ParsedKeyVal(); 511 /// Parse the given input file. 512 ParsedKeyVal(const char*file); 513 /// Read input from s. 514 ParsedKeyVal(std::istream&s); 515 /** Use the given IPV2* object. The new ParsedKeyVal 516 takes wnership of the passed IPV2 object. */ 517 ParsedKeyVal(IPV2*); 518 /** This ctor is given a string which is used to form keywords 519 that are sought in the keyval argument. The associated values 520 are used to construct file names that are used to initialize 521 the ParsedKeyVal. The keywords sought are string'dir' for the 522 directory prefix and string'files' for an array of file names. */ 523 ParsedKeyVal(const char*,const Ref<KeyVal>&); 524 /// Cleanup, deleting the IPV2 object. 525 ~ParsedKeyVal(); 526 527 /** This is like the ParsedKeyVal(const char*,const Ref<KeyVal>&) 528 ctor, but writes the contents of the files to the given ostream. */ 529 static void cat_files(const char*,const Ref<KeyVal>&,std::ostream &o); 530 531 /// Read input data from the given filename 532 void read(const char*); 533 /// Read input data from the given stream. 534 void read(std::istream&); 535 /// Read input data from the given string. 536 void parse_string(const char *); 537 538 /** @name Overrides of parent members. 539 See parent class documentation. */ 540 //@{ 541 const char* stringrep(const char*); 542 const char* classname(const char*); 543 const char* truekeyword(const char*); 544 void errortrace(std::ostream&fp=ExEnv::err0()); 545 void dump(std::ostream&fp=ExEnv::err0()); 546 void print_unseen(std::ostream&fp=ExEnv::out0()); 547 int have_unseen(); 548 //@} 549 }; 550 551 } 552 553 #endif /* _KeyVal_h */ 554 555 // Local Variables: 556 // mode: c++ 557 // c-file-style: "CLJ" 558 // End: 559