📄 wybyteflow.cpp
字号:
/* Copyright is licensed under GNU LGPL. by I.J.Wang 2003*/#define WYLIB_SOURCE#include "wybyteflow.h"#include "wy_atdestroy.h"#include "wystr.h"#include "wy__cfunc_tty.h"#include <memory> // for new#include <typeinfo>const char WyByteFlow::class_name[]="WyByteFlow";Wy__FtBits WyByteFlow::cftbits(void) WY__NOTHROW__{ static const Wy__FtBits fb( Wy__FtBits(S_IFREG)+ Wy__FtBits(S_IFCHR)+ Wy__FtBits(S_IFSOCK)+ Wy__FtBits(S_IFIFO) ); return(fb);};WyByteFlow::WyByteFlow(const Wy__FtBits cif)try : WySysFile(cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(WyFileHandle fh, const Wy__FtBits cif)try : WySysFile(fh,cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(const WySysFile& sysf, const Wy__FtBits cif)try : WySysFile(sysf,cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(const char* pathname, int f, const Wy__FtBits cif)try : WySysFile(pathname,f,cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(const WyStr& pathname, int f, const Wy__FtBits cif)try : WySysFile(pathname,f,cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(const WyByteFlow& sysf, const Wy__FtBits cif)try : WySysFile(sysf,cif) {}catch(const WySysFile::Reply& e) { WY_THROW( Reply(e) );};WyByteFlow::WyByteFlow(WyByteFlow& sysf, Wy::ByMove_t) WY__TSPC() : WySysFile(sysf,Wy::ByMove){};bool WyByteFlow::wy_is_std_fd(void) const WY__TSPC(){ const Wy__TypeFD fd(this->wy_fd()); return (fd==STDIN_FILENO)||(fd==STDOUT_FILENO)||(fd==STDERR_FILENO);};WyByteFlow* WyByteFlow::_alloc(WyRet& r) consttry { if(WY__EQU_TYPEID(*this,WyByteFlow)==false) { r=Wym_ENOSYS; WY_HERE(r); // _alloc not overridden return(NULL); } WyByteFlow* p=new(std::nothrow) WyByteFlow(); if(p==NULL) { r=Wym_ENOMEM; WY_HERE(r); } else { r=Ok; } return(p);}catch(const Reply& e) { r=e; WY_HERE(r); return(NULL);}catch(const WyRet& e) { WY_THROW( WyRet(e) );};WyRet WyByteFlow::read(void *buf, size_t count, size_t& n_read){ n_read=0; // n_read always reports the bytes read#ifdef __GLIBC__ // man. says unspecified results, guess specific for glib if(count>size_t(std::numeric_limits<ssize_t>::max())) { WY_RETURN(Wym_EFBIG); }#endif WY__CANCEL_POINT; const ssize_t v( ::read(this->wy_fd(),buf,count) ); if(v>=0) { n_read=v; if((size_t)v>count) { WY_THROW( WyRet(Wym_EIO) ); } WY__CANCEL_POINT; return(Ok); } else { WY__CANCEL_POINT; WY_RETURN(errno); } // UNREACHABLE};WyRet WyByteFlow::read(WyStr& buf, size_t count, size_t& n_read){ n_read=0; // n_read always reports the bytes read#ifdef __GLIBC__ // man. says unspecified results, guess specific for glib if(count>size_t(std::numeric_limits<ssize_t>::max())) { WY_RETURN(Wym_EFBIG); }#endif const size_t org_size( buf.size() ); const size_t mr_size( org_size+count ); if(mr_size<org_size) { WY_RETURN(Wym_EFBIG); // value overflow } WyRet r; if((r=buf._reserve(mr_size))!=Ok) { // expand capacity for the read WY_RETURN(r); } WY__CANCEL_POINT; const ssize_t v( ::read(this->wy_fd(),&buf[org_size],count) ); if(v>=0) { n_read=v; buf._setsize(org_size+n_read); if((size_t)v>count) { WY_THROW( WyRet() ); } WY__CANCEL_POINT; return(Ok); } else { buf._setsize(org_size); // in case ::read modified the buffer WY__CANCEL_POINT; WY_RETURN(errno); } // UNREACHABLE};WyRet WyByteFlow::write(const void *buf, size_t count, size_t& n_written){ n_written=0; WY__CANCEL_POINT; ssize_t v=::write(this->wy_fd(),buf,count); if(v>=0) { n_written=v; if(size_t(v)>count) { WY_THROW( WyRet() ); } WY__CANCEL_POINT; return(Ok); } WY__CANCEL_POINT; WY_RETURN(errno);};WyRet WyByteFlow::write(WyCSeg buf, size_t& n_written){ n_written=0; WY__CANCEL_POINT; ssize_t v=::write(this->wy_fd(),buf.begin(),buf.size()); if(v>=0) { n_written=v; if(size_t(v)>buf.size()) { WY_THROW( WyRet() ); } WY__CANCEL_POINT; return(Ok); } WY__CANCEL_POINT; WY_RETURN(errno);};WyRet WyByteFlow::write(const WyStr& buf, size_t& n_written){ n_written=0; WY__CANCEL_POINT; ssize_t v=::write(this->wy_fd(),buf.data(),buf.size()); if(v>=0) { n_written=v; if(size_t(v)>buf.size()) { WY_THROW( WyRet() ); } WY__CANCEL_POINT; return(Ok); } WY__CANCEL_POINT; WY_RETURN(errno);};WyRet WyByteFlow::_fsync(void){ if(wyc_fsync(this->wy_fd())==-1) { WY_RETURN(errno); } return(Ok);};WyRet WyByteFlow::_fdatasync(void){ if(wyc_fdatasync(this->wy_fd())==-1) { WY_RETURN(errno); } return(Ok);};WyRet WyByteFlow::_tcdrain(void){ if(wyc_tcdrain(this->wy_fd())!=0) { WY_RETURN(errno); } return(Ok);};bool WyByteFlow::_isatty(void) const{ return(wyc_isatty(this->wy_fd())==1);};//------------------------------------------------------------------------//// [Internal] class for standard err/in/out file descriptor//// Note: object is created non-default.// reset() throws WyRet(Wym_EBADF), others reset(..) return Wym_EBADF// if argument indicate default//class Wy__Std : public WyByteFlow { Wy__TypeFD _StdFd; public: static const char class_name[]; // [Internal] Construct object to handle the fd (exact) // // Note: Object contains the exact _fd as argument fd // fd is supposed (0|1|2) // // [Throw] Reply // Wym_EBADF // Wym_ENOMEM // Wy__Std(Wy__TypeFD fd); ~Wy__Std(); // [Override] WyRet reset(void); WyRet reset(const WySysFile&); WyRet reset(WyFileHandle); WyRet reset(const char* pathname,int flags); WyRet reset(const WyStr& pathname,int flags) { return this->reset(pathname.c_str(),flags); }; WyRet _swap(WySysFile&) WY__TSPC(); // Note: Wy__Std::_alloc() allocates WyByteFlow() (not Wy__Std) // // [Derived] WyByteFlow* _alloc(WyRet&) const;};const char Wy__Std::class_name[]="Wy__Std";Wy__Std::Wy__Std(Wy__TypeFD fd)try : WyByteFlow(),_StdFd(fd) { struct ::stat stt; if(wyc_fstat(fd,&stt)==-1) { WY_THROW( Reply(WyReply(errno)) ); } const mode_t fd_ftype=stt.st_mode&S_IFMT; if(_cif.is_joint(fd_ftype)==false) { WY_THROW( Reply(Wym_EBADF) ); } WyByteFlow::_overwrite(_StdFd,fd_ftype);}catch(const WyByteFlow& e) { throw;}catch(const WyRet& e) { WY_THROW( WyRet(e) );};Wy__Std::~Wy__Std(){ // prevent closing the constructor given fd from destructor // leave it as the constructed state // WyByteFlow::_overwrite(WySysFile::DefaultFd,WySysFile::DefaultFType);};WyRet Wy__Std::reset(void){ // This is the instance that reset() throw postcondition rult // applies to Reply, not WyRet. // Non-Reply postcondition ok (intact). // WY_THROW( WyRet(Wym_EBADF) );};// Note: If _StdFd(0|1|2) had been allocated, that device may be closed first// see dup2(2)//WyRet Wy__Std::reset(WyFileHandle fh){ if(this->is_default()) { WY_THROW( WyRet(Wym_EBADF) ); // object should not be default } if(fh.is_default()) { WY_RETURN(Wym_EBADF); } if(fh.fd()==this->wy_fd()) { // self reset should be no effect for Wy__Std return(Ok); } struct ::stat stt; if(wyc_fstat(fh.fd(),&stt)==-1) { WY_RETURN(errno); } const mode_t fh_type=stt.st_mode&S_IFMT; if(_cif.is_joint(fh_type)==false) { WY_RETURN(Wym_EBADF); } // dup tfd to _StdFd const Wy__TypeFD tfd=wyc_dup2(fh.fd(),_StdFd); if(tfd==-1) { WY_RETURN(errno); } if(tfd!=_StdFd) { WY_TERMINATE(""); // not what dup2 supposed to do } this->_overwrite(_StdFd,fh_type); return(Ok);};// Note: If _StdFd(0|1|2) had been allocated, that device may be closed first// see dup2(2)// Note: object type for standard fd is limited to WyByteFlow family//WyRet Wy__Std::reset(const WySysFile& sysf){ if(this->is_default()) { WY_THROW( WyRet(Wym_EBADF) ); // object should not be default } if(sysf.is_default()) { WY_RETURN(Wym_EBADF); } if(sysf.wy_fd()==this->wy_fd()) { // self reset should be no effect for Wy__Std return(Ok); } if(_cif.is_joint(sysf.ftype())==false) { WY_RETURN(Wym_EBADF); } // dup tfd to _StdFd const Wy__TypeFD tfd=wyc_dup2(sysf.wy_fd(),_StdFd); if(tfd==-1) { WY_RETURN(errno); } if(tfd!=_StdFd) { WY_TERMINATE(""); // not what dup2 supposed to do } this->_overwrite(_StdFd,sysf.ftype()); return(Ok);};WyRet Wy__Std::reset(const char*pathname, int flags){ if(this->is_default()) { WY_THROW( WyRet(Wym_EBADF) ); // object should not be default } // note: report of closing provious fd is ignored // if(flags&O_CREAT) { WY_RETURN(Wym_EINVAL); } Wy__TypeFD tfd=wyc_open(pathname,flags); if(tfd==-1) { WY_RETURN(errno); } Wy_AtDestroy<int,const Wy__TypeFD&> rrid(WySysFile::wy_close,tfd); WyFileStat stt; if(wyc_fstat(tfd,stt.wy_stat_ptr())==-1) { WY_RETURN(errno); } const mode_t p_ftype=stt.sf_mode()&S_IFMT; if(_cif.is_joint(p_ftype)==false) { WY_RETURN(Wym_EBADF); } // dup tfd to _StdFd const Wy__TypeFD tfd2=wyc_dup2(tfd,_StdFd); if(tfd2==-1) { WY_RETURN(errno); } if(tfd2!=_StdFd) { WY_TERMINATE(""); // not what dup2 supposed to do } this->_overwrite(_StdFd,p_ftype); return(Ok);};WyRet Wy__Std::_swap(WySysFile&) WY__TSPC(){ // no swap for now (Wy__Std is not public) // WY_RETURN( Wym_EBADTYPE );};WyByteFlow* Wy__Std::_alloc(WyRet& r) consttry { r=Wym_ENOSYS; WY_HERE(r); // say here (Wy__Std is not public) return(NULL);}catch(const Reply& e) { r=e; WY_HERE(r); return(NULL);}catch(const WyRet& e) { WY_THROW( WyRet(e) );};static Wy__Std wy__stderr(STDERR_FILENO);static Wy__Std wy__stdin(STDIN_FILENO);static Wy__Std wy__stdout(STDOUT_FILENO);namespace Wy { WyByteFlow& cerr(wy__stderr); WyByteFlow& cin(wy__stdin); WyByteFlow& cout(wy__stdout);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -