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

File: [Pegasus] / pegasus / src / Pegasus / CQL / CQLUtilities.cpp (download)
Revision: 1.18, Mon Jan 30 16:16:39 2006 UTC (18 years, 5 months ago) by karl
Branch: MAIN
CVS Tags: TASK_PEP233_EmbeddedInstSupport-merge_out_trunk, TASK_BUG_5314_IPC_REFACTORING_ROOT, TASK_BUG_5314_IPC_REFACTORING_BRANCH, TASK_BUG_5314_IPC_REFACTORING-V1, TASK_BUG_5191_QUEUE_CONSOLIDATION_ROOT, TASK_BUG_5191_QUEUE_CONSOLIDATION_BRANCH, TASK-TASK-BUG4011_WinLocalConnect-branch-New-root, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_out_to_branch, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_out_from_trunk, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_in_to_trunk, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_in_from_branch, TASK-TASK-BUG4011_WinLocalConnect-branch-New-branch, TASK-PEP268_SSLClientCertificatePropagation-root, TASK-PEP268_SSLClientCertificatePropagation-merged_out_to_branch, TASK-PEP268_SSLClientCertificatePropagation-merged_out_from_trunk, TASK-PEP268_SSLClientCertificatePropagation-merged_in_to_trunk, TASK-PEP268_SSLClientCertificatePropagation-merged_in_from_branch, TASK-PEP268_SSLClientCertificatePropagation-branch, TASK-PEP267_SLPReregistrationSupport-root, TASK-PEP267_SLPReregistrationSupport-merging_out_to_branch, TASK-PEP267_SLPReregistrationSupport-merging_out_from_trunk, TASK-PEP267_SLPReregistrationSupport-merged_out_to_branch, TASK-PEP267_SLPReregistrationSupport-merged_out_from_trunk, TASK-PEP267_SLPReregistrationSupport-merged_in_to_trunk, TASK-PEP267_SLPReregistrationSupport-merged_in_from_branch, TASK-PEP267_SLPReregistrationSupport-branch, TASK-PEP250_RPMProvider-root, TASK-PEP250_RPMProvider-merged_out_to_branch, TASK-PEP250_RPMProvider-merged_out_from_trunk, TASK-PEP250_RPMProvider-merged_in_to_trunk, TASK-PEP250_RPMProvider-merged_in_from_branch, TASK-PEP250_RPMProvider-branch, TASK-PEP245_CimErrorInfrastructure-root, TASK-PEP245_CimErrorInfrastructure-merged_out_to_branch, TASK-PEP245_CimErrorInfrastructure-merged_out_from_trunk, TASK-PEP245_CimErrorInfrastructure-merged_in_to_trunk, TASK-PEP245_CimErrorInfrastructure-merged_in_from_branch, TASK-PEP245_CimErrorInfrastructure-branch, TASK-PEP241_OpenPegasusStressTests-root, TASK-PEP241_OpenPegasusStressTests-merged_out_to_branch, TASK-PEP241_OpenPegasusStressTests-merged_out_from_trunk, TASK-PEP241_OpenPegasusStressTests-merged_in_to_trunk, TASK-PEP241_OpenPegasusStressTests-merged_in_from_branch, TASK-PEP241_OpenPegasusStressTests-branch, TASK-Bugs5690_3913_RemoteCMPI-root, TASK-Bugs5690_3913_RemoteCMPI-merged_out_to_branch, TASK-Bugs5690_3913_RemoteCMPI-merged_out_from_trunk, TASK-Bugs5690_3913_RemoteCMPI-merged_in_to_trunk, TASK-Bugs5690_3913_RemoteCMPI-merged_in_from_branch, TASK-Bugs5690_3913_RemoteCMPI-branch, TASK-Bug2102_RCMPIWindows-root, TASK-Bug2102_RCMPIWindows-merged_out_to_branch, TASK-Bug2102_RCMPIWindows-merged_out_from_trunk, TASK-Bug2102_RCMPIWindows-merged_in_to_trunk, TASK-Bug2102_RCMPIWindows-merged_in_from_branch, TASK-Bug2102_RCMPIWindows-branch, TASK-Bug2021_RemoteCMPIonWindows-root, TASK-Bug2021_RemoteCMPIonWindows-merged_out_to_branch, TASK-Bug2021_RemoteCMPIonWindows-merged_out_from_trunk, TASK-Bug2021_RemoteCMPIonWindows-merged_in_to_trunk, TASK-Bug2021_RemoteCMPIonWindows-merged_in_from_branch, TASK-Bug2021_RemoteCMPIonWindows-branch, TASK-Bug2021_RCMPIonWindows-root, TASK-Bug2021_RCMPIonWindows-merged_out_to_branch, TASK-Bug2021_RCMPIonWindows-merged_out_from_trunk, TASK-Bug2021_RCMPIonWindows-merged_in_to_trunk, TASK-Bug2021_RCMPIonWindows-merged_in_from_branch, TASK-Bug2021_RCMPIonWindows-branch, TASK-BUG7240-root, TASK-BUG7240-branch, TASK-BUG4011_WinLocalConnect-root, TASK-BUG4011_WinLocalConnect-merged_out_to_branch, TASK-BUG4011_WinLocalConnect-merged_out_from_trunk, TASK-BUG4011_WinLocalConnect-merged_in_to_trunk, TASK-BUG4011_WinLocalConnect-merged_in_from_branch, TASK-BUG4011_WinLocalConnect-branch-New, TASK-BUG4011_WinLocalConnect-branch, RELEASE_2_6_3-RC2, RELEASE_2_6_3-RC1, RELEASE_2_6_3, RELEASE_2_6_2-RC1, RELEASE_2_6_2, RELEASE_2_6_1-RC1, RELEASE_2_6_1, RELEASE_2_6_0-RC1, RELEASE_2_6_0-FC, RELEASE_2_6_0, RELEASE_2_6-root, RELEASE_2_6-branch-clean, RELEASE_2_6-branch, RELEASE_2_5_5-RC2, RELEASE_2_5_5-RC1, RELEASE_2_5_5, RELEASE_2_5_4-RC2, RELEASE_2_5_4-RC1, RELEASE_2_5_4, RELEASE_2_5_3-RC1, RELEASE_2_5_3, RELEASE_2_5_2-RC1, RELEASE_2_5_2, RELEASE_2_5_1-RC1, RELEASE_2_5_1, RELEASE_2_5-root, RELEASE_2_5-branch, PEP286_PRIVILEGE_SEPARATION_ROOT, PEP286_PRIVILEGE_SEPARATION_CODE_FREEZE, PEP286_PRIVILEGE_SEPARATION_BRANCH, PEP286_PRIVILEGE_SEPARATION_1
Changes since 1.17: +3 -1 lines
BUG#: 4691
TITLE: Update Licenses to 2006

