Back to index

lightning-sunbird  0.9+nobinonly
xpt_xdr.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /* Implementation of XDR primitives. */
00039 
00040 #include "xpt_xdr.h"
00041 #include "nspr.h"
00042 #include <string.h>             /* strchr */
00043 
00044 static PRBool
00045 CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
00046                    XPTCursor *new_cursor, PRBool *already);
00047 
00048 #define ENCODING(cursor)                                                      \
00049   ((cursor)->state->mode == XPT_ENCODE)
00050 
00051 #define CURS_POOL_OFFSET_RAW(cursor)                                          \
00052   ((cursor)->pool == XPT_HEADER                                               \
00053    ? (cursor)->offset                                                         \
00054    : (XPT_ASSERT((cursor)->state->data_offset),                               \
00055       (cursor)->offset + (cursor)->state->data_offset))
00056 
00057 #define CURS_POOL_OFFSET(cursor)                                              \
00058   (CURS_POOL_OFFSET_RAW(cursor) - 1)
00059 
00060 /* can be used as lvalue */
00061 #define CURS_POINT(cursor)                                                    \
00062   ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
00063 
00064 #if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe)
00065 #define DBG(x) printf x
00066 #else
00067 #define DBG(x) (0)
00068 #endif
00069 
00070 /* XXX fail if XPT_DATA and !state->data_offset */
00071 #define CHECK_COUNT_(cursor, space)                                           \
00072  /* if we're in the header, then exceeding the data_offset is illegal */      \
00073 ((cursor)->pool == XPT_HEADER ?                                               \
00074  (ENCODING(cursor) &&                                                         \
00075   ((cursor)->state->data_offset &&                                            \
00076    ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset))           \
00077   ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset,         \
00078           (space), (cursor)->state->data_offset)) && PR_FALSE)                \
00079   : PR_TRUE) :                                                                \
00080  /* if we're in the data area and we're about to exceed the allocation */     \
00081  (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ?     \
00082   /* then grow if we're in ENCODE mode */                                     \
00083   (ENCODING(cursor) ? GrowPool((cursor)->state->arena,                        \
00084                                (cursor)->state->pool,                         \
00085                                (cursor)->state->pool->allocated,              \
00086                                0, CURS_POOL_OFFSET(cursor) + (space))         \
00087    /* and fail if we're in DECODE mode */                                     \
00088    : (DBG(("can't extend in DECODE")) && PR_FALSE))                           \
00089   /* otherwise we're OK */                                                    \
00090   : PR_TRUE))
00091 
00092 #define CHECK_COUNT(cursor, space)                                            \
00093   (CHECK_COUNT_(cursor, space)                                                \
00094    ? PR_TRUE                                                                  \
00095    : (XPT_ASSERT(0),                                                          \
00096       fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space),      \
00097       PR_FALSE))
00098 
00099 /* increase the data allocation for the pool by XPT_GROW_CHUNK */
00100 #define XPT_GROW_CHUNK  8192
00101 
00102 /*
00103  * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib.
00104  * XXXmccabe it might turn out that we could use a simpler data structure here.
00105  */
00106 typedef struct XPTHashRecord {
00107     void *key;
00108     void *value;
00109     struct XPTHashRecord *next;
00110 } XPTHashRecord;
00111 
00112 #define XPT_HASHSIZE 512
00113 
00114 struct XPTHashTable {  /* it's already typedef'ed from before. */
00115     XPTHashRecord *buckets[XPT_HASHSIZE];
00116     XPTArena *arena;
00117 };
00118 
00119 static XPTHashTable *
00120 XPT_NewHashTable(XPTArena *arena) {
00121     XPTHashTable *table;
00122     table = XPT_NEWZAP(arena, XPTHashTable);
00123     if (table)
00124         table->arena = arena;
00125     return table;
00126 }
00127 
00128 static void trimrecord(XPTArena* arena, XPTHashRecord *record) {
00129     if (record == NULL)
00130         return;
00131     trimrecord(arena, record->next);
00132     XPT_DELETE(arena, record);
00133 }
00134 
00135 static void
00136 XPT_HashTableDestroy(XPTHashTable *table) {
00137     int i;
00138     for (i = 0; i < XPT_HASHSIZE; i++)
00139         trimrecord(table->arena, table->buckets[i]);
00140     XPT_FREE(table->arena, table);
00141 }
00142 
00143 static void *
00144 XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) {
00145     XPTHashRecord **bucketloc = table->buckets +
00146         (((PRUint32)key) % XPT_HASHSIZE);
00147     XPTHashRecord *bucket;
00148 
00149     while (*bucketloc != NULL)
00150         bucketloc = &((*bucketloc)->next);
00151 
00152     bucket = XPT_NEW(table->arena, XPTHashRecord);
00153     bucket->key = key;
00154     bucket->value = value;
00155     bucket->next = NULL;
00156     *bucketloc = bucket;
00157     return value;
00158 }
00159 
00160 static void *
00161 XPT_HashTableLookup(XPTHashTable *table, void *key) {
00162     XPTHashRecord *bucket = table->buckets[(PRUint32)key % XPT_HASHSIZE];
00163     while (bucket != NULL) {
00164         if (bucket->key == key)
00165             return bucket->value;
00166         bucket = bucket->next;
00167     }
00168     return NULL;
00169 }
00170 
00171 XPT_PUBLIC_API(XPTState *)
00172 XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len)
00173 {
00174     XPTState *state;
00175     XPTArena *arena;
00176 
00177     arena = XPT_NewArena(512, sizeof(double), "an XDRState");
00178     if (!arena)
00179         return NULL;
00180 
00181     state = XPT_NEWZAP(arena, XPTState);
00182     if (!state)
00183         goto err_free_arena;
00184 
00185     state->arena = arena;
00186     state->mode = mode;
00187     state->pool = XPT_NEW(arena, XPTDatapool);
00188     state->next_cursor[0] = state->next_cursor[1] = 1;
00189     if (!state->pool)
00190         goto err_free_state;
00191 
00192     state->pool->count = 0;
00193     state->pool->offset_map = XPT_NewHashTable(arena);
00194 
00195     if (!state->pool->offset_map)
00196         goto err_free_pool;
00197     if (mode == XPT_DECODE) {
00198         state->pool->data = data;
00199         state->pool->allocated = len;
00200     } else {
00201         state->pool->data = XPT_MALLOC(arena, XPT_GROW_CHUNK);
00202         if (!state->pool->data)
00203             goto err_free_hash;
00204         state->pool->allocated = XPT_GROW_CHUNK;
00205     }
00206 
00207     return state;
00208 
00209  err_free_hash:
00210     XPT_HashTableDestroy(state->pool->offset_map);
00211  err_free_pool:
00212     XPT_DELETE(arena, state->pool);
00213  err_free_state:
00214     XPT_DELETE(arena, state);
00215  err_free_arena:
00216     if (arena)
00217         XPT_DestroyArena(arena);
00218     return NULL;
00219 }
00220 
00221 XPT_PUBLIC_API(void)
00222 XPT_DestroyXDRState(XPTState *state)
00223 {
00224     XPTArena *arena = state->arena;
00225 
00226     if (state->pool->offset_map)
00227         XPT_HashTableDestroy(state->pool->offset_map);
00228     if (state->mode == XPT_ENCODE)
00229         XPT_DELETE(arena, state->pool->data);
00230     XPT_DELETE(arena, state->pool);
00231     XPT_DELETE(arena, state);
00232     if (arena)
00233         XPT_DestroyArena(arena);
00234 }
00235 
00236 XPT_PUBLIC_API(void)
00237 XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len)
00238 {
00239     *len = state->next_cursor[pool] - 1;
00240 }
00241 
00242 XPT_PUBLIC_API(void)
00243 XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len)
00244 {
00245     if (pool == XPT_HEADER) {
00246         *data = state->pool->data;
00247     } else {
00248         *data = state->pool->data + state->data_offset;
00249     }
00250     *len = state->next_cursor[pool] - 1;
00251 }
00252 
00253 /* All offsets are 1-based */
00254 XPT_PUBLIC_API(void)
00255 XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp)
00256 {
00257     if (state->mode == XPT_DECODE)
00258         XPT_SetDataOffset(state, *data_offsetp);
00259     else
00260         *data_offsetp = state->data_offset;
00261 }
00262 
00263 /* if 'exact' is set use that, else grow by the next chunk but
00264  * be sure to grow no less that 'at_least' so that we can't get
00265  * behind on required space.
00266  */
00267 static PRBool
00268 GrowPool(XPTArena *arena, XPTDatapool *pool, PRUint32 old_size, 
00269          PRUint32 exact, PRUint32 at_least)
00270 {
00271     PRUint32 total_size;
00272     char *newdata;
00273 
00274     if (exact) {
00275         XPT_ASSERT(exact > pool->allocated);
00276         total_size = exact;
00277     } else {
00278         total_size = pool->allocated + XPT_GROW_CHUNK;
00279         if (at_least > total_size)
00280             total_size = at_least;
00281     }
00282 
00283     newdata = XPT_MALLOC(arena, total_size);
00284     if (!newdata)
00285         return PR_FALSE;
00286     if (pool->data) {
00287         if (old_size)
00288             memcpy(newdata, pool->data, old_size);
00289         XPT_FREE(arena, pool->data);
00290     }
00291     pool->data = newdata;
00292     pool->allocated = total_size;
00293     return PR_TRUE;
00294 }
00295 
00296 XPT_PUBLIC_API(void)
00297 XPT_SetDataOffset(XPTState *state, PRUint32 data_offset)
00298 {
00299    state->data_offset = data_offset;
00300    /* make sure we've allocated enough space for the header */
00301    if (state->mode == XPT_ENCODE &&
00302        data_offset > state->pool->allocated) {
00303        (void)GrowPool(state->arena, state->pool, state->pool->allocated, 
00304                       data_offset, 0);
00305    }
00306 }
00307 
00308 XPT_PUBLIC_API(PRBool)
00309 XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor)
00310 {
00311     cursor->state = state;
00312     cursor->pool = pool;
00313     cursor->bits = 0;
00314     cursor->offset = state->next_cursor[pool];
00315 
00316     if (!(CHECK_COUNT(cursor, len)))
00317         return PR_FALSE;
00318 
00319     /* this check should be in CHECK_CURSOR */
00320     if (pool == XPT_DATA && !state->data_offset) {
00321         fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
00322         return PR_FALSE;
00323     }
00324 
00325     state->next_cursor[pool] += len;
00326 
00327     return PR_TRUE;
00328 }
00329 
00330 XPT_PUBLIC_API(PRBool)
00331 XPT_SeekTo(XPTCursor *cursor, PRUint32 offset)
00332 {
00333     /* XXX do some real checking and update len and stuff */
00334     cursor->offset = offset;
00335     return PR_TRUE;
00336 }
00337 
00338 XPT_PUBLIC_API(XPTString *)
00339 XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes)
00340 {
00341     XPTString *str = XPT_NEW(arena, XPTString);
00342     if (!str)
00343         return NULL;
00344     str->length = length;
00345     /* Alloc one extra to store the trailing nul. */
00346     str->bytes = XPT_MALLOC(arena, length + 1u);
00347     if (!str->bytes) {
00348         XPT_DELETE(arena, str);
00349         return NULL;
00350     }
00351     memcpy(str->bytes, bytes, length);
00352     /* nul-terminate it. */
00353     str->bytes[length] = '\0';
00354     return str;
00355 }
00356 
00357 XPT_PUBLIC_API(XPTString *)
00358 XPT_NewStringZ(XPTArena *arena, char *bytes)
00359 {
00360     PRUint32 length = strlen(bytes);
00361     if (length > 0xffff)
00362         return NULL;            /* too long */
00363     return XPT_NewString(arena, (PRUint16)length, bytes);
00364 }
00365 
00366 XPT_PUBLIC_API(PRBool)
00367 XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
00368 {
00369     XPTString *str = *strp;
00370     XPTMode mode = cursor->state->mode;
00371     int i;
00372 
00373     if (mode == XPT_DECODE) {
00374         str = XPT_NEWZAP(arena, XPTString);
00375         if (!str)
00376             return PR_FALSE;
00377         *strp = str;
00378     }
00379 
00380     if (!XPT_Do16(cursor, &str->length))
00381         goto error;
00382 
00383     if (mode == XPT_DECODE)
00384         if (!(str->bytes = XPT_MALLOC(arena, str->length + 1u)))
00385             goto error;
00386 
00387     for (i = 0; i < str->length; i++)
00388         if (!XPT_Do8(cursor, (PRUint8 *)&str->bytes[i]))
00389             goto error_2;
00390 
00391     if (mode == XPT_DECODE)
00392         str->bytes[str->length] = 0;
00393 
00394     return PR_TRUE;
00395  error_2:
00396     XPT_DELETE(arena, str->bytes);
00397  error:
00398     XPT_DELETE(arena, str);
00399     return PR_FALSE;
00400 }
00401 
00402 XPT_PUBLIC_API(PRBool)
00403 XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
00404 {
00405     XPTCursor my_cursor;
00406     XPTString *str = *strp;
00407     PRBool already;
00408 
00409     XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2, my_cursor,
00410                           already)
00411 
00412     return XPT_DoStringInline(arena, &my_cursor, strp);
00413 }
00414 
00415 XPT_PUBLIC_API(PRBool)
00416 XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
00417 {
00418     XPTCursor my_cursor;
00419     char *ident = *identp;
00420     PRUint32 offset = 0;
00421 
00422     XPTMode mode = cursor->state->mode;
00423 
00424     if (mode == XPT_DECODE) {
00425         char *start, *end;
00426         int len;
00427 
00428         if (!XPT_Do32(cursor, &offset))
00429             return PR_FALSE;
00430 
00431         if (!offset) {
00432             *identp = NULL;
00433             return PR_TRUE;
00434         }
00435 
00436         my_cursor.pool = XPT_DATA;
00437         my_cursor.offset = offset;
00438         my_cursor.state = cursor->state;
00439         start = &CURS_POINT(&my_cursor);
00440 
00441         end = strchr(start, 0); /* find the end of the string */
00442         if (!end) {
00443             fprintf(stderr, "didn't find end of string on decode!\n");
00444             return PR_FALSE;
00445         }
00446         len = end - start;
00447         XPT_ASSERT(len > 0);
00448 
00449         ident = XPT_MALLOC(arena, len + 1u);
00450         if (!ident)
00451             return PR_FALSE;
00452 
00453         memcpy(ident, start, (size_t)len);
00454         ident[len] = 0;
00455         *identp = ident;
00456 
00457     } else {
00458 
00459         if (!ident) {
00460             offset = 0;
00461             if (!XPT_Do32(cursor, &offset))
00462                 return PR_FALSE;
00463             return PR_TRUE;
00464         }
00465 
00466         if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1,
00467                             &my_cursor) ||
00468             !XPT_Do32(cursor, &my_cursor.offset))
00469             return PR_FALSE;
00470 
00471         while(*ident)
00472             if (!XPT_Do8(&my_cursor, (PRUint8 *)ident++))
00473                 return PR_FALSE;
00474         if (!XPT_Do8(&my_cursor, (PRUint8 *)ident)) /* write trailing zero */
00475             return PR_FALSE;
00476     }
00477 
00478     return PR_TRUE;
00479 }
00480 
00481 /* XXXjband it bothers me that this is one hashtable instead of two.
00482  */
00483 XPT_PUBLIC_API(PRUint32)
00484 XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
00485 {
00486     return (PRUint32)XPT_HashTableLookup(cursor->state->pool->offset_map, addr);
00487 }
00488 
00489 XPT_PUBLIC_API(PRBool)
00490 XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset)
00491 {
00492     return XPT_HashTableAdd(cursor->state->pool->offset_map,
00493                             addr, (void *)offset) != NULL;
00494 }
00495 
00496 XPT_PUBLIC_API(PRBool)
00497 XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr)
00498 {
00499     return XPT_HashTableAdd(cursor->state->pool->offset_map,
00500                             (void *)offset, addr) != NULL;
00501 }
00502 
00503 XPT_PUBLIC_API(void *)
00504 XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset)
00505 {
00506     return XPT_HashTableLookup(cursor->state->pool->offset_map, (void *)offset);
00507 }
00508 
00509 /* Used by XPT_PREAMBLE_NO_ALLOC. */
00510 static PRBool
00511 CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
00512                XPTCursor *new_cursor, PRBool *already)
00513 {
00514     void *last = *addrp;
00515 
00516     *already = PR_FALSE;
00517     new_cursor->state = cursor->state;
00518     new_cursor->pool = pool;
00519     new_cursor->bits = 0;
00520 
00521     if (cursor->state->mode == XPT_DECODE) {
00522 
00523         last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset);
00524 
00525         if (last) {
00526             *already = PR_TRUE;
00527             *addrp = last;
00528         }
00529 
00530     } else {
00531 
00532         new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last);
00533         if (new_cursor->offset) {
00534             *already = PR_TRUE;
00535             return PR_TRUE;
00536         }
00537 
00538         /* haven't already found it, so allocate room for it. */
00539         if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) ||
00540             !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset))
00541             return PR_FALSE;
00542     }
00543     return PR_TRUE;
00544 }
00545 
00546 /*
00547  * IIDs are written in struct order, in the usual big-endian way.  From the
00548  * typelib file spec:
00549  *
00550  *   "For example, this IID:
00551  *     {00112233-4455-6677-8899-aabbccddeeff}
00552  *   is converted to the 128-bit value
00553  *     0x00112233445566778899aabbccddeeff
00554  *   Note that the byte storage order corresponds to the layout of the nsIID
00555  *   C-struct on a big-endian architecture."
00556  *
00557  * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
00558  */
00559 XPT_PUBLIC_API(PRBool)
00560 XPT_DoIID(XPTCursor *cursor, nsID *iidp)
00561 {
00562     int i;
00563 
00564     if (!XPT_Do32(cursor, &iidp->m0) ||
00565         !XPT_Do16(cursor, &iidp->m1) ||
00566         !XPT_Do16(cursor, &iidp->m2))
00567         return PR_FALSE;
00568 
00569     for (i = 0; i < 8; i++)
00570         if (!XPT_Do8(cursor, (PRUint8 *)&iidp->m3[i]))
00571             return PR_FALSE;
00572 
00573     return PR_TRUE;
00574 }
00575 
00576 XPT_PUBLIC_API(PRBool)
00577 XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
00578 {
00579     return XPT_Do32(cursor, (PRUint32 *)u64p) &&
00580         XPT_Do32(cursor, ((PRUint32 *)u64p) + 1);
00581 }
00582 
00583 /*
00584  * When we're writing 32- or 16-bit quantities, we write a byte at a time to
00585  * avoid alignment issues.  Someone could come and optimize this to detect
00586  * well-aligned cases and do a single store, if they cared.  I might care
00587  * later.
00588  */
00589 XPT_PUBLIC_API(PRBool)
00590 XPT_Do32(XPTCursor *cursor, PRUint32 *u32p)
00591 {
00592     union {
00593         PRUint8 b8[4];
00594         PRUint32 b32;
00595     } u;
00596 
00597     if (!CHECK_COUNT(cursor, 4))
00598         return PR_FALSE;
00599 
00600     if (ENCODING(cursor)) {
00601         u.b32 = XPT_SWAB32(*u32p);
00602         CURS_POINT(cursor) = u.b8[0];
00603         cursor->offset++;
00604         CURS_POINT(cursor) = u.b8[1];
00605         cursor->offset++;
00606         CURS_POINT(cursor) = u.b8[2];
00607         cursor->offset++;
00608         CURS_POINT(cursor) = u.b8[3];
00609     } else {
00610         u.b8[0] = CURS_POINT(cursor);
00611         cursor->offset++;
00612         u.b8[1] = CURS_POINT(cursor);
00613         cursor->offset++;
00614         u.b8[2] = CURS_POINT(cursor);
00615         cursor->offset++;
00616         u.b8[3] = CURS_POINT(cursor);
00617         *u32p = XPT_SWAB32(u.b32);
00618     }
00619     cursor->offset++;
00620     return PR_TRUE;
00621 }
00622 
00623 XPT_PUBLIC_API(PRBool)
00624 XPT_Do16(XPTCursor *cursor, PRUint16 *u16p)
00625 {
00626     union {
00627         PRUint8 b8[2];
00628         PRUint16 b16;
00629     } u;
00630 
00631     if (!CHECK_COUNT(cursor, 2))
00632         return PR_FALSE;
00633 
00634     if (ENCODING(cursor)) {
00635         u.b16 = XPT_SWAB16(*u16p);
00636         CURS_POINT(cursor) = u.b8[0];
00637         cursor->offset++;
00638         CURS_POINT(cursor) = u.b8[1];
00639     } else {
00640         u.b8[0] = CURS_POINT(cursor);
00641         cursor->offset++;
00642         u.b8[1] = CURS_POINT(cursor);
00643         *u16p = XPT_SWAB16(u.b16);
00644     }
00645     cursor->offset++;
00646 
00647     return PR_TRUE;
00648 }
00649 
00650 XPT_PUBLIC_API(PRBool)
00651 XPT_Do8(XPTCursor *cursor, PRUint8 *u8p)
00652 {
00653     if (!CHECK_COUNT(cursor, 1))
00654         return PR_FALSE;
00655     if (cursor->state->mode == XPT_ENCODE)
00656         CURS_POINT(cursor) = *u8p;
00657     else
00658         *u8p = CURS_POINT(cursor);
00659 
00660     cursor->offset++;
00661 
00662     return PR_TRUE;
00663 }
00664 
00665