Flow 1.0.0
Flow project: Full implementation reference.
Public Member Functions | Private Types | Private Attributes | List of all members
flow::util::String_ostream Class Reference

Similar to ostringstream but allows fast read-only access directly into the std::string being written; and some limited write access to that string. More...

#include <string_ostream.hpp>

Inheritance diagram for flow::util::String_ostream:
[legend]
Collaboration diagram for flow::util::String_ostream:
[legend]

Public Member Functions

 String_ostream (std::string *target_str=0)
 Wraps either the given std::string or a newly created empty string if a null pointer is passed. More...
 
std::ostream & os ()
 Access to stream that will write to owned string. More...
 
const std::ostream & os () const
 Read-only access to stream that will write to owned string. More...
 
const std::string & str () const
 Read-only access to the string being wrapped. More...
 
void str_clear ()
 Performs std::string::clear() on the object returned by str(). More...
 

Private Types

using String_appender_ostream = boost::iostreams::stream< boost::iostreams::back_insert_device< std::string > >
 Short-hand for an ostream writing to which will append to an std::string it is adapting. More...
 

Private Attributes

std::string m_own_target_str
 Underlying string to use if user chooses not to pass in their own in constructor. More...
 
std::string * m_target
 Pointer to the target string. Emptied at construction and in str_clear() only. More...
 
boost::iostreams::back_insert_device< std::string > m_target_inserter
 Inserter into m_target. More...
 
String_appender_ostream m_target_appender_ostream
 Appender ostream into m_target by way of m_target_inserter. Write/flush here to write to m_target. More...
 

Detailed Description

Similar to ostringstream but allows fast read-only access directly into the std::string being written; and some limited write access to that string.

Also it can take over an existing std::string.

ostringstream is fine, except for the giant flaw that is the fact that the essentially only way to read the string is to call ostringstream::str() which returns a copy, not a reference.

Todo:
Consider using alt_sstream in boost.format; it doesn't seem to have public documentation but isn't in a detail directory either. So that's interesting. It might have better performance than the implementation here (by being more "direct" probably). Then again it might not.

Thread safety

This provides the same level of thread safety as ostringstream. That is, you should use a mutex if planning concurrent read/write access to the same object.

Definition at line 45 of file string_ostream.hpp.

Member Typedef Documentation

◆ String_appender_ostream

using flow::util::String_ostream::String_appender_ostream = boost::iostreams::stream<boost::iostreams::back_insert_device<std::string> >
private

Short-hand for an ostream writing to which will append to an std::string it is adapting.

Definition at line 108 of file string_ostream.hpp.

Constructor & Destructor Documentation

◆ String_ostream()

flow::util::String_ostream::String_ostream ( std::string *  target_str = 0)
explicit

Wraps either the given std::string or a newly created empty string if a null pointer is passed.

Parameters
target_strPointer to the string of which to take ownership; null to use an internal string currently blank. If non-null is passed, any subsequnt access to *target_str except via this class's API results in undefined behavior. (It should go without saying, but using const_cast or equivalents counts as being outside the bounds of this class's API.)

Definition at line 25 of file string_ostream.cpp.

Member Function Documentation

◆ os() [1/2]

std::ostream & flow::util::String_ostream::os ( )

Access to stream that will write to owned string.

Returns
Stream.

Definition at line 33 of file string_ostream.cpp.

References m_target_appender_ostream.

Referenced by flow::log::Thread_local_string_appender::appender_ostream(), flow::util::buffers_dump_string(), flow::util::ostream_op_to_string(), flow::log::Thread_local_string_appender::save_formatting_state_and_restore_prev(), and flow::cfg::Option_set_base::throw_on_invalid_func().

Here is the caller graph for this function:

◆ os() [2/2]

const std::ostream & flow::util::String_ostream::os ( ) const

Read-only access to stream that will write to owned string.

Returns
Read-only reference to stream.

Definition at line 38 of file string_ostream.cpp.

References m_target_appender_ostream.

◆ str()

const std::string & flow::util::String_ostream::str ( ) const

Read-only access to the string being wrapped.

The reference's value never changes for *this object. The string's value may change, if one writes to os() or does str_clear(), etc.

Rationale

Why return const string& instead of util::String_view? Answer: By definition we are backed by an std::string, either our own or one user actively passed to ctor. Hence it's unnecessary obfuscation; plus it can lead to errors, like if the user thinks a returned object's String_view::size() will auto-adjust based on what happens to the wrapped std::string subsequently. If they want a String_view, they can always just construct one, just as we would inside here anyway.

Returns
Read-only reference to string; the address therein is guaranteed to always be the same given a *this.

Definition at line 43 of file string_ostream.cpp.

References m_target.

Referenced by flow::log::Buffer_logger::buffer_str(), and flow::log::Thread_local_string_appender::target_contents().

Here is the caller graph for this function:

◆ str_clear()

void flow::util::String_ostream::str_clear ( )

Performs std::string::clear() on the object returned by str().

The latter is const, so you may not call clear() directly.

Note
clear() is a frequently desired operation, which is why access to it is provided as a special case. It is intentional that no read-write version of str() is provided for arbitrary write operations.

Definition at line 48 of file string_ostream.cpp.

References m_target.

Referenced by flow::log::Thread_local_string_appender::fresh_appender_ostream().

Here is the caller graph for this function:

Member Data Documentation

◆ m_own_target_str

std::string flow::util::String_ostream::m_own_target_str
private

Underlying string to use if user chooses not to pass in their own in constructor.

Otherwise unused. (Could use unique_ptr to avoid even allocating it if not needed; but the memory use of an empty string is negligible, and this is otherwise equally fast or faster and leads to simpler code.)

Definition at line 117 of file string_ostream.hpp.

◆ m_target

std::string* flow::util::String_ostream::m_target
private

Pointer to the target string. Emptied at construction and in str_clear() only.

Definition at line 120 of file string_ostream.hpp.

Referenced by str(), and str_clear().

◆ m_target_appender_ostream

String_appender_ostream flow::util::String_ostream::m_target_appender_ostream
private

Appender ostream into m_target by way of m_target_inserter. Write/flush here to write to m_target.

Definition at line 126 of file string_ostream.hpp.

Referenced by os().

◆ m_target_inserter

boost::iostreams::back_insert_device<std::string> flow::util::String_ostream::m_target_inserter
private

Inserter into m_target.

Definition at line 123 of file string_ostream.hpp.


The documentation for this class was generated from the following files: