source: ThirdParty/mpqc_open/src/lib/util/keyval/keyval.h@ 0035ea

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 0035ea was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 22.4 KB
Line 
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
45namespace 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*/
69class 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.
306 void verbose(int v) { verbose_ = v; }
307 /// Returns nonzero if assignments are printed.
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. */
315class 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*/
352class 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*/
390class 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 */
464class 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
495class 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. */
499class 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:
Note: See TracBrowser for help on using the repository browser.