added some tests (we don't pass yet =) ), wrote some primitives

git-svn-id: svn://10.0.0.236/trunk@18087 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
shaver%netscape.com 1999-01-20 23:17:05 +00:00
parent 1629d20dfd
commit b7788d4156
10 changed files with 760 additions and 162 deletions

View File

@ -0,0 +1,28 @@
#!gmake
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
DIRS += tests
include $(topsrcdir)/config/rules.mk

View File

@ -25,6 +25,7 @@
#include <nspr.h>
#include <plhash.h>
#include <prmem.h>
#include "xpt_struct.h"
typedef struct XPTState XPTState;
@ -40,6 +41,9 @@ XPT_DoIdentifier(XPTCursor *cursor, char **identp);
PRBool
XPT_DoIID(XPTCursor *cursor, nsID *iidp);
PRBool
XPT_Do64(XPTCursor *cursor, PRInt64 *u64p);
PRBool
XPT_Do32(XPTCursor *cursor, uint32 *u32p);
@ -62,6 +66,8 @@ XPT_Do8(XPTCursor *cursor, uint8 *u8p);
PRBool
XPT_DoBits(XPTCursor *cursor, uint8 *u8p, int nbits);
#define XPT_DO_BITS(curs, field, width, scr) (PR_TRUE)
/* returns the number of bits skipped, which should be 0-7 */
int
XPT_FlushBits(XPTCursor *cursor);
@ -78,52 +84,45 @@ typedef enum {
struct XPTState {
XPTMode mode;
XPTDatapool *pools[2];
uint32 data_offset;
XPTDatapool *pool;
};
struct XPTDatapool {
PLHashTable *offset_map;
char *data;
uint32 count;
uint8 bit;
uint32 allocated;
};
struct XPTCursor {
XPTState *state;
XPTDatapool *pool;
XPTPool pool;
uint32 offset;
uint32 len;
uint8 bits;
};
XPTState *
XPT_NewXDRState(XPTMode mode, char *data, uint32 len);
PRBool
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor);
void
XPT_DestroyXDRState(XPTState *state);
void
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len);
/*
* On CreateCursor:
* cursors are used to track position within the byte stream.
* In encode/write mode, the cursor reserves an area of memory for a structure.
* In decode/read mode, it simply tracks position.
*
* Usage will commonly be something like this (taken from XPT_DoString) for
* out-of-line structures:
*
* // create my_cursor and reserve memory as required
* XPT_CreateCursor(parent_cursor, XPT_DATA, str->length + 2, &my_cursor);
* // write mode: store the offset for this structure in the parent cursor
* // read mode: adjust my_cursor to point to the write offset
* XPT_Do32(parent_cursor, &my_cursor->offset);
*/
/* set or get the data offset for the state, depending on mode */
void
XPT_DataOffset(XPTState *state, uint32 *data_offsetp);
void
XPT_SetDataOffset(XPTState *state, uint32 data_offset);
PRBool
XPT_CreateCursor(XPTCursor *base, XPTPool pool, uint32 len, XPTCursor *cursor);
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor);
/* all data structures are big-endian */
@ -188,7 +187,7 @@ XPT_CreateCursor(XPTCursor *base, XPTPool pool, uint32 len, XPTCursor *cursor);
#define XPT_ERROR_HANDLE(free_it) \
error: \
if (cursor->state->mode == XPT_DECODE) \
PR_FREE_IF(free_it); \
PR_FREEIF(free_it); \
return PR_FALSE;

View File

