Fix fcgi_streambuf::underflow() such that when there is no buffer
[catagits/fcgi2.git] / libfcgi / fcgio.cpp
index 4deb4e5..5a54c11 100644 (file)
@@ -1,5 +1,5 @@
 //
-// $Id: fcgio.cpp,v 1.6 2001/11/20 02:29:39 robs Exp $
+// $Id: fcgio.cpp,v 1.14 2003/06/22 00:51:27 robs Exp $
 //
 // Allows you communicate with FastCGI streams using C++ iostreams
 //
 // implied; without even the implied warranty of MERCHANTABILITY or
 // FITNESS FOR A PARTICULAR PURPOSE.
 
-#define DLLAPI  __declspec(dllexport)\r
+#ifdef _WIN32
+#define DLLAPI  __declspec(dllexport)
+#endif
+
+#include <limits.h>
 #include "fcgio.h"
 
-fcgi_streambuf::fcgi_streambuf(FCGX_Stream * strm) 
+using std::streambuf;
+using std::istream;
+using std::ostream;
+using std::streamsize;
+
+fcgi_streambuf::fcgi_streambuf(FCGX_Stream * fs, char * b, int bs)
+{
+    init(fs, b, bs);
+}
+    
+fcgi_streambuf::fcgi_streambuf(char_type * b, streamsize bs)
+{
+    init(0, b, bs);
+}
+    
+fcgi_streambuf::fcgi_streambuf(FCGX_Stream * fs) 
 { 
-    this->fcgx = strm;\r
-    this->buf = NULL;
-    this->bufsize = 0;\r
-    setbuf(NULL, 0);
+    init(fs, 0, 0);
 }
 
 fcgi_streambuf::~fcgi_streambuf(void)
 {
     overflow(EOF);
     // FCGX_Finish()/FCGX_Accept() will flush and close
-} 
+}
+
+void fcgi_streambuf::init(FCGX_Stream * fs, char_type * b, streamsize bs)
+{
+    this->fcgx = fs;
+    this->buf = 0;
+    this->bufsize = 0;
+    setbuf(b, bs);    
+}
 
 int fcgi_streambuf::overflow(int c)
 {
@@ -56,14 +80,29 @@ int fcgi_streambuf::overflow(int c)
     return 0;
 }
 
-// default base class behaviour seems to be inconsistent\r
+// default base class behaviour seems to be inconsistent
 int fcgi_streambuf::sync()
 {
-    if (overflow(EOF)) return EOF;\r
+    if (overflow(EOF)) return EOF;
     if (FCGX_FFlush(this->fcgx)) return EOF;
     return 0;
 }
 
+// uflow() removes the char, underflow() doesn't
+int fcgi_streambuf::uflow() 
+{
+    if (this->bufsize)
+    {
+        int c = underflow();        
+        gbump(1);
+        return c;
+    }
+    else
+    {
+        return FCGX_GetChar(this->fcgx);
+    }
+}
+                               
 int fcgi_streambuf::underflow()
 {
     if (this->bufsize)
@@ -80,82 +119,83 @@ int fcgi_streambuf::underflow()
     }
     else
     {
-        return FCGX_GetChar(this->fcgx);
+        return FCGX_UnGetChar(FCGX_GetChar(this->fcgx), this->fcgx);
     } 
 }
 
-void fcgi_streambuf::reset(void)\r
-{\r
-    // it should be ok to set up both the get and put areas\r
-    char * end = this->buf + this->bufsize;\r
-    this->setg(this->buf, this->buf, end);\r
-    this->setb(this->buf, end);\r
-}\r
-\r
-streambuf * fcgi_streambuf::setbuf(char * buf, int len)
+void fcgi_streambuf::reset(void)
 {
-    // XXX support moving data from an old buffer\r
-    if (this->bufsize) return NULL;\r
-\r
-    this->buf = buf;\r
-    this->bufsize = len;\r
-\r
-    // the base setbuf() *has* to be called\r
-    streambuf::setbuf(buf, len);
+    // it should be ok to set up both the get and put areas
+    setg(this->buf, this->buf, this->buf);
+    setp(this->buf, this->buf + this->bufsize);
+}
 
-    reset();\r
+std::streambuf * fcgi_streambuf::setbuf(char_type * b, streamsize bs)
+{
+    // XXX support moving data from an old buffer
+    if (this->bufsize) return 0;
+
+    this->buf = b;
+    this->bufsize = bs;
+
+    // the base setbuf() *has* to be called
+    streambuf::setbuf(b, bs);
+
+    reset();
 
     return this;
-}\r
-\r
-int fcgi_streambuf::attach(FCGX_Stream * strm)\r
-{ \r
-    this->fcgx = strm;\r
-\r
-    if (this->bufsize)\r
-    {\r
-        reset();\r
-    }\r
-\r
-    return 0;\r
-}
-
-int fcgi_streambuf::xsgetn(char * s, int n) 
-{\r
-    return (this->bufsize) \r
-        ? streambuf::xsgetn(s, n) \r
-        : FCGX_GetStr(s, n, this->fcgx);
-}\r
-   \r
-int fcgi_streambuf::xsputn(const char * s, int n) 
-{\r
-    return (this->bufsize) \r
-        ? streambuf::xsputn(s, n) \r
-        : FCGX_PutStr(s, n, this->fcgx);\r
-}\r
-\r
-// deprecated\r
-fcgi_istream::fcgi_istream(FCGX_Stream * strm) :\r
+}
+
+int fcgi_streambuf::attach(FCGX_Stream * fs)
+{ 
+    this->fcgx = fs;
+
+    if (this->bufsize)
+    {
+        reset();
+    }
+
+    return 0;
+}
+
+streamsize fcgi_streambuf::xsgetn(char_type * s, streamsize n) 
+{
+    if (n > INT_MAX) return 0;
+    return (this->bufsize) 
+        ? streambuf::xsgetn(s, n) 
+        : (streamsize) FCGX_GetStr((char *) s, (int) n, this->fcgx);
+}
+   
+streamsize fcgi_streambuf::xsputn(const char_type * s, streamsize n) 
+{
+    if (n > INT_MAX) return 0;
+    return (this->bufsize) 
+        ? streambuf::xsputn(s, n) 
+        : (streamsize) FCGX_PutStr((char *) s, (int) n, this->fcgx);
+}
+
+// deprecated
+fcgi_istream::fcgi_istream(FCGX_Stream * fs) :
     istream(&fcgi_strmbuf)
 {
-    fcgi_strmbuf.attach(strm);
+    fcgi_strmbuf.attach(fs);
 }
 
-// deprecated\r
-void fcgi_istream::attach(FCGX_Stream * strm)
+// deprecated
+void fcgi_istream::attach(FCGX_Stream * fs)
 {
-    fcgi_strmbuf.attach(strm);
+    fcgi_strmbuf.attach(fs);
 }
 
-// deprecated\r
-fcgi_ostream::fcgi_ostream(FCGX_Stream * strm) :
-    ostream(&fcgi_strmbuf)\r
+// deprecated
+fcgi_ostream::fcgi_ostream(FCGX_Stream * fs) :
+    ostream(&fcgi_strmbuf)
 {
-    fcgi_strmbuf.attach(strm);
+    fcgi_strmbuf.attach(fs);
 }
 
-// deprecated\r
-void fcgi_ostream::attach(FCGX_Stream * strm)
+// deprecated
+void fcgi_ostream::attach(FCGX_Stream * fs)
 {
-    fcgi_strmbuf.attach(strm);
+    fcgi_strmbuf.attach(fs);
 }