libStatGen Software  1
Parameters.cpp
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Parameters.h"
19 #include "Constant.h"
20 #include "MathConstant.h"
21 #include "Error.h"
22 #include "PhoneHome.h"
23 
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdexcept>
29 
30 int Parameter::nameCol = 30;
31 int Parameter::statusCol = 15;
32 
33 Parameter::Parameter(char c, const char * desc, void * v)
34 {
35  ch = (char) tolower(c);
36  description = new char [strlen(desc) + 1];
37  strcpy(description, desc);
38  var = v;
39  warnings = NULL;
40 
41  myNoPhoneHome = true;
42  myVersion.Clear();
43 }
44 
45 bool Parameter::Read(int , char ** argv, int argn)
46 {
47  int p = 0;
48  char c = (char) tolower(argv[argn][p]);
49 
50  if ((c == '-') || (c == '/'))
51  {
52  p++;
53  c = (char) tolower(argv[argn][p]);
54  }
55 
56  if (c == ch)
57  {
58  Translate(&(argv[argn][++p]));
59  return true;
60  }
61  return false;
62 }
63 
64 bool Parameter::TranslateExtras(const char * , const char *)
65 {
66  return false;
67 }
68 
69 void Parameter::warning(const char * format, ...)
70 {
71  String buffer;
72 
73  va_list ap;
74  va_start(ap, format);
75  buffer.vprintf(format, ap);
76  va_end(ap);
77 
78  if (warnings == NULL)
79  ::warning(buffer);
80  else
81  (*warnings) += buffer;
82 }
83 
84 void IntParameter::Translate(const char * value)
85 {
86  *(int *) var = atoi(value);
87 }
88 
89 bool IntParameter::TranslateExtras(const char * value, const char * extras)
90 {
91  if (value[0] != 0 || !CheckInteger(extras))
92  return false;
93 
94  Translate(extras);
95 
96  return true;
97 }
98 
99 void IntParameter::Status()
100 {
101  fprintf(stderr, "%*s : %*d (-%c9999)\n", nameCol, description,
102  statusCol, *(int *) var, ch);
103 }
104 
105 void SwitchParameter::Translate(const char * value)
106 {
107  switch (*value)
108  {
109  case '+' :
110  *(bool *) var = true;
111  break;
112  case '-' :
113  *(bool *) var = false;
114  break;
115  case 0 :
116  *(bool *) var = ! * (bool *) var;
117  break;
118  default :
119  warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
120  ch, value, value[0]);
121  }
122 }
123 
124 void SwitchParameter::Status()
125 {
126  fprintf(stderr, "%*s : %*s (-%c[+|-])\n", nameCol, description,
127  statusCol, *(bool *) var == false ? "OFF" : "ON", ch);
128 }
129 
130 DoubleParameter::DoubleParameter(char c, const char * desc, double & v)
131  : Parameter(c, desc, &v)
132 {
133  precision = 2;
134 }
135 
136 void DoubleParameter::Translate(const char * value)
137 {
138  if (value[0])
139  *(double *) var = atof(value);
140  else
141  *(double *) var = _NAN_;
142 }
143 
144 bool DoubleParameter::TranslateExtras(const char * value, const char * extras)
145 {
146  if (value[0] != 0 || !CheckDouble(extras))
147  return false;
148 
149  Translate(extras);
150 
151  return true;
152 }
153 
154 void DoubleParameter::Status()
155 {
156  double absolute_value = fabs(* (double *) var);
157 
158  if (*(double *) var == _NAN_)
159  fprintf(stderr, "%*s : %*s (-%c99.999)\n", nameCol, description,
160  statusCol, "NAN", ch);
161  else if (absolute_value >= 0.00095)
162  fprintf(stderr, "%*s : % *.*f (-%c99.999)\n", nameCol, description,
163  statusCol, precision, * (double *) var, ch);
164  else if (absolute_value <= 1e-15)
165  fprintf(stderr, "%*s : % *.0f (-%c99.999)\n", nameCol, description,
166  statusCol, * (double *) var, ch);
167  else
168  fprintf(stderr, "%*s : %*.0e (-%c99.999)\n", nameCol, description,
169  statusCol, *(double *) var, ch);
170 }
171 
172 void StringParameter::Translate(const char * value)
173 {
174  String * s = (String *) var;
175 
176  *s = value;
177 }
178 
179 bool StringParameter::TranslateExtras(const char * value, const char * extras)
180 {
181  if ((value[0] != 0) || ((!required) && (extras[0] == '-')))
182  return false;
183 
184  String * s = (String *) var;
185 
186  *s = extras;
187 
188  return true;
189 }
190 
191 void StringParameter::Status()
192 {
193  fprintf(stderr, "%*s : %*s (-%cname)\n", nameCol, description,
194  statusCol, (const char *)(*(String *) var), ch);
195 }
196 
197 void ListParameter::Status()
198 {
199  OptionList * l;
200 
201  for (l = options; l->ch != 0; l++)
202  if (l->code == *((int *)var))
203  break;
204 
205  fprintf(stderr, "%*s : %*s (-%c[%s])\n", nameCol, description,
206  statusCol, l->description, ch, (const char *) key);
207 }
208 
209 void ListParameter::Translate(const char * value)
210 {
211  OptionList * l;
212 
213  for (l = options; l->ch != 0; l++)
214  if (tolower(l->ch) == tolower(value[0]))
215  break;
216 
217  if (l->ch == 0 && tolower(value[0]) != 0)
218  warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
219  ch, value, value[0], (const char *) key);
220 
221  *((int*) var) = l->code;
222 }
223 
224 ListParameter::ListParameter(char c, const char * desc, int & v, OptionList * opt)
225  : Parameter(c, desc, &v)
226 {
227  options = opt;
228 
229  for (OptionList * l = options; l->ch != 0; l++)
230  {
231  key += l->ch;
232  key += '|';
233  }
234 
235  key.SetLength(key.Length() - 1);
236 }
237 
238 SetParameter::SetParameter(char c, const char * desc, int & v, OptionList * opt)
239  : Parameter(c, desc, &v)
240 {
241  options = opt;
242 
243  for (OptionList * l = options; l->ch != 0; l++)
244  {
245  key += l->ch;
246  key += '|';
247  }
248  key.SetLength(key.Length() - 1);
249 }
250 
251 void SetParameter::Status()
252 {
253  bool first = 0;
254  int temp = * (int *) var;
255 
256  for (OptionList * l = options; l->ch != 0; l++)
257  if ((l->code & temp) || (l->code == *(int *) var))
258  {
259  if (!first)
260  fprintf(stderr, "%*s : %*s (-%c{%s})\n", nameCol, description,
261  statusCol, l->description, ch, (const char *) key);
262  else
263  fprintf(stderr, "%*s & %*s\n", nameCol, "",
264  statusCol, l->description);
265  first = true;
266  temp &= ~l->code;
267  }
268 }
269 
270 void SetParameter::Translate(const char * value)
271 {
272  *(int*)var = 0;
273 
274  for (const char * chr = value; *chr != 0; chr++)
275  {
276  int valid = false;
277 
278  for (OptionList * l = options; l->ch != 0; l++)
279  if (tolower(l->ch) == tolower(*chr))
280  {
281  *((int*) var) |= l->code;
282  valid = true;
283  }
284 
285  if (!valid)
286  warning("Command line parameter -%c%s: the option '%c' has no meaning\n",
287  ch, value, *chr);
288  }
289 }
290 
291 LongParameters::LongParameters(const char * desc, LongParameterList * lst)
292  : Parameter('-', desc, NULL)
293 {
294  list = lst;
295 
296  index.Clear();
297  legacyIndex.Clear();
298  group_len = 0;
299 
300  LongParameterList * ptr = list + 1;
301 
302  while (ptr->description != NULL)
303  {
304  if (ptr->type == LP_LEGACY_PARAMETERS)
305  break;
306  if(ptr->type == LP_PHONEHOME_VERSION)
307  {
308  // Phone home is turned on, so add
309  // the parameter for the user to turn it off.
310  myNoPhoneHome = false;
311  myVersion = ptr->description;
312  ptr->description = "noPhoneHome";
313  ptr->value = &myNoPhoneHome;
314  ptr->type = LP_BOOL_PARAMETER;
315  index.Add(ptr->description, ptr);
316  }
317  else
318  {
319  if (ptr->value != NULL)
320  index.Add(ptr->description, ptr);
321  else
322  group_len = max(strlen(ptr->description), group_len);
323  }
324  ptr++;
325  }
326 
327  while (ptr->description != NULL)
328  {
329  if(ptr->type == LP_PHONEHOME_VERSION)
330  {
331  // Phone home is turned on, so add
332  // the parameter for the user to turn it off.
333  myNoPhoneHome = false;
334  myVersion = ptr->description;
335  ptr->description = "noPhoneHome";
336  ptr->value = &myNoPhoneHome;
337  ptr->type = LP_BOOL_PARAMETER;
338  legacyIndex.Add(ptr->description, ptr);
339  }
340  else
341  {
342  if (ptr->value != NULL)
343  legacyIndex.Add(ptr->description, ptr);
344  }
345  ptr++;
346  }
347 
348  precision = 2;
349 }
350 
351 void LongParameters::ExplainAmbiguity(const char * cstr)
352 {
353  String value(cstr);
354 
355  int p = value.FastFindChar(':');
356  String stem = p == -1 ? value : value.Left(p);
357  String matches;
358 
359  for (int i = 0; i < index.Length(); i++)
360  if (index[i].SlowCompareToStem(stem) == 0)
361  {
362  if (matches.Length() + index[i].Length() > 50)
363  {
364  matches += " ...";
365  break;
366  }
367 
368  matches.catprintf(" --%s", (const char *) index[i]);
369  }
370 
371  warning("Ambiguous --%s matches%s\n",
372  (const char *) value, (const char *) matches);
373 }
374 
375 void LongParameters::Translate(const char * cstr)
376 {
377  String value(cstr);
378 
379  int p = value.FastFindChar(':');
380  int option = p == -1 ? index.FindStem(value) : index.FindStem(value.Left(p));
381 
382  if (option == -2)
383  {
384  ExplainAmbiguity(cstr);
385  return;
386  }
387 
388  LongParameterList * ptr;
389 
390  if (option >= 0)
391  ptr = (LongParameterList *) index.Object(option);
392  else
393  {
394  int alternate = p == -1 ? legacyIndex.FindFirstStem(value) :
395  legacyIndex.FindFirstStem(value.Left(p));
396 
397  if (alternate < 0)
398  {
399  warning("Command line parameter --%s is undefined\n", (const char *) value);
400  return;
401  }
402 
403  ptr = (LongParameterList *) legacyIndex.Object(alternate);
404  ptr->touched = true;
405  }
406  ptr->touched = true;
407 
408  if (ptr->type == LP_BOOL_PARAMETER)
409  {
410  if (p == -1)
411  * (bool *) ptr->value ^= true;
412  else
413  *(bool *) ptr->value = value.SubStr(p + 1).SlowCompare("ON") == 0;
414 
415  // In exclusive groups, only one option may be selected
416  if (ptr->exclusive)
417  {
418  for (int i = -1; ptr[i].exclusive; i--) *(bool *)ptr[i].value = false;
419  for (int i = 1; ptr[i].exclusive; i++) *(bool *)ptr[i].value = false;
420  }
421  }
422  else if (ptr->type == LP_INT_PARAMETER)
423  if (p == -1)
424  * (int *) ptr->value = * (int *) ptr->value ? 0 : 1;
425  else
426  *(int *) ptr->value = value.SubStr(p + 1).SlowCompare("ON") == 0 ?
427  1 : value.SubStr(p + 1).AsInteger();
428  else if (ptr->type == LP_DOUBLE_PARAMETER)
429  {
430  if (p != -1)
431  * (double *) ptr->value = value.SubStr(p + 1).AsDouble();
432  }
433  else if (ptr->type == LP_STRING_PARAMETER)
434  {
435  if (p != -1)
436  * (String *) ptr->value = value.SubStr(p + 1);
437  }
438 }
439 
440 bool LongParameters::TranslateExtras(const char * cstr, const char * extras)
441 {
442  if (strchr(cstr, ':') != NULL)
443  return false;
444 
445  int option = index.FindStem(cstr);
446 
447  if (option == -2)
448  {
449  // No need to explain ambiguity here ... will be handle by later call
450  // to Translate()
451  // ExplainAmbiguity(cstr);
452  return false;
453  }
454 
455  LongParameterList * ptr;
456 
457  if (option >= 0)
458  ptr = (LongParameterList *) index.Object(option);
459  else
460  {
461  option = legacyIndex.FindFirstStem(cstr);
462 
463  if (option < 0)
464  return false;
465 
466  ptr = (LongParameterList *) legacyIndex.Object(option);
467  ptr->touched = true;
468  }
469 
470  if (ptr->type == LP_INT_PARAMETER && CheckInteger(extras))
471  {
472  *(int *) ptr->value = atoi(extras);
473  ptr->touched = true;
474  return true;
475  }
476  else if (ptr->type == LP_DOUBLE_PARAMETER && CheckDouble(extras))
477  {
478  *(double *) ptr->value = atof(extras);
479  ptr->touched = true;
480  return true;
481  }
482  else if (ptr->type == LP_STRING_PARAMETER)
483  {
484  *(String *) ptr->value = extras;
485  ptr->touched = true;
486  return true;
487  }
488 
489  return false;
490 }
491 
492 void LongParameters::Status(LongParameterList * ptr, int & line_len, bool & need_a_comma)
493 {
494  String state;
495  int line_start = group_len ? group_len + 5 : 0;
496 
497  if (ptr->value == NULL)
498  {
499  fprintf(stderr, "%s %*s :", need_a_comma ? "\n" : "", group_len + 2, ptr->description);
500  need_a_comma = false;
501  line_len = line_start;
502  }
503  else
504  {
505  if (ptr->type == LP_BOOL_PARAMETER)
506  state = * (bool *) ptr->value ? " [ON]" : "";
507  else if (ptr->type == LP_INT_PARAMETER)
508  if (((* (int *) ptr->value == 1) && (ptr->exclusive)) || (* (int *) ptr->value == 0))
509  state = * (int *) ptr->value ? " [ON]" : "";
510  else
511  state = " [", state += * (int *) ptr->value, state += ']';
512  else if (ptr->type == LP_DOUBLE_PARAMETER)
513  if (* (double *) ptr->value != _NAN_)
514  {
515  double value = * (double *) ptr->value;
516 
517  state = " [";
518  if (value == 0.0 || value >= 0.01)
519  state.catprintf("%.*f", precision, value);
520  else
521  state.catprintf("%.1e", value);
522  state += ']';
523  }
524  else
525  state = "";
526  else if (ptr->type == LP_STRING_PARAMETER)
527  state = " [" + * (String *) ptr->value + "]";
528 
529  int item_len = 3 + strlen(ptr->description) + need_a_comma + state.Length();
530 
531  if (item_len + line_len > 78 && line_len > line_start)
532  {
533  line_len = line_start;
534  fprintf(stderr, "%s\n%*s", need_a_comma ? "," : "", line_len, "");
535  need_a_comma = 0;
536  item_len -= 1;
537  }
538 
539  fprintf(stderr, "%s --%s%s", need_a_comma ? "," : (need_a_comma = true, ""),
540  ptr->description, (const char *) state);
541 
542  need_a_comma = true;
543  line_len += item_len;
544  }
545 }
546 
547 void LongParameters::Status()
548 {
549  if (description != NULL && description[0] != 0)
550  fprintf(stderr, "\n%s\n", description);
551 
552  bool need_a_comma = false;
553  int line_len = 0;
554 
555  bool legacy_parameters = false;
556  int legacy_count = 0;
557 
558  for (LongParameterList * ptr = list + 1; ptr->description != NULL; ptr++)
559  if (ptr->type == LP_LEGACY_PARAMETERS)
560  legacy_parameters = true;
561  else if (legacy_parameters == false)
562  Status(ptr, line_len, need_a_comma);
563  else if (ptr->touched)
564  {
565  if (legacy_count == 0)
566  {
567  fprintf(stderr, "\n\nAdditional Options:\n %*s ", group_len + 3, "");
568  line_len = group_len + 5;
569  need_a_comma = false;
570  }
571 
572  Status(ptr, line_len, need_a_comma);
573  legacy_count++;
574  }
575 
576  fprintf(stderr, "\n");
577 }
578 
579 void LongParameters::addParamsToString(String& params)
580 {
581  for (LongParameterList * ptr = list + 1; ptr->description != NULL; ptr++)
582  {
583  if (ptr->touched)
584  {
585  if(!params.IsEmpty())
586  {
587  params += PARAM_STR_SEP;
588  }
589  params += ptr->description;
590  }
591  }
592 }
593 
594 void ParameterList::Add(Parameter * p)
595 {
596  if (count + 1 >= size)
597  error("Parameter list size should be increased");
598 
599  p->SetWarningBuffer(warnings);
600  pl[count++] = p;
601 };
602 
603 void ParameterList::Read(int argc, char ** argv, int start)
604 {
605  MakeString(argc, argv, start);
606  for (int i=start; i < argc; i++)
607  {
608  bool success = false;
609 
610  if (argv[i][0] == '-' && argv[i][1])
611  for (int j=0; j<count; j++)
612  {
613  success = tolower(argv[i][1]) == pl[j]->ch;
614 
615  if (success)
616  {
617  if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
618  i++;
619  else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] != '-'))
620  pl[j]->Translate(argv[++i]);
621  else
622  pl[j]->Translate(argv[i] + 2);
623 
624  break;
625  }
626  }
627 
628  if (!success)
629  {
630  String warning;
631 
632  warning.printf("Command line parameter %s (#%d) ignored\n", argv[i], i);
633  warnings += warning;
634  }
635  }
636 
637  if (warnings.Length())
638  {
639  ::warning("Problems encountered parsing command line:\n\n%s",
640  (const char *) warnings);
641  warnings.Clear();
642  }
643 
644  HandlePhoneHome(argc, argv, start);
645 }
646 
647 int ParameterList::ReadWithTrailer(int argc, char ** argv, int start)
648 {
649  MakeString(argc, argv, start);
650 
651  int last_success = start - 1;
652  bool split = false;
653 
654  for (int i=start; i < argc; i++)
655  {
656  bool success = false;
657 
658  if (argv[i][0] == '-' && argv[i][1])
659  for (int j=0; j<count; j++)
660  {
661  success = tolower(argv[i][1]) == pl[j]->ch;
662 
663  if (success)
664  {
665  if ((i+1 < argc) && pl[j]->TranslateExtras(argv[i]+2, argv[i+1]))
666  split = true;
667  else if (argv[i][2] == 0 && (i+1 < argc) && (argv[i + 1][0] != '-'))
668  pl[j]->Translate(argv[i + 1]), split = true;
669  else
670  pl[j]->Translate(argv[i] + 2);
671  break;
672  }
673  }
674 
675  if (success)
676  for (last_success++; last_success < i; last_success++)
677  warnings.printf("Command line parameter %s (#%d) ignored\n",
678  argv[last_success], last_success);
679 
680  if (split)
681  {
682  split = false;
683  last_success++;
684  i++;
685  }
686  }
687 
688  if (warnings.Length())
689  {
690  ::warning("Problems encountered parsing command line:\n\n%s",
691  (const char *) warnings);
692  warnings.Clear();
693  }
694 
695  HandlePhoneHome(argc, argv, start);
696 
697  return last_success;
698 };
699 
700 
701 void ParameterList::Status()
702 {
703  for (int i=0; i<count; i++)
704  pl[i]->Status();
705 
706  fprintf(stderr, "\n");
707 
708  if (messages.Length())
709  fprintf(stderr, "NOTES:\n%s\n", (const char *) messages);
710 }
711 
712 void ParameterList::MakeString(int argc, char ** argv, int start)
713 {
714  int len = 0;
715 
716  for (int i=start; i<argc; i++)
717  len += strlen(argv[i]) + 1;
718 
719  string = new char [len+1];
720  string[0] = 0;
721 
722  for (int i=start; i<argc; i++)
723  {
724  strcat(string, argv[i]);
725  strcat(string, " ");
726  }
727 }
728 
729 
730 void ParameterList::HandlePhoneHome(int argc, char ** argv, int start)
731 {
732  // Determine the tool name : args prior to start.
733  String programName = "";
734  for(int i = 0; i < start; i++)
735  {
736  if(i == 0)
737  {
738  programName = argv[i];
739  }
740  else
741  {
742  programName += ":";
743  programName += argv[i];
744  }
745  }
746 
747  // Loop through and get the params
748  String params = "";
749  String version = "";
750 
751  for (int i=0; i<count; i++)
752  {
753  pl[i]->addParamsToString(params);
754  // Check if phonehome is enabled.
755  if(!pl[i]->myVersion.IsEmpty() && (!pl[i]->myNoPhoneHome))
756  {
757  // Version specified & phoneHome enabled, so
758  // phonehome.
759  version = pl[i]->myVersion;
760  }
761  }
762 
763  if(!version.IsEmpty())
764  {
765  PhoneHome::checkVersion(programName.c_str(),
766  version.c_str(),
767  params.c_str());
768  }
769 }
770 
771 
772 ParameterList::~ParameterList()
773 {
774  for (int i = 0; i < count; i++)
775  delete pl[i];
776  delete [] pl;
777  delete [] string;
778 };
779 
780 bool Parameter::CheckInteger(const char * value)
781 {
782  if (value[0] != '+' && value[0] != '-' &&
783  (value[0] < '0' || value[0] > '9'))
784  return false;
785 
786  int pos = 1;
787  while (value[pos] != 0)
788  if (value[pos] < '0' || value[pos] > '9')
789  return false;
790  else
791  pos++;
792 
793  return true;
794 }
795 
796 bool Parameter::CheckDouble(const char * value)
797 {
798  if (value[0] != '+' && value[0] != '-' && value[0] != '.' &&
799  (value[0] < '0' || value[0] > '9'))
800  {
801  return false;
802  }
803 
804  bool decimal = value[0] == '.';
805 
806  for (int pos = 1; value[pos] != 0; pos++)
807  {
808  if (value[pos] < '0' || value[pos] > '9')
809  {
810  if (!decimal && value[pos] == '.')
811  {
812  decimal = true;
813  }
814  else if (value[pos] == 'e' || value[pos] == 'E')
815  {
816  return CheckInteger(value + pos + 1);
817  }
818  }
819  }
820 
821  return true;
822 }
823 
824 void ParameterList::Enforce(bool & var, bool value, const char * format, ...)
825 {
826  if (var == value)
827  return;
828 
829  var = value;
830 
831  String buffer;
832 
833  va_list ap;
834  va_start(ap, format);
835  buffer.vprintf(format, ap);
836  va_end(ap);
837 
838  messages += buffer;
839 }
840 
841 void ParameterList::Enforce(int & var, int value, const char * format, ...)
842 {
843  if (var == value)
844  return;
845 
846  var = value;
847 
848  String buffer;
849 
850  va_list ap;
851  va_start(ap, format);
852  buffer.vprintf(format, ap);
853  va_end(ap);
854 
855  messages += buffer;
856 }
857 
858 void ParameterList::Enforce(double & var, double value, const char * format, ...)
859 {
860  if (var == value)
861  return;
862 
863  var = value;
864 
865  String buffer;
866 
867  va_list ap;
868  va_start(ap, format);
869  buffer.vprintf(format, ap);
870  va_end(ap);
871 
872  messages += buffer;
873 }
874 
875 void ParameterList::Enforce(String & var, const char * value, const char * format, ...)
876 {
877  if (var.SlowCompare(value) == 0)
878  return;
879 
880  var = value;
881 
882  String buffer;
883  va_list ap;
884  va_start(ap, format);
885  buffer.vprintf(format, ap);
886  va_end(ap);
887 
888  messages += buffer;
889 }
890 
891 
892 LongParamContainer::LongParamContainer()
893  : myEndIndex(0)
894 {
895  // Add the first (also adds ending) indicators.
896  add(NULL, NULL, false, 0, 0);
897 }
898 
899 
900 LongParamContainer::~LongParamContainer()
901 {
902 }
903 
904 
905 void LongParamContainer::add(const char * label, void * val, bool excl,
906  int paramType, bool touch)
907 {
908  if(myEndIndex+1 < MAX_PARAM_ARRAY_SIZE)
909  {
910  // Overwrite the previous end record.
911  myArray[myEndIndex].description = label;
912  myArray[myEndIndex].value = val;
913  myArray[myEndIndex].exclusive = excl;
914  myArray[myEndIndex].type = paramType;
915  myArray[myEndIndex].touched = touch;
916  ++myEndIndex;
917 
918  // Add a new empty entry to the end.
919  myArray[myEndIndex].description = NULL;
920  myArray[myEndIndex].value = NULL;
921  myArray[myEndIndex].exclusive = false;
922  myArray[myEndIndex].type = 0;
923  myArray[myEndIndex].touched = 0;
924  }
925  else
926  {
927  throw std::runtime_error("Tool Error: trying to add more parameters than allowed in LongParamContainer.\n");
928  }
929 }
OptionList
Definition: Parameters.h:201
String
Definition: StringBasics.h:39
Parameter
Definition: Parameters.h:30
LongParameterList
Definition: Parameters.h:237