/* * Copyright (c) 2017 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_OSTREAM #define LIBCPP_OSTREAM #include #include #include namespace std { /** * 27.7.3.1, class template basic_ostream: */ template class basic_ostream: virtual public basic_ios { public: using char_type = Char; using traits_type = Traits; using int_type = typename traits_type::int_type; using pos_type = typename traits_type::pos_type; using off_type = typename traits_type::off_type; /** * 27.7.3.2, constructor/destructor: */ explicit basic_ostream(basic_streambuf* sb) { basic_ios::init(sb); } virtual ~basic_ostream() { /* DUMMY BODY */ } /** * 27.7.3.4, prefix/suffix: */ class sentry { public: explicit sentry(basic_ostream& os) : os_{os}, ok_{false} { if (os.good()) { if (os.tie()) os.tie()->flush(); } ok_ = os.good(); } ~sentry() { if ((os_.flags() & ios_base::unitbuf) && os_.good()) { auto ret = os_.rdbuf()->pubsync(); (void)ret; // TODO: if ret == -1, set badbit in rdstate } } explicit operator bool() const { return ok_; } sentry(const sentry&) = delete; sentry& operator=(const sentry&) = delete; private: basic_ostream& os_; bool ok_; }; /** * 27.7.3.6, formatted output: */ basic_ostream& operator<<( basic_ostream& (*pf)(basic_ostream&) ) { return pf(*this); } basic_ostream& operator<<( basic_ios& (*pf)(basic_ios&) ) { pf(*this); return *this; } basic_ostream& operator<<( ios_base& (*pf)(ios_base&) ) { pf(*this); return *this; } basic_ostream& operator<<(bool x) { // TODO: sentry etc /* bool failed = use_facet< */ /* num_put> */ /* >(this->getloc()).put(*this, *this, this->fill(), x).failed(); */ /* if (failed) */ /* this->setstate(ios_base::badbit); */ return *this; } basic_ostream& operator<<(short x) { // TODO: implement return *this; } basic_ostream& operator<<(unsigned short x) { // TODO: implement return *this; } basic_ostream& operator<<(int x) { // TODO: implement return *this; } basic_ostream& operator<<(unsigned int x) { // TODO: implement return *this; } basic_ostream& operator<<(long x) { // TODO: implement return *this; } basic_ostream& operator<<(unsigned long x) { // TODO: implement return *this; } basic_ostream& operator<<(long long x) { // TODO: implement return *this; } basic_ostream& operator<<(unsigned long long x) { // TODO: implement return *this; } basic_ostream& operator<<(float x) { // TODO: implement return *this; } basic_ostream& operator<<(double x) { // TODO: implement return *this; } basic_ostream& operator<<(long double x) { // TODO: implement return *this; } basic_ostream& operator<<(const void* p) { // TODO: implement return *this; } basic_ostream& operator<<(basic_streambuf* sb) { // TODO: implement return *this; } /** * 27.7.3.7, unformatted output: * TODO: when we have exceptions, complete these */ basic_ostream& put(char_type c) { sentry sen{*this}; if (sen) { auto ret = this->rdbuf()->sputc(c); if (traits_type::eq_int_type(ret, traits_type::eof())) this->setstate(ios_base::badbit); } return *this; } basic_ostream& write(const char_type* s, streamsize n) { sentry sen{*this}; if (sen) { for (streamsize i = 0; i < n; ++i) { auto ret = this->rdbuf()->sputc(s[i]); if (traits_type::eq_int_type(ret, traits_type::eof())) { this->setstate(ios_base::badbit); break; } } } return *this; } basic_ostream& flush() { if (this->rdbuf()) { sentry sen{*this}; if (sen) { auto ret = this->rdbuf()->pubsync(); if (ret == -1) this->setstate(ios_base::badbit); } } return *this; } /** * 27.7.3.5, seeks: */ pos_type tellp() { // TODO: implement return pos_type{}; } basic_ostream& seekp(pos_type pos) { // TODO: implement return *this; } basic_ostream& seekp(off_type off, ios_base::seekdir dir) { // TODO: implement return *this; } protected: basic_ostream(const basic_ostream&) = delete; basic_ostream(basic_ostream&& other) { basic_ios::move(other); } /** * 27.7.3.3, assign/swap: */ basic_ostream& operator=(const basic_ostream&) = delete; basic_ostream& operator=(basic_ostream&& other) { swap(other); return *this; } void swap(basic_ostream& rhs) { basic_ios::swap(rhs); } }; using ostream = basic_ostream; using wostream = basic_ostream; template> basic_ostream& endl(basic_ostream& os) { os.put('\n'); os.flush(); return os; } template> basic_ostream& ends(basic_ostream& os); template> basic_ostream& flush(basic_ostream& os); template, class T> basic_ostream& operator<<(basic_ostream& os, const T& x); } #endif