@ -19,81 +19,137 @@
/* Implementation of XDR primitives. */
#include "xpt_xdr.h"
#include <nspr.h>
#include <string.h> /* strchr */
#define CHECK_COUNT(cursor) \
((cursor)->offset == (cursor)->pool->allocated ? \
((cursor)->state->mode == XPT_ENCODE ? XPT_GrowPool((cursor)->pool) : \
PR_FALSE) : PR_TRUE)
#define ENCODING(cursor) \
((cursor)->state->mode == XPT_ENCODE)
#define CURS_POOL_OFFSET(cursor) \
((cursor)->pool == XPT_HEADER \
? (cursor)->offset \
: (PR_ASSERT((cursor)->state->data_offset), \
(cursor)->offset + (cursor)->state->data_offset))
/* can be used as lvalue */
#define CURS_POINT(cursor) \
(cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)]
#define CHECK_COUNT(cursor, space) \
/* if we're in the header, then exceeding the data_offset is illegal */ \
((cursor)->pool == XPT_HEADER ? \
((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) ? XPT_GrowPool((cursor)->state->pool) \
/* and fail if we're in DECODE mode */ \
: PR_FALSE) \
/* otherwise we're OK */ \
: PR_TRUE))
/* increase the data allocation for the pool by XPT_GROW_CHUNK */
#define XPT_GROW_CHUNK 8192
static PLHashNumber
null_hash(const void *key)
{
return (PLHashNumber)key;
}
XPTState *
XPT_NewXDRState(XPTMode mode, char *data, uint32 len)
{
#if 0 /* need to rethink pool management */
XPTState *state;
int i;
state = PR_NEW(XPTState);
if (!state)
return NULL;
state->mode = mode;
for (i = 0; i < 2; i++) {
state->pools[i] = PR_NEW(XPTDatapool);
if (!state->pools[i]) {
if (i) {
PR_FREE(state->pools[0]->data);
PR_FREE(state->pools[0]);
}
PR_FREE(state);
return NULL;
}
state->pools[i]->count = 0;
state->pools[i]->bit = 0;
if (mode == XPT_DECODE) {
state->pools[i]->data = data;
state->pools[i]->allocated = len;
} else {
state->pools[i]->data = PR_MALLOC(XPT_GROW_CHUNK);
if (!state->pools[i]->data) {
PR_FREE(state->pools[i]);
if (i) {
PR_FREE(state->pools[0]->data);
PR_FREE(state->pools[0]);
}
PR_FREE(state);
return NULL;
}
state->pools[i]->allocated = XPT_GROW_CHUNK;
}
state->pool = PR_NEW(XPTDatapool);
if (!state->pool)
goto err_free_state;
state->pool->count = 0;
state->pool->offset_map = PL_NewHashTable(32, null_hash, PL_CompareValues,
PL_CompareValues, NULL, NULL);
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 = PR_MALLOC(XPT_GROW_CHUNK);
if (!state->pool->data)
goto err_free_hash;
state->pool->allocated = XPT_GROW_CHUNK;
}
#endif
return state;
err_free_hash:
PL_HashTableDestroy(state->pool->offset_map);
err_free_pool:
PR_DELETE(state->pool);
err_free_state:
PR_DELETE(state);
return NULL;
}
void
XPT_DestroyXDRState(XPTState *state)
{
#if 0 /* need to rethink pool management */
int i;
if (state->mode == XPT_ENCODE) {
PR_FREE_IF(state->pool->data);
PR_FREE(state->pool);
PR_FREE(state);
} else {
PR_FREE(state->pool);
PR_FREE(state);
}
#endif
if (state->mode == XPT_ENCODE)
PR_DELETE(state->pool->data);
PR_DELETE(state->pool);
PR_DELETE(state);
}
void
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len)
{
*data = state->pools[pool]->data;
*len = state->pools[pool]->count;
if (pool == XPT_HEADER) {
*data = state->pool->data;
*len = state->data_offset;
} else {
*data = state->pool->data + state->data_offset;
*len = state->pool->count - state->data_offset;
}
}
void
XPT_DataOffset(XPTState *state, uint32 *data_offsetp)
{
if (state->mode == XPT_DECODE)
state->data_offset = *data_offsetp;
else
*data_offsetp = state->data_offset;
}
void
XPT_SetDataOffset(XPTState *state, uint32 data_offset)
{
state->data_offset = data_offset;
}
PRBool
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor)
{
cursor->state = state;
cursor->pool = pool;
cursor->bits = 0;
if (pool == XPT_DATA) {
if (!state->data_offset)
return PR_FALSE;
cursor->offset = state->data_offset;
} else {
cursor->offset = 0;
}
return PR_TRUE;
}
static PRBool
@ -142,7 +198,7 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
my_cursor, already);
if (mode == XPT_DECODE) {
char *start = &my_cursor.pool->data[my_cursor.offset], *end;
char *start = &CURS_POINT(&my_cursor), *end;
int len;
end = strchr(start, 0); /* find the end of the string */
@ -161,7 +217,7 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
*identp = ident;
if (!XPT_SetAddrForOffset(&my_cursor, my_cursor.offset, ident)) {
PR_FREE(ident);
PR_DELETE(ident);
return PR_FALSE;
}
@ -179,26 +235,28 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
uint32
XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
{
return 0;
return (uint32)PL_HashTableLookup(cursor->state->pool->offset_map, addr);
}
PRBool
XPT_SetOffsetForAddr(XPTCursor *cursor, void **addr, uint32 offset)
XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32 offset)
{
*addr = NULL;
return PR_FALSE;
return PL_HashTableAdd(cursor->state->pool->offset_map,
addr, (void *)offset) != NULL;
}
PRBool
XPT_SetAddrForOffset(XPTCursor *cursor, void *addr)
{
return PR_FALSE;
return PL_HashTableAdd(cursor->state->pool->offset_map,
(void *)cursor->offset, addr) != NULL;
}
void *
XPT_GetAddrForOffset(XPTCursor *cursor)
{
return PR_FALSE;
return PL_HashTableLookup(cursor->state->pool->offset_map,
(void *)cursor->offset);
}
PRBool
@ -209,7 +267,8 @@ XPT_CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, int len,
*already = PR_FALSE;
new_cursor->state = cursor->state;
new_cursor->pool = cursor->state->pools[pool];
new_cursor->pool = pool;
new_cursor->bits = 0;
if (cursor->state->mode = XPT_DECODE) {
@ -256,27 +315,85 @@ XPT_DoIID(XPTCursor *cursor, nsID *iidp)
return PR_FALSE;
}
PRBool
XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
{
return XPT_Do32(cursor, (uint32 *)u64p) &&
XPT_Do32(cursor, ((uint32 *)u64p) + 1);
}
/*
* When we're writing 32- or 16-bit quantities, we write 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.
*/
PRBool
XPT_Do32(XPTCursor *cursor, uint32 *u32p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 4))
return PR_FALSE;
if (ENCODING(cursor)) {
CURS_POINT(cursor) = ((uint8 *)(u32p))[0];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[1];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[2];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[3];
} else {
((uint8 *)(u32p))[0] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[1] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[2] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[3] = CURS_POINT(cursor);
}
cursor->offset++;
return PR_TRUE;
}
PRBool
XPT_Do16(XPTCursor *cursor, uint16 *u16p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 2))
return PR_FALSE;
if (ENCODING(cursor)) {
CURS_POINT(cursor) = ((uint8 *)(u16p))[0];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u16p))[1];
} else {
((uint8 *)(u16p))[0] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u16p))[1] = CURS_POINT(cursor);
}
cursor->offset++;
return PR_TRUE;
}
PRBool
XPT_Do8(XPTCursor *cursor, uint8 *u8p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 1))
return PR_FALSE;
if (cursor->state->mode == XPT_ENCODE)
CURS_POINT(cursor) = *u8p;
else
*u8p = CURS_POINT(cursor);
cursor->offset++;
return PR_TRUE;
}
static PRBool
do_bit(XPTCursor *cursor, uint8 *u8p, int bitno)
{
return PR_FALSE;
#if 0
int bit_value, delta, new_value;
XPTDatapool *pool = cursor->pool;
@ -297,6 +414,7 @@ do_bit(XPTCursor *cursor, uint8 *u8p, int bitno)
}
return CHECK_COUNT(cursor);
#endif
}
PRBool
@ -335,6 +453,8 @@ XPT_FlushBits(XPTCursor *cursor)
{
int skipped = 8 - cursor->bits;
return 0;
#if 0
cursor->bits = 0;
cursor->offset++;
@ -342,4 +462,5 @@ XPT_FlushBits(XPTCursor *cursor)
return -1;
return skipped == 8 ? 0 : skipped;
#endif
}

