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