Much Faster than std::string, fmt::format, std::to_chars, std::time and more?

✨⚡️ xeerx C++ Format Library ⚡️✨

A super fast c++ library for managing and formatting strings with the ability to convert from/to any type

♻️ Cross-Platform – tested by Google Test.
⚡️ Speed – faster than std::string, std::time, std::to_ch…


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Maysara

✨⚡️ xeerx C++ Format Library ⚡️✨

A super fast c++ library for managing and formatting strings with the ability to convert from/to any type

  • ♻️ Cross-Platform - tested by Google Test.

  • ⚡️ Speed - faster than std::string, std::time, std::to_chars, {fmt}, .., tested by Google Benchmark.

  • 🍃 Light - minimum lines of code, quick compiling, tested by GCC 12.

  • optimization - improved behavior to reduce Memory Allocation, tested by Valgrind.

  • 🌟 Ability - works with a lot of data types any char numbers time bool ..etc.

🔹🔹 you will find test, gtest and benchmark for everything in: tests/🔹🔹

Index

The library contains:

Usage

#include "core.h"

using namespace xeerx;
  • String

    How It Works

    To understand how strings work, let's see the following examples:

    // [1]
    xeerx::string s1 ("Hello World");
    
    // [2]
    xeerx::string s2 ("Hello");
    s2 += "World";
    
    // [3]
    xeerx::string s3 ("chars:");
    for(int i = 0; i < 100; i++) s3 += 'C';
    

    Explanation of examples

    • ### First Example In this case the class will just pointing to the value, like std::string_view so there is no copies, just like normal const char*
    • Second Example

      1- pointing to the value Hello

      2- copy Hello to the stack buffer

      3- copy World to the end of stack buffer to be HelloWorld

    • Third Example

      1- pointing to the value chars:

      2- copy chars: to the stack buffer

      now we need to append C x100 times, and our stack buffer size is 64

      and the current size of the buffer is 6 (chars: is 6 characters)

      so the stack can hold more 64 - 6 = 58 characters

      3- copy C 58 times to the end of stack buffer

      now the stack buffer is full and we need to append more 42 characters

      so allocate an enough space in the heap memory called heap buffer

      4- allocate a space in the heap memory

      5- copy contents of stack buffer to the heap buffer

      6- append the rest 42 characters to the end of the heap buffer

    Typedefs

    Type Definition
    xeerx::string xeerx::basic_string<char>
    xeerx::wstring xeerx::basic_string<wchar_t>
    xeerx::u16string xeerx::basic_string<char16_t>
    xeerx::u32string xeerx::basic_string<char32_t>
    • ### Specialization Types
    // prototype
    template<typename Type, class Alloc = std::allocator<Type>, xeerx::size_t L_Capacity = X_BUFF_SIZE>
    xeerx::basic_string<Type, Alloc, L_Capacity>
    
    // example: basic_string for 'char' with local buffer capacity 256
    typedef xeerx::basic_string<char, std::allocator<char>, 256> string_256;
    

    There are two types of characters allowed, char and wchar_t.

    But you can use any type of character because the class takes tamplate parameter to know what type of character to use,

    BUT I'm not sure about anything except char and wchar_t so you should try and test it yourself.

    Macros

    Name Value Definition
    X_BUFF_SIZE 64UL default size of the local buffer

    Exceptions

    Exception Definition
    std::length_error when the size of the string >= xeex::size_t_max
    std::out_of_range when the index of the string > size()

    Template Parameters

    Parameter Definition
    Type character type
    Alloc Allocator type used to allocate internal storage

    Member Types

    Type Definition
    chars xeerx::char_traits<Type>
    value_type Type
    size_type _traits::size_type xeerx::size_t
    reference _traits::reference Type&
    const_reference _traits::const_reference const Type&
    pointer _traits::pointer Type*
    const_pointer _traits::const_pointer const Type*
    iterator _traits::iterator Type*
    const_iterator _traits::const_iterator const Type*

    Member Functions

    • constructor's | destructor

      🔹 Examples 🔹

      // empty  constructor
      string s0;                          // 👉 ""
      // assign constructor using array of characters
      string s1("Hello");                 // 👉 "Hello"
      // assign constructor using single character 
      string s2('C');                     // 👉 "C"
      // assign constructor using range (iterators)
      string s3(s1.cbegin(), s1.cend());  // 👉 "Hello"
      // assign constructor using bool
      string s4(true);                    // 👉 "true"
      // assign constructor using integer (see convert function for more details)
      string s5(123);                     // 👉 "123"
      // assign constructor using float   (see convert function for more details)
      string s6(0.14);                    // 👉 "0.14"
      // copy constructor
      string s7(s1);                      // 👉 "Hello"
      // move constructor
      string s8(std::move(s1));           // 👉 "Hello"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 0.976 ns 689897792 ⚡️ 1.0 empty constructor
      🔸 std::string 0.978 ns 704357784
      🔹 xeerx::string 1.30 ns 531657012 ⚡️ 2.2 copy constructor
      🔸 std::string 2.93 ns 238350514
      🔹 xeerx::string 1.30 ns 532291700 ⚡️ 4.7 move constructor
      🔸 std::string 6.15 ns 110840133
      🔹 xeerx::string 1.30 ns 473253168 ⚡️ 1.7 array constructor
      🔸 std::string 2.26 ns 356990635
      🔹 xeerx::string 1.41 ns 427177908 ⚡️ 8.0 single char constructor
      🔸 std::string 11.3 ns 62462721
      🔹 xeerx::string 2.45 ns 292649634 ⚡️ 1.6 range constructor
      🔸 std::string 3.93 ns 186850707
      🔹 xeerx::string 1.97 ns 344396141 ⚡️ --- bool constructor
      🔸 std::string --- ns ---------
      🔹 xeerx::string 3.02 ns 234255879 ⚡️ 2.0 long int constructor
      🔸 std::string 6.31 ns 109529125
      🔹 xeerx::string 8.13 ns 84837465 ⚡️ 2.8 short int constructor
      🔸 std::string 22.9 ns 30325927
      🔹 xeerx::string 2.60 ns 267951182 ⚡️ 75.3 long float constructor
      🔸 std::string 196 ns 3535237
      🔹 xeerx::string 3.26 ns 214303767 ⚡️ 61.0 short float constructor
      🔸 std::string 199 ns 3511556

      🌟 std::to_string can't convert bool to string.

    • Copy | Move | Swap

      🔹 Examples 🔹

      string s("Hello World");
      
      string s1; s1.copy(s);              // 👉 "Hello World"
      string s2; s2.move(std::move(s));   // 👉 "Hello World"
      string s3; s3.swap(s);              // 👉 "Hello World"
      

      🔸 Benchmark 🔸

      no benchmark need in this section, you can see constructor section to find copy and move benchmark, as about swap is just std::swap.

    • Assign

      🔹 Examples 🔹

      string s;
      string s1("Another String");
      
      // assign using array of characters
      s.assign("Hello");                  // 👉 "Hello"
      // assign using single character 
      s.assign('C');                      // 👉 "C"
      // assign using range (iterators)
      s.assign(s1.cbegin(), s1.cend());   // 👉 "Another String"
      // assign using bool
      s.assign(true);                     // 👉 "true"
      // assign using integer (see convert function for more details)
      s.assign(123);                      // 👉 "123"
      // assign using float   (see convert function for more details)
      s.assign(0.14);                     // 👉 "0.14"
      // assign using another string
      s.assign(s1);                       // 👉 "Another String"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 1.34 ns 531380206 ⚡️ 2.2 assign using string
      🔸 std::string 2.93 ns 238106163
      🔹 xeerx::string 1.31 ns 528827390 ⚡️ 6.7 assign using array
      🔸 std::string 8.81 ns 78799728
      🔹 xeerx::string 1.31 ns 534289066 ⚡️ 8.6 assign using single char
      🔸 std::string 11.3 ns 61128346
      🔹 xeerx::string 2.28 ns 306184756 ⚡️ 4.3 assign using range
      🔸 std::string 9.90 ns 69530909
      🔹 xeerx::string 1.95 ns 357179984 ⚡️ --- assign using bool
      🔸 std::string --- ns ---------
      🔹 xeerx::string 9.09 ns 75920717 ⚡️ 2.0 assign using long int
      🔸 std::string 18.7 ns 37284998
      🔹 xeerx::string 3.54 ns 169905048 ⚡️ 1.0 assign using short int
      🔸 std::string 3.91 ns 195297191
      🔹 xeerx::string 3.59 ns 195349150 ⚡️ 56.5 assign using long float
      🔸 std::string 203 ns 3436025
      🔹 xeerx::string 2.61 ns 268187597 ⚡️ 76.6 assign using short float
      🔸 std::string 200 ns 3430881

      🌟 std::to_string can't convert bool to string.

    • Convert

      This function using xeerx::to_chars to convert

      So for more information see the conversion section

      🔹 Examples 🔹

      // integer
      string s1; s1.convert(123);                     // 👉 "123"
      // integer base
      string s2; s2.convert(123, 16);                 // 👉 "7b"
      // sign
      string s3; s3.convert(123, 16, '+');            // 👉 "+7b"
      // letter case
      string s4; s4.convert(123, 16, '+', tail, 1);   // 👉 "+7B"
      
      // float
      string s5; s5.convert(3.987);                   // 👉 "3.98"
      // float precision
      string s6; s6.convert(3.987, 3);                // 👉 "3.987"
      // float trailing zeros
      string s7; s7.convert(1.09800, 5, '+', 1);      // 👉 "+1.09800"
      string s8; s8.convert(1.09800, 5, '+', 0);      // 👉 "+1.098"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 2.49 ns 280885493 ⚡️ --- convert using bool
      🔸 std::string --- ns ---------
      🔹 xeerx::string 9.13 ns 75557257 ⚡️ 5.6 convert using long int
      🔸 std::string 52.0 ns 13533688
      🔹 xeerx::string 4.40 ns 163482392 ⚡️ 3.3 convert using short int
      🔸 std::string 14.8 ns 46670954
      🔹 xeerx::string 3.62 ns 195510099 ⚡️ 57.4 convert using long float
      🔸 std::string 208 ns 3371255
      🔹 xeerx::string 2.93 ns 238643277 ⚡️ 69.9 convert using short float
      🔸 std::string 205 ns 3402302

      🌟 std::to_string can't convert bool to string.

    • Append

      🔹 Examples 🔹

      string s;
      string s1("Another String");
      
      // append using array of characters
      s.append("Hello");                  // 👉 "Hello"
      // append using single character 
      s.append('C');                      // 👉 "...C"
      // append using range (iterators)
      s.append(s1.cbegin(), s1.cend());   // 👉 "...Another String"
      // append using bool
      s.append(true);                     // 👉 "...true"
      // append using integer (see convert function for more details)
      s.append(123);                      // 👉 "...123"
      // append using float   (see convert function for more details)
      s.append(0.14);                     // 👉 "...0.14"
      // append using another string
      s.append(s1);                       // 👉 "...Another String"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 45.0 ns 16190001 ⚡️ 2.2 append using string
      🔸 std::string 103 ns 6637803
      🔹 xeerx::string 38.2 ns 18203461 ⚡️ 2.5 append using array
      🔸 std::string 96.0 ns 7101166
      🔹 xeerx::string 21.0 ns 32952515 ⚡️ 2.2 append using single char
      🔸 std::string 46.8 ns 14844033
      🔹 xeerx::string 44.0 ns 15887083 ⚡️ 2.7 append using range
      🔸 std::string 122 ns 5548724
      🔹 xeerx::string 20.9 ns 34528601 ⚡️ --- append using bool
      🔸 std::string --- ns ---------
      🔹 xeerx::string 116 ns 5953486 ⚡️ 2.6 append using long int
      🔸 std::string 307 ns 2270919
      🔹 xeerx::string 75.4 ns 9182231 ⚡️ 1.0 append using short int
      🔸 std::string 80.4 ns 8533531
      🔹 xeerx::string 68.6 ns 9908682 ⚡️ 33.1 append using long float
      🔸 std::string 2253 ns 308565
      🔹 xeerx::string 30.3 ns 22941116 ⚡️ 74.4 append using short float
      🔸 std::string 2242 ns 314610

      🌟 std::to_string can't convert bool to string.

    • Insert

      🔹 Examples 🔹

      You can find the test script in /tests/insert-string.cpp to check it yourself.

      string s("15 : ");
      
      // insert using single character 
      s.insert(0, '0');                   // 👉 "015 : "
      // insert using array of characters
      s.insert(2, "234");                 // 👉 "012345 : "
      // insert using another string
      s.insert(s.size(), s);              // 👉 "012345 : 012345 : "
      // insert using range (iterators)
      string s1("Iterator");
      s.insert(s.size(), s1.cbegin(), s1.cend()); // 👉 "012345 : 012345 : Iterator"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 90.9 ns 7302295 ⚡️ 1.5 insert using string
      🔸 std::string 143 ns 4852644
      🔹 xeerx::string 92.3 ns 7438356 ⚡️ 1.3 insert using array
      🔸 std::string 124 ns 5604204
      🔹 xeerx::string 59.6 ns 11534530 ⚡️ 1.4 insert using single char
      🔸 std::string 83.2 ns 8121425
      🔹 xeerx::string 44.0 ns 7648863 ⚡️ --- insert using range
      🔸 std::string --- ns ---------

      🌟 there is no function to insert using range in std::string.

    • Fill

      🔹 Examples 🔹

      string s;
      
      // string is not initialized yet, so append `C` * 10 times
      s.fill('C', 0, 10);                // 👉 "CCCCCCCCCC"
      // string is initialized, so replace range(0,9) with `M`
      s.fill('M', 0, 10);                // 👉 "MMMMMMMMMM"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 13.9 ns 49118574 ⚡️ 2.6 fill using character
      🔸 std::string 37.0 ns 18117575

      🌟 there is no function to fill in std::string, so i used replace in benchmark.

    • Replace

      🔹 Examples 🔹

      // length of "AB" = 2, length of range to replace is (6-4) = 2
      // so replace "45" with "AB"
      string s1("0123456789"); 
      s1.replace("AB", 4, 6);             // 👉 "0123AB6789"
      
      // length of "A" = 1, length of range to replace is (6-4) = 2
      // so replace "4" with "A"
      // and move "6789" to backward by one.
      // in another word, replace "45" with "A"
      string s2("0123456789"); 
      s2.replace("A", 4, 6);              // 👉 "0123A6789"
      
      // length of "HelloWorld" = 10, length of range to replace is (6-4) = 2
      // so move "6789" to forward by (10 - 2) = 8.
      // and replace "45        " with "HelloWorld"
      // in another word, replace "45" with "HelloWorld"
      string s3("0123456789"); 
      s3.replace("HelloWorld", 4, 6);     // 👉 "0123HelloWorld6789"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 35.5 ns 19680601 ⚡️ 1.3 replace using array
      🔸 std::string 46.5 ns 15060716
    • Erase

      🔹 Examples 🔹

      string s("0123456789"); s.erase(4, 2);  // 👉 "01236789"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 9.36 ns 74738109 ⚡️ 2.2 erase part of string
      🔸 std::string 21.2 ns 32678576
    • Clear

      🔹 Examples 🔹

      string s("0123456789"); s.clear();     // 👉 ""
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 1.30 ns 536039461 ⚡️ 12.6 clear string contents
      🔸 std::string 16.4 ns 40010757
    • Resize

      🔹 Examples 🔹

      string s("0123456789"); s.resize(5);    // 👉 "01234"
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 2.86 ns 267733338 ⚡️ 6.3 resize string size
      🔸 std::string 18.2 ns 36673351
    • Reserve

      🔹 Examples 🔹

      string s; s.reserve(100);               // 👉 heap capacity now is 100
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 16.1 ns 44328723 ⚡️ 2.1 reserve space in the heap
      🔸 std::string 35.3 ns 19861444
    • Compare

      🔹 Examples 🔹

      string s("Hello");  
      
      s.compare("Hello");                     // 👉 0
      s.compare("hello");                     // 👉 -32
      s.compare("Blah" );                     // 👉 6
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 1.63 ns 425109330 ⚡️ 1.2 compare two strings
      🔸 std::string 1.97 ns 354517169
    • Find

      🔹 Examples 🔹

      string s("12 13 12 14"); 
      
      // find using array
      s.find("12", 0);                        // 👉 0
      s.find("12", 2);                        // 👉 6
      
      // find using character
      s.find('3' , 0);                        // 👉 4
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::string 1.30 ns 519393604 ⚡️ 12.8 find using array
      🔸 std::string 16.7 ns 41623313
      🔹 xeerx::string 1.30 ns 532126470 ⚡️ 12.7 find using character
      🔸 std::string 16.6 ns 41633714
    • Letter Case Control

      🔹 Examples 🔹

      string s("hello World s S 123"); 
      
      // all to upper case
      s.upper();                        // 👉 "HELLO WORLD S S 123"
      // all to lower case
      s.lower();                        // 👉 "hello world s s 123"
      // make all words start with upper case character
      s.wupper();                       // 👉 "Hello World s S 123"
      
    • Access Functions

      🔹 Read-Only 🔹

      string.cdata();        // Buffer of characters
      string.cbegin();       // Begin iterator
      string.cend();         // End   iterator
      string.size();         // Size of buffer
      string.max_size();     // Maximum size that can be accommodated
      string.capacity();     // Capacity of buffer
      string.empty();        // Check if size == 0
      string.cat(N);         // Get character at position
      

      🔹 Read-Write 🔹

      string.data();        // Buffer of characters
      string.begin();       // Begin iterator
      string.end();         // End   iterator
      string.at(N);         // Get character at position
      

      🔸 Benchmark 🔸

      no benchmark need in this section, all of this functions just return to the private variables.

    • Operatores

      🔹 copy-move 🔹

      string A("Hello"), B;
      B = A;            // copy
      B = std::move(B); // move
      

      🔹 assign 🔹

      string S;
      S = "Hello";
      S = 123;
      S = ...; // same as assign()
      

      🔹 append 🔹

      string S;
      S += "Hello";
      S += 123;
      S += ...; // same as append()        
      

      🔹 append plus 🔹[The Power Of The Append]

      string A("-> "), S;
      S += A + false + " 123" + 456 + ' ' + 3.14; // 👉 "-> false 123456 3.14"
      // [NOTE] A will be also "-> false 123456 3.14"
      // because the data append to A first, than to S
      // so you must use a temporary string in the first argument
      
      // What if i want to add S1 and S2 to S3 without change S1 and S2 ?
      string S1("Hello"), S2("World"), S3;
      S3 = S1; S3 += S2;     // like this
      S3 += string(S1) + S2; // or   this
      

      🔹 compare 🔹

      string S1("Hello"), S2("World");
      bool is_same = (S1 == S2);    
      

      🔹 at 🔹

      string S1("Hello");
      S1[0] = 'h';  
      

      🔹 stream 🔹

      string S1("Hello");
      std::cout << S1 << std::endl;
      

      🔸 Benchmark 🔸

      no benchmark need in this section, operators do same of it's function, for example += call append, ..etc.

  • Conversions

    • convert numbers to characters array

      🔹 Examples 🔹

      char c[11] = "N:xxxxxxxx";          // can be wchar_t or type of characters
      
      // manual length (overload with 'last' as a parameter)
      to_chars(c, c + sizeof(c), -10);    // c 👉 "-10" 
      
      // auto length   (overload with 'last' as a template parameter)
      to_chars(c,-10);                    // c 👉 "-10" 
      
      // [integer base] you can use any base between 2 and 36
      to_chars(c,-123, 36);               // c 👉 "-3f"
      to_chars(c,-123, 16);               // c 👉 "-7b"
      to_chars(c,-123, 10);               // c 👉 "-123"
      to_chars(c,-123,  8);               // c 👉 "-173" 
      to_chars(c,-123,  2);               // c 👉 "-1111011"
      
      // [sign]
      to_chars(c, 1, 10, '+');            // c 👉 "+1"
      to_chars(c,-1, 10, '+');            // c 👉 "-1"
      
      to_chars(c, 1, 10, '-');            // c 👉  "1"
      to_chars(c,-1, 10, '-');            // c 👉 "-1"
      
      to_chars(c, 1, 10, ' ');            // c 👉 " 1"
      to_chars(c,-1, 10, ' ');            // c 👉 "-1"
      
      // [terminate array]
      to_chars(c, 1, 10, '+', 1);         // c 👉 "+1"
      to_chars(c, 1, 10, '+', 0);         // c 👉 "+1xxxxxxxx"
      
      // [floating precision]
      float f = -1.09800;
      to_chars(c,f);                      // c 👉 "-1.09" 
      to_chars(c,f,  1);                  // c 👉 "-1.0" 
      to_chars(c,f,  2);                  // c 👉 "-1.09" 
      to_chars(c,f,  3);                  // c 👉 "-1.098" 
      to_chars(c,f,  4);                  // c 👉 "-1.0980" 
      
      // [trailing zeros]
      to_chars(c,f,  5, '+', 1, 0);       // c 👉 "-1.098" 
      to_chars(c,f,  5, '+', 1, 1);       // c 👉 "-1.09800"
      
      // [trailing zeros]
      to_chars(c,f,  5, '+', 1, 0);       // c 👉 "-1.098" 
      to_chars(c,f,  5, '+', 1, 1);       // c 👉 "-1.09800"
      
      // [letter case]
      to_chars(c,-123, 36, '+', 1, 1, 1); // c 👉 "-3F"
      to_chars(c,-123, 36, '+', 1, 1, 0); // c 👉 "-3f"
      
      // [length] if you know the length of the integer part, so put it in last argument
      to_chars(c,-123, 36, '+', 1, 1, 3); // c 👉 "-3F"
      
      // [return | exception]
      // 🟩 if successed return to last written position 
      // 🟥 if failed    return to xeerx::size_t_max
      // 🟧 if X_DEBUG macro is defined, when failed will throw an exceptionx
      

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed Type
      🔹 xeerx::to_chars 0.333 ns 1000000000 ⚡️243.8 long float
      🔸 std::to_chars 81.2 ns 8665522
      🔹 xeerx::to_chars 0.327 ns 1000000000 ⚡️177.6 short float
      🔸 std::to_chars 58.1 ns 12034705
      🔹 xeerx::to_chars 0.327 ns 1000000000 ⚡️ 3.9 long int
      🔸 std::to_chars 1.30 ns 531564683
      🔹 xeerx::to_chars 0.326 ns 1000000000 ⚡️ 2.0 short int
      🔸 std::to_chars 0.652 ns 1000000000
    • convert characters array to numbers

      🔹 Examples 🔹

    chars_to<int>("-123");   // 👉 -123
    
    // [integer base] you can use any base between 2 and 36
    chars_to<int>("-3F",       36);     // 👉 -123
    chars_to<int>("-7B",       16);     // 👉 -123
    chars_to<int>("-123",      10);     // 👉 -123
    chars_to<int>("-173",       8);     // 👉 -123
    chars_to<int>("-1111011",   2);     // 👉 -123
    
    // [floating precision]
    chars_to<double>("-1.0098765");     // 👉 -1.00
    chars_to<double>("-1.0098765",  1); // 👉 -1.0
    chars_to<double>("-1.0098765",  2); // 👉 -1.00
    chars_to<double>("-1.0098765",  3); // 👉 -1.009
    chars_to<double>("-1.0098765",  4); // 👉 -1.0098
    chars_to<double>("-1.0098765",  5); // 👉 -1.00986
    chars_to<double>("-1.0098765",  6); // 👉 -1.009865
    
    // [return | exception]
    // 🟩 if successed return to converted value
    // 🟥 if failed    return to std::numeric_limits::max<N>()
    // 🟧 if X_DEBUG macro is defined, when failed will throw an exceptionx
    

    🔸 Benchmark 🔸

    Benchmark Time Iterations Speed Type
    🔹 xeerx::chars_to 0.327 ns 1000000000 ⚡️ 88.6 long float
    🔸 std::from_chars 29.0 ns 24078935
    🔹 xeerx::chars_to 0.327 ns 1000000000 ⚡️ 1.6 short float
    🔸 std::from_chars 0.545 ns 1000000000
    🔹 xeerx::chars_to 0.327 ns 1000000000 ⚡️ 4.0 long int
    🔸 std::from_chars 1.31 ns 533874680
    🔹 xeerx::chars_to 0.328 ns 1000000000 ⚡️ 1.9 short int
    🔸 std::from_chars 0.652 ns 1000000000
  • Time

    • units

      all units using std::chrono

      second;
      milliseconds;
      microseconds;
      nanoseconds;
      
    • timestamp

      timestamp<unit>();           // auto
      timestamp<unit>(1664697587); // manual
      
      // members
      val; // timestamp value
      fac; // factor (second = 1, mirosecond = 1000, ...)
      
    • main time class

      // auto
      time<second>      t; // timestamp 👉 1664697587          , fac 👉 1
      time<millisecond> t; // timestamp 👉 1664697587405       , fac 👉 1000
      time<microsecond> t; // timestamp 👉 1664697587405492    , fac 👉 1000000
      time<nanosecond>  t; // timestamp 👉 1664697587405492704 , fac 👉 1000000000
      
      // manual
      time<second>   t(1664697587); // timestamp -> 1664697587 , fac -> 1
      
      // specification characters type
      time<unit, char_type> t;    // char_type by default is `char`
      
      // for string format use it
      stime<unit, char_type> t;  
      // this will containts same members of normal `time` class
      // in addition to the string members
      
      • numerical members

        t.unit;        // xeerx::timestamp object
        t.unit.val;    // timestamp of unit : 👉 1664697587405492704
        t.unit.fac;    // factor    of unit : 👉 1000000000
        t.year;        // 👉 2022
        t.month;       // 👉 10
        t.week;        // 👉 1
        t.weekday;     // 👉 2
        t.day;         // 👉 2
        t.yday;        // 👉 275
        t.hour;        // 👉 7
        t.Hour;        // 👉 7
        t.minute;      // 👉 59
        t.second;      // 👉 47
        t.millisecond; // 👉 405
        t.microsecond; // 👉 492
        t.nanosecond;  // 👉 704
        
      • string members

        to get time members in string format you should using stimg instead of time.

        t.num;          // xeerx::time object, use it to access the numerical members
        
        t.syear;        // 👉 "2022" 
        t.smonth;       // 👉 "10" 
        t.sweek;        // 👉 "01" 
        t.sweekday;     // 👉 "02" 
        t.sday;         // 👉 "02" 
        
        t.shour;        // 👉 "07"
        t.sHour;        // 👉 "07"
        t.sminute;      // 👉 "59"
        t.ssecond;      // 👉 "47"
        
        t.smillisecond; // 👉 "405"
        t.smicrosecond; // 👉 "492"
        t.snanosecond ; // 👉 "704"
        
        t.m;            // 👉 "AM"
        
        // names
        t.nweekday;     // 👉 "Sun"
        t.Nweekday;     // 👉 "Sunday"
        
        t.nmonth;       // 👉 "Oct"
        t.Nmonth;       // 👉 "October"
        
      • convert between time and stime

        // stime -> time
        time<nanosecond>  t  = stime<nanosecond>;       // ERROR
        time<nanosecond>  t  = stime<nanosecond>().num; // OK
        
        // time  -> stime
        stime<nanosecond> st = time<nanosecond>;        // OK
        

      🔸 Benchmark 🔸

      Benchmark Time Iterations Speed
      🔹 xeerx::time 13.2 ns 51969561 ⚡️ 200.7
      🔹 xeerx::stime 29.4 ns 24039762 ⚡️ 90.1
      🔸 local_time 2430 ns 293162
      🔸 to_time_t 2844 ns 234573
      🔸 asctime 2847 ns 250791
  • Formatting

    • Pattern

      • prototype

        // prototype
        // N -> How many sections are there in this pattern [for optimization]
        // C -> Type of character
        fpattern<N, C = char> ("...");
        
      • arguments

        // sequence argument
        fpattern<1>("{}");
        
        // numbered argument
        fpattern<1>("{I}");
        
        // mix of sequence and numbered argument
        fpattern<4>("{1} {} {0} {}");
        // [1] -> second "{1}"  - (no effect on the last argument id)
        // [2] -> first  "{}"   (last argument id is 0, and will be 1)
        // [3] -> first  "{0}"  - (no effect on the last argument id)
        // [4] -> second "{}"   (last argument id is 1, and will be 2)
        
        // control arguments
        fpattern<1>("{:}" || "{I:}");  // wrtie ':' to manage the argument
        
        // control integer base | float precision
        fpattern<1>("{:N}" || "{I:N}");
        // for integer, 'N' can be any number between 2 and 36 (default is 10)
        // for float  , 'N' can be any number between 1 and 36 (default is  2)
        
        // control letter case (Without specifying case, it will be left as is)
        // [NOTE] letter case contoller works only on integer's 
        //        when base numerical base > 10
        fpattern<1>("{:NC}" || "{I:NC}");  // for all capital
        fpattern<1>("{:Nc}" || "{I:Nc}");  // for all small
        
        // control sign (see conversion section to know more about sign's)
        fpattern<1>("{:SN}" || "{I:SN}");
        
        // the final pattern
        fpattern<1>("{:SNC}" || "{I:SNC}");
        // { -> begin of section (Necessary)
        // I -> argument id      (Not Necessary)
        // : -> controller       (Necessary IF you will manage the argument)
        // S -> sign             (Not Necessary)
        // N -> base | precision (Not Necessary)
        // C -> letter case      (Not Necessary)
        // } -> end of section   (Necessary)
        
        /* ------------ Exceptions ------------ */
        // std::invalid_argument("bad syntax")
        // [-] you must write one or more specifier at least after the controller `:`
        // [-] you must write the begin '{' and the end '}' of the section 
        //     without any-unknown character between it
        //     the known characters is "I:SNC"
        
        // std::out_of_range("invalid argument id")
        // [-] 'I' can not be larger than the template parameter 'N'
        
      • padding

        // prototype
        fpattern<1>("{.AFV.}");
        
        // {. -> begin of padding section       (Necessary)
        // A  -> padding align  ['<', '>', '^'] (Not Necessary) (default is left '<')
        // F  -> padding fill   [any char]      (Necessary)
        // V  -> padding value  [any numbers]   (Necessary)
        // .} -> end   of padding section       (Necessary)
        
        // dynamic padding (with argument's and text inside it)
        fpattern<4>("{.^ 15IP:{}.},{.^ 15PORT:{}.}");
        // IF IP is "127.0.0.1" && PORT is 443, so the result will be like it:
        // --> "IP:127.0.0.1   ,PORT:443       "
        
        // normal padding (without anything inside it)
        fpattern<2>("{.*5.} IP:{}");
        // --> "***** IP:127.0.0.1"
        
      • Examples

        xeerx::format<N> returns to xeerx::basic_string<char>

        xeerx::format<C, N> returns to xeerx::basic_string<C>

        // sequence arguments   👉 "Hello World"
        format<2>("{} {}", "Hello", "World");
        
        // numbered arguments   👉 "World Hello, Hello World"
        format<4>("{1} {0}, {0} {1}", "Hello", "World");
        
        // character            👉 "C, C"
        format<2>("{}, {}", 'C', 'c'); 
        
        // bool                 👉 "true, false"
        format<2>("{}, {}", true, false);                   
        
        // integer              👉 "123"
        format<1>("{}", 123);
        
        // integer base         👉 "d:123, x:7b, o:173, b:1111011, 36:3f"
        format<5>("d:{0:10}, x:{0:16}, o:{0:8}, b:{0:2}, 36:{0:36}", 123);  
        
        // letter case          👉 "Capital:3F, Small:3f"
        format<2>("Capital:{0:36C}, Small:{0:36c}", 123);
        
        // float                👉 "3.14"
        format<1>("{}", 3.14);
        
        // float precision      👉 "3.01, 3.014, 3.0143"
        format<3>("{0:2}, {0:3}, {0:4}", 3.014321);
        
        // sign                 👉 "+:[+1, 1,  1], -:[-1, -1, -1]"
        format<6>("+:[{0:+10}, {0:-10}, {0: 10}], -:[{1:+10}, {1:-10}, {1: 10}]",  1, -1); 
        
        // multi types          👉 "string, C, true, -123, 3.14"
        format<5>("{}, {}, {}, {}, {}", "string", 'C', true, -123, 3.14);
        

        padding examples

        // empty padding        👉 "**********, true"
        format<2>("{.*10.}, {}", true);
        
        // left   aligned       👉 "******true"
        format<2>("{.<*10{}.}", true);
        
        // right  aligned       👉 "true******"
        format<2>("{.>*10{}.}", true);
        
        // center aligned       👉 "***true***"
        format<2>("{.^*10{}.}", true);
        
        // another example      👉 "[IP:127.0.0.1    ] [PORT:443        ]"
        format<4>("[{.> 15IP:{}.}] [{.> 15PORT:{}.}]", "127.0.0.1", 443);
        

    🔸 Benchmark 🔸

    Benchmark Time Iterations Speed Type
    🔹 xeerx::format 3.70 ns 186586391 ⚡️ 52.9 left padding
    🔸 fmt::format 196 ns 3545286
    🔹 xeerx::format 3.70 ns 189126228 ⚡️ 54.3 right padding
    🔸 fmt::format 201 ns 3464272
    🔹 xeerx::format 3.70 ns 188942568 ⚡️ 57.0 center padding
    🔸 fmt::format 211 ns 3304297
    🔹 xeerx::format 2.69 ns 258969920 ⚡️ 9.9 one string
    🔸 fmt::format 26.7 ns 26305344
    🔹 xeerx::format 16.5 ns 42150231 ⚡️ 4.0 two strings
    🔸 fmt::format 66.7 ns 10376705
    🔹 xeerx::format 77.8 ns 8581737 ⚡️ 2.2 a lot strings
    🔸 fmt::format 174 ns 4061439
    🔹 xeerx::format 2.69 ns 259762850 ⚡️ 14.3 signle character
    🔸 fmt::format 38.6 ns 18119202
    🔹 xeerx::format 10.8 ns 64446743 ⚡️ 5.3 bool
    🔸 fmt::format 57.6 ns 11925818
    🔹 xeerx::format 2.02 ns 346543561 ⚡️ 10.0 short int
    🔸 fmt::format 20.1 ns 34644407
    🔹 xeerx::format 3.02 ns 231357308 ⚡️ 17.4 long int
    🔸 fmt::format 52.4 ns 13166775
    🔹 xeerx::format 2.69 ns 252905827 ⚡️ 29.4 float
    🔸 fmt::format 78.6 ns 9923260
    • Optimization with constexpr fpattern

      it will be faster by near 30% in long and complicated patterns

      constexpr fpattern<N> pat("...");
      // then you can pass it to format function like:
      format<N>(pat, ...);
      
  • Exceptions

    0. void test()
    1. {
    2.      x_throw(exceptions::out_of_range);
    3. }
    
    // output:
    // xeerx::exception::out_of_range
    // [FILE] /path/to/file.ext [LINE] 2 [FUNC] test 
    
