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 char
numbers
time
bool
..etc.
🔹🔹 you will find
test
,gtest
andbenchmark
for 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_view
so there is no copies, just like normalconst char*
-
Second Example
1- pointing to the value
Hello
2- copy
Hello
to thestack buffer
3- copy
World
to the end ofstack buffer
to beHelloWorld
-
Third Example
1- pointing to the value
chars:
2- copy
chars:
to thestack buffer
now we need to append
C
x100 times, and ourstack buffer
size is64
and the current size of the buffer is6
(chars:
is6
characters)
so the stack can hold more64 - 6 = 58
characters3- copy
C
58 times
to the end ofstack buffer
now the
stack buffer
is full and we need to append more42
characters
so allocate an enough space in the heap memory calledheap buffer
4- allocate a space in the heap memory
5- copy contents of
stack buffer
to theheap buffer
6- append the rest
42
characters 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,
char
andwchar_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
andwchar_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 findcopy
andmove
benchmark, as aboutswap
is 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_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 usedreplace
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
+=
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
stimg
instead 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
time
andstime
// 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 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
![](https://www.radiofree.org/wp-content/plugins/print-app/icon.jpg)
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.