DESCRIPTION: Updates most of the licenses to 2006. The slp_client directories are excluded for the moment pending discussion. This change has passed unit and system tests.  Note that this changes just about EVERY file in Pegasus.

//%2006////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; Symantec Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Authors: David Rosckes (rosckes@us.ibm.com)
//          Bert Rivero (hurivero@us.ibm.com)
//          Chuck Carmack (carmack@us.ibm.com)
//          Brian Lucier (lucier@us.ibm.com)
//
// Modified By:
//          David Dillard, VERITAS Software Corp.
//              (david.dillard@veritas.com)
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/CQL/CQLUtilities.h>

// Query includes
#include <Pegasus/Query/QueryCommon/QueryException.h>

// Pegasus Common includes
#include <Pegasus/Common/Tracer.h>

// standard includes
#include <errno.h>

// symbol defines
#define PEGASUS_SINT64_MIN (PEGASUS_SINT64_LITERAL(0x8000000000000000))
#define PEGASUS_UINT64_MAX PEGASUS_UINT64_LITERAL(0xFFFFFFFFFFFFFFFF)

// required for the windows compile
#ifndef _MSC_VER
#define _MSC_VER 0
#endif

PEGASUS_NAMESPACE_BEGIN

inline Uint8 _CQLUtilities_hexCharToNumeric(Char16 c)
{
    Uint8 n;

    if (isdigit(c))
        n = (c - '0');
    else if (isupper(c))
        n = (c - 'A' + 10);
    else // if (islower(c))
        n = (c - 'a' + 10);

    return n;
}

