/** @file * IPRT / No-CRT - Minimal C++ ostream header. */ /* * Copyright (C) 2022-2023 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 . * * 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 namespace std { /** * Basic output stream. */ template*/ > class basic_ostream : public basic_ios { public: typedef a_CharType char_type; typedef a_CharTraits traits_type; typedef typename a_CharTraits::int_type int_type; typedef typename a_CharTraits::pos_type pos_type; typedef typename a_CharTraits::off_type off_type; 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(ios::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_pBuf) : basic_ios(a_pBuf) { } /** For cerr initialization. * @internal */ explicit basic_ostream(std::basic_streambuf *a_pBuf, std::basic_ostream *a_pTiedStream, bool a_fUnbuffered) : basic_ios(a_pBuf) { this->m_pTiedStream = a_pTiedStream; if (!a_fUnbuffered) this->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(a_CharType a_ch) { sentry PrePost(*this); if (PrePost) { if (this->m_pBuf->sputc(a_ch) == traits_type::eof()) this->m_fState |= ios::badbit; } return *this; } basic_ostream &write(const a_CharType *a_pchSrc, std::streamsize a_cchToWrite) { sentry PrePost(*this); if (PrePost) { std::streamsize cchWritten = this->m_pBuf->sputn(a_pchSrc, a_cchToWrite); if (cchWritten != a_cchToWrite) this->m_fState |= ios::badbit; } return *this; } basic_ostream &flush() { if (this->m_pBuf) this->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, ios::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 (this->m_fFlags & ios::basefield) { default: case ios::dec: return 10; case ios::hex: return 16; case ios::oct: return 8; } } /** @returns RTSTR_F_XXX . */ inline unsigned intGetIntegerFlags() const RT_NOEXCEPT { unsigned fFlags = 0; if (this->m_fFlags & ios::uppercase) fFlags |= RTSTR_F_CAPITAL; if (this->m_fFlags & ios::showbase) fFlags |= RTSTR_F_SPECIAL; if (this->m_fFlags & ios::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 > basic_ostream &operator<<(basic_ostream &a_rDst, char a_ch) { return a_rDst.put(a_ch); } template > basic_ostream &operator<<(basic_ostream &a_rDst, const char *a_psz) { return a_rDst.intWrite(a_psz, strlen(a_psz)); } /** @} */ /** @name Integer formatting. * @{ */ template > basic_ostream &operator<<(basic_ostream &a_rDst, signed char a_iValue) { return a_rDst.formatInteger(a_iValue, RTSTR_F_8BIT | RTSTR_F_VALSIGNED); } template > basic_ostream &operator<<(basic_ostream &a_rDst, unsigned char a_uValue) { return a_rDst.formatInteger(a_uValue, RTSTR_F_8BIT); } template > basic_ostream &operator<<(basic_ostream &a_rDst, short a_iValue) { return a_rDst.formatInteger(a_iValue, RTSTR_F_16BIT | RTSTR_F_VALSIGNED); } template > basic_ostream &operator<<(basic_ostream &a_rDst, unsigned short a_uValue) { return a_rDst.formatInteger(a_uValue, RTSTR_F_16BIT); } template > basic_ostream &operator<<(basic_ostream &a_rDst, int a_iValue) { return a_rDst.formatInteger(a_iValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED); } template > basic_ostream &operator<<(basic_ostream &a_rDst, unsigned int a_uValue) { return a_rDst.formatInteger(a_uValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED); } template > basic_ostream &operator<<(basic_ostream &a_rDst, long a_iValue) { return a_rDst.formatInteger(a_iValue, (sizeof(a_iValue) > sizeof(int32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT)); } template > basic_ostream &operator<<(basic_ostream &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 > basic_ostream &operator<<(basic_ostream &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 &basic_ostream::intWrite(const char *a_pchSrc, std::streamsize a_cchToWrite) { return write(a_pchSrc, a_cchToWrite); } } #endif /* !VBOX_INCLUDED_SRC_nocrt_ostream */