19
Oct
0

C++ – A custom String class – Basic, fast & portable

In this post I share a custom string class I developed 1 year ago.
This class does the minimum but it works well and it is very fast, I compare it with the std string.
Please, comments.

Source code

Here is the source code.

Header

#ifndef BSTRING_HPP
#define BSTRING_HPP

/**
* @author Berenger
* @version 0.5
* @date 4 novembre 2009
* @file BType.hpp
* @package Utils
* @brief Basic & fast string container
*
*/

class BString {
protected:
    char*   string; 	    /**< String Buffer*/
    int     lenght;		/**< String lenght*/
    int	    bufferLenght;	/**< Buffer lenght - as less string lenght*/

    static const char HexChars[];

    /** MAx lenght int a print version */
    static const int BCharMaxLenght;  		/**< BChar Max lenght in string format 		*/
    static const int BShortMaxLenght;  		/**< BShort Max lenght in string format 	*/
    static const int BIntMaxLenght; 		/**< BInt Max lenght in string format 		*/
    static const int BLongMaxLenght; 		/**< BLong Max lenght in string format 		*/
    static const int BLong64MaxLenght; 	        /**< BLong64 Max lenght in string format 	*/

    static const int BUCharMaxLenght; 		/**< BUChar Max lenght in string format 	*/
    static const int BUShortMaxLenght; 		/**< BUShort Max lenght in string format 	*/
    static const int BUIntMaxLenght; 		/**< BUInt Max lenght in string format 		*/
    static const int BULongMaxLenght; 		/**< BULong Max lenght in string format 	*/
    static const int BULong64MaxLenght; 	/**< BULong64 Max lenght in string format 	*/

    static const int BFloatMaxLenght; 		/**< BFloat Max lenght in string format 	*/
    static const int BDoubleMaxLenght;          /**< BDouble Max lenght in string format 	*/
    static const int BLDoubleMaxLenght; 	/**< BLDouble Max lenght in string format 	*/

    // Maximum value rounded 10 to convert faster to string

    static const int BChar10Max; 			/**< BChar Max lenght in string format 		*/
    static const int BShort10Max;			/**< BShort Max lenght in string format 	*/
    static const int BIntMax10;				/**< BInt Max lenght in string format 		*/
    static const int BLongMax10;			/**< BLong Max lenght in string format 		*/
    static const int BLong6410Max;			/**< BLong64 Max lenght in string format 	*/

    static const int BUChar10Max;			/**< BUChar Max lenght in string format 	*/
    static const int BUShort10Max;			/**< BUShort Max lenght in string format 	*/
    static const int BUInt10Max;		 	/**< BUInt Max lenght in string format 		*/
    static const int BULong10Max;		 	/**< BULong Max lenght in string format 	*/
    static const int BULong6410Max; 	                /**< BULong64 Max lenght in string format 	*/

    static const int BFloat10Max; 		        /**< BFloat Max lenght in string format 	*/
    static const int BDouble10Max;              	/**< BDouble Max lenght in string format 	*/
    static const int BLDouble10Max; 	                /**< BLDouble Max lenght in string format 	*/

public:
    /**
 * @brief Default Constructor
 */
    BString(){
        // Set every thing to zeros
       this->string = 0;
       this->lenght = 0;
       this->bufferLenght = 0;
    }

    /**
     * @brief Constructor with buffer size
     * @param inBufferLenght The buffer size
     * When you know approximatly the buffer you will use
     * this constructor is the more appropriate
     */
    explicit BString(int inBufferLenght){
        if(inBufferLenght > 0){ 					// buffer size > 0
           this->string = new char[inBufferLenght];	                // allocate buffer
           this->string[0] = '\0';					// set first char \0
        }
        else{
           this->string = 0;						// else NULL
        }

       this->bufferLenght = inBufferLenght;                             // Copy buffer lenght
       this->lenght = 0;						// str lenght = 0
    }

