HelenOS sources

root/uspace/lib/cpp/include/__bits/io/streambufs.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. underflow
  2. uflow
  3. imbue
  4. overflow
  5. xsputn
  6. sync

/*
 * Copyright (c) 2018 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_BITS_IO_STREAMBUFS
#define LIBCPP_BITS_IO_STREAMBUFS

#include <iosfwd>
#include <cstdio>
#include <streambuf>

namespace std::aux
{
    template<class Char, class Traits = char_traits<Char>>
    class stdin_streambuf : public basic_streambuf<Char, Traits>
    {
        public:
            stdin_streambuf()
                : basic_streambuf<Char, Traits>{}, buffer_{nullptr}
            { /* DUMMY BODY */ }

            virtual ~stdin_streambuf()
            {
                if (buffer_)
                    delete[] buffer_;
            }

        protected:
            using traits_type = Traits;
            using char_type   = typename traits_type::char_type;
            using int_type    = typename traits_type::int_type;
            using off_type    = typename traits_type::off_type;

            using basic_streambuf<Char, Traits>::input_begin_;
            using basic_streambuf<Char, Traits>::input_next_;
            using basic_streambuf<Char, Traits>::input_end_;

            int_type underflow() override
            {
                if (!this->gptr())
                {
                    buffer_ = new char_type[buf_size_];
                    input_begin_ = input_next_ = input_end_ = buffer_;
                }

                off_type i{};
                if (input_next_ < input_end_)
                {
                    auto idx = static_cast<off_type>(input_next_ - input_begin_);
                    auto count = buf_size_ - idx;

                    for (; i < count; ++i, ++idx)
                        buffer_[i] = buffer_[idx];
                }

                for (; i < buf_size_; ++i)
                {
                    auto c = fgetc(in_);
                    putchar(c); // TODO: Temporary source of feedback.
                    if (c == traits_type::eof())
                        break;

                    buffer_[i] = static_cast<char_type>(c);

                    if (buffer_[i] == '\n')
                    {
                        ++i;
                        break;
                    }
                }

                input_next_ = input_begin_;
                input_end_ = input_begin_ + i;

                if (i == 0)
                    return traits_type::eof();

                return traits_type::to_int_type(*input_next_);
            }

            int_type uflow() override
            {
                auto res = underflow();
                ++input_next_;

                return res;
            }

            void imbue(const locale& loc)
            {
                this->locale_ = loc;
            }

        private:
            FILE* in_{stdin};

            char_type* buffer_;

            static constexpr off_type buf_size_{128};
    };

    template<class Char, class Traits = char_traits<Char>>
    class stdout_streambuf: public basic_streambuf<Char, Traits>
    {
        public:
            stdout_streambuf()
                : basic_streambuf<Char, Traits>{}
            { /* DUMMY BODY */ }

            virtual ~stdout_streambuf()
            { /* DUMMY BODY */ }

        protected:
            using traits_type = Traits;
            using char_type   = typename traits_type::char_type;
            using int_type    = typename traits_type::int_type;
            using off_type    = typename traits_type::off_type;

            int_type overflow(int_type c = traits_type::eof()) override
            {
                if (!traits_type::eq_int_type(c, traits_type::eof()))
                {
                    auto cc = traits_type::to_char_type(c);
                    fwrite(&cc, sizeof(char_type), 1, out_);
                }

                return traits_type::not_eof(c);
            }

            streamsize xsputn(const char_type* s, streamsize n) override
            {
                return fwrite(s, sizeof(char_type), n, out_);
            }

            int sync() override
            {
                if (fflush(out_))
                    return -1;
                return 0;
            }

        private:
            FILE* out_{stdout};
    };
}

#endif

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub