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(const_cast<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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<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(const_cast<char *>(reinterpret_cast<const 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(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<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(const_cast<char *>(reinterpret_cast<const 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         size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
    160         size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
    161         if (new_size == 0)
    162             new_size = __default_alsize;
    163         char* buf = nullptr;
    164         if (__palloc_)
    165             buf = static_cast<char*>(__palloc_(new_size));
    166         else
    167             buf = new char[new_size];
    168         if (buf == nullptr)
    169             return int_type(EOF);
    170         memcpy(buf, eback(), static_cast<size_t>(old_size));
    171         ptrdiff_t ninp = gptr()  - eback();
    172         ptrdiff_t einp = egptr() - eback();
    173         ptrdiff_t nout = pptr()  - pbase();
    174         ptrdiff_t eout = epptr() - pbase();
    175         if (__strmode_ & __allocated)
    176         {
    177             if (__pfree_)
    178                 __pfree_(eback());
    179             else
    180                 delete [] eback();
    181         }
    182         setg(buf, buf + ninp, buf + einp);
    183         setp(buf + einp, buf + einp + eout);
    184         pbump(static_cast<int>(nout));
    185         __strmode_ |= __allocated;
    186     }
    187     *pptr() = static_cast<char>(__c);
    188     pbump(1);
    189     return int_type(static_cast<unsigned char>(__c));
    190 }
    191 
    192 strstreambuf::int_type
    193 strstreambuf::pbackfail(int_type __c)
    194 {
    195     if (eback() == gptr())
    196         return EOF;
    197     if (__c == EOF)
    198     {
    199         gbump(-1);
    200         return int_type(0);
    201     }
    202     if (__strmode_ & __constant)
    203     {
    204         if (gptr()[-1] == static_cast<char>(__c))
    205         {
    206             gbump(-1);
    207             return __c;
    208         }
    209         return EOF;
    210     }
    211     gbump(-1);
    212     *gptr() = static_cast<char>(__c);
    213     return __c;
    214 }
    215 
    216 strstreambuf::int_type
    217 strstreambuf::underflow()
    218 {
    219     if (gptr() == egptr())
    220     {
    221         if (egptr() >= pptr())
    222             return EOF;
    223         setg(eback(), gptr(), pptr());
    224     }
    225     return int_type(static_cast<unsigned char>(*gptr()));
    226 }
    227 
    228 strstreambuf::pos_type
    229 strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
    230 {
    231     off_type __p(-1);
    232     bool pos_in = (__which & ios::in) != 0;
    233     bool pos_out = (__which & ios::out) != 0;
    234     bool legal = false;
    235     switch (__way)
    236     {
    237     case ios::beg:
    238     case ios::end:
    239         if (pos_in || pos_out)
    240             legal = true;
    241         break;
    242     case ios::cur:
    243         if (pos_in != pos_out)
    244             legal = true;
    245         break;
    246     }
    247     if (pos_in && gptr() == nullptr)
    248         legal = false;
    249     if (pos_out && pptr() == nullptr)
    250         legal = false;
    251     if (legal)
    252     {
    253         off_type newoff;
    254         char* seekhigh = epptr() ? epptr() : egptr();
    255         switch (__way)
    256         {
    257         case ios::beg:
    258             newoff = 0;
    259             break;
    260         case ios::cur:
    261             newoff = (pos_in ? gptr() : pptr()) - eback();
    262             break;
    263         case ios::end:
    264             newoff = seekhigh - eback();
    265             break;
    266         }
    267         newoff += __off;
    268         if (0 <= newoff && newoff <= seekhigh - eback())
    269         {
    270             char* newpos = eback() + newoff;
    271             if (pos_in)
    272                 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
    273             if (pos_out)
    274             {
    275                 // min(pbase, newpos), newpos, epptr()
    276                 __off = epptr() - newpos;
    277                 setp(min(pbase(), newpos), epptr());
    278                 pbump(static_cast<int>((epptr() - pbase()) - __off));
    279             }
    280             __p = newoff;
    281         }
    282     }
    283     return pos_type(__p);
    284 }
    285 
    286 strstreambuf::pos_type
    287 strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
    288 {
    289     off_type __p(-1);
    290     bool pos_in = (__which & ios::in) != 0;
    291     bool pos_out = (__which & ios::out) != 0;
    292     if (pos_in || pos_out)
    293     {
    294         if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
    295         {
    296             off_type newoff = __sp;
    297             char* seekhigh = epptr() ? epptr() : egptr();
    298             if (0 <= newoff && newoff <= seekhigh - eback())
    299             {
    300                 char* newpos = eback() + newoff;
    301                 if (pos_in)
    302                     setg(eback(), newpos, _VSTD::max(newpos, egptr()));
    303                 if (pos_out)
    304                 {
    305                     // min(pbase, newpos), newpos, epptr()
    306                     off_type temp = epptr() - newpos;
    307                     setp(min(pbase(), newpos), epptr());
    308                     pbump(static_cast<int>((epptr() - pbase()) - temp));
    309                 }
    310                 __p = newoff;
    311             }
    312         }
    313     }
    314     return pos_type(__p);
    315 }
    316 
    317 istrstream::~istrstream()
    318 {
    319 }
    320 
    321 ostrstream::~ostrstream()
    322 {
    323 }
    324 
    325 strstream::~strstream()
    326 {
    327 }
    328 
    329 _LIBCPP_END_NAMESPACE_STD
    330