View File

@ -0,0 +1,42 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = libxpt
CSRCS = PrimitiveTest.c
include $(topsrcdir)/config/rules.mk
EX_LIBS = $(DIST)/lib/libxpt.$(LIB_SUFFIX) \
$(NULL)
PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=))
TARGETS = $(PROGS)
$(PROGS):$(OBJDIR)/%: $(OBJDIR)/%.o $(EX_LIBS)
@$(MAKE_OBJDIR)
$(CC) -o $@ $@.o $(LDFLAGS) $(EX_LIBS) $(NSPR_LIBS) $(OS_LIBS)
install:: $(PROGS)
$(INSTALL) $(PROGS) $(DIST)/bin

View File

@ -0,0 +1,109 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Test the xdr primitives from xpt_xdr.c */
#include "xpt_xdr.h"
#include <stdio.h>
#define PASS(msg) \
printf("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 TestData {
uint32 bit32;
uint16 bit16;
uint8 bit8[2];
} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe} }, output = {0, 0, {0, 0} };
void
dump_struct(char *label, struct TestData *str)
{
printf("%s: {%#08x, %#04x, {%#02x, %#02x}\n", label,
str->bit32, str->bit16, str->bit8[0], str->bit8[1]);
}
PRBool
XDR(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]));
return 0;
}
int
main(int argc, char **argv)
{
XPTState *state;
XPTCursor curs, *cursor = &curs;
char *data, *data2;
uint32 len = 0, i;
TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0)));
XPT_SetDataOffset(state, 1024);
TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, cursor));
dump_struct("before", &input);
if (XDR(cursor, &input))
return 1;
XPT_GetXDRData(state, XPT_HEADER, &data, &len);
printf("XDR data %d bytes (really %d) at %p: ", len, sizeof input, data);
for (i = 0; i < sizeof input / 4; i++)
printf("%08x,", ((uint32 *)&input)[i]);
printf("\n");
data2 = malloc(len);
if (!data2) {
printf("what the fuck?\n");
return 1;
}
/* TRY_Q("malloc", (data2 = malloc(len))); */
memcpy(data2, data, len);
XPT_DestroyXDRState(state);
TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, data, len)));
XPT_SetDataOffset(state, 1024);
if (XDR(cursor, &output))
return 1;
dump_struct("after", &output);
XPT_DestroyXDRState(state);
return 0;
}

