1 /*  $Id: fcgibuf.cpp 103491 2007-05-04 17:18:18Z kazimird $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Eugene Vasilchenko
27  *
28  * File Description:
29  *   FCGI streambufs
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbistd.hpp>
35 #include <fcgiapp.h>
36 #include "fcgibuf.hpp"
37 #include <algorithm>
38 
39 
40 BEGIN_NCBI_SCOPE
41 
42 
CCgiObuffer(FCGX_Stream * out)43 CCgiObuffer::CCgiObuffer(FCGX_Stream* out)
44     : m_out(out), m_cnt(0)
45 {
46     if (!m_out  ||  m_out->isReader) {
47         THROW1_TRACE(runtime_error, "CCgiObuffer: out is not writer");
48     }
49 
50     setp((CT_CHAR_TYPE*) m_out->wrNext, (CT_CHAR_TYPE*) m_out->stop);
51 }
52 
53 
~CCgiObuffer(void)54 CCgiObuffer::~CCgiObuffer(void)
55 {
56     (void) sync();
57 }
58 
59 
overflow(CT_INT_TYPE c)60 CT_INT_TYPE CCgiObuffer::overflow(CT_INT_TYPE c)
61 {
62     m_cnt += ((unsigned char*) pptr()) - m_out->wrNext;
63 
64     _ASSERT(m_out->stop == (unsigned char*) epptr());
65     m_out->wrNext = (unsigned char*) pptr();
66 
67     if (m_out->wrNext == m_out->stop) {
68         if (m_out->isClosed  || !m_out->emptyBuffProc) {
69             return CT_EOF;
70         }
71 
72         m_out->emptyBuffProc(m_out, false);
73         if (m_out->wrNext == m_out->stop) {
74             if ( !m_out->isClosed ) {
75                 THROW1_TRACE(runtime_error,
76                              "CCgiObuffer::overflow: error in emptyBuffProc");
77             }
78             return CT_EOF;
79         }
80 
81         setp((CT_CHAR_TYPE*) m_out->wrNext, (CT_CHAR_TYPE*) m_out->stop);
82     }
83 
84     return CT_EQ_INT_TYPE(c, CT_EOF)
85         ? CT_NOT_EOF(CT_EOF) : sputc(CT_TO_CHAR_TYPE(c));
86 }
87 
88 
sync(void)89 int CCgiObuffer::sync(void)
90 {
91     CT_INT_TYPE oflow = overflow(CT_EOF);
92     if ( CT_EQ_INT_TYPE(oflow, CT_EOF) )
93         return -1;
94     int flush = FCGX_FFlush(m_out);
95     setp((CT_CHAR_TYPE*) m_out->wrNext, (CT_CHAR_TYPE*) m_out->stop);
96     return flush ? -1 : 0;
97 }
98 
99 
CCgiIbuffer(FCGX_Stream * in)100 CCgiIbuffer::CCgiIbuffer(FCGX_Stream* in)
101     : m_in(in), m_cnt(0)
102 {
103     if (!m_in  ||  !m_in->isReader) {
104         THROW1_TRACE(runtime_error, "CCgiObuffer: in is not reader");
105     }
106 
107     x_Setg();
108 }
109 
110 
x_Setg(void)111 void CCgiIbuffer::x_Setg(void)
112 {
113     m_cnt += m_in->stop - m_in->rdNext;
114     setg((CT_CHAR_TYPE*) m_in->stopUnget,
115          (CT_CHAR_TYPE*) m_in->rdNext, (CT_CHAR_TYPE*) m_in->stop);
116 }
117 
118 
underflow(void)119 CT_INT_TYPE CCgiIbuffer::underflow(void)
120 {
121     _ASSERT(m_in->stop == (unsigned char*) egptr());
122     m_in->rdNext = (unsigned char*) gptr();
123 
124     if (m_in->rdNext == m_in->stop) {
125         if (m_in->isClosed  ||  !m_in->fillBuffProc) {
126             return CT_EOF;
127         }
128 
129         m_in->fillBuffProc(m_in);
130         if (m_in->rdNext == m_in->stop) {
131             if ( !m_in->isClosed ) {
132                 THROW1_TRACE(runtime_error,
133                              "CCgiIbuffer::underflow: error in fillBuffProc");
134             }
135             return CT_EOF;
136         }
137 
138         m_in->stopUnget = m_in->rdNext;
139         x_Setg();
140     }
141 
142     return sgetc();
143 }
144 
145 
146 END_NCBI_SCOPE
147