Skip to content

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

Closed

Description

@mintyc

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?

Activity

  1. vitaut commented on Feb 26, 2015

    @vitaut
    Contributor

    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.

  2. mintyc commented on Feb 27, 2015

    @mintyc
    Author

    Thanks very much

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

  3. vitaut commented on Feb 27, 2015

    @vitaut
    Contributor

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

  4. vitaut commented on Mar 2, 2015

    @vitaut
    Contributor

    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);
    
  5. mintyc commented on Mar 2, 2015

    @mintyc
    Author

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

  6. vitaut commented on Mar 2, 2015

    @vitaut
    Contributor

    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.

  7. vitaut commented on Mar 2, 2015

    @vitaut
    Contributor

    @mintyc Will it work for you?

  8. mintyc commented on Mar 2, 2015

    @mintyc
    Author

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

  9. vitaut commented on Mar 2, 2015

    @vitaut
    Contributor

    Great. Thanks for the feedback.

  10. KindDragon commented on Aug 21, 2015

    @KindDragon

    HI @vitaut

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

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

  11. vitaut commented on Aug 21, 2015

    @vitaut
    Contributor

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions