C++14 support[1], adds more C++1z features[2], and fixes the following LWG issues[3]: 1450: Contradiction in regex_constants 2003: String exception inconsistency in erase. 2075: Progress guarantees, lock-free property, and scheduling assumptions 2104: unique_lock move-assignment should not be noexcept 2112: User-defined classes that cannot be derived from 2132: std::function ambiguity 2135: Unclear requirement for exceptions thrown in condition_variable::wait() 2142: packaged_task::operator() synchronization too broad? 2182: Container::[const_]reference types are misleadingly specified 2186: Incomplete action on async/launch::deferred 2188: Reverse iterator does not fully support targets that overload operator& 2193: Default constructors for standard library containers are explicit 2205: Problematic postconditions of regex_match and regex_search 2213: Return value of std::regex_replace 2240: Probable misuse of term "function scope" in [thread.condition] 2252: Strong guarantee on vector::push_back() still broken with C++11? 2257: Simplify container requirements with the new algorithms 2258: a.erase(q1, q2) unable to directly return q2 2263: Comparing iterators and allocator pointers with different const-character 2268: Setting a default argument in the declaration of a member function assign of std::basic_string 2271: regex_traits::lookup_classname specification unclear 2272: quoted should use char_traits::eq for character comparison 2278: User-defined literals for Standard Library types 2280: begin / end for arrays should be constexpr and noexcept 2285: make_reverse_iterator 2288: Inconsistent requirements for shared mutexes 2291: std::hash is vulnerable to collision DoS attack 2293: Wrong facet used by num_put::do_put 2299: Effects of inaccessible key_compare::is_transparent type are not clear 2301: Why is std::tie not constexpr? 2304: Complexity of count in unordered associative containers 2306: match_results::reference should be value_type&, not const value_type& 2308: Clarify container destructor requirements w.r.t. std::array 2313: tuple_size should always derive from integral_constant<size_t, N> 2314: apply() should return decltype(auto) and use decay_t before tuple_size 2315: weak_ptr should be movable 2316: weak_ptr::lock() should be atomic 2317: The type property queries should be UnaryTypeTraits returning size_t 2320: select_on_container_copy_construction() takes allocators, not containers 2322: Associative(initializer_list, stuff) constructors are underspecified 2323: vector::resize(n, t)'s specification should be simplified 2324: Insert iterator constructors should use addressof() 2329: regex_match()/regex_search() with match_results should forbid temporary strings 2330: regex("meow", regex::icase) is technically forbidden but should be permitted 2332: regex_iterator/regex_token_iterator should forbid temporary regexes 2339: Wording issue in nth_element 2341: Inconsistency between basic_ostream::seekp(pos) and basic_ostream::seekp(off, dir) 2344: quoted()'s interaction with padding is unclear 2346: integral_constant's member functions should be marked noexcept 2350: min, max, and minmax should be constexpr 2356: Stability of erasure in unordered associative containers 2357: Remaining "Assignable" requirement 2359: How does regex_constants::nosubs affect basic_regex::mark_count()? 2360: reverse_iterator::operator*() is unimplementable [1] http://libcxx.llvm.org/cxx1y_status.html [2] http://libcxx.llvm.org/cxx1z_status.html [3] http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html Exp-run: antoine MFC after: 1 month
330 lines
8.3 KiB
C++
330 lines
8.3 KiB
C++
//===------------------------ strstream.cpp -------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "strstream"
|
|
#include "algorithm"
|
|
#include "climits"
|
|
#include "cstring"
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
strstreambuf::strstreambuf(streamsize __alsize)
|
|
: __strmode_(__dynamic),
|
|
__alsize_(__alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
}
|
|
|
|
strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
|
|
: __strmode_(__dynamic),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(__palloc),
|
|
__pfree_(__pfree)
|
|
{
|
|
}
|
|
|
|
void
|
|
strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
|
|
{
|
|
if (__n == 0)
|
|
__n = static_cast<streamsize>(strlen(__gnext));
|
|
else if (__n < 0)
|
|
__n = INT_MAX;
|
|
if (__pbeg == nullptr)
|
|
setg(__gnext, __gnext, __gnext + __n);
|
|
else
|
|
{
|
|
setg(__gnext, __gnext, __pbeg);
|
|
setp(__pbeg, __pbeg + __n);
|
|
}
|
|
}
|
|
|
|
strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
|
|
: __strmode_(),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(__gnext, __n, __pbeg);
|
|
}
|
|
|
|
strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
|
|
: __strmode_(__constant),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(const_cast<char *>(__gnext), __n, nullptr);
|
|
}
|
|
|
|
strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
|
|
: __strmode_(),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
|
|
}
|
|
|
|
strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
|
|
: __strmode_(__constant),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
|
|
}
|
|
|
|
strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
|
|
: __strmode_(),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
|
|
}
|
|
|
|
strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
|
|
: __strmode_(__constant),
|
|
__alsize_(__default_alsize),
|
|
__palloc_(nullptr),
|
|
__pfree_(nullptr)
|
|
{
|
|
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
|
|
}
|
|
|
|
strstreambuf::~strstreambuf()
|
|
{
|
|
if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
|
|
{
|
|
if (__pfree_)
|
|
__pfree_(eback());
|
|
else
|
|
delete [] eback();
|
|
}
|
|
}
|
|
|
|
void
|
|
strstreambuf::swap(strstreambuf& __rhs)
|
|
{
|
|
streambuf::swap(__rhs);
|
|
_VSTD::swap(__strmode_, __rhs.__strmode_);
|
|
_VSTD::swap(__alsize_, __rhs.__alsize_);
|
|
_VSTD::swap(__palloc_, __rhs.__palloc_);
|
|
_VSTD::swap(__pfree_, __rhs.__pfree_);
|
|
}
|
|
|
|
void
|
|
strstreambuf::freeze(bool __freezefl)
|
|
{
|
|
if (__strmode_ & __dynamic)
|
|
{
|
|
if (__freezefl)
|
|
__strmode_ |= __frozen;
|
|
else
|
|
__strmode_ &= ~__frozen;
|
|
}
|
|
}
|
|
|
|
char*
|
|
strstreambuf::str()
|
|
{
|
|
if (__strmode_ & __dynamic)
|
|
__strmode_ |= __frozen;
|
|
return eback();
|
|
}
|
|
|
|
int
|
|
strstreambuf::pcount() const
|
|
{
|
|
return static_cast<int>(pptr() - pbase());
|
|
}
|
|
|
|
strstreambuf::int_type
|
|
strstreambuf::overflow(int_type __c)
|
|
{
|
|
if (__c == EOF)
|
|
return int_type(0);
|
|
if (pptr() == epptr())
|
|
{
|
|
if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
|
|
return int_type(EOF);
|
|
size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
|
|
size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
|
|
if (new_size == 0)
|
|
new_size = __default_alsize;
|
|
char* buf = nullptr;
|
|
if (__palloc_)
|
|
buf = static_cast<char*>(__palloc_(new_size));
|
|
else
|
|
buf = new char[new_size];
|
|
if (buf == nullptr)
|
|
return int_type(EOF);
|
|
memcpy(buf, eback(), static_cast<size_t>(old_size));
|
|
ptrdiff_t ninp = gptr() - eback();
|
|
ptrdiff_t einp = egptr() - eback();
|
|
ptrdiff_t nout = pptr() - pbase();
|
|
ptrdiff_t eout = epptr() - pbase();
|
|
if (__strmode_ & __allocated)
|
|
{
|
|
if (__pfree_)
|
|
__pfree_(eback());
|
|
else
|
|
delete [] eback();
|
|
}
|
|
setg(buf, buf + ninp, buf + einp);
|
|
setp(buf + einp, buf + einp + eout);
|
|
pbump(static_cast<int>(nout));
|
|
__strmode_ |= __allocated;
|
|
}
|
|
*pptr() = static_cast<char>(__c);
|
|
pbump(1);
|
|
return int_type(static_cast<unsigned char>(__c));
|
|
}
|
|
|
|
strstreambuf::int_type
|
|
strstreambuf::pbackfail(int_type __c)
|
|
{
|
|
if (eback() == gptr())
|
|
return EOF;
|
|
if (__c == EOF)
|
|
{
|
|
gbump(-1);
|
|
return int_type(0);
|
|
}
|
|
if (__strmode_ & __constant)
|
|
{
|
|
if (gptr()[-1] == static_cast<char>(__c))
|
|
{
|
|
gbump(-1);
|
|
return __c;
|
|
}
|
|
return EOF;
|
|
}
|
|
gbump(-1);
|
|
*gptr() = static_cast<char>(__c);
|
|
return __c;
|
|
}
|
|
|
|
strstreambuf::int_type
|
|
strstreambuf::underflow()
|
|
{
|
|
if (gptr() == egptr())
|
|
{
|
|
if (egptr() >= pptr())
|
|
return EOF;
|
|
setg(eback(), gptr(), pptr());
|
|
}
|
|
return int_type(static_cast<unsigned char>(*gptr()));
|
|
}
|
|
|
|
strstreambuf::pos_type
|
|
strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
|
|
{
|
|
off_type __p(-1);
|
|
bool pos_in = (__which & ios::in) != 0;
|
|
bool pos_out = (__which & ios::out) != 0;
|
|
bool legal = false;
|
|
switch (__way)
|
|
{
|
|
case ios::beg:
|
|
case ios::end:
|
|
if (pos_in || pos_out)
|
|
legal = true;
|
|
break;
|
|
case ios::cur:
|
|
if (pos_in != pos_out)
|
|
legal = true;
|
|
break;
|
|
}
|
|
if (pos_in && gptr() == nullptr)
|
|
legal = false;
|
|
if (pos_out && pptr() == nullptr)
|
|
legal = false;
|
|
if (legal)
|
|
{
|
|
off_type newoff;
|
|
char* seekhigh = epptr() ? epptr() : egptr();
|
|
switch (__way)
|
|
{
|
|
case ios::beg:
|
|
newoff = 0;
|
|
break;
|
|
case ios::cur:
|
|
newoff = (pos_in ? gptr() : pptr()) - eback();
|
|
break;
|
|
case ios::end:
|
|
newoff = seekhigh - eback();
|
|
break;
|
|
}
|
|
newoff += __off;
|
|
if (0 <= newoff && newoff <= seekhigh - eback())
|
|
{
|
|
char* newpos = eback() + newoff;
|
|
if (pos_in)
|
|
setg(eback(), newpos, _VSTD::max(newpos, egptr()));
|
|
if (pos_out)
|
|
{
|
|
// min(pbase, newpos), newpos, epptr()
|
|
__off = epptr() - newpos;
|
|
setp(min(pbase(), newpos), epptr());
|
|
pbump(static_cast<int>((epptr() - pbase()) - __off));
|
|
}
|
|
__p = newoff;
|
|
}
|
|
}
|
|
return pos_type(__p);
|
|
}
|
|
|
|
strstreambuf::pos_type
|
|
strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
|
|
{
|
|
off_type __p(-1);
|
|
bool pos_in = (__which & ios::in) != 0;
|
|
bool pos_out = (__which & ios::out) != 0;
|
|
if (pos_in || pos_out)
|
|
{
|
|
if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
|
|
{
|
|
off_type newoff = __sp;
|
|
char* seekhigh = epptr() ? epptr() : egptr();
|
|
if (0 <= newoff && newoff <= seekhigh - eback())
|
|
{
|
|
char* newpos = eback() + newoff;
|
|
if (pos_in)
|
|
setg(eback(), newpos, _VSTD::max(newpos, egptr()));
|
|
if (pos_out)
|
|
{
|
|
// min(pbase, newpos), newpos, epptr()
|
|
off_type temp = epptr() - newpos;
|
|
setp(min(pbase(), newpos), epptr());
|
|
pbump(static_cast<int>((epptr() - pbase()) - temp));
|
|
}
|
|
__p = newoff;
|
|
}
|
|
}
|
|
}
|
|
return pos_type(__p);
|
|
}
|
|
|
|
istrstream::~istrstream()
|
|
{
|
|
}
|
|
|
|
ostrstream::~ostrstream()
|
|
{
|
|
}
|
|
|
|
strstream::~strstream()
|
|
{
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|