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

Can't write into a pre-existing buffer?? #122

Closed
mintyc opened this issue Feb 26, 2015 · 11 comments
Closed

Can't write into a pre-existing buffer?? #122

mintyc opened this issue Feb 26, 2015 · 11 comments

Comments

@mintyc
Copy link

mintyc commented Feb 26, 2015

If I have a pre-allocated region of memory I can't find an API that allows me to write directly into it without a memcpy as well (e.g. from a returned string)

Am I missing something?

Seems like a problem for high performance, so given your fantastic benchmark numbers I'm pretty sure it is me that is missing something!

PS Maybe start a forum or discussion area for points like this?

@vitaut
Copy link
Contributor

vitaut commented Feb 26, 2015

It has been discussed in Issue #105. If you have control over allocation of this region of memory I recommend replacing manual allocation with fmt::MemoryWriter because it will gracefully handle the case when buffer is not large enough by allocating more memory. Otherwise you'll have to provide your own buffer class as described here.

Currently the base Buffer class is internal, but if you like I can make it public and, possibly provide a more convenient API for this.

PS Good idea, I'll probably open a Google Group. Until then it's fine to post questions as issues.

@mintyc
Copy link
Author

mintyc commented Feb 27, 2015

Thanks very much

I'd vote for FixedBuffer and FixedWriter to be part of the library. Seems a simple and elegant solution?

@vitaut
Copy link
Contributor

vitaut commented Feb 27, 2015

Sure, I'll include FixedWriter in the public API then.

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

OK, here you go: http://cppformat.readthedocs.org/en/latest/reference.html#fmt::BasicArrayWriter. I've decided to call the class ArrayWriter instead of FixedWriter as it may not be clear what "fixed" refers to. Also there is a ctor that takes an array of the size known at compile-time but it is undocumented because of the bug in Sphinx 1.2.

Example:

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

@vitaut vitaut closed this as completed Mar 2, 2015
@mintyc
Copy link
Author

mintyc commented Mar 2, 2015

Nice work

Would you take a submission that adds

fmt::ArrayWriter::advance(int offset);
fmt::ArrayWriter::advance_to(uint32_t absolute_offset)

both of which throw if you attempt to move outside the bounds of the buffer
(names TBD, perhaps update_position(), set_position()? )

Justification:In practice there may also be non-cppformat activity on the
buffer as well, so these allow rewind/advance and absolute positioning
without affecting cppformat.

e.g. I'm creating a C++ lib to do the work of 'statsd' and create regular
output packets of aggregated stats for 'graphite' and want a combination of
memcpy and cppformat output in each packet.

On 2 March 2015 at 02:33, Victor Zverovich [email protected] wrote:

OK, here you go:
http://cppformat.readthedocs.org/en/latest/reference.html#fmt::BasicArrayWriter.
I've decided to call the class ArrayWriter instead of FixedWriter as it
may not be clear what "fixed" refers to. Also there is a ctor that takes an
array of the size known at compile-time but it is undocumented because of
the bug in Sphinx 1.2.

Example:

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


Reply to this email directly or view it on GitHub
#122 (comment).

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

Thanks.

I'd rather not allow direct manipulation of the underlying buffer, because it doesn't fit very well into the Writer concept. However, you can combine formatting and write operations and writing a string to Writer is pretty much the same as memcpy as it permits embedded nul characters.

char buffer[100];
fmt::ArrayWriter w(buffer);
w << fmt::StringRef("a\0bc", 4); // Copies a string with embedded nul to the buffer.
w << 42;

This uses std::copy, but if you see performance improvement by using memcpy instead, we can change the C++ Format implementation.

Another option is to only construct ArrayWriter at a specific position in the destination buffer when you need to format anything. ArrayWriter is very lightweight, so it should be fine in terms of performance.

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

@mintyc Will it work for you?

@mintyc
Copy link
Author

mintyc commented Mar 2, 2015

I'm just reworking some code to use your preferred approach, so yes. I
didn't like muddying the writer concept either.

Its not ideal for amending stats values inplace in the buffer (rather than
rewriting) but I can live with that.

You have been incredibly helpful. Thank you very much

On 2 March 2015 at 15:19, Victor Zverovich [email protected] wrote:

@mintyc https://github.com/mintyc Will it work for you?


Reply to this email directly or view it on GitHub
#122 (comment).

@vitaut
Copy link
Contributor

vitaut commented Mar 2, 2015

Great. Thanks for the feedback.

@KindDragon
Copy link

HI @vitaut

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

Why write not add '\0' to end of string?

@vitaut
Copy link
Contributor

vitaut commented Aug 21, 2015

Hi @KindDragon,

write doesn't add '\0' to avoid unnecessary work, but you can access the content of the buffer as a null-terminated string via Writer::c_str.

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

No branches or pull requests

3 participants