1 | |
2 | /* |
3 | * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"). |
6 | * You may not use this file except in compliance with the License. |
7 | * A copy of the License is located at |
8 | * |
9 | * http://aws.amazon.com/apache2.0 |
10 | * |
11 | * or in the "license" file accompanying this file. This file is distributed |
12 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
13 | * express or implied. See the License for the specific language governing |
14 | * permissions and limitations under the License. |
15 | */ |
16 | |
17 | #include <aws/core/utils/stream/SimpleStreamBuf.h> |
18 | |
19 | #include <algorithm> |
20 | #include <cassert> |
21 | #include <cstring> |
22 | |
23 | namespace Aws |
24 | { |
25 | namespace Utils |
26 | { |
27 | namespace Stream |
28 | { |
29 | |
30 | static const uint32_t DEFAULT_BUFFER_SIZE = 100; |
31 | static const char* SIMPLE_STREAMBUF_ALLOCATION_TAG = "SimpleStreamBufTag" ; |
32 | |
33 | SimpleStreamBuf::SimpleStreamBuf() : |
34 | m_buffer(nullptr), |
35 | m_bufferSize(0) |
36 | { |
37 | m_buffer = Aws::NewArray<char>(DEFAULT_BUFFER_SIZE, SIMPLE_STREAMBUF_ALLOCATION_TAG); |
38 | m_bufferSize = DEFAULT_BUFFER_SIZE; |
39 | |
40 | char* begin = m_buffer; |
41 | char* end = begin + m_bufferSize; |
42 | |
43 | setp(begin, end); |
44 | setg(begin, begin, begin); |
45 | } |
46 | |
47 | SimpleStreamBuf::SimpleStreamBuf(const Aws::String& value) : |
48 | m_buffer(nullptr), |
49 | m_bufferSize(0) |
50 | { |
51 | size_t baseSize = (std::max)(value.size(), static_cast<std::size_t>(DEFAULT_BUFFER_SIZE)); |
52 | |
53 | m_buffer = Aws::NewArray<char>(baseSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); |
54 | m_bufferSize = baseSize; |
55 | |
56 | std::memcpy(m_buffer, value.c_str(), value.size()); |
57 | |
58 | char* begin = m_buffer; |
59 | char* end = begin + m_bufferSize; |
60 | |
61 | setp(begin + value.size(), end); |
62 | setg(begin, begin, begin); |
63 | } |
64 | |
65 | SimpleStreamBuf::~SimpleStreamBuf() |
66 | { |
67 | if(m_buffer) |
68 | { |
69 | Aws::DeleteArray<char>(m_buffer); |
70 | m_buffer = nullptr; |
71 | } |
72 | |
73 | m_bufferSize = 0; |
74 | } |
75 | |
76 | std::streampos SimpleStreamBuf::seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode which) |
77 | { |
78 | if (dir == std::ios_base::beg) |
79 | { |
80 | return seekpos(off, which); |
81 | } |
82 | else if (dir == std::ios_base::end) |
83 | { |
84 | return seekpos((pptr() - m_buffer) - off, which); |
85 | } |
86 | else if (dir == std::ios_base::cur) |
87 | { |
88 | if(which == std::ios_base::in) |
89 | { |
90 | return seekpos((gptr() - m_buffer) + off, which); |
91 | } |
92 | else |
93 | { |
94 | return seekpos((pptr() - m_buffer) + off, which); |
95 | } |
96 | } |
97 | |
98 | return off_type(-1); |
99 | } |
100 | |
101 | std::streampos SimpleStreamBuf::seekpos(std::streampos pos, std::ios_base::openmode which) |
102 | { |
103 | size_t maxSeek = pptr() - m_buffer; |
104 | assert(static_cast<size_t>(pos) <= maxSeek); |
105 | if (static_cast<size_t>(pos) > maxSeek) |
106 | { |
107 | return pos_type(off_type(-1)); |
108 | } |
109 | |
110 | if (which == std::ios_base::in) |
111 | { |
112 | setg(m_buffer, m_buffer + static_cast<size_t>(pos), pptr()); |
113 | } |
114 | |
115 | if (which == std::ios_base::out) |
116 | { |
117 | setp(m_buffer + static_cast<size_t>(pos), epptr()); |
118 | } |
119 | |
120 | return pos; |
121 | } |
122 | |
123 | bool SimpleStreamBuf::GrowBuffer() |
124 | { |
125 | size_t currentSize = m_bufferSize; |
126 | size_t newSize = currentSize * 2; |
127 | |
128 | char* newBuffer = Aws::NewArray<char>(newSize, SIMPLE_STREAMBUF_ALLOCATION_TAG); |
129 | if(newBuffer == nullptr) |
130 | { |
131 | return false; |
132 | } |
133 | |
134 | if(currentSize > 0) |
135 | { |
136 | std::memcpy(newBuffer, m_buffer, currentSize); |
137 | } |
138 | |
139 | if(m_buffer) |
140 | { |
141 | Aws::DeleteArray<char>(m_buffer); |
142 | } |
143 | |
144 | m_buffer = newBuffer; |
145 | m_bufferSize = newSize; |
146 | |
147 | return true; |
148 | } |
149 | |
150 | int SimpleStreamBuf::overflow (int c) |
151 | { |
152 | auto endOfFile = std::char_traits< char >::eof(); |
153 | if(c == endOfFile) |
154 | { |
155 | return endOfFile; |
156 | } |
157 | |
158 | char* old_begin = m_buffer; |
159 | |
160 | char *old_pptr = pptr(); |
161 | char *old_gptr = gptr(); |
162 | char *old_egptr = egptr(); |
163 | |
164 | size_t currentWritePosition = m_bufferSize; |
165 | |
166 | if(!GrowBuffer()) |
167 | { |
168 | return endOfFile; |
169 | } |
170 | |
171 | char* new_begin = m_buffer; |
172 | char* new_end = new_begin + m_bufferSize; |
173 | |
174 | setp(new_begin + (old_pptr - old_begin) + 1, new_end); |
175 | setg(new_begin, new_begin + (old_gptr - old_begin), new_begin + (old_egptr - old_begin)); |
176 | |
177 | auto val = std::char_traits< char >::to_char_type(c); |
178 | *(new_begin + currentWritePosition) = val; |
179 | |
180 | return c; |
181 | } |
182 | |
183 | std::streamsize SimpleStreamBuf::xsputn(const char* s, std::streamsize n) |
184 | { |
185 | std::streamsize writeCount = 0; |
186 | while(writeCount < n) |
187 | { |
188 | char* current_pptr = pptr(); |
189 | char* current_epptr = epptr(); |
190 | |
191 | if (current_pptr < current_epptr) |
192 | { |
193 | std::size_t copySize = (std::min)(static_cast< std::size_t >(n - writeCount), |
194 | static_cast< std::size_t >(current_epptr - current_pptr)); |
195 | |
196 | std::memcpy(current_pptr, s + writeCount, copySize); |
197 | writeCount += copySize; |
198 | setp(current_pptr + copySize, current_epptr); |
199 | setg(m_buffer, gptr(), pptr()); |
200 | } |
201 | else if (overflow(std::char_traits< char >::to_int_type(*(s + writeCount))) != std::char_traits<char>::eof()) |
202 | { |
203 | writeCount++; |
204 | } |
205 | else |
206 | { |
207 | return writeCount; |
208 | } |
209 | } |
210 | |
211 | return writeCount; |
212 | } |
213 | |
214 | Aws::String SimpleStreamBuf::str() const |
215 | { |
216 | return Aws::String(m_buffer, pptr()); |
217 | } |
218 | |
219 | int SimpleStreamBuf::underflow() |
220 | { |
221 | if(egptr() != pptr()) |
222 | { |
223 | setg(m_buffer, gptr(), pptr()); |
224 | } |
225 | |
226 | if(gptr() != egptr()) |
227 | { |
228 | return std::char_traits< char >::to_int_type(*gptr()); |
229 | } |
230 | else |
231 | { |
232 | return std::char_traits< char >::eof(); |
233 | } |
234 | } |
235 | |
236 | void SimpleStreamBuf::str(const Aws::String& value) |
237 | { |
238 | char* begin = m_buffer; |
239 | char* end = begin + m_bufferSize; |
240 | |
241 | setp(begin, end); |
242 | setg(begin, begin, begin); |
243 | |
244 | xsputn(value.c_str(), value.size()); |
245 | } |
246 | |
247 | } |
248 | } |
249 | } |
250 | |