libdap++  Updated for version 3.11.7
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 
77 XDRStreamUnMarshaller &
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  char *buf = (char *) malloc( i + 4 );
196  if (!buf)
197  throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
198  XDR *source = new XDR;
199  xdrmem_create(source, buf, i + 4, XDR_DECODE);
200  memcpy( buf, _buf, 4 );
201 
202  _in.read( buf + 4, i );
203 
204  xdr_setpos( source, 0 );
205  if( !xdr_string( source, &in_tmp, max_str_len ) ) {
206  delete_xdrstdio( source );
207  throw Error("Network I/O Error. Could not read string data.");
208  }
209 
210  delete_xdrstdio( source );
211  }
212  else {
213  _in.read( _buf + 4, i );
214 
215  xdr_setpos( _source, 0 );
216  if( !xdr_string( _source, &in_tmp, max_str_len ) )
217  throw Error("Network I/O Error. Could not read string data.");
218  }
219 
220  val = in_tmp ;
221 
222  free( in_tmp ) ;
223 }
224 
225 void
227 {
228  get_str( val ) ;
229 }
230 
231 void
232 XDRStreamUnMarshaller::get_opaque( char *val, unsigned int len )
233 {
234  xdr_setpos( _source, 0 );
235 
236  // Round len up to the next multiple of 4. There is also the RNDUP()
237  // macro in xdr.h, at least on OS/X.
238  len += len&3;
239  if ( static_cast<int>(len) > XDR_DAP_BUFF_SIZE )
240  throw Error("Network I/O Error. Length of opaque data larger than allowed");
241 
242  _in.read( _buf, len );
243 
244  xdr_opaque( _source, val, len ) ;
245 }
246 
247 void
249 {
250  xdr_setpos( _source, 0 );
251  _in.read( _buf, 4 );
252 
253  if( !xdr_int( _source, &val ) )
254  throw Error("Network I/O Error(1).");
255 
256  DBG(std::cerr << "get_int: " << val << std::endl);
257 }
258 
259 void
260 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, Vector & )
261 {
262  int i;
263  get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
264  DBG(std::cerr << "i: " << i << std::endl);
265 
266  // Must round up string size to next 4
267  i += i&3;
268  DBG(std::cerr << "i: " << i << std::endl);
269 
270  //char *buf = 0;
271  //XDR *source = 0;
272  // Must address the case where the string is larger than the buffer
273  if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
274  char *buf = (char *) malloc( i + 4 );
275  if (!buf)
276  throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
277  XDR *source = new XDR;
278  xdrmem_create(source, buf, i + 4, XDR_DECODE);
279  memcpy( buf, _buf, 4 );
280 
281  _in.read( buf + 4, i );
282  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
283 
284  xdr_setpos( source, 0 );
285  if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) ) {
286  delete_xdrstdio( source );
287  throw Error("Network I/O Error. Could not read byte array data.");
288  }
289 
290  delete_xdrstdio( source );
291  }
292  else {
293  _in.read( _buf + 4, i );
294  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
295 
296  xdr_setpos( _source, 0 );
297  if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
298  throw Error("Network I/O Error. Could not read byte array data.");
299  }
300 }
301 
302 void
303 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, int width, Vector &vec )
304 {
305  int i;
306  get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
307  DBG(std::cerr << "i: " << i << std::endl);
308 
309  width += width&3;
310  DBG(std::cerr << "width: " << width << std::endl);
311 
312  //char *buf = 0;
313  //XDR *source = 0;
314  int size = i * width; // + 4; // '+ 4' to hold the int already read
315  BaseType *var = vec.var();
316 
317  // Must address the case where the string is larger than the buffer
318  if (size > XDR_DAP_BUFF_SIZE) {
319  char *buf = (char *) malloc( size + 4 );
320  if (!buf)
321  throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
322  XDR *source = new XDR;
323  xdrmem_create(source, buf, size + 4, XDR_DECODE);
324  DBG2(cerr << "size: " << size << endl);
325  memcpy(buf, _buf, 4);
326 
327  _in.read(buf + 4, size); // +4 for the int already read
328  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
329 
330  xdr_setpos( source, 0 );
331  if (!xdr_array( source, val, &num, DODS_MAX_ARRAY, width,
332  XDRUtils::xdr_coder( var->type() ) ) ) {
333  delete_xdrstdio( source );
334  throw Error("Network I/O Error. Could not read array data.");
335  }
336 
337  delete_xdrstdio(source);
338  }
339  else {
340  _in.read(_buf + 4, size);
341  DBG2(cerr << "bytes read: " << _in.gcount() << endl);
342 
343  xdr_setpos( _source, 0 );
344  if (!xdr_array( _source, val, &num, DODS_MAX_ARRAY, width,
345  XDRUtils::xdr_coder( var->type() ) ) )
346  throw Error("Network I/O Error. Could not read array data.");
347  }
348 }
349 
350 void
351 XDRStreamUnMarshaller::dump(ostream &strm) const
352 {
353  strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - ("
354  << (void *)this << ")" << endl ;
355 }
356 
357 } // namespace libdap
358 
#define XDR_UINT32
Definition: config.h:701
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:698
virtual void get_uint16(dods_uint16 &val)
virtual void get_int16(dods_int16 &val)
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
#define XDR_INT32
Definition: config.h:695
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:366
virtual void get_int32(dods_int32 &val)
#define DBG(x)
Definition: debug.h:58
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
double dods_float64
const unsigned int max_str_len
Definition: Str.h:56
virtual void get_byte(dods_byte &val)
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:692
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:60
The basic data type for the DODS DAP types.
Definition: BaseType.h:194
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