libdap  Updated for version 3.20.0
libdap4 is an implementation of OPeNDAP's DAP protocol.
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 "Array.h"
44 #include "util.h"
45 #include "InternalErr.h"
46 #include "debug.h"
47 #include "DapIndent.h"
48 
49 namespace libdap {
50 
51 char *XDRStreamUnMarshaller::d_buf = 0;
52 
53 XDRStreamUnMarshaller::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 
65 XDRStreamUnMarshaller::XDRStreamUnMarshaller() :
66  UnMarshaller(), /*&d_source( 0 ),*/d_in(cin)
67 {
68  throw InternalErr(__FILE__, __LINE__, "Default constructor not implemented.");
69 }
70 
71 XDRStreamUnMarshaller::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 
77 XDRStreamUnMarshaller &
78 XDRStreamUnMarshaller::operator=(const XDRStreamUnMarshaller &)
79 {
80  throw InternalErr(__FILE__, __LINE__, "Copy operator not implemented.");
81 
82  return *this;
83 }
84 
85 XDRStreamUnMarshaller::~XDRStreamUnMarshaller()
86 {
87  xdr_destroy( &d_source );
88  //&d_source = 0;
89 }
90 
91 void 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 
117 void 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 
126 void 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 
135 void 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 
144 void 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 
153 void 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 
162 void 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 
171 void 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 
220 void XDRStreamUnMarshaller::get_url(string &val)
221 {
222  get_str(val);
223 }
224 
225 void 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 
240 void 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 
251 void 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 
291 void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, int width, Vector &vec)
292 {
293  get_vector(val, num, width, vec.var()->type());
294 }
295 
296 void 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 
336 void XDRStreamUnMarshaller::dump(ostream &strm) const
337 {
338  strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - (" << (void *) this << ")" << endl;
339 }
340 
341 } // namespace libdap
342 
Type
Identifies the data type.
Definition: Type.h:94
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
top level DAP object to house generic methods
Definition: AlarmHandler.h:35
static xdrproc_t xdr_coder(const Type &t)
Returns a function used to encode elements of an array.
Definition: XDRUtils.cc:145