LCOV - code coverage report
Current view: directory - xpcom/typelib/xpt/src - xpt_xdr.c (source / functions) Found Hit Coverage
Test: app.info Lines: 273 121 44.3 %
Date: 2012-06-02 Functions: 7 4 57.1 %

       1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /* Implementation of XDR primitives. */
      39                 : 
      40                 : #include "xpt_xdr.h"
      41                 : #include "nspr.h"
      42                 : #include "nscore.h"
      43                 : #include <string.h>             /* strchr */
      44                 : 
      45                 : static PRBool
      46                 : CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
      47                 :                    XPTCursor *new_cursor, PRBool *already);
      48                 : 
      49                 : #define ENCODING(cursor)                                                      \
      50                 :   ((cursor)->state->mode == XPT_ENCODE)
      51                 : 
      52                 : #define CURS_POOL_OFFSET_RAW(cursor)                                          \
      53                 :   ((cursor)->pool == XPT_HEADER                                               \
      54                 :    ? (cursor)->offset                                                         \
      55                 :    : (XPT_ASSERT((cursor)->state->data_offset),                               \
      56                 :       (cursor)->offset + (cursor)->state->data_offset))
      57                 : 
      58                 : #define CURS_POOL_OFFSET(cursor)                                              \
      59                 :   (CURS_POOL_OFFSET_RAW(cursor) - 1)
      60                 : 
      61                 : /* can be used as lvalue */
      62                 : #define CURS_POINT(cursor)                                                    \
      63                 :   ((cursor)->state->pool->data[CURS_POOL_OFFSET(cursor)])
      64                 : 
      65                 : #if defined(DEBUG_shaver) || defined(DEBUG_jband) || defined(DEBUG_mccabe)
      66                 : #define DBG(x) printf x
      67                 : #else
      68                 : #define DBG(x) (0)
      69                 : #endif
      70                 : 
      71                 : /* XXX fail if XPT_DATA and !state->data_offset */
      72                 : #define CHECK_COUNT_(cursor, space)                                           \
      73                 :  /* if we're in the header, then exceeding the data_offset is illegal */      \
      74                 : ((cursor)->pool == XPT_HEADER ?                                               \
      75                 :  (ENCODING(cursor) &&                                                         \
      76                 :   ((cursor)->state->data_offset &&                                            \
      77                 :    ((cursor)->offset - 1 + (space) > (cursor)->state->data_offset))           \
      78                 :   ? (DBG(("no space left in HEADER %d + %d > %d\n", (cursor)->offset,         \
      79                 :           (space), (cursor)->state->data_offset)) && PR_FALSE)                \
      80                 :   : PR_TRUE) :                                                                \
      81                 :  /* if we're in the data area and we're about to exceed the allocation */     \
      82                 :  (CURS_POOL_OFFSET(cursor) + (space) > (cursor)->state->pool->allocated ?     \
      83                 :   /* then grow if we're in ENCODE mode */                                     \
      84                 :   (ENCODING(cursor) ? GrowPool((cursor)->state->arena,                        \
      85                 :                                (cursor)->state->pool,                         \
      86                 :                                (cursor)->state->pool->allocated,              \
      87                 :                                0, CURS_POOL_OFFSET(cursor) + (space))         \
      88                 :    /* and fail if we're in DECODE mode */                                     \
      89                 :    : (DBG(("can't extend in DECODE")) && PR_FALSE))                           \
      90                 :   /* otherwise we're OK */                                                    \
      91                 :   : PR_TRUE))
      92                 : 
      93                 : #define CHECK_COUNT(cursor, space)                                            \
      94                 :   (CHECK_COUNT_(cursor, space)                                                \
      95                 :    ? PR_TRUE                                                                  \
      96                 :    : (XPT_ASSERT(0),                                                          \
      97                 :       fprintf(stderr, "FATAL: can't no room for %d in cursor\n", space),      \
      98                 :       PR_FALSE))
      99                 : 
     100                 : /* increase the data allocation for the pool by XPT_GROW_CHUNK */
     101                 : #define XPT_GROW_CHUNK  8192
     102                 : 
     103                 : /*
     104                 :  * quick and dirty hardcoded hashtable, to avoid dependence on nspr or glib.
     105                 :  * XXXmccabe it might turn out that we could use a simpler data structure here.
     106                 :  */
     107                 : typedef struct XPTHashRecord {
     108                 :     void *key;
     109                 :     void *value;
     110                 :     struct XPTHashRecord *next;
     111                 : } XPTHashRecord;
     112                 : 
     113                 : #define XPT_HASHSIZE 512
     114                 : 
     115                 : struct XPTHashTable {  /* it's already typedef'ed from before. */
     116                 :     XPTHashRecord *buckets[XPT_HASHSIZE];
     117                 :     XPTArena *arena;
     118                 : };
     119                 : 
     120                 : static XPTHashTable *
     121          218497 : XPT_NewHashTable(XPTArena *arena) {
     122                 :     XPTHashTable *table;
     123          218497 :     table = XPT_NEWZAP(arena, XPTHashTable);
     124          218497 :     if (table)
     125          218497 :         table->arena = arena;
     126          218497 :     return table;
     127                 : }
     128                 : 
     129       115268465 : static void trimrecord(XPTArena* arena, XPTHashRecord *record) {
     130       115268465 :     if (record == NULL)
     131       111870464 :         return;
     132         3398001 :     trimrecord(arena, record->next);
     133         3398001 :     XPT_DELETE(arena, record);
     134                 : }
     135                 : 
     136                 : static void
     137          218497 : XPT_HashTableDestroy(XPTHashTable *table) {
     138                 :     int i;
     139       112088961 :     for (i = 0; i < XPT_HASHSIZE; i++)
     140       111870464 :         trimrecord(table->arena, table->buckets[i]);
     141          218497 :     XPT_FREE(table->arena, table);
     142          218497 : }
     143                 : 
     144                 : static void *
     145         3398001 : XPT_HashTableAdd(XPTHashTable *table, void *key, void *value) {
     146         6796002 :     XPTHashRecord **bucketloc = table->buckets +
     147         3398001 :         (NS_PTR_TO_UINT32(key) % XPT_HASHSIZE);
     148                 :     XPTHashRecord *bucket;
     149                 : 
     150         6811611 :     while (*bucketloc != NULL)
     151           15609 :         bucketloc = &((*bucketloc)->next);
     152                 : 
     153         3398001 :     bucket = XPT_NEW(table->arena, XPTHashRecord);
     154         3398001 :     bucket->key = key;
     155         3398001 :     bucket->value = value;
     156         3398001 :     bucket->next = NULL;
     157         3398001 :     *bucketloc = bucket;
     158         3398001 :     return value;
     159                 : }
     160                 : 
     161                 : static void *
     162               0 : XPT_HashTableLookup(XPTHashTable *table, void *key) {
     163               0 :     XPTHashRecord *bucket = table->buckets[NS_PTR_TO_UINT32(key) % XPT_HASHSIZE];
     164               0 :     while (bucket != NULL) {
     165               0 :         if (bucket->key == key)
     166               0 :             return bucket->value;
     167               0 :         bucket = bucket->next;
     168                 :     }
     169               0 :     return NULL;
     170                 : }
     171                 : 
     172                 : XPT_PUBLIC_API(XPTState *)
     173                 : XPT_NewXDRState(XPTMode mode, char *data, PRUint32 len)
     174                 : {
     175                 :     XPTState *state;
     176                 :     XPTArena *arena;
     177                 : 
     178          218497 :     arena = XPT_NewArena(512, sizeof(double), "an XDRState");
     179          218497 :     if (!arena)
     180               0 :         return NULL;
     181                 : 
     182          218497 :     state = XPT_NEWZAP(arena, XPTState);
     183          218497 :     if (!state)
     184               0 :         goto err_free_arena;
     185                 : 
     186          218497 :     state->arena = arena;
     187          218497 :     state->mode = mode;
     188          218497 :     state->pool = XPT_NEW(arena, XPTDatapool);
     189          218497 :     state->next_cursor[0] = state->next_cursor[1] = 1;
     190          218497 :     if (!state->pool)
     191               0 :         goto err_free_state;
     192                 : 
     193          218497 :     state->pool->count = 0;
     194          218497 :     state->pool->offset_map = XPT_NewHashTable(arena);
     195                 : 
     196          218497 :     if (!state->pool->offset_map)
     197               0 :         goto err_free_pool;
     198          218497 :     if (mode == XPT_DECODE) {
     199          218497 :         state->pool->data = data;
     200          218497 :         state->pool->allocated = len;
     201                 :     } else {
     202               0 :         state->pool->data = XPT_MALLOC(arena, XPT_GROW_CHUNK);
     203               0 :         if (!state->pool->data)
     204               0 :             goto err_free_hash;
     205               0 :         state->pool->allocated = XPT_GROW_CHUNK;
     206                 :     }
     207                 : 
     208          218497 :     return state;
     209                 : 
     210                 :  err_free_hash:
     211               0 :     XPT_HashTableDestroy(state->pool->offset_map);
     212                 :  err_free_pool:
     213               0 :     XPT_DELETE(arena, state->pool);
     214                 :  err_free_state:
     215               0 :     XPT_DELETE(arena, state);
     216                 :  err_free_arena:
     217               0 :     if (arena)
     218               0 :         XPT_DestroyArena(arena);
     219               0 :     return NULL;
     220                 : }
     221                 : 
     222                 : XPT_PUBLIC_API(void)
     223                 : XPT_DestroyXDRState(XPTState *state)
     224                 : {
     225          218497 :     XPTArena *arena = state->arena;
     226                 : 
     227          218497 :     if (state->pool->offset_map)
     228          218497 :         XPT_HashTableDestroy(state->pool->offset_map);
     229          218497 :     if (state->mode == XPT_ENCODE)
     230               0 :         XPT_DELETE(arena, state->pool->data);
     231          218497 :     XPT_DELETE(arena, state->pool);
     232          218497 :     XPT_DELETE(arena, state);
     233          218497 :     if (arena)
     234          218497 :         XPT_DestroyArena(arena);
     235          218497 : }
     236                 : 
     237                 : XPT_PUBLIC_API(void)
     238                 : XPT_GetXDRDataLength(XPTState *state, XPTPool pool, PRUint32 *len)
     239                 : {
     240               0 :     *len = state->next_cursor[pool] - 1;
     241               0 : }
     242                 : 
     243                 : XPT_PUBLIC_API(void)
     244                 : XPT_GetXDRData(XPTState *state, XPTPool pool, char **data, PRUint32 *len)
     245                 : {
     246               0 :     if (pool == XPT_HEADER) {
     247               0 :         *data = state->pool->data;
     248                 :     } else {
     249               0 :         *data = state->pool->data + state->data_offset;
     250                 :     }
     251               0 :     *len = state->next_cursor[pool] - 1;
     252               0 : }
     253                 : 
     254                 : /* All offsets are 1-based */
     255                 : XPT_PUBLIC_API(void)
     256                 : XPT_DataOffset(XPTState *state, PRUint32 *data_offsetp)
     257                 : {
     258          218497 :     if (state->mode == XPT_DECODE)
     259          218497 :         XPT_SetDataOffset(state, *data_offsetp);
     260                 :     else
     261               0 :         *data_offsetp = state->data_offset;
     262          218497 : }
     263                 : 
     264                 : /* if 'exact' is set use that, else grow by the next chunk but
     265                 :  * be sure to grow no less that 'at_least' so that we can't get
     266                 :  * behind on required space.
     267                 :  */
     268                 : static PRBool
     269               0 : GrowPool(XPTArena *arena, XPTDatapool *pool, PRUint32 old_size, 
     270                 :          PRUint32 exact, PRUint32 at_least)
     271                 : {
     272                 :     PRUint32 total_size;
     273                 :     char *newdata;
     274                 : 
     275               0 :     if (exact) {
     276               0 :         XPT_ASSERT(exact > pool->allocated);
     277               0 :         total_size = exact;
     278                 :     } else {
     279               0 :         total_size = pool->allocated + XPT_GROW_CHUNK;
     280               0 :         if (at_least > total_size)
     281               0 :             total_size = at_least;
     282                 :     }
     283                 : 
     284               0 :     newdata = XPT_MALLOC(arena, total_size);
     285               0 :     if (!newdata)
     286               0 :         return PR_FALSE;
     287               0 :     if (pool->data) {
     288               0 :         if (old_size)
     289               0 :             memcpy(newdata, pool->data, old_size);
     290               0 :         XPT_FREE(arena, pool->data);
     291                 :     }
     292               0 :     pool->data = newdata;
     293               0 :     pool->allocated = total_size;
     294               0 :     return PR_TRUE;
     295                 : }
     296                 : 
     297                 : XPT_PUBLIC_API(void)
     298                 : XPT_SetDataOffset(XPTState *state, PRUint32 data_offset)
     299                 : {
     300          218497 :    state->data_offset = data_offset;
     301                 :    /* make sure we've allocated enough space for the header */
     302          218497 :    if (state->mode == XPT_ENCODE &&
     303               0 :        data_offset > state->pool->allocated) {
     304               0 :        (void)GrowPool(state->arena, state->pool, state->pool->allocated, 
     305                 :                       data_offset, 0);
     306                 :    }
     307          218497 : }
     308                 : 
     309                 : XPT_PUBLIC_API(PRBool)
     310                 : XPT_MakeCursor(XPTState *state, XPTPool pool, PRUint32 len, XPTCursor *cursor)
     311                 : {
     312         3616498 :     cursor->state = state;
     313         3616498 :     cursor->pool = pool;
     314         3616498 :     cursor->bits = 0;
     315         3616498 :     cursor->offset = state->next_cursor[pool];
     316                 : 
     317         3616498 :     if (!(CHECK_COUNT(cursor, len)))
     318               0 :         return PR_FALSE;
     319                 : 
     320                 :     /* this check should be in CHECK_CURSOR */
     321         3616498 :     if (pool == XPT_DATA && !state->data_offset) {
     322               0 :         fprintf(stderr, "no data offset for XPT_DATA cursor!\n");
     323               0 :         return PR_FALSE;
     324                 :     }
     325                 : 
     326         3616498 :     state->next_cursor[pool] += len;
     327                 : 
     328         3616498 :     return PR_TRUE;
     329                 : }
     330                 : 
     331                 : XPT_PUBLIC_API(PRBool)
     332                 : XPT_SeekTo(XPTCursor *cursor, PRUint32 offset)
     333                 : {
     334                 :     /* XXX do some real checking and update len and stuff */
     335          218497 :     cursor->offset = offset;
     336          218497 :     return PR_TRUE;
     337                 : }
     338                 : 
     339                 : XPT_PUBLIC_API(XPTString *)
     340                 : XPT_NewString(XPTArena *arena, PRUint16 length, char *bytes)
     341                 : {
     342               0 :     XPTString *str = XPT_NEW(arena, XPTString);
     343               0 :     if (!str)
     344               0 :         return NULL;
     345               0 :     str->length = length;
     346                 :     /* Alloc one extra to store the trailing nul. */
     347               0 :     str->bytes = XPT_MALLOC(arena, length + 1u);
     348               0 :     if (!str->bytes) {
     349               0 :         XPT_DELETE(arena, str);
     350               0 :         return NULL;
     351                 :     }
     352               0 :     memcpy(str->bytes, bytes, length);
     353                 :     /* nul-terminate it. */
     354               0 :     str->bytes[length] = '\0';
     355               0 :     return str;
     356                 : }
     357                 : 
     358                 : XPT_PUBLIC_API(XPTString *)
     359                 : XPT_NewStringZ(XPTArena *arena, char *bytes)
     360                 : {
     361               0 :     PRUint32 length = strlen(bytes);
     362               0 :     if (length > 0xffff)
     363               0 :         return NULL;            /* too long */
     364               0 :     return XPT_NewString(arena, (PRUint16)length, bytes);
     365                 : }
     366                 : 
     367                 : XPT_PUBLIC_API(PRBool)
     368                 : XPT_DoStringInline(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
     369                 : {
     370               0 :     XPTString *str = *strp;
     371               0 :     XPTMode mode = cursor->state->mode;
     372                 :     int i;
     373                 : 
     374               0 :     if (mode == XPT_DECODE) {
     375               0 :         str = XPT_NEWZAP(arena, XPTString);
     376               0 :         if (!str)
     377               0 :             return PR_FALSE;
     378               0 :         *strp = str;
     379                 :     }
     380                 : 
     381               0 :     if (!XPT_Do16(cursor, &str->length))
     382               0 :         goto error;
     383                 : 
     384               0 :     if (mode == XPT_DECODE)
     385               0 :         if (!(str->bytes = XPT_MALLOC(arena, str->length + 1u)))
     386               0 :             goto error;
     387                 : 
     388               0 :     for (i = 0; i < str->length; i++)
     389               0 :         if (!XPT_Do8(cursor, (PRUint8 *)&str->bytes[i]))
     390               0 :             goto error_2;
     391                 : 
     392               0 :     if (mode == XPT_DECODE)
     393               0 :         str->bytes[str->length] = 0;
     394                 : 
     395               0 :     return PR_TRUE;
     396                 :  error_2:
     397               0 :     XPT_DELETE(arena, str->bytes);
     398                 :  error:
     399               0 :     XPT_DELETE(arena, str);
     400               0 :     return PR_FALSE;
     401                 : }
     402                 : 
     403                 : XPT_PUBLIC_API(PRBool)
     404                 : XPT_DoString(XPTArena *arena, XPTCursor *cursor, XPTString **strp)
     405                 : {
     406                 :     XPTCursor my_cursor;
     407               0 :     XPTString *str = *strp;
     408                 :     PRBool already;
     409                 : 
     410               0 :     XPT_PREAMBLE_NO_ALLOC(cursor, strp, XPT_DATA, str->length + 2u, my_cursor,
     411                 :                           already)
     412                 : 
     413               0 :     return XPT_DoStringInline(arena, &my_cursor, strp);
     414                 : }
     415                 : 
     416                 : XPT_PUBLIC_API(PRBool)
     417                 : XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp)
     418                 : {
     419                 :     XPTCursor my_cursor;
     420        25952702 :     char *ident = *identp;
     421        25952702 :     PRUint32 offset = 0;
     422                 : 
     423        25952702 :     XPTMode mode = cursor->state->mode;
     424                 : 
     425        25952702 :     if (mode == XPT_DECODE) {
     426                 :         char *start, *end;
     427                 :         int len;
     428                 : 
     429        25952702 :         if (!XPT_Do32(cursor, &offset))
     430               0 :             return PR_FALSE;
     431                 : 
     432        25952702 :         if (!offset) {
     433         3398001 :             *identp = NULL;
     434         3398001 :             return PR_TRUE;
     435                 :         }
     436                 : 
     437        22554701 :         my_cursor.pool = XPT_DATA;
     438        22554701 :         my_cursor.offset = offset;
     439        22554701 :         my_cursor.state = cursor->state;
     440        22554701 :         start = &CURS_POINT(&my_cursor);
     441                 : 
     442        22554701 :         end = strchr(start, 0); /* find the end of the string */
     443        22554701 :         if (!end) {
     444               0 :             fprintf(stderr, "didn't find end of string on decode!\n");
     445               0 :             return PR_FALSE;
     446                 :         }
     447        22554701 :         len = end - start;
     448        22554701 :         XPT_ASSERT(len > 0);
     449                 : 
     450        22554701 :         ident = XPT_MALLOC(arena, len + 1u);
     451        22554701 :         if (!ident)
     452               0 :             return PR_FALSE;
     453                 : 
     454        22554701 :         memcpy(ident, start, (size_t)len);
     455        22554701 :         ident[len] = 0;
     456        22554701 :         *identp = ident;
     457                 : 
     458                 :     } else {
     459                 : 
     460               0 :         if (!ident) {
     461               0 :             offset = 0;
     462               0 :             if (!XPT_Do32(cursor, &offset))
     463               0 :                 return PR_FALSE;
     464               0 :             return PR_TRUE;
     465                 :         }
     466                 : 
     467               0 :         if (!XPT_MakeCursor(cursor->state, XPT_DATA, strlen(ident) + 1,
     468               0 :                             &my_cursor) ||
     469               0 :             !XPT_Do32(cursor, &my_cursor.offset))
     470               0 :             return PR_FALSE;
     471                 : 
     472               0 :         while(*ident)
     473               0 :             if (!XPT_Do8(&my_cursor, (PRUint8 *)ident++))
     474               0 :                 return PR_FALSE;
     475               0 :         if (!XPT_Do8(&my_cursor, (PRUint8 *)ident)) /* write trailing zero */
     476               0 :             return PR_FALSE;
     477                 :     }
     478                 : 
     479        22554701 :     return PR_TRUE;
     480                 : }
     481                 : 
     482                 : /* XXXjband it bothers me that this is one hashtable instead of two.
     483                 :  */
     484                 : XPT_PUBLIC_API(PRUint32)
     485                 : XPT_GetOffsetForAddr(XPTCursor *cursor, void *addr)
     486                 : {
     487               0 :     XPTHashTable *table = cursor->state->pool->offset_map;
     488               0 :     return NS_PTR_TO_UINT32(XPT_HashTableLookup(table, addr));
     489                 : }
     490                 : 
     491                 : XPT_PUBLIC_API(PRBool)
     492                 : XPT_SetOffsetForAddr(XPTCursor *cursor, void *addr, PRUint32 offset)
     493                 : {
     494         3398001 :     return XPT_HashTableAdd(cursor->state->pool->offset_map,
     495                 :                             addr, NS_INT32_TO_PTR(offset)) != NULL;
     496                 : }
     497                 : 
     498                 : XPT_PUBLIC_API(PRBool)
     499                 : XPT_SetAddrForOffset(XPTCursor *cursor, PRUint32 offset, void *addr)
     500                 : {
     501               0 :     return XPT_HashTableAdd(cursor->state->pool->offset_map,
     502                 :                             NS_INT32_TO_PTR(offset), addr) != NULL;
     503                 : }
     504                 : 
     505                 : XPT_PUBLIC_API(void *)
     506                 : XPT_GetAddrForOffset(XPTCursor *cursor, PRUint32 offset)
     507                 : {
     508               0 :     return XPT_HashTableLookup(cursor->state->pool->offset_map,
     509                 :                                NS_INT32_TO_PTR(offset));
     510                 : }
     511                 : 
     512                 : /* Used by XPT_PREAMBLE_NO_ALLOC. */
     513                 : static PRBool
     514               0 : CheckForRepeat(XPTCursor *cursor, void **addrp, XPTPool pool, PRUint32 len,
     515                 :                XPTCursor *new_cursor, PRBool *already)
     516                 : {
     517               0 :     void *last = *addrp;
     518                 : 
     519               0 :     *already = PR_FALSE;
     520               0 :     new_cursor->state = cursor->state;
     521               0 :     new_cursor->pool = pool;
     522               0 :     new_cursor->bits = 0;
     523                 : 
     524               0 :     if (cursor->state->mode == XPT_DECODE) {
     525                 : 
     526               0 :         last = XPT_GetAddrForOffset(new_cursor, new_cursor->offset);
     527                 : 
     528               0 :         if (last) {
     529               0 :             *already = PR_TRUE;
     530               0 :             *addrp = last;
     531                 :         }
     532                 : 
     533                 :     } else {
     534                 : 
     535               0 :         new_cursor->offset = XPT_GetOffsetForAddr(new_cursor, last);
     536               0 :         if (new_cursor->offset) {
     537               0 :             *already = PR_TRUE;
     538               0 :             return PR_TRUE;
     539                 :         }
     540                 : 
     541                 :         /* haven't already found it, so allocate room for it. */
     542               0 :         if (!XPT_MakeCursor(cursor->state, pool, len, new_cursor) ||
     543               0 :             !XPT_SetOffsetForAddr(new_cursor, *addrp, new_cursor->offset))
     544               0 :             return PR_FALSE;
     545                 :     }
     546               0 :     return PR_TRUE;
     547                 : }
     548                 : 
     549                 : /*
     550                 :  * IIDs are written in struct order, in the usual big-endian way.  From the
     551                 :  * typelib file spec:
     552                 :  *
     553                 :  *   "For example, this IID:
     554                 :  *     {00112233-4455-6677-8899-aabbccddeeff}
     555                 :  *   is converted to the 128-bit value
     556                 :  *     0x00112233445566778899aabbccddeeff
     557                 :  *   Note that the byte storage order corresponds to the layout of the nsIID
     558                 :  *   C-struct on a big-endian architecture."
     559                 :  *
     560                 :  * (http://www.mozilla.org/scriptable/typelib_file.html#iid)
     561                 :  */
     562                 : XPT_PUBLIC_API(PRBool)
     563                 : XPT_DoIID(XPTCursor *cursor, nsID *iidp)
     564                 : {
     565                 :     int i;
     566                 : 
     567         6796002 :     if (!XPT_Do32(cursor, &iidp->m0) ||
     568         6796002 :         !XPT_Do16(cursor, &iidp->m1) ||
     569         3398001 :         !XPT_Do16(cursor, &iidp->m2))
     570               0 :         return PR_FALSE;
     571                 : 
     572        30582009 :     for (i = 0; i < 8; i++)
     573        27184008 :         if (!XPT_Do8(cursor, (PRUint8 *)&iidp->m3[i]))
     574               0 :             return PR_FALSE;
     575                 : 
     576         3398001 :     return PR_TRUE;
     577                 : }
     578                 : 
     579                 : XPT_PUBLIC_API(PRBool)
     580                 : XPT_Do64(XPTCursor *cursor, PRInt64 *u64p)
     581                 : {
     582               0 :     return XPT_Do32(cursor, (PRUint32 *)u64p) &&
     583               0 :         XPT_Do32(cursor, ((PRUint32 *)u64p) + 1);
     584                 : }
     585                 : 
     586                 : /*
     587                 :  * When we're writing 32- or 16-bit quantities, we write a byte at a time to
     588                 :  * avoid alignment issues.  Someone could come and optimize this to detect
     589                 :  * well-aligned cases and do a single store, if they cared.  I might care
     590                 :  * later.
     591                 :  */
     592                 : XPT_PUBLIC_API(PRBool)
     593                 : XPT_Do32(XPTCursor *cursor, PRUint32 *u32p)
     594                 : {
     595                 :     union {
     596                 :         PRUint8 b8[4];
     597                 :         PRUint32 b32;
     598                 :     } u;
     599                 : 
     600        36317402 :     if (!CHECK_COUNT(cursor, 4))
     601               0 :         return PR_FALSE;
     602                 : 
     603        36317402 :     if (ENCODING(cursor)) {
     604               0 :         u.b32 = XPT_SWAB32(*u32p);
     605               0 :         CURS_POINT(cursor) = u.b8[0];
     606               0 :         cursor->offset++;
     607               0 :         CURS_POINT(cursor) = u.b8[1];
     608               0 :         cursor->offset++;
     609               0 :         CURS_POINT(cursor) = u.b8[2];
     610               0 :         cursor->offset++;
     611               0 :         CURS_POINT(cursor) = u.b8[3];
     612                 :     } else {
     613        36317402 :         u.b8[0] = CURS_POINT(cursor);
     614        36317402 :         cursor->offset++;
     615        36317402 :         u.b8[1] = CURS_POINT(cursor);
     616        36317402 :         cursor->offset++;
     617        36317402 :         u.b8[2] = CURS_POINT(cursor);
     618        36317402 :         cursor->offset++;
     619        36317402 :         u.b8[3] = CURS_POINT(cursor);
     620        36317402 :         *u32p = XPT_SWAB32(u.b32);
     621                 :     }
     622        36317402 :     cursor->offset++;
     623        36317402 :     return PR_TRUE;
     624                 : }
     625                 : 
     626                 : XPT_PUBLIC_API(PRBool)
     627                 : XPT_Do16(XPTCursor *cursor, PRUint16 *u16p)
     628                 : {
     629                 :     union {
     630                 :         PRUint8 b8[2];
     631                 :         PRUint16 b16;
     632                 :     } u;
     633                 : 
     634        20878564 :     if (!CHECK_COUNT(cursor, 2))
     635               0 :         return PR_FALSE;
     636                 : 
     637        20878564 :     if (ENCODING(cursor)) {
     638               0 :         u.b16 = XPT_SWAB16(*u16p);
     639               0 :         CURS_POINT(cursor) = u.b8[0];
     640               0 :         cursor->offset++;
     641               0 :         CURS_POINT(cursor) = u.b8[1];
     642                 :     } else {
     643        20878564 :         u.b8[0] = CURS_POINT(cursor);
     644        20878564 :         cursor->offset++;
     645        20878564 :         u.b8[1] = CURS_POINT(cursor);
     646        20878564 :         *u16p = XPT_SWAB16(u.b16);
     647                 :     }
     648        20878564 :     cursor->offset++;
     649                 : 
     650        20878564 :     return PR_TRUE;
     651                 : }
     652                 : 
     653                 : XPT_PUBLIC_API(PRBool)
     654                 : XPT_Do8(XPTCursor *cursor, PRUint8 *u8p)
     655                 : {
     656       145093993 :     if (!CHECK_COUNT(cursor, 1))
     657               0 :         return PR_FALSE;
     658       145093993 :     if (cursor->state->mode == XPT_ENCODE)
     659               0 :         CURS_POINT(cursor) = *u8p;
     660                 :     else
     661       145093993 :         *u8p = CURS_POINT(cursor);
     662                 : 
     663       145093993 :     cursor->offset++;
     664                 : 
     665       145093993 :     return PR_TRUE;
     666                 : }
     667                 : 
     668                 : 

Generated by: LCOV version 1.7