(file) Return to CQLUtilities.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / CQL

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2