Giter Site home page Giter Site logo

seanmiddleditch / nanofmt Goto Github PK

View Code? Open in Web Editor NEW
23.0 23.0 1.0 188 KB

Cut down and minimalistic C++ string formatting library

Home Page: https://nanofmt.readthedocs.io/

License: MIT License

CMake 1.18% C++ 98.52% C 0.29%
c-plus-plus c-plus-plus-17 formatting

nanofmt's People

Contributors

seanmiddleditch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

ilobilo

nanofmt's Issues

Design error handling

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?)
  • Return error code instead of, or in addition to, the char*
  • Add overloads that take an error code output parameter
  • Write detailed error string into output
  • Some combination of the above

Alignment and fill

Alignment and fill are only supported for string types, currently. Investigate the cost of implementing them for other built-in types.

Audit NUL termination of format functions

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.

Rename `format_buffer`

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 different
  • format_output - seems direct and semi-clear
  • format_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 guess

C++14 support

Add 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.

Light dynamic buffer

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.

Namespace configuration

Allow configuring the nanofmt namespace via a macro or other facility.

Test case:

  • User can replace nanofmt namespace with my_custom namespace.
  • nanofmt compiled with two different namespaces can be linked into the same executable.

Revise format string parameters

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.

Benchmark compilation

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:

  • Benchmark large scale tests on many TUs
  • Benchmark with and without PCHs
  • Benchmark with modules (requires #5)
  • Benchmark single TU with many format calls with different permutations of argument types
  • ??? moar benches

`format_append_to` or similar

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.

format_length returns incorrect value

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");

Add a `format_value` set of functions

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);

Name prefix configuration

Enable configuring nanofmt to use name prefixes instead of C++ namespaces.

Test case:

  • User can compile library so all public symbols have custom_ prefix instead of nanofmt:: namespace.
  • Two copies of the library compiled with different prefixes, or one with prefixes and one with namespaces, can link.

C++20 module

Add a C++20 module interface to nanofmt. This should not just be a header module unit.

Success:

  • Module unit can be compiled on MSVC
  • Module unit can be imported on MSVC
  • Tests pass when using module imports

Rethink `format_to` overloads that target `format_buffer`

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.