1 karl 1.18 //%2006////////////////////////////////////////////////////////////////////////
|
2 chuck 1.2 //
|
3 karl 1.13 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 chuck 1.2 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.13 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.18 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 chuck 1.2 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Authors: David Rosckes (rosckes@us.ibm.com)
33 // Bert Rivero (hurivero@us.ibm.com)
34 chuck 1.2 // Chuck Carmack (carmack@us.ibm.com)
35 // Brian Lucier (lucier@us.ibm.com)
36 //
|
37 david.dillard 1.14 // Modified By:
38 // David Dillard, VERITAS Software Corp.
39 // (david.dillard@veritas.com)
|
40 chuck 1.2 //
41 //%/////////////////////////////////////////////////////////////////////////////
|
42 lucier 1.7
|
43 chuck 1.2 #include <Pegasus/CQL/CQLUtilities.h>
|
44 lucier 1.7
45 // Query includes
46 #include <Pegasus/Query/QueryCommon/QueryException.h>
47
48 // Pegasus Common includes
49 #include <Pegasus/Common/Tracer.h>
50
51 // standard includes
|
52 chuck 1.3 #include <errno.h>
|
53 chuck 1.2
|
54 lucier 1.7 // symbol defines
|
55 chuck 1.2 #define PEGASUS_SINT64_MIN (PEGASUS_SINT64_LITERAL(0x8000000000000000))
56 #define PEGASUS_UINT64_MAX PEGASUS_UINT64_LITERAL(0xFFFFFFFFFFFFFFFF)
57
|
58 lucier 1.7 // required for the windows compile
|
59 lucier 1.5 #ifndef _MSC_VER
60 #define _MSC_VER 0
61 #endif
62
|
63 chuck 1.2 PEGASUS_NAMESPACE_BEGIN
64
|
65 david.dillard 1.14 inline Uint8 _CQLUtilities_hexCharToNumeric(Char16 c)
|
66 chuck 1.2 {
67 Uint8 n;
68
|
69 david.dillard 1.15 if (isdigit(c))
|
70 chuck 1.2 n = (c - '0');
|
71 david.dillard 1.15 else if (isupper(c))
|
72 chuck 1.2 n = (c - 'A' + 10);
73 else // if (islower(c))
74 n = (c - 'a' + 10);
75
76 return n;
77 }
78
79 Uint64 CQLUtilities::stringToUint64(const String &stringNum)
80 {
|
81 lucier 1.7 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToUint64()");
82
|
83 chuck 1.2 Uint64 x = 0;
84 const Char16* p = stringNum.getChar16Data();
85 const Char16* pStart = p;
86
|
87 lucier 1.8 if (String::equal(stringNum, String::EMPTY))
88 {
89 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
|
90 humberto 1.12 String("Error converting string to $0. String cannot be $1."),
91 String("Uint64"), String("empty"));
|
92 lucier 1.8 throw CQLRuntimeException(mload);
93 }
94
|
95 chuck 1.2 if (!p)
|
96 lucier 1.7 {
|
97 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
98 String("Error converting string to $0. String cannot be $1."),
99 String("Uint64"), String("NULL"));
|
100 lucier 1.7 throw CQLRuntimeException(mload);
101 }
|
102 chuck 1.2
|
103 humberto 1.12 // If the string is a real number, use stringToReal, then convert to a Uint64
104 if (isReal(stringNum))
105 {
106 // Note: the cast will rip off any non-whole number precision. CQL spec
107 // is silent on whether to round up, round down, throw an error, or allow
108 // the platform to round as it sees fit. We chose the latter for now.
109 return (Uint64) stringToReal64(stringNum);
110 }
111
|
112 chuck 1.2 // There cannot be a negative '-' sign
113 if (*p == '-')
|
114 lucier 1.7 {
115 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NEG"),
|
116 humberto 1.12 String("Error converting string to $0. String '$1' cannot begin with '-'."),
117 String("Uint64"),
|
118 lucier 1.7 stringNum);
119 throw CQLRuntimeException(mload);
120 }
|
121 chuck 1.2 if (*p == '+')
122 p++; // skip over the positive sign
123
|
124 kumpf 1.16 if (!((*p >= '0') && (*p <= '9')))
|
125 lucier 1.7 {
126 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NUM_FORMAT"),
|
127 humberto 1.12 String("Error converting string to $0. String '$1' is badly formed."),
128 String("Uint64"),
|
129 lucier 1.7 stringNum);
130 throw CQLRuntimeException(mload);
131 }
|
132 chuck 1.2
|
133 humberto 1.12 // if hexidecimal
134 if ( (*p == '0') && ((p[1] == 'x') || (p[1] == 'X')) )
|
135 chuck 1.2 {
|
136 humberto 1.12 // Convert a hexadecimal string
137
138 // Skip over the "0x"
139 p+=2;
140
141 // At least one hexadecimal digit is required
142 if (!*p)
143 {
144 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_FORMAT"),
145 String("Error converting string to $0. String '$1' needs a hexadecimal digit character following '0x'"),
146 String("Uint64"),
147 stringNum);
148 throw CQLRuntimeException(mload);
149 }
150
|
151 chuck 1.2 // Add on each digit, checking for overflow errors
|
152 kumpf 1.16 while (isascii(*p) && isxdigit(*p))
|
153 chuck 1.2 {
|
154 humberto 1.12 // Make sure we won't overflow when we multiply by 16
155 if (x > PEGASUS_UINT64_MAX/16)
|
156 lucier 1.7 {
157 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
158 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
159 String("Uint64"),
|
160 lucier 1.7 stringNum);
161 throw CQLRuntimeException(mload);
162 }
|
163 chuck 1.2
|
164 humberto 1.12 x = x << 4;
|
165 chuck 1.2
166 // We can't overflow when we add the next digit
|
167 humberto 1.12 Uint64 newDigit = Uint64(_CQLUtilities_hexCharToNumeric(*p++));
|
168 chuck 1.2 if (PEGASUS_UINT64_MAX - x < newDigit)
|
169 lucier 1.7 {
170 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
171 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
172 String("Uint64"),
173 stringNum);
|
174 lucier 1.7 throw CQLRuntimeException(mload);
175 }
|
176 chuck 1.2
177 x = x + newDigit;
178 }
179
|
180 humberto 1.12 // If we found a non-hexadecimal digit, report an error
181 if (*p)
|
182 lucier 1.7 {
|
183 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_CHAR"),
184 String("Error converting string to $0. Character '$1' in string '$2' is not a hexidecimal digit."),
185 String("Uint64"),
186 String(p, 1), stringNum);
|
187 lucier 1.7 throw CQLRuntimeException(mload);
188 }
|
189 chuck 1.2
|
190 humberto 1.12 // return value from the hex string
|
191 lucier 1.7 PEG_METHOD_EXIT();
|
192 humberto 1.12 return x;
193 } // end if hexidecimal
|
194 chuck 1.2
|
195 humberto 1.12 // if binary
196 Uint32 endString = stringNum.size() - 1;
197 if ( (pStart[endString] == 'b') || (pStart[endString] == 'B') )
|
198 chuck 1.2 {
199 // Add on each digit, checking for overflow errors
|
200 humberto 1.12 while ((*p == '0') || (*p == '1'))
|
201 chuck 1.2 {
|
202 humberto 1.12 // Make sure we won't overflow when we multiply by 2
203 if (x > PEGASUS_UINT64_MAX/2)
|
204 lucier 1.7 {
205 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
206 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
207 String("Uint64"),
|
208 lucier 1.7 stringNum);
209 throw CQLRuntimeException(mload);
210 }
|
211 chuck 1.2
|
212 humberto 1.12 x = x << 1;
|
213 chuck 1.2
214 // We can't overflow when we add the next digit
|
215 humberto 1.12 Uint64 newDigit = 0;
216 if (*p++ == '1')
217 newDigit = 1;
|
218 chuck 1.2 if (PEGASUS_UINT64_MAX - x < newDigit)
|
219 lucier 1.7 {
220 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
221 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
222 String("Uint64"),
|
223 lucier 1.7 stringNum);
224 throw CQLRuntimeException(mload);
225 }
|
226 chuck 1.2
227 x = x + newDigit;
228 }
229
|
230 humberto 1.12 // If we found a non-binary digit before the terminating 'b', then report an error
231 if (*p && (p-pStart < (Sint32)endString || (*p != 'b' && *p != 'B')))
|
232 lucier 1.7 {
|
233 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_BIN_CHAR"),
234 String("Error converting string to $0. Character '$1' in string '$2' is not a binary digit."),
235 String("Uint64"),
236 String(p, 1), stringNum);
|
237 lucier 1.7 throw CQLRuntimeException(mload);
238 }
|
239 chuck 1.2
|
240 humberto 1.12 // return value from the binary string
|
241 lucier 1.7 PEG_METHOD_EXIT();
|
242 humberto 1.12 return x;
243 } // end if binary
|
244 chuck 1.2
245
246 // Expect a positive decimal digit:
247
248 // Add on each digit, checking for overflow errors
|
249 kumpf 1.16 while ((*p >= '0') && (*p <= '9'))
|
250 chuck 1.2 {
251 // Make sure we won't overflow when we multiply by 10
252 if (x > PEGASUS_UINT64_MAX/10)
|
253 lucier 1.7 {
254 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
255 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
256 String("Uint64"),
|
257 lucier 1.7 stringNum);
258 throw CQLRuntimeException(mload);
259 }
|
260 chuck 1.2 x = 10 * x;
261
262 // Make sure we won't overflow when we add the next digit
263 Uint64 newDigit = (*p++ - '0');
264 if (PEGASUS_UINT64_MAX - x < newDigit)
|
265 lucier 1.7 {
266 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
267 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
268 String("Uint64"),
269 stringNum);
|
270 lucier 1.7 throw CQLRuntimeException(mload);
271 }
|
272 chuck 1.2
273 x = x + newDigit;
274 }
275
|
276 lucier 1.9 // If we found a non-decimal digit, report an error
|
277 chuck 1.2 if (*p)
|
278 lucier 1.7 {
|
279 lucier 1.9 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
|
280 humberto 1.12 String("Error converting string to $0. Character '$1' in string '$2' is not a decimal digit."),
281 String("Uint64"),
|
282 lucier 1.9 String(p, 1), stringNum);
283 throw CQLRuntimeException(mload);
|
284 lucier 1.7 }
|
285 chuck 1.2
286 // return the value for the decimal string
|
287 lucier 1.7 PEG_METHOD_EXIT();
|
288 chuck 1.2 return x;
289 }
290
291 Sint64 CQLUtilities::stringToSint64(const String &stringNum)
292 {
|
293 lucier 1.7 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToSint64()");
294
|
295 chuck 1.2 Sint64 x = 0;
296 Boolean invert = false;
297 const Char16* p = stringNum.getChar16Data();
298 const Char16* pStart = p;
299
|
300 lucier 1.8 if (String::equal(stringNum, String::EMPTY))
301 {
302 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
|
303 humberto 1.12 String("Error converting string to $0. String cannot be $1."),
304 String("Sint64"), String("empty"));
|
305 lucier 1.8 throw CQLRuntimeException(mload);
306 }
307
|
308 chuck 1.2 if (!p)
|
309 lucier 1.7 {
|
310 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
311 String("Error converting string to $0. String cannot be $1."),
312 String("Sint64"), String("NULL"));
|
313 lucier 1.7 throw CQLRuntimeException(mload);
314 }
|
315 chuck 1.2
|
316 humberto 1.12 // If the string is a real number, use stringToReal, then convert to a Sint64
317 if (isReal(stringNum))
318 {
319 // Note: the cast will rip off any non-whole number precision. CQL spec
320 // is silent on whether to round up, round down, throw an error, or allow
321 // the platform to round as it sees fit. We chose the latter for now.
322 return (Sint64) stringToReal64(stringNum);
323 }
324
|
325 chuck 1.2 // skip over the sign if there is one
326 if (*p == '-')
327 {
328 invert = true;
329 p++;
330 }
331 if (*p == '+')
332 p++;
333
|
334 kumpf 1.16 if (!((*p >= '0') && (*p <= '9')))
|
335 lucier 1.7 {
336 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NUM_FORMAT"),
|
337 humberto 1.12 String("Error converting string to $0. String '$1' is badly formed."),
338 String("Uint64"),
|
339 lucier 1.7 stringNum);
340 throw CQLRuntimeException(mload);
341 }
|
342 chuck 1.2
343 // ********************
344 // Build the Sint64 as a negative number, regardless of the
345 // eventual sign (negative numbers can be bigger than positive ones)
346 // ********************
347
|
348 humberto 1.12 // if hexidecimal
349 if ( (*p == '0') && ((p[1] == 'x') || (p[1] == 'X')) )
|
350 chuck 1.2 {
|
351 humberto 1.12 // Convert a hexadecimal string
352
353 // Skip over the "0x"
354 p+=2;
355
356 // At least one hexidecimal digit is required
357 if (!*p)
358 {
359 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_FORMAT"),
360 String("Error converting string to $0. String '$1' needs a hexadecimal digit character following '0x'."),
361 String("Sint64"),
362 stringNum);
363 throw CQLRuntimeException(mload);
364 }
365
|
366 chuck 1.2 // Add on each digit, checking for overflow errors
|
367 kumpf 1.16 while (isascii(*p) && isxdigit(*p))
|
368 chuck 1.2 {
|
369 humberto 1.12 // Make sure we won't overflow when we multiply by 16
370 if (x < PEGASUS_SINT64_MIN/16)
|
371 lucier 1.7 {
372 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
373 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
374 String("Sint64"),
|
375 lucier 1.7 stringNum);
376 throw CQLRuntimeException(mload);
377 }
|
378 chuck 1.2
|
379 humberto 1.12 x = x << 4;
|
380 chuck 1.2
381 // We can't overflow when we add the next digit
|
382 humberto 1.12 Sint64 newDigit = Sint64(_CQLUtilities_hexCharToNumeric(*p++));
|
383 chuck 1.2 if (PEGASUS_SINT64_MIN - x > -newDigit)
|
384 lucier 1.7 {
385 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
386 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
387 String("Sint64"),
|
388 lucier 1.7 stringNum);
389 throw CQLRuntimeException(mload);
390 }
|
391 chuck 1.2
392 x = x - newDigit;
393 }
394
|
395 humberto 1.12 // If we found a non-hexidecimal digit, report an error
396 if (*p)
|
397 lucier 1.7 {
|
398 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_CHAR"),
399 String("Error converting string to $0. Character '$1' in string '$2' is not a hexidecimal digit."),
400 String("Sint64"),
401 String(p, 1), stringNum);
|
402 lucier 1.7 throw CQLRuntimeException(mload);
403 }
|
404 chuck 1.2
405 // Return the integer to positive, if necessary, checking for an
406 // overflow error
407 if (!invert)
408 {
409 if (x == PEGASUS_SINT64_MIN)
|
410 lucier 1.7 {
411 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
412 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
413 String("Sint64"),
|
414 lucier 1.7 stringNum);
415 throw CQLRuntimeException(mload);
416 }
|
417 chuck 1.2 x = -x;
418 }
419
|
420 humberto 1.12 // return value from the hex string
|
421 lucier 1.7 PEG_METHOD_EXIT();
|
422 humberto 1.12 return x;
423 } // end if hexidecimal
|
424 chuck 1.2
|
425 humberto 1.12 // if binary
426 Uint32 endString = stringNum.size() - 1;
427 if ( (pStart[endString] == 'b') || (pStart[endString] == 'B') )
|
428 chuck 1.2 {
429 // Add on each digit, checking for overflow errors
|
430 humberto 1.12 while ((*p == '0') || (*p == '1'))
|
431 chuck 1.2 {
|
432 humberto 1.12 // Make sure we won't overflow when we multiply by 2
433 if (x < PEGASUS_SINT64_MIN/2)
|
434 lucier 1.7 {
435 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
436 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
437 String("Sint64"),
438 stringNum);
|
439 lucier 1.7 throw CQLRuntimeException(mload);
440 }
|
441 chuck 1.2
|
442 humberto 1.12 x = x << 1;
|
443 chuck 1.2
444 // We can't overflow when we add the next digit
|
445 humberto 1.12 Sint64 newDigit = 0;
446 if (*p++ == '1')
447 newDigit = 1;
|
448 chuck 1.2 if (PEGASUS_SINT64_MIN - x > -newDigit)
|
449 lucier 1.7 {
450 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
451 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
452 String("Sint64"),
|
453 lucier 1.7 stringNum);
454 throw CQLRuntimeException(mload);
455 }
|
456 chuck 1.2
|
457 lucier 1.4 x = x - newDigit;
|
458 chuck 1.2 }
459
|
460 humberto 1.12 // If we found a non-binary digit before the terminating 'b', then report an error
461 if (*p && (p-pStart < (Sint32)endString || (*p != 'b' && *p != 'B')))
|
462 lucier 1.7 {
|
463 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_BIN_CHAR"),
464 String("Error converting string to $0. Character '$1' in string '$2' is not a binary digit."),
465 String("Sint64"),
466 String(p, 1), stringNum);
|
467 lucier 1.7 throw CQLRuntimeException(mload);
468 }
|
469 chuck 1.2
470 // Return the integer to positive, if necessary, checking for an
471 // overflow error
472 if (!invert)
473 {
474 if (x == PEGASUS_SINT64_MIN)
|
475 lucier 1.7 {
476 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
477 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
478 String("Sint64"),
|
479 lucier 1.7 stringNum);
480 throw CQLRuntimeException(mload);
481 }
|
482 chuck 1.2 x = -x;
483 }
484
|
485 humberto 1.12 // return value from the binary string
|
486 lucier 1.7 PEG_METHOD_EXIT();
|
487 humberto 1.12 return x;
488 } // end if binary
|
489 chuck 1.2
490 // Expect a positive decimal digit:
491
492 // Add on each digit, checking for overflow errors
|
493 kumpf 1.16 while ((*p >= '0') && (*p <= '9'))
|
494 chuck 1.2 {
495 // Make sure we won't overflow when we multiply by 10
|
496 lucier 1.4 if (x < PEGASUS_SINT64_MIN/10)
|
497 lucier 1.7 {
498 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
499 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
500 String("Sint64"),
|
501 lucier 1.7 stringNum);
502 throw CQLRuntimeException(mload);
503 }
|
504 chuck 1.2 x = 10 * x;
505
506 // Make sure we won't overflow when we add the next digit
507 Sint64 newDigit = (*p++ - '0');
508 if (PEGASUS_SINT64_MIN - x > -newDigit)
|
509 lucier 1.7 {
510 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
511 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
512 String("Sint64"),
|
513 lucier 1.7 stringNum);
514 throw CQLRuntimeException(mload);
515 }
|
516 chuck 1.2
|
517 lucier 1.4 x = x - newDigit;
|
518 chuck 1.2 }
519
520 // If we found a non-decimal digit, report an error
521 if (*p)
|
522 lucier 1.7 {
523 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
|
524 humberto 1.12 String("Error converting string to $0. Character '$1' in string '$2' is not a decimal digit."),
525 String("Sint64"),
|
526 lucier 1.9 String(p, 1), stringNum);
|
527 lucier 1.7 throw CQLRuntimeException(mload);
528 }
|
529 chuck 1.2
530 // Return the integer to positive, if necessary, checking for an
531 // overflow error
532 if (!invert)
533 {
534 if (x == PEGASUS_SINT64_MIN)
|
535 lucier 1.7 {
536 MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
|
537 humberto 1.12 String("Error converting string to $0. String '$1' caused an overflow."),
538 String("Sint64"),
|
539 lucier 1.7 stringNum);
540 throw CQLRuntimeException(mload);
541 }
|
542 chuck 1.2 x = -x;
543 }
544
545 // return the value for the decimal string
|
546 lucier 1.7 PEG_METHOD_EXIT();
|
547 chuck 1.2 return x;
548 }
549
550 Real64 CQLUtilities::stringToReal64(const String &stringNum)
551 {
|
552 lucier 1.7 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToReal64()");
553
|
554 chuck 1.2 Real64 x = 0;
555 const Char16* p = stringNum.getChar16Data();
|
556 lucier 1.4 Boolean neg = false;
557 const Char16* pStart = p;
|
558 chuck 1.2
|
559 lucier 1.8 if (String::equal(stringNum, String::EMPTY))
560 {
561 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
|
562 humberto 1.12 String("Error converting string to $0. String cannot be $1."),
563 String("Real64"), String("empty"));
|
564 lucier 1.8 throw CQLRuntimeException(mload);
565 }
566
567 if (!p)
|
568 lucier 1.7 {
|
569 humberto 1.12 MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
570 String("Error converting string to $0. String cannot be $1."),
571 String("Real64"), String("NULL"));
|
572 lucier 1.7 throw CQLRuntimeException(mload);
573 }
|
574 chuck 1.2
|
575 lucier 1.4
|
576 chuck 1.2 // Skip optional sign:
577
|
578 lucier 1.4 if (*p == '+')
|
579 chuck 1.2 p++;
|
580 lucier 1.4
581 if (*p == '-')
582 {
583 neg = true;
584 p++;
585 };
|
586 lucier 1.5
|
587 lucier 1.4 // Check if it it is a binary or hex integer
588 Uint32 endString = stringNum.size() - 1;
589 if ((*p == '0' && (p[1] == 'x' || p[1] == 'X')) || // hex OR
590 pStart[endString] == 'b' || pStart[endString] == 'B') // binary
591 {
592 if (neg)
593 x = stringToSint64(stringNum);
594 else
|
595 lucier 1.5
596 // Check if the complier is MSVC 6, which does not support the conversion operator from Uint64 to Real64
597 #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) && (_MSC_VER < 1300)
598 {
599 Uint64 num = stringToUint64(stringNum);
600 Sint64 half = num / 2;
601 x = half;
|
602 lucier 1.6 x += half;
|
603 lucier 1.5 if (num % 2) // if odd, then add the lost remainder
604 x += 1;
605 }
606 #else
|
607 lucier 1.4 x = stringToUint64(stringNum);
|
608 lucier 1.5 #endif
|
609 lucier 1.7 PEG_METHOD_EXIT();
|
610 lucier 1.4 return x;
611 }
612
|
613 chuck 1.2 // Skip optional first set of digits:
614
|
615 kumpf 1.16 while ((*p >= '0') && (*p <= '9'))
|
616 chuck 1.2 p++;
617
618 // Test if optional dot is there
619 if (*p++ == '.')
620 {
621 // One or more digits required:
|
622 kumpf 1.16 if (!((*p >= '0') && (*p <= '9')))
|
623 lucier 1.7 {
624 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_CHAR_POST_DOT"),
|
625 humberto 1.12 String("Error converting string to Real64. String '$0' must have a digit character following the decimal point."),
|
626 lucier 1.7 stringNum);
627 throw CQLRuntimeException(mload);
628 }
|
629 kumpf 1.16 p++;
|
630 chuck 1.2
|
631 kumpf 1.16 while ((*p >= '0') && (*p <= '9'))
|
632 chuck 1.2 p++;
633
634 // If there is an exponent now:
635 if (*p)
636 {
637 // Test exponent:
638
639 if (*p != 'e' && *p != 'E')
|
640 lucier 1.7 {
641 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_REAL_CHAR"),
|
642 humberto 1.12 String("Error converting string to $0. Character '$1' in string '$2` is invalid."),
643 String("Real64"),
|
644 kumpf 1.17 String(p, 1), stringNum);
|
645 lucier 1.7 throw CQLRuntimeException(mload);
646 }
|
647 chuck 1.2 p++;
648
649 // Skip optional sign:
650
651 if (*p == '+' || *p == '-')
652 p++;
653
654 // One or more digits required:
|
655 kumpf 1.16 if (!((*p >= '0') && (*p <= '9')))
|
656 lucier 1.7 {
657 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_REAL_EXP"),
|
658 kumpf 1.16 String("Error converting string to Real64. String '$0' has a badly formed exponent. Character '$1' is invalid."),
|
659 lucier 1.9 stringNum, String(p, 1));
|
660 lucier 1.7 throw CQLRuntimeException(mload);
661 }
|
662 kumpf 1.16 p++;
|
663 chuck 1.2
|
664 kumpf 1.16 while ((*p >= '0') && (*p <= '9'))
|
665 chuck 1.2 p++;
666 }
|
667 lucier 1.7 } // end-if optional decimal point
|
668 humberto 1.12 if (*p && p - pStart <= (Sint32) stringNum.size())
|
669 lucier 1.7 {
|
670 lucier 1.8 // printf("This is char # %d\n", p - pStart);
|
671 lucier 1.7 MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
|
672 humberto 1.12 String("Error converting string to $0. Character '$1' in string '$2' is not a decimal digit."),
673 String("Real64"),
|
674 lucier 1.9 String(p-1, 1), stringNum);
|
675 lucier 1.7 throw CQLRuntimeException(mload);
|
676 chuck 1.2 }
677 //
678 // Do the conversion
679 //
680 char* end;
681 errno = 0;
682 CString temp = stringNum.getCString();
683 x = strtod((const char *) temp, &end);
684 if (*end || (errno == ERANGE))
685 {
|
686 humberto 1.10 MessageLoaderParms mload(String("CQL.CQLUtilities.CONVERSION_REAL_ERROR"),
|
687 humberto 1.12 String("String '$0' was unable to be converted to a Real64. It could be out of range."),
|
688 lucier 1.7 stringNum);
689 throw CQLRuntimeException(mload);
|
690 chuck 1.2 }
|
691 lucier 1.7 PEG_METHOD_EXIT();
|
692 lucier 1.9 // printf("String %s = %.16e\n", (const char *)stringNum.getCString(), x);
|
693 chuck 1.2 return x;
694 }
695
|
696 lucier 1.11 String CQLUtilities::formatRealStringExponent(const String &realString)
697 {
698 String newString(realString);
699 Uint32 expIndex = PEG_NOT_FOUND;
700 Uint32 index = newString.size() - 1;
701
702 expIndex = newString.find('E');
703 if (expIndex == PEG_NOT_FOUND)
704 expIndex = newString.find('e');
705
706 if (expIndex == PEG_NOT_FOUND)
707 return newString; // no exponent symbol, so just return
708
709 // format the exponent
710 index = expIndex + 1; // start index at next character
711 if (newString[index] == '+')
712 newString.remove(index, 1); // remove the '+' symbol
713
714 if (newString[index] == '-')
715 index++; // skip the '-' exponent sign
716
717 lucier 1.11 while (newString[index] == '0' && index < newString.size())
718 {
719 newString.remove(index, 1);
720 }
721
722 // If only an 'e' is left (only 0's behind it) then strip the 'e'
723 if (index >= newString.size())
724 newString.remove(expIndex, 1);
725
726 return newString;
727 }
728
|
729 humberto 1.12 Boolean CQLUtilities::isReal(const String &numString)
730 {
731 // If there is a decimal point, we consider it to be a real.
732 if (numString.find('.') == PEG_NOT_FOUND)
733 return false;
734 return true;
735 }
736
|
737 chuck 1.2 PEGASUS_NAMESPACE_END
|