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