Path: blob/main/contrib/llvm-project/libcxx/src/strstream.cpp
35154 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <__assert>9#include <__utility/unreachable.h>10#include <algorithm>11#include <climits>12#include <cstdlib>13#include <cstring>14#include <strstream>1516_LIBCPP_PUSH_MACROS17#include <__undef_macros>1819_LIBCPP_BEGIN_NAMESPACE_STD2021strstreambuf::strstreambuf(streamsize __alsize)22: __strmode_(__dynamic), __alsize_(__alsize), __palloc_(nullptr), __pfree_(nullptr) {}2324strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))25: __strmode_(__dynamic), __alsize_(__default_alsize), __palloc_(__palloc), __pfree_(__pfree) {}2627void strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) {28if (__n == 0)29__n = static_cast<streamsize>(strlen(__gnext));30else if (__n < 0)31__n = INT_MAX;32if (__pbeg == nullptr)33setg(__gnext, __gnext, __gnext + __n);34else {35setg(__gnext, __gnext, __pbeg);36setp(__pbeg, __pbeg + __n);37}38}3940strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)41: __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {42__init(__gnext, __n, __pbeg);43}4445strstreambuf::strstreambuf(const char* __gnext, streamsize __n)46: __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {47__init(const_cast<char*>(__gnext), __n, nullptr);48}4950strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)51: __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {52__init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));53}5455strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)56: __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {57__init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);58}5960strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)61: __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {62__init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));63}6465strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)66: __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {67__init(const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);68}6970strstreambuf::~strstreambuf() {71if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) {72if (__pfree_)73__pfree_(eback());74else75delete[] eback();76}77}7879void strstreambuf::swap(strstreambuf& __rhs) {80streambuf::swap(__rhs);81std::swap(__strmode_, __rhs.__strmode_);82std::swap(__alsize_, __rhs.__alsize_);83std::swap(__palloc_, __rhs.__palloc_);84std::swap(__pfree_, __rhs.__pfree_);85}8687void strstreambuf::freeze(bool __freezefl) {88if (__strmode_ & __dynamic) {89if (__freezefl)90__strmode_ |= __frozen;91else92__strmode_ &= ~__frozen;93}94}9596char* strstreambuf::str() {97if (__strmode_ & __dynamic)98__strmode_ |= __frozen;99return eback();100}101102int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); }103104strstreambuf::int_type strstreambuf::overflow(int_type __c) {105if (__c == EOF)106return int_type(0);107if (pptr() == epptr()) {108if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)109return int_type(EOF);110size_t old_size = static_cast<size_t>((epptr() ? epptr() : egptr()) - eback());111size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2 * old_size);112if (new_size == 0)113new_size = __default_alsize;114char* buf = nullptr;115if (__palloc_)116buf = static_cast<char*>(__palloc_(new_size));117else118buf = new char[new_size];119if (buf == nullptr)120return int_type(EOF);121if (old_size != 0) {122_LIBCPP_ASSERT_INTERNAL(eback(), "strstreambuf::overflow reallocating but the get area is a null pointer");123memcpy(buf, eback(), static_cast<size_t>(old_size));124}125ptrdiff_t ninp = gptr() - eback();126ptrdiff_t einp = egptr() - eback();127ptrdiff_t nout = pptr() - pbase();128if (__strmode_ & __allocated) {129if (__pfree_)130__pfree_(eback());131else132delete[] eback();133}134setg(buf, buf + ninp, buf + einp);135setp(buf + einp, buf + new_size);136__pbump(nout);137__strmode_ |= __allocated;138}139*pptr() = static_cast<char>(__c);140pbump(1);141return int_type(static_cast<unsigned char>(__c));142}143144strstreambuf::int_type strstreambuf::pbackfail(int_type __c) {145if (eback() == gptr())146return EOF;147if (__c == EOF) {148gbump(-1);149return int_type(0);150}151if (__strmode_ & __constant) {152if (gptr()[-1] == static_cast<char>(__c)) {153gbump(-1);154return __c;155}156return EOF;157}158gbump(-1);159*gptr() = static_cast<char>(__c);160return __c;161}162163strstreambuf::int_type strstreambuf::underflow() {164if (gptr() == egptr()) {165if (egptr() >= pptr())166return EOF;167setg(eback(), gptr(), pptr());168}169return int_type(static_cast<unsigned char>(*gptr()));170}171172strstreambuf::pos_type strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) {173bool pos_in = (__which & ios::in) != 0;174bool pos_out = (__which & ios::out) != 0;175switch (__way) {176case ios::beg:177case ios::end:178if (!pos_in && !pos_out)179return pos_type(off_type(-1));180break;181case ios::cur:182if (pos_in == pos_out)183return pos_type(off_type(-1));184break;185}186187if (pos_in && gptr() == nullptr)188return pos_type(off_type(-1));189if (pos_out && pptr() == nullptr)190return pos_type(off_type(-1));191192off_type newoff;193char* seekhigh = epptr() ? epptr() : egptr();194switch (__way) {195case ios::beg:196newoff = 0;197break;198case ios::cur:199newoff = (pos_in ? gptr() : pptr()) - eback();200break;201case ios::end:202newoff = seekhigh - eback();203break;204default:205__libcpp_unreachable();206}207newoff += __off;208if (newoff < 0 || newoff > seekhigh - eback())209return pos_type(off_type(-1));210211char* newpos = eback() + newoff;212if (pos_in)213setg(eback(), newpos, std::max(newpos, egptr()));214if (pos_out) {215// min(pbase, newpos), newpos, epptr()216__off = epptr() - newpos;217setp(min(pbase(), newpos), epptr());218__pbump((epptr() - pbase()) - __off);219}220return pos_type(newoff);221}222223strstreambuf::pos_type strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) {224bool pos_in = (__which & ios::in) != 0;225bool pos_out = (__which & ios::out) != 0;226if (!pos_in && !pos_out)227return pos_type(off_type(-1));228229if ((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))230return pos_type(off_type(-1));231232off_type newoff = __sp;233char* seekhigh = epptr() ? epptr() : egptr();234if (newoff < 0 || newoff > seekhigh - eback())235return pos_type(off_type(-1));236237char* newpos = eback() + newoff;238if (pos_in)239setg(eback(), newpos, std::max(newpos, egptr()));240if (pos_out) {241// min(pbase, newpos), newpos, epptr()242off_type temp = epptr() - newpos;243setp(min(pbase(), newpos), epptr());244__pbump((epptr() - pbase()) - temp);245}246return pos_type(newoff);247}248249istrstream::~istrstream() {}250251ostrstream::~ostrstream() {}252253strstream::~strstream() {}254255_LIBCPP_END_NAMESPACE_STD256257_LIBCPP_POP_MACROS258259260