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