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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2