libdap Updated for version 3.18.1
XDRStreamUnMarshaller.cc
1// XDRStreamUnMarshaller.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of libdap, A C++ implementation of the OPeNDAP Data
6// Access Protocol.
7
8// Copyright (c) 2002,2003 OPeNDAP, Inc.
9// Author: Patrick West <pwest@ucar.edu>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27// (c) COPYRIGHT URI/MIT 1994-1999
28// Please read the full copyright statement in the file COPYRIGHT_URI.
29//
30// Authors:
31// pwest Patrick West <pwest@ucar.edu>
32#include "config.h"
33#include "XDRStreamUnMarshaller.h"
34
35#include <cstring> // for memcpy
36#include <string>
37#include <sstream>
38
39//#define DODS_DEBUG2 1
40//#define DODS_DEBUG 1
41
42#include "Str.h"
43// #include "Vector.h"
44#include "Array.h"
45#include "util.h"
46#include "InternalErr.h"
47#include "debug.h"
48
49namespace libdap {
50
51char *XDRStreamUnMarshaller::d_buf = 0;
52
53XDRStreamUnMarshaller::XDRStreamUnMarshaller(istream &in) : /*&d_source( 0 ),*/
54 d_in(in)
55{
56 if (!d_buf)
57 d_buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
58 if (!d_buf)
59 throw Error(internal_error, "Failed to allocate memory for data serialization.");
60
61 //&d_source = new XDR;
62 xdrmem_create(&d_source, d_buf, XDR_DAP_BUFF_SIZE, XDR_DECODE);
63}
64
65XDRStreamUnMarshaller::XDRStreamUnMarshaller() :
66 UnMarshaller(), /*&d_source( 0 ),*/d_in(cin)
67{
68 throw InternalErr(__FILE__, __LINE__, "Default constructor not implemented.");
69}
70
71XDRStreamUnMarshaller::XDRStreamUnMarshaller(const XDRStreamUnMarshaller &um) :
72 UnMarshaller(um), /*&d_source( 0 ),*/d_in(cin)
73{
74 throw InternalErr(__FILE__, __LINE__, "Copy constructor not implemented.");
75}
76
77XDRStreamUnMarshaller &
78XDRStreamUnMarshaller::operator=(const XDRStreamUnMarshaller &)
79{
80 throw InternalErr(__FILE__, __LINE__, "Copy operator not implemented.");
81
82 return *this;
83}
84
85XDRStreamUnMarshaller::~XDRStreamUnMarshaller()
86{
87 xdr_destroy( &d_source );
88 //&d_source = 0;
89}
90
91void XDRStreamUnMarshaller::get_byte(dods_byte &val)
92{
93 if (xdr_setpos( &d_source, 0 ) < 0)
94 throw Error("Failed to reposition input stream");
95 if (!(d_in.read(d_buf, 4))) {
96 if (d_in.eof())
97 throw Error("Premature EOF in input stream");
98 else {
99 ostringstream ss("Error reading from input stream: ");
100 ss << d_in.rdstate();
101 throw Error(ss.str());
102 }
103 }
104
105 DBG2( std::cerr << "_in.gcount(): " << d_in.gcount() << std::endl );
106 DBG2( std::cerr << "_in.tellg(): " << d_in.tellg() << std::endl );
107 DBG2( std::cerr << "_buf[0]: " << hex << d_buf[0] << "; _buf[1]: " << d_buf[1]
108 << "; _buf[2]: " << d_buf[2] << "; _buf[3]: " << d_buf[3]
109 << dec << std::endl );
110
111 if (!xdr_char(&d_source, (char *) &val))
112 throw Error("Network I/O Error. Could not read byte data.");
113
114 DBG2(std::cerr << "get_byte: " << val << std::endl );
115}
116
117void XDRStreamUnMarshaller::get_int16(dods_int16 &val)
118{
119 xdr_setpos( &d_source, 0);
120 d_in.read(d_buf, 4);
121
122 if (!XDR_INT16(&d_source, &val))
123 throw Error("Network I/O Error. Could not read int 16 data.");
124}
125
126void XDRStreamUnMarshaller::get_int32(dods_int32 &val)
127{
128 xdr_setpos( &d_source, 0);
129 d_in.read(d_buf, 4);
130
131 if (!XDR_INT32(&d_source, &val))
132 throw Error("Network I/O Error. Could not read int 32 data.");
133}
134
135void XDRStreamUnMarshaller::get_float32(dods_float32 &val)
136{
137 xdr_setpos( &d_source, 0);
138 d_in.read(d_buf, 4);
139
140 if (!xdr_float(&d_source, &val))
141 throw Error("Network I/O Error. Could not read float 32 data.");
142}
143
144void XDRStreamUnMarshaller::get_float64(dods_float64 &val)
145{
146 xdr_setpos( &d_source, 0);
147 d_in.read(d_buf, 8);
148
149 if (!xdr_double(&d_source, &val))
150 throw Error("Network I/O Error. Could not read float 64 data.");
151}
152
153void XDRStreamUnMarshaller::get_uint16(dods_uint16 &val)
154{
155 xdr_setpos( &d_source, 0);
156 d_in.read(d_buf, 4);
157
158 if (!XDR_UINT16(&d_source, &val))
159 throw Error("Network I/O Error. Could not read uint 16 data.");
160}
161
162void XDRStreamUnMarshaller::get_uint32(dods_uint32 &val)
163{
164 xdr_setpos( &d_source, 0);
165 d_in.read(d_buf, 4);
166
167 if (!XDR_UINT32(&d_source, &val))
168 throw Error("Network I/O Error. Could not read uint 32 data.");
169}
170
171void XDRStreamUnMarshaller::get_str(string &val)
172{
173 int i;
174 get_int(i);
175 DBG(std::cerr << "i: " << i << std::endl);
176
177 // Must round up string size to next 4
178 i = ((i + 3) / 4) * 4;
179 DBG(std::cerr << "i: " << i << std::endl);
180
181 char *in_tmp = 0;
182 //char *buf = 0;
183 //XDR *source = 0;
184 // Must address the case where the string is larger than the buffer
185 if (i + 4 > XDR_DAP_BUFF_SIZE) {
186#if 0
187 char *buf = (char *) malloc(i + 4);
188 if (!buf)
189 throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
190#endif
191 vector<char> buf(i+4);
192
193 XDR source;// = new XDR;
194 xdrmem_create(&source, &buf[0], i + 4, XDR_DECODE);
195 memcpy(&buf[0], d_buf, 4);
196
197 d_in.read(&buf[0] + 4, i);
198
199 xdr_setpos( &source, 0);
200 if (!xdr_string( &source, &in_tmp, max_str_len)) {
201 xdr_destroy( &source );
202 throw Error("Network I/O Error. Could not read string data.");
203 }
204
205 xdr_destroy( &source );
206 }
207 else {
208 d_in.read(d_buf + 4, i);
209
210 xdr_setpos( &d_source, 0);
211 if (!xdr_string(&d_source, &in_tmp, max_str_len))
212 throw Error("Network I/O Error. Could not read string data.");
213 }
214
215 val = in_tmp;
216
217 free(in_tmp);
218}
219
220void XDRStreamUnMarshaller::get_url(string &val)
221{
222 get_str(val);
223}
224
225void XDRStreamUnMarshaller::get_opaque(char *val, unsigned int len)
226{
227 xdr_setpos( &d_source, 0);
228
229 // Round len up to the next multiple of 4. There is also the RNDUP()
230 // macro in xdr.h, at least on OS/X.
231 len += len & 3;
232 if (static_cast<int>(len) > XDR_DAP_BUFF_SIZE)
233 throw Error("Network I/O Error. Length of opaque data larger than allowed");
234
235 d_in.read(d_buf, len);
236
237 xdr_opaque(&d_source, val, len);
238}
239
240void XDRStreamUnMarshaller::get_int(int &val)
241{
242 xdr_setpos( &d_source, 0);
243 d_in.read(d_buf, 4);
244
245 if (!xdr_int(&d_source, &val))
246 throw Error("Network I/O Error(1).");
247
248 DBG(std::cerr << "get_int: " << val << std::endl);
249}
250
251void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, Vector &)
252{
253 int i;
254 get_int(i); // This leaves the XDR encoded value in d_buf; used later
255 DBG(std::cerr << "i: " << i << std::endl);
256
257 // Must round up string size to next 4
258 i += i & 3;
259 DBG(std::cerr << "i: " << i << std::endl);
260
261 //char *buf = 0;
262 //XDR *source = 0;
263 // Must address the case where the string is larger than the buffer
264 if (i + 4 > XDR_DAP_BUFF_SIZE) {
265 vector<char> buf(i+4);
266 XDR source;
267 xdrmem_create(&source, &buf[0], i + 4, XDR_DECODE);
268 memcpy(&buf[0], d_buf, 4);
269
270 d_in.read(&buf[0] + 4, i);
271 DBG2(cerr << "bytes read: " << d_in.gcount() << endl);
272
273 xdr_setpos(&source, 0);
274 if (!xdr_bytes(&d_source, val, &num, DODS_MAX_ARRAY)) {
275 xdr_destroy(&source);
276 throw Error("Network I/O Error. Could not read byte array data.");
277 }
278
279 xdr_destroy( &source );
280 }
281 else {
282 d_in.read(d_buf + 4, i);
283 DBG2(cerr << "bytes read: " << d_in.gcount() << endl);
284
285 xdr_setpos(&d_source, 0);
286 if (!xdr_bytes(&d_source, val, &num, DODS_MAX_ARRAY))
287 throw Error("Network I/O Error. Could not read byte array data.");
288 }
289}
290
291void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, int width, Vector &vec)
292{
293 get_vector(val, num, width, vec.var()->type());
294}
295
296void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, int width, Type type)
297{
298 int i;
299 get_int(i); // This leaves the XDR encoded value in d_buf; used later
300 DBG(std::cerr << "i: " << i << std::endl);
301
302 width += width & 3;
303 DBG(std::cerr << "width: " << width << std::endl);
304
305 int size = i * width; // + 4; // '+ 4' to hold the int already read
306
307 // Must address the case where the string is larger than the buffer
308 if (size > XDR_DAP_BUFF_SIZE) {
309 vector<char> buf(size+4);
310 XDR source;
311 xdrmem_create(&source, &buf[0], size + 4, XDR_DECODE);
312 DBG(cerr << "size: " << size << endl);
313 memcpy(&buf[0], d_buf, 4);
314
315 d_in.read(&buf[0] + 4, size); // +4 for the int already read
316 DBG(cerr << "bytes read: " << d_in.gcount() << endl);
317
318 xdr_setpos(&source, 0);
319 if (!xdr_array(&source, val, &num, DODS_MAX_ARRAY, width, XDRUtils::xdr_coder(type))) {
320 xdr_destroy( &source );
321 throw Error("Network I/O Error. Could not read array data.");
322 }
323
324 xdr_destroy( &source );
325 }
326 else {
327 d_in.read(d_buf + 4, size);
328 DBG(cerr << "bytes read (2): " << d_in.gcount() << endl);
329
330 xdr_setpos( &d_source, 0);
331 if (!xdr_array(&d_source, val, &num, DODS_MAX_ARRAY, width, XDRUtils::xdr_coder(type)))
332 throw Error("Network I/O Error. Could not read array data.");
333 }
334}
335
336void XDRStreamUnMarshaller::dump(ostream &strm) const
337{
338 strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - (" << (void *) this << ")" << endl;
339}
340
341} // namespace libdap
342