libdap++  Updated for version 3.8.2
XDRStreamMarshaller.cc
Go to the documentation of this file.
1 // XDRStreamMarshaller.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 
33 #include "XDRStreamMarshaller.h"
34 
35 //#define DODS_DEBUG 1
36 
37 #include "Vector.h"
38 #include "util.h"
39 #include "debug.h"
40 
41 namespace libdap {
42 
43 char *XDRStreamMarshaller::_buf = 0 ;
44 
45 #define XDR_DAP_BUFF_SIZE 256
46 
47 XDRStreamMarshaller::XDRStreamMarshaller( ostream &out )
48  : _sink( 0 ),
49  _out( out )
50 {
51  if( !_buf )
52  _buf = (char *)malloc( XDR_DAP_BUFF_SIZE ) ;
53  if ( !_buf )
54  throw Error("Failed to allocate memory for data serialization.");
55 
56  _sink = new XDR ;
57  xdrmem_create( _sink, _buf, XDR_DAP_BUFF_SIZE, XDR_ENCODE ) ;
58 }
59 
60 XDRStreamMarshaller::XDRStreamMarshaller()
61  : Marshaller(),
62  _sink( 0 ),
63  _out( cout )
64 {
65  throw InternalErr( __FILE__, __LINE__, "Default constructor not implemented." ) ;
66 }
67 
68 XDRStreamMarshaller::XDRStreamMarshaller( const XDRStreamMarshaller &m )
69  : Marshaller( m ),
70  _sink( 0 ),
71  _out( cout )
72 {
73  throw InternalErr( __FILE__, __LINE__, "Copy constructor not implemented." ) ;
74 }
75 
76 XDRStreamMarshaller &
77 XDRStreamMarshaller::operator=( const XDRStreamMarshaller & )
78 {
79  throw InternalErr( __FILE__, __LINE__, "Copy operator not implemented." ) ;
80 
81  return *this ;
82 }
83 
85 {
86  if( _sink )
87  delete_xdrstdio( _sink ) ;
88  _sink = 0 ;
89 }
90 
91 void
93 {
94  DBG( std::cerr << "put_byte: " << val << std::endl );
95  if( !xdr_setpos( _sink, 0 ) )
96  throw Error("Network I/O Error. Could not send byte data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
97 
98  if( !xdr_char( _sink, (char *)&val ) )
99  throw Error("Network I/O Error. Could not send byte data.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
100 
101  unsigned int bytes_written = xdr_getpos( _sink ) ;
102  if( !bytes_written )
103  throw Error("Network I/O Error. Could not send byte data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
104 
105  _out.write( _buf, bytes_written ) ;
106 }
107 
108 void
110 {
111  if( !xdr_setpos( _sink, 0 ) )
112  throw Error("Network I/O Error. Could not send int 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
113 
114  if( !XDR_INT16( _sink, &val ) )
115  throw Error("Network I/O Error. Could not send int 16 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
116 
117  unsigned int bytes_written = xdr_getpos( _sink ) ;
118  if( !bytes_written )
119  throw Error("Network I/O Error. Could not send int 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
120 
121  _out.write( _buf, bytes_written ) ;
122 }
123 
124 void
126 {
127  if( !xdr_setpos( _sink, 0 ) )
128  throw Error("Network I/O Error. Could not send int 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
129 
130  if( !XDR_INT32( _sink, &val ) )
131  throw Error("Network I/O Error. Culd not read int 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
132 
133  unsigned int bytes_written = xdr_getpos( _sink ) ;
134  if( !bytes_written )
135  throw Error("Network I/O Error. Could not send int 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
136 
137  _out.write( _buf, bytes_written ) ;
138 }
139 
140 void
142 {
143  if( !xdr_setpos( _sink, 0 ) )
144  throw Error("Network I/O Error. Could not send float 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
145 
146  if( !xdr_float( _sink, &val ) )
147  throw Error("Network I/O Error. Could not send float 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
148 
149  unsigned int bytes_written = xdr_getpos( _sink ) ;
150  if( !bytes_written )
151  throw Error("Network I/O Error. Could not send float 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
152 
153  _out.write( _buf, bytes_written ) ;
154 }
155 
156 void
158 {
159  if( !xdr_setpos( _sink, 0 ) )
160  throw Error("Network I/O Error. Could not send float 64 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
161 
162  if( !xdr_double( _sink, &val ) )
163  throw Error("Network I/O Error. Could not send float 64 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
164 
165  unsigned int bytes_written = xdr_getpos( _sink ) ;
166  if( !bytes_written )
167  throw Error("Network I/O Error. Could not send float 64 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
168 
169  _out.write( _buf, bytes_written ) ;
170 }
171 
172 void
174 {
175  if( !xdr_setpos( _sink, 0 ) )
176  throw Error("Network I/O Error. Could not send uint 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
177 
178  if( !XDR_UINT16( _sink, &val ) )
179  throw Error("Network I/O Error. Could not send uint 16 data. This may be due to a\nbug in libdap or a problem with the network connection.");
180 
181  unsigned int bytes_written = xdr_getpos( _sink ) ;
182  if( !bytes_written )
183  throw Error("Network I/O Error. Could not send uint 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
184 
185  _out.write( _buf, bytes_written ) ;
186 }
187 
188 void
190 {
191  if( !xdr_setpos( _sink, 0 ) )
192  throw Error("Network I/O Error. Could not send uint 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
193 
194  if( !XDR_UINT32( _sink, &val ) )
195  throw Error("Network I/O Error. Could not send uint 32 data. This may be due to a\nbug in libdap or a problem with the network connection.");
196 
197  unsigned int bytes_written = xdr_getpos( _sink ) ;
198  if( !bytes_written )
199  throw Error("Network I/O Error. Could not send uint 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
200 
201  _out.write( _buf, bytes_written ) ;
202 }
203 
204 void
205 XDRStreamMarshaller::put_str( const string &val )
206 {
207  int size = val.length() + 8 ;
208  char *str_buf = (char *)malloc( size ) ;
209 
210  if ( !str_buf ) {
211  throw Error("Failed to allocate memory for string data serialization.");
212  }
213 
214  XDR *str_sink = new XDR ;
215  xdrmem_create( str_sink, str_buf, size, XDR_ENCODE ) ;
216 
217  if( !xdr_setpos( str_sink, 0 ) ) {
218  delete_xdrstdio( str_sink ) ;
219  free( str_buf ) ;
220  throw Error("Network I/O Error. Could not send string data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
221  }
222 
223  const char *out_tmp = val.c_str() ;
224  if( !xdr_string( str_sink, (char **)&out_tmp, size ) ) {
225  delete_xdrstdio( str_sink ) ;
226  free( str_buf ) ;
227  throw Error("Network I/O Error. Could not send string data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
228  }
229 
230  unsigned int bytes_written = xdr_getpos( str_sink ) ;
231  if( !bytes_written ) {
232  delete_xdrstdio( str_sink ) ;
233  free( str_buf ) ;
234  throw Error("Network I/O Error. Could not send string data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
235  }
236 
237  _out.write( str_buf, bytes_written ) ;
238 
239  delete_xdrstdio( str_sink ) ;
240  free( str_buf ) ;
241 }
242 
243 void
244 XDRStreamMarshaller::put_url( const string &val )
245 {
246  put_str( val ) ;
247 }
248 
249 void
250 XDRStreamMarshaller::put_opaque( char *val, unsigned int len )
251 {
252  if( len > XDR_DAP_BUFF_SIZE )
253  throw Error("Network I/O Error. Could not send opaque data - length of opaque data larger than allowed");
254 
255  if( !xdr_setpos( _sink, 0 ) )
256  throw Error("Network I/O Error. Could not send opaque data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
257 
258  if( !xdr_opaque( _sink, val, len ) )
259  throw Error("Network I/O Error. Could not send opaque data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
260 
261  unsigned int bytes_written = xdr_getpos( _sink ) ;
262  if( !bytes_written )
263  throw Error("Network I/O Error. Could not send opaque data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
264 
265  _out.write( _buf, bytes_written ) ;
266 }
267 
268 void
270 {
271  if( !xdr_setpos( _sink, 0 ) )
272  throw Error("Network I/O Error. Could not send int data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
273 
274  if( !xdr_int( _sink, &val) )
275  throw Error("Network I/O Error(1). Could not send int data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
276 
277  unsigned int bytes_written = xdr_getpos( _sink ) ;
278  if( !bytes_written )
279  throw Error("Network I/O Error. Could not send int data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
280 
281  _out.write( _buf, bytes_written ) ;
282 }
283 
284 void
285 XDRStreamMarshaller::put_vector( char *val, int num, Vector & )
286 {
287  if (!val)
288  throw InternalErr(__FILE__, __LINE__, "Could not send byte vector data. Buffer pointer is not set.");
289 
290  // write the number of members of the array being written and then set the position to 0
291  put_int( num ) ;
292 
293  // this is the word boundary for writing xdr bytes in a vector.
294  unsigned int add_to = 8 ;
295 
296  char *byte_buf = (char *)malloc( num + add_to ) ;
297  if ( !byte_buf ) {
298  throw Error("Failed to allocate memory for byte vector data serialization.");
299  }
300 
301  XDR *byte_sink = new XDR ;
302  xdrmem_create( byte_sink, byte_buf, num + add_to, XDR_ENCODE ) ;
303 
304  if( !xdr_setpos( byte_sink, 0 ) ) {
305  delete_xdrstdio( byte_sink ) ;
306  free(byte_buf);
307  throw Error("Network I/O Error. Could not send byte vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
308  }
309 
310  if( !xdr_bytes( byte_sink, (char **)&val, (unsigned int *) &num,
311  num + add_to ) )
312  {
313  delete_xdrstdio( byte_sink ) ;
314  free(byte_buf);
315  throw Error("Network I/O Error(2). Could not send byte vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
316  }
317 
318  unsigned int bytes_written = xdr_getpos( byte_sink ) ;
319  if( !bytes_written ) {
320  delete_xdrstdio( byte_sink ) ;
321  free(byte_buf);
322  throw Error("Network I/O Error. Could not send byte vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
323  }
324 
325  _out.write( byte_buf, bytes_written ) ;
326 
327  delete_xdrstdio( byte_sink ) ;
328  free( byte_buf ) ;
329 }
330 
331 void
332 XDRStreamMarshaller::put_vector( char *val, int num, int width, Vector &vec )
333 {
334  if (!val)
335  throw InternalErr(__FILE__, __LINE__,
336  "Buffer pointer is not set.");
337  // write the number of array members being written, then set the position back to 0
338  put_int( num ) ;
339 
340  int use_width = width ;
341  if( use_width < 4 )
342  use_width = 4 ;
343 
344  // the size is the number of elements num times the width of each
345  // element, then add 4 bytes for the number of elements
346  int size = ( num * use_width ) + 4 ;
347 
348  // allocate enough memory for the elements
349  char *vec_buf = (char *)malloc( size ) ;
350  if ( !vec_buf ) {
351  free(vec_buf);
352  throw Error("Failed to allocate memory for vector data serialization.");
353  }
354 
355  XDR *vec_sink = new XDR ;
356  xdrmem_create( vec_sink, vec_buf, size, XDR_ENCODE ) ;
357 
358  // set the position of the sink to 0, we're starting at the beginning
359  if( !xdr_setpos( vec_sink, 0 ) ) {
360  delete_xdrstdio( vec_sink ) ;
361  free(vec_buf);
362  throw Error("Network I/O Error. Could not send vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
363  }
364 
365  BaseType *var = vec.var() ;
366 
367  // write the array to the buffer
368  if( !xdr_array( vec_sink, (char **)&val,
369  (unsigned int *) & num,
370  size, width,
371  XDRUtils::xdr_coder( var->type() ) ) )
372  {
373  delete_xdrstdio( vec_sink ) ;
374  free(vec_buf);
375  throw Error("Network I/O Error(2). Could not send vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
376  }
377 
378  // how much was written to the buffer
379  unsigned int bytes_written = xdr_getpos( vec_sink ) ;
380  if( !bytes_written ) {
381  delete_xdrstdio( vec_sink ) ;
382  free(vec_buf);
383  throw Error("Network I/O Error. Could not send vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
384  }
385 
386  // write that much out to the output stream
387  _out.write( vec_buf, bytes_written ) ;
388 
389  delete_xdrstdio( vec_sink ) ;
390  free( vec_buf ) ;
391 }
392 
393 void
394 XDRStreamMarshaller::dump(ostream &strm) const
395 {
396  strm << DapIndent::LMarg << "XDRStreamMarshaller::dump - ("
397  << (void *)this << ")" << endl ;
398 }
399 
400 } // namespace libdap
401