updated io stream, simplified interface, faster cin
This commit is contained in:
parent
4aad422411
commit
c123fb39c2
4 changed files with 239 additions and 84 deletions
|
|
@ -12,25 +12,7 @@ namespace fc {
|
||||||
virtual size_t readsome( char* buf, size_t len ) = 0;
|
virtual size_t readsome( char* buf, size_t len ) = 0;
|
||||||
virtual istream& read( char* buf, size_t len ) = 0;
|
virtual istream& read( char* buf, size_t len ) = 0;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
friend istream& operator>>( istream& i, T& v ){ return i.read(v); }
|
|
||||||
|
|
||||||
virtual bool eof()const = 0;
|
virtual bool eof()const = 0;
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual istream& read( int64_t& ) = 0;
|
|
||||||
virtual istream& read( uint64_t& ) = 0;
|
|
||||||
virtual istream& read( int32_t& ) = 0;
|
|
||||||
virtual istream& read( uint32_t& ) = 0;
|
|
||||||
virtual istream& read( int16_t& ) = 0;
|
|
||||||
virtual istream& read( uint16_t& ) = 0;
|
|
||||||
virtual istream& read( int8_t& ) = 0;
|
|
||||||
virtual istream& read( uint8_t& ) = 0;
|
|
||||||
virtual istream& read( float& ) = 0;
|
|
||||||
virtual istream& read( double& ) = 0;
|
|
||||||
virtual istream& read( bool& ) = 0;
|
|
||||||
virtual istream& read( char& ) = 0;
|
|
||||||
virtual istream& read( fc::string& ) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ostream {
|
class ostream {
|
||||||
|
|
@ -38,18 +20,10 @@ namespace fc {
|
||||||
virtual ~ostream(){};
|
virtual ~ostream(){};
|
||||||
|
|
||||||
virtual ostream& write( const char* buf, size_t len ) = 0;
|
virtual ostream& write( const char* buf, size_t len ) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close(){}
|
||||||
virtual void flush() = 0;
|
virtual void flush(){}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
friend ostream& operator<<( ostream& o, const T& v ) { return o.write(fc::lexical_cast<fc::string>(v)); }
|
|
||||||
friend ostream& operator<<( ostream& o, char* v ) { return o.write(v); }
|
|
||||||
friend ostream& operator<<( ostream& o, const char* v ) { return o.write(v); }
|
|
||||||
friend ostream& operator<<( ostream& o, const fc::string& v ){ return o.write(v); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ostream& write( const fc::string& ) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class iostream : public virtual ostream, public virtual istream {};
|
class iostream : public virtual ostream, public virtual istream {};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,26 +47,42 @@ namespace fc {
|
||||||
virtual size_t readsome( char* buf, size_t len );
|
virtual size_t readsome( char* buf, size_t len );
|
||||||
virtual istream& read( char* buf, size_t len );
|
virtual istream& read( char* buf, size_t len );
|
||||||
virtual bool eof()const;
|
virtual bool eof()const;
|
||||||
|
|
||||||
virtual istream& read( int64_t& );
|
|
||||||
virtual istream& read( uint64_t& );
|
|
||||||
virtual istream& read( int32_t& );
|
|
||||||
virtual istream& read( uint32_t& );
|
|
||||||
virtual istream& read( int16_t& );
|
|
||||||
virtual istream& read( uint16_t& );
|
|
||||||
virtual istream& read( int8_t& );
|
|
||||||
virtual istream& read( uint8_t& );
|
|
||||||
virtual istream& read( float& );
|
|
||||||
virtual istream& read( double& );
|
|
||||||
virtual istream& read( bool& );
|
|
||||||
virtual istream& read( char& );
|
|
||||||
virtual istream& read( fc::string& );
|
|
||||||
};
|
};
|
||||||
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
|
fc::istream& getline( fc::istream&, fc::string&, char delim = '\n' );
|
||||||
fc::cin_t& getline( fc::cin_t&, fc::string&, char delim = '\n' );
|
|
||||||
|
|
||||||
|
|
||||||
extern cout_t cout;
|
extern cout_t cout;
|
||||||
extern cerr_t cerr;
|
extern cerr_t cerr;
|
||||||
extern cin_t cin;
|
extern cin_t cin;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ostream& operator<<( ostream& o, const T& v ) {
|
||||||
|
auto str = fc::lexical_cast<fc::string>(v);
|
||||||
|
o.write( str.c_str(), str.size() );
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
ostream& operator<<( ostream& o, const char* v );
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ostream& operator<<( ostream& o, const fc::string& str ) {
|
||||||
|
o.write( str.c_str(), str.size() );
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
istream& operator>>( istream& o, T& v ) {
|
||||||
|
fc::string str;
|
||||||
|
getline( o, str, ' ' );
|
||||||
|
v = fc::lexical_cast<T>(str);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::cin_t& getline( fc::cin_t&, fc::string&, char delim = '\n' );
|
||||||
|
template<typename T>
|
||||||
|
cin_t& operator>>( cin_t& o, T& v ) {
|
||||||
|
fc::string str;
|
||||||
|
getline( o, str, ' ' );
|
||||||
|
v = fc::lexical_cast<T>(str);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
109
include/fc/iostream_wrapper.hpp
Normal file
109
include/fc/iostream_wrapper.hpp
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fc/iostream.hpp>
|
||||||
|
#include <fc/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace fc {
|
||||||
|
/**
|
||||||
|
* Used to wrap references to other streams
|
||||||
|
*/
|
||||||
|
class ostream_wrapper : public ostream {
|
||||||
|
public:
|
||||||
|
template<typename Stream>
|
||||||
|
ostream_wrapper( Stream& s )
|
||||||
|
:my( new impl<Stream>(s) ){}
|
||||||
|
|
||||||
|
virtual ~ostream_wrapper(){};
|
||||||
|
|
||||||
|
virtual ostream& write( const char* buf, size_t len ) {
|
||||||
|
my->write(buf,len);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
virtual void close() {
|
||||||
|
my->close();
|
||||||
|
}
|
||||||
|
virtual void flush() {
|
||||||
|
my->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ostream& write( const fc::string& s ) {
|
||||||
|
return write( s.c_str(), s.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct impl_base : public fc::retainable {
|
||||||
|
virtual void write( const char* buf, size_t len ) = 0;
|
||||||
|
virtual void close() = 0;
|
||||||
|
virtual void flush() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct impl : public impl_base {
|
||||||
|
impl(T& i):st(i){}
|
||||||
|
|
||||||
|
virtual void write( const char* buf, size_t len ) {
|
||||||
|
st.write(buf,len);
|
||||||
|
}
|
||||||
|
virtual void close() { st.close(); }
|
||||||
|
virtual void flush() { st.flush(); }
|
||||||
|
T& st;
|
||||||
|
};
|
||||||
|
|
||||||
|
fc::shared_ptr<impl_base> my;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Used to wrap references to other streams
|
||||||
|
*/
|
||||||
|
class istream_wrapper : public istream {
|
||||||
|
public:
|
||||||
|
template<typename Stream>
|
||||||
|
istream_wrapper( Stream& s )
|
||||||
|
:my( new impl<Stream>(s) ){}
|
||||||
|
|
||||||
|
virtual ~istream_wrapper(){};
|
||||||
|
|
||||||
|
virtual size_t readsome( char* buf, size_t len ) { return my->readsome(buf,len); }
|
||||||
|
virtual istream& read( char* buf, size_t len ) {
|
||||||
|
my->read(buf,len);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
virtual void close() { }
|
||||||
|
virtual bool eof()const{ return my->eof(); }
|
||||||
|
|
||||||
|
virtual istream& read( int64_t& ) { return *this; }
|
||||||
|
virtual istream& read( uint64_t& ) { return *this; }
|
||||||
|
virtual istream& read( int32_t& ) { return *this; }
|
||||||
|
virtual istream& read( uint32_t& ) { return *this; }
|
||||||
|
virtual istream& read( int16_t& ) { return *this; }
|
||||||
|
virtual istream& read( uint16_t& ) { return *this; }
|
||||||
|
virtual istream& read( int8_t& ) { return *this; }
|
||||||
|
virtual istream& read( uint8_t& ) { return *this; }
|
||||||
|
virtual istream& read( float& ) { return *this; }
|
||||||
|
virtual istream& read( double& ) { return *this; }
|
||||||
|
virtual istream& read( bool& ) { return *this; }
|
||||||
|
virtual istream& read( char& ) { return *this; }
|
||||||
|
virtual istream& read( fc::string& ) { return *this; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct impl_base : public fc::retainable {
|
||||||
|
virtual void read( char* buf, size_t len ) = 0;
|
||||||
|
virtual size_t readsome( char* buf, size_t len ) = 0;
|
||||||
|
virtual bool eof()const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct impl : public impl_base {
|
||||||
|
impl(T& i):st(i){}
|
||||||
|
|
||||||
|
virtual size_t readsome( char* buf, size_t len ) { return st.readsome(buf,len); }
|
||||||
|
virtual void read( char* buf, size_t len ) {
|
||||||
|
st.read(buf,len);
|
||||||
|
}
|
||||||
|
virtual bool eof()const { return st.eof(); }
|
||||||
|
T& st;
|
||||||
|
};
|
||||||
|
|
||||||
|
fc::shared_ptr<impl_base> my;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fc
|
||||||
|
|
||||||
|
|
@ -28,6 +28,8 @@ namespace fc {
|
||||||
fc::string to_string( int16_t d );
|
fc::string to_string( int16_t d );
|
||||||
fc::string to_string( int8_t d );
|
fc::string to_string( int8_t d );
|
||||||
fc::string to_string( char d );
|
fc::string to_string( char d );
|
||||||
|
fc::string to_string( const char* d );
|
||||||
|
inline fc::string to_string( fc::string s ) { return s; }
|
||||||
|
|
||||||
template<typename R>
|
template<typename R>
|
||||||
struct lexical_cast<double, R> {
|
struct lexical_cast<double, R> {
|
||||||
|
|
|
||||||
134
src/iostream.cpp
134
src/iostream.cpp
|
|
@ -2,28 +2,65 @@
|
||||||
#include <fc/sstream.hpp>
|
#include <fc/sstream.hpp>
|
||||||
#include <fc/thread.hpp>
|
#include <fc/thread.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string.h>
|
||||||
#include <fc/log.hpp>
|
#include <fc/log.hpp>
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
|
ostream& operator<<( ostream& o, const char* v ) {
|
||||||
|
o.write( v, strlen(v) );
|
||||||
fc::cin_t& getline( fc::cin_t& i, fc::string& s, char delim ) {
|
return o;
|
||||||
if( !cin_thread().is_current() ) {
|
|
||||||
cin_thread().async([&](){ getline(i,s,delim); } ).wait();
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
fc::stringstream ss;
|
|
||||||
char c;
|
|
||||||
i.read( &c, 1 );
|
|
||||||
while( !i.eof() ) {
|
|
||||||
if( c == delim ) { s = ss.str(); return i; }
|
|
||||||
ss.write(&c,1);
|
|
||||||
i.read( &c, 1 );
|
|
||||||
}
|
|
||||||
s = ss.str();
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cin_buffer {
|
||||||
|
cin_buffer():eof(false),write_pos(0),read_pos(0),cinthread("cin"){
|
||||||
|
cinthread.async( [=](){read();} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void read() {
|
||||||
|
char c;
|
||||||
|
std::cin.read(&c,1);
|
||||||
|
while( !std::cin.eof() ) {
|
||||||
|
while( write_pos - read_pos > 0xfffff ) {
|
||||||
|
fc::promise<void>::ptr wr( new fc::promise<void>() );
|
||||||
|
write_ready = wr;
|
||||||
|
if( write_pos - read_pos <= 0xfffff ) {
|
||||||
|
wr->wait();
|
||||||
|
}
|
||||||
|
write_ready.reset();
|
||||||
|
}
|
||||||
|
buf[write_pos&0xfffff] = c;
|
||||||
|
++write_pos;
|
||||||
|
|
||||||
|
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
|
||||||
|
if( tmp && !tmp->ready() ) {
|
||||||
|
tmp->set_value();
|
||||||
|
}
|
||||||
|
std::cin.read(&c,1);
|
||||||
|
}
|
||||||
|
eof = true;
|
||||||
|
auto tmp = read_ready; // copy read_ready because it is accessed from multiple threads
|
||||||
|
if( tmp && !tmp->ready() ) {
|
||||||
|
tmp->set_value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fc::promise<void>::ptr read_ready;
|
||||||
|
fc::promise<void>::ptr write_ready;
|
||||||
|
|
||||||
|
volatile bool eof;
|
||||||
|
|
||||||
|
volatile uint64_t write_pos;
|
||||||
|
char buf[0xfffff+1]; // 1 mb buffer
|
||||||
|
volatile uint64_t read_pos;
|
||||||
|
fc::thread cinthread;
|
||||||
|
};
|
||||||
|
|
||||||
|
cin_buffer& get_cin_buffer() {
|
||||||
|
static cin_buffer* b = new cin_buffer();
|
||||||
|
return *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
|
||||||
|
|
||||||
fc::istream& getline( fc::istream& i, fc::string& s, char delim ) {
|
fc::istream& getline( fc::istream& i, fc::string& s, char delim ) {
|
||||||
fc::stringstream ss;
|
fc::stringstream ss;
|
||||||
|
|
@ -52,32 +89,49 @@ namespace fc {
|
||||||
ostream& cerr_t::write( const fc::string& s ) { std::cerr<< *reinterpret_cast<const std::string*>(&s); return *this; }
|
ostream& cerr_t::write( const fc::string& s ) { std::cerr<< *reinterpret_cast<const std::string*>(&s); return *this; }
|
||||||
|
|
||||||
size_t cin_t::readsome( char* buf, size_t len ) {
|
size_t cin_t::readsome( char* buf, size_t len ) {
|
||||||
return std::cin.readsome(buf,len);
|
cin_buffer& b = get_cin_buffer();
|
||||||
}
|
size_t avail = b.write_pos - b.read_pos;
|
||||||
istream& cin_t::read( char* buf, size_t len ) {
|
avail = (fc::min)(len,avail);
|
||||||
if( !cin_thread().is_current() ) {
|
size_t u = 0;
|
||||||
cin_thread().async( [=](){ this->read(buf,len); } ).wait();
|
while( avail && len ) {
|
||||||
return *this;
|
*buf = b.buf[b.read_pos&0xfffff];
|
||||||
|
++b.read_pos;
|
||||||
|
++buf;
|
||||||
|
--avail;
|
||||||
|
--len;
|
||||||
|
++u;
|
||||||
}
|
}
|
||||||
std::cin.read(buf,len);
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
istream& cin_t::read( char* buf, size_t len ) {
|
||||||
|
cin_buffer& b = get_cin_buffer();
|
||||||
|
do {
|
||||||
|
while( !b.eof && (b.write_pos - b.read_pos)==0 ){
|
||||||
|
// wait for more...
|
||||||
|
fc::promise<void>::ptr rr( new fc::promise<void>() );
|
||||||
|
b.read_ready = rr;
|
||||||
|
if( b.write_pos - b.read_pos == 0 ) {
|
||||||
|
rr->wait();
|
||||||
|
}
|
||||||
|
b.read_ready.reset();
|
||||||
|
}
|
||||||
|
if( b.eof ) return *this;
|
||||||
|
size_t r = readsome( buf, len );
|
||||||
|
buf += r;
|
||||||
|
len -= r;
|
||||||
|
|
||||||
|
auto tmp = b.write_ready; // copy write_writey because it is accessed from multiple thwrites
|
||||||
|
if( tmp && !tmp->ready() ) {
|
||||||
|
tmp->set_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} while( len > 0 && !b.eof );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
bool cin_t::eof()const { return std::cin.eof(); }
|
|
||||||
|
|
||||||
istream& cin_t::read( int64_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( uint64_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( int32_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( uint32_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( int16_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( uint16_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( int8_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( uint8_t& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( float& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( double& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( bool& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( char& v) { slog(""); std::cin >> v; return *this; }
|
|
||||||
istream& cin_t::read( fc::string& v) { slog(""); std::cin >> *reinterpret_cast<std::string*>(&v); return *this; }
|
|
||||||
|
|
||||||
|
bool cin_t::eof()const { return get_cin_buffer().eof; }
|
||||||
|
|
||||||
cout_t cout;
|
cout_t cout;
|
||||||
cerr_t cerr;
|
cerr_t cerr;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue