tenfourfox/xpcom/typelib/xpt/xpt_struct.cpp
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

912 lines
26 KiB
C++

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Implementation of XDR routines for typelib structures. */
#include "xpt_xdr.h"
#include "xpt_struct.h"
#include <string.h>
#include <stdio.h>
/***************************************************************************/
/* Forward declarations. */
static uint32_t
SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id);
static uint32_t
SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id);
static uint32_t
SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id);
static uint32_t
SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id);
static PRBool
DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
XPTInterfaceDirectoryEntry *ide, uint16_t entry_index);
static PRBool
DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id);
static PRBool
DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id);
static PRBool
DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp);
static PRBool
DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer, XPTInterfaceDescriptor **idp);
static PRBool
DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp);
static PRBool
DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id);
static PRBool
DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id);
/***************************************************************************/
XPT_PUBLIC_API(uint32_t)
XPT_SizeOfHeader(XPTHeader *header)
{
XPTAnnotation *ann, *last;
uint32_t size = 16 /* magic */ +
1 /* major */ + 1 /* minor */ +
2 /* num_interfaces */ + 4 /* file_length */ +
4 /* interface_directory */ + 4 /* data_pool */;
ann = header->annotations;
do {
size += 1; /* Annotation prefix */
if (XPT_ANN_IS_PRIVATE(ann->flags))
size += 2 + ann->creator->length + 2 + ann->private_data->length;
last = ann;
ann = ann->next;
} while (!XPT_ANN_IS_LAST(last->flags));
return size;
}
XPT_PUBLIC_API(uint32_t)
XPT_SizeOfHeaderBlock(XPTHeader *header)
{
uint32_t ide_size = 16 /* IID */ + 4 /* name */ +
4 /* namespace */ + 4 /* descriptor */;
return XPT_SizeOfHeader(header) + header->num_interfaces * ide_size;
}
XPT_PUBLIC_API(XPTHeader *)
XPT_NewHeader(XPTArena *arena, uint16_t num_interfaces, uint8_t major_version, uint8_t minor_version)
{
XPTHeader *header = XPT_NEWZAP(arena, XPTHeader);
if (!header)
return NULL;
memcpy(header->magic, XPT_MAGIC, 16);
header->major_version = major_version;
header->minor_version = minor_version;
header->num_interfaces = num_interfaces;
if (num_interfaces) {
header->interface_directory =
(XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena,
num_interfaces * sizeof(XPTInterfaceDirectoryEntry));
if (!header->interface_directory) {
XPT_DELETE(arena, header);
return NULL;
}
}
header->data_pool = 0; /* XXX do we even need this struct any more? */
return header;
}
XPT_PUBLIC_API(void)
XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader)
{
if (aHeader) {
XPTAnnotation* ann;
XPTInterfaceDirectoryEntry* entry = aHeader->interface_directory;
XPTInterfaceDirectoryEntry* end = entry + aHeader->num_interfaces;
for (; entry < end; entry++) {
XPT_DestroyInterfaceDirectoryEntry(arena, entry);
}
ann = aHeader->annotations;
while (ann) {
XPTAnnotation* next = ann->next;
if (XPT_ANN_IS_PRIVATE(ann->flags)) {
XPT_FREEIF(arena, ann->creator);
XPT_FREEIF(arena, ann->private_data);
}
XPT_DELETE(arena, ann);
ann = next;
}
XPT_FREEIF(arena, aHeader->interface_directory);
XPT_DELETE(arena, aHeader);
}
}
XPT_PUBLIC_API(PRBool)
XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, uint32_t * ide_offset)
{
XPTMode mode = cursor->state->mode;
unsigned int i;
XPTHeader * header;
if (mode == XPT_DECODE) {
header = XPT_NEWZAP(arena, XPTHeader);
if (!header)
return PR_FALSE;
*headerp = header;
} else {
header = *headerp;
}
if (mode == XPT_ENCODE) {
/* IDEs appear after header, including annotations */
if (ide_offset != NULL)
{
*ide_offset = XPT_SizeOfHeader(*headerp) + 1; /* one-based offset */
}
header->data_pool = XPT_SizeOfHeaderBlock(*headerp);
XPT_SetDataOffset(cursor->state, header->data_pool);
}
for (i = 0; i < sizeof(header->magic); i++) {
if (!XPT_Do8(cursor, &header->magic[i]))
goto error;
}
if (mode == XPT_DECODE &&
strncmp((const char*)header->magic, XPT_MAGIC, 16) != 0)
{
/* Require that the header contain the proper magic */
fprintf(stderr,
"libxpt: bad magic header in input file; "
"found '%s', expected '%s'\n",
header->magic, XPT_MAGIC_STRING);
goto error;
}
if (!XPT_Do8(cursor, &header->major_version) ||
!XPT_Do8(cursor, &header->minor_version)) {
goto error;
}
if (mode == XPT_DECODE &&
header->major_version >= XPT_MAJOR_INCOMPATIBLE_VERSION) {
/* This file is newer than we are and set to an incompatible version
* number. We must set the header state thusly and return.
*/
header->num_interfaces = 0;
header->file_length = 0;
return PR_TRUE;
}
if (!XPT_Do16(cursor, &header->num_interfaces) ||
!XPT_Do32(cursor, &header->file_length) ||
(ide_offset != NULL && !XPT_Do32(cursor, ide_offset))) {
goto error;
}
return PR_TRUE;
/* XXX need to free child data sometimes! */
XPT_ERROR_HANDLE(arena, header);
}
XPT_PUBLIC_API(PRBool)
XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
{
XPTMode mode = cursor->state->mode;
XPTHeader * header;
uint32_t ide_offset;
int i;
XPTAnnotation *ann, *next, **annp;
if (!XPT_DoHeaderPrologue(arena, cursor, headerp, &ide_offset))
return PR_FALSE;
header = *headerp;
/*
* Make sure the file length reported in the header is the same size as
* as our buffer unless it is zero (not set)
*/
if (mode == XPT_DECODE && (header->file_length != 0 &&
cursor->state->pool->allocated < header->file_length)) {
fputs("libxpt: File length in header does not match actual length. File may be corrupt\n",
stderr);
goto error;
}
if (mode == XPT_ENCODE)
XPT_DataOffset(cursor->state, &header->data_pool);
if (!XPT_Do32(cursor, &header->data_pool))
goto error;
if (mode == XPT_DECODE)
XPT_DataOffset(cursor->state, &header->data_pool);
if (mode == XPT_DECODE && header->num_interfaces) {
header->interface_directory =
(XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, header->num_interfaces *
sizeof(XPTInterfaceDirectoryEntry));
if (!header->interface_directory)
goto error;
}
/*
* Iterate through the annotations rather than recurring, to avoid blowing
* the stack on large xpt files.
*/
ann = next = header->annotations;
annp = &header->annotations;
do {
ann = next;
if (!DoAnnotation(arena, cursor, &ann))
goto error;
if (mode == XPT_DECODE) {
/*
* Make sure that we store the address of the newly allocated
* annotation in the previous annotation's ``next'' slot, or
* header->annotations for the first one.
*/
*annp = ann;
annp = &ann->next;
}
next = ann->next;
} while (!XPT_ANN_IS_LAST(ann->flags));
/* shouldn't be necessary now, but maybe later */
XPT_SeekTo(cursor, ide_offset);
for (i = 0; i < header->num_interfaces; i++) {
if (!DoInterfaceDirectoryEntry(arena, cursor,
&header->interface_directory[i],
(uint16_t)(i + 1)))
goto error;
}
return PR_TRUE;
/* XXX need to free child data sometimes! */
XPT_ERROR_HANDLE(arena, header);
}
XPT_PUBLIC_API(PRBool)
XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry *ide,
nsID *iid, const char *name,
const char *name_space,
XPTInterfaceDescriptor *descriptor)
{
XPT_COPY_IID(ide->iid, *iid);
ide->name = name ? XPT_STRDUP(arena, name) : NULL; /* what good is it w/o a name? */
ide->name_space = name_space ? XPT_STRDUP(arena, name_space) : NULL;
ide->interface_descriptor = descriptor;
return PR_TRUE;
}
XPT_PUBLIC_API(void)
XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry* ide)
{
if (ide) {
if (ide->name) XPT_FREE(arena, ide->name);
if (ide->name_space) XPT_FREE(arena, ide->name_space);
XPT_FreeInterfaceDescriptor(arena, ide->interface_descriptor);
}
}
/* InterfaceDirectoryEntry records go in the header */
PRBool
DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
XPTInterfaceDirectoryEntry *ide, uint16_t entry_index)
{
XPTMode mode = cursor->state->mode;
/* write the IID in our cursor space */
if (!XPT_DoIID(cursor, &(ide->iid)) ||
/* write the name string in the data pool, and the offset in our
cursor space */
!XPT_DoCString(arena, cursor, &(ide->name)) ||
/* write the name_space string in the data pool, and the offset in our
cursor space */
!XPT_DoCString(arena, cursor, &(ide->name_space)) ||
/* do InterfaceDescriptors -- later, only on encode (see below) */
!DoInterfaceDescriptor(arena, cursor, &ide->interface_descriptor)) {
goto error;
}
if (mode == XPT_DECODE)
XPT_SetOffsetForAddr(cursor, ide, entry_index);
return PR_TRUE;
XPT_ERROR_HANDLE(arena, ide);
}
XPT_PUBLIC_API(XPTInterfaceDescriptor *)
XPT_NewInterfaceDescriptor(XPTArena *arena,
uint16_t parent_interface, uint16_t num_methods,
uint16_t num_constants, uint8_t flags)
{
XPTInterfaceDescriptor *id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
if (!id)
return NULL;
if (num_methods) {
id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, num_methods *
sizeof(XPTMethodDescriptor));
if (!id->method_descriptors)
goto free_id;
id->num_methods = num_methods;
}
if (num_constants) {
id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, num_constants *
sizeof(XPTConstDescriptor));
if (!id->const_descriptors)
goto free_meth;
id->num_constants = num_constants;
}
if (parent_interface) {
id->parent_interface = parent_interface;
} else {
id->parent_interface = 0;
}
id->flags = flags;
return id;
free_meth:
XPT_FREEIF(arena, id->method_descriptors);
free_id:
XPT_DELETE(arena, id);
return NULL;
}
XPT_PUBLIC_API(void)
XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id)
{
if (id) {
XPTMethodDescriptor *md, *mdend;
XPTConstDescriptor *cd, *cdend;
/* Free up method descriptors */
md = id->method_descriptors;
mdend = md + id->num_methods;
for (; md < mdend; md++) {
XPT_FREEIF(arena, md->name);
XPT_FREEIF(arena, md->params);
}
XPT_FREEIF(arena, id->method_descriptors);
/* Free up const descriptors */
cd = id->const_descriptors;
cdend = cd + id->num_constants;
for (; cd < cdend; cd++) {
XPT_FREEIF(arena, cd->name);
}
XPT_FREEIF(arena, id->const_descriptors);
/* Free up type descriptors */
XPT_FREEIF(arena, id->additional_types);
XPT_DELETE(arena, id);
}
}
XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num)
{
XPTTypeDescriptor *old = id->additional_types;
XPTTypeDescriptor *new_;
size_t old_size = id->num_additional_types * sizeof(XPTTypeDescriptor);
size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
/* XXX should grow in chunks to minimize alloc overhead */
new_ = (XPTTypeDescriptor*)XPT_CALLOC(arena, new_size);
if (!new_)
return PR_FALSE;
if (old) {
if (old_size)
memcpy(new_, old, old_size);
XPT_FREE(arena, old);
}
id->additional_types = new_;
id->num_additional_types += num;
return PR_TRUE;
}
XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num)
{
XPTMethodDescriptor *old = id->method_descriptors;
XPTMethodDescriptor *new_;
size_t old_size = id->num_methods * sizeof(XPTMethodDescriptor);
size_t new_size = (num * sizeof(XPTMethodDescriptor)) + old_size;
/* XXX should grow in chunks to minimize alloc overhead */
new_ = (XPTMethodDescriptor*)XPT_CALLOC(arena, new_size);
if (!new_)
return PR_FALSE;
if (old) {
if (old_size)
memcpy(new_, old, old_size);
XPT_FREE(arena, old);
}
id->method_descriptors = new_;
id->num_methods += num;
return PR_TRUE;
}
XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num)
{
XPTConstDescriptor *old = id->const_descriptors;
XPTConstDescriptor *new_;
size_t old_size = id->num_constants * sizeof(XPTConstDescriptor);
size_t new_size = (num * sizeof(XPTConstDescriptor)) + old_size;
/* XXX should grow in chunks to minimize alloc overhead */
new_ = (XPTConstDescriptor*)XPT_CALLOC(arena, new_size);
if (!new_)
return PR_FALSE;
if (old) {
if (old_size)
memcpy(new_, old, old_size);
XPT_FREE(arena, old);
}
id->const_descriptors = new_;
id->num_constants += num;
return PR_TRUE;
}
uint32_t
SizeOfTypeDescriptor(XPTTypeDescriptor *td, XPTInterfaceDescriptor *id)
{
uint32_t size = 1; /* prefix */
switch (XPT_TDP_TAG(td->prefix)) {
case TD_INTERFACE_TYPE:
size += 2; /* interface_index */
break;
case TD_INTERFACE_IS_TYPE:
size += 1; /* argnum */
break;
case TD_ARRAY:
size += 2 + SizeOfTypeDescriptor(
&id->additional_types[td->type.additional_type], id);
break;
case TD_PSTRING_SIZE_IS:
size += 2; /* argnum + argnum2 */
break;
case TD_PWSTRING_SIZE_IS:
size += 2; /* argnum + argnum2 */
break;
default:
/* nothing special */
break;
}
return size;
}
uint32_t
SizeOfMethodDescriptor(XPTMethodDescriptor *md, XPTInterfaceDescriptor *id)
{
uint32_t i, size = 1 /* flags */ + 4 /* name */ + 1 /* num_args */;
for (i = 0; i < md->num_args; i++)
size += 1 + SizeOfTypeDescriptor(&md->params[i].type, id);
size += 1 + SizeOfTypeDescriptor(&md->result.type, id);
return size;
}
uint32_t
SizeOfConstDescriptor(XPTConstDescriptor *cd, XPTInterfaceDescriptor *id)
{
uint32_t size = 4 /* name */ + SizeOfTypeDescriptor(&cd->type, id);
switch (XPT_TDP_TAG(cd->type.prefix)) {
case TD_INT8:
case TD_UINT8:
case TD_CHAR:
size ++;
break;
case TD_INT16:
case TD_UINT16:
case TD_WCHAR:
size += 2;
break;
case TD_INT32:
case TD_UINT32:
case TD_PSTRING:
size += 4;
break;
case TD_INT64:
case TD_UINT64:
size += 8;
break;
default:
fprintf(stderr, "libxpt: illegal type in ConstDescriptor: 0x%02x\n",
XPT_TDP_TAG(cd->type.prefix));
return 0;
}
return size;
}
uint32_t
SizeOfInterfaceDescriptor(XPTInterfaceDescriptor *id)
{
uint32_t size = 2 /* parent interface */ + 2 /* num_methods */
+ 2 /* num_constants */ + 1 /* flags */, i;
for (i = 0; i < id->num_methods; i++)
size += SizeOfMethodDescriptor(&id->method_descriptors[i], id);
for (i = 0; i < id->num_constants; i++)
size += SizeOfConstDescriptor(&id->const_descriptors[i], id);
return size;
}
PRBool
DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
XPTInterfaceDescriptor **idp)
{
XPTMode mode = outer->state->mode;
XPTInterfaceDescriptor *id;
XPTCursor curs, *cursor = &curs;
uint32_t i, id_sz = 0;
if (mode == XPT_DECODE) {
id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
if (!id)
return PR_FALSE;
*idp = id;
} else {
id = *idp;
if (!id) {
id_sz = 0;
return XPT_Do32(outer, &id_sz);
}
id_sz = SizeOfInterfaceDescriptor(id);
}
if (!XPT_MakeCursor(outer->state, XPT_DATA, id_sz, cursor))
goto error;
if (!XPT_Do32(outer, &cursor->offset))
goto error;
if (mode == XPT_DECODE && !cursor->offset) {
XPT_DELETE(arena, *idp);
return PR_TRUE;
}
if(!XPT_Do16(cursor, &id->parent_interface) ||
!XPT_Do16(cursor, &id->num_methods)) {
goto error;
}
if (mode == XPT_DECODE && id->num_methods) {
id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, id->num_methods *
sizeof(XPTMethodDescriptor));
if (!id->method_descriptors)
goto error;
}
for (i = 0; i < id->num_methods; i++) {
if (!DoMethodDescriptor(arena, cursor, &id->method_descriptors[i], id))
goto error;
}
if (!XPT_Do16(cursor, &id->num_constants)) {
goto error;
}
if (mode == XPT_DECODE && id->num_constants) {
id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, id->num_constants *
sizeof(XPTConstDescriptor));
if (!id->const_descriptors)
goto error;
}
for (i = 0; i < id->num_constants; i++) {
if (!DoConstDescriptor(arena, cursor, &id->const_descriptors[i], id)) {
goto error;
}
}
if (!XPT_Do8(cursor, &id->flags)) {
goto error;
}
return PR_TRUE;
XPT_ERROR_HANDLE(arena, id);
}
PRBool
DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
XPTInterfaceDescriptor *id)
{
PRBool ok = PR_FALSE;
if (!XPT_DoCString(arena, cursor, &cd->name) ||
!DoTypeDescriptor(arena, cursor, &cd->type, id)) {
return PR_FALSE;
}
switch(XPT_TDP_TAG(cd->type.prefix)) {
case TD_INT8:
ok = XPT_Do8(cursor, (uint8_t*) &cd->value.i8);
break;
case TD_INT16:
ok = XPT_Do16(cursor, (uint16_t*) &cd->value.i16);
break;
case TD_INT32:
ok = XPT_Do32(cursor, (uint32_t*) &cd->value.i32);
break;
case TD_INT64:
ok = XPT_Do64(cursor, &cd->value.i64);
break;
case TD_UINT8:
ok = XPT_Do8(cursor, &cd->value.ui8);
break;
case TD_UINT16:
ok = XPT_Do16(cursor, &cd->value.ui16);
break;
case TD_UINT32:
ok = XPT_Do32(cursor, &cd->value.ui32);
break;
case TD_UINT64:
ok = XPT_Do64(cursor, (int64_t *)&cd->value.ui64);
break;
case TD_CHAR:
ok = XPT_Do8(cursor, (uint8_t*) &cd->value.ch);
break;
case TD_WCHAR:
ok = XPT_Do16(cursor, &cd->value.wch);
break;
/* fall-through */
default:
fprintf(stderr, "illegal type!\n");
break;
}
return ok;
}
XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena, XPTMethodDescriptor *meth,
uint8_t flags, const char *name, uint8_t num_args)
{
meth->flags = flags & XPT_MD_FLAGMASK;
meth->name = XPT_STRDUP(arena, name);
if (!meth->name)
return PR_FALSE;
meth->num_args = num_args;
if (num_args) {
meth->params = (XPTParamDescriptor*)XPT_CALLOC(arena, num_args * sizeof(XPTParamDescriptor));
if (!meth->params)
goto free_name;
} else {
meth->params = NULL;
}
return PR_TRUE;
XPT_DELETE(arena, meth->params);
free_name:
XPT_DELETE(arena, meth->name);
return PR_FALSE;
}
PRBool
DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
XPTInterfaceDescriptor *id)
{
XPTMode mode = cursor->state->mode;
int i;
if (!XPT_Do8(cursor, &md->flags) ||
!XPT_DoCString(arena, cursor, &md->name) ||
!XPT_Do8(cursor, &md->num_args))
return PR_FALSE;
if (mode == XPT_DECODE && md->num_args) {
md->params = (XPTParamDescriptor*)XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
if (!md->params)
return PR_FALSE;
}
for(i = 0; i < md->num_args; i++) {
if (!DoParamDescriptor(arena, cursor, &md->params[i], id))
goto error;
}
if (!DoParamDescriptor(arena, cursor, &md->result, id))
goto error;
return PR_TRUE;
XPT_ERROR_HANDLE(arena, md->params);
}
XPT_PUBLIC_API(PRBool)
XPT_FillParamDescriptor(XPTArena *arena, XPTParamDescriptor *pd, uint8_t flags,
XPTTypeDescriptor *type)
{
pd->flags = flags & XPT_PD_FLAGMASK;
XPT_COPY_TYPE(pd->type, *type);
return PR_TRUE;
}
PRBool
DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
XPTInterfaceDescriptor *id)
{
if (!XPT_Do8(cursor, &pd->flags) ||
!DoTypeDescriptor(arena, cursor, &pd->type, id))
return PR_FALSE;
return PR_TRUE;
}
PRBool
DoTypeDescriptorPrefix(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptorPrefix *tdp)
{
return XPT_Do8(cursor, &tdp->flags);
}
PRBool
DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
XPTInterfaceDescriptor *id)
{
if (!DoTypeDescriptorPrefix(arena, cursor, &td->prefix)) {
goto error;
}
switch (XPT_TDP_TAG(td->prefix)) {
case TD_INTERFACE_TYPE:
if (!XPT_Do16(cursor, &td->type.iface))
goto error;
break;
case TD_INTERFACE_IS_TYPE:
if (!XPT_Do8(cursor, &td->argnum))
goto error;
break;
case TD_ARRAY:
if (!XPT_Do8(cursor, &td->argnum) ||
!XPT_Do8(cursor, &td->argnum2))
goto error;
if (cursor->state->mode == XPT_DECODE) {
if(!XPT_InterfaceDescriptorAddTypes(arena, id, 1))
goto error;
td->type.additional_type = id->num_additional_types - 1;
}
if (!DoTypeDescriptor(arena, cursor,
&id->additional_types[td->type.additional_type],
id))
goto error;
break;
case TD_PSTRING_SIZE_IS:
case TD_PWSTRING_SIZE_IS:
if (!XPT_Do8(cursor, &td->argnum) ||
!XPT_Do8(cursor, &td->argnum2))
goto error;
break;
default:
/* nothing special */
break;
}
return PR_TRUE;
XPT_ERROR_HANDLE(arena, td);
}
XPT_PUBLIC_API(XPTAnnotation *)
XPT_NewAnnotation(XPTArena *arena, uint8_t flags, XPTString *creator,
XPTString *private_data)
{
XPTAnnotation *ann = XPT_NEWZAP(arena, XPTAnnotation);
if (!ann)
return NULL;
ann->flags = flags;
if (XPT_ANN_IS_PRIVATE(flags)) {
ann->creator = creator;
ann->private_data = private_data;
}
return ann;
}
PRBool
DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
{
XPTMode mode = cursor->state->mode;
XPTAnnotation *ann;
if (mode == XPT_DECODE) {
ann = XPT_NEWZAP(arena, XPTAnnotation);
if (!ann)
return PR_FALSE;
*annp = ann;
} else {
ann = *annp;
}
if (!XPT_Do8(cursor, &ann->flags))
goto error;
if (XPT_ANN_IS_PRIVATE(ann->flags)) {
if (!XPT_DoStringInline(arena, cursor, &ann->creator) ||
!XPT_DoStringInline(arena, cursor, &ann->private_data))
goto error_2;
}
return PR_TRUE;
error_2:
if (ann && XPT_ANN_IS_PRIVATE(ann->flags)) {
XPT_FREEIF(arena, ann->creator);
XPT_FREEIF(arena, ann->private_data);
}
XPT_ERROR_HANDLE(arena, ann);
}
PRBool
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
uint16_t num_interfaces, const char *name,
uint16_t *indexp)
{
int i;
for (i=1; i<=num_interfaces; i++) {
fprintf(stderr, "%s == %s ?\n", ide_block[i].name, name);
if (strcmp(ide_block[i].name, name) == 0) {
*indexp = i;
return PR_TRUE;
}
}
indexp = 0;
return PR_FALSE;
}
static XPT_TYPELIB_VERSIONS_STRUCT versions[] = XPT_TYPELIB_VERSIONS;
#define XPT_TYPELIB_VERSIONS_COUNT (sizeof(versions) / sizeof(versions[0]))
XPT_PUBLIC_API(uint16_t)
XPT_ParseVersionString(const char* str, uint8_t* major, uint8_t* minor)
{
unsigned int i;
for (i = 0; i < XPT_TYPELIB_VERSIONS_COUNT; i++) {
if (!strcmp(versions[i].str, str)) {
*major = versions[i].major;
*minor = versions[i].minor;
return versions[i].code;
}
}
return XPT_VERSION_UNKNOWN;
}