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