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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2