summaryrefslogtreecommitdiff
path: root/TAO/IIOP/lib/cdr.h
blob: 1b48b18f2be8efa614cfaa98e51030af4adde7de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
// This may look like C, but it's really -*- C++ -*-

// Copyright 1994-1995 by Sun Microsystems Inc.
// All Rights Reserved
//
// ============================================================================
//
// = LIBRARY
//    TAO
// 
// = FILENAME
//    cdr.h
//
// = DESCRIPTION
//     Common Data Representation (CDR) marshaling streams.
//
//     This implementation assumes that the native numeric
//     representation is two's complement for integers, IEEE
//     single/double for floats.  Also that characters are in ISO
//     Latin/1.
//
//     Note that CDR itself makes no such assumptions, but this
//     implementation makes such assumptions for reasons of
//     efficiency.  Careful enhancements could preserve that
//     efficiency where the assumptions are true, yet still allow the
//     code to work when they aren't true.
//
//     The implementation expects that buffers are aligned according
//     to the strongest CDR alignment restriction.
//
//     NOTE: this does everything "CDR 1.1" does ... that is, it
//     supports the five extended OMG-IDL data types in UNO Appendix
//     A, which provide richer arithmetic types (64 bit integers,
//     "quad precision" FP) and UNICODE-based characters and strings.
//     Those types are not standard parts of OMG-IDL at this time.
//
//     THREADING NOTE: CDR data structures must be protected against
//     concurrent access by their owning thread.
//
// = AUTHOR
//     Copyright 1994-1995 by Sun Microsystems, Inc.
// 
// ============================================================================

#if !defined (TAO_CDR_H)
#define	TAO_CDR_H

#include <assert.h>
#include "ace/OS.h"

#if defined(__IIOP_BUILD)
#  include "orb.h"
#else
#  include <corba/orb.h>
#endif

#include	<align.h>

// Identify byte order ... this is basically dependent on processor,
// but some processors support different byte orders (e.g. MIPS,
// UltraSPARC, PowerPC) as required for different software
// environments.
//
// We currently get this information through the "configure" script,
// which must (!!) be run before source code can be correctly
// compiled; too bad we have no way to ensure that the machine on
// which "configure" ran is the same as the one on which "make" will
// be run.

#undef	LITTLE_ENDIAN
#undef	BIG_ENDIAN
#undef	MY_BYTE_SEX

// PC compilers normally don't assume they'll be given code that runs
// on other architectures; cope with that limitation once here, so
// that only truly compiler-specific code needs to use their
// predefines.
//
// NOTE:  should really be using "__i386" to be strictly ANSI compliant.
//
#if defined (__BORLANDC__) || defined (_M_IX86)
#	if	!defined (i386)
#		define	i386
#		undef	WORDS_BIGENDIAN
#	endif
#endif

// Yes, we assume no bizarre mixed-endian "nuxi" machine, just as we
// assume only IEEE arithmetic.

#if defined (WORDS_BIGENDIAN)
#	define	BIG_ENDIAN
#	define	MY_BYTE_SEX	0
#else
#	define	LITTLE_ENDIAN
#	define	MY_BYTE_SEX	1
#endif