    /**
     * @brief Copy Constructor
     * @param inString The original string
     */
    BString(const BString& inString){
        if(inString.lenght){						// if original string is not empty
           this->lenght = inString.lenght;
           this->bufferLenght = inString.lenght + 1;
           this->string = new char[bufferLenght];                      //allocate buffer
            BString::Copy(inString.string,string); 			// copy and save size
        }
        else{
           this->string = 0;						// set to zeros
           this->lenght = 0;						//
           this->bufferLenght = 0;					//
        }
    }
    /**
     * @brief Copy Constructor with char*
     * @param inString The original string
     */
    explicit BString(const char* const inString){
        int inlenght;

        if(inString && (inlenght = BString::Strlen(inString))){	// if original string is not empty
           this->lenght = inlenght;
           this->bufferLenght = inlenght + 1;
           this->string = new char[bufferLenght];		//allocate buffer
            Copy(inString,string); 								// copy and save size
        }
        else{
           this->string = 0;									// set to zeros
           this->lenght = 0;									//
           this->bufferLenght = 0;								//
        }
    }
    /**
     * @brief Destructor
     */
    virtual ~BString(){
        if(string) delete(string);
    }

    /**
 * @brief String lenght
 * @return lenght
 */
    int getLenght() const{
        return this->lenght;
    }
    /**
 * @brief Clear string but keep buffer in memory
 */
    void clear(){
        if(string && this->lenght){
            this->string[0] = '\0';
        }
        this->lenght = 0;
    }
    /**
     * @brief Check if there is enough free space, if not
     * @brief allocate and copy string
     * @param in_requeriedSpace the space that is needed
     * @return true if space was allocate
     */
    bool allocateIfNeeded(const int in_requeriedSpace);
    /**
     * @brief Append with char*
     * @param inString The original string
     */
    BString& append(const char * const inString);
    /**
     * @brief Append with BString
     * @param inString The original string
     */
    BString& append(const BString& inString);
    /**
     * @brief Append with char
     * @param in_char The char
     */
    BString& append(const char in_char);
    /**
     * @brief Append with BString
     * @param inString The original string
     */
    BString operator+(const BString& inString) const;
    /**
     * @brief Append with BString
     * @param inString The original string
     */
    BString operator+(const char* const inString) const;
    /**
     * @brief Get a char from the string
     * @param in_index the char position
     * @return the char or BCharMax if index too large
     */
    char operator[](const int in_index) const;
    /**
     * @brief Set the string
     * @param inString the new string
     * @return the current string after modifying
     */
    BString& operator=(const BString & inString);
     /**
     * @brief Set the string
     * @param inString the new string
     * @return the current string after modifying
     */
    BString& operator=(const char* const inString);
    /**
     * @brief Test if 2 string are equals
     * @param inString the string to test
     * @return true if string are equal
     */
    bool operator==(const BString& inString) const;
    /**
     * @brief Test if 2 string are equals
     * @param inString the string to test
     * @return true if string are equal
     */
    bool operator==(const char* const inString) const;

    /**
     * @brief Test if 2 string are different
     * @param inString the string to test
     * @return true if string are different
     */
    bool operator!=(const BString& inString) const{
        return !((*this)==inString);
    }

    /**
     * @brief To get the buffer
     * @return the string buffer of char
     */
    const char * data() const{
        return this->string;
    }

    /**
     * @brief Count the lenght of a string
     * @param inString the string to test
     * @return the lenght
     * The method count until '\n' or '\0'
     */
    static int Strlen(const char* const inString);

    /**
     * @brief Count the lenght of a string
     * @param in_src the source
     * @param in_dest the destination
     * @return the lenght of the copy
     * The method copy until '\n' or '\0'
     */
    static int Copy(const char* const in_src, char* const in_dest);

    /**
     * @brief Add a string to another
     * @param inString the string to add
     * @return the string concat in in_string1
     */
    BString& operator+=(const BString& inString){
        append(inString);
        return *this;
    }

    /**
     * @brief Add a string to another
     * @param inString the string to add
     * @return the string concat in in_string1
     */
    BString& operator+=(const char* const inString){
        append(inString);
        return *this;
    }

