so I rewrote snprintf! I figured it was cleaner to keep it outside the UString class for now.
i think we should move towards replacing the existing snprintf implementations in UString with this one. It is much faster (doing a lot of work at compile time) + extendable + much less code.
it processes the format string at compile time, and constructs an interleaved stream of compile time format strings and run time function calls on the parameters to gather byte buffers + lengths, deduced by type. Basically at runtime all that happens is a pre-organized series of memcpys.
this also allows for specialization for any class. see static void snprintf_specialization(Lambda&& lambda, LengthSurplusPackage<T>& t)
I used the python syntax.
And as we grow the implementation we can add additional format specialization in between the brackets, for example something like {3}when passed an integral would only print the first 3 digits. Refer again to the LengthSurplusPackage example to see how we can package these specialized requirements into the generated stream at compile time.
ALSO
now snprintf calculates the length of the format + all parameters, and grows the target UString is necessary to accommodate any needed new capacity. So no more runtime crashes because the buffer gets maxed out.
also, calculating the length as above allowed me to fix the snprintf_pos implementation to the way I had assumed it worked. aka... if I want to print the formatted string in at position 15, it now shifts over any bytes to make space for the new input.
and then I rebuilt the Redis RESP encoder on top of the new snprintf. And as you can see, this implementation now allows for any abstract protocol translation over top snprintf.
TL;DR
(code time)
UCompileTimeStringFormatter::snprintf<"HSET {{}}.cache firstname {}"_ctv>(token, firstname);
(compile time)"HSET {"_ctv, token, "}.cache firstname "_ctv, firstname
(run time)"HSET {a}.cache firstname Victor"
so I rewrote snprintf! I figured it was cleaner to keep it outside the UString class for now.
i think we should move towards replacing the existing snprintf implementations in UString with this one. It is much faster (doing a lot of work at compile time) + extendable + much less code.
it processes the format string at compile time, and constructs an interleaved stream of compile time format strings and run time function calls on the parameters to gather byte buffers + lengths, deduced by type. Basically at runtime all that happens is a pre-organized series of
memcpy
s.this also allows for specialization for any class. see
static void snprintf_specialization(Lambda&& lambda, LengthSurplusPackage<T>& t)
I used the python syntax.
And as we grow the implementation we can add additional format specialization in between the brackets, for example something like
{3}
when passed an integral would only print the first 3 digits. Refer again to theLengthSurplusPackage
example to see how we can package these specialized requirements into the generated stream at compile time.ALSO
now
snprintf
calculates the length of the format + all parameters, and grows the target UString is necessary to accommodate any needed new capacity. So no more runtime crashes because the buffer gets maxed out.also, calculating the length as above allowed me to fix the snprintf_pos implementation to the way I had assumed it worked. aka... if I want to print the formatted string in at position 15, it now shifts over any bytes to make space for the new input.
and then I rebuilt the Redis RESP encoder on top of the new snprintf. And as you can see, this implementation now allows for any abstract protocol translation over top snprintf.
example program