seanmiddleditch / nanofmt Goto Github PK
View Code? Open in Web Editor NEWCut down and minimalistic C++ string formatting library
Home Page: https://nanofmt.readthedocs.io/
License: MIT License
Cut down and minimalistic C++ string formatting library
Home Page: https://nanofmt.readthedocs.io/
License: MIT License
Use via add_subdirectory
should build nicely and not introduce oddities like tests.
Currently, a malformed format spec, out of range argument, or other runtime problem just silently terminates formatting and returns.
Design a "proper" error handling solution.
Exceptions would not fit the target userbase. Possible options include:
terminate
(with macro to replace call with custom termination handler?)char*
Alignment and fill are only supported for string types, currently. Investigate the cost of implementing them for other built-in types.
Functions like format_to_n
should not NUL-terminate, ensure documentation is correct.
All versions of format_to
should NUL-terminate.
If we add other functions, like #28, ensure those NUL-terminate unless there's a darn good reason not to.
The name could be confused with an owning buffer.
And an owning buffer would actually be a cheap and handy thing to include in nanofmt.
Consider:
format_context
- name used in fmtlib/std::format
, but may be confusing since our interface would be differentformat_output
- seems direct and semi-clearformat_target
- less clear, but maybe not as easily confused with output iterators?format_dest
- would be consistent with use of dest
as the variable name, I guessAdd the ability to compile in C++14 mode.
This mostly just means replacing use of if constexpr
, likely only in C++14 builds given the cost of SFINAE overloads.
Support alternate form flag.
Currently there are too many formatter specializations, some being esoteric.
They can be emulated by user code that needs them almost trivially.
A very light-weight dynamic buffer could be implemented with minimal overhead on the current model.
The current model uses a char*
and size_t
pair. Ultimately all we really need to support dynamic buffers would be a single function/callback invoked on overflow, along with the ability to update the char*
/size_t
.
format_output
is close to the only use of member functions in nanofmt.
Consider migrating to free-functions instead.
Allow configuring the nanofmt
namespace via a macro or other facility.
Test case:
nanofmt
namespace with my_custom
namespace.All format functions take an unconstrained template parameter for the format string.
This makes the API a bit more finicky and tool-unfriendly than desired.
Constraining the template (especially with SFINAE) doesn't help tools at all, and goes against some of the project's goals.
Refactor to use a specific format_string
type or the like, with automatic conversion from other string types.
This might be the only place we use our string_view
, too. Confirm and, if it is, nuke it.
nanofmt::format_to_n(buf, size, "{:.2f}", 0.9999);
produces "0.99" instead of "1.00". The problem is in charconv: the calls to to_chars_n_round
don't consider if we've rounded the last digit to zero.
Run some quality benchmarks comparing the compilation speed when using snprintf
, fmtlib, and nanofmt.
Investigate using the benchmark tools at https://github.com/fmtlib/format-benchmark for this task.
Requirements:
The fmtlib/std::format
interface has one very unfortunate design issue where the format_to_n
requires a pointer and length.
This means that you can't easily chain these calls together, as you must adjust both pointer and length on every call.
An improved interface takes an end-pointer instead of a length, so the return value of the format calls can be chained together.
Fitting this into the existing APIs without introducing weird overload shenanigans would be painful, though. Just adding/changing a format_to_n(char* dest, char* end, ...)
overload could cause confusion/bugs on where the format_string
argument comes in. (One option may be to make format_string
not implicitly convert from char*
?). Better may be a new function, e.g. something like format_append_to(char* dest, char* end, format_string, ...)
.
format_to_n
also doesn't NUL-terminate, but any format_append_to
should NUL-terminate, so overloading that name is likely a very bad idea.
Not terribly fond of having so many functions, though. I'd rather we trim down function names and overloads, not expand things further.
I'm trying to make print() function with nanofmt but format_length returns incorrect value.
string I'm trying to format is: ("{0} = 0x{0:X} = 0b{0:b}\n", 28) which is 11 characters if we remove {}s.
format_length returns 11 too but it should be 20
so instead of "28 = 0x1C = 0b11100\n" it prints "28 = 0x1C ="
template<typename ...Args>
auto print(nanofmt::format_string fmt, Args &&...args) -> size_t
{
size_t length = nanofmt::format_length(fmt, std::forward<Args>(args)...);
auto buffer = std::make_unique<char[]>(length + 1);
auto end = nanofmt::format_to_n(buffer.get(), length, fmt, std::forward<Args>(args)...);
buffer[end - buffer.get()] = 0;
puts(buffer.get());
return length;
}
/* ... */
print("{0} = 0x{0:X} = 0b{0:b}\n", length);
Btw idk why but if I do this it works fine:
print("{}, {} from {}!\n", "Hello"s, "World"sv, "kernelv2");
Function that does the equivalent of format_to(dest, "{}", value)
but allows passing the format specification as a string.
More accurately, it would do:
formatter<T> fmt;
fmt.parse(spec);
fmt.format(dst);
The vformat internals instantiate formatter for all built-in types. It could instead directly call formatting functions for each.
Enable configuring nanofmt to use name prefixes instead of C++ namespaces.
Test case:
custom_
prefix instead of nanofmt::
namespace.Add a C++20 module interface to nanofmt. This should not just be a header module unit.
Success:
Ensure everything installs properly as a CMake package.
Target users have indicated they'd never want to pay the "cost" of keeping these in headers.
Can revisit adding constexpr
support with Modules builds.
The behavior of formatting to a format_buffer
is odd; should it NUL terminate or not?
Perhaps, since format_buffer
is normally interacted with using member functions, there instead should be .format()
and .vformat()
member functions instead of free function overloads?
Free functions are nicer because they're composable, but I think since the behavior is slightly different than format_to
to a character array, we may want different names, at least.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.