Bug 1248534 (part 1) - Remove XPT encoding support. r=khuey.

Currently XPT can both encode and decode, but encoding has been handled by
Python code since bug 643817, so the encoding support can be removed. This
results in many simplifications. Some notable changes:

- All the XPTHashTable code (including XPTDatapool::offset_map) is no longer
  necessary.

- PrimitiveTest.cpp and SimpleTypeLib.cpp both don't make much sense without
  encoding support, so I removed them.

- A lot of the version code was already unused, e.g. XPT_VERSION_*,
  XPT_TYPELIB_VERSIONS_STRUCT, XPT_TYPELIB_VERSIONS.
  XPT_MAJOR_INCOMPATIBLE_VERSION is the only thing actually used in version
  checks.

- The patch also removes some code that was dead even before encoding removal,
  such as XPT_ParseVersionString().
This commit is contained in:
Nicholas Nethercote 2016-02-16 19:02:51 +11:00
parent ac662bf0d6
commit 9352570917
9 changed files with 109 additions and 1425 deletions

View File

@ -32,7 +32,6 @@ if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_DEBUG']:
TEST_DIRS += [
'tests',
'typelib/xpt/tests',
]
# Can't build internal xptcall tests that use symbols which are not exported.

View File

@ -99,7 +99,7 @@ XPTInterfaceInfoManager::InitMemoryReporter()
void
XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
{
XPTState *state = XPT_NewXDRState(XPT_DECODE, buf, length);
XPTState *state = XPT_NewXDRState(buf, length);
if (!state)
return;

View File

@ -1,127 +0,0 @@
/* -*- 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/. */
/* Test the xdr primitives from xpt_xdr.c */
#include "xpt_xdr.h"
#include <stdio.h>
#include <string.h> /* for memcpy */
#define PASS(msg) \
fprintf(stderr, "PASSED : %s\n", msg);
#define FAIL(msg) \
fprintf(stderr, "FAILURE: %s\n", msg);
#define TRY_(msg, cond, silent) \
if ((cond) && !silent) { \
PASS(msg); \
} else { \
FAIL(msg); \
return 1; \
}
#define TRY(msg, cond) TRY_(msg, cond, 0)
#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
static char bazz[] = "bazz";
XPTString in_str = { 4, bazz };
static char foobar[] = "foobar";
struct TestData {
uint32_t bit32;
uint16_t bit16;
uint8_t bit8[2];
char *cstr;
XPTString *str;
} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe}, foobar, &in_str},
output = {0, 0, {0, 0}, NULL, NULL };
void
dump_struct(const char *label, struct TestData *str)
{
fprintf(stderr, "%s: {%#08x, %#04x, {%#02x, %#02x}, %s, %d/%s}\n",
label, str->bit32, str->bit16, str->bit8[0], str->bit8[1],
str->cstr, str->str->length, str->str->bytes);
}
PRBool
XDR(XPTArena *arena, XPTCursor *cursor, struct TestData *str)
{
TRY("Do32", XPT_Do32(cursor, &str->bit32));
TRY("Do16", XPT_Do16(cursor, &str->bit16));
TRY("Do8", XPT_Do8 (cursor, &str->bit8[0]));
TRY("Do8", XPT_Do8 (cursor, &str->bit8[1]));
TRY("DoCString", XPT_DoCString(arena, cursor, &str->cstr));
TRY("DoString", XPT_DoString(arena, cursor, &str->str));
return 0;
}
int
main(int argc, char **argv)
{
XPTArena *arena;
XPTState *state;
XPTCursor curs, *cursor = &curs;
char *header, *data, *whole;
uint32_t hlen, dlen, i;
TRY("XPT_NewArena", (arena = XPT_NewArena(1024, sizeof(double), "main")));
TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0)));
XPT_SetDataOffset(state, sizeof input);
TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
dump_struct("before", &input);
if (XDR(arena, cursor, &input))
return 1;
fprintf(stderr, "ENCODE successful\n");
XPT_GetXDRData(state, XPT_HEADER, &header, &hlen);
fprintf(stderr, "XDR header %d bytes at %p:",
hlen, header);
for (i = 0; i < hlen; i++)
fprintf(stderr, "%c%02x", i ? ',' : ' ', (uint8_t)header[i]);
fprintf(stderr, "\n");
XPT_GetXDRData(state, XPT_DATA, &data, &dlen);
fprintf(stderr, "XDR data %d bytes at %p:",
dlen, data);
for (i = 0; i < dlen; i++)
fprintf(stderr, "%c%02x/%c", i ? ',' : ' ', (uint8_t)data[i],
(uint8_t)data[i]);
fprintf(stderr, "\n");
whole = (char*)malloc(dlen + hlen);
if (!whole) {
fprintf(stderr, "malloc %d failed!\n", dlen + hlen);
return 1;
}
/* TRY_Q("malloc", (data2 = malloc(len))); */
memcpy(whole, header, hlen);
memcpy(whole + hlen, data, dlen);
XPT_DestroyXDRState(state);
TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, whole,
hlen + dlen)));
TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, sizeof input, cursor));
XPT_SetDataOffset(state, sizeof input);
if (XDR(arena, cursor, &output))
return 1;
dump_struct("after", &output);
XPT_DestroyXDRState(state);
XPT_DestroyArena(arena);
free(whole);
return 0;
}

View File

@ -1,152 +0,0 @@
/* -*- 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/. */
/* Test the structure creation and serialization APIs from xpt_struct.c */
#include <stdio.h>
#include "xpt_xdr.h"
#include "xpt_struct.h"
#define PASS(msg) \
fprintf(stderr, "PASSED : %s\n", msg);
#define FAIL(msg) \
fprintf(stderr, "FAILURE: %s\n", msg);
#define TRY_(msg, cond, silent) \
if ((cond) && !silent) { \
PASS(msg); \
} else { \
FAIL(msg); \
return 1; \
}
#define TRY(msg, cond) TRY_(msg, cond, 0)
#define TRY_Q(msg, cond) TRY_(msg, cond, 1);
struct nsID iid = {
0x00112233,
0x4455,
0x6677,
{0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
};
XPTTypeDescriptor td_void;
int
main(int argc, char **argv)
{
XPTArena *arena;
XPTHeader *header;
XPTAnnotation *ann;
XPTInterfaceDescriptor *id;
XPTMethodDescriptor *meth;
XPTState *state;
XPTCursor curs, *cursor = &curs;
char *data, *head;
FILE *out;
uint32_t len, header_sz;
PRBool ok;
td_void.prefix.flags = TD_VOID;
if (argc != 2) {
fprintf(stderr, "Usage: %s <filename.xpt>\n"
" Creates a simple typelib file.\n", argv[0]);
return 1;
}
arena = XPT_NewArena(1024, sizeof(double), "main");
TRY("XPT_NewArena", arena);
/* construct a header */
header = XPT_NewHeader(arena, 1, XPT_MAJOR_VERSION, XPT_MINOR_VERSION);
TRY("NewHeader", header);
ann = XPT_NewAnnotation(arena, XPT_ANN_LAST | XPT_ANN_PRIVATE,
XPT_NewStringZ(arena, "SimpleTypeLib 1.0"),
XPT_NewStringZ(arena, "See You In Rome"));
TRY("NewAnnotation", ann);
header->annotations = ann;
header_sz = XPT_SizeOfHeaderBlock(header);
id = XPT_NewInterfaceDescriptor(arena, 0, 2, 2, 0);
TRY("NewInterfaceDescriptor", id);
ok = XPT_FillInterfaceDirectoryEntry(arena, header->interface_directory, &iid,
"Interface", "NS", id);
TRY("FillInterfaceDirectoryEntry", ok);
/* void method1(void) */
meth = &id->method_descriptors[0];
ok = XPT_FillMethodDescriptor(arena, meth, 0, "method1", 0);
TRY("FillMethodDescriptor", ok);
meth->result.flags = 0;
meth->result.type.prefix.flags = TD_VOID;
/* wstring method2(in uint32_t, in bool) */
meth = &id->method_descriptors[1];
ok = XPT_FillMethodDescriptor(arena, meth, 0, "method2", 2);
TRY("FillMethodDescriptor", ok);
meth->result.flags = 0;
meth->result.type.prefix.flags = TD_PSTRING | XPT_TDP_POINTER;
meth->params[0].type.prefix.flags = TD_UINT32;
meth->params[0].flags = XPT_PD_IN;
meth->params[1].type.prefix.flags = TD_BOOL;
meth->params[1].flags = XPT_PD_IN;
#if 0
/* const one = 1; */
id->const_descriptors[0].name = "one";
id->const_descriptors[0].type.prefix.flags = TD_UINT16;
id->const_descriptors[0].value.ui16 = 1;
/* const squeamish = "ossifrage"; */
id->const_descriptors[1].name = "squeamish";
id->const_descriptors[1].type.prefix.flags = TD_PBSTR | XPT_TDP_POINTER;
id->const_descriptors[1].value.string = XPT_NewStringZ(arena, "ossifrage");
#endif
/* serialize it */
state = XPT_NewXDRState(XPT_ENCODE, NULL, 0);
TRY("NewState (ENCODE)", state);
ok = XPT_MakeCursor(state, XPT_HEADER, header_sz, cursor);
TRY("MakeCursor", ok);
ok = XPT_DoHeader(arena, cursor, &header);
TRY("DoHeader", ok);
out = fopen(argv[1], "wb");
if (!out) {
perror("FAILED: fopen");
return 1;
}
XPT_GetXDRData(state, XPT_HEADER, &head, &len);
fwrite(head, len, 1, out);
XPT_GetXDRData(state, XPT_DATA, &data, &len);
fwrite(data, len, 1, out);
if (ferror(out) != 0 || fclose(out) != 0) {
fprintf(stderr, "\nError writing file: %s\n\n", argv[1]);
} else {
fprintf(stderr, "\nFile written: %s\n\n", argv[1]);
}
XPT_DestroyXDRState(state);
XPT_FreeHeader(arena, header);
XPT_DestroyArena(arena);
return 0;
}

View File

@ -1,14 +0,0 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
SimplePrograms([
'PrimitiveTest',
'SimpleTypeLib',
])
USE_LIBS += [
'xpt',
]

View File

@ -13,21 +13,9 @@
/***************************************************************************/
/* 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);
XPTInterfaceDirectoryEntry *ide);
static PRBool
DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
@ -56,121 +44,21 @@ DoParamDescriptor(XPTArena *arena, XPTCursor *cursor, XPTParamDescriptor *pd,
/***************************************************************************/
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);
}
XPTHeader* header = XPT_NEWZAP(arena, XPTHeader);
if (!header)
return PR_FALSE;
*headerp = header;
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)
{
if (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; "
@ -178,14 +66,13 @@ XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, ui
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) {
if (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.
*/
@ -207,7 +94,6 @@ XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, ui
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;
@ -220,21 +106,19 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **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)) {
if (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) {
XPT_SetDataOffset(cursor->state, header->data_pool);
if (header->num_interfaces) {
header->interface_directory =
(XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, header->num_interfaces *
sizeof(XPTInterfaceDirectoryEntry));
@ -252,15 +136,14 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
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;
}
/*
* 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));
@ -269,8 +152,7 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
for (i = 0; i < header->num_interfaces; i++) {
if (!DoInterfaceDirectoryEntry(arena, cursor,
&header->interface_directory[i],
(uint16_t)(i + 1)))
&header->interface_directory[i]))
goto error;
}
@ -280,38 +162,11 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
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)
XPTInterfaceDirectoryEntry *ide)
{
XPTMode mode = cursor->state->mode;
/* write the IID in our cursor space */
if (!XPT_DoIID(cursor, &(ide->iid)) ||
@ -323,93 +178,16 @@ DoInterfaceDirectoryEntry(XPTArena *arena, XPTCursor *cursor,
cursor space */
!XPT_DoCString(arena, cursor, &(ide->name_space)) ||
/* do InterfaceDescriptors -- later, only on encode (see below) */
/* do InterfaceDescriptors */
!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)
@ -433,168 +211,25 @@ XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
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);
}
id = XPT_NEWZAP(arena, XPTInterfaceDescriptor);
if (!id)
return PR_FALSE;
*idp = 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) {
if (!cursor->offset) {
XPT_DELETE(arena, *idp);
return PR_TRUE;
}
@ -603,7 +238,7 @@ DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
goto error;
}
if (mode == XPT_DECODE && id->num_methods) {
if (id->num_methods) {
id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, id->num_methods *
sizeof(XPTMethodDescriptor));
if (!id->method_descriptors)
@ -619,7 +254,7 @@ DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
goto error;
}
if (mode == XPT_DECODE && id->num_constants) {
if (id->num_constants) {
id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, id->num_constants *
sizeof(XPTConstDescriptor));
if (!id->const_descriptors)
@ -694,35 +329,10 @@ DoConstDescriptor(XPTArena *arena, XPTCursor *cursor, XPTConstDescriptor *cd,
}
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) ||
@ -730,7 +340,7 @@ DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
!XPT_Do8(cursor, &md->num_args))
return PR_FALSE;
if (mode == XPT_DECODE && md->num_args) {
if (md->num_args) {
md->params = (XPTParamDescriptor*)XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
if (!md->params)
return PR_FALSE;
@ -749,15 +359,6 @@ DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
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)
@ -797,11 +398,9 @@ DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
!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 (!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],
@ -824,36 +423,14 @@ DoTypeDescriptor(XPTArena *arena, XPTCursor *cursor, XPTTypeDescriptor *td,
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;
}
XPTAnnotation* ann = XPT_NEWZAP(arena, XPTAnnotation);
if (!ann)
return PR_FALSE;
*annp = ann;
if (!XPT_Do8(cursor, &ann->flags))
goto error;
@ -873,39 +450,3 @@ DoAnnotation(XPTArena *arena, XPTCursor *cursor, XPTAnnotation **annp)
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;
}

View File

@ -37,6 +37,7 @@ typedef struct XPTTypeDescriptor XPTTypeDescriptor;
typedef struct XPTTypeDescriptorPrefix XPTTypeDescriptorPrefix;
typedef struct XPTString XPTString;
typedef struct XPTAnnotation XPTAnnotation;
#ifndef nsID_h__
/*
* We can't include nsID.h, because it's full of C++ goop and we're not doing
@ -53,20 +54,6 @@ struct nsID {
typedef struct nsID nsID;
#endif
#define XPT_COPY_IID(to, from) \
(to).m0 = (from).m0; \
(to).m1 = (from).m1; \
(to).m2 = (from).m2; \
(to).m3[0] = (from).m3[0]; \
(to).m3[1] = (from).m3[1]; \
(to).m3[2] = (from).m3[2]; \
(to).m3[3] = (from).m3[3]; \
(to).m3[4] = (from).m3[4]; \
(to).m3[5] = (from).m3[5]; \
(to).m3[6] = (from).m3[6]; \
(to).m3[7] = (from).m3[7];
/*
* Every XPCOM typelib file begins with a header.
*/
@ -99,78 +86,6 @@ struct XPTHeader {
*/
#define XPT_MAJOR_INCOMPATIBLE_VERSION 0x02
/*
* The "[-t version number]" cmd line parameter to the XPIDL compiler and XPT
* linker specifies the major and minor version number of the output
* type library.
*
* The goal is for the compiler to check that the input IDL file only uses
* constructs that are supported in the version specified. The linker will
* check that all typelib files it reads are of the version specified or
* below.
*
* Both the compiler and the linker will report errors and abort if these
* checks fail.
*
* When you rev up major or minor versions of the type library in the future,
* think about the new stuff that you added to the type library and add checks
* to make sure that occurrences of that new "stuff" will get caught when [-t
* version number] is used with the compiler. Here's what you'll probably
* have to do each time you rev up major/minor versions:
*
* 1) Add the current version number string (before your change) to the
* XPT_TYPELIB_VERSIONS list.
*
* 2) Do your changes add new features to XPIDL? Ensure that those new
* features are rejected by the XPIDL compiler when any version number in
* the XPT_TYPELIB_VERSIONS list is specified on the command line. The
* one place that currently does this kind of error checking is the function
* verify_type_fits_version() in xpidl_util.c. It currently checks
* attribute types, parameter types, and return types. You'll probably have
* to add to it or generalize it further based on what kind of changes you
* are making.
*
* 3) You will probably NOT need to make any changes to the error checking
* in the linker.
*/
#define XPT_VERSION_UNKNOWN 0
#define XPT_VERSION_UNSUPPORTED 1
#define XPT_VERSION_OLD 2
#define XPT_VERSION_CURRENT 3
typedef struct {
const char* str;
uint8_t major;
uint8_t minor;
uint16_t code;
} XPT_TYPELIB_VERSIONS_STRUCT;
/* Currently accepted list of versions for typelibs */
#define XPT_TYPELIB_VERSIONS { \
{"1.0", 1, 0, XPT_VERSION_UNSUPPORTED}, \
{"1.1", 1, 1, XPT_VERSION_OLD}, \
{"1.2", 1, 2, XPT_VERSION_CURRENT} \
}
extern XPT_PUBLIC_API(uint16_t)
XPT_ParseVersionString(const char* str, uint8_t* major, uint8_t* minor);
extern XPT_PUBLIC_API(XPTHeader *)
XPT_NewHeader(XPTArena *arena, uint16_t num_interfaces,
uint8_t major_version, uint8_t minor_version);
extern XPT_PUBLIC_API(void)
XPT_FreeHeader(XPTArena *arena, XPTHeader* aHeader);
/* size of header and annotations */
extern XPT_PUBLIC_API(uint32_t)
XPT_SizeOfHeader(XPTHeader *header);
/* size of header and annotations and InterfaceDirectoryEntries */
extern XPT_PUBLIC_API(uint32_t)
XPT_SizeOfHeaderBlock(XPTHeader *header);
/*
* A contiguous array of fixed-size InterfaceDirectoryEntry records begins at
* the byte offset identified by the interface_directory field in the file
@ -182,24 +97,8 @@ struct XPTInterfaceDirectoryEntry {
char *name;
char *name_space;
XPTInterfaceDescriptor *interface_descriptor;
#if 0 /* not yet */
/* not stored on disk */
uint32_t offset; /* the offset for an ID still to be read */
#endif
};
extern XPT_PUBLIC_API(PRBool)
XPT_FillInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry *ide,
nsID *iid, const char *name,
const char *name_space,
XPTInterfaceDescriptor *descriptor);
extern XPT_PUBLIC_API(void)
XPT_DestroyInterfaceDirectoryEntry(XPTArena *arena,
XPTInterfaceDirectoryEntry* ide);
/*
* An InterfaceDescriptor is a variable-size record used to describe a
* single XPCOM interface, including all of its methods.
@ -232,7 +131,6 @@ struct XPTInterfaceDescriptor {
* them to be of fixed size. This additional_types scheme is here to allow
* for that.
*/
uint16_t num_additional_types;
};
@ -247,31 +145,10 @@ struct XPTInterfaceDescriptor {
#define XPT_ID_IS_BUILTINCLASS(flags) (!!(flags & XPT_ID_BUILTINCLASS))
#define XPT_ID_IS_MAIN_PROCESS_SCRIPTABLE_ONLY(flags) (!!(flags & XPT_ID_MAIN_PROCESS_SCRIPTABLE_ONLY))
extern XPT_PUBLIC_API(PRBool)
XPT_GetInterfaceIndexByName(XPTInterfaceDirectoryEntry *ide_block,
uint16_t num_interfaces, const char *name,
uint16_t *indexp);
extern XPT_PUBLIC_API(XPTInterfaceDescriptor *)
XPT_NewInterfaceDescriptor(XPTArena *arena,
uint16_t parent_interface, uint16_t num_methods,
uint16_t num_constants, uint8_t flags);
extern XPT_PUBLIC_API(void)
XPT_FreeInterfaceDescriptor(XPTArena *arena, XPTInterfaceDescriptor* id);
extern XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num);
extern XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddMethods(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num);
extern XPT_PUBLIC_API(PRBool)
XPT_InterfaceDescriptorAddConsts(XPTArena *arena, XPTInterfaceDescriptor *id,
uint16_t num);
/*
* This is our special string struct with a length value associated with it,
* which means that it can contains embedded NULs.
@ -281,12 +158,6 @@ struct XPTString {
char *bytes;
};
extern XPT_PUBLIC_API(XPTString *)
XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes);
extern XPT_PUBLIC_API(XPTString *)
XPT_NewStringZ(XPTArena *arena, const char *bytes);
/*
* A TypeDescriptor is a variable-size record used to identify the type of a
* method argument or return value.
@ -366,12 +237,6 @@ struct XPTTypeDescriptor {
} type;
};
#define XPT_COPY_TYPE(to, from) \
(to).prefix.flags = (from).prefix.flags; \
(to).argnum = (from).argnum; \
(to).argnum2 = (from).argnum2; \
(to).type.additional_type = (from).type.additional_type;
/*
* A ConstDescriptor is a variable-size record that records the name and
* value of a scoped interface constant.
@ -440,11 +305,6 @@ struct XPTParamDescriptor {
#define XPT_PD_IS_DIPPER(flags) (flags & XPT_PD_DIPPER)
#define XPT_PD_IS_OPTIONAL(flags) (flags & XPT_PD_OPTIONAL)
extern XPT_PUBLIC_API(PRBool)
XPT_FillParamDescriptor(XPTArena *arena,
XPTParamDescriptor *pd, uint8_t flags,
XPTTypeDescriptor *type);
/*
* A MethodDescriptor is a variable-size record used to describe a single
* interface method.
@ -475,11 +335,6 @@ struct XPTMethodDescriptor {
#define XPT_MD_WANTS_OPT_ARGC(flags) (flags & XPT_MD_OPT_ARGC)
#define XPT_MD_WANTS_CONTEXT(flags) (flags & XPT_MD_CONTEXT)
extern XPT_PUBLIC_API(PRBool)
XPT_FillMethodDescriptor(XPTArena *arena,
XPTMethodDescriptor *meth, uint8_t flags,
const char *name, uint8_t num_args);
/*
* Annotation records are variable-size records used to store secondary
* information about the typelib, e.g. such as the name of the tool that
@ -512,10 +367,6 @@ struct XPTAnnotation {
#define XPT_ANN_PRIVATE 0x40
#define XPT_ANN_IS_PRIVATE(flags) (flags & XPT_ANN_PRIVATE)
extern XPT_PUBLIC_API(XPTAnnotation *)
XPT_NewAnnotation(XPTArena *arena, uint8_t flags, XPTString *creator,
XPTString *private_data);
}
#endif /* __xpt_struct_h__ */

View File

@ -10,13 +10,6 @@
#include "nscore.h"
#include <string.h> /* strchr */
static PRBool
CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len,
XPTCursor *new_cursor, PRBool *already);
#define ENCODING(cursor) \
((cursor)->state->mode == XPT_ENCODE)
#define CURS_POOL_OFFSET_RAW(cursor) \
((cursor)->pool == XPT_HEADER \
? (cursor)->offset \
@ -30,115 +23,23 @@ CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len,
#define CURS_POINT(cursor) \
((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
#if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe)
#define DBG(x) printf x
#else
#define DBG(x) (0)
#endif
/* XXX fail if XPT_DATA and !state->data_offset */
#define CHECK_COUNT_(cursor, space) \
/* if we're in the header, then exceeding the data_offset is illegal */ \
((cursor)->pool == XPT_HEADER ? \
(ENCODING(cursor) && \
((cursor)->state->data_offset && \
((cursor)->offset - 1 + (space) > (cursor)->state->data_offset)) \
? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset, \
(space), (cursor)->state->data_offset)) && PR_FALSE) \
: PR_TRUE) : \
/* if we're in the data area and we're about to exceed the allocation */ \
(CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ? \
/* then grow if we're in ENCODE mode */ \
(ENCODING(cursor) ? GrowPool((cursor)->state->arena, \
(cursor)->state->pool, \
(cursor)->state->pool->allocated, \
0, CURS_POOL_OFFSET(cursor) + (space)) \
/* and fail if we're in DECODE mode */ \
: (DBG(("can't extend in DECODE")) && PR_FALSE)) \
/* otherwise we're OK */ \
: PR_TRUE))
#define CHECK_COUNT(cursor, space) \
(CHECK_COUNT_(cursor, space) \
? PR_TRUE \
: (XPT_ASSERT(0), \
fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space), \
PR_FALSE))
/* increase the data allocation for the pool by XPT_GROW_CHUNK */
#define XPT_GROW_CHUNK 8192
/*
* quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib.
* XXXmccabe it might turn out that we could use a simpler data structure here.
*/
typedef struct XPTHashRecord {
void *key;
void *value;
struct XPTHashRecord *next;
} XPTHashRecord;
#define XPT_HASHSIZE 512
struct XPTHashTable { /* it's already typedef'ed from before. */
XPTHashRecord *buckets[XPT_HASHSIZE];
XPTArena *arena;
};
static XPTHashTable *
XPT_NewHashTable(XPTArena *arena) {
XPTHashTable *table;
table = XPT_NEWZAP(arena, XPTHashTable);
if (table)
table->arena = arena;
return table;
}
static void trimrecord(XPTArena* arena, XPTHashRecord *record) {
if (record == NULL)
return;
trimrecord(arena, record->next);
XPT_DELETE(arena, record);
}
static void
XPT_HashTableDestroy(XPTHashTable *table) {
int i;
for (i = 0; i < XPT_HASHSIZE; i++)
trimrecord(table->arena, table->buckets[i]);
XPT_FREE(table->arena, table);
}
static void *
XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) {
XPTHashRecord **bucketloc = table->buckets +
(NS_PTR_TO_UINT32(key) % XPT_HASHSIZE);
XPTHashRecord *bucket;
while (*bucketloc != NULL)
bucketloc = &((*bucketloc)->next);
bucket = XPT_NEW(table->arena, XPTHashRecord);
bucket->key = key;
bucket->value = value;
bucket->next = NULL;
*bucketloc = bucket;
return value;
}
static void *
XPT_HashTableLookup(XPTHashTable *table, void *key) {
XPTHashRecord *bucket = table->buckets[NS_PTR_TO_UINT32(key) % XPT_HASHSIZE];
while (bucket != NULL) {
if (bucket->key == key)
return bucket->value;
bucket = bucket->next;
static PRBool
CHECK_COUNT(XPTCursor* cursor, uint32_t space)
{
// Fail if we're in the data area and about to exceed the allocation.
// XXX Also fail if we're in the data area and !state->data_offset
if (cursor->pool == XPT_DATA &&
(CURS_POOL_OFFSET(cursor) + space > (cursor)->state->pool->allocated)) {
XPT_ASSERT(0);
fprintf(stderr, "FATAL: no room for %d in cursor\n", space);
return PR_FALSE;
}
return NULL;
return PR_TRUE;
}
XPT_PUBLIC_API(XPTState *)
XPT_NewXDRState(XPTMode mode, char *data, uint32_t len)
XPT_NewXDRState(char *data, uint32_t len)
{
XPTState *state;
XPTArena *arena;
@ -152,33 +53,16 @@ XPT_NewXDRState(XPTMode mode, char *data, uint32_t len)
goto err_free_arena;
state->arena = arena;
state->mode = mode;
state->pool = XPT_NEW(arena, XPTDatapool);
state->next_cursor[0] = state->next_cursor[1] = 1;
if (!state->pool)
goto err_free_state;
state->pool->count = 0;
state->pool->offset_map = XPT_NewHashTable(arena);
if (!state->pool->offset_map)
goto err_free_pool;
if (mode == XPT_DECODE) {
state->pool->data = data;
state->pool->allocated = len;
} else {
state->pool->data = (char*)XPT_MALLOC(arena, XPT_GROW_CHUNK);
if (!state->pool->data)
goto err_free_hash;
state->pool->allocated = XPT_GROW_CHUNK;
}
state->pool->data = data;
state->pool->allocated = len;
return state;
err_free_hash:
XPT_HashTableDestroy(state->pool->offset_map);
err_free_pool:
XPT_DELETE(arena, state->pool);
err_free_state:
XPT_DELETE(arena, state);
err_free_arena:
@ -192,86 +76,17 @@ XPT_DestroyXDRState(XPTState *state)
{
XPTArena *arena = state->arena;
if (state->pool->offset_map)
XPT_HashTableDestroy(state->pool->offset_map);
if (state->mode == XPT_ENCODE)
XPT_DELETE(arena, state->pool->data);
XPT_DELETE(arena, state->pool);
XPT_DELETE(arena, state);
if (arena)
XPT_DestroyArena(arena);
}
XPT_PUBLIC_API(void)
XPT_GetXDRDataLength(XPTState *state, XPTPool pool, uint32_t *len)
{
*len = state->next_cursor[pool] - 1;
}
XPT_PUBLIC_API(void)
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32_t *len)
{
if (pool == XPT_HEADER) {
*data = state->pool->data;
} else {
*data = state->pool->data + state->data_offset;
}
*len = state->next_cursor[pool] - 1;
}
/* All offsets are 1-based */
XPT_PUBLIC_API(void)
XPT_DataOffset(XPTState *state, uint32_t *data_offsetp)
{
if (state->mode == XPT_DECODE)
XPT_SetDataOffset(state, *data_offsetp);
else
*data_offsetp = state->data_offset;
}
/* if 'exact' is set use that, else grow by the next chunk but
* be sure to grow no less that 'at_least' so that we can't get
* behind on required space.
*/
static PRBool
GrowPool(XPTArena *arena, XPTDatapool *pool, uint32_t old_size,
uint32_t exact, uint32_t at_least)
{
uint32_t total_size;
char *newdata;
if (exact) {
XPT_ASSERT(exact > pool->allocated);
total_size = exact;
} else {
total_size = pool->allocated + XPT_GROW_CHUNK;
if (at_least > total_size)
total_size = at_least;
}
newdata = (char*)XPT_MALLOC(arena, total_size);
if (!newdata)
return PR_FALSE;
if (pool->data) {
if (old_size)
memcpy(newdata, pool->data, old_size);
XPT_FREE(arena, pool->data);
}
pool->data = newdata;
pool->allocated = total_size;
return PR_TRUE;
}
XPT_PUBLIC_API(void)
XPT_SetDataOffset(XPTState *state, uint32_t data_offset)
{
state->data_offset = data_offset;
/* make sure we've allocated enough space for the header */
if (state->mode == XPT_ENCODE &&
data_offset > state->pool->allocated) {
(void)GrowPool(state->arena, state->pool, state->pool->allocated,
data_offset, 0);
}
}
XPT_PUBLIC_API(PRBool)
@ -304,63 +119,31 @@ XPT_SeekTo(XPTCursor *cursor, uint32_t offset)
return PR_TRUE;
}
XPT_PUBLIC_API(XPTString *)
XPT_NewString(XPTArena *arena, uint16_t length, const char *bytes)
{
XPTString *str = XPT_NEW(arena, XPTString);
if (!str)
return NULL;
str->length = length;
/* Alloc one extra to store the trailing nul. */
str->bytes = (char*)XPT_MALLOC(arena, length + 1u);
if (!str->bytes) {
XPT_DELETE(arena, str);
return NULL;
}
memcpy(str->bytes, bytes, length);
/* nul-terminate it. */
str->bytes[length] = '\0';
return str;
}
XPT_PUBLIC_API(XPTString *)
XPT_NewStringZ(XPTArena *arena, const char *bytes)
{
uint32_t length = strlen(bytes);
if (length > 0xffff)
return NULL; /* too long */
return XPT_NewString(arena, (uint16_t)length, bytes);
}
XPT_PUBLIC_API(PRBool)
XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
{
XPTString *str = *strp;
XPTMode mode = cursor->state->mode;
int i;
if (mode == XPT_DECODE) {
str = XPT_NEWZAP(arena, XPTString);
if (!str)
return PR_FALSE;
*strp = str;
}
str = XPT_NEWZAP(arena, XPTString);
if (!str)
return PR_FALSE;
*strp = str;
if (!XPT_Do16(cursor, &str->length))
goto error;
if (mode == XPT_DECODE)
if (!(str->bytes = (char*)XPT_MALLOC(arena, str->length + 1u)))
goto error;
if (!(str->bytes = (char*)XPT_MALLOC(arena, str->length + 1u)))
goto error;
for (i = 0; i < str->length; i++)
if (!XPT_Do8(cursor, (uint8_t *)&str->bytes[i]))
goto error_2;
if (mode == XPT_DECODE)
str->bytes[str->length] = 0;
str->bytes[str->length] = 0;
return PR_TRUE;
error_2:
XPT_DELETE(arena, str->bytes);
error:
@ -368,149 +151,40 @@ XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
return PR_FALSE;
}
XPT_PUBLIC_API(PRBool)
XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
{
XPTCursor my_cursor;
XPTString *str = *strp;
PRBool already;
XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2u, my_cursor,
already)
return XPT_DoStringInline(arena, &my_cursor, strp);
}
XPT_PUBLIC_API(PRBool)
XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
{
XPTCursor my_cursor;
char *ident = *identp;
uint32_t offset = 0;
if (!XPT_Do32(cursor, &offset))
return PR_FALSE;
XPTMode mode = cursor->state->mode;
if (mode == XPT_DECODE) {
char *start, *end;
int len;
if (!XPT_Do32(cursor, &offset))
return PR_FALSE;
if (!offset) {
*identp = NULL;
return PR_TRUE;
}
my_cursor.pool = XPT_DATA;
my_cursor.offset = offset;
my_cursor.state = cursor->state;
start = &CURS_POINT(&my_cursor);
end = strchr(start, 0); /* find the end of the string */
if (!end) {
fprintf(stderr, "didn't find end of string on decode!\n");
return PR_FALSE;
}
len = end - start;
XPT_ASSERT(len > 0);
ident = (char*)XPT_MALLOC(arena, len + 1u);
if (!ident)
return PR_FALSE;
memcpy(ident, start, (size_t)len);
ident[len] = 0;
*identp = ident;
} else {
if (!ident) {
offset = 0;
if (!XPT_Do32(cursor, &offset))
return PR_FALSE;
return PR_TRUE;
}
if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1,
&my_cursor) ||
!XPT_Do32(cursor, &my_cursor.offset))
return PR_FALSE;
while(*ident)
if (!XPT_Do8(&my_cursor, (uint8_t *)ident++))
return PR_FALSE;
if (!XPT_Do8(&my_cursor, (uint8_t *)ident)) /* write trailing zero */
return PR_FALSE;
if (!offset) {
*identp = NULL;
return PR_TRUE;
}
return PR_TRUE;
}
XPTCursor my_cursor;
my_cursor.pool = XPT_DATA;
my_cursor.offset = offset;
my_cursor.state = cursor->state;
char* start = &CURS_POINT(&my_cursor);
/* XXXjband it bothers me that this is one hashtable instead of two.
*/
XPT_PUBLIC_API(uint32_t)
XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
{
XPTHashTable *table = cursor->state->pool->offset_map;
return NS_PTR_TO_UINT32(XPT_HashTableLookup(table, addr));
}
XPT_PUBLIC_API(PRBool)
XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32_t offset)
{
return XPT_HashTableAdd(cursor->state->pool->offset_map,
addr, NS_INT32_TO_PTR(offset)) != NULL;
}
XPT_PUBLIC_API(PRBool)
XPT_SetAddrForOffset(XPTCursor *cursor, uint32_t offset, void *addr)
{
return XPT_HashTableAdd(cursor->state->pool->offset_map,
NS_INT32_TO_PTR(offset), addr) != NULL;
}
XPT_PUBLIC_API(void *)
XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset)
{
return XPT_HashTableLookup(cursor->state->pool->offset_map,
NS_INT32_TO_PTR(offset));
}
/* Used by XPT_PREAMBLE_NO_ALLOC. */
static PRBool
CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, uint32_t len,
XPTCursor *new_cursor, PRBool *already)
{
void *last = *addrp;
*already = PR_FALSE;
new_cursor->state = cursor->state;
new_cursor->pool = pool;
new_cursor->bits = 0;
if (cursor->state->mode == XPT_DECODE) {
last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset);
if (last) {
*already = PR_TRUE;
*addrp = last;
}
} else {
new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last);
if (new_cursor->offset) {
*already = PR_TRUE;
return PR_TRUE;
}
/* haven't already found it, so allocate room for it. */
if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) ||
!XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset))
return PR_FALSE;
char* end = strchr(start, 0); /* find the end of the string */
if (!end) {
fprintf(stderr, "didn't find end of string on decode!\n");
return PR_FALSE;
}
int len = end - start;
XPT_ASSERT(len > 0);
char *ident = (char*)XPT_MALLOC(arena, len + 1u);
if (!ident)
return PR_FALSE;
memcpy(ident, start, (size_t)len);
ident[len] = 0;
*identp = ident;
return PR_TRUE;
}
@ -552,7 +226,7 @@ XPT_Do64(XPTCursor *cursor, int64_t *u64p)
}
/*
* When we're writing 32- or 16-bit quantities, we write a byte at a time to
* When we're handling 32- or 16-bit quantities, we handle a byte at a time to
* avoid alignment issues. Someone could come and optimize this to detect
* well-aligned cases and do a single store, if they cared. I might care
* later.
@ -568,25 +242,15 @@ XPT_Do32(XPTCursor *cursor, uint32_t *u32p)
if (!CHECK_COUNT(cursor, 4))
return PR_FALSE;
if (ENCODING(cursor)) {
u.b32 = XPT_SWAB32(*u32p);
CURS_POINT(cursor) = u.b8[0];
cursor->offset++;
CURS_POINT(cursor) = u.b8[1];
cursor->offset++;
CURS_POINT(cursor) = u.b8[2];
cursor->offset++;
CURS_POINT(cursor) = u.b8[3];
} else {
u.b8[0] = CURS_POINT(cursor);
cursor->offset++;
u.b8[1] = CURS_POINT(cursor);
cursor->offset++;
u.b8[2] = CURS_POINT(cursor);
cursor->offset++;
u.b8[3] = CURS_POINT(cursor);
*u32p = XPT_SWAB32(u.b32);
}
u.b8[0] = CURS_POINT(cursor);
cursor->offset++;
u.b8[1] = CURS_POINT(cursor);
cursor->offset++;
u.b8[2] = CURS_POINT(cursor);
cursor->offset++;
u.b8[3] = CURS_POINT(cursor);
*u32p = XPT_SWAB32(u.b32);
cursor->offset++;
return PR_TRUE;
}
@ -602,17 +266,11 @@ XPT_Do16(XPTCursor *cursor, uint16_t *u16p)
if (!CHECK_COUNT(cursor, 2))
return PR_FALSE;
if (ENCODING(cursor)) {
u.b16 = XPT_SWAB16(*u16p);
CURS_POINT(cursor) = u.b8[0];
cursor->offset++;
CURS_POINT(cursor) = u.b8[1];
} else {
u.b8[0] = CURS_POINT(cursor);
cursor->offset++;
u.b8[1] = CURS_POINT(cursor);
*u16p = XPT_SWAB16(u.b16);
}
u.b8[0] = CURS_POINT(cursor);
cursor->offset++;
u.b8[1] = CURS_POINT(cursor);
*u16p = XPT_SWAB16(u.b16);
cursor->offset++;
return PR_TRUE;
@ -623,10 +281,8 @@ XPT_Do8(XPTCursor *cursor, uint8_t *u8p)
{
if (!CHECK_COUNT(cursor, 1))
return PR_FALSE;
if (cursor->state->mode == XPT_ENCODE)
CURS_POINT(cursor) = *u8p;
else
*u8p = CURS_POINT(cursor);
*u8p = CURS_POINT(cursor);
cursor->offset++;

View File

@ -4,7 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Basic APIs for streaming typelib structures to/from disk.
* Basic APIs for streaming typelib structures from disk.
*/
#ifndef __xpt_xdr_h__
@ -20,12 +20,6 @@ typedef struct XPTState XPTState;
typedef struct XPTDatapool XPTDatapool;
typedef struct XPTCursor XPTCursor;
/* Opaque type, for internal use */
typedef struct XPTHashTable XPTHashTable;
extern XPT_PUBLIC_API(PRBool)
XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
extern XPT_PUBLIC_API(PRBool)
XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp);
@ -52,18 +46,12 @@ XPT_DoHeaderPrologue(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp, ui
extern XPT_PUBLIC_API(PRBool)
XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp);
typedef enum {
XPT_ENCODE,
XPT_DECODE
} XPTMode;
typedef enum {
XPT_HEADER = 0,
XPT_DATA = 1
} XPTPool;
struct XPTState {
XPTMode mode;
uint32_t data_offset;
uint32_t next_cursor[2];
XPTDatapool *pool;
@ -71,9 +59,7 @@ struct XPTState {
};
struct XPTDatapool {
XPTHashTable *offset_map;
char *data;
uint32_t count;
uint32_t allocated;
};
@ -85,7 +71,7 @@ struct XPTCursor {
};
extern XPT_PUBLIC_API(XPTState *)
XPT_NewXDRState(XPTMode mode, char *data, uint32_t len);
XPT_NewXDRState(char *data, uint32_t len);
extern XPT_PUBLIC_API(PRBool)
XPT_MakeCursor(XPTState *state, XPTPool pool, uint32_t len, XPTCursor *cursor);
@ -96,36 +82,9 @@ XPT_SeekTo(XPTCursor *cursor, uint32_t offset);
extern XPT_PUBLIC_API(void)
XPT_DestroyXDRState(XPTState *state);
/* Set file_length based on the data used in the state. (Only ENCODE.) */
extern XPT_PUBLIC_API(PRBool)
XPT_UpdateFileLength(XPTState *state);
/* returns the length of the specified data block */
extern XPT_PUBLIC_API(void)
XPT_GetXDRDataLength(XPTState *state, XPTPool pool, uint32_t *len);
extern XPT_PUBLIC_API(void)
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32_t *len);
/* set or get the data offset for the state, depending on mode */
extern XPT_PUBLIC_API(void)
XPT_DataOffset(XPTState *state, uint32_t *data_offsetp);
extern XPT_PUBLIC_API(void)
XPT_SetDataOffset(XPTState *state, uint32_t data_offset);
extern XPT_PUBLIC_API(uint32_t)
XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr);
extern XPT_PUBLIC_API(PRBool)
XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32_t offset);
extern XPT_PUBLIC_API(PRBool)
XPT_SetAddrForOffset(XPTCursor *cursor, uint32_t offset, void *addr);
extern XPT_PUBLIC_API(void *)
XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset);
/* all data structures are big-endian */
#if defined IS_BIG_ENDIAN
@ -141,37 +100,8 @@ XPT_GetAddrForOffset(XPTCursor *cursor, uint32_t offset);
# error "unknown byte order"
#endif
/*
* If we're decoding, we want to read the offset before we check
* for already-decoded values.
*
* Then we check for repetition: CheckForRepeat will see if we've already
* encoded/decoded this value, and if so will set offset/addr correctly
* and make already be true. If not, it will set up the cursor for
* encoding (reserve space) or decoding (seek to correct location) as
* appropriate. In the encode case, it will also set the addr->offset
* mapping.
*/
#define XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
XPTMode mode = cursor->state->mode; \
if (!(mode == XPT_ENCODE || XPT_Do32(cursor, &new_curs.offset)) || \
!CheckForRepeat(cursor, (void **)addrp, pool, \
mode == XPT_ENCODE ? size : 0u, &new_curs, \
&already) || \
!(mode == XPT_DECODE || XPT_Do32(cursor, &new_curs.offset))) \
return PR_FALSE; \
if (already) \
return PR_TRUE; \
#define XPT_PREAMBLE_NO_ALLOC(cursor, addrp, pool, size, new_curs, already) \
{ \
XPT_PREAMBLE_(cursor, addrp, pool, size, new_curs, already) \
}
#define XPT_ERROR_HANDLE(arena, free_it) \
error: \
if (cursor->state->mode == XPT_DECODE) \
XPT_FREEIF(arena, free_it); \
return PR_FALSE;