HelenOS sources

root/uspace/lib/cpp/include/__bits/string/string_io.hpp

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

DEFINITIONS

This source file includes following definitions.
  1. getline
  2. getline
  3. getline
  4. getline

/*
 * 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_STRING_IO
#define LIBCPP_BITS_STRING_IO

#include <__bits/string/string.hpp>
#include <ios>

namespace std
{
    /**
     * 21.4.8.9, inserters and extractors:
     */

    template<class Char, class Traits, class Allocator>
    basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is,
                                            basic_string<Char, Traits, Allocator>& str)
    {
        using sentry = typename basic_istream<Char, Traits>::sentry;
        sentry sen{is, false};

        if (sen)
        {
            str.erase();

            auto max_size = is.width();
            if (max_size <= 0)
                max_size = static_cast<streamsize>(str.max_size());

            streamsize i{};
            for(; i < max_size; ++i)
            {
                auto ic = is.rdbuf()->sgetc();
                if (Traits::eq_int_type(ic, Traits::eof()))
                {
                    is.setstate(ios_base::eofbit);
                    break;
                }

                auto c = Traits::to_char_type(ic);
                if(isspace(c, is.getloc()))
                    break;

                str.push_back(c);
                is.rdbuf()->sbumpc();
            }

            if (i == 0)
                is.setstate(ios_base::failbit);
        }
        else
            is.setstate(ios_base::failbit);

        return is;
    }

    template<class Char, class Traits, class Allocator>
    basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
                                            const basic_string<Char, Traits, Allocator>& str)
    {
        // TODO: determine padding as described in 27.7.3.6.1
        using sentry = typename basic_ostream<Char, Traits>::sentry;
        sentry sen{os};

        if (sen)
        {
            auto width = os.width();
            auto size = str.size();

            size_t to_pad{};
            if (width > 0)
                to_pad = (static_cast<size_t>(width) - size);

            if (to_pad > 0)
            {
                if ((os.flags() & ios_base::adjustfield) != ios_base::left)
                {
                    for (std::size_t i = 0; i < to_pad; ++i)
                        os.put(os.fill());
                }

                os.rdbuf()->sputn(str.data(), size);

                if ((os.flags() & ios_base::adjustfield) == ios_base::left)
                {
                    for (std::size_t i = 0; i < to_pad; ++i)
                        os.put(os.fill());
                }
            }
            else
                os.rdbuf()->sputn(str.data(), size);

            os.width(0);
        }

        return os;
    }

    template<class Char, class Traits, class Allocator>
    basic_istream<Char, Traits>& getline(basic_istream<Char, Traits>& is,
                                         basic_string<Char, Traits, Allocator>& str,
                                         Char delim)
    {
        typename basic_istream<Char, Traits>::sentry sen{is, true};

        if (sen)
        {
            str.clear();
            streamsize count{};

            while (true)
            {
                auto ic = is.rdbuf()->sbumpc();
                if (Traits::eq_int_type(ic, Traits::eof()))
                {
                    is.setstate(ios_base::eofbit);
                    break;
                }

                auto c = Traits::to_char_type(ic);
                if (Traits::eq(c, delim))
                    break;

                str.push_back(c);
                ++count;

                if (count >= static_cast<streamsize>(str.max_size()))
                {
                    is.setstate(ios_base::failbit);
                    break;
                }
            }

            if (count == 0)
                is.setstate(ios_base::failbit);
        }
        else
            is.setstate(ios_base::failbit);

        return is;
    }

    template<class Char, class Traits, class Allocator>
    basic_istream<Char, Traits>& getline(basic_istream<Char, Traits>&& is,
                                         basic_string<Char, Traits, Allocator>& str,
                                         Char delim)
    {
        return getline(is, str, delim);
    }

    template<class Char, class Traits, class Allocator>
    basic_istream<Char, Traits>& getline(basic_istream<Char, Traits>& is,
                                         basic_string<Char, Traits, Allocator>& str)
    {
        return getline(is, str, is.widen('\n'));
    }

    template<class Char, class Traits, class Allocator>
    basic_istream<Char, Traits>& getline(basic_istream<Char, Traits>&& is,
                                         basic_string<Char, Traits, Allocator>& str)
    {
        return getline(is, str, is.widen('\n'));
    }
}

#endif

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