Branch data Line data Source code
1 : : /**\file CGMFileOptions.cpp
2 : : *\ copied from MOAB
3 : : *\date 2009-06-11
4 : : */
5 : :
6 : : #include "CGMFileOptions.hpp"
7 : :
8 : : #include <ctype.h>
9 : : #include <stdlib.h>
10 : : #include <string.h>
11 : :
12 : : const char DEFAULT_SEPARATOR = ';';
13 : :
14 : 10670 : static inline bool strempty( const char* s ) { return !*s; }
15 : :
16 : 55 : CGMFileOptions::CGMFileOptions( const char* str )
17 : 55 : : mData(0)
18 : : {
19 : : // if option string is null, just return
20 [ + + ]: 55 : if (!str)
21 : 55 : return;
22 : :
23 : : // check if alternate separator is specified
24 : 44 : char separator[2] = { DEFAULT_SEPARATOR, '\0' };
25 [ + + ]: 44 : if (*str == DEFAULT_SEPARATOR) {
26 : 33 : ++str;
27 [ - + ]: 33 : if (strempty(str))
28 : 0 : return;
29 : 33 : separator[0] = *str;
30 : 33 : ++str;
31 : : }
32 : :
33 : : // don't bother allocating copy of input string if
34 : : // input string is empty.
35 [ + + ]: 44 : if (!strempty(str))
36 : : {
37 : : // tokenize at separator character
38 : 33 : mData = strdup( str );
39 [ + + ]: 198 : for (char* i = strtok( mData, separator ); i; i = strtok( 0, separator ))
40 [ + - ]: 154 : if (!strempty(i)) // skip empty strings
41 [ + - ]: 154 : mOptions.push_back( i );
42 : : }
43 : : }
44 : :
45 : 33 : CGMFileOptions::CGMFileOptions( const CGMFileOptions& copy ) :
46 [ + - ][ + - ]: 33 : mData(0), mOptions( copy.mOptions.size() )
47 : : {
48 [ + - ][ + + ]: 33 : if (!copy.mOptions.empty()) {
49 [ + - ]: 22 : const char* last = copy.mOptions.back();
50 : 22 : const char* endptr = last + strlen(last) + 1;
51 : 22 : size_t len = endptr - copy.mData;
52 : 22 : mData = (char*)malloc( len );
53 : 22 : memcpy( mData, copy.mData, len );
54 [ + - ][ + + ]: 66 : for (size_t i = 0; i < mOptions.size(); ++i)
55 [ + - ][ + - ]: 44 : mOptions[i] = mData + (copy.mOptions[i] - copy.mData);
56 : : }
57 : 33 : }
58 : :
59 : 11 : CGMFileOptions& CGMFileOptions::operator=( const CGMFileOptions& copy )
60 : : {
61 : 11 : free( mData );
62 : 11 : mData = 0;
63 : 11 : mOptions.resize( copy.mOptions.size() );
64 : :
65 [ + - ]: 11 : if (!copy.mOptions.empty()) {
66 : 11 : const char* last = copy.mOptions.back();
67 : 11 : const char* endptr = last + strlen(last) + 1;
68 : 11 : size_t len = endptr - copy.mData;
69 : 11 : mData = (char*)malloc( len );
70 : 11 : memcpy( mData, copy.mData, len );
71 [ + + ]: 143 : for (size_t i = 0; i < mOptions.size(); ++i)
72 : 132 : mOptions[i] = mData + (copy.mOptions[i] - copy.mData);
73 : : }
74 : :
75 : 11 : return *this;
76 : : }
77 : :
78 : 176 : CGMFileOptions::~CGMFileOptions()
79 : : {
80 : 88 : free( mData );
81 : 88 : }
82 : :
83 : 22 : CGMFOErrorCode CGMFileOptions::get_null_option( const char* name ) const
84 : : {
85 : : const char* s;
86 [ + - ]: 22 : CGMFOErrorCode rval = get_option( name, s );
87 [ - + ]: 22 : if (FO_SUCCESS != rval)
88 : 0 : return rval;
89 [ + + ]: 22 : return strempty(s) ? FO_SUCCESS : FO_TYPE_OUT_OF_RANGE;
90 : : }
91 : :
92 : 44 : CGMFOErrorCode CGMFileOptions::get_int_option( const char* name, int& value ) const
93 : : {
94 : : const char* s;
95 [ + - ]: 44 : CGMFOErrorCode rval = get_option( name, s );
96 [ - + ]: 44 : if (FO_SUCCESS != rval)
97 : 0 : return rval;
98 : :
99 : : // empty string
100 [ + + ]: 44 : if (strempty(s))
101 : 11 : return FO_TYPE_OUT_OF_RANGE;
102 : :
103 : : // parse value
104 : : char* endptr;
105 : 33 : long int pval = strtol( s, &endptr, 0 );
106 [ + + ]: 33 : if (!strempty(endptr)) // syntax error
107 : 11 : return FO_TYPE_OUT_OF_RANGE;
108 : :
109 : : // check for overflow (parsing long int, returning int)
110 : 22 : value = pval;
111 [ - + ]: 22 : if (pval != (long int)value)
112 : 0 : return FO_TYPE_OUT_OF_RANGE;
113 : :
114 : 44 : return FO_SUCCESS;
115 : : }
116 : :
117 : 0 : CGMFOErrorCode CGMFileOptions::get_ints_option( const char* name,
118 : : std::vector<int>& values) const
119 : : {
120 : : const char* s;
121 [ # # ]: 0 : CGMFOErrorCode rval = get_option( name, s );
122 [ # # ]: 0 : if (FO_SUCCESS != rval)
123 : 0 : return rval;
124 : :
125 : : // empty string
126 [ # # ]: 0 : if (strempty(s))
127 : 0 : return FO_TYPE_OUT_OF_RANGE;
128 : :
129 : : // parse values
130 [ # # ]: 0 : while (!strempty(s)) {
131 : : char* endptr;
132 : 0 : long int sval = strtol( s, &endptr, 0 );
133 : :
134 : : #define EATSPACE(a) while ((!strncmp(a, " ", 1) || \
135 : : !strncmp(a, ",", 1)) && !strempty(a)) a++;
136 : : //EATSPACE(endptr);
137 : :
138 [ # # ][ # # ]: 0 : while ((!strncmp(endptr, " ", 1) ||
139 [ # # ][ # # ]: 0 : !strncmp(endptr, ",", 1)) && !strempty(endptr)) {
140 : 0 : endptr++;
141 : : }
142 : :
143 : 0 : long int eval = sval;
144 [ # # ]: 0 : if (!strcmp(endptr, "-")) {
145 : 0 : endptr++;
146 : 0 : s = endptr;
147 : 0 : eval = strtol(s, &endptr, 0);
148 [ # # ][ # # ]: 0 : EATSPACE(endptr);
[ # # ][ # # ]
149 : : }
150 : :
151 : : // check for overflow (parsing long int, returning int)
152 : 0 : int value = sval;
153 [ # # ]: 0 : if (sval != (long int)value)
154 : 0 : return FO_TYPE_OUT_OF_RANGE;
155 : 0 : value = eval;
156 [ # # ]: 0 : if (eval != (long int)value)
157 : 0 : return FO_TYPE_OUT_OF_RANGE;
158 : :
159 [ # # ]: 0 : for (int i = sval; i <= eval; i++)
160 [ # # ]: 0 : values.push_back(i);
161 : :
162 : 0 : s = endptr;
163 : : }
164 : :
165 : 0 : return FO_SUCCESS;
166 : : }
167 : :
168 : 55 : CGMFOErrorCode CGMFileOptions::get_real_option ( const char* name, double& value ) const
169 : : {
170 : : const char* s;
171 [ + - ]: 55 : CGMFOErrorCode rval = get_option( name, s );
172 [ - + ]: 55 : if (FO_SUCCESS != rval)
173 : 0 : return rval;
174 : :
175 : : // empty string
176 [ + + ]: 55 : if (strempty(s))
177 : 11 : return FO_TYPE_OUT_OF_RANGE;
178 : :
179 : : // parse value
180 : : char* endptr;
181 : 44 : value = strtod( s, &endptr );
182 [ + + ]: 44 : if (!strempty(endptr)) // syntax error
183 : 11 : return FO_TYPE_OUT_OF_RANGE;
184 : :
185 : 55 : return FO_SUCCESS;
186 : : }
187 : :
188 : 33 : CGMFOErrorCode CGMFileOptions::get_str_option( const char* name, std::string& value ) const
189 : : {
190 : : const char* s;
191 [ + - ]: 33 : CGMFOErrorCode rval = get_option( name, s );
192 [ - + ]: 33 : if (FO_SUCCESS != rval)
193 : 0 : return rval;
194 [ + + ]: 33 : if (strempty(s))
195 : 11 : return FO_TYPE_OUT_OF_RANGE;
196 [ + - ]: 22 : value = s;
197 : 33 : return FO_SUCCESS;
198 : : }
199 : :
200 : 99 : CGMFOErrorCode CGMFileOptions::get_option( const char* name, std::string& value ) const
201 : : {
202 : : const char* s;
203 [ + - ]: 99 : CGMFOErrorCode rval = get_option( name, s );
204 [ - + ]: 99 : if (FO_SUCCESS != rval)
205 : 0 : return rval;
206 : :
207 [ + - ]: 99 : value = s;
208 : 99 : return FO_SUCCESS;
209 : : }
210 : :
211 : 253 : CGMFOErrorCode CGMFileOptions::get_option( const char* name, const char*& value ) const
212 : : {
213 [ + - ]: 253 : std::vector<const char*>::const_iterator i;
214 [ + - ][ + - ]: 1441 : for (i = mOptions.begin(); i != mOptions.end(); ++i) {
[ + - ][ + - ]
[ + - ]
215 [ + - ]: 1441 : const char* opt = *i;
216 [ + - ][ + + ]: 1441 : if (compare( name, opt )) {
217 : 253 : value = opt + strlen(name);
218 : : // if compare returned true, next char after option
219 : : // name must be either the null char or an equals symbol.
220 [ + + ]: 253 : if (*value == '=')
221 : 187 : ++value;
222 : :
223 : 253 : return FO_SUCCESS;
224 : : }
225 : : }
226 : :
227 : 253 : return FO_ENTITY_NOT_FOUND;
228 : : }
229 : :
230 : 0 : CGMFOErrorCode CGMFileOptions::match_option( const char* name,
231 : : const char* value ) const
232 : : {
233 : : int idx;
234 : 0 : const char* array[] = { value, NULL };
235 [ # # ]: 0 : return match_option( name, array, idx );
236 : : }
237 : :
238 : 0 : CGMFOErrorCode CGMFileOptions::match_option( const char* name,
239 : : const char* const* values,
240 : : int& index ) const
241 : : {
242 : : const char* optval;
243 [ # # ]: 0 : CGMFOErrorCode rval = get_option( name, optval );
244 [ # # ]: 0 : if (FO_SUCCESS != rval)
245 : 0 : return rval;
246 : :
247 [ # # ]: 0 : for (index = 0; values[index]; ++index)
248 [ # # ][ # # ]: 0 : if (compare( optval, values[index] ))
249 : 0 : return FO_SUCCESS;
250 : :
251 : 0 : index = -1;
252 : 0 : return FO_FAILURE;
253 : : }
254 : :
255 : :
256 : 1441 : bool CGMFileOptions::compare( const char* name, const char* option )
257 : : {
258 [ + + ][ + + ]: 3179 : while (!strempty(name) && toupper(*name) == toupper(*option)) {
[ + + ]
259 : 1738 : ++name;
260 : 1738 : ++option;
261 : : }
262 : : // match if name matched option for length of name,
263 : : // and option either matched entirely or matches up to
264 : : // and equals sign.
265 [ + + ][ + + ]: 1441 : return strempty(name) && (strempty(option) || *option == '=');
[ + - ]
266 : : }
267 : :
268 : 0 : void CGMFileOptions::get_options( std::vector<std::string>& list ) const
269 : : {
270 : 0 : list.clear();
271 [ # # ][ # # ]: 0 : list.resize( mOptions.size() );
272 : 0 : std::copy( mOptions.begin(), mOptions.end(), list.begin() );
273 : 0 : }
274 : :
|