Uint64 CQLUtilities::stringToUint64(const String &stringNum)
{
  PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToUint64()");

  Uint64 x = 0;
  const Char16* p = stringNum.getChar16Data();
  const Char16* pStart = p;

  if (String::equal(stringNum, String::EMPTY))
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Uint64"), String("empty"));
    throw CQLRuntimeException(mload);    
  }
  
  if (!p)
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Uint64"), String("NULL"));
    throw CQLRuntimeException(mload);    
  }

  // If the string is a real number, use stringToReal, then convert to a Uint64
  if (isReal(stringNum))
  {
    // Note:  the cast will rip off any non-whole number precision.   CQL spec
    // is silent on whether to round up, round down, throw an error, or allow
    // the platform to round as it sees fit.  We chose the latter for now.
    return (Uint64) stringToReal64(stringNum);
  }

  // There cannot be a negative '-' sign
  if (*p == '-')
  {
     MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NEG"),
                              String("Error converting string to $0.  String '$1' cannot begin with '-'."),
                              String("Uint64"),
                              stringNum);
    throw CQLRuntimeException(mload);    
  }
  if (*p == '+')
    p++;  // skip over the positive sign

  if (!((*p >= '0') && (*p <= '9')))
  {
     MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NUM_FORMAT"),
                              String("Error converting string to $0.  String '$1' is badly formed."),
                              String("Uint64"),
                              stringNum);
    throw CQLRuntimeException(mload);    
  }

  // if hexidecimal
  if ( (*p == '0') && ((p[1] == 'x') || (p[1] == 'X')) )
  {
    // Convert a hexadecimal string

    // Skip over the "0x"
    p+=2;

    // At least one hexadecimal digit is required
    if (!*p)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_FORMAT"),
                               String("Error converting string to $0.  String '$1' needs a hexadecimal digit character following '0x'"),
                               String("Uint64"),
                               stringNum);
      throw CQLRuntimeException(mload);    
    }

    // Add on each digit, checking for overflow errors
    while (isascii(*p) && isxdigit(*p))
    {
      // Make sure we won't overflow when we multiply by 16
      if (x > PEGASUS_UINT64_MAX/16)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x << 4;

      // We can't overflow when we add the next digit
      Uint64 newDigit = Uint64(_CQLUtilities_hexCharToNumeric(*p++));
      if (PEGASUS_UINT64_MAX - x < newDigit)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                                  stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x + newDigit;
    }

    // If we found a non-hexadecimal digit, report an error
    if (*p)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_CHAR"),
                               String("Error converting string to $0.  Character '$1' in string '$2' is not a hexidecimal digit."),
                               String("Uint64"),
                             String(p, 1), stringNum);
      throw CQLRuntimeException(mload);    
    }

    // return value from the hex string
    PEG_METHOD_EXIT();
    return x;
  }  // end if hexidecimal     

  // if binary
  Uint32 endString = stringNum.size() - 1;
  if ( (pStart[endString] == 'b') || (pStart[endString] == 'B') )
  {
    // Add on each digit, checking for overflow errors
    while ((*p == '0') || (*p == '1'))
    {
      // Make sure we won't overflow when we multiply by 2
      if (x > PEGASUS_UINT64_MAX/2)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x << 1;

      // We can't overflow when we add the next digit
      Uint64 newDigit = 0;
      if (*p++ == '1')
        newDigit = 1;
      if (PEGASUS_UINT64_MAX - x < newDigit)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x + newDigit;
    }

    // If we found a non-binary digit before the terminating 'b', then report an error
    if (*p && (p-pStart < (Sint32)endString || (*p != 'b' && *p != 'B')))
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_BIN_CHAR"),
                               String("Error converting string to $0.  Character '$1' in string '$2' is not a binary digit."),
                               String("Uint64"),
                               String(p, 1), stringNum);
      throw CQLRuntimeException(mload);    
    }

    // return value from the binary string
    PEG_METHOD_EXIT();
    return x;      
  } // end if binary


  // Expect a positive decimal digit:

  // Add on each digit, checking for overflow errors
  while ((*p >= '0') && (*p <= '9'))
  {
    // Make sure we won't overflow when we multiply by 10
    if (x > PEGASUS_UINT64_MAX/10)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                               stringNum);
      throw CQLRuntimeException(mload);    
    }
    x = 10 * x;

    // Make sure we won't overflow when we add the next digit
    Uint64 newDigit = (*p++ - '0');
    if (PEGASUS_UINT64_MAX - x < newDigit)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Uint64"),
                                stringNum);
      throw CQLRuntimeException(mload);    
    }

    x = x + newDigit;
  }

  // If we found a non-decimal digit, report an error
  if (*p)
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
                             String("Error converting string to $0.  Character '$1' in string '$2' is not a decimal digit."),
                             String("Uint64"),
                             String(p, 1), stringNum);
    throw CQLRuntimeException(mload);    
  }

  // return the value for the decimal string
  PEG_METHOD_EXIT();
  return x;
}