View File

@ -0,0 +1,28 @@
#!gmake
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
DIRS += tests
include $(topsrcdir)/config/rules.mk

View File

@ -25,6 +25,7 @@
#include <nspr.h>
#include <plhash.h>
#include <prmem.h>
#include "xpt_struct.h"
typedef struct XPTState XPTState;
@ -40,6 +41,9 @@ XPT_DoIdentifier(XPTCursor *cursor, char **identp);
PRBool
XPT_DoIID(XPTCursor *cursor, nsID *iidp);
PRBool
XPT_Do64(XPTCursor *cursor, PRInt64 *u64p);
PRBool
XPT_Do32(XPTCursor *cursor, uint32 *u32p);
@ -62,6 +66,8 @@ XPT_Do8(XPTCursor *cursor, uint8 *u8p);
PRBool
XPT_DoBits(XPTCursor *cursor, uint8 *u8p, int nbits);
#define XPT_DO_BITS(curs, field, width, scr) (PR_TRUE)
/* returns the number of bits skipped, which should be 0-7 */
int
XPT_FlushBits(XPTCursor *cursor);
@ -78,52 +84,45 @@ typedef enum {
struct XPTState {
XPTMode mode;
XPTDatapool *pools[2];
uint32 data_offset;
XPTDatapool *pool;
};
struct XPTDatapool {
PLHashTable *offset_map;
char *data;
uint32 count;
uint8 bit;
uint32 allocated;
};
struct XPTCursor {
XPTState *state;
XPTDatapool *pool;
XPTPool pool;
uint32 offset;
uint32 len;
uint8 bits;
};
XPTState *
XPT_NewXDRState(XPTMode mode, char *data, uint32 len);
PRBool
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor);
void
XPT_DestroyXDRState(XPTState *state);
void
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len);
/*
* On CreateCursor:
* cursors are used to track position within the byte stream.
* In encode/write mode, the cursor reserves an area of memory for a structure.
* In decode/read mode, it simply tracks position.
*
* Usage will commonly be something like this (taken from XPT_DoString) for
* out-of-line structures:
*
* // create my_cursor and reserve memory as required
* XPT_CreateCursor(parent_cursor, XPT_DATA, str->length + 2, &my_cursor);
* // write mode: store the offset for this structure in the parent cursor
* // read mode: adjust my_cursor to point to the write offset
* XPT_Do32(parent_cursor, &my_cursor->offset);
*/
/* set or get the data offset for the state, depending on mode */
void
XPT_DataOffset(XPTState *state, uint32 *data_offsetp);
void
XPT_SetDataOffset(XPTState *state, uint32 data_offset);
PRBool
XPT_CreateCursor(XPTCursor *base, XPTPool pool, uint32 len, XPTCursor *cursor);
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor);
/* all data structures are big-endian */
@ -188,7 +187,7 @@ XPT_CreateCursor(XPTCursor *base, XPTPool pool, uint32 len, XPTCursor *cursor);
#define XPT_ERROR_HANDLE(free_it) \
error: \
if (cursor->state->mode == XPT_DECODE) \
PR_FREE_IF(free_it); \
PR_FREEIF(free_it); \
return PR_FALSE;

