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