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 byGoogle Benchmark.🍃 Light - minimum lines of code, quick compiling, tested by
GCC 12.✨ optimization - improved behavior to reduce
Memory Allocation, tested byValgrind.🌟 Ability - works with a lot of data types
any charnumberstimebool..etc.
🔹🔹 you will find
test,gtestandbenchmarkfor everything in:tests/🔹🔹
Index
The library contains:
- xeerx::string fastest string class.
- xeerx::to_chars, chars_to fastest numbers-strings conversion functions.
- xeerx::time, xeerx::stime fastest time classes.
- xeerx::format fastest formatting function.
- xeerx::exception to throw an exception with information about it.
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_viewso there is no copies, just like normalconst char* -
Second Example
1- pointing to the value
Hello2- copy
Helloto thestack buffer3- copy
Worldto the end ofstack bufferto beHelloWorld -
Third Example
1- pointing to the value
chars:2- copy
chars:to thestack buffernow we need to append
Cx100 times, and ourstack buffersize is64
and the current size of the buffer is6(chars:is6characters)
so the stack can hold more64 - 6 = 58characters3- copy
C58 timesto the end ofstack buffernow the
stack bufferis full and we need to append more42characters
so allocate an enough space in the heap memory calledheap buffer4- allocate a space in the heap memory
5- copy contents of
stack bufferto theheap buffer6- append the rest
42characters to the end of theheap 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,
charandwchar_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
charandwchar_tso you should try and test it yourself.Macros
Name Value Definition X_BUFF_SIZE64UL default size of the local buffer Exceptions
Exception Definition std::length_errorwhen the size of the string >= xeex::size_t_maxstd::out_of_rangewhen 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 Typesize_type _traits::size_type xeerx::size_treference _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_stringcan'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
constructorsection to findcopyandmovebenchmark, as aboutswapis juststd::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_stringcan't convert bool to string. -
Convert
This function using
xeerx::to_charsto 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_stringcan'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_stringcan't convert bool to string. -
Insert
🔹 Examples 🔹
You can find the test script in
/tests/insert-string.cppto 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 usedreplacein 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
+=callappend, ..etc.
- ### First Example
In this case the class will just pointing to the value, like
-
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
stimginstead oftime.
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
timeandstime
// 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 toxeerx::basic_string<char>xeerx::format<C, N>returns toxeerx::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 fpatternit 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
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/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.