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