]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/trains/Option.C
Changed default mutliplicity estimator to V0A.
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / Option.C
CommitLineData
fdfd93b4 1/**
2 * @file Option.C
3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Tue Oct 16 18:59:04 2012
5 *
6 * @brief
7 *
8 *
9 * @ingroup pwglf_forward_trains_util
10 */
11#ifndef OPTION_C
12#define OPTION_C
13#include <TNamed.h>
14#include <iomanip>
15#ifndef __CINT__
16# include <TString.h>
17# include <TList.h>
18# include <TObjArray.h>
19# include <TObjString.h>
20# include <TMath.h>
21# include <iostream>
22# include <iomanip>
23# include <cstdarg>
24# include <cstdio>
25#else
26class TString;
27class TList;
28class TObjArray;
29#endif
30
31/**
32 * An option. The value is stored as a string
33 *
34 * @ingroup pwglf_forward_trains_util
35 */
36struct Option /* : public TNamed */
37{
38 /**
39 * Constructor
40 *
41 * @param name Name of option
42 * @param arg Dummy argument (possibly null)
43 * @param description Description
44 * @param value Default value
45 */
46 Option(const TString& name,
47 const TString& arg,
48 const TString& description,
49 const TString& value)
50 : fName(name), fDescription(description),
51 fValue(value), fArg(arg), fIsSet(false)
52 {}
53 /**
54 * Copy constructor
55 *
56 * @param other Object to copy from
57 */
58 Option(const Option& other)
59 : fName(other.fName),
60 fDescription(other.fDescription),
61 fValue(other.fValue),
62 fArg(other.fArg),
63 fIsSet(other.fIsSet)
64 {}
65 /**
66 * Assignment operator
67 *
68 * @param other Object to assign from
69 *
70 * @return Reference to this object
71 */
72 Option& operator=(const Option& other)
73 {
74 if (&other == this) return *this;
75
76 fName = other.fName;
77 fDescription = other.fDescription;
78 fValue = other.fValue;
79 fArg = other.fArg;
80 fIsSet = other.fIsSet;
81
82 return *this;
83 }
84 /**
85 * Set the value
86 *
87 * @param val New value
88 */
d25cb579 89 void Set(const TString& val)
90 {
91 if (HasArg()) {
92 fIsSet = true;
93 fValue = val;
024ec5ac 94 // Info("Set", "Setting option %s with arg %s to %s",
95 // fName.Data(), fArg.Data(), fValue.Data());
d25cb579 96 return;
97 }
98
024ec5ac 99 // Info("Set", "Setting option %s with no arg", fName.Data());
d25cb579 100 // Allow flags to get =true, =1, =false, =0 values
101 if (!val.IsNull() &&
102 (val.EqualTo("false", TString::kIgnoreCase) ||
103 (val.IsDigit() && !val.Atoi()))) {
104 fIsSet = false;
105 fValue = "false";
106 }
107 else {
108 fIsSet = true;
109 fValue = "true";
110 }
111 }
fdfd93b4 112 /**
113 * Set the value
114 */
115 void Set()
116 {
117 if (HasArg()) {
118 Error("Option::Set", "Option %s needs an argument", fName.Data());
119 return;
120 }
d25cb579 121 Set("true");
fdfd93b4 122 }
123 /**
124 * Reset the set flag
125 *
126 */
d25cb579 127 void Reset()
128 {
129 fIsSet = false;
130 if (!HasArg()) fValue = "false";
131 }
fdfd93b4 132 /**
133 * @return constant reference to value
134 */
135 const TString& Get() const { return fValue; }
136 /**
137 * @return true if this option was set externally
138 */
139 Bool_t IsSet() const { return fIsSet; }
140 /**
141 * @return true if this option needs an argument
142 */
143 Bool_t HasArg() const { return !fArg.IsNull(); }
144 /**
145 * @return value as a boolean value
146 */
147 Bool_t AsBool() const { return fIsSet; }
148 /**
149 * @return value as an integer value
150 */
151 Int_t AsInt() const { return fValue.Atoi(); }
152 /**
153 * @return value as a long integer value
154 */
155 Long64_t AsLong() const { return fValue.Atoll(); }
156 /**
157 * @return value as a double precision value
158 */
159 Double_t AsDouble() const { return fValue.Atof(); }
160 /**
161 * @return value as a C string
162 */
163 const char* AsString() const { return fValue.Data(); }
164 /**
165 * @return Width of the name
166 */
167 Int_t NameWidth() const { return fName.IsNull() ? 0 : fName.Length(); }
168 /**
169 * @return the width of the dummy argument
170 */
171 Int_t ArgWidth() const { return fArg.IsNull() ? 0 : fArg.Length(); }
172 /**
173 * Show help
174 *
175 * @param o Output stream
176 * @param w With of option plus argument
177 */
178 void Help(std::ostream& o, Int_t w=-1) const
179 {
180 TString tmp(fName);
181 if (HasArg()) {
182 tmp.Append("=");
183 tmp.Append(fArg);
184 }
185 if (w <= 0) w = NameWidth() + ArgWidth() + 1;
186 std::ios::fmtflags oldf = o.setf(std::ios::left);
187 o << std::setw(w) << tmp << " " << fDescription << " [";
188 if (!HasArg()) o << (IsSet() ? "true" : "false");
189 else o << fValue;
190 o << "]" << std::endl;
191 o.setf(oldf);
192 }
193 /**
194 * Show the option
195 *
196 * @param o Output stream
197 * @param w With of name
198 */
199 void Show(std::ostream& o, Int_t w=-1) const
200 {
201 if (w <= 0) w = NameWidth();
202 std::ios::fmtflags oldf = o.setf(std::ios::left);
203 o << std::setw(w) << fName << ": ";
204 if (!HasArg()) o << (IsSet() ? "true" : "false");
205 else o << fValue;
206 o << std::endl;
207 o.setf(oldf);
208 }
209 /**
210 * Store option and possible value
211 *
212 * @param o Output stream
33438b4c 213 * @param quote If true, quote output
fdfd93b4 214 */
215 void Store(std::ostream& o, bool quote=true) const
216 {
217 o << fName;
218 if (!HasArg()) return;
219 o << "=" << (quote ? "\"" : "") << fValue << (quote ? "\"" : "");
220 }
221 TString fName; // Name
222 TString fDescription; // Description
223 TString fValue; // Value
224 TString fArg; // Argument dummy
225 Bool_t fIsSet; // True if this option was set
226
227 // ClassDef(Option,1) // Option
228};
229
230/**
231 * A List of options
232 */
233struct OptionList
234{
235 // Linked list element
236 struct Link
237 {
238 Link* fPrev;
239 Link* fNext;
240 Option* fThis;
241 Link() : fPrev(0), fNext(0), fThis(0) {}
242 Link(Link* next, Option* opt)
243 : fPrev(next ? next->fPrev : 0), // Set previous
244 fNext(next), // Set next link
245 fThis(opt) // Set data
246 {
247 if (fPrev) fPrev->fNext = this; // Set forward link
248 if (fNext) fNext->fPrev = this; // Set previous link
249 }
250 ~Link() {
251 if (fPrev) fPrev->fNext = fNext;
252 if (fNext) fNext->fPrev = fPrev;
253 delete fThis;
254 }
46b25775 255 Link(const Link& o)
256 : fPrev(o.fPrev),
257 fNext(o.fNext),
258 fThis(o.fThis)
259 {
260 }
261 Link& operator=(const Link& o)
262 {
263 if (&o == this) return *this;
264 fPrev = o.fPrev;
265 fNext = o.fNext;
266 fThis = o.fThis;
267 return *this;
268 }
fdfd93b4 269 };
270 /**
271 * Constructor
272 */
273 OptionList() : fList(0) { }
274 /**
275 * Copy constructor
276 *
277 * @param other Object to copy from
278 */
279 OptionList(const OptionList& other)
280 : fList(0)
281 {
282 // fList.SetOwner();
283 // TIter next(&other.fList);
284 // Option* o = 0;
285 // while ((o = static_cast<Option*>(next())))
286 // fList.Add(new Option(*o));
287 Copy(other);
288 }
289 /**
290 * Destructor
291 */
292 ~OptionList() { Delete(); }
293
294 /**
295 * Remove all options
296 */
297 void Delete()
298 {
299 Link* cur = fList;
300 while (cur) {
301 Link* tmp = cur->fNext;
302 delete cur;
303 cur = tmp;
304 // Remove(cur->fThis->fName);
305 // cur = tmp;
306 }
307 fList = 0;
308 }
309 /**
310 * Assignment operator
311 *
312 * @param other Object to assign from
313 *
314 * @return reference to this
315 */
316 OptionList& operator=(const OptionList& other)
317 {
318 if (&other == this) return *this;
319 Delete();
320 Copy(other);
321
322 return *this;
323 }
324 /**
325 * Copy list from other object
326 *
327 * @param other Object to copy from
328 */
329 void Copy(const OptionList& other)
330 {
331 Delete();
332 const Link* ocur = other.fList;
333 Link* cur = fList;
334 Link* prev = fList;
335 while (ocur) {
336 cur = new Link;
337 cur->fThis = new Option(*(ocur->fThis));
338 cur->fNext = 0;
339 cur->fPrev = prev;
340 if (fList == 0) fList = cur;
341 if (prev) prev->fNext = cur;
342 prev = cur;
343 ocur = ocur->fNext;
344 }
345 }
346 void DebugLink(const Link* link) const
347 {
348 std::cout << "Link=" << link;
349 if (link) {
350 std::cout << " prev=" << link->fPrev
351 << " next=" << link->fNext
352 << " obj=" << link->fThis;
353 if (link->fThis)
354 std::cout << " name=" << link->fThis->fName;
355 }
356 std::cout <<std::endl;
357 }
358 /**
359 * Find an optio by name
360 *
361 * @param name Name of option to find
362 *
363 * @return Pointer to option or null
364 */
365 Option* Find(const TString& name) const
366 {
367 const Link* cur = fList;
368 // DebugLink(cur);
369 while (cur && cur->fThis) {
370 if (name.EqualTo(cur->fThis->fName)) return cur->fThis;
371 cur = cur->fNext;
372 }
373 return 0;
374 }
375 /**
376 * Add an option with argument
377 *
378 * @param name Name of option
379 * @param arg Dummy argument
380 * @param desc Description
381 * @param val Default value
382 *
383 * @return Newly added option
384 */
385 Option* Add(const TString& name,
386 const TString& arg,
387 const TString& desc,
d25cb579 388 const TString& val="")
fdfd93b4 389 {
390 Option* o = Find(name);
391 if (o) {
392 Warning("OptionList::Add", "Option %s already registered", name.Data());
393 return o;
394 }
024ec5ac 395 // Info("Add", "New option %s with arg %s (%s) and value %s",
396 // name.Data(), arg.Data(), desc.Data(), val.Data());
fdfd93b4 397 o = new Option(name, arg, desc, val);
398 Link* cur = fList;
399 if (!cur) {
400 cur = new Link;
401 cur->fThis = o;
402 cur->fNext = 0;
403 cur->fPrev = 0;
404 fList = cur;
405 }
406 else {
407 Link* n = 0;
408 Link* l = 0;
409 while (cur) {
410 if (cur->fThis->fName.CompareTo(name) < 0) {
411 l = cur;
412 cur = cur->fNext;
413 continue;
414 }
415 n = new Link(cur, o);
416 if (cur == fList) fList = n;
417 break;
418 }
419 if (!n) {
420 n = new Link;
421 l->fNext = n;
422 n->fPrev = l;
423 n->fNext = 0;
424 n->fThis = o;
425 }
426 }
427 return o;
428 }
429 /**
430 * Add an option with no argument
431 *
432 * @param name Name of option
433 * @param desc Description
434 *
435 * @return Newly created option
436 */
437 Option* Add(const TString& name,
438 const TString& desc)
439 {
440 return Add(name, "", desc, "");
441 }
33438b4c 442 /**
443 * Add an option with no argument
444 *
445 * @param name Name of option
446 * @param desc Description
447 * @param def Default value (true, or false)
448 *
449 * @return Newly created option
450 */
451 Option* Add(const TString& name,
452 const TString& desc,
453 Bool_t def)
454 {
455 Option* o = Add(name, "", desc, "");
456 if (o) o->Set(def ? "true" : "false");
457 return o;
458 }
d25cb579 459 /**
460 * Add an option with argument
461 *
462 * @param name Name of option
463 * @param arg Dummy argument
464 * @param desc Description
465 * @param val Default value
33438b4c 466 * @param asHex If true, interpret as hex number
d25cb579 467 *
468 * @return Newly added option
469 */
470 Option* Add(const TString& name,
471 const TString& arg,
472 const TString& desc,
473 Int_t val,
474 Bool_t asHex=false)
475 {
476 if (asHex) {
477 UInt_t uval = val;
478 return Add(name, arg, desc, Form("0x%x", uval));
479 }
480 return Add(name, arg, desc, Form("%d", val));
481 }
482 /**
483 * Add an option with argument
484 *
485 * @param name Name of option
486 * @param arg Dummy argument
487 * @param desc Description
488 * @param val Default value
33438b4c 489 * @param asHex If true, interpret as hex
d25cb579 490 *
491 * @return Newly added option
492 */
493 Option* Add(const TString& name,
494 const TString& arg,
495 const TString& desc,
496 Long64_t val,
497 Bool_t asHex=false)
498 {
499 if (asHex) {
500 ULong64_t uval = val;
501 return Add(name, arg, desc, Form("0x%llx", uval));
502 }
503 return Add(name, arg, desc, Form("%lld", val));
504 }
505 /**
506 * Add an option with argument
507 *
508 * @param name Name of option
509 * @param arg Dummy argument
510 * @param desc Description
511 * @param val Default value
512 *
513 * @return Newly added option
514 */
515 Option* Add(const TString& name,
516 const TString& arg,
517 const TString& desc,
518 Double_t val)
519 {
520 return Add(name, arg, desc, Form("%lg", val));
521 }
522
fdfd93b4 523 /**
524 * Remove an option
525 *
526 * @param name Name of option to remove
527 */
528 void Remove(const TString& name)
529 {
530 Link* cur = fList;
531 while (cur) {
532 if (!cur->fThis->fName.EqualTo(name)) {
533 cur = cur->fNext;
534 continue;
535 }
536 if (fList == cur) fList = cur->fNext;
537 delete cur;
538 break;
539 }
540 }
541 /**
542 * Check if a given option was set externally
543 *
544 * @param name Name of option
545 *
546 * @return true if option exists and was set externally
547 */
548 Bool_t Has(const TString& name) const
549 {
550 Option* o = Find(name);
551 return (o && o->IsSet());
552 }
553 /**
554 * Get the value of an option
555 *
556 * @param name Name of option
557 *
558 * @return Value of option, or empty string
559 */
560 const TString& Get(const TString& name) const
561 {
562 static TString null("");
563 Option* o = Find(name);
564 if (!o) return null;
565 return o->Get();
566 }
567 /**
568 * Get a value using a format statement. Remember argument(s) must
569 * be passed by address (as pointers)
570 *
571 * @param name Name of option @param format Format statement.
572 * Remeber, double and long needs the "l" modifier
573 *
574 * @return true on success
575 */
576 Bool_t GetF(const TString& name, const Char_t* format, ...) const
577 {
578 Option* o = Find(name);
579 if (!o) return false;
580
581 va_list ap;
582 va_start(ap, format);
583 int ret = vsscanf(o->fValue.Data(), format, ap);
584 va_end(ap);
585
586 return ret > 0;
587 }
588 /**
589 * Get value of an option as a boolean
590 *
591 * @param name Name of
592 *
593 * @return Value or false if not found
594 */
595 Bool_t AsBool(const TString& name) const
596 {
597 Option* o = Find(name);
598 if (!o) return false;
599 return o->AsBool();
600 }
601 /**
602 * Return value of an option as an integer
603 *
604 * @param name Name of option
605 * @param def Default value if options isn't found
606 *
607 * @return Value or default value
608 */
609 Int_t AsInt(const TString& name, Int_t def=0) const
610 {
611 Option* o = Find(name);
612 if (!o) return def;
613 return o->AsInt();
614 }
615 /**
616 * Return value of an option as an integer
617 *
618 * @param name Name of option
619 * @param def Default value if options isn't found
620 *
621 * @return Value or default value
622 */
623 Long64_t AsLong(const TString& name, Long64_t def=0) const
624 {
625 Option* o = Find(name);
626 if (!o) return def;
627 return o->AsLong();
628 }
629 /**
630 * Return value of an option as a double precision real number
631 *
632 * @param name Name of option
633 * @param def Default value if options isn't found
634 *
635 * @return Value or default value
636 */
637 Double_t AsDouble(const TString& name, Double_t def=0) const
638 {
639 Option* o = Find(name);
640 if (!o) return def;
641 return o->AsDouble();
642 }
643 /**
644 * Set value using a format statement
645 *
646 * @param name Name of option.
647 * @param format Format statement
648 */
649 void SetF(const TString& name, const Char_t* format, ...)
650 {
651 Option* o = Find(name);
652 if (!o) return;
653
654 static char buf[1024];
655 va_list ap;
656
657 va_start(ap, format);
658 vsnprintf(buf, 1023, format, ap);
659 buf[1023] = '\0';
660 va_end(ap);
661
662 o->Set(buf);
663 }
664 /**
665 * Set an option
666 *
667 * @param name Name of option
668 * @param value Value of option
669 */
670 void Set(const TString& name, const TString& value)
671 {
672 Option* o = Find(name);
673 if (!o) return;
674 o->Set(value);
675 }
676 /**
677 * Set a flag
678 *
679 * @param name Name of flag
680 */
681 void Set(const TString& name)
682 {
683 Option* o = Find(name);
684 if (!o) return;
685 o->Set();
686 }
687 /**
688 * Set long integer value
689 *
690 * @param name Name of option
691 * @param val Value
33438b4c 692 * @param asHex If true, interpret as hex
fdfd93b4 693 */
694 void Set(const TString& name, Int_t val, Bool_t asHex=false)
695 {
696 if (asHex) Set(name, Form("0x%x", val));
697 else Set(name, Form("%d", val));
698 }
699 /**
700 * Set long integer value
701 *
702 * @param name Name of option
703 * @param val Value
33438b4c 704 * @param asHex If true, interpret as hex value
fdfd93b4 705 */
706 void Set(const TString& name, Long64_t val, Bool_t asHex=false)
707 {
708 ULong64_t uval = val;
709 if (asHex) Set(name, Form("0x%llx", uval));
710 else Set(name, Form("%lld", val));
711 }
712 /**
713 * Set double precision floating point value
714 *
715 * @param name Name of option
716 * @param val Value
717 */
718 void Set(const TString& name, Double_t val)
719 {
720 Set(name, Form("%lg", val));
721 }
722 /**
723 * Parse the options given in tmp
724 *
725 * @param tmp String to pass
726 * @param delims Delimiters
727 *
728 * @return true on success
729 */
730 Bool_t Parse(const TString& tmp, const TString& delims)
731 {
732 TObjArray* opts = tmp.Tokenize(delims);
733 // Info("OptionList::Parse", "Parsing options %s", tmp.Data());
734 Bool_t ret = Parse(opts);
735 opts->Delete();
736 return ret;
737 }
738 /**
739 * Parse options given in a collection
740 *
741 * @param opts List of arguments
33438b4c 742 * @param ignoreUnknown If true, ignore unknown options
fdfd93b4 743 *
744 * @return true on success
745 */
746 Bool_t Parse(const TCollection* opts, Bool_t ignoreUnknown=false)
747 {
748 // Info("OptionList::Parse", "List of options");
749 // opts->ls();
750 TIter next(opts);
751 TObjString* o = 0;
752 while ((o = static_cast<TObjString*>(next()))) {
753 TString& s = o->String();
754 TString key = s;
755 TString val = "";
756 Int_t eq = s.Index("=");
757 if (eq != kNPOS) {
758 key = s(0, eq);
759 val = s(eq+1, s.Length()-eq-1);
760 }
761
762 // Info("OptionList::Parse", "Looking for key=%s", key.Data());
763 Option* opt = Find(key);
764 if (!opt) {
765 if (!ignoreUnknown)
766 Warning("OptionList::Parse", "Unknown option: \"%s\"", s.Data());
767 continue;
768 }
769 if (opt->HasArg() && val.IsNull()) {
770 Warning("OptionList::Parse",
771 "Option %s needs an argument, using default %s",
772 key.Data(), opt->fValue.Data());
773 val = opt->fValue;
774 // return false;
775 }
776 opt->Set(val);
777 }
778 return true;
779 }
780 /**
781 * Find the widest name and dummy argument
782 *
783 * @param nWidth On return, the largest width of option names
784 * @param aWidth On return, the largest width of option dummy args
785 */
786 void Widest(Int_t& nWidth, Int_t& aWidth) const
787 {
788 nWidth = 0;
789 aWidth = 0;
790 const Link* cur = fList;
791 while (cur) {
792 Option* opt = cur->fThis;
793 nWidth = TMath::Max(nWidth, opt->NameWidth());
794 aWidth = TMath::Max(aWidth, opt->ArgWidth());
795 cur = cur->fNext;
796 }
797
798 // while ((opt = static_cast<Option*>(next()))) {
799 // }
800 }
801 /**
802 * Display option help
803 *
804 * @param o Output stream
805 * @param prefix Prefix for each option.
806 */
807 void Help(std::ostream& o, const char* prefix=" ") const
808 {
809 Int_t nWidth, aWidth;
810 Widest(nWidth, aWidth);
811 if (aWidth > 0) nWidth += aWidth+1;
812
813 const Link* cur = fList;
814 while (cur) {
815 Option* opt = cur->fThis;
816 o << prefix;
817 opt->Help(o, nWidth);
818 cur = cur->fNext;
819 }
820 }
821 /**
822 * Show the values of options
823 *
824 * @param o Output stream
825 * @param prefix Prefix for each option
826 */
827 void Show(std::ostream& o, const char* prefix=" ") const
828 {
829 Int_t nWidth, aWidth;
830 Widest(nWidth, aWidth);
831
832
833 const Link* cur = fList;
834 while (cur) {
835 Option* opt = cur->fThis;
836 o << prefix;
837 opt->Show(o, nWidth);
838 cur = cur->fNext;
839 }
840 }
841 /**
842 * Show the values of options
843 *
844 * @param o Output stream
845 * @param prefix Prefix for each option
33438b4c 846 * @param delim Delimters
847 * @param quote Quote output
848 * @param onlySet if true, only output set options
fdfd93b4 849 */
850 void Store(std::ostream& o, const char* prefix="",
d25cb579 851 const char* delim=",", bool quote=true,
852 bool onlySet=false) const
fdfd93b4 853 {
854 Int_t nWidth, aWidth;
855 Widest(nWidth, aWidth);
856
857 const Link* cur = fList;
858 while (cur) {
859 Option* opt = cur->fThis;
d25cb579 860 if ((!opt->HasArg() || onlySet) && !opt->IsSet()) {
fdfd93b4 861 cur = cur->fNext;
862 continue;
863 }
864 o << prefix;
865 opt->Store(o, quote);
866 o << delim;
867 cur = cur->fNext;
868 }
869 }
870 // Our linked list
871 Link* fList;
872
d25cb579 873 static void Test(const char* opts="")
fdfd93b4 874 {
875 OptionList l;
876 l.Add("int", "NUMBER", "Integer", "42");
877 l.Add("float", "NUMBER", "Floating point", "3.14");
878 l.Add("bool", "Flag");
879 l.Add("hex", "NUMBER", "Hexadecimal", "0xdead");
880 l.Add("string", "STRING", "A string", "Hello, world");
881 l.Show(std::cout, "\t");
882
883 std::cout << "Find" << std::endl;
884 Option* b = l.Find("bool");
d25cb579 885 b->Set("true");
fdfd93b4 886 b->Show(std::cout);
887
888 std::cout << "SetF" << std::endl;
889 l.SetF("float", "%f", 2.17);
890 l.Show(std::cout, "\t");
891
892 std::cout << "GetF" << std::endl;
893 Float_t f;
894 l.GetF("float", "%f", &f);
895 std::cout << "\tf=" << f << std::endl;
896 std::cout << "Remove" << std::endl;
897 l.Remove("float");
898 l.Show(std::cout, "\t");
899
900 std::cout << "Set" << std::endl;
901 l.Set("int", "10");
902 l.Set("hex", 0xbeef, true);
d25cb579 903 l.Set("bool", "false");
fdfd93b4 904 l.Show(std::cout, "\t");
905
906 std::cout << "Copy" << std::endl;
907 OptionList c(l);
908 c.Show(std::cout, "\t");
909
d25cb579 910 std::cout << "Parse" << std::endl;
911 c.Parse(opts,",");
912 c.Show(std::cout, "\t");
fdfd93b4 913 std::cout << "End of test" << std::endl;
914 }
915 // TList fList;
916};
917
918#endif
919