Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for fixed sized buffers #105

Closed
fmatthew5876 opened this issue Feb 9, 2015 · 7 comments
Closed

Add support for fixed sized buffers #105

fmatthew5876 opened this issue Feb 9, 2015 · 7 comments

Comments

@fmatthew5876
Copy link

This library looks very promising. One thing that's missing is efficient snprintf() like functionality which can print directly to a fixed size buffer with truncation but without any memory allocations.

I would suggest an interface like this:

StringRef format(ArrayRef<char> buffer, StringRef fmt, ArgList args);

In this example, ArrayRef would be a simplified version of array_view which is proposed for C++17. You don't need all of the multi-dimensional and striding support, just a generic adapter for any array type container.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3851.pdf

The returned StringRef references a sub-array of buffer that was filled in by the formatting.

Usage example:

char path_buf[4096];
auto path = format(path_buf, "{}/{}", dir, filename);
@vitaut
Copy link
Contributor

vitaut commented Feb 9, 2015

Thank you for the suggestion. The library already doesn't do dynamic memory allocations if the result of formatting is less than fmt::internal::INLINE_BUFFER_SIZE (which you can configure to better suit your application):

fmt::MemoryWriter w;
w.write("{}/{}", dir, filename); // no dynamic memory allocation for small output
w.c_str(); // returns a pointer to the internal buffer

The advantage of this method is that it works with large output by using dynamic memory allocation (only) if necessary.

Also you can define your own function (or a writer class) that prints directly to a fixed buffer:

#include "format.h"

class FixedBuffer : public fmt::internal::Buffer<char> {
 public:
  FixedBuffer(char *array, std::size_t size)
    : fmt::internal::Buffer<char>(array, size) {}

 protected:
  void grow(std::size_t size) {
    throw std::runtime_error("buffer overflow");
  }
};

class FixedWriter : public fmt::Writer {
 private:
  FixedBuffer buffer_;
 public:
  FixedWriter(char *array, std::size_t size)
    : fmt::Writer(buffer_), buffer_(array, size) {}
};

int main() {
  char buffer[100];
  FixedWriter w(buffer, sizeof(buffer));
  w.write("Hello, {}!", "world");
}

@vitaut
Copy link
Contributor

vitaut commented Feb 10, 2015

Closing for now, but feel free to reopen if the alternatives I described don't fit your use cases.

@vitaut vitaut closed this as completed Feb 10, 2015
@patlecat
Copy link

@vitaut So fmt::internal::INLINE_BUFFER_SIZE should and can only be configured by deriving my own class like in your example above? Otherwise how is it defined?

@vitaut
Copy link
Contributor

vitaut commented Feb 17, 2015

@patlecat No, you can change the value of fmt::internal::INLINE_BUFFER_SIZE constant if you embed C++ Format in your application (although in most cases the default should be fine). Deriving your own class is only necessary if you want to support a custom buffer, e.g. fixed-sized as in the above example.

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

C++ Format now supports formatting to fixed-size arrays: http://cppformat.readthedocs.org/en/latest/reference.html#fmt::BasicArrayWriter.

Example:

char buffer[100];
fmt::ArrayWriter w(buffer);
w.write("The answer is {}", 42);

@patlecat
Copy link

patlecat commented Mar 2, 2015

Does this represent any performance gain in any way or is it just a convenience for C code?

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

There is no performance gain. It's mostly for the case where you can't replace the destination array with MemoryWriter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants