//================================================================================================== // B + + L o w - L e v e l S t r i n g Interface // By Bruno Bachelet //================================================================================================== // Copyright (c) 1999-2016 // Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net // // This file is part of the B++ Library. This library is free software; you can redistribute it // and/or modify it under the terms of the GNU Library General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your option) any later // version. // // This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU Library General Public License for more details (http://www.gnu.org).
/*DESCRIPTION*/ /* Provides basic functions to manipulate strings. They are useful when the standard <CODE>sprintf</CODE> and <CODE>sscanf</CODE> functions are not working correctly (for instance, when loading Cygwin's dynamic library inside a Java environment). */
// Guardian //-------------------------------------------------------------------------------------- #ifndef _BPP_LOW_STRING_ #define _BPP_LOW_STRING_
// Headers //--------------------------------------------------------------------------------------- #include <cctype> #include <cfloat> #include <cmath>
namespace bpp { namespace low {
// Macrocommands //--------------------------------------------------------------------------------- #define BUFFER_SIZE 64
// Types & Classes //------------------------------------------------------------------------------- typedef BOOLEAN_TYPE tyBoolean; typedef BYTE_TYPE tyByte; typedef CARDINAL_TYPE tyCardinal; typedef CHARACTER_TYPE tyCharacter; typedef INTEGER_TYPE tyInteger; typedef void * tyPointer; typedef REAL_TYPE tyReal; typedef tyCharacter * tyString; typedef const tyCharacter * tcString;
template <int prDummy> class clString;
/*TYPE*/ /* Represents an instantiation of the parameterized class <CODE>clString</CODE>. */ typedef clString<0> string;
// S t r i n g Interface //------------------------------------------------------------------------ /*CLASS string */ /* Provides basic functions to manipulate strings. */ template <int prDummy> class clString { //------------------------------------------------------------------------------------------Private protected: static tcString atHexaCodeS; //-------------------------------------------------------------------------------------------Public public: static void concatenate(tcString,tcString); public: static void copy(tcString,tcString); public: static tyCardinal length(tcString);
public: static tcString toString(tyString,tyCardinal); public: static tcString toString(tyString,tyInteger); public: static tcString toString(tyString,tyPointer); public: static tcString toString(tyString,tyReal);
public: static tcString toCardinal(tcString,tyCardinal &); public: static tcString toInteger(tcString,tyInteger &); public: static tcString toPointer(tcString,tyPointer &); public: static tcString toReal(tcString,tyReal &); };
// S t r i n g Implementation //-------------------------------------------------------------------
template <int prDummy> tcString clString<prDummy>::atHexaCodeS = "0123456789abcdef";
//---------------------------------------------------------------------------------------Concatenate /*METHOD string */ /* Concatenates two strings. There must be enough space in the first string to copy the second one. */ template <int prDummy> void clString<prDummy>::concatenate(tcString agTarget,tcString agSource) { tyString lcTarget = tyString(agTarget);
while (*lcTarget!=0) ++lcTarget; copy(lcTarget,agSource); } //----------------------------------------------------------------------------------------------Copy /*METHOD string */ /* Copies a string. There must be enough space in the first string to copy the second one. */ template <int prDummy> void clString<prDummy>::copy(tcString agTarget,tcString agSource) { tyString lcTarget = tyString(agTarget);
if (agSource!=0) while (*agSource!=0) *(lcTarget++)=*(agSource++); *lcTarget=0; } //--------------------------------------------------------------------------------------------Length /*METHOD string */ /* Returns the number of characters in a string. */ template <int prDummy> tyCardinal clString<prDummy>::length(tcString agString) { tyCardinal lcLength = 0;
if (agString!=0) while (agString[lcLength]!=0) ++lcLength; return (lcLength); }
//-------------------------------------------------------------------------------ToString (Cardinal) /*METHOD string */ /* Converts a cardinal number into a string. There must be enough space in the string given as argument to store the result. */ template <int prDummy> tcString clString<prDummy>::toString(tyString agString,tyCardinal agNumber) { tyCharacter lcBuffer[BUFFER_SIZE];
tyCardinal lcCounter = 0; tyString lcString = agString;
do { lcBuffer[lcCounter++]=tyCharacter(tyCharacter('0')+tyCharacter(agNumber%10)); agNumber/=10; } while (agNumber>0);
while (lcCounter>0) *(lcString++)=lcBuffer[--lcCounter]; *lcString=0;
return (agString); } //--------------------------------------------------------------------------------ToString (Integer) /*METHOD string */ /* Converts an integer number into a string. There must be enough space in the string given as argument to store the result. */ template <int prDummy> tcString clString<prDummy>::toString(tyString agString,tyInteger agNumber) { tyCharacter lcBuffer[BUFFER_SIZE];
tyCardinal lcCounter = 0; tyInteger lcModSign = (agNumber<0 ? (-1)%2 : 1); tyString lcString = agString;
if (agNumber<0) *(lcString++)='-';
do { lcBuffer[lcCounter++]=tyCharacter(tyCharacter('0')+tyCharacter(lcModSign*(agNumber%10))); agNumber/=10; } while (agNumber!=0);
while (lcCounter>0) *(lcString++)=lcBuffer[--lcCounter]; *lcString=0;
return (agString); } //--------------------------------------------------------------------------------ToString (Pointer) /*METHOD string */ /* Converts a pointer into a string. There must be enough space in the string given as argument to store the result. */ template <int prDummy> tcString clString<prDummy>::toString(tyString agString,tyPointer agNumber) { tyCardinal lcCounter = sizeof(tyPointer); tyString lcString = agString; tyByte * lcNumber = (tyByte *)(&agNumber);
*(lcString++)='0'; *(lcString++)='x';
while (lcCounter>0) { *(lcString++)=atHexaCodeS[lcNumber[--lcCounter]/16]; *(lcString++)=atHexaCodeS[lcNumber[lcCounter]%16]; }
*lcString=0;
return (agString); } //-----------------------------------------------------------------------------------ToString (Real) /*METHOD string */ /* Converts a real number into a string. There must be enough space in the string given as argument to store the result. */ template <int prDummy> tcString clString<prDummy>::toString(tyString agString,tyReal agNumber) { tyByte lcBuffer[BUFFER_SIZE]; tyCardinal lcComma; tyCardinal lcCounter; tyByte lcDigit; tyInteger lcExp; tyCharacter lcSign; tyCardinal lcLast; tyInteger lcLog;
tyReal lcDigits = 0.0; tyByte * lcNumber = lcBuffer; tyString lcString = agString;
// Sign // if (agNumber<0) { lcSign='-'; agNumber*=-1.0; } else lcSign='+';
// Logarithm // if (agNumber==0.0) lcLog=0; else lcLog=tyInteger(std::floor(std::log(agNumber)/std::log(10.0)));
if (lcLog<0) agNumber*=std::pow(tyReal(10.0),tyReal(-lcLog)); else if (lcLog>0) agNumber/=std::pow(tyReal(10.0),tyReal(lcLog));
// Digits // lcNumber[0]=0; lcCounter=0;
while (lcCounter<=REAL_DECIMAL_PRECISION) { lcDigit=tyByte(std::floor(agNumber-lcDigits)); lcDigits=10*(lcDigits+lcDigit); agNumber*=10.0; lcNumber[++lcCounter]=lcDigit; }
// Amount Carried // if (lcNumber[lcCounter]>=5) { lcDigit=1;
while (lcCounter>0 && lcDigit==1) { lcNumber[--lcCounter]+=lcDigit;
if (lcNumber[lcCounter]==10) { lcNumber[lcCounter]=0; lcDigit=1; } else lcDigit=0; } }
if (lcNumber[0]==1) ++lcLog; else ++lcNumber;
// String Generation // if (lcSign=='-') *(lcString++)='-';
if (lcLog>=0 && lcLog<6) { lcComma=tyCardinal(lcLog)+1; lcExp=0; } else if (lcLog<0 && lcLog>-5) { *(lcString++)='0'; *(lcString++)='.';
lcCounter=0; while (++lcCounter<tyCardinal(-lcLog)) *(lcString++)='0';
lcComma=0; lcExp=0; } else { lcComma=1; lcExp=lcLog; }
lcLast=REAL_DECIMAL_PRECISION; while (lcLast>1 && lcLast>lcComma && lcNumber[lcLast-1]==0) --lcLast;
lcCounter=0;
while (lcCounter<lcLast) { *(lcString++)=tyCharacter(tyCharacter('0')+tyCharacter(lcNumber[lcCounter])); if (lcCounter==lcComma-1 && lcCounter+1<lcLast) *(lcString++)='.'; ++lcCounter; }
if (lcExp!=0) { *(lcString++)='e'; if (lcExp>0) *(lcString++)='+'; toString(lcString,lcExp); } else *lcString=0;
return (agString); }
//----------------------------------------------------------------------------------------ToCardinal /*METHOD string */ /* Converts a string into a cardinal number. */ template <int prDummy> tcString clString<prDummy>::toCardinal(tcString agString,tyCardinal & agNumber) { tyBoolean lcError = false;
agNumber=0; if (agString==0) return (0);
while (*agString!=0 && isspace(*agString)) ++agString;
if (*agString==0) lcError=true; else if (*agString=='+') ++agString;
while (!lcError && *agString!=0 && !isspace(*agString)) { if (isdigit(*agString)) agNumber=10*agNumber+(*(agString++)-'0'); else lcError=true; }
if (lcError) { agString=0; agNumber=0; }
return (agString); } //-----------------------------------------------------------------------------------------ToInteger /*METHOD string */ /* Converts a string into an integer number. */ template <int prDummy> tcString clString<prDummy>::toInteger(tcString agString,tyInteger & agNumber) { tyBoolean lcError = false; tyInteger lcSign = 1;
agNumber=0; if (agString==0) return (0);
while (*agString!=0 && isspace(*agString)) ++agString;
if (*agString==0) lcError=true; else if (*agString=='+') ++agString; else if (*agString=='-') { lcSign=-1; ++agString; }
while (!lcError && *agString!=0 && !isspace(*agString)) { if (isdigit(*agString)) agNumber=10*agNumber+(*(agString++)-'0'); else lcError=true; }
agNumber*=lcSign;
if (lcError) { agString=0; agNumber=0; }
return (agString); } //-----------------------------------------------------------------------------------------ToPointer /*METHOD string */ /* Converts a string into a pointer. */ template <int prDummy> tcString clString<prDummy>::toPointer(tcString agString,tyPointer & agNumber) { tyCardinal lcCounter = sizeof(tyPointer)*2; tyBoolean lcError = false; tyByte * lcNumber = (tyByte *)(&agNumber);
tyByte lcDigit;
agNumber=0; if (agString==0) return (0);
while (*agString!=0 && isspace(*agString)) ++agString;
if (*agString!='0') lcError=true; else { if (*(++agString)!='x') lcError=true; else ++agString; }
while (!lcError && *agString!=0 && !isspace(*agString)) { if (isxdigit(*agString)) { if (islower(*agString)) lcDigit=tyByte(*agString-tyCharacter('a')+tyCharacter(10)); else if (isupper(*agString)) lcDigit=tyByte(*agString-tyCharacter('A')+tyCharacter(10)); else lcDigit=tyByte(tyCharacter(*agString)-tyCharacter('0'));
if (lcCounter>0) { --lcCounter; ++agString;
if (lcCounter%2==1) lcNumber[lcCounter/2]=tyByte(16*lcDigit); else lcNumber[lcCounter/2]+=lcDigit; } else lcError=true; } else lcError=true; }
if (lcCounter!=0) lcError=true;
if (lcError) { agString=0; agNumber=0; }
return (agString); } //--------------------------------------------------------------------------------------------ToReal /*METHOD string */ /* Converts a string into a real number. */ template <int prDummy> tcString clString<prDummy>::toReal(tcString agString,tyReal & agNumber) { tyBoolean lcDot = false; tyBoolean lcError = false; tyInteger lcExp = 0; tyCardinal lcLog = 0; tyInteger lcSign = 1;
agNumber=0; if (agString==0) return (0);
while (*agString!=0 && isspace(*agString)) ++agString;
if (*agString==0) lcError=true; else if (*agString=='+') ++agString; else if (*agString=='-') { lcSign=-1; ++agString; }
while (!lcError && *agString!=0 && !isspace(*agString)) { if (isdigit(*agString)) { agNumber=10.0*agNumber+(*(agString++)-'0'); if (lcDot) ++lcLog; } else if (*agString=='.') { lcDot=true; ++agString; } else if (*agString=='e' || *agString=='E') { agString=toInteger(++agString,lcExp); if (agString==0) lcError=true; } else lcError=true; }
if (lcError) { agString=0; agNumber=0.0; } else { if (lcLog>0) agNumber/=std::pow(tyReal(10.0),tyReal(lcLog));
if (lcExp>0) agNumber*=std::pow(tyReal(10.0),tyReal(lcExp)); else if (lcExp<0) agNumber/=std::pow(tyReal(10.0),tyReal(-lcExp));
agNumber*=lcSign; }
return (agString); }
// End //------------------------------------------------------------------------------------------- }} #undef BUFFER_SIZE #endif |
|