1 /*
2  * Copyright 2009-2017 Alibaba Cloud All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 #include <iostream>
19 
20 namespace AlibabaCloud
21 {
22 namespace OSS
23 {
24 
25 template<class _Elem, class _Traits>
26 class basic_streambuf_proxy : public std::basic_streambuf <_Elem, _Traits>
27 {
28 public:
~basic_streambuf_proxy()29     virtual ~basic_streambuf_proxy() {
30         std::ios_base::iostate state = _Stream->rdstate();
31         _Stream->rdbuf(_Sbuf);
32         _Stream->setstate(state);
33     }
34     using int_type = typename _Traits::int_type;
35     using pos_type = typename _Traits::pos_type;
36     using off_type = typename _Traits::off_type;
37 
38 protected:
basic_streambuf_proxy(std::basic_iostream<_Elem,_Traits> & stream)39     basic_streambuf_proxy(std::basic_iostream<_Elem, _Traits>& stream)
40         : _Stream(&stream)
41         , _Sbuf(_Stream->rdbuf(this)) {
42     }
43 
44     int_type overflow(int_type _Meta = _Traits::eof())
45     {   // put a character to stream
46         return _Sbuf->sputc(_Meta);
47     }
48 
49     int_type pbackfail(int_type _Meta = _Traits::eof())
50     {   // put a character back to stream
51         return _Sbuf->sputbackc(_Meta);
52     }
53 
showmanyc()54     std::streamsize showmanyc()
55     {   // return count of input characters
56         return _Sbuf->in_avail();;
57     }
58 
underflow()59     int_type underflow()
60     {   // get a character from stream, but don't point past it
61         return _Sbuf->sgetc();
62     }
63 
uflow()64     int_type uflow()
65     {   // get a character from stream, point past it
66         return _Sbuf->sbumpc();
67     }
68 
xsgetn(_Elem * _Ptr,std::streamsize _Count)69     std::streamsize xsgetn(_Elem * _Ptr, std::streamsize _Count)
70     {   // get _Count characters from stream
71         return _Sbuf->sgetn(_Ptr, _Count);
72     }
73 
xsputn(const _Elem * _Ptr,std::streamsize _Count)74     std::streamsize xsputn(const _Elem *_Ptr, std::streamsize _Count)
75     {   // put _Count characters to stream
76         return _Sbuf->sputn(_Ptr, _Count);
77     }
78 
79     pos_type seekoff(off_type _Off, std::ios_base::seekdir _Way, std::ios_base::openmode _Mode = std::ios_base::in | std::ios_base::out)
80     {   // change position by offset, according to way and mode
81         return _Sbuf->pubseekoff(_Off, _Way, _Mode);
82     }
83 
84     pos_type seekpos(pos_type _Pos, std::ios_base::openmode _Mode = std::ios_base::in | std::ios_base::out)
85     {   // change to specified position, according to mode
86         return _Sbuf->pubseekpos(_Pos, _Mode);
87     }
88 
setbuf(_Elem * _Buffer,std::streamsize _Count)89     std::basic_streambuf<_Elem, _Traits>* setbuf(_Elem *_Buffer, std::streamsize _Count)
90     {   // offer buffer to external agent
91         return _Sbuf->pubsetbuf(_Buffer, _Count);
92     }
93 
sync()94     int sync()
95     {   // synchronize with external agent
96         return _Sbuf->pubsync();
97     }
98 
imbue(const std::locale & _Newlocale)99     void imbue(const std::locale& _Newlocale)
100     {   // set locale to argument
101         _Sbuf->pubimbue(_Newlocale);
102     }
103 private:
104     std::basic_iostream<_Elem, _Traits>*  _Stream;
105     std::basic_streambuf<_Elem, _Traits>* _Sbuf;
106 };
107 
108 using StreamBufProxy = basic_streambuf_proxy<char, std::char_traits<char>>;
109 
110 }
111 }
112