(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                            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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2