1 /*
2  *  cArgSchema.h
3  *  Avida
4  *
5  *  Created by David Bryson on 9/12/06.
6  *  Copyright 1999-2011 Michigan State University. All rights reserved.
7  *
8  *
9  *  This file is part of Avida.
10  *
11  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
12  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
13  *
14  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
18  *  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef cArgSchema_h
23 #define cArgSchema_h
24 
25 #ifndef tDictionary_h
26 #include "tDictionary.h"
27 #endif
28 
29 
30 class cArgSchema
31 {
32 public:
33   enum tType { SCHEMA_INT, SCHEMA_DOUBLE, SCHEMA_STRING };
34 
35 private:
36   struct sArgSchemaEntry
37   {
38     cString name;
39     tType type;
40     int index;
41     bool optional;
42     union {
43       int def_int;
44       double def_double;
45       cString* def_string;
46     };
47     bool has_range_limits;
48     union {
49       int r_l_int;
50       double r_l_double;
51     };
52     union {
53       int r_u_int;
54       double r_u_double;
55     };
56 
57 
sArgSchemaEntrysArgSchemaEntry58     sArgSchemaEntry() { ; }
sArgSchemaEntrysArgSchemaEntry59     sArgSchemaEntry(const cString& in_name, int in_idx, tType in_type)  // Required Argument (supplied type)
60       : name(in_name), type(in_type), index(in_idx), optional(false), has_range_limits(false) { ; }
sArgSchemaEntrysArgSchemaEntry61     sArgSchemaEntry(const cString& in_name, int in_idx, int def)        // Optional Int Argument
62       : name(in_name), type(SCHEMA_INT), index(in_idx), optional(true), def_int(def), has_range_limits(false) { ; }
sArgSchemaEntrysArgSchemaEntry63     sArgSchemaEntry(const cString& in_name, int in_idx, double def)     // Optional Double Argument
64       : name(in_name), type(SCHEMA_DOUBLE), index(in_idx), optional(true), def_double(def), has_range_limits(false) { ; }
sArgSchemaEntrysArgSchemaEntry65     sArgSchemaEntry(const cString& in_name, int in_idx, cString* def)   // Optional String Argument
66       : name(in_name), type(SCHEMA_STRING), index(in_idx), optional(true), def_string(def), has_range_limits(false) { ; }
~sArgSchemaEntrysArgSchemaEntry67     ~sArgSchemaEntry() { if (type == SCHEMA_STRING && optional) delete def_string; }  // Cleanup string object
68   };
69 
70 
71   tDictionary<sArgSchemaEntry*> m_entries;
72   tArray<sArgSchemaEntry*> m_ints;
73   tArray<sArgSchemaEntry*> m_doubles;
74   tArray<sArgSchemaEntry*> m_strings;
75 
76   char m_sep_entry;
77   char m_sep_value;
78 
79   bool m_case_sensitive;
80 
81 
82 public:
83   cArgSchema(char entry = ',', char value = '=', bool case_sensitive = false)
m_sep_entry(entry)84     : m_sep_entry(entry), m_sep_value(value), m_case_sensitive(case_sensitive) { ; }
85   ~cArgSchema();
86 
87   inline void AdjustArgName(cString& in_name) const;
88 
GetEntrySeparator()89   char GetEntrySeparator() const { return m_sep_entry; }
GetValueSeparator()90   char GetValueSeparator() const { return m_sep_value; }
IsCaseSensitive()91   bool IsCaseSensitive() const { return m_case_sensitive; }
92 
93   bool AddEntry(cString in_name, int in_idx, tType in_type);                  // Required Argument (supplied type)
94   bool AddEntry(cString in_name, int in_idx, int def);                         // Optional Int Argument
95   bool AddEntry(cString in_name, int in_idx, int lower, int upper);           // Required Int Argument (with range limits)
96   bool AddEntry(cString in_name, int in_idx, int lower, int upper, int def);  // Optional Int Argument (with range limits)
97   bool AddEntry(cString in_name, int in_idx, double def);                     // Optional Double Argument
98   bool AddEntry(cString in_name, int in_idx, double lower, double upper);     // Required Double Argument (with range limits)
99   bool AddEntry(cString in_name, int in_idx, double lower, double upper, double def); // Optional Double (with range limits)
100   bool AddEntry(cString in_name, int in_idx, const cString& def);             // Optional String Argument
101 
102   bool FindEntry(const cString& in_name, tType& ret_type, int& ret_idx) const;
103 
GetNumIntArgs()104   inline int GetNumIntArgs() const { return m_ints.GetSize(); }
GetNumDoubleArgs()105   inline int GetNumDoubleArgs() const { return m_doubles.GetSize(); }
GetNumStringArgs()106   inline int GetNumStringArgs() const { return m_strings.GetSize(); }
107 
108   inline bool IsOptionalInt(int i) const;
109   inline bool IsOptionalDouble(int i) const;
110   inline bool IsOptionalString(int i) const;
111 
112   inline void SetDefaultInt(int i, int& v) const;
113   inline void SetDefaultDouble(int i, double& v) const;
114   inline void SetDefaultString(int i, cString& v) const;
115 
116   inline bool GetIntName(int i, cString& name) const;
117   inline bool GetDoubleName(int i, cString& name) const;
118   inline bool GetStringName(int i, cString& name) const;
119 
120   inline bool ValidateInt(int i, int v) const;
121   inline bool ValidateDouble(int i, double v) const;
122 };
123 
124 
AdjustArgName(cString & in_name)125 inline void cArgSchema::AdjustArgName(cString& in_name) const
126 {
127   in_name.Trim();
128   if (!m_case_sensitive) in_name.ToLower();
129 }
130 
131 
SetDefaultInt(int i,int & v)132 inline void cArgSchema::SetDefaultInt(int i, int& v) const
133 {
134   if (IsOptionalInt(i)) v = m_ints[i]->def_int;
135 }
136 
SetDefaultDouble(int i,double & v)137 inline void cArgSchema::SetDefaultDouble(int i, double& v) const
138 {
139   if (IsOptionalDouble(i)) v = m_doubles[i]->def_double;
140 }
141 
SetDefaultString(int i,cString & v)142 inline void cArgSchema::SetDefaultString(int i, cString& v) const
143 {
144   if (IsOptionalString(i)) v = *m_strings[i]->def_string;
145 }
146 
147 
IsOptionalInt(int i)148 inline bool cArgSchema::IsOptionalInt(int i) const
149 {
150   if (i < m_ints.GetSize() && m_ints[i]) return m_ints[i]->optional;
151   return false;
152 }
153 
IsOptionalDouble(int i)154 inline bool cArgSchema::IsOptionalDouble(int i) const
155 {
156   if (i < m_doubles.GetSize() && m_doubles[i]) return m_doubles[i]->optional;
157   return false;
158 }
159 
IsOptionalString(int i)160 inline bool cArgSchema::IsOptionalString(int i) const
161 {
162   if (i < m_strings.GetSize() && m_strings[i]) return m_strings[i]->optional;
163   return false;
164 }
165 
166 
GetIntName(int i,cString & name)167 inline bool cArgSchema::GetIntName(int i, cString& name) const
168 {
169   if (i < m_ints.GetSize() && m_ints[i]) {
170     name = m_ints[i]->name;
171     return true;
172   }
173   return false;
174 }
175 
GetDoubleName(int i,cString & name)176 inline bool cArgSchema::GetDoubleName(int i, cString& name) const
177 {
178   if (i < m_doubles.GetSize() && m_doubles[i]) {
179     name = m_doubles[i]->name;
180     return true;
181   }
182   return false;
183 }
184 
GetStringName(int i,cString & name)185 inline bool cArgSchema::GetStringName(int i, cString& name) const
186 {
187   if (i < m_strings.GetSize() && m_strings[i]) {
188     name = m_strings[i]->name;
189     return true;
190   }
191   return false;
192 }
193 
ValidateInt(int i,int v)194 inline bool cArgSchema::ValidateInt(int i, int v) const
195 {
196   if (i < m_ints.GetSize() && m_ints[i] &&
197       (!m_ints[i]->has_range_limits || (v <= m_ints[i]->r_u_int && v >= m_ints[i]->r_l_int))) {
198     return true;
199   }
200 
201   return false;
202 }
203 
ValidateDouble(int i,double v)204 inline bool cArgSchema::ValidateDouble(int i, double v) const
205 {
206   if (i < m_doubles.GetSize() && m_doubles[i] &&
207       (!m_doubles[i]->has_range_limits || (v <= m_doubles[i]->r_u_double && v >= m_doubles[i]->r_l_double))) {
208     return true;
209   }
210 
211   return false;
212 }
213 
214 
215 #endif
216