libdap++  Updated for version 3.8.2
XDRStreamUnMarshaller.cc
Go to the documentation of this file.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 
49 namespace libdap {
50 
51 char *XDRStreamUnMarshaller::_buf = 0 ;
52 
53 XDRStreamUnMarshaller::XDRStreamUnMarshaller( istream &in )
54  : _source( 0 ), _in( in )
55 {
56  if (!_buf)
57  _buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
58  if (!_buf)
59  throw Error("Failed to allocate memory for data serialization.");
60 
61  _source = new XDR;
62  xdrmem_create(_source, _buf, XDR_DAP_BUFF_SIZE, XDR_DECODE);
63 }
64 
65 XDRStreamUnMarshaller::XDRStreamUnMarshaller()
66  : UnMarshaller(), _source( 0 ), _in( cin )
67 {
68  throw InternalErr( __FILE__, __LINE__, "Default constructor not implemented." ) ;
69 }
70 
71 XDRStreamUnMarshaller::XDRStreamUnMarshaller( const XDRStreamUnMarshaller &um )
72  : UnMarshaller( um ), _source( 0 ), _in( cin )
73 {
74  throw InternalErr( __FILE__, __LINE__, "Copy constructor not implemented." ) ;
75 }
76 
78 XDRStreamUnMarshaller::operator=( const XDRStreamUnMarshaller & )
79 {
80  throw InternalErr( __FILE__, __LINE__, "Copy operator not implemented." ) ;
81 
82  return *this ;
83 }
84 
86 {
87  if ( _source )
88  delete_xdrstdio( _source ) ;
89  _source = 0;
90 }
91 
92 void
94 {
95  if (xdr_setpos( _source, 0 ) < 0)
96  throw Error("Failed to reposition input stream");
97  if (!(_in.read( _buf, 4 ))) {
98  if (_in.eof())
99  throw Error("Premature EOF in input stream");
100  else {
101  ostringstream ss("Error reading from input stream: ");
102  ss << _in.rdstate();
103  throw Error(ss.str());
104  }
105  }
106 
107  DBG2( std::cerr << "_in.gcount(): " << _in.gcount() << std::endl );
108  DBG2( std::cerr << "_in.tellg(): " << _in.tellg() << std::endl );
109  DBG2( std::cerr << "_buf[0]: " << hex << _buf[0] << "; _buf[1]: " << _buf[1]
110  << "; _buf[2]: " << _buf[2] << "; _buf[3]: " << _buf[3]
111  << dec << std::endl );
112 
113  if( !xdr_char( _source, (char *)&val ) )
114  throw Error("Network I/O Error. Could not read byte data.");
115 
116  DBG2(std::cerr << "get_byte: " << val << std::endl );
117 }
118 
119 void
121 {
122  xdr_setpos( _source, 0 );
123  _in.read( _buf, 4 );
124 
125  if( !XDR_INT16( _source, &val ) )
126  throw Error("Network I/O Error. Could not read int 16 data.");
127 }
128 
129 void
131 {
132  xdr_setpos( _source, 0 );
133  _in.read( _buf, 4 );
134 
135  if( !XDR_INT32( _source, &val ) )
136  throw Error("Network I/O Error. Could not read int 32 data.");
137 }
138 
139 void
141 {
142  xdr_setpos( _source, 0 );
143  _in.read( _buf, 4 );
144 
145  if( !xdr_float( _source, &val ) )
146  throw Error("Network I/O Error. Could not read float 32 data.");
147 }
148 
149 void
151 {
152  xdr_setpos( _source, 0 );
153  _in.read( _buf, 8 );
154 
155  if( !xdr_double( _source, &val ) )
156  throw Error("Network I/O Error. Could not read float 64 data.");
157 }
158 
159 void
161 {
162  xdr_setpos( _source, 0 );
163  _in.read( _buf, 4 );
164 
165  if( !XDR_UINT16( _source, &val ) )
166  throw Error("Network I/O Error. Could not read uint 16 data.");
167 }
168 
169 void
171 {
172  xdr_setpos( _source, 0 );
173  _in.read( _buf, 4 );
174 
175  if( !XDR_UINT32( _source, &val ) )
176  throw Error("Network I/O Error. Could not read uint 32 data.");
177 }
178 
179 void
181 {
182  int i;
183  get_int( i ) ;
184  DBG(std::cerr << "i: " << i << std::endl);
185 
186  // Must round up string size to next 4
187  i = ( ( i + 3 ) / 4 ) * 4;
188  DBG(std::cerr << "i: " << i << std::endl);
189 
190  char *in_tmp = 0;
191  char *buf = 0;
192  XDR *source = 0;
193  // Must address the case where the string is larger than the buffer
194  if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
195  source = new XDR;
196  buf = (char *) malloc( i + 4 );
197  xdrmem_create(source, buf, i + 4, XDR_DECODE);
198  memcpy( buf, _buf, 4 );
199 
200  _in.read( buf + 4, i );
201 
202  xdr_setpos( source, 0 );
203  if( !xdr_string( source, &in_tmp, max_str_len ) )
204  throw Error("Network I/O Error. Could not read string data.");
205 
206  delete_xdrstdio( source );
207  }
208  else {
209  _in.read( _buf + 4, i );
210 
211  xdr_setpos( _source, 0 );
212  if( !xdr_string( _source, &in_tmp, max_str_len ) )
213  throw Error("Network I/O Error. Could not read string data.");
214  }
215 
216  val = in_tmp ;
217 
218  free( in_tmp ) ;
219 }
220 
221 void
223 {
224  get_str( val ) ;
225 }
226 
227 void
228 XDRStreamUnMarshaller::get_opaque( char *val, unsigned int len )
229 {
230  xdr_setpos( _source, 0 );
231 
232  // Round len up to the next multiple of 4. There is also the RNDUP()
233  // macro in xdr.h, at least on OS/X.
234  len += len&3;
235  if ( static_cast<int>(len) > XDR_DAP_BUFF_SIZE )
236  throw Error("Network I/O Error. Length of opaque data larger than allowed");
237 
238  _in.read( _buf, len );
239 
240  xdr_opaque( _source, val, len ) ;
241 }
242 
243 void
245 {
246  xdr_setpos( _source, 0 );
247  _in.read( _buf, 4 );
248 
249  if( !xdr_int( _source, &val ) )
250  throw Error("Network I/O Error(1).");
251 
252  DBG(std::cerr << "get_int: " << val << std::endl);
253 }
254 
255 void
256 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, Vector & )
257 {
258  int i;
259  get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
260  DBG(std::cerr << "i: " << i << std::endl);
261 
262  // Must round up string size to next 4
263  i += i&3;
264  DBG(std::cerr << "i: " << i << std::endl);
265 
266  char *buf = 0;
267  XDR *source = 0;
268  // Must address the case where the string is larger than the buffer
269  if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
270  source = new XDR;
271  buf = (char *) malloc( i + 4 );
272  xdrmem_create(source, buf, i + 4, XDR_DECODE);
273  memcpy( buf, _buf, 4 );
274 
275  _in.read( buf + 4, i );
276  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
277 
278  xdr_setpos( source, 0 );
279  if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
280  throw Error("Network I/O Error. Could not read byte array data.");
281 
282  delete_xdrstdio( source );
283  }
284  else {
285  _in.read( _buf + 4, i );
286  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
287 
288  xdr_setpos( _source, 0 );
289  if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
290  throw Error("Network I/O Error. Could not read byte array data.");
291  }
292 }
293 
294 void
295 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, int width, Vector &vec )
296 {
297  int i;
298  get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
299  DBG(std::cerr << "i: " << i << std::endl);
300 
301  width += width&3;
302  DBG(std::cerr << "width: " << width << std::endl);
303 
304  char *buf = 0;
305  XDR *source = 0;
306  int size = i * width; // + 4; // '+ 4' to hold the int already read
307  BaseType *var = vec.var();
308 
309  // Must address the case where the string is larger than the buffer
310  if (size > XDR_DAP_BUFF_SIZE) {
311  source = new XDR;
312  buf = (char *) malloc( size + 4 );
313  xdrmem_create(source, buf, size + 4, XDR_DECODE);
314  DBG2(cerr << "size: " << size << endl);
315  memcpy(buf, _buf, 4);
316 
317  _in.read(buf + 4, size); // +4 for the int already read
318  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
319 
320  xdr_setpos( source, 0 );
321  if (!xdr_array( source, val, &num, DODS_MAX_ARRAY, width,
322  XDRUtils::xdr_coder( var->type() ) ) )
323  throw Error("Network I/O Error. Could not read array data.");
324 
325  delete_xdrstdio(source);
326  }
327  else {
328  _in.read(_buf + 4, size);
329  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
330 
331  xdr_setpos( _source, 0 );
332  if (!xdr_array( _source, val, &num, DODS_MAX_ARRAY, width,
333  XDRUtils::xdr_coder( var->type() ) ) )
334  throw Error("Network I/O Error. Could not read array data.");
335  }
336 }
337 
338 void
339 XDRStreamUnMarshaller::dump(ostream &strm) const
340 {
341  strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - ("
342  << (void *)this << ")" << endl ;
343 }
344 
345 } // namespace libdap
346 
#define XDR_UINT32
Definition: config.h:395
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
virtual void get_uint32(dods_uint32 &val)
uint8_t dods_byte
virtual void get_vector(char **val, unsigned int &num, Vector &vec)
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:78
#define XDR_UINT16
Definition: config.h:392
virtual void get_uint16(dods_uint16 &val)
virtual void get_int16(dods_int16 &val)
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
#define XDR_INT32
Definition: config.h:389
uint16_t dods_uint16
#define DBG2(x)
Definition: debug.h:73
const int XDR_DAP_BUFF_SIZE
A class for software fault reporting.
Definition: InternalErr.h:64
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:383
virtual void get_int32(dods_int32 &val)
unmarshaller that knows how to unmarshall/deserialize dap objects using XDR from a file ...
#define DBG(x)
Definition: debug.h:58
double dods_float64
const unsigned int max_str_len
Definition: Str.h:56
virtual void get_byte(dods_byte &val)
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
uint32_t dods_uint32
virtual void get_float64(dods_float64 &val)
void delete_xdrstdio(XDR *xdr)
Definition: XDRUtils.cc:69
#define XDR_INT16
Definition: config.h:386
virtual void get_str(string &val)
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual void get_float32(dods_float32 &val)
virtual void get_url(string &val)
int16_t dods_int16
const int DODS_MAX_ARRAY
Definition: Array.h:56
The basic data type for the DODS DAP types.
Definition: BaseType.h:190
static xdrproc_t xdr_coder(const Type &t)
Returns a function used to encode elements of an array.
Definition: XDRUtils.cc:143
A class for error processing.
Definition: Error.h:90
virtual void get_opaque(char *val, unsigned int len)
int32_t dods_int32