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 :
|