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
|
// This may look like C, but it's really -*- C++ -*-
// $Id$
// ============================================================================
//
// = LIBRARY
// TAO
//
// = FILENAME
// CDR_Interpreter.h
//
// = DESCRIPTION
// Header file for TAO's CDR interpreter.
//
// = AUTHOR
// Douglas C. Schmidt
//
// ============================================================================
#ifndef TAO_CDR_INTERPRETER_H
#define TAO_CDR_INTERPRETER_H
#include "tao/corbafwd.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
// Useful typedefs.
typedef size_t TAO_attribute_calculator (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV);
typedef CORBA::Boolean TAO_param_skip_rtn (TAO_InputCDR *);
class TAO_Export TAO_CDR_Interpreter
{
// = TITLE
// TAO's CORBA TypeCode interpreter, which traverses GIOP/CDR
// data structures.
//
// = DESCRIPTION
// This uses the standard C/C++ representation for data, and knows
// how to do things like align and pad according to standard
// rules. It is driven by CDR marshaled representations of
// TypeCodes.
//
// It does two key things: (a) calculate size and alignment
// restrictions for the data type described by any given typecode;
// and (b) "visits" each element of a data type in the order those
// elements are defined in the type's IDL definition.
//
// A typical use is that some application-specific "visit"
// function will be called with a typecode and data value. Then
// that "visit" function may choose to use the interpreter's
// knowledge of the environment's size, padding, and alignment
// rules to help it examine each of the constituents of complex
// data values. It does so by making a call to
// <TypeCode::traverse>, and passing itself for future recursive
// calls.
//
// NOTE that this module has system dependent parts, and so should
// be examined when porting to new CPU architectures, compilers,
// and so forth to make sure it correctly implements the
// appropriate binary interfaces.
//
// Issues of concern are primarily that sizes and representations
// of CORBA primitive data types are correct (key issues are
// verified when the ORB initializes) and that the alignment rules
// are recognized.
//
// Also, exceptions have vtables in them, which may cause trouble
// if they aren't located at the very beginning by the compiler in
// question.
//
// So for example, moving to another CPU architecture which still
// uses standard sized two's complement integers and IEEE floating
// point, and expects "natural" alignment, won't be hard. Even
// using PC style tightly packed data is simple; the alignment
// rules are just simpler. Most volume microprocessors used in
// 1995 are correctly supported.
//
// Using data representations that are far from the standard C/C++
// style data layout is probably not practical with this
// implementation. LISP systems, as one example, probably won't
// use "in-memory" representations much like C/C++, even though
// its "wire form" could directly match CDR.
//
// ALSO, the treatment of exceptions may need to be examined in
// language environments which actually rely on C++ exceptions.
// The RTTI data that identifies exceptions can easily be ignored
// by this interpreter (if it's taught about that compiler's RTTI)
// but it may not be practical for any code not generated by that
// specific C++ compiler to store such data in the right place to
// look like a C++ exception, or to throw exceptions when that's
// needed. (RTTI == "Run Time Typing Information", needed to make
// C++ exceptions work correctly and partially exposed to users by
// the ANSI standards comittee. It provides type-safe
// "downcasting" and other features previously unavailable in
// C++.)
//
// THREADING NOTE: Data structures being traversed should only be
// modified by the thread doing the traversal. The interpretive
// code itself is reentrant (recursive!) so presents no threading
// issues; only the data being fed to the interpreter must be
// protected against concurrency.
public:
static void init (void);
// Initialize TAO's TypeCode table.
static size_t calc_nested_size_and_alignment (CORBA::TypeCode_ptr tc,
TAO_InputCDR *original_stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
static size_t calc_nested_size_and_alignment_i (CORBA::TypeCode_ptr tc,
TAO_InputCDR *stream,
CORBA::TCKind kind,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// For a given typecode, figure out its size and alignment needs.
// This version is used mostly when traversing other typecodes, and
// follows these rules:
//
// - Some typecodes are illegal (can't be nested inside others);
// - Indirections are allowed;
// - The whole typecode (including TCKind enum) is in the stream
//
// When the routine returns, the stream has skipped this TypeCode.
//
// "size" is returned, "alignment" is an 'out' parameter. If it is
// non-null, "tc" is initialized to hold the contents of the TypeCode;
// it depends on the contents of the original stream to be valid.
//
// The _i routine encapsulates some common code for the case were an
// indirected TypeCode is in use.
//
// @@ explore splitting apart returning the size/alignment data and
// the TypeCode initialization; union traversal would benefit a bit,
// but it would need more than that to make it as speedy as struct
// traversal.
// = Static visitor methods.
// These methods manipulate CDR-encapsulated TypeCode parameter
// lists, calculating the size and alignment of the data type being
// described. The TCKind value has always been removed from the CDR
// stream when these calculator routines get called.
static size_t calc_struct_and_except_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA::Boolean is_exception,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Given typecode bytes for a structure (or exception), figure out
// its alignment and size; return size, alignment is an 'out'
// parameter. Only "CORBA::tk_struct" (or "CORBA::tk_except") has
// been taken out of the stream parameter holding the bytes.
//
// We use a one-pass algorithm, calculating size and inter-element
// padding while recording the strongest alignment restriction.
// Then we correct the size to account for tail-padding.
//
// This routine recognizes that exceptions are just structs with
// some additional information. Different environments may differ
// in what that additional information is, so this routine may need
// to be taught about compiler-specific representation of that
// additional "RTTI" data.
static size_t calc_struct_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment for a structure.
#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
static size_t calc_seq_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment for a sequence, most of them have
// the same requirements, but for the sequences of Octets that are
// optimized to minimize copying.
#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
static size_t calc_exception_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment for an exception.
static size_t calc_union_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment for a CORBA discriminated union.
//
// Note that this is really a two-element structure. The first
// element is the discriminator; the second is the value. All normal
// structure padding/alignment rules apply. In particular, all arms
// of the union have the same initial address (adequately aligned for
// any of the members).
static size_t calc_alias_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment for a typedeffed type.
static size_t calc_array_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Calculate size and alignment of an array. (All such arrays are
// described as single dimensional, even though the IDL definition
// may specify a multidimensional array ... such arrays are treated
// as nested single dimensional arrays.)
static CORBA::Boolean match_value (CORBA::TCKind kind,
TAO_InputCDR *tc_stream,
const void *value,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// Cast the discriminant values to the right type and compare them.
static size_t
calc_key_union_attributes (TAO_InputCDR *stream,
size_t &overall_alignment,
size_t &discrim_size_with_pad,
CORBA_Environment &ACE_TRY_ENV =
TAO_default_environment ());
// = Utility routine that checks if a union member is a variable sized type
// (and hence is a pointer)
static int calc_union_attr_is_var_sized_member (TAO_InputCDR *temp,
CORBA::Boolean &flag);
// = Utility routines that skip unneeded parameter lists.
static CORBA::Boolean skip_encapsulation (TAO_InputCDR *stream);
static CORBA::Boolean skip_long (TAO_InputCDR *stream);
struct Table_Element
{
size_t size_;
size_t alignment_;
TAO_attribute_calculator *calc_;
TAO_param_skip_rtn *skipper_;
};
static Table_Element table_[CORBA::TC_KIND_COUNT];
// Table supporting calculation of size and alignment requirements
// for any one instance of a given data types.
//
// This is indexed via CDR's TCKind values, which are "frozen" as
// part of the CDR standard. Entries hold either the size and
// alignment values for that data type, or a pointer to a function
// that is used to calculate those values. Function pointers are
// normally needed only for constructed types.
//
// A "skipper" routine is provided for some data types whose size is
// known statically (e.g. objrefs, structures, strings) but whose
// typecodes have parameters that sometimes need to be ignored when
// found in a CDR stream. Any attribute calculator routine always
// skips parameters in the CDR input stream, so no type with such a
// routine also needs a "skipper".
//
// Rather than growing a set of processor-specific #ifdefs, we
// calculate most of this table (except functions) at ORB
// initialization time.
};
#endif /* TAO_CDR_INTERPRETER_H */
|