Add string_stream
This commit is contained in:
parent
59314b6d95
commit
c4f2b74e99
142
include/mtl/string_stream.hpp
Normal file
142
include/mtl/string_stream.hpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mtl/stream.hpp"
|
||||||
|
#include "mtl/string.hpp"
|
||||||
|
|
||||||
|
namespace mtl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Basic string builder
|
||||||
|
*
|
||||||
|
* Mimics std::stringstream basic functionality. Does not provide thorough
|
||||||
|
* formatting options, only decimal/hexadecimal switching. If more extensive
|
||||||
|
* formatting is needed, use mtl::string_streamx instead.
|
||||||
|
*
|
||||||
|
* Variables are piped to the stream using operator<<. The string is buffered
|
||||||
|
* until flush is called, mtl::flush is piped, or mtl::endl is piped.
|
||||||
|
*/
|
||||||
|
class string_stream {
|
||||||
|
istring& m_str;
|
||||||
|
bool m_hex = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
string_stream(istring& str) : m_str(str) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Flushes the buffer to the underlying output sequence and
|
||||||
|
* clears the buffer
|
||||||
|
*
|
||||||
|
* By default simply clears the buffer, but can be overriden to
|
||||||
|
* provide more functionality. This function is called internally when
|
||||||
|
* mtl::flush and mtl::endl are piped to the stream. The derived
|
||||||
|
* class must be sure to clear the buffer when finished.
|
||||||
|
*/
|
||||||
|
virtual void flush() {
|
||||||
|
m_str.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
m_str.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
string_stream& operator<<(const string_view& str) {
|
||||||
|
m_str.append(str);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_stream& operator<<(char ch) {
|
||||||
|
m_str += ch;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Appends the signed integer x
|
||||||
|
*
|
||||||
|
* Writes the integer in decimal if the stream was piped mtl::dec,
|
||||||
|
* hexidecimal if the stream was piped mtl::hex. Defaults to mtl::dec.
|
||||||
|
*
|
||||||
|
* The template does not need to check that the integer is a boolean
|
||||||
|
* because booleans are not signed.
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_signed_v<T>, bool> = true>
|
||||||
|
string_stream& operator<<(T x) {
|
||||||
|
string<16> str;
|
||||||
|
m_str.append(to_string(x, str, m_hex));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Appends the unsigned integer x
|
||||||
|
*
|
||||||
|
* Writes the integer in decimal if the stream was piped mtl::dec,
|
||||||
|
* hexidecimal if the stream was piped mtl::hex. Defaults to mtl::dec.
|
||||||
|
*
|
||||||
|
* The template must check that the integer is not a boolean because
|
||||||
|
* std::is_unsigned counts booleans as unsigned integers.
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_unsigned_v<T> && !std::is_same_v<T, bool>, bool> = true>
|
||||||
|
string_stream& operator<<(T x) {
|
||||||
|
string<16> str;
|
||||||
|
m_str.append(to_string(x, str, m_hex));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Appends the boolean x
|
||||||
|
*
|
||||||
|
* Writes the boolean as either "true" or "false".
|
||||||
|
*
|
||||||
|
* This function needs to be templated otherwise non-boolean arguments
|
||||||
|
* might be implicitly converted to boolean. Ex. const char* would be
|
||||||
|
* implicitly converted to boolean instead of mtl::string_view.
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_same_v<T, bool>, bool> = true>
|
||||||
|
string_stream& operator<<(T x) {
|
||||||
|
m_str.append(x ? "true" : "false");
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Appends the address of the pointer addr
|
||||||
|
*
|
||||||
|
* Always writes the address is hexidecimal format. Does not pad the
|
||||||
|
* value to the address width.
|
||||||
|
*
|
||||||
|
* The template must check that the pointer is not a character pointer
|
||||||
|
* otherwise C strings will not be converted to a mtl::string_view and
|
||||||
|
* the address of the string will be printed instead.
|
||||||
|
*/
|
||||||
|
template <typename T, std::enable_if_t<std::is_pointer_v<T>
|
||||||
|
&& !std::is_same_v<T, char*>
|
||||||
|
&& !std::is_same_v<T, const char*>, bool> = true>
|
||||||
|
string_stream& operator<<(T addr) {
|
||||||
|
string<16> str;
|
||||||
|
m_str.append(to_string(addr, str));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_stream& operator<<(_flush) {
|
||||||
|
flush();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
string_stream& operator<<(_endl) {
|
||||||
|
m_str += '\n';
|
||||||
|
flush();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_stream& operator<<(_dec) {
|
||||||
|
m_hex = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
string_stream& operator<<(_hex) {
|
||||||
|
m_hex = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mtl
|
||||||
Loading…
x
Reference in New Issue
Block a user