diff options
author | 2016-03-01 06:45:41 +1100 | |
---|---|---|
committer | 2016-03-01 06:52:36 +1100 | |
commit | a830ea76270b7894a03922a172d58bfaefbc827f (patch) | |
tree | 01d929c08c8fa3e66285a3130004d4aa5d31e393 /src/lib | |
parent | b2fc583ed75b19321849fcd4fec518e2b719294b (diff) |
* Support *n conversion in stream_format/string_format
* Make stream_format return characters printed
* Add iostreams with std::vector storage
* Move to type-safe templates for logerror and popmessage
* Remove now-unnecessary I64FMT from calls to logerror/popmessage
* Put some lib/util stuff in util:: namespace
* Some fixes to Japanese translation
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/util/corestr.h | 5 | ||||
-rw-r--r-- | src/lib/util/options.cpp | 10 | ||||
-rw-r--r-- | src/lib/util/strformat.h | 86 | ||||
-rw-r--r-- | src/lib/util/vecstream.h | 362 |
4 files changed, 449 insertions, 14 deletions
diff --git a/src/lib/util/corestr.h b/src/lib/util/corestr.h index 9d06b30c9f7..209cde389e1 100644 --- a/src/lib/util/corestr.h +++ b/src/lib/util/corestr.h @@ -15,6 +15,9 @@ #include "osdcore.h" #include "strformat.h" + +#include <string> + #include <string.h> @@ -63,8 +66,6 @@ char *core_i64_format(UINT64 value, UINT8 mindigits, bool is_octal); char *core_i64_hex_format(UINT64 value, UINT8 mindigits); char *core_i64_oct_format(UINT64 value, UINT8 mindigits); -#include <string> - int strvprintf(std::string &str, const char *format, va_list args); int strcatvprintf(std::string &str, const char *format, va_list args); diff --git a/src/lib/util/options.cpp b/src/lib/util/options.cpp index ccc6024c9f9..56bad147bcb 100644 --- a/src/lib/util/options.cpp +++ b/src/lib/util/options.cpp @@ -519,7 +519,7 @@ std::string core_options::output_ini(const core_options *diff) const { if (num_valid_headers++) buffer << '\n'; - stream_format(buffer, "#\n# %s\n#\n", last_header); + util::stream_format(buffer, "#\n# %s\n#\n", last_header); last_header = nullptr; } @@ -527,9 +527,9 @@ std::string core_options::output_ini(const core_options *diff) const if (!is_unadorned) { if (strchr(value, ' ') != nullptr) - stream_format(buffer, "%-25s \"%s\"\n", name, value); + util::stream_format(buffer, "%-25s \"%s\"\n", name, value); else - stream_format(buffer, "%-25s %s\n", name, value); + util::stream_format(buffer, "%-25s %s\n", name, value); } } } @@ -553,11 +553,11 @@ std::string core_options::output_help() const { // header: just print if (curentry->is_header()) - stream_format(buffer, "\n#\n# %s\n#\n", curentry->description()); + util::stream_format(buffer, "\n#\n# %s\n#\n", curentry->description()); // otherwise, output entries for all non-deprecated items else if (curentry->description() != nullptr) - stream_format(buffer, "-%-20s%s\n", curentry->name(), curentry->description()); + util::stream_format(buffer, "-%-20s%s\n", curentry->name(), curentry->description()); } return buffer.str(); } diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h index 3bf95a5df29..96add0dfcca 100644 --- a/src/lib/util/strformat.h +++ b/src/lib/util/strformat.h @@ -91,6 +91,8 @@ widening or narrowing - s/S: default stream output behaviour for argument - p/P: cast any integer/char/bool/pointer/array to void const * + - n: store characters printed so far, produces no output, argument + must be pointer to type that std::streamoff is convertible to - m: output of std::strerror(errno), no automatic widening or narrowing, does not consume an argument - %: literal %, field width applied, does not consume an argument @@ -128,13 +130,13 @@ - Out-of-range argument/width/precision position - Inappropriate type for parameterised width/precision - Positional width/precision specifier not terminated with $ + - Inappropriate type for n conversion Some limitations have been described in passing. Major limitations and bugs include: - No automatic widening/narrowing support, so no simple way to output wide characters/strings to narrow streams/strings and vice versa. - - No support for n conversion (store characters printed so far) - Precision ignored for d/i/u/o/x/X conversions (should set minimum digits to print). - Precisoin for s/S conversion is only honoured for string-like @@ -183,7 +185,7 @@ #include <type_traits> #include <utility> - +namespace util { namespace detail { template <typename Character> class format_chars @@ -221,6 +223,7 @@ public: l = Character('l'), L = Character('L'), m = Character('m'), + n = Character('n'), o = Character('o'), p = Character('p'), s = Character('s'), @@ -270,6 +273,7 @@ public: l = L'l', L = L'L', m = L'm', + n = L'n', o = L'o', p = L'p', s = L's', @@ -320,6 +324,7 @@ public: character, // c, C string, // s, S pointer, // p + tell, // n strerror, // m percent // % }; @@ -389,6 +394,7 @@ public: case conversion::character: case conversion::string: case conversion::pointer: + case conversion::tell: case conversion::strerror: case conversion::percent: break; @@ -839,6 +845,9 @@ public: case format_helper::p: flags.set_conversion(format_flags::conversion::pointer); break; + case format_helper::n: + flags.set_conversion(format_flags::conversion::tell); + break; case format_helper::m: flags.set_conversion(format_flags::conversion::strerror); break; @@ -1256,6 +1265,39 @@ public: } }; +template <typename T> +class format_store_integer +{ +private: + template <typename U> struct is_non_const_ptr + { static constexpr bool value = std::is_pointer<U>::value && !std::is_const<std::remove_pointer_t<U> >::value; }; + template <typename U> struct is_unsigned_ptr + { static constexpr bool value = std::is_pointer<U>::value && std::is_unsigned<std::remove_pointer_t<U> >::value; }; + template <typename U> struct use_unsigned_cast + { static constexpr bool value = is_non_const_ptr<U>::value && is_unsigned_ptr<U>::value && std::is_convertible<std::make_unsigned_t<std::streamoff>, std::remove_pointer_t<U> >::value; }; + template <typename U> struct use_signed_cast + { static constexpr bool value = is_non_const_ptr<U>::value && !use_unsigned_cast<U>::value && std::is_convertible<std::streamoff, std::remove_pointer_t<U> >::value; }; + template <typename U> struct disable + { static constexpr bool value = !use_unsigned_cast<U>::value && !use_signed_cast<U>::value; }; + +public: + template <typename U> static std::enable_if_t<use_unsigned_cast<U>::value, bool> apply(U const &value, std::streamoff data) + { + *value = std::remove_pointer_t<U>(std::make_unsigned_t<std::streamoff>(data)); + return true; + } + template <typename U> static std::enable_if_t<use_signed_cast<U>::value, bool> apply(U const &value, std::streamoff data) + { + *value = std::remove_pointer_t<U>(std::make_signed_t<std::streamoff>(data)); + return true; + } + template <typename U> static std::enable_if_t<disable<U>::value, bool> apply(U const &value, std::streamoff data) + { + assert(false); // inappropriate type for storing characters written so far + return false; + } +}; + template <typename Stream> class format_argument { @@ -1264,6 +1306,7 @@ public: : m_value(nullptr) , m_output_function(nullptr) , m_make_integer_function(nullptr) + , m_store_integer_function(nullptr) { } @@ -1272,15 +1315,18 @@ public: : m_value(reinterpret_cast<void const *>(&value)) , m_output_function(&static_output<T>) , m_make_integer_function(&static_make_integer<T>) + , m_store_integer_function(&static_store_integer<T>) { } void output(Stream &str, format_flags const &flags) const { m_output_function(str, flags, m_value); } bool make_integer(int &result) const { return m_make_integer_function(m_value, result); } + void store_integer(std::streamoff data) const { m_store_integer_function(m_value, data); } private: typedef void (*output_function)(Stream &str, format_flags const &flags, void const *value); typedef bool (*make_integer_function)(void const *value, int &result); + typedef void (*store_integer_function)(void const *value, std::streamoff data); template <typename T> static void static_output(Stream &str, format_flags const &flags, void const *value) { @@ -1292,9 +1338,15 @@ private: return format_make_integer<T>::apply(*reinterpret_cast<T const *>(value), result); } + template <typename T> static void static_store_integer(void const *value, std::streamoff data) + { + format_store_integer<T>::apply(*reinterpret_cast<T const *>(value), data); + } + void const *m_value; output_function m_output_function; make_integer_function m_make_integer_function; + store_integer_function m_store_integer_function; }; template <typename Stream, typename... Params> @@ -1304,7 +1356,7 @@ inline std::array<format_argument<Stream>, sizeof...(Params)> make_format_argume } template <typename Stream, typename Format, std::size_t Count> -void stream_format(Stream &str, Format const &fmt, std::array<format_argument<Stream>, Count> const &args) +typename Stream::off_type stream_format(Stream &str, Format const &fmt, std::array<format_argument<Stream>, Count> const &args) { typedef format_helper<std::remove_reference_t<Format> > format_helper; typedef typename format_helper::iterator iterator; @@ -1334,7 +1386,8 @@ void stream_format(Stream &str, Format const &fmt, std::array<format_argument<St std::streamsize m_width; }; - stream_preserver preserver(str); + typename Stream::pos_type const begin(str.tellp()); + stream_preserver const preserver(str); int next_pos(1); iterator start = format_helper::begin(fmt); for (iterator it = start; !format_helper::at_end(fmt, start); ) @@ -1415,20 +1468,35 @@ void stream_format(Stream &str, Format const &fmt, std::array<format_argument<St assert(args.size() >= unsigned(arg_pos)); if ((0 >= arg_pos) || (args.size() < unsigned(arg_pos))) continue; - args[arg_pos - 1].output(str, flags); + if (format_flags::conversion::tell == flags.get_conversion()) + { + typename Stream::pos_type const current(str.tellp()); + args[arg_pos - 1].store_integer( + ((typename Stream::pos_type(-1) == begin) || (typename Stream::pos_type(-1) == current)) + ? typename Stream::off_type(-1) + : (current - begin)); + } + else + { + args[arg_pos - 1].output(str, flags); + } start = it; } } } + typename Stream::pos_type const end(str.tellp()); + return ((typename Stream::pos_type(-1) == begin) || (typename Stream::pos_type(-1) == end)) + ? typename Stream::off_type(-1) + : (end - begin); } } // namespace detail template <typename Stream, typename Format, typename... Params> -inline void stream_format(Stream &str, Format const &fmt, Params &&... args) +inline typename Stream::off_type stream_format(Stream &str, Format const &fmt, Params &&... args) { auto const arg_pack(detail::make_format_arguments<Stream>(std::forward<Params>(args)...)); - detail::stream_format(str, fmt, arg_pack); + return detail::stream_format(str, fmt, arg_pack); } template <typename String = std::string, typename Format, typename... Params> @@ -1450,4 +1518,8 @@ inline String string_format(std::locale const &locale, Format const &fmt, Params return str.str(); }; +} // namespace util + +using util::string_format; + #endif // __MAME_UTIL_STRFORMAT_H__ diff --git a/src/lib/util/vecstream.h b/src/lib/util/vecstream.h new file mode 100644 index 00000000000..9c7c5d5b4e0 --- /dev/null +++ b/src/lib/util/vecstream.h @@ -0,0 +1,362 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + vecstream.h + + streams with vector storage + + These types are useful if you want a persistent buffer for formatted + text and you need to use it like a character array or character + pointer, as you get read-only access to it without copying. The + storage is always guaranteed to be contiguous. Writing to the + stream may invalidate pointers to storage. + +***************************************************************************/ + +#ifndef __MAME_UTIL_VECSTREAM_H__ +#define __MAME_UTIL_VECSTREAM_H__ + +#include <cassert> +#include <ostream> +#include <streambuf> +#include <string> +#include <type_traits> +#include <utility> +#include <vector> + +namespace util { +template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT> > +class basic_vectorbuf : public std::basic_streambuf<CharT, Traits> +{ +public: + typedef typename std::basic_streambuf<CharT, Traits>::char_type char_type; + typedef typename std::basic_streambuf<CharT, Traits>::int_type int_type; + typedef typename std::basic_streambuf<CharT, Traits>::pos_type pos_type; + typedef typename std::basic_streambuf<CharT, Traits>::off_type off_type; + typedef Allocator allocator_type; + typedef std::vector<char_type, Allocator> vector_type; + + basic_vectorbuf(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_streambuf<CharT, Traits>(), m_mode(mode), m_storage(), m_threshold(nullptr) + { + setup(); + } + + basic_vectorbuf(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_streambuf<CharT, Traits>(), m_mode(mode), m_storage(content), m_threshold(nullptr) + { + setup(); + } + + basic_vectorbuf(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_streambuf<CharT, Traits>(), m_mode(mode), m_storage(std::move(content)), m_threshold(nullptr) + { + setup(); + } + + basic_vectorbuf(basic_vectorbuf const &that) : std::basic_streambuf<CharT, Traits>(that), m_mode(that.m_mode), m_storage(that.m_storage), m_threshold(nullptr) + { + adjust(); + } + + basic_vectorbuf(basic_vectorbuf &&that) : std::basic_streambuf<CharT, Traits>(that), m_mode(that.m_mode), m_storage(std::move(that.m_storage)), m_threshold(that.m_threshold) + { + that.clear(); + } + + vector_type const &vec() const + { + if (m_mode & std::ios_base::out) + { + if (this->pptr() > m_threshold) m_threshold = this->pptr(); + auto const base(this->pbase()); + auto const end(m_threshold - base); + if (m_storage.size() > std::make_unsigned_t<decltype(end)>(end)) + { + m_storage.resize(std::make_unsigned_t<decltype(end)>(end)); + assert(&m_storage[0] == base); + auto const put_offset(this->pptr() - base); + const_cast<basic_vectorbuf *>(this)->setp(base, base + put_offset); + const_cast<basic_vectorbuf *>(this)->pbump(put_offset); + } + } + return m_storage; + } + + void vec(const vector_type &content) + { + m_storage = content; + setup(); + } + + void vec(vector_type &&content) + { + m_storage = std::move(content); + setup(); + } + + void clear() + { + m_storage.clear(); + setup(); + } + + void reserve(typename vector_type::size_type size) + { + if ((m_mode & std::ios_base::out) && (m_storage.size() < size)) + { + m_storage.reserve(size); + adjust(); + } + } + + basic_vectorbuf &operator=(basic_vectorbuf const &that) + { + std::basic_streambuf<CharT, Traits>::operator=(that); + m_mode = that.m_mode; + m_storage = that.m_storage; + m_threshold = that.m_threshold; + adjust(); + return *this; + } + + basic_vectorbuf &operator=(basic_vectorbuf &&that) + { + std::basic_streambuf<CharT, Traits>::operator=(that); + m_mode = that.m_mode; + m_storage = std::move(that.m_storage); + m_threshold = that.m_threshold; + that.clear(); + return *this; + } + +protected: + pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) override + { + bool const in(which & std::ios_base::in); + bool const out(which & std::ios_base::out); + if ((!in && !out) || + (in && out && (std::ios_base::cur == dir)) || + (in && (!(m_mode & std::ios_base::in) || !this->gptr())) || + (out && (!(m_mode & std::ios_base::out) || !this->pptr()))) + { + return pos_type(off_type(-1)); + } + maximise_egptr(); + off_type const end((m_mode & std::ios_base::out) ? off_type(m_threshold - this->pbase()) : off_type(m_storage.size())); + switch (dir) + { + case std::ios_base::beg: + break; + case std::ios_base::end: + off += end; + break; + case std::ios_base::cur: + off += off_type(in ? (this->gptr() - this->eback()) : (this->pptr() - this->pbase())); + break; + default: + return pos_type(off_type(-1)); + } + if ((off_type(0) > off) || (end < off) || ((m_mode & std::ios_base::app) && out && (end != off))) + return pos_type(off_type(-1)); + if (in) this->setg(this->eback(), this->eback() + off, this->egptr()); + if (out) + { + this->setp(this->pbase(), this->epptr()); + this->pbump(off); + } + return pos_type(off); + } + + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in |std:: ios_base::out) override + { + return seekoff(off_type(pos), std::ios_base::beg, which); + } + + virtual int_type underflow() override + { + if (!this->gptr()) return Traits::eof(); + maximise_egptr(); + return (this->gptr() < this->egptr()) ? Traits::to_int_type(*this->gptr()) : Traits::eof(); + } + + virtual int_type overflow(int_type ch = Traits::eof()) override + { + if (!(m_mode & std::ios_base::out)) return Traits::eof(); + if (Traits::eq_int_type(ch, Traits::eof())) return Traits::not_eof(ch); + auto const put_offset(this->pptr() - this->pbase() + 1); + auto const threshold_offset((std::max)(m_threshold - this->pbase(), put_offset)); + m_storage.push_back(Traits::to_char_type(ch)); + m_storage.resize(m_storage.capacity()); + auto const base(&m_storage[0]); + this->setp(base, base + m_storage.size()); + m_threshold = base + threshold_offset; + if (m_mode & std::ios_base::in) this->setg(base, base + (this->gptr() - this->eback()), m_threshold); + this->pbump(int(put_offset)); + return ch; + } + + virtual int_type pbackfail(int_type ch = Traits::eof()) override + { + if (this->gptr() != this->eback()) + { + if (Traits::eq_int_type(ch, Traits::eof())) + { + this->gbump(-1); + return Traits::not_eof(ch); + } + else if (Traits::eq(Traits::to_char_type(ch), this->gptr()[-1])) + { + this->gbump(-1); + return ch; + } + else if (m_mode & std::ios_base::out) + { + this->gbump(-1); + *this->gptr() = Traits::to_char_type(ch); + return ch; + } + } + return Traits::eof(); + } + +private: + void setup() + { + if (m_mode & std::ios_base::out) + { + auto const end(m_storage.size()); + m_storage.resize(m_storage.capacity()); + if (m_storage.empty()) + { + m_threshold = nullptr; + this->setg(nullptr, nullptr, nullptr); + this->setp(nullptr, nullptr); + } + else + { + auto const base(&m_storage[0]); + m_threshold = base + end; + this->setp(base, base + m_storage.size()); + if (m_mode & std::ios_base::in) this->setg(base, base, m_threshold); + } + if (m_mode & (std::ios_base::app | std::ios_base::ate)) this->pbump(int(unsigned(end))); + } + else if (m_storage.empty()) + { + this->setg(nullptr, nullptr, nullptr); + } + else if (m_mode & std::ios_base::in) + { + auto const base(&m_storage[0]); + this->setg(base, base, base + m_storage.size()); + } + } + + void adjust() + { + auto const put_offset(this->pptr() - this->pbase()); + auto const get_offset(this->gptr() - this->eback()); + setup(); + if (m_mode & std::ios_base::out) + { + this->pbump(int(put_offset)); + m_threshold = this->pptr(); + if (m_mode & std::ios_base::in) + { + auto const base(&m_storage[0]); + this->setg(base, base + get_offset, m_threshold); + } + } + else if (m_mode & std::ios_base::in) + { + this->gbump(int(get_offset)); + } + } + + void maximise_egptr() + { + if (m_mode & std::ios_base::out) + { + if (m_threshold < this->pptr()) m_threshold = this->pptr(); + if ((m_mode & std::ios_base::in) && (this->egptr() < m_threshold)) this->setg(this->eback(), this->gptr(), m_threshold); + } + } + + std::ios_base::openmode m_mode; + mutable vector_type m_storage; + mutable CharT *m_threshold; +}; + +template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT> > +class basic_ivectorstream : public std::basic_istream<CharT, Traits> +{ +public: + typedef typename basic_vectorbuf<CharT, Traits, Allocator>::vector_type vector_type; + + basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(mode) { } + basic_ivectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } + basic_ivectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in) : std::basic_istream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } + + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_istream<CharT, Traits>::rdbuf()); } + vector_type const &vec() const { return rdbuf()->vec(); } + void vec(const vector_type &content) { rdbuf()->vec(content); } + void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } + void clear() { rdbuf()->clear(); } + +private: + basic_vectorbuf<CharT, Traits, Allocator> m_rdbuf; +}; + +template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT> > +class basic_ovectorstream : public std::basic_ostream<CharT, Traits> +{ +public: + typedef typename basic_vectorbuf<CharT, Traits, Allocator>::vector_type vector_type; + + basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(mode) { } + basic_ovectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } + basic_ovectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::out) : std::basic_ostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } + + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_ostream<CharT, Traits>::rdbuf()); } + + vector_type const &vec() const { return rdbuf()->vec(); } + void vec(const vector_type &content) { rdbuf()->vec(content); } + void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } + void clear() { rdbuf()->clear(); } + void reserve(typename vector_type::size_type size) { rdbuf->reserve(size); } + +private: + basic_vectorbuf<CharT, Traits, Allocator> m_rdbuf; +}; + +template <typename CharT, typename Traits = std::char_traits<CharT>, typename Allocator = std::allocator<CharT> > +class basic_vectorstream : public std::basic_iostream<CharT, Traits> +{ +public: + typedef typename basic_vectorbuf<CharT, Traits, Allocator>::vector_type vector_type; + + basic_vectorstream(std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(mode) { } + basic_vectorstream(vector_type const &content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(content, mode) { } + basic_vectorstream(vector_type &&content, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : std::basic_iostream<CharT, Traits>(&m_rdbuf), m_rdbuf(std::move(content), mode) { } + + basic_vectorbuf<CharT, Traits, Allocator> *rdbuf() const { return reinterpret_cast<basic_vectorbuf<CharT, Traits, Allocator> *>(std::basic_iostream<CharT, Traits>::rdbuf()); } + + vector_type const &vec() const { return rdbuf()->vec(); } + void vec(const vector_type &content) { rdbuf()->vec(content); } + void vec(vector_type &&content) { rdbuf()->vec(std::move(content)); } + void clear() { rdbuf()->clear(); } + void reserve(typename vector_type::size_type size) { rdbuf->reserve(size); } + +private: + basic_vectorbuf<CharT, Traits, Allocator> m_rdbuf; +}; + +typedef basic_ivectorstream<char> ivectorstream; +typedef basic_ivectorstream<wchar_t> wivectorstream; +typedef basic_ovectorstream<char> ovectorstream; +typedef basic_ovectorstream<wchar_t> wovectorstream; +typedef basic_vectorstream<char> vectorstream; +typedef basic_vectorstream<wchar_t> wvectorstream; + +} // namespace util + +#endif // __MAME_UTIL_VECSTREAM_H__ |