Commit | Line | Data |
c124bb9b |
1 | // |
25413d1c |
2 | // $Id: fcgio.cpp,v 1.12 2001/12/04 00:22:06 robs Exp $ |
c124bb9b |
3 | // |
f684a497 |
4 | // Allows you communicate with FastCGI streams using C++ iostreams |
c124bb9b |
5 | // |
98e2ddaa |
6 | // ORIGINAL AUTHOR: George Feinberg |
7 | // REWRITTEN BY: Michael Richards 06/20/1999 |
8 | // REWRITTEN AGAIN BY: Michael Shell 02/23/2000 |
f684a497 |
9 | // REWRITTEN AGAIN BY: Rob Saccoccio 11 Nov 2001 |
98e2ddaa |
10 | // |
11 | // Copyright (c) 2000 Tux the Linux Penguin |
c124bb9b |
12 | // |
13 | // You are free to use this software without charge or royalty |
14 | // as long as this notice is not removed or altered, and recognition |
98e2ddaa |
15 | // is given to the author(s) |
16 | // |
17 | // This code is offered as-is without any warranty either expressed or |
18 | // implied; without even the implied warranty of MERCHANTABILITY or |
19 | // FITNESS FOR A PARTICULAR PURPOSE. |
20 | |
af4a4f30 |
21 | #ifdef _WIN32 |
22 | #define DLLAPI __declspec(dllexport) |
23 | #endif |
24 | |
e52a7487 |
25 | #include "fcgio.h" |
98e2ddaa |
26 | |
25413d1c |
27 | fcgi_streambuf::fcgi_streambuf(FCGX_Stream * fs, char * b, int bs) |
0cf44b19 |
28 | { |
25413d1c |
29 | init(fs, b, bs); |
0cf44b19 |
30 | } |
31 | |
25413d1c |
32 | fcgi_streambuf::fcgi_streambuf(char * b, int bs) |
0cf44b19 |
33 | { |
25413d1c |
34 | init(0, b, bs); |
0cf44b19 |
35 | } |
36 | |
25413d1c |
37 | fcgi_streambuf::fcgi_streambuf(FCGX_Stream * fs) |
f684a497 |
38 | { |
25413d1c |
39 | init(fs, 0, 0); |
f684a497 |
40 | } |
98e2ddaa |
41 | |
f684a497 |
42 | fcgi_streambuf::~fcgi_streambuf(void) |
43 | { |
44 | overflow(EOF); |
45 | // FCGX_Finish()/FCGX_Accept() will flush and close |
0cf44b19 |
46 | } |
47 | |
25413d1c |
48 | void fcgi_streambuf::init(FCGX_Stream * fs, char * b, int bs) |
0cf44b19 |
49 | { |
25413d1c |
50 | this->fcgx = fs; |
51 | this->buf = 0; |
0cf44b19 |
52 | this->bufsize = 0; |
25413d1c |
53 | setbuf(b, bs); |
282622d5 |
54 | } |
98e2ddaa |
55 | |
98e2ddaa |
56 | int fcgi_streambuf::overflow(int c) |
f684a497 |
57 | { |
58 | if (this->bufsize) |
59 | { |
60 | int plen = pptr() - pbase(); |
61 | |
62 | if (plen) |
63 | { |
64 | if (FCGX_PutStr(pbase(), plen, this->fcgx) != plen) return EOF; |
65 | pbump(-plen); |
66 | } |
67 | } |
68 | |
69 | if (c != EOF) |
70 | { |
71 | if (FCGX_PutChar(c, this->fcgx) != c) return EOF; |
72 | } |
73 | |
74 | return 0; |
75 | } |
76 | |
0cf44b19 |
77 | // default base class behaviour seems to be inconsistent |
98e2ddaa |
78 | int fcgi_streambuf::sync() |
f684a497 |
79 | { |
0cf44b19 |
80 | if (overflow(EOF)) return EOF; |
f684a497 |
81 | if (FCGX_FFlush(this->fcgx)) return EOF; |
82 | return 0; |
83 | } |
c124bb9b |
84 | |
4c4f72f0 |
85 | // uflow() removes the char, underflow() doesn't |
86 | int fcgi_streambuf::uflow() |
87 | { |
88 | int rv = underflow(); |
89 | if (this->bufsize) gbump(1); |
90 | return rv; |
91 | } |
92 | |
93 | // Note that the expected behaviour when there is no buffer varies |
98e2ddaa |
94 | int fcgi_streambuf::underflow() |
f684a497 |
95 | { |
96 | if (this->bufsize) |
97 | { |
98 | if (in_avail() == 0) |
99 | { |
100 | int glen = FCGX_GetStr(eback(), this->bufsize, this->fcgx); |
101 | if (glen <= 0) return EOF; |
102 | |
103 | setg(eback(), eback(), eback() + glen); |
104 | } |
105 | |
106 | return (unsigned char) *gptr(); |
107 | } |
108 | else |
109 | { |
110 | return FCGX_GetChar(this->fcgx); |
111 | } |
112 | } |
113 | |
0cf44b19 |
114 | void fcgi_streambuf::reset(void) |
115 | { |
116 | // it should be ok to set up both the get and put areas |
117 | setg(this->buf, this->buf, this->buf); |
118 | setp(this->buf, this->buf + this->bufsize); |
119 | } |
120 | |
25413d1c |
121 | streambuf * fcgi_streambuf::setbuf(char * b, int bs) |
f684a497 |
122 | { |
0cf44b19 |
123 | // XXX support moving data from an old buffer |
25413d1c |
124 | if (this->bufsize) return 0; |
0cf44b19 |
125 | |
25413d1c |
126 | this->buf = b; |
127 | this->bufsize = bs; |
0cf44b19 |
128 | |
129 | // the base setbuf() *has* to be called |
25413d1c |
130 | streambuf::setbuf(b, bs); |
f684a497 |
131 | |
0cf44b19 |
132 | reset(); |
f684a497 |
133 | |
134 | return this; |
0cf44b19 |
135 | } |
136 | |
25413d1c |
137 | int fcgi_streambuf::attach(FCGX_Stream * fs) |
0cf44b19 |
138 | { |
25413d1c |
139 | this->fcgx = fs; |
0cf44b19 |
140 | |
141 | if (this->bufsize) |
142 | { |
143 | reset(); |
144 | } |
145 | |
146 | return 0; |
f684a497 |
147 | } |
148 | |
149 | int fcgi_streambuf::xsgetn(char * s, int n) |
0cf44b19 |
150 | { |
151 | return (this->bufsize) |
152 | ? streambuf::xsgetn(s, n) |
f684a497 |
153 | : FCGX_GetStr(s, n, this->fcgx); |
0cf44b19 |
154 | } |
155 | |
f684a497 |
156 | int fcgi_streambuf::xsputn(const char * s, int n) |
0cf44b19 |
157 | { |
158 | return (this->bufsize) |
159 | ? streambuf::xsputn(s, n) |
160 | : FCGX_PutStr(s, n, this->fcgx); |
161 | } |
162 | |
163 | // deprecated |
25413d1c |
164 | fcgi_istream::fcgi_istream(FCGX_Stream * fs) : |
f684a497 |
165 | istream(&fcgi_strmbuf) |
166 | { |
25413d1c |
167 | fcgi_strmbuf.attach(fs); |
f684a497 |
168 | } |
169 | |
0cf44b19 |
170 | // deprecated |
25413d1c |
171 | void fcgi_istream::attach(FCGX_Stream * fs) |
f684a497 |
172 | { |
25413d1c |
173 | fcgi_strmbuf.attach(fs); |
f684a497 |
174 | } |
175 | |
0cf44b19 |
176 | // deprecated |
25413d1c |
177 | fcgi_ostream::fcgi_ostream(FCGX_Stream * fs) : |
0cf44b19 |
178 | ostream(&fcgi_strmbuf) |
f684a497 |
179 | { |
25413d1c |
180 | fcgi_strmbuf.attach(fs); |
f684a497 |
181 | } |
182 | |
0cf44b19 |
183 | // deprecated |
25413d1c |
184 | void fcgi_ostream::attach(FCGX_Stream * fs) |
f684a497 |
185 | { |
25413d1c |
186 | fcgi_strmbuf.attach(fs); |
f684a497 |
187 | } |