17a984708SDavid Chisnall //===------------------------ strstream.cpp -------------------------------===//
27a984708SDavid Chisnall //
37a984708SDavid Chisnall // The LLVM Compiler Infrastructure
47a984708SDavid Chisnall //
57a984708SDavid Chisnall // This file is dual licensed under the MIT and the University of Illinois Open
67a984708SDavid Chisnall // Source Licenses. See LICENSE.TXT for details.
77a984708SDavid Chisnall //
87a984708SDavid Chisnall //===----------------------------------------------------------------------===//
97a984708SDavid Chisnall
107a984708SDavid Chisnall #include "strstream"
117a984708SDavid Chisnall #include "algorithm"
127a984708SDavid Chisnall #include "climits"
137a984708SDavid Chisnall #include "cstring"
14aed8d94eSDimitry Andric #include "cstdlib"
157c82a1ecSDimitry Andric #include "__debug"
16f9448bf3SDimitry Andric #include "__undef_macros"
177a984708SDavid Chisnall
187a984708SDavid Chisnall _LIBCPP_BEGIN_NAMESPACE_STD
197a984708SDavid Chisnall
strstreambuf(streamsize __alsize)207a984708SDavid Chisnall strstreambuf::strstreambuf(streamsize __alsize)
217a984708SDavid Chisnall : __strmode_(__dynamic),
227a984708SDavid Chisnall __alsize_(__alsize),
237a984708SDavid Chisnall __palloc_(nullptr),
247a984708SDavid Chisnall __pfree_(nullptr)
257a984708SDavid Chisnall {
267a984708SDavid Chisnall }
277a984708SDavid Chisnall
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))287a984708SDavid Chisnall strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
297a984708SDavid Chisnall : __strmode_(__dynamic),
307a984708SDavid Chisnall __alsize_(__default_alsize),
317a984708SDavid Chisnall __palloc_(__palloc),
327a984708SDavid Chisnall __pfree_(__pfree)
337a984708SDavid Chisnall {
347a984708SDavid Chisnall }
357a984708SDavid Chisnall
367a984708SDavid Chisnall void
__init(char * __gnext,streamsize __n,char * __pbeg)377a984708SDavid Chisnall strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
387a984708SDavid Chisnall {
397a984708SDavid Chisnall if (__n == 0)
4094e3ee44SDavid Chisnall __n = static_cast<streamsize>(strlen(__gnext));
417a984708SDavid Chisnall else if (__n < 0)
427a984708SDavid Chisnall __n = INT_MAX;
437a984708SDavid Chisnall if (__pbeg == nullptr)
447a984708SDavid Chisnall setg(__gnext, __gnext, __gnext + __n);
457a984708SDavid Chisnall else
467a984708SDavid Chisnall {
477a984708SDavid Chisnall setg(__gnext, __gnext, __pbeg);
487a984708SDavid Chisnall setp(__pbeg, __pbeg + __n);
497a984708SDavid Chisnall }
507a984708SDavid Chisnall }
517a984708SDavid Chisnall
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)527a984708SDavid Chisnall strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
537a984708SDavid Chisnall : __strmode_(),
547a984708SDavid Chisnall __alsize_(__default_alsize),
557a984708SDavid Chisnall __palloc_(nullptr),
567a984708SDavid Chisnall __pfree_(nullptr)
577a984708SDavid Chisnall {
587a984708SDavid Chisnall __init(__gnext, __n, __pbeg);
597a984708SDavid Chisnall }
607a984708SDavid Chisnall
strstreambuf(const char * __gnext,streamsize __n)617a984708SDavid Chisnall strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
627a984708SDavid Chisnall : __strmode_(__constant),
637a984708SDavid Chisnall __alsize_(__default_alsize),
647a984708SDavid Chisnall __palloc_(nullptr),
657a984708SDavid Chisnall __pfree_(nullptr)
667a984708SDavid Chisnall {
67d72607e9SDimitry Andric __init(const_cast<char *>(__gnext), __n, nullptr);
687a984708SDavid Chisnall }
697a984708SDavid Chisnall
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)707a984708SDavid Chisnall strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
717a984708SDavid Chisnall : __strmode_(),
727a984708SDavid Chisnall __alsize_(__default_alsize),
737a984708SDavid Chisnall __palloc_(nullptr),
747a984708SDavid Chisnall __pfree_(nullptr)
757a984708SDavid Chisnall {
76d72607e9SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
777a984708SDavid Chisnall }
787a984708SDavid Chisnall
strstreambuf(const signed char * __gnext,streamsize __n)797a984708SDavid Chisnall strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
807a984708SDavid Chisnall : __strmode_(__constant),
817a984708SDavid Chisnall __alsize_(__default_alsize),
827a984708SDavid Chisnall __palloc_(nullptr),
837a984708SDavid Chisnall __pfree_(nullptr)
847a984708SDavid Chisnall {
85d72607e9SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
867a984708SDavid Chisnall }
877a984708SDavid Chisnall
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)887a984708SDavid Chisnall strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
897a984708SDavid Chisnall : __strmode_(),
907a984708SDavid Chisnall __alsize_(__default_alsize),
917a984708SDavid Chisnall __palloc_(nullptr),
927a984708SDavid Chisnall __pfree_(nullptr)
937a984708SDavid Chisnall {
94d72607e9SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
957a984708SDavid Chisnall }
967a984708SDavid Chisnall
strstreambuf(const unsigned char * __gnext,streamsize __n)977a984708SDavid Chisnall strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
987a984708SDavid Chisnall : __strmode_(__constant),
997a984708SDavid Chisnall __alsize_(__default_alsize),
1007a984708SDavid Chisnall __palloc_(nullptr),
1017a984708SDavid Chisnall __pfree_(nullptr)
1027a984708SDavid Chisnall {
103d72607e9SDimitry Andric __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
1047a984708SDavid Chisnall }
1057a984708SDavid Chisnall
~strstreambuf()1067a984708SDavid Chisnall strstreambuf::~strstreambuf()
1077a984708SDavid Chisnall {
1087a984708SDavid Chisnall if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
1097a984708SDavid Chisnall {
1107a984708SDavid Chisnall if (__pfree_)
1117a984708SDavid Chisnall __pfree_(eback());
1127a984708SDavid Chisnall else
1137a984708SDavid Chisnall delete [] eback();
1147a984708SDavid Chisnall }
1157a984708SDavid Chisnall }
1167a984708SDavid Chisnall
1177a984708SDavid Chisnall void
swap(strstreambuf & __rhs)1187a984708SDavid Chisnall strstreambuf::swap(strstreambuf& __rhs)
1197a984708SDavid Chisnall {
1207a984708SDavid Chisnall streambuf::swap(__rhs);
1217a984708SDavid Chisnall _VSTD::swap(__strmode_, __rhs.__strmode_);
1227a984708SDavid Chisnall _VSTD::swap(__alsize_, __rhs.__alsize_);
1237a984708SDavid Chisnall _VSTD::swap(__palloc_, __rhs.__palloc_);
1247a984708SDavid Chisnall _VSTD::swap(__pfree_, __rhs.__pfree_);
1257a984708SDavid Chisnall }
1267a984708SDavid Chisnall
1277a984708SDavid Chisnall void
freeze(bool __freezefl)1287a984708SDavid Chisnall strstreambuf::freeze(bool __freezefl)
1297a984708SDavid Chisnall {
1307a984708SDavid Chisnall if (__strmode_ & __dynamic)
1317a984708SDavid Chisnall {
1327a984708SDavid Chisnall if (__freezefl)
1337a984708SDavid Chisnall __strmode_ |= __frozen;
1347a984708SDavid Chisnall else
1357a984708SDavid Chisnall __strmode_ &= ~__frozen;
1367a984708SDavid Chisnall }
1377a984708SDavid Chisnall }
1387a984708SDavid Chisnall
1397a984708SDavid Chisnall char*
str()1407a984708SDavid Chisnall strstreambuf::str()
1417a984708SDavid Chisnall {
1427a984708SDavid Chisnall if (__strmode_ & __dynamic)
1437a984708SDavid Chisnall __strmode_ |= __frozen;
1447a984708SDavid Chisnall return eback();
1457a984708SDavid Chisnall }
1467a984708SDavid Chisnall
1477a984708SDavid Chisnall int
pcount() const1487a984708SDavid Chisnall strstreambuf::pcount() const
1497a984708SDavid Chisnall {
1507a984708SDavid Chisnall return static_cast<int>(pptr() - pbase());
1517a984708SDavid Chisnall }
1527a984708SDavid Chisnall
1537a984708SDavid Chisnall strstreambuf::int_type
overflow(int_type __c)1547a984708SDavid Chisnall strstreambuf::overflow(int_type __c)
1557a984708SDavid Chisnall {
1567a984708SDavid Chisnall if (__c == EOF)
1577a984708SDavid Chisnall return int_type(0);
1587a984708SDavid Chisnall if (pptr() == epptr())
1597a984708SDavid Chisnall {
1607a984708SDavid Chisnall if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
1617a984708SDavid Chisnall return int_type(EOF);
1624f7ab58eSDimitry Andric size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
1634f7ab58eSDimitry Andric size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
1641bf9f7c1SDimitry Andric if (new_size == 0)
1651bf9f7c1SDimitry Andric new_size = __default_alsize;
1667a984708SDavid Chisnall char* buf = nullptr;
1677a984708SDavid Chisnall if (__palloc_)
1684f7ab58eSDimitry Andric buf = static_cast<char*>(__palloc_(new_size));
1697a984708SDavid Chisnall else
1707a984708SDavid Chisnall buf = new char[new_size];
1717a984708SDavid Chisnall if (buf == nullptr)
1727a984708SDavid Chisnall return int_type(EOF);
1737c82a1ecSDimitry Andric if (old_size != 0) {
1747c82a1ecSDimitry Andric _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
17594e3ee44SDavid Chisnall memcpy(buf, eback(), static_cast<size_t>(old_size));
1767c82a1ecSDimitry Andric }
1777a984708SDavid Chisnall ptrdiff_t ninp = gptr() - eback();
1787a984708SDavid Chisnall ptrdiff_t einp = egptr() - eback();
1797a984708SDavid Chisnall ptrdiff_t nout = pptr() - pbase();
1807a984708SDavid Chisnall if (__strmode_ & __allocated)
1817a984708SDavid Chisnall {
1827a984708SDavid Chisnall if (__pfree_)
1837a984708SDavid Chisnall __pfree_(eback());
1847a984708SDavid Chisnall else
1857a984708SDavid Chisnall delete [] eback();
1867a984708SDavid Chisnall }
1877a984708SDavid Chisnall setg(buf, buf + ninp, buf + einp);
1887c82a1ecSDimitry Andric setp(buf + einp, buf + new_size);
189*b2c7081bSDimitry Andric __pbump(nout);
1907a984708SDavid Chisnall __strmode_ |= __allocated;
1917a984708SDavid Chisnall }
1927a984708SDavid Chisnall *pptr() = static_cast<char>(__c);
1937a984708SDavid Chisnall pbump(1);
194d72607e9SDimitry Andric return int_type(static_cast<unsigned char>(__c));
1957a984708SDavid Chisnall }
1967a984708SDavid Chisnall
1977a984708SDavid Chisnall strstreambuf::int_type
pbackfail(int_type __c)1987a984708SDavid Chisnall strstreambuf::pbackfail(int_type __c)
1997a984708SDavid Chisnall {
2007a984708SDavid Chisnall if (eback() == gptr())
2017a984708SDavid Chisnall return EOF;
2027a984708SDavid Chisnall if (__c == EOF)
2037a984708SDavid Chisnall {
2047a984708SDavid Chisnall gbump(-1);
2057a984708SDavid Chisnall return int_type(0);
2067a984708SDavid Chisnall }
2077a984708SDavid Chisnall if (__strmode_ & __constant)
2087a984708SDavid Chisnall {
2097a984708SDavid Chisnall if (gptr()[-1] == static_cast<char>(__c))
2107a984708SDavid Chisnall {
2117a984708SDavid Chisnall gbump(-1);
2127a984708SDavid Chisnall return __c;
2137a984708SDavid Chisnall }
2147a984708SDavid Chisnall return EOF;
2157a984708SDavid Chisnall }
2167a984708SDavid Chisnall gbump(-1);
2177a984708SDavid Chisnall *gptr() = static_cast<char>(__c);
2187a984708SDavid Chisnall return __c;
2197a984708SDavid Chisnall }
2207a984708SDavid Chisnall
2217a984708SDavid Chisnall strstreambuf::int_type
underflow()2227a984708SDavid Chisnall strstreambuf::underflow()
2237a984708SDavid Chisnall {
2247a984708SDavid Chisnall if (gptr() == egptr())
2257a984708SDavid Chisnall {
2267a984708SDavid Chisnall if (egptr() >= pptr())
2277a984708SDavid Chisnall return EOF;
2287a984708SDavid Chisnall setg(eback(), gptr(), pptr());
2297a984708SDavid Chisnall }
230d72607e9SDimitry Andric return int_type(static_cast<unsigned char>(*gptr()));
2317a984708SDavid Chisnall }
2327a984708SDavid Chisnall
2337a984708SDavid Chisnall strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)2347a984708SDavid Chisnall strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
2357a984708SDavid Chisnall {
2367a984708SDavid Chisnall off_type __p(-1);
2374f7ab58eSDimitry Andric bool pos_in = (__which & ios::in) != 0;
2384f7ab58eSDimitry Andric bool pos_out = (__which & ios::out) != 0;
2397a984708SDavid Chisnall bool legal = false;
2407a984708SDavid Chisnall switch (__way)
2417a984708SDavid Chisnall {
2427a984708SDavid Chisnall case ios::beg:
2437a984708SDavid Chisnall case ios::end:
2447a984708SDavid Chisnall if (pos_in || pos_out)
2457a984708SDavid Chisnall legal = true;
2467a984708SDavid Chisnall break;
2477a984708SDavid Chisnall case ios::cur:
2487a984708SDavid Chisnall if (pos_in != pos_out)
2497a984708SDavid Chisnall legal = true;
2507a984708SDavid Chisnall break;
2517a984708SDavid Chisnall }
2527a984708SDavid Chisnall if (pos_in && gptr() == nullptr)
2537a984708SDavid Chisnall legal = false;
2547a984708SDavid Chisnall if (pos_out && pptr() == nullptr)
2557a984708SDavid Chisnall legal = false;
2567a984708SDavid Chisnall if (legal)
2577a984708SDavid Chisnall {
2587a984708SDavid Chisnall off_type newoff;
2597a984708SDavid Chisnall char* seekhigh = epptr() ? epptr() : egptr();
2607a984708SDavid Chisnall switch (__way)
2617a984708SDavid Chisnall {
2627a984708SDavid Chisnall case ios::beg:
2637a984708SDavid Chisnall newoff = 0;
2647a984708SDavid Chisnall break;
2657a984708SDavid Chisnall case ios::cur:
2667a984708SDavid Chisnall newoff = (pos_in ? gptr() : pptr()) - eback();
2677a984708SDavid Chisnall break;
2687a984708SDavid Chisnall case ios::end:
2697a984708SDavid Chisnall newoff = seekhigh - eback();
2707a984708SDavid Chisnall break;
271aed8d94eSDimitry Andric default:
272aed8d94eSDimitry Andric _LIBCPP_UNREACHABLE();
2737a984708SDavid Chisnall }
2747a984708SDavid Chisnall newoff += __off;
2757a984708SDavid Chisnall if (0 <= newoff && newoff <= seekhigh - eback())
2767a984708SDavid Chisnall {
2777a984708SDavid Chisnall char* newpos = eback() + newoff;
2787a984708SDavid Chisnall if (pos_in)
2797a984708SDavid Chisnall setg(eback(), newpos, _VSTD::max(newpos, egptr()));
2807a984708SDavid Chisnall if (pos_out)
2817a984708SDavid Chisnall {
2827a984708SDavid Chisnall // min(pbase, newpos), newpos, epptr()
2837a984708SDavid Chisnall __off = epptr() - newpos;
2847a984708SDavid Chisnall setp(min(pbase(), newpos), epptr());
285*b2c7081bSDimitry Andric __pbump((epptr() - pbase()) - __off);
2867a984708SDavid Chisnall }
2877a984708SDavid Chisnall __p = newoff;
2887a984708SDavid Chisnall }
2897a984708SDavid Chisnall }
2907a984708SDavid Chisnall return pos_type(__p);
2917a984708SDavid Chisnall }
2927a984708SDavid Chisnall
2937a984708SDavid Chisnall strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)2947a984708SDavid Chisnall strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
2957a984708SDavid Chisnall {
2967a984708SDavid Chisnall off_type __p(-1);
2974f7ab58eSDimitry Andric bool pos_in = (__which & ios::in) != 0;
2984f7ab58eSDimitry Andric bool pos_out = (__which & ios::out) != 0;
2997a984708SDavid Chisnall if (pos_in || pos_out)
3007a984708SDavid Chisnall {
3017a984708SDavid Chisnall if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
3027a984708SDavid Chisnall {
3037a984708SDavid Chisnall off_type newoff = __sp;
3047a984708SDavid Chisnall char* seekhigh = epptr() ? epptr() : egptr();
3057a984708SDavid Chisnall if (0 <= newoff && newoff <= seekhigh - eback())
3067a984708SDavid Chisnall {
3077a984708SDavid Chisnall char* newpos = eback() + newoff;
3087a984708SDavid Chisnall if (pos_in)
3097a984708SDavid Chisnall setg(eback(), newpos, _VSTD::max(newpos, egptr()));
3107a984708SDavid Chisnall if (pos_out)
3117a984708SDavid Chisnall {
3127a984708SDavid Chisnall // min(pbase, newpos), newpos, epptr()
3137a984708SDavid Chisnall off_type temp = epptr() - newpos;
3147a984708SDavid Chisnall setp(min(pbase(), newpos), epptr());
315*b2c7081bSDimitry Andric __pbump((epptr() - pbase()) - temp);
3167a984708SDavid Chisnall }
3177a984708SDavid Chisnall __p = newoff;
3187a984708SDavid Chisnall }
3197a984708SDavid Chisnall }
3207a984708SDavid Chisnall }
3217a984708SDavid Chisnall return pos_type(__p);
3227a984708SDavid Chisnall }
3237a984708SDavid Chisnall
~istrstream()3247a984708SDavid Chisnall istrstream::~istrstream()
3257a984708SDavid Chisnall {
3267a984708SDavid Chisnall }
3277a984708SDavid Chisnall
~ostrstream()3287a984708SDavid Chisnall ostrstream::~ostrstream()
3297a984708SDavid Chisnall {
3307a984708SDavid Chisnall }
3317a984708SDavid Chisnall
~strstream()3327a984708SDavid Chisnall strstream::~strstream()
3337a984708SDavid Chisnall {
3347a984708SDavid Chisnall }
3357a984708SDavid Chisnall
3367a984708SDavid Chisnall _LIBCPP_END_NAMESPACE_STD
337