zoukankan      html  css  js  c++  java
  • c++标准库sstream文件

    // sstream standard header
    
    // Copyright (c) Microsoft Corporation.
    // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
    
    #pragma once
    #ifndef _SSTREAM_
    #define _SSTREAM_
    #include <yvals_core.h>
    #if _STL_COMPILER_PREPROCESSOR
    #include <istream>
    #include <string>
    
    #pragma pack(push, _CRT_PACKING)
    #pragma warning(push, _STL_WARNING_LEVEL)
    #pragma warning(disable : _STL_DISABLED_WARNINGS)
    _STL_DISABLE_CLANG_WARNINGS
    #pragma push_macro("new")
    #undef new
    _STD_BEGIN
    
    // CLASS TEMPLATE basic_stringbuf
    template <class _Elem, class _Traits, class _Alloc>
    class basic_stringbuf
        : public basic_streambuf<_Elem, _Traits> { // stream buffer maintaining an allocated character array
    public:
        using allocator_type = _Alloc;
        using _Mysb          = basic_streambuf<_Elem, _Traits>;
        using _Mystr         = basic_string<_Elem, _Traits, _Alloc>;
        using _Mysize_type   = typename _Mystr::size_type;
    
        explicit basic_stringbuf(ios_base::openmode _Mode = ios_base::in | ios_base::out)
            : _Seekhigh(nullptr), _Mystate(_Getstate(_Mode)), _Al() {}
    
        explicit basic_stringbuf(const _Mystr& _Str, ios_base::openmode _Mode = ios_base::in | ios_base::out)
            : _Al(_Str.get_allocator()) {
            _Init(_Str.c_str(), _Str.size(), _Getstate(_Mode));
        }
    
        basic_stringbuf(basic_stringbuf&& _Right) {
            _Assign_rv(_STD move(_Right));
        }
    
        basic_stringbuf& operator=(basic_stringbuf&& _Right) {
            _Assign_rv(_STD move(_Right));
            return *this;
        }
    
        void _Assign_rv(basic_stringbuf&& _Right) {
            if (this != _STD addressof(_Right)) {
                _Tidy();
                this->swap(_Right);
            }
        }
    
        void swap(basic_stringbuf& _Right) {
            if (this != _STD addressof(_Right)) {
                _Mysb::swap(_Right);
                _STD swap(_Seekhigh, _Right._Seekhigh);
                _STD swap(_Mystate, _Right._Mystate);
                _Swap_adl(_Al, _Right._Al);
            }
        }
    
        basic_stringbuf(const basic_stringbuf&) = delete;
        basic_stringbuf& operator=(const basic_stringbuf&) = delete;
    
        virtual ~basic_stringbuf() noexcept {
            _Tidy();
        }
    
        enum { // constants for bits in stream state
            _Allocated = 1, // set if character array storage has been allocated, eback() points to allocated storage
            _Constant  = 2, // set if character array nonmutable
            _Noread    = 4, // set if character array cannot be read
            _Append    = 8, // set if all writes are appends
            _Atend     = 16 // set if initial writes are appends
        };
    
        using int_type = typename _Traits::int_type;
        using pos_type = typename _Traits::pos_type;
        using off_type = typename _Traits::off_type;
    
        _NODISCARD _Mystr str() const {
            _Mystr _Result(_Al);
            if (!(_Mystate & _Constant) && _Mysb::pptr()) { // writable, make string from write buffer
                const auto _Base = _Mysb::pbase();
                _Result.assign(_Base, static_cast<_Mysize_type>(_Max_value(_Mysb::pptr(), _Seekhigh) - _Base));
            } else if (!(_Mystate & _Noread) && _Mysb::gptr()) { // readable, make string from read buffer
                const auto _Base = _Mysb::eback();
                _Result.assign(_Base, static_cast<_Mysize_type>(_Mysb::egptr() - _Base));
            }
    
            return _Result;
        }
    
        void str(const _Mystr& _Newstr) { // replace character array from string
            _Tidy();
            _Init(_Newstr.c_str(), _Newstr.size(), _Mystate);
        }
    
    protected:
        virtual int_type overflow(int_type _Meta = _Traits::eof()) { // put an element to stream
            if (_Mystate & _Constant) {
                return _Traits::eof(); // array nonmutable, fail
            }
    
            if (_Traits::eq_int_type(_Traits::eof(), _Meta)) {
                return _Traits::not_eof(_Meta); // EOF, return success code
            }
    
            const auto _Pptr  = _Mysb::pptr();
            const auto _Epptr = _Mysb::epptr();
            if (_Pptr && _Pptr < _Epptr) { // room in buffer, store it
                *_Mysb::_Pninc() = _Traits::to_char_type(_Meta);
                _Seekhigh        = _Pptr + 1;
                return _Meta;
            }
    
            // grow buffer and store element
            size_t _Oldsize    = 0;
            const auto _Oldptr = _Mysb::eback();
            if (_Pptr) {
                _Oldsize = static_cast<size_t>(_Epptr - _Oldptr);
            }
    
            size_t _Newsize;
            if (_Oldsize < _MINSIZE) {
                _Newsize = _MINSIZE;
            } else if (_Oldsize < INT_MAX / 2) { // grow by 50 percent
                _Newsize = _Oldsize << 1;
            } else if (_Oldsize < INT_MAX) {
                _Newsize = INT_MAX;
            } else { // buffer can't grow, fail
                return _Traits::eof();
            }
    
            const auto _Newptr = _Unfancy(_Al.allocate(_Newsize));
            _Traits::copy(_Newptr, _Oldptr, _Oldsize);
    
            const auto _New_pnext = _Newptr + _Oldsize;
            _Seekhigh             = _New_pnext + 1; // to include _Meta
    
            _Mysb::setp(_Newptr, _New_pnext, _Newptr + _Newsize);
            if (_Mystate & _Noread) { // maintain eback() == allocated pointer invariant
                _Mysb::setg(_Newptr, nullptr, _Newptr);
            } else { // if readable, set the get area to initialized region
                _Mysb::setg(_Newptr, _Newptr + (_Mysb::gptr() - _Oldptr), _Seekhigh);
            }
    
            if (_Mystate & _Allocated) {
                _Al.deallocate(_Ptr_traits::pointer_to(*_Oldptr), _Oldsize);
            }
    
            _Mystate |= _Allocated;
            *_Mysb::_Pninc() = _Traits::to_char_type(_Meta);
            return _Meta;
        }
    
        virtual int_type pbackfail(int_type _Meta = _Traits::eof()) { // put an element back to stream
            const auto _Gptr = _Mysb::gptr();
            if (!_Gptr || _Gptr <= _Mysb::eback()
                || (!_Traits::eq_int_type(_Traits::eof(), _Meta) && !_Traits::eq(_Traits::to_char_type(_Meta), _Gptr[-1])
                    && (_Mystate & _Constant))) { // can't put back, fail
                return _Traits::eof();
            }
    
            // back up one position and store put-back character
            _Mysb::gbump(-1);
            if (!_Traits::eq_int_type(_Traits::eof(), _Meta)) {
                *_Mysb::gptr() = _Traits::to_char_type(_Meta);
            }
    
            return _Traits::not_eof(_Meta);
        }
    
        virtual int_type underflow() { // get an element from stream, but don't point past it
            const auto _Gptr = _Mysb::gptr();
            if (!_Gptr) { // no character buffer, fail
                return _Traits::eof();
            }
    
            if (_Gptr < _Mysb::egptr()) {
                return _Traits::to_int_type(*_Gptr);
            }
    
            // try to add initialized characters from the put area into the get area
            const auto _Pptr = _Mysb::pptr();
            if (!_Pptr || (_Mystate & _Noread)) { // no put area or read disallowed
                return _Traits::eof();
            }
    
            const auto _Local_highwater = _Max_value(_Seekhigh, _Pptr);
            if (_Local_highwater <= _Gptr) { // nothing in the put area to take
                return _Traits::eof();
            }
    
            _Seekhigh = _Local_highwater;
            _Mysb::setg(_Mysb::eback(), _Mysb::gptr(), _Local_highwater);
            return _Traits::to_int_type(*_Mysb::gptr());
        }
    
        virtual pos_type seekoff(
            off_type _Off, ios_base::seekdir _Way, ios_base::openmode _Mode = ios_base::in | ios_base::out) {
            // change position by _Off, according to _Way, _Mode
            const auto _Gptr_old = _Mysb::gptr();
            const auto _Pptr_old = _Mysb::pptr();
            if (_Pptr_old && _Seekhigh < _Pptr_old) { // update high-water pointer
                _Seekhigh = _Pptr_old;
            }
    
            const auto _Seeklow  = _Mysb::eback();
            const auto _Seekdist = _Seekhigh - _Seeklow;
            off_type _Newoff;
            switch (_Way) {
            case ios_base::beg:
                _Newoff = 0;
                break;
            case ios_base::end:
                _Newoff = _Seekdist;
                break;
            case ios_base::cur: {
                constexpr auto _Both = ios_base::in | ios_base::out;
                if ((_Mode & _Both) != _Both) { // prohibited by N4727 [stringbuf.virtuals] Table 107 "seekoff positioning"
                    if (_Mode & ios_base::in) {
                        if (_Gptr_old || !_Seeklow) {
                            _Newoff = _Gptr_old - _Seeklow;
                            break;
                        }
                    } else if ((_Mode & ios_base::out) && (_Pptr_old || !_Seeklow)) {
                        _Newoff = _Pptr_old - _Seeklow;
                        break;
                    }
                }
            }
    
                // fallthrough
            default:
                return pos_type(off_type(-1));
            }
    
            if (static_cast<unsigned long long>(_Off) + _Newoff > static_cast<unsigned long long>(_Seekdist)) {
                return pos_type(off_type(-1));
            }
    
            _Off += _Newoff;
            if (_Off != 0 && (((_Mode & ios_base::in) && !_Gptr_old) || ((_Mode & ios_base::out) && !_Pptr_old))) {
                return pos_type(off_type(-1));
            }
    
            const auto _Newptr = _Seeklow + _Off; // may perform nullptr + 0
            if ((_Mode & ios_base::in) && _Gptr_old) {
                _Mysb::setg(_Seeklow, _Newptr, _Seekhigh);
            }
    
            if ((_Mode & ios_base::out) && _Pptr_old) {
                _Mysb::setp(_Seeklow, _Newptr, _Mysb::epptr());
            }
    
            return pos_type(_Off);
        }
    
        virtual pos_type seekpos(pos_type _Pos, ios_base::openmode _Mode = ios_base::in | ios_base::out) {
            // change position to _Pos, according to _Mode
            const auto _Off      = static_cast<streamoff>(_Pos);
            const auto _Gptr_old = _Mysb::gptr();
            const auto _Pptr_old = _Mysb::pptr();
            if (_Pptr_old && _Seekhigh < _Pptr_old) { // update high-water pointer
                _Seekhigh = _Pptr_old;
            }
    
            const auto _Seeklow  = _Mysb::eback();
            const auto _Seekdist = _Seekhigh - _Seeklow;
            if (static_cast<unsigned long long>(_Off) > static_cast<unsigned long long>(_Seekdist)) {
                return pos_type(off_type(-1));
            }
    
            if (_Off != 0 && (((_Mode & ios_base::in) && !_Gptr_old) || ((_Mode & ios_base::out) && !_Pptr_old))) {
                return pos_type(off_type(-1));
            }
    
            const auto _Newptr = _Seeklow + _Off; // may perform nullptr + 0
            if ((_Mode & ios_base::in) && _Gptr_old) {
                _Mysb::setg(_Seeklow, _Newptr, _Seekhigh);
            }
    
            if ((_Mode & ios_base::out) && _Pptr_old) {
                _Mysb::setp(_Seeklow, _Newptr, _Mysb::epptr());
            }
    
            return pos_type(_Off);
        }
    
    protected:
        void _Init(const _Elem* _Ptr, _Mysize_type _Count, int _State) {
            // initialize buffer to [_Ptr, _Ptr + _Count), set state
            if (_Count > INT_MAX) { // TRANSITION, VSO#485517
                _Xbad_alloc();
            }
    
            if (_Count != 0
                && (_State & (_Noread | _Constant))
                       != (_Noread | _Constant)) { // finite buffer that can be read or written, set it up
                const auto _Pnew = _Unfancy(_Al.allocate(_Count));
                _Traits::copy(_Pnew, _Ptr, _Count);
                _Seekhigh = _Pnew + _Count;
    
                if (!(_State & _Noread)) {
                    _Mysb::setg(_Pnew, _Pnew, _Seekhigh); // setup read buffer
                }
    
                if (!(_State & _Constant)) { // setup write buffer, and maybe read buffer
                    _Mysb::setp(_Pnew, (_State & (_Atend | _Append)) ? _Seekhigh : _Pnew, _Seekhigh);
    
                    if (_State & _Noread) { // maintain "_Allocated == eback() points to buffer base" invariant
                        _Mysb::setg(_Pnew, nullptr, _Pnew);
                    }
                }
    
                _State |= _Allocated;
            } else {
                _Seekhigh = nullptr;
            }
    
            _Mystate = _State;
        }
    
        void _Tidy() noexcept { // discard any allocated buffer and clear pointers
            if (_Mystate & _Allocated) {
                _Al.deallocate(_Ptr_traits::pointer_to(*_Mysb::eback()),
                    static_cast<typename allocator_traits<allocator_type>::size_type>(
                        (_Mysb::pptr() ? _Mysb::epptr() : _Mysb::egptr()) - _Mysb::eback()));
            }
    
            _Mysb::setg(nullptr, nullptr, nullptr);
            _Mysb::setp(nullptr, nullptr);
            _Seekhigh = nullptr;
            _Mystate &= ~_Allocated;
        }
    
    private:
        using _Ptr_traits = pointer_traits<typename allocator_traits<allocator_type>::pointer>;
    
        enum { // constant for minimum buffer size
            _MINSIZE = 32
        };
    
        static int _Getstate(ios_base::openmode _Mode) { // convert open mode to stream state bits
            int _State = 0;
            if (!(_Mode & ios_base::in)) {
                _State |= _Noread;
            }
    
            if (!(_Mode & ios_base::out)) {
                _State |= _Constant;
            }
    
            if (_Mode & ios_base::app) {
                _State |= _Append;
            }
    
            if (_Mode & ios_base::ate) {
                _State |= _Atend;
            }
    
            return _State;
        }
    
        _Elem* _Seekhigh; // the high-water pointer in character array
        int _Mystate; // the stream state
        allocator_type _Al; // the allocator object
    };
    
    template <class _Elem, class _Traits, class _Alloc>
    void swap(basic_stringbuf<_Elem, _Traits, _Alloc>& _Left, basic_stringbuf<_Elem, _Traits, _Alloc>& _Right) {
        _Left.swap(_Right);
    }
    
    // CLASS TEMPLATE basic_istringstream
    template <class _Elem, class _Traits, class _Alloc>
    class basic_istringstream : public basic_istream<_Elem, _Traits> { // input stream associated with a character array
    public:
        using _Mybase        = basic_istream<_Elem, _Traits>;
        using allocator_type = _Alloc;
        using _Mysb          = basic_stringbuf<_Elem, _Traits, _Alloc>;
        using _Mystr         = basic_string<_Elem, _Traits, _Alloc>;
    
        explicit basic_istringstream(ios_base::openmode _Mode = ios_base::in)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Mode | ios_base::in) {}
    
        explicit basic_istringstream(const _Mystr& _Str, ios_base::openmode _Mode = ios_base::in)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::in) {}
    
        basic_istringstream(basic_istringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) {
            _Assign_rv(_STD move(_Right));
        }
    
        basic_istringstream& operator=(basic_istringstream&& _Right) {
            _Assign_rv(_STD move(_Right));
            return *this;
        }
    
        void _Assign_rv(basic_istringstream&& _Right) {
            if (this != _STD addressof(_Right)) {
                _Stringbuffer.str(_Mystr());
                this->swap(_Right);
            }
        }
    
        void swap(basic_istringstream& _Right) {
            if (this != _STD addressof(_Right)) {
                _Mybase::swap(_Right);
                _Stringbuffer.swap(_Right._Stringbuffer);
            }
        }
    
        basic_istringstream(const basic_istringstream&) = delete;
        basic_istringstream& operator=(const basic_istringstream&) = delete;
    
        virtual ~basic_istringstream() noexcept {}
    
        _NODISCARD _Mysb* rdbuf() const {
            return const_cast<_Mysb*>(_STD addressof(_Stringbuffer));
        }
    
        _NODISCARD _Mystr str() const {
            return _Stringbuffer.str();
        }
    
        void str(const _Mystr& _Newstr) { // replace character array from string
            _Stringbuffer.str(_Newstr);
        }
    
    private:
        _Mysb _Stringbuffer;
    };
    
    template <class _Elem, class _Traits, class _Alloc>
    void swap(basic_istringstream<_Elem, _Traits, _Alloc>& _Left, basic_istringstream<_Elem, _Traits, _Alloc>& _Right) {
        _Left.swap(_Right);
    }
    
    // CLASS TEMPLATE basic_ostringstream
    template <class _Elem, class _Traits, class _Alloc>
    class basic_ostringstream : public basic_ostream<_Elem, _Traits> { // output stream associated with a character array
    public:
        using _Mybase        = basic_ostream<_Elem, _Traits>;
        using allocator_type = _Alloc;
        using _Mysb          = basic_stringbuf<_Elem, _Traits, _Alloc>;
        using _Mystr         = basic_string<_Elem, _Traits, _Alloc>;
    
        explicit basic_ostringstream(ios_base::openmode _Mode = ios_base::out)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Mode | ios_base::out) {}
    
        explicit basic_ostringstream(const _Mystr& _Str, ios_base::openmode _Mode = ios_base::out)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode | ios_base::out) {}
    
        basic_ostringstream(basic_ostringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) {
            _Assign_rv(_STD move(_Right));
        }
    
        basic_ostringstream& operator=(basic_ostringstream&& _Right) {
            _Assign_rv(_STD move(_Right));
            return *this;
        }
    
        void _Assign_rv(basic_ostringstream&& _Right) {
            if (this != _STD addressof(_Right)) {
                _Stringbuffer.str(_Mystr());
                this->swap(_Right);
            }
        }
    
        void swap(basic_ostringstream& _Right) {
            if (this != _STD addressof(_Right)) {
                _Mybase::swap(_Right);
                _Stringbuffer.swap(_Right._Stringbuffer);
            }
        }
    
        basic_ostringstream(const basic_ostringstream&) = delete;
        basic_ostringstream& operator=(const basic_ostringstream&) = delete;
    
        virtual ~basic_ostringstream() noexcept {}
    
        _NODISCARD _Mysb* rdbuf() const {
            return const_cast<_Mysb*>(_STD addressof(_Stringbuffer));
        }
    
        _NODISCARD _Mystr str() const {
            return _Stringbuffer.str();
        }
    
        void str(const _Mystr& _Newstr) { // replace character array from string
            _Stringbuffer.str(_Newstr);
        }
    
    private:
        _Mysb _Stringbuffer;
    };
    
    template <class _Elem, class _Traits, class _Alloc>
    void swap(basic_ostringstream<_Elem, _Traits, _Alloc>& _Left, basic_ostringstream<_Elem, _Traits, _Alloc>& _Right) {
        _Left.swap(_Right);
    }
    
    // CLASS TEMPLATE basic_stringstream
    template <class _Elem, class _Traits, class _Alloc>
    class basic_stringstream
        : public basic_iostream<_Elem, _Traits> { // input/output stream associated with a character array
    public:
        using _Mybase        = basic_iostream<_Elem, _Traits>;
        using char_type      = _Elem;
        using traits_type    = _Traits;
        using allocator_type = _Alloc;
        using int_type       = typename _Traits::int_type;
        using pos_type       = typename _Traits::pos_type;
        using off_type       = typename _Traits::off_type;
        using _Mysb          = basic_stringbuf<_Elem, _Traits, _Alloc>;
        using _Mystr         = basic_string<_Elem, _Traits, _Alloc>;
    
        explicit basic_stringstream(ios_base::openmode _Mode = ios_base::in | ios_base::out)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Mode) {}
    
        explicit basic_stringstream(const _Mystr& _Str, ios_base::openmode _Mode = ios_base::in | ios_base::out)
            : _Mybase(_STD addressof(_Stringbuffer)), _Stringbuffer(_Str, _Mode) {}
    
        basic_stringstream(basic_stringstream&& _Right) : _Mybase(_STD addressof(_Stringbuffer)) {
            _Assign_rv(_STD move(_Right));
        }
    
        basic_stringstream& operator=(basic_stringstream&& _Right) {
            _Assign_rv(_STD move(_Right));
            return *this;
        }
    
        void _Assign_rv(basic_stringstream&& _Right) {
            if (this != _STD addressof(_Right)) {
                _Stringbuffer.str(_Mystr());
                this->swap(_Right);
            }
        }
    
        void swap(basic_stringstream& _Right) {
            if (this != _STD addressof(_Right)) {
                _Mybase::swap(_Right);
                _Stringbuffer.swap(_Right._Stringbuffer);
            }
        }
    
        basic_stringstream(const basic_stringstream&) = delete;
        basic_stringstream& operator=(const basic_stringstream&) = delete;
    
        virtual ~basic_stringstream() noexcept {}
    
        _NODISCARD _Mysb* rdbuf() const {
            return const_cast<_Mysb*>(_STD addressof(_Stringbuffer));
        }
    
        _NODISCARD _Mystr str() const {
            return _Stringbuffer.str();
        }
    
        void str(const _Mystr& _Newstr) { // replace character array from string
            _Stringbuffer.str(_Newstr);
        }
    
    private:
        _Mysb _Stringbuffer;
    };
    
    template <class _Elem, class _Traits, class _Alloc>
    void swap(basic_stringstream<_Elem, _Traits, _Alloc>& _Left, basic_stringstream<_Elem, _Traits, _Alloc>& _Right) {
        _Left.swap(_Right);
    }
    _STD_END
    #pragma pop_macro("new")
    _STL_RESTORE_CLANG_WARNINGS
    #pragma warning(pop)
    #pragma pack(pop)
    #endif // _STL_COMPILER_PREPROCESSOR
    #endif // _SSTREAM_
    
    
  • 相关阅读:
    第二阶段个人总结八
    第二阶段个人总结七
    第二阶段个人总结六
    第二阶段个人总结五
    电梯演说模板练习
    对敏捷开发的理解
    团队的不同形式
    认识JQuery的三天--看视频得到的一些小知识点
    结对编码
    结对互评
  • 原文地址:https://www.cnblogs.com/coding365/p/12872391.html
Copyright © 2011-2022 走看看