libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
fdiostream.cc
Go to the documentation of this file.
1// -*- mode: c++; c-basic-offset:4 -*-
2
3// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4// Access Protocol.
5
6// Copyright (c) 2009 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24//
25// Portions of this code were taken verbatim from Josuttis,
26// "The C++ Standard Library," p.672
27
28#include "config.h"
29
30#include "fdiostream.h"
31#include <cstring> // for memcpy
32// #define DODS_DEBUG
33#include "debug.h"
34
35namespace libdap {
36
43fdoutbuf::fdoutbuf(int _fd, bool _close) : fd(_fd), close(_close) { setp(buffer, buffer + (bufferSize - 1)); }
44
48 sync();
49 if (close)
50 ::close(fd);
51}
52
53// flush the characters in the buffer
55 int num = pptr() - pbase();
56 if (write(1, buffer, num) != num) {
57 return EOF;
58 }
59 pbump(-num);
60 return num;
61}
62
65 if (c != EOF) {
66 *pptr() = c;
67 pbump(1);
68 }
69 // flush the buffer
70 if (flushBuffer() == EOF) {
71 // Error
72 return EOF;
73 }
74
75 return c;
76}
77
80 if (flushBuffer() == EOF) {
81 // Error
82 return -1;
83 }
84 return 0;
85}
86
88std::streamsize fdoutbuf::xsputn(const char *s, std::streamsize num) { return write(fd, s, num); }
89
90/*
91 How the buffer works for input streams:
92
93 Initialized:
94 eback() --\
95 gptr() --|
96 egptr() --|
97 |
98 ---------------------------
99 | | | | | | | | | | | | | |
100 ---------------------------
101
102 After the first call to read, the buffer is filled:
103 eback() --\
104 gptr() --|
105 | egptr() --|
106 | |
107 ---------------------------
108 | | | | | | |h|a|l|l|o|w|e|
109 ---------------------------
110
111 After 'hallowe' is read from the stream, gptr() reaches egptr() and that
112 triggers the second read, which first must shuffle the characters 'hallowe'
113 to the 'put back' area of the buffer and then read more characters from the
114 underlying input source (fle descriptor or FILE*).
115
116 eback() --\
117 | gptr() --|
118 | |
119 | |
120 ---------------------------
121 | | | | | | |h|a|l|l|o|w|e|
122 ---------------------------
123 |
124 egptr() --|
125
126 After each read, gptr() is advanced until it hits egptr, which triggers a
127 read. However, before the read takes place, characters are moved into the
128 put back part of the buffer. IE when a character is 'read' using the stream
129 all the really happens is the gptr is advanced, the character is still in the
130 buffer
131
132 gptr() --|
133 | egptr()
134 /-eback() | |
135 ---------------------------
136 |h|a|l|l|o|w|e|e|n| |c|o|s|
137 ---------------------------
138
139 */
140
147fdinbuf::fdinbuf(int _fd, bool _close) : fd(_fd), close(_close) {
148 setg(buffer + putBack, // beginning of put back area
149 buffer + putBack, // read position
150 buffer + putBack); // end position
151}
152
155 if (close)
156 ::close(fd);
157}
158
161 if (gptr() < egptr()) {
162 DBG(std::cerr << "underflow, no read" << std::endl);
163 return *gptr();
164 }
165
166 // How many characters are in the 'put back' part of the buffer? Cap
167 // this number at putBack, which is nominally 128.
168 int numPutBack = gptr() - eback();
169 if (numPutBack > putBack)
170 numPutBack = putBack;
171
172 // copy characters previously read into the put back area of the
173 // buffer. In a typical call, putBack is 128 and numPutBack is 128 too.
174 // In this case the destination of memcpy is the start of the buffer and
175 // gptr() - numPutBack (the source of the copy) points to the last 128
176 // characters in the buffer.
177 memcpy(buffer + (putBack - numPutBack), gptr() - numPutBack, numPutBack);
178
179 // read new characters
180 int num = read(fd, buffer + putBack, bufferSize - putBack);
181 DBG(std::cerr << "underflow, read returns: " << num << std::endl);
182 if (num <= 0) {
183 // Error or EOF; error < 0; EOF == 0
184 return EOF;
185 }
186
187 setg(buffer + (putBack - numPutBack), // beginning of put back area
188 buffer + putBack, // read position
189 buffer + putBack + num); // end of buffer
190
191 // return next character
192#ifdef DODS_DEBUG
193 char c = *gptr();
194 DBG(std::cerr << "returning :" << c << std::endl);
195 return c;
196#else
197 return *gptr();
198#endif
199}
200
207fpinbuf::fpinbuf(FILE *_fp, bool _close) : fp(_fp), close(_close) {
208 setg(buffer + putBack, // beginning of put back area
209 buffer + putBack, // read position
210 buffer + putBack); // end position
211}
212
215 if (close)
216 fclose(fp);
217}
218
221 if (gptr() < egptr()) {
222 DBG(std::cerr << "underflow, no read" << std::endl);
223 return *gptr();
224 }
225
226 // process size of putBack area
227 // use the number of characters read, but a maximum of putBack
228 int numPutBack = gptr() - eback();
229 if (numPutBack > putBack)
230 numPutBack = putBack;
231
232 // copy characters previously read into the put back area of the
233 // buffer.
234 memcpy(buffer + (putBack - numPutBack), gptr() - numPutBack, numPutBack);
235
236 // read new characters
237 int num = fread(buffer + putBack, 1, bufferSize - putBack, fp);
238 DBG(std::cerr << "underflow, read returns: " << num << std::endl);
239 if (num == 0) {
240 // Error or EOF; use feof() or ferror() to test
241 return EOF;
242 }
243
244 setg(buffer + (putBack - numPutBack), // beginning of put back area
245 buffer + putBack, // read position
246 buffer + putBack + num); // end of buffer
247
248 // return next character
249 return *gptr();
250}
251
252} // namespace libdap
static const int bufferSize
Definition fdiostream.h:103
static const int putBack
Definition fdiostream.h:104
fdinbuf(int _fd, bool close)
char buffer[bufferSize]
Definition fdiostream.h:105
virtual int underflow()
virtual ~fdinbuf()
virtual int sync()
Definition fdiostream.cc:79
virtual int overflow(int c)
Definition fdiostream.cc:64
virtual std::streamsize xsputn(const char *s, std::streamsize num)
Definition fdiostream.cc:88
char buffer[bufferSize]
Definition fdiostream.h:55
static const int bufferSize
Definition fdiostream.h:54
virtual ~fdoutbuf()
Definition fdiostream.cc:47
fdoutbuf(int _fd, bool _close)
Definition fdiostream.cc:43
static const int putBack
Definition fdiostream.h:145
char buffer[bufferSize]
Definition fdiostream.h:146
virtual ~fpinbuf()
static const int bufferSize
Definition fdiostream.h:144
virtual int underflow()
fpinbuf(FILE *_fp, bool _close)
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30