1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
|
// ----------------------------------------------------------------------------
// alt_sstream_impl.hpp : alternative stringstream, templates implementation
// ----------------------------------------------------------------------------
// Copyright Samuel Krempp 2003. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/format for library home page
// ----------------------------------------------------------------------------
#ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP
#define BOOST_SK_ALT_SSTREAM_IMPL_HPP
namespace boost {
namespace io {
// --- Implementation ------------------------------------------------------//
template<class Ch, class Tr, class Alloc>
void basic_altstringbuf<Ch, Tr, Alloc>::
clear_buffer () {
const Ch * p = pptr();
const Ch * b = pbase();
if(p != NULL && p != b) {
seekpos(0, ::std::ios_base::out);
}
p = gptr();
b = eback();
if(p != NULL && p != b) {
seekpos(0, ::std::ios_base::in);
}
}
template<class Ch, class Tr, class Alloc>
void basic_altstringbuf<Ch, Tr, Alloc>::
str (const string_type& s) {
size_type sz=s.size();
if(sz != 0 && mode_ & (::std::ios_base::in | ::std::ios_base::out) ) {
#ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC
void *vd_ptr = alloc_.allocate(sz, is_allocated_? eback() : 0);
Ch *new_ptr = static_cast<Ch *>(vd_ptr);
#else
Ch *new_ptr = alloc_.allocate(sz, is_allocated_? eback() : 0);
#endif
// if this didnt throw, we're safe, update the buffer
dealloc();
sz = s.copy(new_ptr, sz);
putend_ = new_ptr + sz;
if(mode_ & ::std::ios_base::in)
streambuf_t::setg(new_ptr, new_ptr, new_ptr + sz);
if(mode_ & ::std::ios_base::out) {
streambuf_t::setp(new_ptr, new_ptr + sz);
if(mode_ & (::std::ios_base::app | ::std::ios_base::ate))
streambuf_t::pbump(static_cast<int>(sz));
if(gptr() == NULL)
streambuf_t::setg(new_ptr, NULL, new_ptr);
}
is_allocated_ = true;
}
else
dealloc();
}
template<class Ch, class Tr, class Alloc>
Ch* basic_altstringbuf<Ch, Tr, Alloc>::
begin () const {
if(mode_ & ::std::ios_base::out && pptr() != NULL)
return pbase();
else if(mode_ & ::std::ios_base::in && gptr() != NULL)
return eback();
return NULL;
}
template<class Ch, class Tr, class Alloc>
typename std::basic_string<Ch,Tr,Alloc>::size_type
basic_altstringbuf<Ch, Tr, Alloc>::
size () const {
if(mode_ & ::std::ios_base::out && pptr())
return static_cast<size_type>(pend() - pbase());
else if(mode_ & ::std::ios_base::in && gptr())
return static_cast<size_type>(egptr() - eback());
else
return 0;
}
template<class Ch, class Tr, class Alloc>
typename std::basic_string<Ch,Tr,Alloc>::size_type
basic_altstringbuf<Ch, Tr, Alloc>::
cur_size () const {
if(mode_ & ::std::ios_base::out && pptr())
return static_cast<streamsize>( pptr() - pbase());
else if(mode_ & ::std::ios_base::in && gptr())
return static_cast<streamsize>( gptr() - eback());
else
return 0;
}
template<class Ch, class Tr, class Alloc>
typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
basic_altstringbuf<Ch, Tr, Alloc>::
seekoff (off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
if(pptr() != NULL && putend_ < pptr())
putend_ = pptr();
if(which & ::std::ios_base::in && gptr() != NULL) {
// get area
if(way == ::std::ios_base::end)
off += static_cast<off_type>(putend_ - gptr());
else if(way == ::std::ios_base::beg)
off += static_cast<off_type>(eback() - gptr());
else if(way != ::std::ios_base::cur || (which & ::std::ios_base::out) )
// (altering in&out is only supported if way is beg or end, not cur)
return pos_type(off_type(-1));
if(eback() <= off+gptr() && off+gptr() <= putend_ ) {
// set gptr
streambuf_t::gbump(static_cast<int>(off));
if(which & ::std::ios_base::out && pptr() != NULL)
// update pptr to match gptr
streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
}
else
off = off_type(-1);
}
else if(which & ::std::ios_base::out && pptr() != NULL) {
// put area
if(way == ::std::ios_base::end)
off += static_cast<off_type>(putend_ - pptr());
else if(way == ::std::ios_base::beg)
off += static_cast<off_type>(pbase() - pptr());
else if(way != ::std::ios_base::beg)
return pos_type(off_type(-1));
if(pbase() <= off+pptr() && off+pptr() <= putend_)
// set pptr
streambuf_t::pbump(static_cast<int>(off));
else
off = off_type(-1);
}
else // neither in nor out
off = off_type(-1);
return (pos_type(off));
}
//- end seekoff(..)
template<class Ch, class Tr, class Alloc>
typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
basic_altstringbuf<Ch, Tr, Alloc>::
seekpos (pos_type pos, ::std::ios_base::openmode which) {
off_type off = off_type(pos); // operation guaranteed by fpos.operations table 127
if(pptr() != NULL && putend_ < pptr())
putend_ = pptr();
if(off != off_type(-1)) {
if(which & ::std::ios_base::in && gptr() != NULL) {
// get area
if(0 <= off && off <= putend_ - eback()) {
streambuf_t::gbump(static_cast<int>(eback() - gptr() + off));
if(which & ::std::ios_base::out && pptr() != NULL) {
// update pptr to match gptr
streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
}
}
else
off = off_type(-1);
}
else if(which & ::std::ios_base::out && pptr() != NULL) {
// put area
if(0 <= off && off <= putend_ - eback())
streambuf_t::pbump(static_cast<int>(eback() - pptr() + off));
else
off = off_type(-1);
}
else // neither in nor out
off = off_type(-1);
return (pos_type(off));
}
else {
BOOST_ASSERT(0); // fpos.operations allows undefined-behaviour here
return pos_type(off_type(-1));
}
}
// -end seekpos(..)
template<class Ch, class Tr, class Alloc>
typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
basic_altstringbuf<Ch, Tr, Alloc>::
underflow () {
if(gptr() == NULL) // no get area -> nothing to get.
return (compat_traits_type::eof());
else if(gptr() < egptr()) // ok, in buffer
return (compat_traits_type::to_int_type(*gptr()));
else if(mode_ & ::std::ios_base::in && pptr() != NULL
&& (gptr() < pptr() || gptr() < putend_) )
{ // expand get area
if(putend_ < pptr())
putend_ = pptr(); // remember pptr reached this far
streambuf_t::setg(eback(), gptr(), putend_);
return (compat_traits_type::to_int_type(*gptr()));
}
else // couldnt get anything. EOF.
return (compat_traits_type::eof());
}
// -end underflow(..)
template<class Ch, class Tr, class Alloc>
typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
basic_altstringbuf<Ch, Tr, Alloc>::
pbackfail (int_type meta) {
if(gptr() != NULL && (eback() < gptr())
&& (mode_ & (::std::ios_base::out)
|| compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)
|| compat_traits_type::eq(compat_traits_type::to_char_type(meta), gptr()[-1]) ) ) {
streambuf_t::gbump(-1); // back one character
if(!compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
// put-back meta into get area
*gptr() = compat_traits_type::to_char_type(meta);
return (compat_traits_type::not_eof(meta));
}
else
return (compat_traits_type::eof()); // failed putback
}
// -end pbackfail(..)
template<class Ch, class Tr, class Alloc>
typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
basic_altstringbuf<Ch, Tr, Alloc>::
overflow (int_type meta) {
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4996)
#endif
if(compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
return compat_traits_type::not_eof(meta); // nothing to do
else if(pptr() != NULL && pptr() < epptr()) {
streambuf_t::sputc(compat_traits_type::to_char_type(meta));
return meta;
}
else if(! (mode_ & ::std::ios_base::out))
// no write position, and cant make one
return compat_traits_type::eof();
else { // make a write position available
std::size_t prev_size = pptr() == NULL ? 0 : epptr() - eback();
std::size_t new_size = prev_size;
// exponential growth : size *= 1.5
std::size_t add_size = new_size / 2;
if(add_size < alloc_min)
add_size = alloc_min;
Ch * newptr = NULL, *oldptr = eback();
// make sure adding add_size wont overflow size_t
while (0 < add_size && ((std::numeric_limits<std::size_t>::max)()
- add_size < new_size) )
add_size /= 2;
if(0 < add_size) {
new_size += add_size;
#ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC
void *vdptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0);
newptr = static_cast<Ch *>(vdptr);
#else
newptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0);
#endif
}
if(0 < prev_size)
compat_traits_type::copy(newptr, oldptr, prev_size);
if(is_allocated_)
alloc_.deallocate(oldptr, prev_size);
is_allocated_=true;
if(prev_size == 0) { // first allocation
putend_ = newptr;
streambuf_t::setp(newptr, newptr + new_size);
if(mode_ & ::std::ios_base::in)
streambuf_t::setg(newptr, newptr, newptr + 1);
else
streambuf_t::setg(newptr, 0, newptr);
}
else { // update pointers
putend_ = putend_ - oldptr + newptr;
int pptr_count = static_cast<int>(pptr()-pbase());
int gptr_count = static_cast<int>(gptr()-eback());
streambuf_t::setp(pbase() - oldptr + newptr, newptr + new_size);
streambuf_t::pbump(pptr_count);
if(mode_ & ::std::ios_base::in)
streambuf_t::setg(newptr, newptr + gptr_count, pptr() + 1);
else
streambuf_t::setg(newptr, 0, newptr);
}
streambuf_t::sputc(compat_traits_type::to_char_type(meta));
return meta;
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
}
// -end overflow(..)
template<class Ch, class Tr, class Alloc>
void basic_altstringbuf<Ch, Tr, Alloc>:: dealloc() {
if(is_allocated_)
alloc_.deallocate(eback(), (pptr() != NULL ? epptr() : egptr()) - eback());
is_allocated_ = false;
streambuf_t::setg(0, 0, 0);
streambuf_t::setp(0, 0);
putend_ = NULL;
}
}// N.S. io
} // N.S. boost
#endif // include guard
|