li_string.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:8k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /* li_string, locale independant conversions */
  2. /****************License************************************************
  3.  * Vocalocity OpenVXI
  4.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *  
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  19.  * registered trademarks of Vocalocity, Inc. 
  20.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  21.  * by Vocalocity.
  22.  ***********************************************************************/
  23. /* -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  24.  */
  25. #include <math.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <wctype.h>
  29. #include <wchar.h>
  30. #include <string.h>
  31. #include <float.h>
  32. #include "SWIstring.h"
  33. const int    MAX_PRECISION = 6;
  34. const int    precision_multiplier = 1000000; /* 10^6 */
  35. const double VIRTUAL_ZERO = pow(10, -MAX_PRECISION);
  36. const double TOO_BIG      = pow(10, MAX_PRECISION) - 1;
  37. /*=========================================================================
  38. ** SWIatof(string) -- Converts character string to double
  39. **
  40. ** Arguments:
  41. **           string -- string to be converted to double 
  42. **
  43. ** Returns:  double representation of value in wstring
  44. **
  45. ** Description:
  46. **          Ignores leading whitespace in string of this form:
  47. **          [(+|-)[0123456789]+(.[0123456789])]
  48. **          charcater.  Converts the integer parts and the
  49. **          decimal part separately, adding them together at the
  50. **          end and applying the sign
  51. ** 
  52. **=========================================================================
  53. */
  54. double SWIatof(const char *str)
  55. {
  56.    double result = 0.0;
  57.    int negative = 0;
  58.    char *cp = NULL;
  59.    // NOTE:  unicode values for white space, '+', and '-'
  60.    // are unambiguous
  61.    // Skip over whitespace
  62.    while (SWIchar_isspace(*str) )
  63.      str++;
  64.    // Handle sign
  65.    if (*str == '+')
  66.      *str++;
  67.    else if (*str == '-')
  68.    {
  69.      negative = 1;
  70.      *str++;
  71.    }
  72.    // NOTE: This is very clever code. It intentionally calls the
  73.    // locale dependant C library string to double function, strtod( ),
  74.    // in an attempt for very efficient conversion with locale
  75.    // dependant fraction delimiters (, for some locales)
  76.    // supported. But then it goes on to ensure the SWI cannonical
  77.    // fraction delimiter (.) is supported as well by doing a secondary
  78.    // conversion where required.
  79.    result = strtod(str, &cp);   // integer part
  80.    if ( (cp != 0) && (*cp == '.'))  // has fraction?
  81.    {
  82.      cp++;  // skip over radix point
  83.      int decDigits = strspn(cp, "0123456789");
  84.      if (decDigits > 0) /* avoid divide by zero */
  85.        result += strtod(cp, &cp) / pow(10, decDigits); // add fraction
  86.    }
  87.    // Apply the sign 
  88.    if (negative)
  89.       result = -result;
  90.    return(result);
  91. }
  92. /*=======================================================================
  93. SWIatofloat -- as above but converts a string to a float
  94. **=======================================================================
  95. */
  96. float SWIatofloat(const char *str)
  97. {
  98.   double d = SWIatof(str);
  99.   return( (float)d );
  100. }
  101. /*========================================================================
  102. ** SWIdtowcs -- converts floating point number to a string
  103. **
  104. ** Arguments:
  105. **              double toConvert -- number to be converted
  106. **              wchar_t* result  -- container for wide char representation
  107. **              int len          -- size in characters of output buffer
  108. **
  109. ** Returns:     void
  110. **
  111. ** Description:
  112. **              Notes the sign of the number, using only its absolute
  113. **              value.  Converts the integer and fractional parts
  114. **              separately, combining them later, stripping extraneous
  115. **              trailing zeros, and applying the sign character.
  116. **
  117. ** NOTE:        The conversion fails if the number of digits in the
  118. **              integer part exceeds MAX_PRECISION - 1 (there must
  119. **              be at least a single digit in the fraction.)
  120. **
  121. **========================================================================
  122. */
  123. SWIcharResult SWIdtowcs(const double toConvert, 
  124.                              wchar_t *result,
  125.                              int len)
  126. {
  127.   SWIcharResult rc;
  128.   int integerPart = (int) toConvert;
  129.   int slen, fractionPart;
  130.   double fraction = 0.0;
  131.   fractionPart = (int) ( (toConvert-integerPart)*((double)precision_multiplier)+0.5 );
  132.   if ( fractionPart ) {
  133.     fraction = fractionPart/(double) precision_multiplier;
  134.     int overflow = (int) fraction;
  135.     if ( overflow ) {
  136.       integerPart += overflow;
  137.       fraction -= overflow;
  138.     }
  139.   }
  140.   rc = SWIitowcs(integerPart, result, len);
  141.   if ( rc != SWIchar_SUCCESS ) return rc;
  142.  
  143.   slen = wcslen(result);
  144.   if ( slen+2+MAX_PRECISION > len ) 
  145.     return SWIchar_BUFFER_OVERFLOW;
  146.   if ( fractionPart ) {
  147.     int i;
  148.     wchar_t *p = result+slen;
  149.     *p++ = '.';
  150.     for ( i = 0; i < MAX_PRECISION; ++i ) {
  151.       int nextDigit;
  152.       fraction *= 10;
  153.       nextDigit = (int) (fraction+0.0000000001);
  154.       *p++ = (char)nextDigit+'0';
  155.       fraction -= nextDigit;
  156.     }
  157.     *p = 0;
  158.     // Remove extraneous zeros
  159.     while (  (p[-1] == L'0') && ( p[-2] != L'.'))
  160.       *--p = 0;
  161.   }
  162.   return SWIchar_SUCCESS;
  163. }
  164. #if 0
  165. // old code!!!
  166. {
  167.   wchar_t integerString[SWIchar_MAXSTRLEN];
  168.   wchar_t fractionString[SWIchar_MAXSTRLEN] = {L'.', L'0'};
  169.   double d = toConvert;
  170.   int integerPart = (int)d;  // overflow caught by TOO_BIG check below.
  171.  
  172.   SWIcharResult status = (d > TOO_BIG) ? SWIchar_BUFFER_OVERFLOW : SWIitowcs(integerPart, integerString, MAX_PRECISION-2);
  173.   if (status == SWIchar_SUCCESS)
  174.   {
  175.     d -= integerPart;  // fraction remaining
  176.     if (d < 0)         // fraction should be positive 
  177.       d = -d;
  178.     if ( (d > 0.0) && (d > VIRTUAL_ZERO) ) // has fraction?
  179.     {
  180.       int decimalPlaces = MAX_PRECISION - wcslen(integerString);
  181.       if (decimalPlaces >= 1)  // least one digit after the decimal
  182.       {
  183.         wchar_t* fp = &fractionString[1];  // after decimal.
  184.         while (d < 0.1)  // account for leading zeros.
  185.         {
  186.           *fp++ = L'0';
  187.           d *= 10.0;
  188.           decimalPlaces--;
  189.         }
  190.         int integerFract = (int)((d * pow(10, decimalPlaces)) + 0.5);
  191.         status = SWIitowcs(integerFract, fp, SWIchar_MAXSTRLEN);
  192.         if (status == SWIchar_SUCCESS)
  193.         {
  194.           // Remove extraneous zeros
  195.           wchar_t* wp = fractionString + wcslen(fractionString) - 1;
  196.           while (  (*wp == L'0') && ( *(wp-1) != L'.'))
  197.             *wp-- = L'';
  198.         }
  199.       }
  200.       else // too small for handle fraction
  201.         status = SWIchar_BUFFER_OVERFLOW;
  202.     }
  203.     // Combine the integer and fractional parts
  204.     if (status == SWIchar_SUCCESS)
  205.     {
  206.       if (wcslen(integerString)+wcslen(fractionString)+1 <= (unsigned int)len)
  207.       {
  208.         wcscpy(result, integerString);
  209.         wcscat(result, fractionString);
  210.       }
  211.       else
  212.         status = SWIchar_BUFFER_OVERFLOW;
  213.     }
  214.   }
  215.   return(status);
  216. }
  217. #endif
  218. /*=========================================================================
  219. ** SWIdtostr -- as above but converts from double to character string
  220. **=========================================================================
  221. */
  222. SWIcharResult SWIdtostr(const double toConvert, char *str, int len)
  223. {
  224.   wchar_t wideArray[SWIchar_MAXSTRLEN];
  225.   SWIcharResult status = SWIdtowcs(toConvert, wideArray, len);
  226.   if (status == SWIchar_SUCCESS)
  227.   {
  228.     const wchar_t* wp = wideArray;
  229.     status = SWIwcstostr(wp, str, len); 
  230.   }
  231.   return(status);
  232. }