diff options
Diffstat (limited to 'include/iprt/nocrt/ostream')
-rw-r--r-- | include/iprt/nocrt/ostream | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/include/iprt/nocrt/ostream b/include/iprt/nocrt/ostream new file mode 100644 index 00000000..98820e27 --- /dev/null +++ b/include/iprt/nocrt/ostream @@ -0,0 +1,280 @@ +/** @file + * IPRT / No-CRT - Minimal C++ ostream header. + */ + +/* + * Copyright (C) 2022 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included + * in the VirtualBox distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + * + * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 + */ + +#ifndef VBOX_INCLUDED_SRC_nocrt_ostream +#define VBOX_INCLUDED_SRC_nocrt_ostream +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/* Currently all in the ios header. */ +#include <iprt/nocrt/ios> + +namespace std +{ + /** + * Basic output stream. + */ + template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ > + class basic_ostream : public basic_ios<a_CharType, a_CharTraits> + { + protected: + /** Sentry class that performs pre and post output work. */ + class sentry + { + private: + basic_ostream &m_rParent; + + public: + explicit sentry(basic_ostream &a_rParent) + : m_rParent(a_rParent) + { + if (a_rParent.good()) + { + basic_ostream *pTiedStream = a_rParent.tie(); + if (!pTiedStream) + { /* likely? */ } + else + { + pTiedStream->flush(); + if (!pTiedStream->good()) + a_rParent.setstate(failbit); + } + } + } + + explicit operator bool() const + { + return m_rParent.good(); + } + + ~sentry() + { + if ( (m_rParent.flags() & std::ios_base::unitbuf) + && m_rParent.good()) + m_rParent.rdbuf()->pubsync(); + } + }; + + public: + explicit basic_ostream(std::basic_streambuf<a_CharType,a_CharTraits> *a_pBuf) + : basic_ios(a_pBuf) + { } + + /** For cerr initialization. + * @internal */ + explicit basic_ostream(std::basic_streambuf<a_CharType,a_CharTraits> *a_pBuf, + std::basic_ostream<a_CharType, a_CharTraits> *a_pTiedStream, + bool a_fUnbuffered) + : basic_ios(a_pBuf) + { + m_pTiedStream = a_pTiedStream; + if (!a_fUnbuffered) + setf(std::ios_base::unitbuf); + } + + private: + basic_ostream(basic_ostream const &a_rSrc); /* not copyable */ + basic_ostream &operator=(basic_ostream const &a_rSrc); /* not copyable */ + + public: + virtual ~basic_ostream() + { + } + + public: + basic_ostream &put(char_type a_ch) + { + sentry PrePost(*this); + if (PrePost) + { + if (m_pBuf->sputc(a_ch) == traits_type::eof()) + m_fState |= badbit; + } + return *this; + } + + basic_ostream &write(const char_type *a_pchSrc, std::streamsize a_cchToWrite) + { + sentry PrePost(*this); + if (PrePost) + { + std::streamsize cchWritten = m_pBuf->sputn(a_pchSrc, a_cchToWrite); + if (cchWritten != a_cchToWrite) + m_fState |= badbit; + } + return *this; + } + + basic_ostream &flush() + { + if (m_pBuf) + m_pBuf->pubsync(); + return *this; + } + + pos_type tellp() RT_NOEXCEPT; + basic_ostream &seekp(pos_type a_off) RT_NOEXCEPT; + basic_ostream &seekp(off_type a_off, seekdir enmDir) RT_NOEXCEPT; + + /** @name Internal support methods + * @{ */ + inline basic_ostream &intWrite(const char *a_pchSrc, std::streamsize a_cchToWrite); /**< Internal method outputting char buffers. */ + + /** @returns 8, 10 or 16. */ + inline unsigned intGetIntegerBase() const RT_NOEXCEPT + { + switch (m_fFlags & basefield) + { + default: + case dec: return 10; + case hex: return 16; + case oct: return 8; + } + } + + /** @returns RTSTR_F_XXX . */ + inline unsigned intGetIntegerFlags() const RT_NOEXCEPT + { + unsigned fFlags = 0; + if (m_fFlags & uppercase) + fFlags |= RTSTR_F_CAPITAL; + if (m_fFlags & showbase) + fFlags |= RTSTR_F_SPECIAL; + if (m_fFlags & showpos) + fFlags |= RTSTR_F_PLUS; + return fFlags; + } + + basic_ostream &formatInteger(uint64_t a_uValue, uint32_t a_fFlags, unsigned a_uBase = 0) + { + a_fFlags |= intGetIntegerFlags(); + char szTmp[72]; + int cchTmp = RTStrFormatNumber(szTmp, a_uValue, !a_uBase ? intGetIntegerBase() : a_uBase, 0, 0, a_fFlags); + + /** @todo apply cchWidth and padding. */ + + return intWrite(szTmp, cchTmp); + } + + /** @} */ + }; + + /** @name Character and string output. + * @{ */ + /** @todo not sure if this really works... */ + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, char a_ch) + { + return a_rDst.put(a_ch); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, const char *a_psz) + { + return a_rDst.intWrite(a_psz, strlen(a_psz)); + } + /** @} */ + + /** @name Integer formatting. + * @{ */ + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, signed char a_iValue) + { + return a_rDst.formatInteger(a_iValue, RTSTR_F_8BIT | RTSTR_F_VALSIGNED); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned char a_uValue) + { + return a_rDst.formatInteger(a_uValue, RTSTR_F_8BIT); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, short a_iValue) + { + return a_rDst.formatInteger(a_iValue, RTSTR_F_16BIT | RTSTR_F_VALSIGNED); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned short a_uValue) + { + return a_rDst.formatInteger(a_uValue, RTSTR_F_16BIT); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, int a_iValue) + { + return a_rDst.formatInteger(a_iValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned int a_uValue) + { + return a_rDst.formatInteger(a_uValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, long a_iValue) + { + return a_rDst.formatInteger(a_iValue, (sizeof(a_iValue) > sizeof(int32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT)); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned long a_uValue) + { + return a_rDst.formatInteger(a_uValue, + RTSTR_F_VALSIGNED | (sizeof(a_uValue) > sizeof(uint32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT)); + } + + template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > + basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, void const *a_pvValue) + { + return a_rDst.formatInteger((uintptr_t)a_pvValue, + (sizeof(a_pvValue) > sizeof(uint32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT), 16); + } + /** @} */ + + template<> + inline basic_ostream<char> &basic_ostream<char>::intWrite(const char *a_pchSrc, std::streamsize a_cchToWrite) + { + return write(a_pchSrc, a_cchToWrite); + } + + +} + +#endif /* !VBOX_INCLUDED_SRC_nocrt_ostream */ + |