View File

@ -19,81 +19,137 @@
/* Implementation of XDR primitives. */
#include "xpt_xdr.h"
#include <nspr.h>
#include <string.h> /* strchr */
#define CHECK_COUNT(cursor) \
((cursor)->offset == (cursor)->pool->allocated ? \
((cursor)->state->mode == XPT_ENCODE ? XPT_GrowPool((cursor)->pool) : \
PR_FALSE) : PR_TRUE)
#define ENCODING(cursor) \
((cursor)->state->mode == XPT_ENCODE)
#define CURS_POOL_OFFSET(cursor) \
((cursor)->pool == XPT_HEADER \
? (cursor)->offset \
: (PR_ASSERT((cursor)->state->data_offset), \
(cursor)->offset + (cursor)->state->data_offset))
/* can be used as lvalue */
#define CURS_POINT(cursor) \
(cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)]
#define CHECK_COUNT(cursor, space) \
/* if we're in the header, then exceeding the data_offset is illegal */ \
((cursor)->pool == XPT_HEADER ? \
((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) ? XPT_GrowPool((cursor)->state->pool) \
/* and fail if we're in DECODE mode */ \
: PR_FALSE) \
/* otherwise we're OK */ \
: PR_TRUE))
/* increase the data allocation for the pool by XPT_GROW_CHUNK */
#define XPT_GROW_CHUNK 8192
static PLHashNumber
null_hash(const void *key)
{
return (PLHashNumber)key;
}
XPTState *
XPT_NewXDRState(XPTMode mode, char *data, uint32 len)
{
#if 0 /* need to rethink pool management */
XPTState *state;
int i;
state = PR_NEW(XPTState);
if (!state)
return NULL;
state->mode = mode;
for (i = 0; i < 2; i++) {
state->pools[i] = PR_NEW(XPTDatapool);
if (!state->pools[i]) {
if (i) {
PR_FREE(state->pools[0]->data);
PR_FREE(state->pools[0]);
}
PR_FREE(state);
return NULL;
}
state->pools[i]->count = 0;
state->pools[i]->bit = 0;
if (mode == XPT_DECODE) {
state->pools[i]->data = data;
state->pools[i]->allocated = len;
} else {
state->pools[i]->data = PR_MALLOC(XPT_GROW_CHUNK);
if (!state->pools[i]->data) {
PR_FREE(state->pools[i]);
if (i) {
PR_FREE(state->pools[0]->data);
PR_FREE(state->pools[0]);
}
PR_FREE(state);
return NULL;
}
state->pools[i]->allocated = XPT_GROW_CHUNK;
}
state->pool = PR_NEW(XPTDatapool);
if (!state->pool)
goto err_free_state;
state->pool->count = 0;
state->pool->offset_map = PL_NewHashTable(32, null_hash, PL_CompareValues,
PL_CompareValues, NULL, NULL);
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 = PR_MALLOC(XPT_GROW_CHUNK);
if (!state->pool->data)
goto err_free_hash;
state->pool->allocated = XPT_GROW_CHUNK;
}
#endif
return state;
err_free_hash:
PL_HashTableDestroy(state->pool->offset_map);
err_free_pool:
PR_DELETE(state->pool);
err_free_state:
PR_DELETE(state);
return NULL;
}
void
XPT_DestroyXDRState(XPTState *state)
{
#if 0 /* need to rethink pool management */
int i;
if (state->mode == XPT_ENCODE) {
PR_FREE_IF(state->pool->data);
PR_FREE(state->pool);
PR_FREE(state);
} else {
PR_FREE(state->pool);
PR_FREE(state);
}
#endif
if (state->mode == XPT_ENCODE)
PR_DELETE(state->pool->data);
PR_DELETE(state->pool);
PR_DELETE(state);
}
void
XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, uint32 *len)
{
*data = state->pools[pool]->data;
*len = state->pools[pool]->count;
if (pool == XPT_HEADER) {
*data = state->pool->data;
*len = state->data_offset;
} else {
*data = state->pool->data + state->data_offset;
*len = state->pool->count - state->data_offset;
}
}
void
XPT_DataOffset(XPTState *state, uint32 *data_offsetp)
{
if (state->mode == XPT_DECODE)
state->data_offset = *data_offsetp;
else
*data_offsetp = state->data_offset;
}
void
XPT_SetDataOffset(XPTState *state, uint32 data_offset)
{
state->data_offset = data_offset;
}
PRBool
XPT_MakeCursor(XPTState *state, XPTPool pool, XPTCursor *cursor)
{
cursor->state = state;
cursor->pool = pool;
cursor->bits = 0;
if (pool == XPT_DATA) {
if (!state->data_offset)
return PR_FALSE;
cursor->offset = state->data_offset;
} else {
cursor->offset = 0;
}
return PR_TRUE;
}
static PRBool
@ -142,7 +198,7 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
my_cursor, already);
if (mode == XPT_DECODE) {
char *start = &my_cursor.pool->data[my_cursor.offset], *end;
char *start = &CURS_POINT(&my_cursor), *end;
int len;
end = strchr(start, 0); /* find the end of the string */
@ -161,7 +217,7 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
*identp = ident;
if (!XPT_SetAddrForOffset(&my_cursor, my_cursor.offset, ident)) {
PR_FREE(ident);
PR_DELETE(ident);
return PR_FALSE;
}
@ -179,26 +235,28 @@ XPT_DoCString(XPTCursor *cursor, char **identp)
uint32
XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
{
return 0;
return (uint32)PL_HashTableLookup(cursor->state->pool->offset_map, addr);
}
PRBool
XPT_SetOffsetForAddr(XPTCursor *cursor, void **addr, uint32 offset)
XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, uint32 offset)
{
*addr = NULL;
return PR_FALSE;
return PL_HashTableAdd(cursor->state->pool->offset_map,
addr, (void *)offset) != NULL;
}
PRBool
XPT_SetAddrForOffset(XPTCursor *cursor, void *addr)
{
return PR_FALSE;
return PL_HashTableAdd(cursor->state->pool->offset_map,
(void *)cursor->offset, addr) != NULL;
}
void *
XPT_GetAddrForOffset(XPTCursor *cursor)
{
return PR_FALSE;
return PL_HashTableLookup(cursor->state->pool->offset_map,
(void *)cursor->offset);
}
PRBool
@ -209,7 +267,8 @@ XPT_CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, int len,
*already = PR_FALSE;
new_cursor->state = cursor->state;
new_cursor->pool = cursor->state->pools[pool];
new_cursor->pool = pool;
new_cursor->bits = 0;
if (cursor->state->mode = XPT_DECODE) {
@ -256,27 +315,85 @@ XPT_DoIID(XPTCursor *cursor, nsID *iidp)
return PR_FALSE;
}
PRBool
XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
{
return XPT_Do32(cursor, (uint32 *)u64p) &&
XPT_Do32(cursor, ((uint32 *)u64p) + 1);
}
/*
* When we're writing 32- or 16-bit quantities, we write 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.
*/
PRBool
XPT_Do32(XPTCursor *cursor, uint32 *u32p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 4))
return PR_FALSE;
if (ENCODING(cursor)) {
CURS_POINT(cursor) = ((uint8 *)(u32p))[0];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[1];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[2];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u32p))[3];
} else {
((uint8 *)(u32p))[0] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[1] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[2] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u32p))[3] = CURS_POINT(cursor);
}
cursor->offset++;
return PR_TRUE;
}
PRBool
XPT_Do16(XPTCursor *cursor, uint16 *u16p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 2))
return PR_FALSE;
if (ENCODING(cursor)) {
CURS_POINT(cursor) = ((uint8 *)(u16p))[0];
cursor->offset++;
CURS_POINT(cursor) = ((uint8 *)(u16p))[1];
} else {
((uint8 *)(u16p))[0] = CURS_POINT(cursor);
cursor->offset++;
((uint8 *)(u16p))[1] = CURS_POINT(cursor);
}
cursor->offset++;
return PR_TRUE;
}
PRBool
XPT_Do8(XPTCursor *cursor, uint8 *u8p)
{
return PR_FALSE;
if (!CHECK_COUNT(cursor, 1))
return PR_FALSE;
if (cursor->state->mode == XPT_ENCODE)
CURS_POINT(cursor) = *u8p;
else
*u8p = CURS_POINT(cursor);
cursor->offset++;
return PR_TRUE;
}
static PRBool
do_bit(XPTCursor *cursor, uint8 *u8p, int bitno)
{
return PR_FALSE;
#if 0
int bit_value, delta, new_value;
XPTDatapool *pool = cursor->pool;
@ -297,6 +414,7 @@ do_bit(XPTCursor *cursor, uint8 *u8p, int bitno)
}
return CHECK_COUNT(cursor);
#endif
}
PRBool
@ -335,6 +453,8 @@ XPT_FlushBits(XPTCursor *cursor)
{
int skipped = 8 - cursor->bits;
return 0;
#if 0
cursor->bits = 0;
cursor->offset++;
@ -342,4 +462,5 @@ XPT_FlushBits(XPTCursor *cursor)
return -1;
return skipped == 8 ? 0 : skipped;
#endif
}

