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 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;
|
||||
|
||||
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 {
|
||||
|
|
@ -38,18 +20,10 @@ namespace fc {
|
|||
virtual ~ostream(){};
|
||||
|
||||
virtual ostream& write( const char* buf, size_t len ) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
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;
|
||||
virtual void close(){}
|
||||
virtual void flush(){}
|
||||
};
|
||||
|
||||
class iostream : public virtual ostream, public virtual istream {};
|
||||
|
||||
|
||||
|
|
@ -73,26 +47,42 @@ namespace fc {
|
|||
virtual size_t readsome( char* buf, size_t len );
|
||||
virtual istream& read( char* buf, size_t len );
|
||||
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::cin_t& getline( fc::cin_t&, fc::string&, char delim = '\n' );
|
||||
|
||||
|
||||
extern cout_t cout;
|
||||
extern cerr_t cerr;
|
||||
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( int8_t 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>
|
||||
struct lexical_cast<double, R> {
|
||||
|
|
|
|||
134
src/iostream.cpp
134
src/iostream.cpp
|
|
@ -2,28 +2,65 @@
|
|||
#include <fc/sstream.hpp>
|
||||
#include <fc/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <string.h>
|
||||
#include <fc/log.hpp>
|
||||
|
||||
namespace fc {
|
||||
fc::thread& cin_thread() { static fc::thread i("cin"); return i; }
|
||||
|
||||
fc::cin_t& getline( fc::cin_t& i, fc::string& s, char delim ) {
|
||||
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;
|
||||
ostream& operator<<( ostream& o, const char* v ) {
|
||||
o.write( v, strlen(v) );
|
||||
return o;
|
||||
}
|
||||
|
||||
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::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; }
|
||||
|
||||
size_t cin_t::readsome( char* buf, size_t len ) {
|
||||
return std::cin.readsome(buf,len);
|
||||
}
|
||||
istream& cin_t::read( char* buf, size_t len ) {
|
||||
if( !cin_thread().is_current() ) {
|
||||
cin_thread().async( [=](){ this->read(buf,len); } ).wait();
|
||||
return *this;
|
||||
cin_buffer& b = get_cin_buffer();
|
||||
size_t avail = b.write_pos - b.read_pos;
|
||||
avail = (fc::min)(len,avail);
|
||||
size_t u = 0;
|
||||
while( avail && len ) {
|
||||
*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;
|
||||
}
|
||||
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;
|
||||
cerr_t cerr;
|
||||
|
|
|
|||
Loading…
Reference in a new issue