/*  Copyright (C) 2015  Povilas Kanapickas <povilas@radix.lt>

    This file is part of cppreference-doc

    This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
    Unported License. To view a copy of this license, visit
    http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
    Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.3 or
    any later version published by the Free Software Foundation; with no
    Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
*/

#ifndef CPPREFERENCE_ISTREAM_H
#define CPPREFERENCE_ISTREAM_H

namespace std {

template <
    class CharT,
    class Traits = std::char_traits<CharT>
    > class basic_istream : virtual public std::basic_ios<CharT, Traits> {
public:
    explicit basic_istream(std::basic_streambuf<CharT, Traits>* sb);
    virtual ~basic_istream();

    basic_istream& operator>>(short& value);
    basic_istream& operator>>(unsigned short& value);
    basic_istream& operator>>(int& value);
    basic_istream& operator>>(unsigned int& value);
    basic_istream& operator>>(long& value);
    basic_istream& operator>>(unsigned long& value);
#if CPPREFERENCE_STDVER>= 2011
    basic_istream& operator>>(long long& value);
    basic_istream& operator>>(unsigned long long& value);
#endif
    basic_istream& operator>>(float& value);
    basic_istream& operator>>(double& value);
    basic_istream& operator>>(long double& value);
    basic_istream& operator>>(bool& value);
    basic_istream& operator>>(void*& value);
    basic_istream& operator>>(basic_istream& st,
                              std::ios_base & (*func)(std::ios_base&));
    basic_istream& operator>>(basic_istream& st,
                              std::basic_ios<CharT, Traits>& (*func)(std::basic_ios<CharT, Traits>&));
    basic_istream& operator>>(basic_istream& st,
                              std::basic_istream & (*func)(std::basic_istream&));
    basic_istream& operator>>(basic_istream& st,
                              std::basic_streambuf<CharT, Traits>* sb);

    int_type get();
    basic_istream& get(char_type& ch);
    basic_istream& get(char_type* s, std::streamsize count);
    basic_istream& get(char_type* s, std::streamsize count, char_type delim);
    basic_istream& get(basic_streambuf& strbuf);
    basic_istream& get(basic_streambuf& strbuf, char_type delim);

    int_type peek();
    basic_istream& unget();
    basic_istream& putback(char_type ch);
    basic_istream& getline(char_type* s, std::streamsize count);
    basic_istream& getline(char_type* s, std::streamsize count, char_type delim);
    basic_istream& ignore(std::streamsize count = 1, int_type delim = Traits::eof());
    basic_istream& read(char_type* s, std::streamsize count);
    std::streamsize readsome(char_type* s, std::streamsize count);
    std::streamsize gcount() const;
    pos_type tellg();
    basic_istream& seekg(pos_type pos);
    basic_istream& seekg(off_type off, std::ios_base::seekdir dir);
    int sync();

    class sentry {
    public:
        typedef Traits traits_type;
        explicit sentry(std::basic_istream<CharT, Traits>& is, bool noskipws = false);
        ~sentry();
        explicit operator bool() const;
    };

protected:
#if CPPREFERENCE_STDVER>= 2011
    basic_istream(const basic_istream& rhs) = delete;
    basic_istream(basic_istream&& rhs);
#endif

    basic_istream& operator=(const basic_istream& rhs) = delete;
#if CPPREFERENCE_STDVER>= 2011
    basic_istream& operator=(basic_istream&& rhs);
    void swap(basic_istream& rhs);
#endif
};

typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;

extern istream cin;
extern wistream wcin;

template <
    class CharT,
    class Traits = std::char_traits<CharT>
    > class basic_iostream : public std::basic_istream<CharT, Traits>,
    public basic_ostream<CharT, Traits> {
public:
    explicit basic_iostream(std::basic_streambuf<CharT, Traits>* sb);

protected:
#if CPPREFERENCE_STDVER>= 2011
    basic_iostream(const basic_iostream& other) = delete;
    basic_iostream(basic_iostream&& other);
#endif

    basic_iostream& operator=(const basic_iostream& rhs) = delete;
#if CPPREFERENCE_STDVER>= 2011
    basic_iostream& operator=(basic_iostream&& rhs);
    void swap(basic_iostream& rhs);
#endif
};

typedef basic_iostream<char> iostream;
typedef basic_iostream<wchar_t> wiostream;

template<class CharT, class Traits>
basic_istream<CharT, Traits>& operator>>(basic_istream<CharT, Traits>& st, CharT& ch);

template<class Traits>
basic_istream<char, Traits>& operator>>(basic_istream<char, Traits>& st, signed char& ch);

template<class Traits>
basic_istream<char, Traits>& operator>>(basic_istream<char, Traits>& st, unsigned char& ch);

template<class CharT, class Traits>
basic_istream<CharT, Traits>& operator>>(basic_istream<CharT, Traits>& st, CharT* s);

template<class Traits>
basic_istream<char, Traits>& operator>>(basic_istream<char, Traits>& st, signed char* s);

template<class Traits>
basic_istream<char, Traits>& operator>>(basic_istream<char, Traits>& st, unsigned char* s);

template<class CharT, class Traits, class T>
basic_istream<CharT, Traits>& operator>>(basic_istream<CharT, Traits>&& st, T& value);

#if CPPREFERENCE_STDVER>= 2011
template<class CharT, class Traits>
std::basic_istream<CharT, Traits>& ws(std::basic_istream<CharT, Traits>& is);
#endif

} // namespace std

#endif // CPPREFERENCE_ISTREAM_H