    // ------------------------------------------------------------------- //
    // ------------------------  Convertion Function --------------------- //
    // ------------------------------------------------------------------- //
    /** @brief Append a value to the current string */
    BString& append(const short& in_value){
        if(in_value == 0 ) append('0');
        else stoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const unsigned short& in_value){
        if(in_value == 0u ) append('0');
        else ustoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const int& in_value){
        if(in_value == 0 ) append('0');
        else itoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const unsigned int& in_value){
        if(in_value == 0u ) append('0');
        else uitoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const long& in_value){
        if(in_value == 0 ) append('0');
        else litoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const unsigned long& in_value){
        if(in_value == 0u ) append('0');
        else ulitoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& appendHex(const int& in_value){
        if(in_value == 0 ) append("0x00");
        else ithex(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& appendHex(const unsigned int& in_value){
        if(in_value == 0u ) append("0x00");
        else uithex(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& appendHex(const long& in_value){
        if(in_value == 0 ) append("0x00");
        else ithex(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& appendHex(const unsigned long& in_value){
        if(in_value == 0u ) append("0x00");
        else ulthex(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const float& in_value){
        if(in_value < 0.0000001 && in_value > -0.0000001 ) append("0.0");
        else ftoa(in_value);
        return *this;
    }
    /** @brief Append a value to the current string */
    BString& append(const double& in_value){
        if(in_value < 0.0000001 && in_value > -0.0000001 ) append("0.0");
        else dtoa(in_value);
        return *this;
    }

private:
    // ------------------------------------------------------------------- //
    // ------------------------  ItoA functions      --------------------- //
    // ------------------------------------------------------------------- //
    /**
     * @brief Convert long to hex
     */
    void lthex(long val);
    /**
     * @brief Convert int to hex
     */
    void ithex(int val);
    /**
     * @brief Convert unsigned long to hex
     */
    void ulthex(unsigned long val);
    /**
     * @brief Convert unsigned int to hex
     */
    void uithex(unsigned int val);

    /**
     * @brief Convert int to char
     */
    void stoa (short num);

    /**
     * @brief Convert unsigned short to char
     */
    void ustoa (unsigned short num);

    /**
     * @brief Convert int to char
     */
    void itoa (int num);

    /**
     * @brief Convert unsigned int to char
     */
    void uitoa (unsigned int num);

    /**
     * @brief Convert int to char
     */
    void litoa (long num);

    /**
     * @brief Convert int to char
     */
    void ulitoa (unsigned long num);

    /**
     * @brief Convert int to char
     */
    void ftoa (float num);

    /**
     * @brief Convert int to char
     */
    void dtoa (double num);

};

/**
* @brief Test if 2 string are equals
* @param in_string1 the string to test
* @param in_string2 the string to test
* @return true if string are equal
*/
/*bool operator==(const BString& in_string1, const BString& in_string2);*/

/**
* @brief Create a string from two string by concatening
* @param in_string1 the string to start
* @param in_string2 the string to ebd
* @return the new string
*/
/*BString operator+(const BString& in_string1, const BString& in_string2);*/

#endif

Implementation

#include "BString.hpp"

const char BString::HexChars[] = {"0123456789ABCDEF"};

// Char Maximum Lenght

const int BString::BCharMaxLenght =  3;  		/**< BChar Max lenght in string format 		*/
const int BString::BShortMaxLenght =  6;  		/**< BShort Max lenght in string format 	*/
const int BString::BIntMaxLenght  = 11; 		/**< BInt Max lenght in string format 		*/
const int BString::BLongMaxLenght =  11; 		/**< BLong Max lenght in string format 		*/
const int BString::BLong64MaxLenght =  21; 	    /**< BLong64 Max lenght in string format 	*/

const int BString::BUCharMaxLenght =  3; 		/**< BUChar Max lenght in string format 	*/
const int BString::BUShortMaxLenght =  5; 		/**< BUShort Max lenght in string format 	*/
const int BString::BUIntMaxLenght  = 10; 		/**< BUInt Max lenght in string format 		*/
const int BString::BULongMaxLenght  = 10; 		/**< BULong Max lenght in string format 	*/
const int BString::BULong64MaxLenght  = 20; 	/**< BULong64 Max lenght in string format 	*/

const int BString::BFloatMaxLenght  = 15; 		/**< BFloat Max lenght in string format 	*/
const int BString::BDoubleMaxLenght  = 15; 	    /**< BDouble Max lenght in string format 	*/
const int BString::BLDoubleMaxLenght =  15; 	/**< BLDouble Max lenght in string format 	*/

// Maximum value rounded 10 to convert faster to string

const int BString::BChar10Max  = 2; 			/**< BChar Max lenght in string format 		*/
const int BString::BShort10Max  = 4;			/**< BShort Max lenght in string format 	*/
const int BString::BIntMax10 =  10;				/**< BInt Max lenght in string format 		*/
const int BString::BLongMax10 =  10;			/**< BLong Max lenght in string format 		*/
const int BString::BLong6410Max  = 18 ;			/**< BLong64 Max lenght in string format 	*/

const int BString::BUChar10Max  = 2;			/**< BUChar Max lenght in string format 	*/
const int BString::BUShort10Max =  4;			/**< BUShort Max lenght in string format 	*/
const int BString::BUInt10Max =  10;		 	/**< BUInt Max lenght in string format 		*/
const int BString::BULong10Max  = 10;		 	/**< BULong Max lenght in string format 	*/
const int BString::BULong6410Max =  20; 	    /**< BULong64 Max lenght in string format 	*/

const int BString::BFloat10Max  = 20; 		    /**< BFloat Max lenght in string format 	*/
const int BString::BDouble10Max =  20; 	        /**< BDouble Max lenght in string format 	*/
const int BString::BLDouble10Max =  20;     	/**< BLDouble Max lenght in string format 	*/

/**
* @breif Check buffer size
*/
bool BString::allocateIfNeeded(const int inRequeriedSpace){
        if( bufferLenght <= inRequeriedSpace + lenght ){		// If the buffer is too small
                bufferLenght = 2 * (lenght + inRequeriedSpace);	// calcul requierd buffer
                char * str = new char[bufferLenght];				// allocate buffer

                if(string){
                        BString::Copy(string , str);					// copy original string
                        delete(string);								// remove buffer
                }
                else{
                        str[0] = '\0';
                }
                string = str;
                return true;
        }
        return false;
}

/**
* @brief BString implementation
* @file BString.cpp
*/

BString& BString::append(const char * const inString){
        if(!inString) return *this;						// Test if null

        const int sl = BString::Strlen(inString);		// Check str lenght

        allocateIfNeeded(sl);

        BString::Copy(inString,&string[lenght]);	// copy append string
        lenght += sl;								// calcul new size

        return *this;
}

BString& BString::append(const BString& inString){
        allocateIfNeeded(inString.lenght);
        BString::Copy(inString.string,&string[lenght]);	// copy append string
        lenght += inString.lenght;						// calcul new size

        return *this;
}

BString& BString::append(const char in_char){
        allocateIfNeeded(1);								// check size

        string[lenght + 1] = this->string[lenght];			//
        string[lenght] = in_char;							// copy append char
        ++lenght;											// calcul new size

        return *this;
}

BString BString::operator+(const BString& inString) const{
        BString concat(lenght + inString.lenght + 1);	// create a string with big buffer

        BString::Copy(string,concat.string);
        BString::Copy(inString.string,&concat.string[lenght]);
        concat.lenght = lenght + inString.lenght;

        return concat;
}

BString BString::operator+(const char* const inString) const{
        const int stringlenght = BString::Strlen(inString);
        BString concat(lenght + stringlenght + 1);			// create a string with big buffer

        BString::Copy(string,concat.string);				// add currrent string
        BString::Copy(inString,&concat.string[lenght]);	// add 2nd string
        concat.lenght = lenght + stringlenght;

        return concat;
}

char BString::operator[](const int in_index) const{
        if(0 <= in_index && in_index < lenght) return string[in_index];
        return char();
}

BString& BString::operator=(const BString & inString){
        if(inString.lenght >= bufferLenght ){			// check if buffer is enought big
                if(string) delete(string);					// if not delete
                bufferLenght = inString.lenght + 1;			// allocate buffer
                string = new char[bufferLenght];
        }
        BString::Copy(inString.string,string);			// copy string
        lenght = inString.lenght;						// save lenght
        return *this;
}

BString& BString::operator=(const char* const inString){
        if(!inString){
                if(string) this->string[0] = '\0';
                lenght = 0;
                return *this;
        }

        const int sl = BString::Strlen(inString);
        if(sl >= bufferLenght ){
                if(string) delete(string);
                bufferLenght = sl + 1;
                string = new char[bufferLenght];
        }

        BString::Copy(inString,string);
        lenght = sl;

        return *this;
}

bool BString::operator==(const BString& inString) const{
        if( lenght != inString.lenght ||
                (lenght && this->string[0] != inString.string[0]) ) return false;

        for( int indexString = 0 ; indexString < lenght ; ++indexString ){
                if(string[indexString] != inString.string[indexString]) return false;
        }

        return true;
}

bool BString::operator==(const char* inString) const{
        if( lenght != BString::Strlen(inString) ||
                (lenght && this->string[0] != inString[0]) ) return false;

        for( int indexString = 0 ; indexString < lenght ; ++indexString ){
                if(string[indexString] != inString[indexString]) return false;
        }

        return true;
}

int BString::Strlen(const char* const inString){
        int indexString = 0;
        if(inString){
                while(inString[indexString] != '\n' && inString[indexString] != '\0') ++indexString;
        }
        return indexString;
}

int BString::Copy(const char* const in_src, char* const in_dest){
        if(!in_dest) return 0;
        if(!in_src) {
                in_dest[0] = '\0';
                return 0;
        }

        int indexString = 0;

        while(in_src[indexString] != '\n' && in_src[indexString] != '\0'){
                in_dest[indexString] = in_src[indexString];
                ++indexString;
        }
        in_dest[indexString] = in_src[indexString];

        return indexString;
}

// ------------------------------------------------------------------- //
// ------------------------  ItoA functions      --------------------- //
// ------------------------------------------------------------------- //

void BString::ithex(int val)
{
        int lenght = sizeof(val);
        allocateIfNeeded(lenght+2);

        char *str = this->string + lenght;
        lenght += lenght+2;

        *str = '0';
        ++str;
        *str = 'x';
        ++str;

        while(lenght--){
                *(str + lenght) = HexChars[0xf & val];
                val >>= 4;
        }

    *(string + lenght) = '\0';
}

void BString::lthex(long val)
{
        int lenght = sizeof(val);
        allocateIfNeeded(lenght+2);

        char *str = this->string + lenght;
        lenght += lenght+2;

        *str = '0';
        ++str;
        *str = 'x';
        ++str;

        while(lenght--){
                *(str + lenght) = HexChars[0xf & val];
                val >>= 4;
        }

    *(string + lenght) = '\0';
}

void BString::uithex(unsigned int val)
{
        int lenght = sizeof(val);
        allocateIfNeeded(lenght+2);

        char *str = this->string + lenght;
        lenght += lenght+2;

        *str = '0';
        ++str;
        *str = 'x';
        ++str;

        while(lenght--){
                *(str + lenght) = HexChars[0xf & val];
                val >>= 4;
        }

    *(string + lenght) = '\0';
}

void BString::ulthex(unsigned long val)
{
        int lenght = sizeof(val);
        allocateIfNeeded(lenght+2);

        char *str = this->string + lenght;
        lenght += lenght+2;

        *str = '0';
        ++str;
        *str = 'x';
        ++str;

        while(lenght--){
                *(str + lenght) = HexChars[0xf & val];
                val >>= 4;
        }

    *(string + lenght) = '\0';
}

void BString::stoa (short num){
        allocateIfNeeded(BShortMaxLenght);

        char *str = this->string + lenght;

        // check if is a negative number
    if (num < 0) {
                // print '-'
        *str = '-';
                ++str;
                ++lenght;
                // convert int to positif
        num = -num;
    }

        short diviser = 1;
        while( num >= diviser*10 ) diviser *= 10;

        short tmp;
        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10;
        }
        *str = '\0';
}

void BString::ustoa (unsigned short num){
        allocateIfNeeded(BUShortMaxLenght);

    char *str = this->string + lenght;

        short diviser = 1;
        while( num >= diviser*10 ) diviser *= 10;

        short tmp;
        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10;
        }
        *str = '\0';
}

/**
* @brief Convert int to char
*/
void BString::itoa (int num){
        allocateIfNeeded(BIntMaxLenght);

        char *str = this->string + lenght;

        // check if is a negative number
    if (num < 0) {
                // print '-'
        *str = '-';
                ++str;
                ++lenght;
                // convert int to positif
        num = -num;
    }

        int diviser = 1;
        while( num >= diviser*10 ) diviser *= 10;

        int tmp;
        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10;
        }
        *str = '\0';

}

/**
* @brief Convert int to char
*/
void BString::uitoa (unsigned int num){
        allocateIfNeeded(BUIntMaxLenght);

    char *str = this->string + lenght;

        unsigned int diviser = 1;
        unsigned int tmp;

        while( num >= diviser*10u ) diviser *= 10u;

        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10u;
        }
        *str = '\0';
}

/**
* @brief Convert int to char
*/
void BString::litoa (long num){
        allocateIfNeeded(BLongMaxLenght);

    char *str = this->string + lenght;
        // check if is a negative number
        if (num < 0) {
                // print '-'
                *str = '-';
                ++str;
                ++lenght;
                // convert int to positif
                num = -num;
        }

        long diviser = 1;
        long tmp;

        while( num >= diviser*10 ) diviser *= 10;

        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10;
        }
        *str = '\0';
}

/**
* @brief Convert int to char
*/
void BString::ulitoa (unsigned long num){
        allocateIfNeeded(BULongMaxLenght);

    char *str = this->string + lenght;

        unsigned long diviser = 1;
        unsigned long tmp;

        while( num >= diviser*10 ) diviser *= 10;

        while( num ){
                tmp = num/diviser;

                num -= (tmp*diviser);
                *str = char('0' + tmp);
                ++str;

                ++lenght;
                diviser /= 10;
        }
        *str = '\0';
}

/**
* @brief Convert float to char
*/
void BString::ftoa (float num){
        allocateIfNeeded(BFloatMaxLenght);

    float digit_value;
        short digit;
        char *str = this->string + lenght;

        // check if is a negative number
    if (num < 0) {
                // print '-'
        *str = '-';
                ++str;
                ++lenght;
                // convert int to positif
        num = -num;
    }

        // start from 1
    digit_value = 1;
        // progress until this is under the number we want to convert
    while (digit_value*10 <= num){
                digit_value *= 10;
        }

        // then while this non zeros value
    while (digit_value >= 1) {
                // copy division
        digit = static_cast<short>( num / digit_value );
                // dec number
        num -= digit * digit_value;
                // print value
        *str = char('0' + digit);
                ++str;
                ++lenght;
                // dec by base
        digit_value /= 10;
    }

        if( num >= 0.000001 ){
                digit_value = 100000;
                num *= digit_value * 10;
                *str = '.';
                ++str;
                ++lenght;
                // then while this non zeros value
            while (digit_value > 1) {
                        // copy division
                digit = static_cast<short>( num / digit_value );
                        // dec number
                num -= digit * digit_value;
                        // print value
                *str = char('0' + digit);
                        ++str;
                        ++lenght;
                        // dec by base
                digit_value /= 10;
            }
        }

        *str = '\0';
}

/**
* @brief Convert double to char
*/
void BString::dtoa (double num){
        allocateIfNeeded(BDoubleMaxLenght);

    double digit_value;
        short digit;
        char *str = this->string + lenght;

        // check if is a negative number
    if (num < 0) {
                // print '-'
        *str = '-';
                ++str;
                ++lenght;
                // convert int to positif
        num = -num;
    }

        // start from 1
    digit_value = 1;
        // progress until this is under the number we want to convert
    while (digit_value*10 <= num){
                digit_value *= 10;
        }

        // then while this non zeros value
    while (digit_value >= 1) {
                // copy division
        digit = static_cast<short>( num / digit_value );
                // dec number
        num -= digit * digit_value;
                // print value
        *str = char('0' + digit);
                ++str;
                ++lenght;
                // dec by base
        digit_value /= 10;
    }

        if( num >= 0.000001 ){
                digit_value = 100000;
                num *= digit_value * 10;
                *str = '.';
                ++str;
                ++lenght;
                // then while this non zeros value
            while (digit_value > 1) {
                        // copy division
                digit = static_cast<short>( num / digit_value );
                        // dec number
                num -= digit * digit_value;
                        // print value
                *str = char('0' + digit);
                        ++str;
                        ++lenght;
                        // dec by base
                digit_value /= 10;
            }
        }

        *str = '\0';
}

// ------------------------------------------------------------------- //
// ------------------------  out of class functions ------------------ //
// ------------------------------------------------------------------- //

/*bool operator==(const BString& in_string1, const BString& in_string2){
        if( in_string1.lenght() != in_string2.lenght() ||
                (in_string1.lenght() && in_string1[0] != in_string2[0]) ) return false;

        for( int indexString = 0 ; indexString < in_string1.lenght() ; ++indexString ){
                if(in_string1[indexString] != in_string2[indexString]) return false;
        }

        return true;
}*/

/*BString operator+(const BString& in_string1, const BString& in_string2){
        BString concat(in_string1.lenght() + in_string2.lenght());

        concat.append(in_string1);
        concat.append(in_string2);

        return concat;
}*/

Testing & Comparing

In this code I compare my string and the std string.
I used a timer I posted here : http://berenger.eu/blog/2010/09/01/c-time-clock-time-manager-cross-platform-windows-posix/.
As you can see, my string goes a lot faster (it is only because I did the minimum) excepted for the creation with a buffer size.

#include <sstream>
#include <iostream>
#include <vector>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

///////////////////////////////////////////////////////
// This calss is an example to compare our string
// to the std string.
///////////////////////////////////////////////////////

// We use the BTic class (available on this blog)
#include "../Time-Berenger.eu20110606/Time/BTic.hpp"
#include "BString.hpp"

void Compare(){
        BTic tc;

        tc.tic();
        for(unsigned long lg = 0 ; lg < 2000000u ; ++lg){
                std::string tmp;
        }
        tc.tac();

        std::cout << "Result string : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                BString tmp;
        }
        tc.tac();

        std::cout << "Result BString : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long lg = 0 ; lg < 2000000u ; ++lg){
                std::string tmp;
                tmp = "zer";
                tmp += "azsxc";
                tmp.clear();
                tmp += "blabloubla";
        }
        tc.tac();

        std::cout << "Result string : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                BString tmp(50);
                tmp = "zer";
                tmp += "azsxc";
                tmp.clear();
                tmp += "blabloubla";
        }
        tc.tac();