View File

@ -0,0 +1,42 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = libxpt
CSRCS = PrimitiveTest.c
include $(topsrcdir)/config/rules.mk
EX_LIBS = $(DIST)/lib/libxpt.$(LIB_SUFFIX) \
$(NULL)
PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=))
TARGETS = $(PROGS)
$(PROGS):$(OBJDIR)/%: $(OBJDIR)/%.o $(EX_LIBS)
@$(MAKE_OBJDIR)
$(CC) -o $@ $@.o $(LDFLAGS) $(EX_LIBS) $(NSPR_LIBS) $(OS_LIBS)
install:: $(PROGS)
$(INSTALL) $(PROGS) $(DIST)/bin

View File

@ -0,0 +1,109 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Test the xdr primitives from xpt_xdr.c */
#include "xpt_xdr.h"
#include <stdio.h>
#define PASS(msg) \
printf("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 TestData {
uint32 bit32;
uint16 bit16;
uint8 bit8[2];
} input = { 0xdeadbeef, 0xcafe, {0xba, 0xbe} }, output = {0, 0, {0, 0} };
void
dump_struct(char *label, struct TestData *str)
{
printf("%s: {%#08x, %#04x, {%#02x, %#02x}\n", label,
str->bit32, str->bit16, str->bit8[0], str->bit8[1]);
}
PRBool
XDR(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]));
return 0;
}
int
main(int argc, char **argv)
{
XPTState *state;
XPTCursor curs, *cursor = &curs;
char *data, *data2;
uint32 len = 0, i;
TRY("NewState (ENCODE)", (state = XPT_NewXDRState(XPT_ENCODE, NULL, 0)));
XPT_SetDataOffset(state, 1024);
TRY("MakeCursor", XPT_MakeCursor(state, XPT_HEADER, cursor));
dump_struct("before", &input);
if (XDR(cursor, &input))
return 1;
XPT_GetXDRData(state, XPT_HEADER, &data, &len);
printf("XDR data %d bytes (really %d) at %p: ", len, sizeof input, data);
for (i = 0; i < sizeof input / 4; i++)
printf("%08x,", ((uint32 *)&input)[i]);
printf("\n");
data2 = malloc(len);
if (!data2) {
printf("what the fuck?\n");
return 1;
}
/* TRY_Q("malloc", (data2 = malloc(len))); */
memcpy(data2, data, len);
XPT_DestroyXDRState(state);
TRY("NewState (DECODE)", (state = XPT_NewXDRState(XPT_DECODE, data, len)));
XPT_SetDataOffset(state, 1024);
if (XDR(cursor, &output))
return 1;
dump_struct("after", &output);
XPT_DestroyXDRState(state);
return 0;
}