00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_TCL_CHANNELBUF_CC_UTC20050628162421_DEFINED
00035 #define GROOVX_TCL_CHANNELBUF_CC_UTC20050628162421_DEFINED
00036
00037 #include "tcl/channelbuf.h"
00038
00039 #include "rutz/error.h"
00040 #include "rutz/fstring.h"
00041 #include "rutz/sfmt.h"
00042 #include "rutz/shared_ptr.h"
00043
00044 #include "rutz/trace.h"
00045
00046 tcl::channel_buf::channel_buf(Tcl_Interp* interp,
00047 const char* channame, int ) :
00048 opened(false), owned(false), mode(0), m_interp(interp), chan(0)
00049 {
00050 int origmode = 0;
00051 chan = Tcl_GetChannel(interp, channame, &origmode);
00052 if (chan == 0)
00053 {
00054 throw rutz::error(rutz::sfmt("no channel named '%s'",
00055 channame), SRC_POS);
00056 }
00057 opened = true;
00058 }
00059
00060 void tcl::channel_buf::close()
00061 {
00062 if (opened && owned)
00063 {
00064 opened = false;
00065 Tcl_Close(m_interp, chan);
00066 }
00067 }
00068
00069 int tcl::channel_buf::underflow()
00070 {
00071 GVX_TRACE("tcl::channel_buf::underflow");
00072
00073 if (gptr() < egptr())
00074 return *gptr();
00075
00076 int num_putback = 0;
00077 if (s_pback_size > 0)
00078 {
00079
00080
00081
00082 num_putback = gptr() - eback();
00083 if (num_putback > 4)
00084 num_putback = 4;
00085
00086
00087
00088 std::memcpy (m_buffer+(4-num_putback), gptr()-num_putback,
00089 num_putback);
00090 }
00091
00092
00093 const int num = Tcl_Read(chan,
00094 m_buffer+s_pback_size,
00095 s_buf_size-s_pback_size);
00096
00097 if (num <= 0)
00098 return EOF;
00099
00100
00101 setg (m_buffer+(s_pback_size-num_putback),
00102 m_buffer+s_pback_size,
00103 m_buffer+s_pback_size+num);
00104
00105
00106
00107
00108
00109
00110 return static_cast<unsigned char>(*gptr());
00111 }
00112
00113 int tcl::channel_buf::overflow(int c)
00114 {
00115 GVX_TRACE("tcl::channel_buf::overflow");
00116 if (!(mode & std::ios::out) || !opened) return EOF;
00117
00118 if (c != EOF)
00119 {
00120
00121 *pptr() = c;
00122 pbump(1);
00123 }
00124
00125 if (flushoutput() == EOF)
00126 {
00127 return -1;
00128 }
00129
00130 return c;
00131 }
00132
00133 int tcl::channel_buf::sync()
00134 {
00135 if (flushoutput() == EOF)
00136 {
00137 return -1;
00138 }
00139 return 0;
00140 }
00141
00142 int tcl::channel_buf::flushoutput()
00143 {
00144 if (!(mode & std::ios::out) || !opened) return EOF;
00145
00146 int num = pptr()-pbase();
00147 if ( Tcl_Write(chan, pbase(), num) != num )
00148 {
00149 return EOF;
00150 }
00151
00152 pbump(-num);
00153 return num;
00154 }
00155
00156 namespace
00157 {
00158 class tcl_stream : public std::iostream
00159 {
00160 private:
00161 tcl::channel_buf m_buf;
00162 public:
00163 tcl_stream(Tcl_Interp* interp,
00164 const char* channame, std::ios::openmode mode)
00165 :
00166 std::iostream(0),
00167 m_buf(interp, channame, mode)
00168 {
00169 rdbuf(&m_buf);
00170 }
00171 };
00172 }
00173
00174 using rutz::shared_ptr;
00175
00176 shared_ptr<std::ostream> tcl::ochanopen(Tcl_Interp* interp,
00177 const char* channame,
00178 std::ios::openmode flags)
00179 {
00180 return shared_ptr<std::ostream>
00181 (new tcl_stream(interp, channame, std::ios::out|flags));
00182 }
00183
00184 shared_ptr<std::istream> tcl::ichanopen(Tcl_Interp* interp,
00185 const char* channame,
00186 std::ios::openmode flags)
00187 {
00188 return shared_ptr<std::iostream>
00189 (new tcl_stream(interp, channame, std::ios::in|flags));
00190 }
00191
00192
00193 static const char __attribute__((used)) vcid_groovx_tcl_channelbuf_cc_utc20050628162421[] = "$Id: channelbuf.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00194 #endif // !GROOVX_TCL_CHANNELBUF_CC_UTC20050628162421_DEFINED