xref: /minix3/external/bsd/libc++/dist/libcxx/src/strstream.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
14684ddb6SLionel Sambuc //===------------------------ strstream.cpp -------------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc //                     The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc 
104684ddb6SLionel Sambuc #include "strstream"
114684ddb6SLionel Sambuc #include "algorithm"
124684ddb6SLionel Sambuc #include "climits"
134684ddb6SLionel Sambuc #include "cstring"
144684ddb6SLionel Sambuc 
154684ddb6SLionel Sambuc _LIBCPP_BEGIN_NAMESPACE_STD
164684ddb6SLionel Sambuc 
strstreambuf(streamsize __alsize)174684ddb6SLionel Sambuc strstreambuf::strstreambuf(streamsize __alsize)
184684ddb6SLionel Sambuc     : __strmode_(__dynamic),
194684ddb6SLionel Sambuc       __alsize_(__alsize),
204684ddb6SLionel Sambuc       __palloc_(nullptr),
214684ddb6SLionel Sambuc       __pfree_(nullptr)
224684ddb6SLionel Sambuc {
234684ddb6SLionel Sambuc }
244684ddb6SLionel Sambuc 
strstreambuf(void * (* __palloc)(size_t),void (* __pfree)(void *))254684ddb6SLionel Sambuc strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
264684ddb6SLionel Sambuc     : __strmode_(__dynamic),
274684ddb6SLionel Sambuc       __alsize_(__default_alsize),
284684ddb6SLionel Sambuc       __palloc_(__palloc),
294684ddb6SLionel Sambuc       __pfree_(__pfree)
304684ddb6SLionel Sambuc {
314684ddb6SLionel Sambuc }
324684ddb6SLionel Sambuc 
334684ddb6SLionel Sambuc void
__init(char * __gnext,streamsize __n,char * __pbeg)344684ddb6SLionel Sambuc strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
354684ddb6SLionel Sambuc {
364684ddb6SLionel Sambuc     if (__n == 0)
374684ddb6SLionel Sambuc         __n = static_cast<streamsize>(strlen(__gnext));
384684ddb6SLionel Sambuc     else if (__n < 0)
394684ddb6SLionel Sambuc         __n = INT_MAX;
404684ddb6SLionel Sambuc     if (__pbeg == nullptr)
414684ddb6SLionel Sambuc         setg(__gnext, __gnext, __gnext + __n);
424684ddb6SLionel Sambuc     else
434684ddb6SLionel Sambuc     {
444684ddb6SLionel Sambuc         setg(__gnext, __gnext, __pbeg);
454684ddb6SLionel Sambuc         setp(__pbeg, __pbeg + __n);
464684ddb6SLionel Sambuc     }
474684ddb6SLionel Sambuc }
484684ddb6SLionel Sambuc 
strstreambuf(char * __gnext,streamsize __n,char * __pbeg)494684ddb6SLionel Sambuc strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
504684ddb6SLionel Sambuc     : __strmode_(),
514684ddb6SLionel Sambuc       __alsize_(__default_alsize),
524684ddb6SLionel Sambuc       __palloc_(nullptr),
534684ddb6SLionel Sambuc       __pfree_(nullptr)
544684ddb6SLionel Sambuc {
554684ddb6SLionel Sambuc     __init(__gnext, __n, __pbeg);
564684ddb6SLionel Sambuc }
574684ddb6SLionel Sambuc 
strstreambuf(const char * __gnext,streamsize __n)584684ddb6SLionel Sambuc strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
594684ddb6SLionel Sambuc     : __strmode_(__constant),
604684ddb6SLionel Sambuc       __alsize_(__default_alsize),
614684ddb6SLionel Sambuc       __palloc_(nullptr),
624684ddb6SLionel Sambuc       __pfree_(nullptr)
634684ddb6SLionel Sambuc {
64*0a6a1f1dSLionel Sambuc     __init(const_cast<char *>(__gnext), __n, nullptr);
654684ddb6SLionel Sambuc }
664684ddb6SLionel Sambuc 
strstreambuf(signed char * __gnext,streamsize __n,signed char * __pbeg)674684ddb6SLionel Sambuc strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
684684ddb6SLionel Sambuc     : __strmode_(),
694684ddb6SLionel Sambuc       __alsize_(__default_alsize),
704684ddb6SLionel Sambuc       __palloc_(nullptr),
714684ddb6SLionel Sambuc       __pfree_(nullptr)
724684ddb6SLionel Sambuc {
73*0a6a1f1dSLionel Sambuc     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
744684ddb6SLionel Sambuc }
754684ddb6SLionel Sambuc 
strstreambuf(const signed char * __gnext,streamsize __n)764684ddb6SLionel Sambuc strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
774684ddb6SLionel Sambuc     : __strmode_(__constant),
784684ddb6SLionel Sambuc       __alsize_(__default_alsize),
794684ddb6SLionel Sambuc       __palloc_(nullptr),
804684ddb6SLionel Sambuc       __pfree_(nullptr)
814684ddb6SLionel Sambuc {
82*0a6a1f1dSLionel Sambuc     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
834684ddb6SLionel Sambuc }
844684ddb6SLionel Sambuc 
strstreambuf(unsigned char * __gnext,streamsize __n,unsigned char * __pbeg)854684ddb6SLionel Sambuc strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
864684ddb6SLionel Sambuc     : __strmode_(),
874684ddb6SLionel Sambuc       __alsize_(__default_alsize),
884684ddb6SLionel Sambuc       __palloc_(nullptr),
894684ddb6SLionel Sambuc       __pfree_(nullptr)
904684ddb6SLionel Sambuc {
91*0a6a1f1dSLionel Sambuc     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
924684ddb6SLionel Sambuc }
934684ddb6SLionel Sambuc 
strstreambuf(const unsigned char * __gnext,streamsize __n)944684ddb6SLionel Sambuc strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
954684ddb6SLionel Sambuc     : __strmode_(__constant),
964684ddb6SLionel Sambuc       __alsize_(__default_alsize),
974684ddb6SLionel Sambuc       __palloc_(nullptr),
984684ddb6SLionel Sambuc       __pfree_(nullptr)
994684ddb6SLionel Sambuc {
100*0a6a1f1dSLionel Sambuc     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
1014684ddb6SLionel Sambuc }
1024684ddb6SLionel Sambuc 
~strstreambuf()1034684ddb6SLionel Sambuc strstreambuf::~strstreambuf()
1044684ddb6SLionel Sambuc {
1054684ddb6SLionel Sambuc     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
1064684ddb6SLionel Sambuc     {
1074684ddb6SLionel Sambuc         if (__pfree_)
1084684ddb6SLionel Sambuc             __pfree_(eback());
1094684ddb6SLionel Sambuc         else
1104684ddb6SLionel Sambuc             delete [] eback();
1114684ddb6SLionel Sambuc     }
1124684ddb6SLionel Sambuc }
1134684ddb6SLionel Sambuc 
1144684ddb6SLionel Sambuc void
swap(strstreambuf & __rhs)1154684ddb6SLionel Sambuc strstreambuf::swap(strstreambuf& __rhs)
1164684ddb6SLionel Sambuc {
1174684ddb6SLionel Sambuc     streambuf::swap(__rhs);
1184684ddb6SLionel Sambuc     _VSTD::swap(__strmode_, __rhs.__strmode_);
1194684ddb6SLionel Sambuc     _VSTD::swap(__alsize_, __rhs.__alsize_);
1204684ddb6SLionel Sambuc     _VSTD::swap(__palloc_, __rhs.__palloc_);
1214684ddb6SLionel Sambuc     _VSTD::swap(__pfree_, __rhs.__pfree_);
1224684ddb6SLionel Sambuc }
1234684ddb6SLionel Sambuc 
1244684ddb6SLionel Sambuc void
freeze(bool __freezefl)1254684ddb6SLionel Sambuc strstreambuf::freeze(bool __freezefl)
1264684ddb6SLionel Sambuc {
1274684ddb6SLionel Sambuc     if (__strmode_ & __dynamic)
1284684ddb6SLionel Sambuc     {
1294684ddb6SLionel Sambuc         if (__freezefl)
1304684ddb6SLionel Sambuc             __strmode_ |= __frozen;
1314684ddb6SLionel Sambuc         else
1324684ddb6SLionel Sambuc             __strmode_ &= ~__frozen;
1334684ddb6SLionel Sambuc     }
1344684ddb6SLionel Sambuc }
1354684ddb6SLionel Sambuc 
1364684ddb6SLionel Sambuc char*
str()1374684ddb6SLionel Sambuc strstreambuf::str()
1384684ddb6SLionel Sambuc {
1394684ddb6SLionel Sambuc     if (__strmode_ & __dynamic)
1404684ddb6SLionel Sambuc         __strmode_ |= __frozen;
1414684ddb6SLionel Sambuc     return eback();
1424684ddb6SLionel Sambuc }
1434684ddb6SLionel Sambuc 
1444684ddb6SLionel Sambuc int
pcount() const1454684ddb6SLionel Sambuc strstreambuf::pcount() const
1464684ddb6SLionel Sambuc {
1474684ddb6SLionel Sambuc     return static_cast<int>(pptr() - pbase());
1484684ddb6SLionel Sambuc }
1494684ddb6SLionel Sambuc 
1504684ddb6SLionel Sambuc strstreambuf::int_type
overflow(int_type __c)1514684ddb6SLionel Sambuc strstreambuf::overflow(int_type __c)
1524684ddb6SLionel Sambuc {
1534684ddb6SLionel Sambuc     if (__c == EOF)
1544684ddb6SLionel Sambuc         return int_type(0);
1554684ddb6SLionel Sambuc     if (pptr() == epptr())
1564684ddb6SLionel Sambuc     {
1574684ddb6SLionel Sambuc         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
1584684ddb6SLionel Sambuc             return int_type(EOF);
1594684ddb6SLionel Sambuc         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
1604684ddb6SLionel Sambuc         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
1614684ddb6SLionel Sambuc         if (new_size == 0)
1624684ddb6SLionel Sambuc             new_size = __default_alsize;
1634684ddb6SLionel Sambuc         char* buf = nullptr;
1644684ddb6SLionel Sambuc         if (__palloc_)
1654684ddb6SLionel Sambuc             buf = static_cast<char*>(__palloc_(new_size));
1664684ddb6SLionel Sambuc         else
1674684ddb6SLionel Sambuc             buf = new char[new_size];
1684684ddb6SLionel Sambuc         if (buf == nullptr)
1694684ddb6SLionel Sambuc             return int_type(EOF);
1704684ddb6SLionel Sambuc         memcpy(buf, eback(), static_cast<size_t>(old_size));
1714684ddb6SLionel Sambuc         ptrdiff_t ninp = gptr()  - eback();
1724684ddb6SLionel Sambuc         ptrdiff_t einp = egptr() - eback();
1734684ddb6SLionel Sambuc         ptrdiff_t nout = pptr()  - pbase();
1744684ddb6SLionel Sambuc         ptrdiff_t eout = epptr() - pbase();
1754684ddb6SLionel Sambuc         if (__strmode_ & __allocated)
1764684ddb6SLionel Sambuc         {
1774684ddb6SLionel Sambuc             if (__pfree_)
1784684ddb6SLionel Sambuc                 __pfree_(eback());
1794684ddb6SLionel Sambuc             else
1804684ddb6SLionel Sambuc                 delete [] eback();
1814684ddb6SLionel Sambuc         }
1824684ddb6SLionel Sambuc         setg(buf, buf + ninp, buf + einp);
1834684ddb6SLionel Sambuc         setp(buf + einp, buf + einp + eout);
1844684ddb6SLionel Sambuc         pbump(static_cast<int>(nout));
1854684ddb6SLionel Sambuc         __strmode_ |= __allocated;
1864684ddb6SLionel Sambuc     }
1874684ddb6SLionel Sambuc     *pptr() = static_cast<char>(__c);
1884684ddb6SLionel Sambuc     pbump(1);
189*0a6a1f1dSLionel Sambuc     return int_type(static_cast<unsigned char>(__c));
1904684ddb6SLionel Sambuc }
1914684ddb6SLionel Sambuc 
1924684ddb6SLionel Sambuc strstreambuf::int_type
pbackfail(int_type __c)1934684ddb6SLionel Sambuc strstreambuf::pbackfail(int_type __c)
1944684ddb6SLionel Sambuc {
1954684ddb6SLionel Sambuc     if (eback() == gptr())
1964684ddb6SLionel Sambuc         return EOF;
1974684ddb6SLionel Sambuc     if (__c == EOF)
1984684ddb6SLionel Sambuc     {
1994684ddb6SLionel Sambuc         gbump(-1);
2004684ddb6SLionel Sambuc         return int_type(0);
2014684ddb6SLionel Sambuc     }
2024684ddb6SLionel Sambuc     if (__strmode_ & __constant)
2034684ddb6SLionel Sambuc     {
2044684ddb6SLionel Sambuc         if (gptr()[-1] == static_cast<char>(__c))
2054684ddb6SLionel Sambuc         {
2064684ddb6SLionel Sambuc             gbump(-1);
2074684ddb6SLionel Sambuc             return __c;
2084684ddb6SLionel Sambuc         }
2094684ddb6SLionel Sambuc         return EOF;
2104684ddb6SLionel Sambuc     }
2114684ddb6SLionel Sambuc     gbump(-1);
2124684ddb6SLionel Sambuc     *gptr() = static_cast<char>(__c);
2134684ddb6SLionel Sambuc     return __c;
2144684ddb6SLionel Sambuc }
2154684ddb6SLionel Sambuc 
2164684ddb6SLionel Sambuc strstreambuf::int_type
underflow()2174684ddb6SLionel Sambuc strstreambuf::underflow()
2184684ddb6SLionel Sambuc {
2194684ddb6SLionel Sambuc     if (gptr() == egptr())
2204684ddb6SLionel Sambuc     {
2214684ddb6SLionel Sambuc         if (egptr() >= pptr())
2224684ddb6SLionel Sambuc             return EOF;
2234684ddb6SLionel Sambuc         setg(eback(), gptr(), pptr());
2244684ddb6SLionel Sambuc     }
225*0a6a1f1dSLionel Sambuc     return int_type(static_cast<unsigned char>(*gptr()));
2264684ddb6SLionel Sambuc }
2274684ddb6SLionel Sambuc 
2284684ddb6SLionel Sambuc strstreambuf::pos_type
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __which)2294684ddb6SLionel Sambuc strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
2304684ddb6SLionel Sambuc {
2314684ddb6SLionel Sambuc     off_type __p(-1);
2324684ddb6SLionel Sambuc     bool pos_in = (__which & ios::in) != 0;
2334684ddb6SLionel Sambuc     bool pos_out = (__which & ios::out) != 0;
2344684ddb6SLionel Sambuc     bool legal = false;
2354684ddb6SLionel Sambuc     switch (__way)
2364684ddb6SLionel Sambuc     {
2374684ddb6SLionel Sambuc     case ios::beg:
2384684ddb6SLionel Sambuc     case ios::end:
2394684ddb6SLionel Sambuc         if (pos_in || pos_out)
2404684ddb6SLionel Sambuc             legal = true;
2414684ddb6SLionel Sambuc         break;
2424684ddb6SLionel Sambuc     case ios::cur:
2434684ddb6SLionel Sambuc         if (pos_in != pos_out)
2444684ddb6SLionel Sambuc             legal = true;
2454684ddb6SLionel Sambuc         break;
2464684ddb6SLionel Sambuc     }
2474684ddb6SLionel Sambuc     if (pos_in && gptr() == nullptr)
2484684ddb6SLionel Sambuc         legal = false;
2494684ddb6SLionel Sambuc     if (pos_out && pptr() == nullptr)
2504684ddb6SLionel Sambuc         legal = false;
2514684ddb6SLionel Sambuc     if (legal)
2524684ddb6SLionel Sambuc     {
2534684ddb6SLionel Sambuc         off_type newoff;
2544684ddb6SLionel Sambuc         char* seekhigh = epptr() ? epptr() : egptr();
2554684ddb6SLionel Sambuc         switch (__way)
2564684ddb6SLionel Sambuc         {
2574684ddb6SLionel Sambuc         case ios::beg:
2584684ddb6SLionel Sambuc             newoff = 0;
2594684ddb6SLionel Sambuc             break;
2604684ddb6SLionel Sambuc         case ios::cur:
2614684ddb6SLionel Sambuc             newoff = (pos_in ? gptr() : pptr()) - eback();
2624684ddb6SLionel Sambuc             break;
2634684ddb6SLionel Sambuc         case ios::end:
2644684ddb6SLionel Sambuc             newoff = seekhigh - eback();
2654684ddb6SLionel Sambuc             break;
2664684ddb6SLionel Sambuc         }
2674684ddb6SLionel Sambuc         newoff += __off;
2684684ddb6SLionel Sambuc         if (0 <= newoff && newoff <= seekhigh - eback())
2694684ddb6SLionel Sambuc         {
2704684ddb6SLionel Sambuc             char* newpos = eback() + newoff;
2714684ddb6SLionel Sambuc             if (pos_in)
2724684ddb6SLionel Sambuc                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
2734684ddb6SLionel Sambuc             if (pos_out)
2744684ddb6SLionel Sambuc             {
2754684ddb6SLionel Sambuc                 // min(pbase, newpos), newpos, epptr()
2764684ddb6SLionel Sambuc                 __off = epptr() - newpos;
2774684ddb6SLionel Sambuc                 setp(min(pbase(), newpos), epptr());
2784684ddb6SLionel Sambuc                 pbump(static_cast<int>((epptr() - pbase()) - __off));
2794684ddb6SLionel Sambuc             }
2804684ddb6SLionel Sambuc             __p = newoff;
2814684ddb6SLionel Sambuc         }
2824684ddb6SLionel Sambuc     }
2834684ddb6SLionel Sambuc     return pos_type(__p);
2844684ddb6SLionel Sambuc }
2854684ddb6SLionel Sambuc 
2864684ddb6SLionel Sambuc strstreambuf::pos_type
seekpos(pos_type __sp,ios_base::openmode __which)2874684ddb6SLionel Sambuc strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
2884684ddb6SLionel Sambuc {
2894684ddb6SLionel Sambuc     off_type __p(-1);
2904684ddb6SLionel Sambuc     bool pos_in = (__which & ios::in) != 0;
2914684ddb6SLionel Sambuc     bool pos_out = (__which & ios::out) != 0;
2924684ddb6SLionel Sambuc     if (pos_in || pos_out)
2934684ddb6SLionel Sambuc     {
2944684ddb6SLionel Sambuc         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
2954684ddb6SLionel Sambuc         {
2964684ddb6SLionel Sambuc             off_type newoff = __sp;
2974684ddb6SLionel Sambuc             char* seekhigh = epptr() ? epptr() : egptr();
2984684ddb6SLionel Sambuc             if (0 <= newoff && newoff <= seekhigh - eback())
2994684ddb6SLionel Sambuc             {
3004684ddb6SLionel Sambuc                 char* newpos = eback() + newoff;
3014684ddb6SLionel Sambuc                 if (pos_in)
3024684ddb6SLionel Sambuc                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
3034684ddb6SLionel Sambuc                 if (pos_out)
3044684ddb6SLionel Sambuc                 {
3054684ddb6SLionel Sambuc                     // min(pbase, newpos), newpos, epptr()
3064684ddb6SLionel Sambuc                     off_type temp = epptr() - newpos;
3074684ddb6SLionel Sambuc                     setp(min(pbase(), newpos), epptr());
3084684ddb6SLionel Sambuc                     pbump(static_cast<int>((epptr() - pbase()) - temp));
3094684ddb6SLionel Sambuc                 }
3104684ddb6SLionel Sambuc                 __p = newoff;
3114684ddb6SLionel Sambuc             }
3124684ddb6SLionel Sambuc         }
3134684ddb6SLionel Sambuc     }
3144684ddb6SLionel Sambuc     return pos_type(__p);
3154684ddb6SLionel Sambuc }
3164684ddb6SLionel Sambuc 
~istrstream()3174684ddb6SLionel Sambuc istrstream::~istrstream()
3184684ddb6SLionel Sambuc {
3194684ddb6SLionel Sambuc }
3204684ddb6SLionel Sambuc 
~ostrstream()3214684ddb6SLionel Sambuc ostrstream::~ostrstream()
3224684ddb6SLionel Sambuc {
3234684ddb6SLionel Sambuc }
3244684ddb6SLionel Sambuc 
~strstream()3254684ddb6SLionel Sambuc strstream::~strstream()
3264684ddb6SLionel Sambuc {
3274684ddb6SLionel Sambuc }
3284684ddb6SLionel Sambuc 
3294684ddb6SLionel Sambuc _LIBCPP_END_NAMESPACE_STD
330