Sint64 CQLUtilities::stringToSint64(const String &stringNum)
{
  PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToSint64()");
  
  Sint64 x = 0;
  Boolean invert = false;
  const Char16* p = stringNum.getChar16Data();
  const Char16* pStart = p;

  if (String::equal(stringNum, String::EMPTY))
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Sint64"), String("empty"));
    throw CQLRuntimeException(mload);    
  }
  
  if (!p)
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Sint64"), String("NULL"));
    throw CQLRuntimeException(mload);    
  }

  // If the string is a real number, use stringToReal, then convert to a Sint64
  if (isReal(stringNum))
  {
    // Note:  the cast will rip off any non-whole number precision.   CQL spec
    // is silent on whether to round up, round down, throw an error, or allow
    // the platform to round as it sees fit.  We chose the latter for now.
    return (Sint64) stringToReal64(stringNum);
  }
  
  // skip over the sign if there is one
  if (*p == '-')
  {
    invert = true;
    p++;
  }
  if (*p == '+')
    p++;

  if (!((*p >= '0') && (*p <= '9')))
  {
     MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_NUM_FORMAT"),
                              String("Error converting string to $0.  String '$1' is badly formed."),
                              String("Uint64"),
                              stringNum);
    throw CQLRuntimeException(mload);    
  }

  // ********************
  // Build the Sint64 as a negative number, regardless of the
  // eventual sign (negative numbers can be bigger than positive ones)
  // ********************
  
  // if hexidecimal
  if ( (*p == '0') && ((p[1] == 'x') || (p[1] == 'X')) )
  {
    // Convert a hexadecimal string

    // Skip over the "0x"
    p+=2;

    // At least one hexidecimal digit is required
    if (!*p)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_FORMAT"),
                               String("Error converting string to $0.  String '$1' needs a hexadecimal digit character following '0x'."),
                               String("Sint64"),
                               stringNum);
      throw CQLRuntimeException(mload);    
    }

    // Add on each digit, checking for overflow errors
    while (isascii(*p) && isxdigit(*p))
    {
      // Make sure we won't overflow when we multiply by 16
      if (x < PEGASUS_SINT64_MIN/16)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x << 4;

      // We can't overflow when we add the next digit
      Sint64 newDigit = Sint64(_CQLUtilities_hexCharToNumeric(*p++));
      if (PEGASUS_SINT64_MIN - x > -newDigit)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x - newDigit;
    }

    // If we found a non-hexidecimal digit, report an error
    if (*p)
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_HEX_CHAR"),
                               String("Error converting string to $0.  Character '$1' in string '$2' is not a hexidecimal digit."),
                               String("Sint64"),
                             String(p, 1), stringNum);
      throw CQLRuntimeException(mload);    
    }

    // Return the integer to positive, if necessary, checking for an
    // overflow error
    if (!invert)
    {
      if (x == PEGASUS_SINT64_MIN)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }
      x = -x;
    }
    
    // return value from the hex string
    PEG_METHOD_EXIT();
    return x;
  }  // end if hexidecimal     

  // if binary
  Uint32 endString = stringNum.size() - 1;
  if ( (pStart[endString] == 'b') || (pStart[endString] == 'B') )
  {
    // Add on each digit, checking for overflow errors
    while ((*p == '0') || (*p == '1'))
    {
      // Make sure we won't overflow when we multiply by 2
      if (x < PEGASUS_SINT64_MIN/2)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                  stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x << 1;

      // We can't overflow when we add the next digit
      Sint64 newDigit = 0;
      if (*p++ == '1')
        newDigit = 1;
      if (PEGASUS_SINT64_MIN - x > -newDigit)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }

      x = x - newDigit;
    }

    // If we found a non-binary digit before the terminating 'b', then report an error
    if (*p && (p-pStart < (Sint32)endString || (*p != 'b' && *p != 'B')))
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_BIN_CHAR"),
                               String("Error converting string to $0.  Character '$1' in string '$2' is not a binary digit."),
                               String("Sint64"),
                               String(p, 1), stringNum);
      throw CQLRuntimeException(mload);    
    }

    // Return the integer to positive, if necessary, checking for an
    // overflow error
    if (!invert)
    {
      if (x == PEGASUS_SINT64_MIN)
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
      }
      x = -x;
    }
    
    // return value from the binary string
    PEG_METHOD_EXIT();
    return x;      
  }  // end if binary

  // Expect a positive decimal digit:

  // Add on each digit, checking for overflow errors
  while ((*p >= '0') && (*p <= '9'))
  {
    // Make sure we won't overflow when we multiply by 10
    if (x < PEGASUS_SINT64_MIN/10)
    {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
    }
    x = 10 * x;

    // Make sure we won't overflow when we add the next digit
    Sint64 newDigit = (*p++ - '0');
    if (PEGASUS_SINT64_MIN - x > -newDigit)
    {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
    }

    x = x - newDigit;
  }

  // If we found a non-decimal digit, report an error
  if (*p)
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
                             String("Error converting string to $0.  Character '$1' in string '$2' is not a decimal digit."),
                             String("Sint64"),
                             String(p, 1), stringNum);
    throw CQLRuntimeException(mload);    
  }

  // Return the integer to positive, if necessary, checking for an
  // overflow error
  if (!invert)
  {
    if (x == PEGASUS_SINT64_MIN)
    {
        MessageLoaderParms mload(String("CQL.CQLUtilities.OVERFLOW"),
                                 String("Error converting string to $0.  String '$1' caused an overflow."),
                                 String("Sint64"),
                                 stringNum);
        throw CQLRuntimeException(mload);    
    }
    x = -x;
  }

  // return the value for the decimal string
  PEG_METHOD_EXIT();
  return x;  
}