        std::cout << "Result BString : " << tc.elapsed() << " ms" << '\n';

        std::ostringstream str;
        BString bstr(50);

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                str << 55;
                str.clear();
        }
        tc.tac();

        std::cout << "Result string : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                bstr.append(55);
                bstr.clear();
        }
        tc.tac();

        std::cout << "Result BString : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                str << 55.02;
                str.clear();
        }
        tc.tac();

        std::cout << "Result string : " << tc.elapsed() << " ms" << '\n';

        tc.tic();
        for(unsigned long  lg = 0 ; lg < 2000000u ; ++lg){
                bstr.append(55.02);
                bstr.clear();
        }
        tc.tac();

        std::cout << "Result BString : " << tc.elapsed() << " ms" << '\n';
}

///////////////////////////////////////////////////////
///////////////////////////////////////////////////////

void Test(){
        {
                BString str;
                str.append(99);
                str.append(" ");
                str.append(5.5985);
                str.append('#');
                str.appendHex(0x5684);
                str.append('\n');
                str.append("Youpla!");
                std::cout << "Str : " << str.data() << '\n';
        }
        {
                BString toto("toto");
                if(toto == "toto"){
                        std::cout << "Toto equals" << std::endl;
                }

                BString tata2("tata2");
                if(toto != tata2){
                        std::cout << "Toto != tata2" << std::endl;
                }

                tata2 = toto;
                if(toto == tata2){
                        std::cout << "Toto == tata2" << std::endl;
                }

                std::cout << (toto + tata2).data() << std::endl;
        }
}

///////////////////////////////////////////////////////
///////////////////////////////////////////////////////

int main()
{
    Compare();
        Test();

    return 0;
}

Result in console :

$ ./BStringLGPL
Result string : 0.001157 ms
Result BString : 0 ms
Result string : 0.503508 ms
Result BString : 0.188768 ms
Result string : 0.134228 ms
Result BString : 0.032374 ms
Result string : 1.13637 ms
Result BString : 0.210538 ms
Str : 99 50x00000
Youpla!
Toto equals
Toto != tata2
Toto == tata2
totototo

Licence

BString is under LGPL.

Download

BStringLGPL

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.

Comments are closed.

Celadon theme by the Themes Boutique