option
This commit refactors string_stream and string_streamx into a common
basic_string_stream template class. When the EXT template == true, the
string_streamx formatting options are enabled, they default to disabled.
These options are enabled at compile time, and do not affect performance
when they are disabled. By implementing the two streams in this manner,
duplicated code is removed.
This commit also adds the ENDL template paramter. When ENDL is set to
zero, no endline character is printed when piping mtl::endl. Otherwise,
the character is printed. Defaults to '\n'. This allows logging on the
GBA to handle mtl::endl correctly and not print two newlines on the MGBA
emulator.
Both assembly macros failed when given large numbers ending in 9. For
example, udiv100000 of 3999999999 produced 40000 instead of 39999.
Similarly, udiv1000000000 of 3999999999 produced 4 instead of 3.
Both of the previous implementations failed the Granlund-Montgomery
integer division algorithm. This commit replaces these macros with the
correct implementation generated by clang for a constant integer
division. I do not understand how this implementation works. All other
macros do pass the Granlund-Montgomery algorithm.
string_streamx is a string_stream with additional formatting options.
Currently the only extra option is the ability to expand strings to a
length using a fill character, along with left/right justification. More
options similar to std::stringstream may be added in the future. These
extra options do come at a performance cost, and string_stream should be
preferred unless the extra options are absolutely needed.
This implementation also writes the digits from left to right instead of
right to left. Using this method we can write the string to the
beginning of the buffer and still avoid reversing the string. It also
has the benefit of being slightly slower than the previous
implementation. The function's signature changed as well because there
is no longer a reason to pass the buffer size or a pointer to output the
start of the string.
Can't use std::exception because it dynamically allocates memory. This
implementation doesn't allocate memory, but also doesn't allow leaving
an exception message.
The istring and string_view operators have identical implementations. By
changing the istring operators to cast to string_view and use that
implementation instead, the number of redundant implementations is
reduced. This does incurr a small performance penalty, around 15 cycles
when tested on the MGBA Gameboy Advance emulator (uses an armv7tdmi).
When compared to the time operations take, the performance difference is
negligible. Ex. An insertion with two 8 character strings takes around
450 cycles.