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