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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2