struct ACE_Svc_Export CDR
  // = TITLE
  // The core marshaling primitive: a memory buffer, into which all the
  // basic OMG-IDL datatypes can be placed ... or from which they can be
  // retreived.
  //
  // = DESCRIPTION
  // A particularly useful static member function for this buffer is an
  // interpretive encoding routine, usable as a typecode interpreter
  // callback.  Ditto for decoding.  These are used to support all
  // OMG-IDL datatypes, even those not supported directly by put/get
  // primitives.
  //
  // Struct members are intentionally exposed; the functionality of this
  // class, and hence the appropriate abstactions for them, hasn't quite
  // settled down enough to settle on fast abstractions that let data be
  // hidden without pointlessly sacrificing speed.
{
  // = Constants defined by the CDR protocol.  

  // By defining these constants as enums we ensure they get inlined
  // and avoid pointless static memory allocations.

  enum 
  {
    // Note that some of these get reused as part of the standard
    // binary format: unsigned is the same size as its signed cousin,
    // float is CDR_LONG_SIZE, and double is CDR_LONGLONG_SIZE.

    SHORT_SIZE = 2,
    LONG_SIZE = 4,
    LONGLONG_SIZE = 8,
    LONGDOUBLE_SIZE = 16,

    MAX_ALIGNMENT = 16,
    // Maximal CDR 1.1 alignment: "quad precision" FP (i.e. "long
    // double", size as above).

    DEFAULT_BUFSIZE = 1430 
    // Ethernet MTU, less headers.  Default buffer size for
    // request/response messages.  These are normally stack-allocated,
    // and tuning may cause you to want to change this value.  The
    // best value depends on your particular application mix; you can
    // also change how buffers grow().  Most remote invocations
    // (statistically) are "small", and the default used here is
    // perhaps larger than most such messages.
    // 
    // If this size is "too small" you need to heap-allocate buffers too
    // often.  "Too large" is mostly a waste of stackspace, but stack
    // frames as large as the system page size (often 4Kb) can easily
    // overrun the "redzone" at the bottom of most VM-based stacks.
  };

  // = ENCODING SUPPORT 

  // Adjust pointers as needed, then store in the native byte order.
  //
  // There exist only routines to put byte, halfword (2 bytes), word
  // (4 bytes), doubleword (8 bytes) and quadword (16 byte) entities,
  // plus the interpretive encoder.

  CORBA_Boolean put_byte (char c);
  CORBA_Boolean put_short (CORBA_Short s);
  CORBA_Boolean put_long (CORBA_Long l);
  CORBA_Boolean put_longlong (const CORBA_LongLong &ll);
  CORBA_Boolean put_char (CORBA_Char c);
  CORBA_Boolean put_wchar (CORBA_WChar wc);
  CORBA_Boolean put_boolean (CORBA_Boolean b);
  CORBA_Boolean	put_octet (CORBA_Octet o);
  CORBA_Boolean	put_ushort (CORBA_UShort s);
  CORBA_Boolean	put_ulong (CORBA_ULong l);
  CORBA_Boolean	put_ulonglong (const CORBA_ULongLong &ll);
  CORBA_Boolean	put_float (float f);
  CORBA_Boolean	put_double (const double &d);
  CORBA_Boolean put_longdouble (CORBA_LongDouble &ld);

  static CORBA_TypeCode::traverse_status encoder (CORBA_TypeCode_ptr tc,
                                                  const void *data,
                                                  const void *,
                                                  void *context,
                                                  CORBA_Environment &env);
  // Marshaling interpreter ... <context> really points to a <CDR>.

  // = DECODING SUPPORT 

  // Same assumptions are made as above, but a flag is tested to
  // determine whether decode should byteswap or not.  It's cheaper to
  // do it that way than to use virtual functions.

  CORBA_Boolean get_byte (char &c);
  CORBA_Boolean get_short (CORBA_Short &s);
  CORBA_Boolean get_long (CORBA_Long &l);
  CORBA_Boolean get_longlong (CORBA_LongLong &ll);
  CORBA_Boolean get_char (CORBA_Char &o);
  CORBA_Boolean get_wchar (CORBA_WChar &wc);
  CORBA_Boolean get_boolean (CORBA_Boolean &b);
  CORBA_Boolean	get_octet (CORBA_Octet &o);
  CORBA_Boolean	get_ushort (CORBA_UShort &s);
  CORBA_Boolean	get_ulong (CORBA_ULong &l);
  CORBA_Boolean	get_ulonglong (const CORBA_ULongLong &ull);
  CORBA_Boolean	get_float (float &f);
  CORBA_Boolean	get_double (double &d);
  CORBA_Boolean get_longdouble (CORBA_LongDouble &ld);

  static CORBA_TypeCode::traverse_status decoder (CORBA_TypeCode_ptr tc,
                                                  const void *data,
                                                  const void *,
                                                  void *context,
                                                  CORBA_Environment &env);
  // Unmarshaling interpreter ... <context> really points to a <CDR>.

  CDR (u_char *buf = 0,
       u_int len = 0,
       int byte_order = MY_BYTE_SEX,
       int consume_buf = 0);
  

  ~CDR (void);

  void *operator new (size_t, void *_FAR p);
  void *operator new (size_t s);
  void operator delete (void *p);

  // = Used mostly when interpreting typecodes.

  // These may change the state of a CDR buffer even when errors are
  // reported.

  CORBA_Boolean skip_string (void);
  CORBA_Boolean skip_bytes (u_int nbytes);
    
  void setup_encapsulation (u_char *buf, u_int len);
  // Also used when interpreting typecodes, but more generally when
  // getting ready to read from encapsulations.  In such cases the
  // buffer alignment guarantees must be provided by the caller, this
  // code doesn't verify them.  These streams are "read only".

  CORBA_Boolean grow (size_t newlength);
  // Grow the buffer to the identified size ... if it's zero, just
  // grow it by a standard quantum (e.g. when encoding we can't know
  // in advance how big it will need to become).

  size_t bytes_remaining (void);
  // Some code needs to know how much is left on encode or decode

  // private:
  //  DATA MEMBERS ...

  u_char *next;		
  // next data goes here

  size_t remaining;	
  // space left

  u_char *real_buffer;	
  // maybe not aligned

  int do_free;
  // Shall we free the memory?

  u_char *buffer;
  // Points to the dynamically allocated memory.

  size_t length;
  // Length of the dynamically allocated memory.

  int do_byteswap;	
  // Decode ONLY.
};

// In this ONE case, we make a substantial exception to how inline
// files are included.  Normally, we would conditionally include the
// inline file iff __ACE_INLINE__ is defined.  But, in the original,
// highly optimized Sun IIOP code, much of what is in the inline file
// was here ready to be inlined at a moments notice and ALWAYS.  So,
// in this ONE file, we defer to David Brownell's considerable prowess
// at creating typecode interpreters as well as to the ACE convention
// of placing inline functions into separate files.
#  if !defined(__ACE_INLINE__)
#    undef ACE_INLINE
#    define ACE_INLINE inline
#    define do_undef_on_ACE_INLINE
#  endif

#  include "cdr.i"

#  if defined(do_undef_on_ACE_INLINE)
#    undef do_undef_on_ACE_INLINE
#    undef ACE_INLINE
#    define ACE_INLINE
#  endif

#endif /* TAO_CDR_H */