mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-25 23:00:15 +00:00
57b08b0944
to reflect the new license. These used slightly different spellings that defeated my regular expressions. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351648
362 lines
10 KiB
C++
362 lines
10 KiB
C++
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___STD_STREAM
|
|
#define _LIBCPP___STD_STREAM
|
|
|
|
#include <__config>
|
|
#include <ostream>
|
|
#include <istream>
|
|
#include <__locale>
|
|
#include <cstdio>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_PUSH_MACROS
|
|
#include <__undef_macros>
|
|
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
static const int __limit = 8;
|
|
|
|
// __stdinbuf
|
|
|
|
template <class _CharT>
|
|
class _LIBCPP_HIDDEN __stdinbuf
|
|
: public basic_streambuf<_CharT, char_traits<_CharT> >
|
|
{
|
|
public:
|
|
typedef _CharT char_type;
|
|
typedef char_traits<char_type> traits_type;
|
|
typedef typename traits_type::int_type int_type;
|
|
typedef typename traits_type::pos_type pos_type;
|
|
typedef typename traits_type::off_type off_type;
|
|
typedef typename traits_type::state_type state_type;
|
|
|
|
__stdinbuf(FILE* __fp, state_type* __st);
|
|
|
|
protected:
|
|
virtual int_type underflow();
|
|
virtual int_type uflow();
|
|
virtual int_type pbackfail(int_type __c = traits_type::eof());
|
|
virtual void imbue(const locale& __loc);
|
|
|
|
private:
|
|
|
|
FILE* __file_;
|
|
const codecvt<char_type, char, state_type>* __cv_;
|
|
state_type* __st_;
|
|
int __encoding_;
|
|
int_type __last_consumed_;
|
|
bool __last_consumed_is_next_;
|
|
bool __always_noconv_;
|
|
|
|
__stdinbuf(const __stdinbuf&);
|
|
__stdinbuf& operator=(const __stdinbuf&);
|
|
|
|
int_type __getchar(bool __consume);
|
|
};
|
|
|
|
template <class _CharT>
|
|
__stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st)
|
|
: __file_(__fp),
|
|
__st_(__st),
|
|
__last_consumed_(traits_type::eof()),
|
|
__last_consumed_is_next_(false)
|
|
{
|
|
imbue(this->getloc());
|
|
}
|
|
|
|
template <class _CharT>
|
|
void
|
|
__stdinbuf<_CharT>::imbue(const locale& __loc)
|
|
{
|
|
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc);
|
|
__encoding_ = __cv_->encoding();
|
|
__always_noconv_ = __cv_->always_noconv();
|
|
if (__encoding_ > __limit)
|
|
__throw_runtime_error("unsupported locale for standard input");
|
|
}
|
|
|
|
template <class _CharT>
|
|
typename __stdinbuf<_CharT>::int_type
|
|
__stdinbuf<_CharT>::underflow()
|
|
{
|
|
return __getchar(false);
|
|
}
|
|
|
|
template <class _CharT>
|
|
typename __stdinbuf<_CharT>::int_type
|
|
__stdinbuf<_CharT>::uflow()
|
|
{
|
|
return __getchar(true);
|
|
}
|
|
|
|
template <class _CharT>
|
|
typename __stdinbuf<_CharT>::int_type
|
|
__stdinbuf<_CharT>::__getchar(bool __consume)
|
|
{
|
|
if (__last_consumed_is_next_)
|
|
{
|
|
int_type __result = __last_consumed_;
|
|
if (__consume)
|
|
{
|
|
__last_consumed_ = traits_type::eof();
|
|
__last_consumed_is_next_ = false;
|
|
}
|
|
return __result;
|
|
}
|
|
char __extbuf[__limit];
|
|
int __nread = _VSTD::max(1, __encoding_);
|
|
for (int __i = 0; __i < __nread; ++__i)
|
|
{
|
|
int __c = getc(__file_);
|
|
if (__c == EOF)
|
|
return traits_type::eof();
|
|
__extbuf[__i] = static_cast<char>(__c);
|
|
}
|
|
char_type __1buf;
|
|
if (__always_noconv_)
|
|
__1buf = static_cast<char_type>(__extbuf[0]);
|
|
else
|
|
{
|
|
const char* __enxt;
|
|
char_type* __inxt;
|
|
codecvt_base::result __r;
|
|
do
|
|
{
|
|
state_type __sv_st = *__st_;
|
|
__r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt,
|
|
&__1buf, &__1buf + 1, __inxt);
|
|
switch (__r)
|
|
{
|
|
case _VSTD::codecvt_base::ok:
|
|
break;
|
|
case codecvt_base::partial:
|
|
*__st_ = __sv_st;
|
|
if (__nread == sizeof(__extbuf))
|
|
return traits_type::eof();
|
|
{
|
|
int __c = getc(__file_);
|
|
if (__c == EOF)
|
|
return traits_type::eof();
|
|
__extbuf[__nread] = static_cast<char>(__c);
|
|
}
|
|
++__nread;
|
|
break;
|
|
case codecvt_base::error:
|
|
return traits_type::eof();
|
|
case _VSTD::codecvt_base::noconv:
|
|
__1buf = static_cast<char_type>(__extbuf[0]);
|
|
break;
|
|
}
|
|
} while (__r == _VSTD::codecvt_base::partial);
|
|
}
|
|
if (!__consume)
|
|
{
|
|
for (int __i = __nread; __i > 0;)
|
|
{
|
|
if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
|
|
return traits_type::eof();
|
|
}
|
|
}
|
|
else
|
|
__last_consumed_ = traits_type::to_int_type(__1buf);
|
|
return traits_type::to_int_type(__1buf);
|
|
}
|
|
|
|
template <class _CharT>
|
|
typename __stdinbuf<_CharT>::int_type
|
|
__stdinbuf<_CharT>::pbackfail(int_type __c)
|
|
{
|
|
if (traits_type::eq_int_type(__c, traits_type::eof()))
|
|
{
|
|
if (!__last_consumed_is_next_)
|
|
{
|
|
__c = __last_consumed_;
|
|
__last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_,
|
|
traits_type::eof());
|
|
}
|
|
return __c;
|
|
}
|
|
if (__last_consumed_is_next_)
|
|
{
|
|
char __extbuf[__limit];
|
|
char* __enxt;
|
|
const char_type __ci = traits_type::to_char_type(__last_consumed_);
|
|
const char_type* __inxt;
|
|
switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt,
|
|
__extbuf, __extbuf + sizeof(__extbuf), __enxt))
|
|
{
|
|
case _VSTD::codecvt_base::ok:
|
|
break;
|
|
case _VSTD::codecvt_base::noconv:
|
|
__extbuf[0] = static_cast<char>(__last_consumed_);
|
|
__enxt = __extbuf + 1;
|
|
break;
|
|
case codecvt_base::partial:
|
|
case codecvt_base::error:
|
|
return traits_type::eof();
|
|
}
|
|
while (__enxt > __extbuf)
|
|
if (ungetc(*--__enxt, __file_) == EOF)
|
|
return traits_type::eof();
|
|
}
|
|
__last_consumed_ = __c;
|
|
__last_consumed_is_next_ = true;
|
|
return __c;
|
|
}
|
|
|
|
// __stdoutbuf
|
|
|
|
template <class _CharT>
|
|
class _LIBCPP_HIDDEN __stdoutbuf
|
|
: public basic_streambuf<_CharT, char_traits<_CharT> >
|
|
{
|
|
public:
|
|
typedef _CharT char_type;
|
|
typedef char_traits<char_type> traits_type;
|
|
typedef typename traits_type::int_type int_type;
|
|
typedef typename traits_type::pos_type pos_type;
|
|
typedef typename traits_type::off_type off_type;
|
|
typedef typename traits_type::state_type state_type;
|
|
|
|
__stdoutbuf(FILE* __fp, state_type* __st);
|
|
|
|
protected:
|
|
virtual int_type overflow (int_type __c = traits_type::eof());
|
|
virtual streamsize xsputn(const char_type* __s, streamsize __n);
|
|
virtual int sync();
|
|
virtual void imbue(const locale& __loc);
|
|
|
|
private:
|
|
FILE* __file_;
|
|
const codecvt<char_type, char, state_type>* __cv_;
|
|
state_type* __st_;
|
|
bool __always_noconv_;
|
|
|
|
__stdoutbuf(const __stdoutbuf&);
|
|
__stdoutbuf& operator=(const __stdoutbuf&);
|
|
};
|
|
|
|
template <class _CharT>
|
|
__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st)
|
|
: __file_(__fp),
|
|
__cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())),
|
|
__st_(__st),
|
|
__always_noconv_(__cv_->always_noconv())
|
|
{
|
|
}
|
|
|
|
template <class _CharT>
|
|
typename __stdoutbuf<_CharT>::int_type
|
|
__stdoutbuf<_CharT>::overflow(int_type __c)
|
|
{
|
|
char __extbuf[__limit];
|
|
char_type __1buf;
|
|
if (!traits_type::eq_int_type(__c, traits_type::eof()))
|
|
{
|
|
__1buf = traits_type::to_char_type(__c);
|
|
if (__always_noconv_)
|
|
{
|
|
if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1)
|
|
return traits_type::eof();
|
|
}
|
|
else
|
|
{
|
|
char* __extbe = __extbuf;
|
|
codecvt_base::result __r;
|
|
char_type* pbase = &__1buf;
|
|
char_type* pptr = pbase + 1;
|
|
do
|
|
{
|
|
const char_type* __e;
|
|
__r = __cv_->out(*__st_, pbase, pptr, __e,
|
|
__extbuf,
|
|
__extbuf + sizeof(__extbuf),
|
|
__extbe);
|
|
if (__e == pbase)
|
|
return traits_type::eof();
|
|
if (__r == codecvt_base::noconv)
|
|
{
|
|
if (fwrite(pbase, 1, 1, __file_) != 1)
|
|
return traits_type::eof();
|
|
}
|
|
else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
|
|
{
|
|
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf);
|
|
if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb)
|
|
return traits_type::eof();
|
|
if (__r == codecvt_base::partial)
|
|
{
|
|
pbase = const_cast<char_type*>(__e);
|
|
}
|
|
}
|
|
else
|
|
return traits_type::eof();
|
|
} while (__r == codecvt_base::partial);
|
|
}
|
|
}
|
|
return traits_type::not_eof(__c);
|
|
}
|
|
|
|
template <class _CharT>
|
|
streamsize
|
|
__stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n)
|
|
{
|
|
if (__always_noconv_)
|
|
return fwrite(__s, sizeof(char_type), __n, __file_);
|
|
streamsize __i = 0;
|
|
for (; __i < __n; ++__i, ++__s)
|
|
if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof())
|
|
break;
|
|
return __i;
|
|
}
|
|
|
|
template <class _CharT>
|
|
int
|
|
__stdoutbuf<_CharT>::sync()
|
|
{
|
|
char __extbuf[__limit];
|
|
codecvt_base::result __r;
|
|
do
|
|
{
|
|
char* __extbe;
|
|
__r = __cv_->unshift(*__st_, __extbuf,
|
|
__extbuf + sizeof(__extbuf),
|
|
__extbe);
|
|
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf);
|
|
if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb)
|
|
return -1;
|
|
} while (__r == codecvt_base::partial);
|
|
if (__r == codecvt_base::error)
|
|
return -1;
|
|
if (fflush(__file_))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
template <class _CharT>
|
|
void
|
|
__stdoutbuf<_CharT>::imbue(const locale& __loc)
|
|
{
|
|
sync();
|
|
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc);
|
|
__always_noconv_ = __cv_->always_noconv();
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
#endif // _LIBCPP___STD_STREAM
|