I've recreated std::string
in a way that might be faster.
System Features:
Much faster than std::string.
Easy to use.
It was designed as part of a large database so it is very fast and good at handling memory.
Responsive to all types of data, you can enter characters, numbers, even decimal numbers, boolean values or even lists, without the need to convert data types to a string.
It contains a system dedicated to calculating numbers and converting them into text strings, It works great with decimal numbers. see below to learn more.
All functions tested, no errors detected.
The reason for the speed of performance:
The reason lies in the way I handle the heap memory, I don't need to realloc memory every time the value changes, and I don't need to completely reset the object when any modification is made.
If you are interested you can check out the set()
function, i have left comments that can explain this further.
Test results:
+-------------------------+--------+------+------------------------------+
|METHOD |CLASS |TIME |NOTES |
+-------------------------+--------+------+------------------------------+
|create empty |xstring |210 | |
| |string |1586 | |
+-------------------------+--------+------+------------------------------+
|create by string |xstring |1859 | |
| |string |3194 | |
+-------------------------+--------+------+------------------------------+
|create by character |xstring |1852 | |
| |string |2680 |Unavailable, used to_string() |
+-------------------------+--------+------+------------------------------+
|create by bool |xstring |1836 | |
| |string |2487 |Unavailable, used to_string() |
+-------------------------+--------+------+------------------------------+
|create by integer |xstring |2477 | |
| |string |2453 |Unavailable, used to_string() |
+-------------------------+--------+------+------------------------------+
|create by decimal |xstring |4428 | |
| |string |23053 |Unavailable, used to_string() |
+-------------------------+--------+------+------------------------------+
|create by same object |xstring |3750 | |
| |string |9779 | |
+-------------------------+--------+------+------------------------------+
|create by multiple |xstring |3726 | |
| |string |-- |Unavailable |
+-------------------------+--------+------+------------------------------+
|append |xstring |2426 | |
| |string |7685 | |
+-------------------------+--------+------+------------------------------+
|prepend |xstring |2593 | |
| |string |10665 |Unavailable, used insert(0,) |
+-------------------------+--------+------+------------------------------+
|insert |xstring |2574 | |
| |string |10579 | |
+-------------------------+--------+------+------------------------------+
|compare |xstring |3985 | |
| |string |8200 | |
+-------------------------+--------+------+------------------------------+
|swap |xstring |3928 | |
| |string |11579 | |
+-------------------------+--------+------+------------------------------+
|to lower |xstring |2407 | |
| |string |-- |Unavailable |
+-------------------------+--------+------+------------------------------+
|to upper |xstring |2432 | |
| |string |-- |Unavailable |
+-------------------------+--------+------+------------------------------+
|select by index |xstring |1984 | |
| |string |3303 | |
+-------------------------+--------+------+------------------------------+
|select by char and pos |xstring |1976 | |
| |string |4138 | |
+-------------------------+--------+------+------------------------------+
|select last |xstring |1910 | |
| |string |3563 | |
+-------------------------+--------+------+------------------------------+
|pop last |xstring |2114 | |
| |string |4338 | |
+-------------------------+--------+------+------------------------------+
|pop by index |xstring |2095 | |
| |string |6591 | |
+-------------------------+--------+------+------------------------------+
|reverse |xstring |2465 | |
| |string |-- |Unavailable |
+-------------------------+--------+------+------------------------------+
|find first of |xstring |2001 | |
| |string |4446 | |
+-------------------------+--------+------+------------------------------+
|find last of |xstring |1979 | |
| |string |4199 | |
+-------------------------+--------+------+------------------------------+
|sub string |xstring |4070 | |
| |string |17287 | |
+-------------------------+--------+------+------------------------------+
|is empty |xstring |1909 | |
| |string |3262 | |
+-------------------------+--------+------+------------------------------+
Test Info
OS linux, ubuntu 20.04
processor Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
memory 8064MiB System memory
Compiler g++ 11
C++ Version c++ 20
tested by valgrind, you can test with just run script and you will got same ratios
You can find the source file and test script here GitHub: xString
I have some questions :
Are there any errors that I did not notice?
Is there anything that can be done to improve performance?
Is there anything missing?
What is your opinion and what are your suggestions?
Edit: xstring.h
/*
All rights reserved: Maysara Khalid Elshewehy [github.com/xeerx]
Created on: 4 Apr 2022
Commercial use of this file is prohibited without written permission
*/
#ifndef XCPP_XSTRING_H
#define XCPP_XSTRING_H
#include <string.h> // strlen
#include <cstdlib> // calloc, realloc, free
#include <initializer_list> // initializer_list
#include <stddef.h> // size_t
#include <stdint.h> // SIZE_MAX
#include <ostream> // ostream operator
// xstring macros
#define xnpos SIZE_MAX // max size of size_t, when error, return to it
#define _xs_extra_space_ 25 // the extra space size in heap memory
// xstring helpers
namespace x::hlpr
{
// [INTEGER LENGTH]
#define __sig_int_len__(t) (t int src) { unsigned t int len = src < 0 ? 1 : 0; while(true) { src /= 10; if(src != 0) len ++; else return len; } }
#define __uns_int_len__(t) (unsigned t int src) { unsigned t int len = 0; while(true) { src /= 10; if(src != 0) len ++; else return len; } }
unsigned int intlen __sig_int_len__()
unsigned int uintlen __uns_int_len__()
unsigned short int sintlen __sig_int_len__(short)
unsigned short int usintlen __uns_int_len__(short)
unsigned long lintlen __sig_int_len__(long)
unsigned long ulintlen __uns_int_len__(long)
unsigned long long llintlen __sig_int_len__(long long)
unsigned long long ullintlen __uns_int_len__(long long)
// [INTEGER TO STRING]
#define __sig_int_str__(s,t) (char *ref, s src, unsigned s len = 0) { if(src == 0){ ref[0] = '0'; ref[1] = '\0'; return; } if (len == 0) len = t(src) + 1; if (src < 0) { src = src * -1; ref[0] = '-'; } len--; ref[len + 1] = '\0'; while (src > 0) { ref[len] = src % 10 + '0'; src /= 10; len--; } }
#define __uns_int_str__(s,t) (char *ref, unsigned s src, unsigned s len = 0) { if(src == 0){ ref[0] = '0'; ref[1] = '\0'; return; } if(len == 0) len = t(src) +1; len --; ref[len+1] = '\0'; while(src >= 1) { ref[len] = src % 10 + '0'; src /= 10; len --; } }
void intstr __sig_int_str__(int,intlen)
void uintstr __uns_int_str__(int ,uintlen)
void sintstr __sig_int_str__(short int,sintlen)
void usintstr __uns_int_str__(short int ,usintlen)
void lintstr __sig_int_str__(long int,lintlen)
void ulintstr __uns_int_str__(long int ,ulintlen)
void llintstr __sig_int_str__(long long int,llintlen)
void ullintstr __uns_int_str__(long long int ,ullintlen)
// [INTEGER MACROS]
#define __int_str_shortcut__(src,l,lfunc,sfunc) unsigned l __len = x::hlpr::lfunc(src) +1; char * __ref = new char[__len+1]; x::hlpr::sfunc(__ref,src,__len); delete [] __ref;
#define __intstr__(src) __int_str_shortcut__(src,int,intlen,intstr)
#define __uintstr__(src) __int_str_shortcut__(src,int,uintlen,uintstr)
#define __sintstr__(src) __int_str_shortcut__(src,short int,sintlen,sintstr)
#define __usintstr__(src) __int_str_shortcut__(src,short int,usintlen,usintstr)
#define __lintstr__(src) __int_str_shortcut__(src,long int,lintlen,lintstr)
#define __ulintstr__(src) __int_str_shortcut__(src,long int,ulintlen,ulintstr)
#define __llintstr__(src) __int_str_shortcut__(src,long long int,llintlen,llintstr)
#define __ullintstr__(src) __int_str_shortcut__(src,long long int,ullintlen,ullintstr)
// [DECIMAL LENGTH]
#define __decimal_len__(t) (t src, unsigned short int max = 6) { unsigned int len = 0, ilen = 0, i = 0; int isrc = (int)src; if(src < 0) src *= -1; if(src > 0) { ilen = intlen(isrc); src -= isrc;} while(i < max && (isrc - src) != 0) { src = src * 10; i++; len ++; } return len + ilen; }
unsigned int floatlen __decimal_len__(float)
unsigned int doublelen __decimal_len__(double)
unsigned int ldoublelen __decimal_len__(long double)
// [DECIMAL TO STRING]
#define __decimal_str__(t,lfunc) (char *ref, t src, unsigned short int max = 0, bool setmax = false) { bool neg = false; if(src < 0) { src = src * -1; neg = true; } if(src == 0) { ref[0] = '0'; ref[1] = '.'; ref[2] = '0'; ref[3] = '\0'; } int numbers = src, digit = 0, numberslen = x::hlpr::intlen(numbers), index = numberslen + 1; long pow_value = 0; unsigned int flen = x::hlpr::lfunc(src); if(numberslen > 0) flen -= numberslen; if(!max) max = flen; else if(setmax) max -= numberslen; max --; x::hlpr::intstr(ref,numbers,index); ref[index] = '.'; index ++; if(numbers == src) { ref[index] = '0'; index ++; if(neg) { unsigned int bi = index; ref[bi] = '\0'; while (index >= 0) { ref[index+1] = ref[index]; index --; } ref[0] = '-'; return bi +1; } else ref[index] = '\0'; return index; } t fraction_part = src - numbers; t tmp1 = fraction_part, tmp =0; for( int i= 1; i < max + 2; i++) { pow_value = 10; tmp = tmp1 * pow_value; digit = tmp; ref[index] = digit +48; tmp1 = tmp - digit; index ++; } int temp_index = index -1; while(temp_index >= 0) { if(ref[temp_index] == '0') { ref[temp_index] = '\0'; index --; } else break; temp_index --; } temp_index = index -1; while(temp_index >= 0) { if(ref[temp_index] == ref[temp_index-1]) { ref[temp_index] = '\0'; index --; } else break; temp_index --; } if(neg) { unsigned int bi = index; ref[bi] = '\0'; while (index >= 0) { ref[index+1] = ref[index]; index --; } ref[0] = '-'; return bi+1; } else ref[index] = '\0'; return index;}
unsigned int floatstr __decimal_str__(float,floatlen)
unsigned int doublestr __decimal_str__(double,doublelen)
unsigned int ldoublestr __decimal_str__(long double,ldoublelen)
// [DECIMAL MACROS]
#define __decimal_str_shortcut__(src,lfunc,sfunc,max) unsigned short int __len = x::hlpr::lfunc(src,max) +1; char * __ref = new char[__len+4];__len = x::hlpr::sfunc(__ref,src,__len,true); delete [] __ref;
#define __floatstr__(src) __decimal_str_shortcut__(src,floatlen,floatstr,max)
#define __doublestr__(src) __decimal_str_shortcut__(src,doublelen,doublestr,max)
#define __ldoublestr__(src) __decimal_str_shortcut__(src,ldoublelen,ldoublestr,max)
}
// xstring class
namespace x
{
// some variables used to return to error
char xstr_null_char = '\0';
class xstring
{
public:
// data
char *src = nullptr; // pointer to character array wich contains to value of object
size_t len = 0; // length of src, zero means empty
size_t siz = 0; // size of src in heap memory
// constructor -> default empty
xstring () { }
xstring (const char *ref, size_t rlen = 0) { set(ref,rlen); }
xstring (char ref) { set(ref); }
xstring (bool ref) { set(ref); }
xstring ( int ref) { set(ref); }
xstring (unsigned int ref) { set(ref); }
xstring (short int ref) { set(ref); }
xstring (unsigned short int ref) { set(ref); }
xstring (long int ref) { set(ref); }
xstring (unsigned long int ref) { set(ref); }
xstring (long long int ref) { set(ref); }
xstring (unsigned long long int ref) { set(ref); }
xstring (float ref,unsigned short max = 1) { set(ref,max); }
xstring (double ref,unsigned short max = 1) { set(ref,max); }
xstring (long double ref,unsigned short max = 1) { set(ref,max); }
xstring (xstring &ref) { set(ref); }
xstring (const xstring &ref) { set(ref); }
template <typename T>
xstring (std::initializer_list<T> ref) { for(auto i:ref) append(i); }
// set
bool set (const char *ref, size_t rlen);
bool set (char ref) { char __ref[] = {ref}; return set(__ref, 1); }
bool set (bool ref) { return set(ref ? "1" : "0", 1); }
bool set ( int ref) { __intstr__ (ref) return set(__ref, __len); }
bool set (unsigned int ref) { __uintstr__ (ref) return set(__ref, __len); }
bool set (short int ref) { __sintstr__ (ref) return set(__ref, __len); }
bool set (unsigned short int ref) { __usintstr__ (ref) return set(__ref, __len); }
bool set (long int ref) { __lintstr__ (ref) return set(__ref, __len); }
bool set (unsigned long int ref) { __ulintstr__ (ref) return set(__ref, __len); }
bool set (long long int ref) { __llintstr__ (ref) return set(__ref, __len); }
bool set (unsigned long long int ref) { __ullintstr__ (ref) return set(__ref, __len); }
bool set (float ref,unsigned short max = 1) { __floatstr__ (ref) return set(__ref, __len); }
bool set (double ref,unsigned short max = 1) { __doublestr__ (ref) return set(__ref, __len); }
bool set (long double ref,unsigned short max = 1) { __ldoublestr__ (ref) return set(__ref, __len); }
bool set (xstring &ref) { if(&ref != this) return set(ref.src, ref.len); else return false; }
bool set (const xstring &ref) { if(&ref != this) return set(ref.src, ref.len); else return false; }
template <typename T>
bool set (std::initializer_list<T> ref) { reset(); for(auto i:ref) if(!append(i)) return false; return true; }
template <typename T>
bool operator = (T ref) { return set(ref); }
template <typename T>
bool operator = (std::initializer_list<T> ref) { return set(ref); }
// append
bool append (const char *ref, size_t rlen);
bool append (char ref) { char __ref[] = {ref}; return append(__ref, 1); }
bool append (bool ref) { return append(ref ? "1" : "0", 1); }
bool append ( int ref) { __intstr__ (ref) return append(__ref, __len); }
bool append (unsigned int ref) { __uintstr__ (ref) return append(__ref, __len); }
bool append (short int ref) { __sintstr__ (ref) return append(__ref, __len); }
bool append (unsigned short int ref) { __usintstr__ (ref) return append(__ref, __len); }
bool append (long int ref) { __lintstr__ (ref) return append(__ref, __len); }
bool append (unsigned long int ref) { __ulintstr__ (ref) return append(__ref, __len); }
bool append (long long int ref) { __llintstr__ (ref) return append(__ref, __len); }
bool append (unsigned long long int ref) { __ullintstr__ (ref) return append(__ref, __len); }
bool append (float ref,unsigned short max = 1) { __floatstr__ (ref) return append(__ref, __len); }
bool append (double ref,unsigned short max = 1) { __doublestr__ (ref) return append(__ref, __len); }
bool append (long double ref,unsigned short max = 1) { __ldoublestr__ (ref) return append(__ref, __len); }
bool append (xstring &ref) { if(&ref != this) return append(ref.src, ref.len); else return false; }
bool append (const xstring &ref) { if(&ref != this) return append(ref.src, ref.len); else return false; }
template <typename T>
bool append (std::initializer_list<T> ref) { for(auto i:ref) if(!append(i)) return false; return true; }
template <typename T>
bool operator += (T ref) { return append(ref); }
template <typename T>
bool operator += (std::initializer_list<T> ref) { return append(ref); }
// prepend
bool prepend (const char *ref, size_t rlen);
bool prepend (char ref) { char __ref[] = {ref}; return prepend(__ref, 1); }
bool prepend (bool ref) { return prepend(ref ? "1" : "0", 1); }
bool prepend ( int ref) { __intstr__ (ref) return prepend(__ref, __len); }
bool prepend (unsigned int ref) { __uintstr__ (ref) return prepend(__ref, __len); }
bool prepend (short int ref) { __sintstr__ (ref) return prepend(__ref, __len); }
bool prepend (unsigned short int ref) { __usintstr__ (ref) return prepend(__ref, __len); }
bool prepend (long int ref) { __lintstr__ (ref) return prepend(__ref, __len); }
bool prepend (unsigned long int ref) { __ulintstr__ (ref) return prepend(__ref, __len); }
bool prepend (long long int ref) { __llintstr__ (ref) return prepend(__ref, __len); }
bool prepend (unsigned long long int ref) { __ullintstr__ (ref) return prepend(__ref, __len); }
bool prepend (float ref,unsigned short max = 1) { __floatstr__ (ref) return prepend(__ref, __len); }
bool prepend (double ref,unsigned short max = 1) { __doublestr__ (ref) return prepend(__ref, __len); }
bool prepend (long double ref,unsigned short max = 1) { __ldoublestr__ (ref) return prepend(__ref, __len); }
bool prepend (xstring &ref) { if(&ref != this) return prepend(ref.src, ref.len); else return false; }
bool prepend (const xstring &ref) { if(&ref != this) return prepend(ref.src, ref.len); else return false; }
template <typename T>
bool prepend (std::initializer_list<T> ref) { for(auto i:ref) if(!prepend(i)) return false; return true; }
template <typename T>
bool operator |= (T ref) { return prepend(ref); }
template <typename T>
bool operator |= (std::initializer_list<T> ref) { return prepend(ref); }
// print
friend std::ostream &operator<<(std::ostream &os, const xstring &s) { os << (s.src ? s.src : ""); return (os); }
// insert
bool insert (size_t pos, const char *ref, size_t rlen);
bool insert (size_t pos, char ref) { char __ref[] = {ref}; return insert(pos,__ref, 1); }
// compare between two strings
bool compare(const char *ref) { return strcmp(src,ref) == 0; }
bool compare(xstring& ref) { return compare(ref.src); }
bool compare(const xstring& ref) { return compare(ref.src); }
bool compare( char ref) { char __ref[] = {ref}; return compare(__ref); }
bool operator == (const char *ref) { return compare(ref) == true; }
bool operator == (xstring& ref) { return compare(ref) == true; }
bool operator == (const xstring& ref) { return compare(ref) == true; }
bool operator == ( char ref) { return compare(ref) == true; }
// no need in C++ 20
// bool operator != (const char *ref) { return compare(ref) == false; }
// bool operator != (xstring& ref) { return compare(ref) == false; }
// bool operator != (const xstring& ref) { return compare(ref) == false; }
// bool operator != ( char ref) { return compare(ref) == false; }
// swap value,len,size between two string objects
void swap(xstring &ref)
{
char *tmp_src = src;
size_t tmp_len = len;
size_t tmp_siz = siz;
src = ref.src;
len = ref.len;
siz = ref.siz;
ref.src = tmp_src;
ref.len = tmp_len;
ref.siz = tmp_siz;
}
// convert src characters to lower case
void to_lower()
{
size_t i = 0;
while(src[i] != '\0') { src[i] = std::tolower(src[i]); i++; }
}
// convert src characters to upper case
void to_upper()
{
size_t i = 0;
while(src[i] != '\0') { src[i] = std::toupper(src[i]); i++; }
}
// select character by index, return xstr_null_char if not found
char& getChar(size_t ref)
{
if(ref > len) return xstr_null_char;
return src[ref];
}
char& operator[](size_t ref) { return getChar(ref); }
// select index by value, start from position, return xnpos if not found
size_t getIndex(char ref, size_t pos = 0)
{
if(pos > len) return xnpos;
size_t counter = pos;
while(counter < len)
{
if(src[counter] == ref) return counter;
counter ++;
}
return xnpos;
}
// get last character
char& getLast() { return src[len-1]; }
// remove from value by index
bool pop(size_t pos = 0, size_t max = 1)
{
if(pos >= len) return false;
if(max > len || max == 0) max = len;
memmove(&src[pos], &src[pos + max], len - pos - 1);
src[len - 1] = '\0';
len --;
return true;
}
// remove last character using pop(len-1)
bool pop_last() { return pop(len-1); }
// reverse characters
void reverse()
{
char *tmp = new char[len];
size_t count = len;
size_t count_src = 0;
while(count > 0)
{
tmp[count-1] = src[count_src];
count --;
count_src ++;
}
tmp[len] = '\0';
memcpy(src,tmp,len+1);
delete [] tmp;
}
// check if value is empty by check if length equals zero
bool empty() { return len == 0; }
// find first matched character in string, start from begin + pos, if failed return to xnpos
size_t first_of(char ref, size_t pos = 0)
{
if(pos >= len) return xnpos;
while( src[pos]!=ref && pos < len) pos++;
return pos == len ? xnpos : pos;
}
// find last matched character in string, start from end - pos, if failed return to xnpos
size_t last_of (char ref, size_t pos = 0)
{
if(pos >= len) return xnpos;
pos = len - pos -1;
while(src[pos]!=ref && pos > 0) pos--;
if(src[pos] == ref) return pos; else return xnpos;
}
// cut string from [start] to [end] and set to ref
bool sub(xstring &ref, size_t start = 0, size_t end = 0)
{
if(start >= len) start = len -1;
if(start == end) return false;
if(end == 0 || end >= len) end = len;
size_t llen = end - start;
char *res = new char[llen+1];
size_t pos = 0;
while(start < end)
{
res[pos] = src[start];
start ++;
pos ++;
}
res[pos] = '\0';
ref.set(res, llen+1);
delete [] res;
return true;
}
// free memory, set values to zero
void reset () { if(!siz) return; free(src); len = 0; siz = 0; }
// destructor
~xstring () { reset(); }
};
}
// xstring class functions, i will write long functions here to arrange the file and keep it beautiful
namespace x
{
/**
* @brief set value of xstring object
*/
bool xstring::set (const char *ref, size_t rlen = 0)
{
if(!rlen) rlen = strlen(ref); // [increase performance] If the length is known, there is no need to recalculate it
if(siz == 0) // alloc space in heap memory to store value
{
siz = rlen + _xs_extra_space_; // [increase performance] extra 25 bytes space to avoid realloc in next times if space is enough
if(siz >= xnpos - 25) { siz -= rlen + _xs_extra_space_; return false; } // check if size > max size
src = (char*) calloc(siz, sizeof(char)); // allocate space
if(src == nullptr) return false; // check if space is allocated
}
else if(siz <= rlen) // realloc more space to contains the new value
{
siz = rlen + _xs_extra_space_;
if(siz >= xnpos - 25) { siz -= rlen + _xs_extra_space_; return false; }
src = (char*) realloc(src, siz * sizeof(char));
if(src == nullptr) return false;
}
memcpy(src, ref, rlen+1); // copy value from ref
len = rlen; // update length
src[len] = '\0'; // terminate the array
return true;
}
/**
* @brief add value to begin of xstring object
*/
bool xstring::append (const char *ref, size_t rlen = 0)
{
if(siz == 0) return set(ref,rlen); // if space is null, call set()
if(!rlen) rlen = strlen(ref);
if(siz <= (len + rlen))
{
siz += rlen + _xs_extra_space_;
if(siz >= xnpos - 25) { siz -= rlen + _xs_extra_space_; return false; }
src = (char*) realloc(src, siz * sizeof(char));
if(src == nullptr) return false;
}
memcpy(src + len, ref, rlen+1);
len += rlen;
src[len] = '\0';
return true;
}
/**
* @brief add value to end of xstring object
*/
bool xstring::prepend (const char *ref, size_t rlen = 0)
{
if(siz == 0) return set(ref,rlen);
if(!rlen) rlen = strlen(ref);
if(siz <= (len + rlen))
{
siz += rlen + _xs_extra_space_;
if(siz >= xnpos - 25) { siz -= rlen + _xs_extra_space_; return false; }
src = (char*) realloc(src, siz * sizeof(char)); if(src == nullptr) return false;
}
memmove(src + rlen, src, len); // move data to rlen pos
size_t i = 0;
while(i < rlen) // loop in copy ref to begin of src
{
src[i] = ref[i];
++i;
}
len += rlen;
src[len] = '\0';
return true;
}
/**
* @brief add value to position of xstring object
*/
bool xstring::insert (size_t pos, const char *ref, size_t rlen = 0)
{
if(siz == 0) return set(ref,rlen);
if(pos > len) return false;
if(!rlen) rlen = strlen(ref);
if(siz <= (len + rlen))
{
siz += rlen + _xs_extra_space_;
if(siz >= xnpos - 25) { siz -= rlen + _xs_extra_space_; return false; }
src = (char*) realloc(src, siz * sizeof(char)); if(src == nullptr) return false;
}
memmove(src + rlen, src, len);
size_t i = 0; while(true) { size_t target = pos == 0 ? (0 + i) : (pos+i); src[target] = ref[i]; if(++i >= rlen) break;; }
len += rlen; src[len] = '\0'; return true;
}
}
#endif
test.cpp
#include "xstring.h"
#include <chrono>
#include <string>
#include <iostream>
#include <iomanip>
#include <limits.h>
#include <float.h>
using namespace x;
using namespace std;
void TEST_PRNT (const char*f, const char*t, const char*r, const char*n, bool row = false) { char sep = row ? '+' : '|'; std::cout << std::left << sep << std::setw(25) << f << sep << std::setw(8) << t << sep << std::setw(6) << r << sep << std::setw(30) << n << sep << std::endl; }
#define TEST_STUP std::chrono::steady_clock::time_point test_begin; std::chrono::steady_clock::time_point test_end; char test_result[75]; TEST_PRNT("-------------------------", "--------", "------", "------------------------------",true);TEST_PRNT("METHOD", "CLASS", "TIME", "NOTES");TEST_PRNT("-------------------------", "--------", "------", "------------------------------",true);
#define TEST_STRT test_begin = std::chrono::steady_clock::now(); for(int i = 0; i < 1000000; ++i) {
#define TEST_STOP } test_end = std::chrono::steady_clock::now(); sprintf(test_result,"%-6ld",(std::chrono::duration_cast<std::chrono::microseconds>(test_end - test_begin).count()) / 1000);
#define TEST_LINE TEST_PRNT("-------------------------", "--------", "------", "------------------------------", true);
using namespace x;
int main()
{
std::cout << "----------------------------------------" << std::endl;
std::cout << "USE: g++ --std c++20 -g test.cpp -o test" << std::endl;
std::cout << "----------------------------------------" << std::endl;
TEST_STUP
// create empty
TEST_STRT xstring x; TEST_STOP TEST_PRNT("create empty","xstring" ,test_result,"");
TEST_STRT string x; TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// create by string
TEST_STRT xstring x = "value"; TEST_STOP TEST_PRNT("create by string","xstring" ,test_result,"");
TEST_STRT string x = "value"; TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// create by character
TEST_STRT xstring x = 'c'; TEST_STOP TEST_PRNT("create by character","xstring" ,test_result,"");
TEST_STRT string x = to_string('c'); TEST_STOP TEST_PRNT(" ","string" ,test_result,"Unavailable, used to_string()"); TEST_LINE
// create by bool
TEST_STRT xstring x = true; TEST_STOP TEST_PRNT("create by bool","xstring" ,test_result,"");
TEST_STRT string x = to_string(true); TEST_STOP TEST_PRNT(" ","string" ,test_result,"Unavailable, used to_string()"); TEST_LINE
// create by integer
TEST_STRT xstring x = 1; TEST_STOP TEST_PRNT("create by integer","xstring" ,test_result,"");
TEST_STRT string x = to_string(1); TEST_STOP TEST_PRNT(" ","string" ,test_result,"Unavailable, used to_string()"); TEST_LINE
// create by decimal
TEST_STRT xstring x = 123.456; TEST_STOP TEST_PRNT("create by decimal","xstring" ,test_result,"");
TEST_STRT string x = to_string(123.456); TEST_STOP TEST_PRNT(" ","string" ,test_result,"Unavailable, used to_string()"); TEST_LINE
// create by same object
TEST_STRT xstring y = "val"; xstring x = y; TEST_STOP TEST_PRNT("create by same object","xstring" ,test_result,"");
TEST_STRT string y = "val"; string x = y; TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// create by multiple
TEST_STRT xstring x = {"Hello"," ","World","!"}; TEST_STOP TEST_PRNT("create by multiple","xstring" ,test_result,"");
TEST_PRNT(" ","string" ,"--" ,"Unavailable"); TEST_LINE
// append
TEST_STRT xstring x = "Hello"; x += "World"; TEST_STOP TEST_PRNT("append","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x += "World"; TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// prepend
TEST_STRT xstring x = "Hello"; x |= "Hello"; TEST_STOP TEST_PRNT("prepend","xstring" ,test_result,"");
TEST_STRT string x = "World"; x.insert(0,"Hello"); TEST_STOP TEST_PRNT(" ","string" ,test_result,"Unavailable, used insert(0,)"); TEST_LINE
// insert
TEST_STRT xstring x = "Hello"; x.insert(3,"Hello"); TEST_STOP TEST_PRNT("insert","xstring" ,test_result,"");
TEST_STRT string x = "World"; x.insert(3,"Hello"); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// compare
TEST_STRT xstring x = "Hello", y = "World"; x.compare(y); TEST_STOP TEST_PRNT("compare" ,"xstring" ,test_result,"");
TEST_STRT string x = "Hello", y = "World"; x.compare(y); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// swap
TEST_STRT xstring x = "Hello", y = "World"; x.swap(y); TEST_STOP TEST_PRNT("swap" ,"xstring" ,test_result,"");
TEST_STRT string x = "Hello", y = "World"; x.swap(y); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// to lower
TEST_STRT xstring x = "Hello"; x.to_lower(); TEST_STOP TEST_PRNT("to lower" ,"xstring" ,test_result,"");
TEST_PRNT(" ","string" ,"--","Unavailable"); TEST_LINE
// to upper
TEST_STRT xstring x = "Hello"; x.to_upper(); TEST_STOP TEST_PRNT("to upper" ,"xstring" ,test_result,"");
TEST_PRNT(" ","string" ,"--","Unavailable"); TEST_LINE
// select by index
TEST_STRT xstring x = "Hello"; x[0] = 'x'; TEST_STOP TEST_PRNT("select by index","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x[0] = 'x'; TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// select char
TEST_STRT xstring x = "Hello"; x.getIndex('l',1); TEST_STOP TEST_PRNT("select by char and pos","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.find('l',1); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// select last
TEST_STRT xstring x = "Hello"; x.getLast(); TEST_STOP TEST_PRNT("select last","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.back(); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// pop last
TEST_STRT xstring x = "Hello"; x.pop_last(); TEST_STOP TEST_PRNT("pop last","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.pop_back(); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// pop by index
TEST_STRT xstring x = "Hello"; x.pop(2,1); TEST_STOP TEST_PRNT("pop by index","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.erase(2,1); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// reverse
TEST_STRT xstring x = "Hello"; x.reverse(); TEST_STOP TEST_PRNT("reverse","xstring" ,test_result,"");
TEST_PRNT(" ","string" ,"--","Unavailable"); TEST_LINE
// find first of
TEST_STRT xstring x = "Hello"; x.first_of('l'); TEST_STOP TEST_PRNT("find first of","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.find_first_of('l'); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// find last of
TEST_STRT xstring x = "Hello"; x.last_of('l'); TEST_STOP TEST_PRNT("find last of","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; x.find_last_of('l'); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// sub string
TEST_STRT xstring x = "Hello",y; x.sub(y, 0,3); TEST_STOP TEST_PRNT("sub string","xstring" ,test_result,"");
TEST_STRT string x = "Hello",y; y = x.substr(0,3); TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
// is empty
TEST_STRT xstring x = "Hello"; if(x.empty()){} TEST_STOP TEST_PRNT("is empty","xstring" ,test_result,"");
TEST_STRT string x = "Hello"; if(x.empty()){} TEST_STOP TEST_PRNT(" ","string" ,test_result,""); TEST_LINE
}
Final Note:
I only started learning C++ a couple of months ago, so I don't have much experience, I wasn't aware of the optimization options, so it seems like I was too quick to judge my project and my abilities!
I will learn more and re-work on the same project to fix my mistakes not to do something faster! I will be glad for your suggestions, and please tell me how to improve the code, what should I do? What do I learn?
The Second Final Note :D
I will stop working for a while, I will try to develop my skills and increase my knowledge of the language and the compiler.
I will not delete the code now, my mistake does not mean my end, on the contrary, I will learn from this mistake and will come back soon with something strong.