mirror of
https://git.mirrors.martin98.com/https://github.com/SoftFever/OrcaSlicer.git
synced 2025-04-20 13:10:09 +08:00
416 lines
12 KiB
C++
416 lines
12 KiB
C++
//
|
|
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
#ifndef BOOST_NOWIDE_FILEBUF_HPP
|
|
#define BOOST_NOWIDE_FILEBUF_HPP
|
|
|
|
#include <iosfwd>
|
|
#include <boost/config.hpp>
|
|
#include <boost/nowide/stackstring.hpp>
|
|
#include <fstream>
|
|
#include <streambuf>
|
|
#include <stdio.h>
|
|
|
|
#ifdef BOOST_MSVC
|
|
# pragma warning(push)
|
|
# pragma warning(disable : 4996 4244 4800)
|
|
#endif
|
|
|
|
|
|
namespace boost {
|
|
namespace nowide {
|
|
#if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_FSTREAM_TESTS) && !defined(BOOST_NOWIDE_DOXYGEN)
|
|
using std::basic_filebuf;
|
|
using std::filebuf;
|
|
#else // Windows
|
|
|
|
///
|
|
/// \brief This forward declaration defined the basic_filebuf type.
|
|
///
|
|
/// it is implemented and specialized for CharType = char, it behaves
|
|
/// implements std::filebuf over standard C I/O
|
|
///
|
|
template<typename CharType,typename Traits = std::char_traits<CharType> >
|
|
class basic_filebuf;
|
|
|
|
///
|
|
/// \brief This is implementation of std::filebuf
|
|
///
|
|
/// it is implemented and specialized for CharType = char, it behaves
|
|
/// implements std::filebuf over standard C I/O
|
|
///
|
|
template<>
|
|
class basic_filebuf<char> : public std::basic_streambuf<char> {
|
|
public:
|
|
///
|
|
/// Creates new filebuf
|
|
///
|
|
basic_filebuf() :
|
|
buffer_size_(4),
|
|
buffer_(0),
|
|
file_(0),
|
|
own_(true),
|
|
mode_(std::ios::in | std::ios::out)
|
|
{
|
|
setg(0,0,0);
|
|
setp(0,0);
|
|
}
|
|
|
|
virtual ~basic_filebuf()
|
|
{
|
|
if(file_) {
|
|
::fclose(file_);
|
|
file_ = 0;
|
|
}
|
|
if(own_ && buffer_)
|
|
delete [] buffer_;
|
|
}
|
|
|
|
///
|
|
/// Same as std::filebuf::open but s is UTF-8 string
|
|
///
|
|
basic_filebuf *open(std::string const &s,std::ios_base::openmode mode)
|
|
{
|
|
return open(s.c_str(),mode);
|
|
}
|
|
///
|
|
/// Same as std::filebuf::open but s is UTF-8 string
|
|
///
|
|
basic_filebuf *open(char const *s,std::ios_base::openmode mode)
|
|
{
|
|
if(file_) {
|
|
sync();
|
|
::fclose(file_);
|
|
file_ = 0;
|
|
}
|
|
bool ate = bool(mode & std::ios_base::ate);
|
|
if(ate)
|
|
mode = mode ^ std::ios_base::ate;
|
|
wchar_t const *smode = get_mode(mode);
|
|
if(!smode)
|
|
return 0;
|
|
wstackstring name;
|
|
if(!name.convert(s))
|
|
return 0;
|
|
#ifdef BOOST_NOWIDE_FSTREAM_TESTS
|
|
FILE *f = ::fopen(s,boost::nowide::convert(smode).c_str());
|
|
#else
|
|
FILE *f = ::_wfopen(name.c_str(),smode);
|
|
#endif
|
|
if(!f)
|
|
return 0;
|
|
if(ate && fseek(f,0,SEEK_END)!=0) {
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
file_ = f;
|
|
return this;
|
|
}
|
|
///
|
|
/// Same as std::filebuf::close()
|
|
///
|
|
basic_filebuf *close()
|
|
{
|
|
bool res = sync() == 0;
|
|
if(file_) {
|
|
if(::fclose(file_)!=0)
|
|
res = false;
|
|
file_ = 0;
|
|
}
|
|
return res ? this : 0;
|
|
}
|
|
///
|
|
/// Same as std::filebuf::is_open()
|
|
///
|
|
bool is_open() const
|
|
{
|
|
return file_ != 0;
|
|
}
|
|
|
|
private:
|
|
void make_buffer()
|
|
{
|
|
if(buffer_)
|
|
return;
|
|
if(buffer_size_ > 0) {
|
|
buffer_ = new char [buffer_size_];
|
|
own_ = true;
|
|
}
|
|
}
|
|
protected:
|
|
|
|
virtual std::streambuf *setbuf(char *s,std::streamsize n)
|
|
{
|
|
if(!buffer_ && n>=0) {
|
|
buffer_ = s;
|
|
buffer_size_ = n;
|
|
own_ = false;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
|
|
|
void print_buf(char *b,char *p,char *e)
|
|
{
|
|
std::cerr << "-- Is Null: " << (b==0) << std::endl;;
|
|
if(b==0)
|
|
return;
|
|
if(e != 0)
|
|
std::cerr << "-- Total: " << e - b <<" offset from start " << p - b << std::endl;
|
|
else
|
|
std::cerr << "-- Total: " << p - b << std::endl;
|
|
|
|
std::cerr << "-- [";
|
|
for(char *ptr = b;ptr<p;ptr++)
|
|
std::cerr << *ptr;
|
|
if(e!=0) {
|
|
std::cerr << "|";
|
|
for(char *ptr = p;ptr<e;ptr++)
|
|
std::cerr << *ptr;
|
|
}
|
|
std::cerr << "]" << std::endl;
|
|
|
|
}
|
|
|
|
void print_state()
|
|
{
|
|
std::cerr << "- Output:" << std::endl;
|
|
print_buf(pbase(),pptr(),0);
|
|
std::cerr << "- Input:" << std::endl;
|
|
print_buf(eback(),gptr(),egptr());
|
|
std::cerr << "- fpos: " << (file_ ? ftell(file_) : -1L) << std::endl;
|
|
}
|
|
|
|
struct print_guard
|
|
{
|
|
print_guard(basic_filebuf *p,char const *func)
|
|
{
|
|
self = p;
|
|
f=func;
|
|
std::cerr << "In: " << f << std::endl;
|
|
self->print_state();
|
|
}
|
|
~print_guard()
|
|
{
|
|
std::cerr << "Out: " << f << std::endl;
|
|
self->print_state();
|
|
}
|
|
basic_filebuf *self;
|
|
char const *f;
|
|
};
|
|
#else
|
|
#endif
|
|
|
|
int overflow(int c)
|
|
{
|
|
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
|
print_guard g(this,__FUNCTION__);
|
|
#endif
|
|
if(!file_)
|
|
return EOF;
|
|
|
|
if(fixg() < 0)
|
|
return EOF;
|
|
|
|
size_t n = pptr() - pbase();
|
|
if(n > 0) {
|
|
if(::fwrite(pbase(),1,n,file_) < n)
|
|
return -1;
|
|
fflush(file_);
|
|
}
|
|
|
|
if(buffer_size_ > 0) {
|
|
make_buffer();
|
|
setp(buffer_,buffer_+buffer_size_);
|
|
if(c!=EOF)
|
|
sputc(c);
|
|
}
|
|
else if(c!=EOF) {
|
|
if(::fputc(c,file_)==EOF)
|
|
return EOF;
|
|
fflush(file_);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int sync()
|
|
{
|
|
return overflow(EOF);
|
|
}
|
|
|
|
int underflow()
|
|
{
|
|
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
|
print_guard g(this,__FUNCTION__);
|
|
#endif
|
|
if(!file_)
|
|
return EOF;
|
|
if(fixp() < 0)
|
|
return EOF;
|
|
if(buffer_size_ == 0) {
|
|
int c = ::fgetc(file_);
|
|
if(c==EOF) {
|
|
return EOF;
|
|
}
|
|
last_char_ = c;
|
|
setg(&last_char_,&last_char_,&last_char_ + 1);
|
|
return c;
|
|
}
|
|
make_buffer();
|
|
size_t n = ::fread(buffer_,1,buffer_size_,file_);
|
|
setg(buffer_,buffer_,buffer_+n);
|
|
if(n == 0)
|
|
return EOF;
|
|
return std::char_traits<char>::to_int_type(*gptr());
|
|
}
|
|
|
|
int pbackfail(int)
|
|
{
|
|
return pubseekoff(-1,std::ios::cur);
|
|
}
|
|
|
|
std::streampos seekoff(std::streamoff off,
|
|
std::ios_base::seekdir seekdir,
|
|
std::ios_base::openmode /*m*/)
|
|
{
|
|
#ifdef BOOST_NOWIDE_DEBUG_FILEBUF
|
|
print_guard g(this,__FUNCTION__);
|
|
#endif
|
|
if(!file_)
|
|
return EOF;
|
|
if(fixp() < 0 || fixg() < 0)
|
|
return EOF;
|
|
if(seekdir == std::ios_base::cur) {
|
|
if( ::fseek(file_,off,SEEK_CUR) < 0)
|
|
return EOF;
|
|
}
|
|
else if(seekdir == std::ios_base::beg) {
|
|
if( ::fseek(file_,off,SEEK_SET) < 0)
|
|
return EOF;
|
|
}
|
|
else if(seekdir == std::ios_base::end) {
|
|
if( ::fseek(file_,off,SEEK_END) < 0)
|
|
return EOF;
|
|
}
|
|
else
|
|
return -1;
|
|
return ftell(file_);
|
|
}
|
|
std::streampos seekpos(std::streampos off,std::ios_base::openmode m)
|
|
{
|
|
return seekoff(std::streamoff(off),std::ios_base::beg,m);
|
|
}
|
|
private:
|
|
int fixg()
|
|
{
|
|
if(gptr()!=egptr()) {
|
|
std::streamsize off = gptr() - egptr();
|
|
setg(0,0,0);
|
|
if(fseek(file_,off,SEEK_CUR) != 0)
|
|
return -1;
|
|
}
|
|
setg(0,0,0);
|
|
return 0;
|
|
}
|
|
|
|
int fixp()
|
|
{
|
|
if(pptr()!=0) {
|
|
int r = sync();
|
|
setp(0,0);
|
|
return r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void reset(FILE *f = 0)
|
|
{
|
|
sync();
|
|
if(file_) {
|
|
fclose(file_);
|
|
file_ = 0;
|
|
}
|
|
file_ = f;
|
|
}
|
|
|
|
|
|
static wchar_t const *get_mode(std::ios_base::openmode mode)
|
|
{
|
|
//
|
|
// done according to n2914 table 106 27.9.1.4
|
|
//
|
|
|
|
// note can't use switch case as overload operator can't be used
|
|
// in constant expression
|
|
if(mode == (std::ios_base::out))
|
|
return L"w";
|
|
if(mode == (std::ios_base::out | std::ios_base::app))
|
|
return L"a";
|
|
if(mode == (std::ios_base::app))
|
|
return L"a";
|
|
if(mode == (std::ios_base::out | std::ios_base::trunc))
|
|
return L"w";
|
|
if(mode == (std::ios_base::in))
|
|
return L"r";
|
|
if(mode == (std::ios_base::in | std::ios_base::out))
|
|
return L"r+";
|
|
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
|
return L"w+";
|
|
if(mode == (std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
|
return L"a+";
|
|
if(mode == (std::ios_base::in | std::ios_base::app))
|
|
return L"a+";
|
|
if(mode == (std::ios_base::binary | std::ios_base::out))
|
|
return L"wb";
|
|
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::app))
|
|
return L"ab";
|
|
if(mode == (std::ios_base::binary | std::ios_base::app))
|
|
return L"ab";
|
|
if(mode == (std::ios_base::binary | std::ios_base::out | std::ios_base::trunc))
|
|
return L"wb";
|
|
if(mode == (std::ios_base::binary | std::ios_base::in))
|
|
return L"rb";
|
|
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out))
|
|
return L"r+b";
|
|
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::trunc))
|
|
return L"w+b";
|
|
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::out | std::ios_base::app))
|
|
return L"a+b";
|
|
if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app))
|
|
return L"a+b";
|
|
return 0;
|
|
}
|
|
|
|
size_t buffer_size_;
|
|
char *buffer_;
|
|
FILE *file_;
|
|
bool own_;
|
|
char last_char_;
|
|
std::ios::openmode mode_;
|
|
};
|
|
|
|
///
|
|
/// \brief Convinience typedef
|
|
///
|
|
typedef basic_filebuf<char> filebuf;
|
|
|
|
#endif // windows
|
|
|
|
} // nowide
|
|
} // namespace boost
|
|
|
|
#ifdef BOOST_MSVC
|
|
# pragma warning(pop)
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|