```cpp
0. void test()
1. {    int pos = 21, size = 20;
2.      x_throws(exceptions::out_of_range, format<2>("pos:{} >= size:{}", pos, size));
3. }

// output:
// xeerx::exception::out_of_range
// [FILE] /path/to/file.ext [LINE] 2 [FUNC] test : pos:21 >= size:20
```

Benchmark Info

  • compiler: GCC 12
  • c++ version: 20
  • operator system: Ubuntu 22.04.1 LTS
  • processor: Intel® Core™ i7-6500U CPU @ 2.50GHz × 4
  • flags: -Ofast

Source Code

you can find the source code on Github

because the source code is big and has a lot script's

so i can't put it here.

This Post Was Published In Version 0.0.1

Updates

..

Hope I made something useful

This version is still a beta version and I have not finished fully developing the library

So I would like to know your opinion about this

  • Are there problems ?

  • Is there anything that can be developed or added?

  • Did I do anything wrong?

Thanks.


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Maysara


Print Share Comment Cite Upload Translate Updates
APA

Maysara | Sciencx (2022-10-06T03:27:49+00:00) Much Faster than std::string, fmt::format, std::to_chars, std::time and more?. Retrieved from https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/

MLA
" » Much Faster than std::string, fmt::format, std::to_chars, std::time and more?." Maysara | Sciencx - Thursday October 6, 2022, https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/
HARVARD
Maysara | Sciencx Thursday October 6, 2022 » Much Faster than std::string, fmt::format, std::to_chars, std::time and more?., viewed ,<https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/>
VANCOUVER
Maysara | Sciencx - » Much Faster than std::string, fmt::format, std::to_chars, std::time and more?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/
CHICAGO
" » Much Faster than std::string, fmt::format, std::to_chars, std::time and more?." Maysara | Sciencx - Accessed . https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/
IEEE
" » Much Faster than std::string, fmt::format, std::to_chars, std::time and more?." Maysara | Sciencx [Online]. Available: https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/. [Accessed: ]
rf:citation
» Much Faster than std::string, fmt::format, std::to_chars, std::time and more? | Maysara | Sciencx | https://www.scien.cx/2022/10/06/much-faster-than-stdstring-fmtformat-stdto_chars-stdtime-and-more/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.