Real64 CQLUtilities::stringToReal64(const String &stringNum)
{
  PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToReal64()");
  
  Real64 x = 0;
  const Char16* p = stringNum.getChar16Data();
  Boolean neg = false;
  const Char16* pStart = p;

  if (String::equal(stringNum, String::EMPTY))
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Real64"), String("empty"));
    throw CQLRuntimeException(mload);    
  }
  
  if (!p)
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.EMPTY_STRING"),
                             String("Error converting string to $0.  String cannot be $1."),
                             String("Real64"), String("NULL"));
    throw CQLRuntimeException(mload);    
  }

  
  // Skip optional sign:

  if (*p == '+')
    p++;
  
  if (*p  == '-')
  {
    neg = true;
    p++;
  };
  
  // Check if it it is a binary or hex integer
  Uint32 endString = stringNum.size() - 1;
  if ((*p == '0' && (p[1] == 'x' || p[1] == 'X')) ||  // hex OR
      pStart[endString] == 'b' || pStart[endString] == 'B')  // binary
  {
    if (neg)
      x = stringToSint64(stringNum);
    else

// Check if the complier is MSVC 6, which does not support the conversion operator from Uint64 to Real64      
#if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) && (_MSC_VER < 1300)
    {
      Uint64 num = stringToUint64(stringNum);
      Sint64 half = num / 2;
      x = half;
      x += half;
      if (num % 2)  // if odd, then add the lost remainder
        x += 1;
    }
#else
      x = stringToUint64(stringNum);
#endif    
    PEG_METHOD_EXIT();
    return x;
  }  
  
  // Skip optional first set of digits:

  while ((*p >= '0') && (*p <= '9'))
    p++;

  // Test if optional dot is there
  if (*p++ == '.')
  {
    // One or more digits required:
    if (!((*p >= '0') && (*p <= '9')))
    {
      MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_CHAR_POST_DOT"),
                               String("Error converting string to Real64.  String '$0' must have a digit character following the decimal point."),
                               stringNum);
      throw CQLRuntimeException(mload);    
    }
    p++;

    while ((*p >= '0') && (*p <= '9'))
      p++;

    // If there is an exponent now:
    if (*p)
    {
      // Test exponent:

      if (*p != 'e' && *p != 'E')
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_REAL_CHAR"),
                                 String("Error converting string to $0.  Character '$1' in string '$2` is invalid."),
                                 String("Real64"),
                                 String(p, 1), stringNum);
        throw CQLRuntimeException(mload);    
      }
      p++;

      // Skip optional sign:

      if (*p == '+' || *p  == '-')
        p++;

      // One or more digits required:
      if (!((*p >= '0') && (*p <= '9')))
      {
        MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_REAL_EXP"),
                                 String("Error converting string to Real64.  String '$0' has a badly formed exponent.  Character '$1' is invalid."),
                                 stringNum, String(p, 1));
        throw CQLRuntimeException(mload);    
      }
      p++;

      while ((*p >= '0') && (*p <= '9'))
        p++;
    }
  } // end-if optional decimal point
  if (*p && p - pStart <= (Sint32) stringNum.size())
  {
  //  printf("This is char # %d\n", p - pStart);
    MessageLoaderParms mload(String("CQL.CQLUtilities.INVALID_DECIMAL_CHAR"),
                             String("Error converting string to $0.  Character '$1' in string '$2' is not a decimal digit."),
                             String("Real64"),
                             String(p-1, 1), stringNum);
    throw CQLRuntimeException(mload);    
  }
  //
  // Do the conversion
  //
  char* end;
  errno = 0;
  CString temp = stringNum.getCString();
  x = strtod((const char *) temp, &end);
  if (*end || (errno == ERANGE))
  {
    MessageLoaderParms mload(String("CQL.CQLUtilities.CONVERSION_REAL_ERROR"),
                             String("String '$0' was unable to be converted to a Real64.  It could be out of range."),
                             stringNum);
    throw CQLRuntimeException(mload);    
  }
  PEG_METHOD_EXIT();
//  printf("String %s = %.16e\n", (const char *)stringNum.getCString(), x);
  return x;
}

String CQLUtilities::formatRealStringExponent(const String &realString)
{
  String newString(realString);
  Uint32 expIndex = PEG_NOT_FOUND;
  Uint32 index = newString.size() - 1;
  
  expIndex = newString.find('E');
  if (expIndex == PEG_NOT_FOUND)
    expIndex = newString.find('e');

  if (expIndex == PEG_NOT_FOUND)
    return newString;  // no exponent symbol, so just return

  // format the exponent
  index = expIndex + 1;  // start index at next character
  if (newString[index] == '+')
    newString.remove(index, 1);  // remove the '+' symbol

  if (newString[index] == '-')
    index++;   // skip the '-' exponent sign

  while (newString[index] == '0' && index < newString.size())
  {
    newString.remove(index, 1);
  }

  // If only an 'e' is left (only 0's behind it) then strip the 'e'
  if (index >= newString.size())
    newString.remove(expIndex, 1);

  return newString;
}

Boolean CQLUtilities::isReal(const String &numString)
{
  // If there is a decimal point, we consider it to be a real.
  if (numString.find('.') == PEG_NOT_FOUND)
    return false;
  return true;
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2