Home | History | Annotate | Download | only in src
      1 //===------------------------ strstream.cpp -------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "strstream"
     11 #include "algorithm"
     12 #include "climits"
     13 #include "cstring"
     14 #include "cstdlib"
     15 #include "__debug"
     16 #include "__undef_macros"
     17 
     18 _LIBCPP_BEGIN_NAMESPACE_STD
     19 
     20 strstreambuf::strstreambuf(streamsize __alsize)
     21     : __strmode_(__dynamic),
     22       __alsize_(__alsize),
     23       __palloc_(nullptr),
     24       __pfree_(nullptr)
     25 {
     26 }
     27 
     28 strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
     29     : __strmode_(__dynamic),
     30       __alsize_(__default_alsize),
     31       __palloc_(__palloc),
     32       __pfree_(__pfree)
     33 {
     34 }
     35 
     36 void
     37 strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
     38 {
     39     if (__n == 0)
     40         __n = static_cast<streamsize>(strlen(__gnext));
     41     else if (__n < 0)
     42         __n = INT_MAX;
     43     if (__pbeg == nullptr)
     44         setg(__gnext, __gnext, __gnext + __n);
     45     else
     46     {
     47         setg(__gnext, __gnext, __pbeg);
     48         setp(__pbeg, __pbeg + __n);
     49     }
     50 }
     51 
     52 strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
     53     : __strmode_(),
     54       __alsize_(__default_alsize),
     55       __palloc_(nullptr),
     56       __pfree_(nullptr)
     57 {
     58     __init(__gnext, __n, __pbeg);
     59 }
     60 
     61 strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
     62     : __strmode_(__constant),
     63       __alsize_(__default_alsize),
     64       __palloc_(nullptr),
     65       __pfree_(nullptr)
     66 {
     67     __init(const_cast<char *>(__gnext), __n, nullptr);
     68 }
     69 
     70 strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
     71     : __strmode_(),
     72       __alsize_(__default_alsize),
     73       __palloc_(nullptr),
     74       __pfree_(nullptr)
     75 {
     76     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
     77 }
     78 
     79 strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
     80     : __strmode_(__constant),
     81       __alsize_(__default_alsize),
     82       __palloc_(nullptr),
     83       __pfree_(nullptr)
     84 {
     85     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
     86 }
     87 
     88 strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
     89     : __strmode_(),
     90       __alsize_(__default_alsize),
     91       __palloc_(nullptr),
     92       __pfree_(nullptr)
     93 {
     94     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
     95 }
     96 
     97 strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
     98     : __strmode_(__constant),
     99       __alsize_(__default_alsize),
    100       __palloc_(nullptr),
    101       __pfree_(nullptr)
    102 {
    103     __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
    104 }
    105 
    106 strstreambuf::~strstreambuf()
    107 {
    108     if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
    109     {
    110         if (__pfree_)
    111             __pfree_(eback());
    112         else
    113             delete [] eback();
    114     }
    115 }
    116 
    117 void
    118 strstreambuf::swap(strstreambuf& __rhs)
    119 {
    120     streambuf::swap(__rhs);
    121     _VSTD::swap(__strmode_, __rhs.__strmode_);
    122     _VSTD::swap(__alsize_, __rhs.__alsize_);
    123     _VSTD::swap(__palloc_, __rhs.__palloc_);
    124     _VSTD::swap(__pfree_, __rhs.__pfree_);
    125 }
    126 
    127 void
    128 strstreambuf::freeze(bool __freezefl)
    129 {
    130     if (__strmode_ & __dynamic)
    131     {
    132         if (__freezefl)
    133             __strmode_ |= __frozen;
    134         else
    135             __strmode_ &= ~__frozen;
    136     }
    137 }
    138 
    139 char*
    140 strstreambuf::str()
    141 {
    142     if (__strmode_ & __dynamic)
    143         __strmode_ |= __frozen;
    144     return eback();
    145 }
    146 
    147 int
    148 strstreambuf::pcount() const
    149 {
    150     return static_cast<int>(pptr() - pbase());
    151 }
    152 
    153 strstreambuf::int_type
    154 strstreambuf::overflow(int_type __c)
    155 {
    156     if (__c == EOF)
    157         return int_type(0);
    158     if (pptr() == epptr())
    159     {
    160         if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
    161             return int_type(EOF);
    162         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
    163         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
    164         if (new_size == 0)
    165             new_size = __default_alsize;
    166         char* buf = nullptr;
    167         if (__palloc_)
    168             buf = static_cast<char*>(__palloc_(new_size));
    169         else
    170             buf = new char[new_size];
    171         if (buf == nullptr)
    172             return int_type(EOF);
    173         if (old_size != 0) {
    174             _LIBCPP_ASSERT(eback(), "overflow copying from NULL");
    175             memcpy(buf, eback(), static_cast<size_t>(old_size));
    176         }
    177         ptrdiff_t ninp = gptr()  - eback();
    178         ptrdiff_t einp = egptr() - eback();
    179         ptrdiff_t nout = pptr()  - pbase();
    180         if (__strmode_ & __allocated)
    181         {
    182             if (__pfree_)
    183                 __pfree_(eback());
    184             else
    185                 delete [] eback();
    186         }
    187         setg(buf, buf + ninp, buf + einp);
    188         setp(buf + einp, buf + new_size);
    189         pbump(static_cast<int>(nout));
    190         __strmode_ |= __allocated;
    191     }
    192     *pptr() = static_cast<char>(__c);
    193     pbump(1);
    194     return int_type(static_cast<unsigned char>(__c));
    195 }
    196 
    197 strstreambuf::int_type
    198 strstreambuf::pbackfail(int_type __c)
    199 {
    200     if (eback() == gptr())
    201         return EOF;
    202     if (__c == EOF)
    203     {
    204         gbump(-1);
    205         return int_type(0);
    206     }
    207     if (__strmode_ & __constant)
    208     {
    209         if (gptr()[-1] == static_cast<char>(__c))
    210         {
    211             gbump(-1);
    212             return __c;
    213         }
    214         return EOF;
    215     }
    216     gbump(-1);
    217     *gptr() = static_cast<char>(__c);
    218     return __c;
    219 }
    220 
    221 strstreambuf::int_type
    222 strstreambuf::underflow()
    223 {
    224     if (gptr() == egptr())
    225     {
    226         if (egptr() >= pptr())
    227             return EOF;
    228         setg(eback(), gptr(), pptr());
    229     }
    230     return int_type(static_cast<unsigned char>(*gptr()));
    231 }
    232 
    233 strstreambuf::pos_type
    234 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
    235 {
    236     off_type __p(-1);
    237     bool pos_in = (__which & ios::in) != 0;
    238     bool pos_out = (__which & ios::out) != 0;
    239     bool legal = false;
    240     switch (__way)
    241     {
    242     case ios::beg:
    243     case ios::end:
    244         if (pos_in || pos_out)
    245             legal = true;
    246         break;
    247     case ios::cur:
    248         if (pos_in != pos_out)
    249             legal = true;
    250         break;
    251     }
    252     if (pos_in && gptr() == nullptr)
    253         legal = false;
    254     if (pos_out && pptr() == nullptr)
    255         legal = false;
    256     if (legal)
    257     {
    258         off_type newoff;
    259         char* seekhigh = epptr() ? epptr() : egptr();
    260         switch (__way)
    261         {
    262         case ios::beg:
    263             newoff = 0;
    264             break;
    265         case ios::cur:
    266             newoff = (pos_in ? gptr() : pptr()) - eback();
    267             break;
    268         case ios::end:
    269             newoff = seekhigh - eback();
    270             break;
    271         default:
    272             _LIBCPP_UNREACHABLE();
    273         }
    274         newoff += __off;
    275         if (0 <= newoff && newoff <= seekhigh - eback())
    276         {
    277             char* newpos = eback() + newoff;
    278             if (pos_in)
    279                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
    280             if (pos_out)
    281             {
    282                 // min(pbase, newpos), newpos, epptr()
    283                 __off = epptr() - newpos;
    284                 setp(min(pbase(), newpos), epptr());
    285                 pbump(static_cast<int>((epptr() - pbase()) - __off));
    286             }
    287             __p = newoff;
    288         }
    289     }
    290     return pos_type(__p);
    291 }
    292 
    293 strstreambuf::pos_type
    294 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
    295 {
    296     off_type __p(-1);
    297     bool pos_in = (__which & ios::in) != 0;
    298     bool pos_out = (__which & ios::out) != 0;
    299     if (pos_in || pos_out)
    300     {
    301         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
    302         {
    303             off_type newoff = __sp;
    304             char* seekhigh = epptr() ? epptr() : egptr();
    305             if (0 <= newoff && newoff <= seekhigh - eback())
    306             {
    307                 char* newpos = eback() + newoff;
    308                 if (pos_in)
    309                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
    310                 if (pos_out)
    311                 {
    312                     // min(pbase, newpos), newpos, epptr()
    313                     off_type temp = epptr() - newpos;
    314                     setp(min(pbase(), newpos), epptr());
    315                     pbump(static_cast<int>((epptr() - pbase()) - temp));
    316                 }
    317                 __p = newoff;
    318             }
    319         }
    320     }
    321     return pos_type(__p);
    322 }
    323 
    324 istrstream::~istrstream()
    325 {
    326 }
    327 
    328 ostrstream::~ostrstream()
    329 {
    330 }
    331 
    332 strstream::~strstream()
    333 {
    334 }
    335 
    336 _LIBCPP_END_NAMESPACE_STD
    337