f43ac6c401fc2d03e755eda80a37e07cee9bbcca
[catagits/fcgi2.git] / libfcgi / fcgio.cpp
1 // FILE NAME: fcgio.cpp
2 //
3 // $Id: fcgio.cpp,v 1.1 1999/08/15 03:37:59 roberts Exp $
4 //
5 // REWRITTEN BY: Michael Richards  06/20/1999
6 //          -added cin support
7 //          -added ability to replace cin/cout so existing code only
8 //           needs to include the header file and use the normal cin/cout
9 //          -added buffered read support which is required by getline
10 //
11 // ORIGINAL AUTHOR: George Feinberg
12 //
13 // NOTES: encapsulates FCGI function in an ostream and replaces cin,
14 //        cout and cerr
15 //
16 // This work is based on routines written by George Feinberg. They   
17 // have been mostly re-written and extensively changed by
18 // Michael Richards.
19 //    
20 // Copyright (c) 1999 by Apollo Software. All rights reserved.
21 //
22 // You are free to use this software without charge or royalty
23 // as long as this notice is not removed or altered, and recognition
24 // is given to the author(s)   
25 //   
26
27 #include <fcgiapp.h>
28 #include "fcgio.h"
29
30
31 // the definition that replaces cout and cin
32 #ifndef USE_CIN_COUT_CERR
33   fcgio_ostream *FCGIX_cout;
34   fcgio_ostream *FCGIX_cerr;
35   fcgio_istream *FCGIX_cin;
36 #endif
37    
38 /*---------------------------------------------------------------------*/
39    
40
41 // gets a number of characters at once for a more efficient implementation
42 int fcgio_buf::xsgetn(char *s, int n) {
43   return FCGX_GetStr(s, n, fcgi_str);
44 }
45    
46
47 // writes a gob of data out, This is called for things like:
48 // output << "hello world"
49 // output.write(string, n);
50 int fcgio_buf::xsputn(const char* s, int n) {
51   return FCGX_PutStr(s, n, fcgi_str);
52 }
53    
54
55 // overflow is called for "endl" and every time the put buffer
56 // is full. Since we are using a single char put buffer, we just
57 // pump the waiting character out and return the number of chars
58 // we just got rid of (1). Returns EOF on error
59 int fcgio_buf::overflow(int c) {
60   if (c)
61     return FCGX_PutChar(c, fcgi_str);
62   else
63     return EOF;
64 }
65
66
67 // Underflow is called to get characters to fill up the get buffer
68 // so something that uses the stream can get the data. If there
69 // is nothing else to read, this returns EOF
70 int fcgio_buf::underflow() {
71   // if it is unbuffered, then get & return a char
72   if (unbuffered())
73     return FCGX_GetChar(fcgi_str);
74
75   // read as much data as we can, then adjust the get area so it
76   // reflects the data we just read
77   int numread=FCGX_GetStr(eback(), blen(), fcgi_str);
78   if (numread==0) return EOF;
79   setg(eback(),eback(),eback()+numread);
80
81   return *eback();
82 }
83
84
85 // sets up any buffering used for input or output   
86 streambuf* fcgio_buf::setbuf(char *p, int n) {
87   // if setbuf is offered a buffer, then use it, otherwise, set the stream to unbuffered
88   setb(p,p+n,0);
89   // output is not buffered
90   setp(0,0);
91   setg(p,p+n,p+n);
92
93   unbuffered(p==NULL);
94   return this;
95 }
96
97
98 // flush all the output using FCGX_FFlush
99 int fcgio_buf::sync() {
100   return FCGX_FFlush(fcgi_str); 
101 }
102
103
104 // constructor calls ios::init to assign our streambuf to
105 // the ostream derived class. Also sets up buffering
106 fcgio_ostream::fcgio_ostream(FCGX_Stream *str) : buf(str) {
107   // init is a protected member of ios
108   init(&buf);
109   buf.setbuf(NULL,0);
110 }
111
112
113 // constructor calls ios::init to assign our streambuf to
114 // the ostream derived class. Also sets up buffering
115 fcgio_istream::fcgio_istream(FCGX_Stream *str) : buf(str) {
116   // init is a protected member of ios
117   init(&buf);
118   // set up the buffers
119   buf.setbuf(buffer,buffersize);
120 }
121
122