// -*- c++ -*- //------------------------------------------------------------------------------ // Streambuf.cpp //------------------------------------------------------------------------------ // Copyright (c) 1999 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // //------------------------------------------------------------------------------ // Created: 12/02/99 //------------------------------------------------------------------------------ #include "assa/Streambuf.h" #include "assa/MemDump.h" using namespace ASSA; void io_ptrs:: dump () const { #ifdef LOG_PACKET trace_with_mask("io_ptrs::dump",STRMBUF); int len; DL((STRMBUF,"---Ptr------:---Val---\n")); DL((STRMBUF,"m_read_base.: 0x%x\n", (u_long)m_read_base)); DL((STRMBUF,"m_read_ptr..: 0x%x\n", (u_long)m_read_ptr )); DL((STRMBUF,"m_read_end..: 0x%x\n", (u_long)m_read_end )); if (m_read_ptr && (len = m_read_end - m_read_ptr) > 0) { MemDump get_area (m_read_ptr, len); DL((STRMBUF,"\n%s\n", get_area.getMemDump ())); } DL((STRMBUF,"m_write_base: 0x%x\n", (u_long)m_write_base)); DL((STRMBUF,"m_write_ptr.: 0x%x\n", (u_long)m_write_ptr )); DL((STRMBUF,"m_write_end.: 0x%x\n", (u_long)m_write_end )); if (m_write_base && (len = m_write_ptr - m_write_base) > 0) { MemDump put_area (m_write_base, len); DL((STRMBUF,"%s\n", put_area.getMemDump ())); } DL((STRMBUF,"m_buf_base..: 0x%x\n", (u_long)m_buf_base )); DL((STRMBUF,"m_buf_end...: 0x%x\n", (u_long)m_buf_end )); DL((STRMBUF,"------------:---------\n"); #endif } int Streambuf:: snextc () { trace_with_mask("Streambuf::snextc",STRMBUFTRACE); if (m_read_ptr >= m_read_end && underflow () == EOF) { return EOF; } return m_read_ptr++, sgetc (); } void Streambuf:: setg (char* gbeg_, char* gnext_, char* gend_) { trace_with_mask("Streambuf::setg",STRMBUFTRACE); m_read_base = gbeg_; m_read_ptr = gnext_; m_read_end = gend_; } void Streambuf:: setb (char* b_, char* eb_, int del_) { trace_with_mask("Streambuf::setb",STRMBUFTRACE); if (m_buf_base && !(m_flags & USER_BUF)) delete m_buf_base; m_buf_base = b_; m_buf_end = eb_; if (del_) m_flags &= ~ USER_BUF; // clear bit else m_flags |= USER_BUF; // set bit dump (); } Streambuf* Streambuf:: setbuf (char* p_, int len_) { trace_with_mask("Streambuf::setb",STRMBUFTRACE); if (sync () == EOF) // Flush out all pending bytes before return NULL; // resetting buffer. Also, first time around, // calling sync() suppose to set put area // pointers. if (p_ == NULL || len_ == 0) { DL((STRMBUF,"Unbuffered IO set.\n")); unbuffered (1); // We do it from doalloc instead - vlg // setb (m_shortbuf, m_shortbuf+1, 0); } else { DL((STRMBUF,"Buffered IO set.\n")); unbuffered (0); setb (p_, p_ + len_, 0); } setp (0, 0); setg (0, 0, 0); return this; } int Streambuf:: xsgetn (char* data_, int len_) { trace_with_mask("Streambuf::xsgetn",STRMBUFTRACE); /* Get area is empty and nothing is on the socket. */ int count = m_read_end - m_read_ptr; // Bytes in Get area if (count == 0 && underflow () == EOF) { DL((STRMBUFTRACE,"returning %d. count: %d\n", EOF)); return EOF; } count = m_read_end - m_read_ptr; // Adjusted bytes in Get area DL((STRMBUFTRACE,"Adjusted bytes in Get Area: %d\n",count)); if (count > len_) { count = len_; } if (count <= 0) { count = 0; // Peer closed connection } else if (count > 20) { memcpy (data_, m_read_ptr, count); m_read_ptr += count; } else { char* s = data_; char* p = m_read_ptr; int i = count; while (i-- > 0) { *s++ = *p++; } m_read_ptr = p; } DL((STRMBUFTRACE,"Transferred %d bytes to user-space buffer\n", count)); return (count); } int Streambuf:: uflow () { trace_with_mask("Streambuf::uflow",STRMBUFTRACE); if (underflow () == EOF) return EOF; dump (); return *(unsigned char *) m_read_ptr++; } int Streambuf:: xsputn (const char* data_, int len_) { trace_with_mask("Streambuf::xsputn",STRMBUFTRACE); const char* s = data_; int more = len_; if (more <= 0) { return 0; } for (;;) { int count = m_write_end - m_write_ptr; // Space available if (count > 0) { if (count > more) // Enough buffer space count = more; if (count > 20) { memcpy (m_write_ptr, s, count); s += count; m_write_ptr += count; } else if (count <= 0) { count = 0; } else { char* p = m_write_ptr; int i; for (i=count; --i >= 0;) { *p++ = *s++; } m_write_ptr = p; } more -= count; } // if (count>0) if (more == 0 || overflow ((unsigned char) *s++) == EOF) { break; } more--; } // for (;;) return (len_ - more); } int Streambuf::doallocate () { trace_with_mask("Streambuf::doallocate",STRMBUFTRACE); char* buf; buf = new char [1024]; if (buf == NULL) { return EOF; } setb (buf, buf+1024, 1); return 1; }