Line data Source code
1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : /*
7 : * Structures matching the in-memory representation of typelib structures.
8 : * http://www.mozilla.org/scriptable/typelib_file.html
9 : */
10 :
11 : #ifndef __xpt_struct_h__
12 : #define __xpt_struct_h__
13 :
14 : #include "xpt_arena.h"
15 : #include <stdint.h>
16 :
17 : extern "C" {
18 :
19 : /*
20 : * Originally, I was going to have structures that exactly matched the on-disk
21 : * representation, but that proved difficult: different compilers can pack
22 : * their structs differently, and that makes overlaying them atop a
23 : * read-from-disk byte buffer troublesome. So now I just have some structures
24 : * that are used in memory, and we're going to write a nice XDR library to
25 : * write them to disk and stuff. It is pure joy. -- shaver
26 : */
27 :
28 : /* Structures for the typelib components */
29 :
30 : typedef struct XPTHeader XPTHeader;
31 : typedef struct XPTInterfaceDirectoryEntry XPTInterfaceDirectoryEntry;
32 : typedef struct XPTInterfaceDescriptor XPTInterfaceDescriptor;
33 : typedef struct XPTConstDescriptor XPTConstDescriptor;
34 : typedef struct XPTMethodDescriptor XPTMethodDescriptor;
35 : typedef struct XPTParamDescriptor XPTParamDescriptor;
36 : typedef struct XPTTypeDescriptor XPTTypeDescriptor;
37 : typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
38 :
39 : #ifndef nsID_h__
40 : /*
41 : * We can't include nsID.h, because it's full of C++ goop and we're not doing
42 : * C++ here, so we define our own minimal struct. We protect against multiple
43 : * definitions of this struct, though, and use the same field naming.
44 : */
45 : struct nsID {
46 : uint32_t m0;
47 : uint16_t m1;
48 : uint16_t m2;
49 : uint8_t m3[8];
50 : };
51 :
52 : typedef struct nsID nsID;
53 : #endif
54 :
55 : /*
56 : * Every XPCOM typelib file begins with a header.
57 : */
58 : struct XPTHeader {
59 : // Some of these fields exists in the on-disk format but don't need to be
60 : // stored in memory (other than very briefly, which can be done with local
61 : // variables).
62 :
63 : //uint8_t magic[16];
64 : uint8_t major_version;
65 : uint8_t minor_version;
66 : uint16_t num_interfaces;
67 : //uint32_t file_length;
68 : XPTInterfaceDirectoryEntry *interface_directory;
69 : //uint32_t data_pool;
70 : };
71 :
72 : #define XPT_MAGIC "XPCOM\nTypeLib\r\n\032"
73 : /* For error messages. */
74 : #define XPT_MAGIC_STRING "XPCOM\\nTypeLib\\r\\n\\032"
75 : #define XPT_MAJOR_VERSION 0x01
76 : #define XPT_MINOR_VERSION 0x02
77 :
78 : /* Any file with a major version number of XPT_MAJOR_INCOMPATIBLE_VERSION
79 : * or higher is to be considered incompatible by this version of xpt and
80 : * we will refuse to read it. We will return a header with magic, major and
81 : * minor versions set from the file. num_interfaces will be set to zero to
82 : * confirm our inability to read the file; i.e. even if some client of this
83 : * library gets out of sync with us regarding the agreed upon value for
84 : * XPT_MAJOR_INCOMPATIBLE_VERSION, anytime num_interfaces is zero we *know*
85 : * that this library refused to read the file due to version incompatibility.
86 : */
87 : #define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02
88 :
89 : /*
90 : * A contiguous array of fixed-size InterfaceDirectoryEntry records begins at
91 : * the byte offset identified by the interface_directory field in the file
92 : * header. The array is used to quickly locate an interface description
93 : * using its IID. No interface should appear more than once in the array.
94 : */
95 : struct XPTInterfaceDirectoryEntry {
96 : nsID iid;
97 : char *name;
98 :
99 : // This field exists in the on-disk format. But it isn't used so we don't
100 : // allocate space for it in memory.
101 : //char *name_space;
102 :
103 : XPTInterfaceDescriptor *interface_descriptor;
104 : };
105 :
106 : /*
107 : * An InterfaceDescriptor describes a single XPCOM interface, including all of
108 : * its methods.
109 : */
110 : struct XPTInterfaceDescriptor {
111 : /* This field ordering minimizes the size of this struct.
112 : * The fields are serialized on disk in a different order.
113 : * See DoInterfaceDescriptor().
114 : */
115 : XPTMethodDescriptor *method_descriptors;
116 : XPTConstDescriptor *const_descriptors;
117 : XPTTypeDescriptor *additional_types;
118 : uint16_t parent_interface;
119 : uint16_t num_methods;
120 : uint16_t num_constants;
121 : uint8_t flags;
122 :
123 : /* additional_types are used for arrays where we may need multiple
124 : * XPTTypeDescriptors for a single XPTMethodDescriptor. Since we still
125 : * want to have a simple array of XPTMethodDescriptor (each with a single
126 : * embedded XPTTypeDescriptor), a XPTTypeDescriptor can have a reference
127 : * to an 'additional_type'. That reference is an index in this
128 : * "additional_types" array. So a given XPTMethodDescriptor might have
129 : * a whole chain of these XPTTypeDescriptors to represent, say, a multi
130 : * dimensional array.
131 : *
132 : * Note that in the typelib file these additional types are stored 'inline'
133 : * in the MethodDescriptor. But, in the typelib MethodDescriptors can be
134 : * of varying sizes, where in XPT's in memory mapping of the data we want
135 : * them to be of fixed size. This additional_types scheme is here to allow
136 : * for that.
137 : */
138 : uint8_t num_additional_types;
139 : };
140 :
141 : #define XPT_ID_SCRIPTABLE 0x80
142 : #define XPT_ID_FUNCTION 0x40
143 : #define XPT_ID_BUILTINCLASS 0x20
144 : #define XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY 0x10
145 : #define XPT_ID_FLAGMASK 0xf0
146 :
147 : #define XPT_ID_IS_SCRIPTABLE(flags) (!!(flags & XPT_ID_SCRIPTABLE))
148 : #define XPT_ID_IS_FUNCTION(flags) (!!(flags & XPT_ID_FUNCTION))
149 : #define XPT_ID_IS_BUILTINCLASS(flags) (!!(flags & XPT_ID_BUILTINCLASS))
150 : #define XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(flags) (!!(flags & XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY))
151 :
152 : /*
153 : * A TypeDescriptor is a variable-size record used to identify the type of a
154 : * method argument or return value.
155 : *
156 : * There are three types of TypeDescriptors:
157 : *
158 : * SimpleTypeDescriptor
159 : * InterfaceTypeDescriptor
160 : * InterfaceIsTypeDescriptor
161 : *
162 : * The tag field in the prefix indicates which of the variant TypeDescriptor
163 : * records is being used, and hence the way any remaining fields should be
164 : * parsed. Values from 0 to 17 refer to SimpleTypeDescriptors. The value 18
165 : * designates an InterfaceTypeDescriptor, while 19 represents an
166 : * InterfaceIsTypeDescriptor.
167 : */
168 :
169 : /* why bother with a struct? - other code relies on this being a struct */
170 189876 : struct XPTTypeDescriptorPrefix {
171 : uint8_t flags;
172 : };
173 :
174 : /* flag bits */
175 :
176 : #define XPT_TDP_FLAGMASK 0xe0
177 : #define XPT_TDP_TAGMASK (~XPT_TDP_FLAGMASK)
178 : #define XPT_TDP_TAG(tdp) ((tdp).flags & XPT_TDP_TAGMASK)
179 :
180 : /*
181 : * The following enum maps mnemonic names to the different numeric values
182 : * of XPTTypeDescriptor->tag.
183 : */
184 : enum XPTTypeDescriptorTags {
185 : TD_INT8 = 0,
186 : TD_INT16 = 1,
187 : TD_INT32 = 2,
188 : TD_INT64 = 3,
189 : TD_UINT8 = 4,
190 : TD_UINT16 = 5,
191 : TD_UINT32 = 6,
192 : TD_UINT64 = 7,
193 : TD_FLOAT = 8,
194 : TD_DOUBLE = 9,
195 : TD_BOOL = 10,
196 : TD_CHAR = 11,
197 : TD_WCHAR = 12,
198 : TD_VOID = 13,
199 : TD_PNSIID = 14,
200 : TD_DOMSTRING = 15,
201 : TD_PSTRING = 16,
202 : TD_PWSTRING = 17,
203 : TD_INTERFACE_TYPE = 18,
204 : TD_INTERFACE_IS_TYPE = 19,
205 : TD_ARRAY = 20,
206 : TD_PSTRING_SIZE_IS = 21,
207 : TD_PWSTRING_SIZE_IS = 22,
208 : TD_UTF8STRING = 23,
209 : TD_CSTRING = 24,
210 : TD_ASTRING = 25,
211 : TD_JSVAL = 26
212 : };
213 :
214 : struct XPTTypeDescriptor {
215 : XPTTypeDescriptorPrefix prefix;
216 :
217 : // The memory layout here doesn't exactly match (for the appropriate types)
218 : // the on-disk format. This is to save memory.
219 : union {
220 : // Used for TD_INTERFACE_IS_TYPE.
221 : struct {
222 : uint8_t argnum;
223 : } interface_is;
224 :
225 : // Used for TD_PSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS.
226 : struct {
227 : uint8_t argnum;
228 : //uint8_t argnum2; // Present on disk, omitted here.
229 : } pstring_is;
230 :
231 : // Used for TD_ARRAY.
232 : struct {
233 : uint8_t argnum;
234 : //uint8_t argnum2; // Present on disk, omitted here.
235 : uint8_t additional_type; // uint16_t on disk, uint8_t here;
236 : // in practice it never exceeds 20.
237 : } array;
238 :
239 : // Used for TD_INTERFACE_TYPE.
240 : struct {
241 : // We store the 16-bit iface value as two 8-bit values in order to
242 : // avoid 16-bit alignment requirements for XPTTypeDescriptor, which
243 : // reduces its size and also the size of XPTParamDescriptor.
244 : uint8_t iface_hi8;
245 : uint8_t iface_lo8;
246 : } iface;
247 : } u;
248 : };
249 :
250 : /*
251 : * A ConstDescriptor is a variable-size record that records the name and
252 : * value of a scoped interface constant.
253 : *
254 : * The types of the method parameter are restricted to the following subset
255 : * of TypeDescriptors:
256 : *
257 : * int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
258 : * int64_t, uint64_t, wchar_t, char
259 : *
260 : * The type (and thus the size) of the value record is determined by the
261 : * contents of the associated TypeDescriptor record. For instance, if type
262 : * corresponds to int16_t, then value is a two-byte record consisting of a
263 : * 16-bit signed integer.
264 : */
265 : union XPTConstValue {
266 : int8_t i8;
267 : uint8_t ui8;
268 : int16_t i16;
269 : uint16_t ui16;
270 : int32_t i32;
271 : uint32_t ui32;
272 : int64_t i64;
273 : uint64_t ui64;
274 : char ch;
275 : uint16_t wch;
276 : }; /* varies according to type */
277 :
278 : struct XPTConstDescriptor {
279 : char *name;
280 : XPTTypeDescriptor type;
281 : union XPTConstValue value;
282 : };
283 :
284 : /*
285 : * A ParamDescriptor is a variable-size record used to describe either a
286 : * single argument to a method or a method's result.
287 : */
288 167000 : struct XPTParamDescriptor {
289 : uint8_t flags;
290 : XPTTypeDescriptor type;
291 : };
292 :
293 : /* flag bits */
294 : #define XPT_PD_IN 0x80
295 : #define XPT_PD_OUT 0x40
296 : #define XPT_PD_RETVAL 0x20
297 : #define XPT_PD_SHARED 0x10
298 : #define XPT_PD_DIPPER 0x08
299 : #define XPT_PD_OPTIONAL 0x04
300 : #define XPT_PD_FLAGMASK 0xfc
301 :
302 : #define XPT_PD_IS_IN(flags) (flags & XPT_PD_IN)
303 : #define XPT_PD_IS_OUT(flags) (flags & XPT_PD_OUT)
304 : #define XPT_PD_IS_RETVAL(flags) (flags & XPT_PD_RETVAL)
305 : #define XPT_PD_IS_SHARED(flags) (flags & XPT_PD_SHARED)
306 : #define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
307 : #define XPT_PD_IS_OPTIONAL(flags) (flags & XPT_PD_OPTIONAL)
308 :
309 : /*
310 : * A MethodDescriptor is a variable-size record used to describe a single
311 : * interface method.
312 : */
313 : struct XPTMethodDescriptor {
314 : char *name;
315 : XPTParamDescriptor *params;
316 : XPTParamDescriptor result;
317 : uint8_t flags;
318 : uint8_t num_args;
319 : };
320 :
321 : /* flag bits */
322 : #define XPT_MD_GETTER 0x80
323 : #define XPT_MD_SETTER 0x40
324 : #define XPT_MD_NOTXPCOM 0x20
325 : #define XPT_MD_HIDDEN 0x08
326 : #define XPT_MD_OPT_ARGC 0x04
327 : #define XPT_MD_CONTEXT 0x02
328 : #define XPT_MD_FLAGMASK 0xfe
329 :
330 : #define XPT_MD_IS_GETTER(flags) (flags & XPT_MD_GETTER)
331 : #define XPT_MD_IS_SETTER(flags) (flags & XPT_MD_SETTER)
332 : #define XPT_MD_IS_NOTXPCOM(flags) (flags & XPT_MD_NOTXPCOM)
333 : #define XPT_MD_IS_HIDDEN(flags) (flags & XPT_MD_HIDDEN)
334 : #define XPT_MD_WANTS_OPT_ARGC(flags) (flags & XPT_MD_OPT_ARGC)
335 : #define XPT_MD_WANTS_CONTEXT(flags) (flags & XPT_MD_CONTEXT)
336 :
337 : /*
338 : * Annotation records are variable-size records used to store secondary
339 : * information about the typelib, e.g. such as the name of the tool that
340 : * generated the typelib file, the date it was generated, etc. The
341 : * information is stored with very loose format requirements so as to
342 : * allow virtually any private data to be stored in the typelib.
343 : *
344 : * There are two types of Annotations:
345 : *
346 : * EmptyAnnotation
347 : * PrivateAnnotation
348 : *
349 : * The tag field of the prefix discriminates among the variant record
350 : * types for Annotation's. If the tag is 0, this record is an
351 : * EmptyAnnotation. EmptyAnnotation's are ignored - they're only used to
352 : * indicate an array of Annotation's that's completely empty. If the tag
353 : * is 1, the record is a PrivateAnnotation.
354 : *
355 : * We don't actually store annotations; we just skip over them if they are
356 : * present.
357 : */
358 :
359 : #define XPT_ANN_LAST 0x80
360 : #define XPT_ANN_IS_LAST(flags) (flags & XPT_ANN_LAST)
361 : #define XPT_ANN_PRIVATE 0x40
362 : #define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
363 :
364 : }
365 :
366 : #endif /* __xpt_struct_h__ */
|