~ubuntu-branches/ubuntu/trusty/ruby-ferret/trusty

« back to all changes in this revision

Viewing changes to ext/posh.c

  • Committer: Bazaar Package Importer
  • Author(s): Antonio Terceiro
  • Date: 2011-07-28 00:02:49 UTC
  • Revision ID: james.westby@ubuntu.com-20110728000249-v0443y69ftcpxwi6
Tags: upstream-0.11.6
ImportĀ upstreamĀ versionĀ 0.11.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
LICENSE:
 
3
 
 
4
Copyright (c) 2004, Brian Hook
 
5
All rights reserved.
 
6
 
 
7
Redistribution and use in source and binary forms, with or without
 
8
modification, are permitted provided that the following conditions are
 
9
met:
 
10
 
 
11
    * Redistributions of source code must retain the above copyright
 
12
      notice, this list of conditions and the following disclaimer.
 
13
 
 
14
    * Redistributions in binary form must reproduce the above
 
15
      copyright notice, this list of conditions and the following
 
16
      disclaimer in the documentation and/or other materials provided
 
17
      with the distribution.
 
18
 
 
19
    * The names of this package'ss contributors contributors may not
 
20
      be used to endorse or promote products derived from this
 
21
      software without specific prior written permission.
 
22
 
 
23
 
 
24
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
25
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
26
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
27
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
28
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
29
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
30
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
31
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
32
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
33
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
34
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
35
*/
 
36
/** 
 
37
 @file    posh.c
 
38
 @author  Brian Hook
 
39
 @date    2002
 
40
 @brief   Portable Open Source Harness primary source file
 
41
*/
 
42
#include "posh.h"
 
43
 
 
44
#if !defined FORCE_DOXYGEN
 
45
 
 
46
#if !defined POSH_NO_FLOAT
 
47
#  define POSH_FLOAT_STRING "enabled"
 
48
#else
 
49
#  define POSH_FLOAT_STRING "disabled"
 
50
#endif
 
51
 
 
52
#if defined POSH_64BIT_INTEGER
 
53
#  define POSH_64BIT_INTEGER_STRING "yes"
 
54
#else
 
55
#  define POSH_64BIT_INTEGER_STRING "no"
 
56
#endif
 
57
 
 
58
#if defined POSH_64BIT_POINTER
 
59
#  define POSH_POINTER_STRING "64-bits"
 
60
#else
 
61
#  define POSH_POINTER_STRING "32-bits"
 
62
#endif
 
63
 
 
64
#if defined POSH_LITTLE_ENDIAN
 
65
#  define IS_BIG_ENDIAN    0
 
66
 
 
67
#  define NATIVE16  POSH_LittleU16
 
68
#  define NATIVE32  POSH_LittleU32
 
69
#  define NATIVE64  POSH_LittleU64
 
70
#  define FOREIGN16 POSH_BigU16
 
71
#  define FOREIGN32 POSH_BigU32
 
72
#  define FOREIGN64 POSH_BigU64
 
73
#else
 
74
#  define IS_BIG_ENDIAN    1
 
75
 
 
76
#  define NATIVE16  POSH_BigU16
 
77
#  define NATIVE32  POSH_BigU32
 
78
#  define NATIVE64  POSH_BigU64
 
79
#  define FOREIGN16 POSH_LittleU16
 
80
#  define FOREIGN32 POSH_LittleU32
 
81
#  define FOREIGN64 POSH_LittleU64
 
82
#endif /* POSH_LITTLE_ENDIAN */
 
83
 
 
84
static 
 
85
int 
 
86
s_testBigEndian( void )
 
87
{
 
88
   union 
 
89
   {
 
90
      posh_byte_t c[ 4 ];
 
91
      posh_u32_t  i;
 
92
   } u;
 
93
 
 
94
   u.i= 1;
 
95
 
 
96
   if ( u.c[ 0 ] == 1 )
 
97
   {
 
98
      return 0;
 
99
   }
 
100
   return 1;
 
101
}
 
102
 
 
103
static
 
104
const char *
 
105
s_testSerialization( void )
 
106
{
 
107
   posh_byte_t serbuf[ 8 ];
 
108
   posh_u16_t  tmp16;
 
109
   posh_u32_t  tmp32;
 
110
 
 
111
   /* 16-bit serialization */
 
112
   POSH_WriteU16ToLittle( serbuf, 0xABCD );
 
113
   if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD )
 
114
   {
 
115
      return "*ERROR: failed little-endian 16-bit serialization test";
 
116
   }
 
117
 
 
118
   POSH_WriteU16ToBig( serbuf, 0xABCD );
 
119
   if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD )
 
120
   {
 
121
      return "*ERROR: failed big-endian 16-bit serialization test";
 
122
   }
 
123
 
 
124
   /* 32-bit serialization */
 
125
   POSH_WriteU32ToLittle( serbuf, 0xABCD1234L );
 
126
   if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 )
 
127
   {
 
128
      return "*ERROR: failed little-endian 32-bit serialization test";
 
129
   }
 
130
 
 
131
   POSH_WriteU32ToBig( serbuf, 0xABCD1234L );
 
132
   if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 )
 
133
   {
 
134
      return "*ERROR: failed big-endian 32-bit serialization test";
 
135
   }
 
136
 
 
137
#if defined POSH_64BIT_INTEGER
 
138
   {
 
139
#define REF64 POSH_U64(0xFEDCBA9876543210)
 
140
 
 
141
      posh_u64_t tmp64;
 
142
 
 
143
      POSH_WriteU64ToLittle( serbuf, REF64 );
 
144
 
 
145
      if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 )
 
146
      {
 
147
         return "*ERROR: failed little-endian 64-bit serialization test";
 
148
      }
 
149
 
 
150
      POSH_WriteU64ToBig( serbuf, REF64 );
 
151
 
 
152
      if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 )
 
153
      {
 
154
         return "*ERROR: failed big-endian 64-bit serialization test";
 
155
      }
 
156
   }
 
157
#endif
 
158
 
 
159
   return 0;
 
160
}
 
161
 
 
162
#if !defined POSH_NO_FLOAT
 
163
static
 
164
const char *
 
165
s_testFloatingPoint( void )
 
166
{
 
167
   float fRef = 10.0f/30.0f;
 
168
   double dRef = 10.0/30.0;
 
169
   posh_byte_t dbuf[ 8 ];
 
170
   float fTmp;
 
171
   double dTmp;
 
172
 
 
173
   fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) );
 
174
 
 
175
   if ( fTmp != fRef )
 
176
   {
 
177
      return "*ERROR: POSH little endian floating point conversion failed.  Please report this to poshlib@poshlib.org!\n";
 
178
   }
 
179
 
 
180
   fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) );
 
181
   if ( fTmp != fRef )
 
182
   {
 
183
      return "*ERROR: POSH big endian floating point conversion failed.  Please report this to poshlib@poshlib.org!\n";
 
184
   }
 
185
 
 
186
   POSH_DoubleBits( dRef, dbuf );
 
187
 
 
188
   dTmp = POSH_DoubleFromBits( dbuf );
 
189
 
 
190
   if ( dTmp != dRef )
 
191
   {
 
192
      return "*ERROR: POSH double precision floating point serialization failed.  Please report this to poshlib@poshlib.org!\n";
 
193
   }
 
194
 
 
195
   return 0;
 
196
}
 
197
#endif /* !defined POSH_NO_FLOAT */
 
198
 
 
199
static
 
200
const char *
 
201
s_testEndianess( void )
 
202
{
 
203
   /* check endianess */
 
204
   if ( s_testBigEndian() != IS_BIG_ENDIAN )
 
205
   {
 
206
      return "*ERROR: POSH compile time endianess does not match run-time endianess verification.  Please report this to poshlib@poshlib.org!\n";
 
207
   }
 
208
 
 
209
   /* make sure our endian swap routines work */
 
210
   if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) || 
 
211
        ( FOREIGN32( 0x11223344L ) != 0x44332211L ) ||
 
212
        ( NATIVE16( 0x1234 ) != 0x1234 ) ||
 
213
        ( FOREIGN16( 0x1234 ) != 0x3412 ) )
 
214
   {
 
215
      return "*ERROR: POSH endianess macro selection failed.  Please report this to poshlib@poshlib.org!\n";
 
216
   }
 
217
 
 
218
   /* test serialization routines */
 
219
 
 
220
   return 0;
 
221
}
 
222
#endif /* !defined FORCE_DOXYGEN */
 
223
 
 
224
/**
 
225
  Returns a string describing this platform's basic attributes.  
 
226
 
 
227
  POSH_GetArchString() reports on an architecture's statically determined
 
228
  attributes.  In addition, it will perform run-time verification checks
 
229
  to make sure the various platform specific functions work.  If an error
 
230
  occurs, please contact me at poshlib@poshlib.org so we can try to resolve
 
231
  what the specific failure case is.
 
232
  @returns a string describing this platform on success, or a string in the 
 
233
           form "*ERROR: [text]" on failure.  You can simply check to see if
 
234
           the first character returned is '*' to verify an error condition.
 
235
*/
 
236
const char *
 
237
POSH_GetArchString( void )
 
238
{
 
239
   const char *err;
 
240
   const char *s = "OS:.............."POSH_OS_STRING"\n"
 
241
                   "CPU:............."POSH_CPU_STRING"\n"
 
242
                   "endian:.........."POSH_ENDIAN_STRING"\n"
 
243
                   "ptr size:........"POSH_POINTER_STRING"\n"
 
244
                   "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n"
 
245
                   "floating point..."POSH_FLOAT_STRING"\n"
 
246
                   "compiler........."POSH_COMPILER_STRING"\n";
 
247
 
 
248
   /* test endianess */
 
249
   err = s_testEndianess();
 
250
 
 
251
   if ( err != 0 )
 
252
   {
 
253
      return err;
 
254
   }
 
255
 
 
256
   /* test serialization */
 
257
   err = s_testSerialization();
 
258
 
 
259
   if ( err != 0 )
 
260
   {
 
261
      return err;
 
262
   }
 
263
 
 
264
#if !defined POSH_NO_FLOAT
 
265
   /* check that our floating point support is correct */
 
266
   err = s_testFloatingPoint();
 
267
 
 
268
   if ( err != 0 )
 
269
   {
 
270
      return err;
 
271
   }
 
272
 
 
273
#endif
 
274
 
 
275
   return s;
 
276
}
 
277
 
 
278
/* ---------------------------------------------------------------------------*/
 
279
/*                           BYTE SWAPPING SUPPORT                            */
 
280
/* ---------------------------------------------------------------------------*/
 
281
/** 
 
282
 * Byte swaps a 16-bit unsigned value
 
283
 *
 
284
   @ingroup ByteSwapFunctions
 
285
   @param v [in] unsigned 16-bit input value to swap
 
286
   @returns a byte swapped version of v
 
287
 */
 
288
posh_u16_t
 
289
POSH_SwapU16( posh_u16_t v )
 
290
{
 
291
   posh_u16_t swapped;
 
292
 
 
293
   swapped  = v << 8;
 
294
   swapped |= v >> 8;
 
295
 
 
296
   return swapped;
 
297
}
 
298
 
 
299
/** 
 
300
 * Byte swaps a 16-bit signed value
 
301
 *
 
302
   @ingroup ByteSwapFunctions
 
303
   @param v [in] signed 16-bit input value to swap
 
304
   @returns a byte swapped version of v
 
305
   @remarks This just calls back to the unsigned version, since byte swapping 
 
306
            is independent of sign.  However, we still provide this function to
 
307
            avoid signed/unsigned mismatch compiler warnings.
 
308
 */
 
309
posh_i16_t
 
310
POSH_SwapI16( posh_i16_t v )
 
311
{
 
312
   return ( posh_i16_t ) POSH_SwapU16( v );
 
313
}
 
314
 
 
315
/** 
 
316
 * Byte swaps a 32-bit unsigned value
 
317
 *
 
318
   @ingroup ByteSwapFunctions
 
319
   @param v [in] unsigned 32-bit input value to swap
 
320
   @returns a byte swapped version of v
 
321
 */
 
322
posh_u32_t
 
323
POSH_SwapU32( posh_u32_t v )
 
324
{
 
325
   posh_u32_t swapped;
 
326
 
 
327
   swapped  = ( v & 0xFF ) << 24;
 
328
   swapped |= ( v & 0xFF00 ) << 8;
 
329
   swapped |= ( v >> 8 ) & 0xFF00;
 
330
   swapped |= ( v >> 24 );
 
331
 
 
332
   return swapped;
 
333
}
 
334
 
 
335
/** 
 
336
 * Byte swaps a 32-bit signed value
 
337
 *
 
338
   @ingroup ByteSwapFunctions
 
339
   @param v [in] signed 32-bit input value to swap
 
340
   @returns a byte swapped version of v
 
341
   @remarks This just calls back to the unsigned version, since byte swapping 
 
342
            is independent of sign.  However, we still provide this function to
 
343
            avoid signed/unsigned mismatch compiler warnings.
 
344
 */
 
345
posh_i32_t
 
346
POSH_SwapI32( posh_i32_t v )
 
347
{
 
348
   return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v );
 
349
}
 
350
 
 
351
#if defined POSH_64BIT_INTEGER
 
352
/**
 
353
 * Byte swaps a 64-bit unsigned value
 
354
 
 
355
   @param v [in] a 64-bit input value to swap
 
356
   @ingroup SixtyFourBit
 
357
   @returns a byte swapped version of v
 
358
*/
 
359
posh_u64_t 
 
360
POSH_SwapU64( posh_u64_t v )
 
361
{
 
362
   posh_byte_t tmp;
 
363
   union {
 
364
      posh_byte_t bytes[ 8 ];
 
365
      posh_u64_t  u64;
 
366
   } u;
 
367
 
 
368
   u.u64 = v;
 
369
 
 
370
   tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp;
 
371
   tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp;
 
372
   tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp;
 
373
   tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp;
 
374
 
 
375
   return u.u64;
 
376
}
 
377
 
 
378
/**
 
379
 * Byte swaps a 64-bit signed value
 
380
 
 
381
   @param v [in] a 64-bit input value to swap
 
382
   @ingroup SixtyFourBit
 
383
   @returns a byte swapped version of v
 
384
*/
 
385
posh_i64_t 
 
386
POSH_SwapI64( posh_i64_t v )
 
387
{
 
388
   return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v );
 
389
}
 
390
 
 
391
#endif /* defined POSH_64BIT_INTEGER */
 
392
 
 
393
/* ---------------------------------------------------------------------------*/
 
394
/*                           IN-MEMORY SERIALIZATION                          */
 
395
/* ---------------------------------------------------------------------------*/
 
396
 
 
397
/**
 
398
 * Writes an unsigned 16-bit value to a little endian buffer
 
399
 
 
400
 @ingroup MemoryBuffer
 
401
 @param dst [out] pointer to the destination buffer, may not be NULL.  Alignment doesn't matter.
 
402
 @param value [in] host-endian unsigned 16-bit value
 
403
 @returns a pointer to the location two bytes after dst
 
404
 @remarks does no validation of the inputs
 
405
*/
 
406
posh_u16_t *
 
407
POSH_WriteU16ToLittle( void *dst, posh_u16_t value )
 
408
{
 
409
   posh_u16_t  *p16 = ( posh_u16_t * ) dst;
 
410
   posh_byte_t *p   = ( posh_byte_t * ) dst;
 
411
 
 
412
   p[ 0 ] = value & 0xFF;
 
413
   p[ 1 ] = ( value & 0xFF00) >> 8;
 
414
 
 
415
   return p16 + 1;
 
416
}
 
417
 
 
418
/**
 
419
 * Writes a signed 16-bit value to a little endian buffer
 
420
 
 
421
 @ingroup MemoryBuffer
 
422
 @param dst [out] pointer to the destination buffer, may not be NULL
 
423
 @param value [in] host-endian signed 16-bit value
 
424
 @returns a pointer to the location two bytes after dst
 
425
 @remarks does no validation of the inputs.  This simply calls
 
426
          POSH_WriteU16ToLittle() with appropriate casting.
 
427
*/
 
428
posh_i16_t *
 
429
POSH_WriteI16ToLittle( void *dst, posh_i16_t value )
 
430
{
 
431
   return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value );
 
432
}
 
433
 
 
434
/**
 
435
 * Writes an unsigned 32-bit value to a little endian buffer
 
436
 
 
437
 @ingroup MemoryBuffer
 
438
 @param dst [out] pointer to the destination buffer, may not be NULL
 
439
 @param value [in] host-endian signed 32-bit value
 
440
 @returns a pointer to the location four bytes after dst
 
441
 @remarks does no validation of the inputs.
 
442
*/
 
443
posh_u32_t *
 
444
POSH_WriteU32ToLittle( void *dst, posh_u32_t value )
 
445
{
 
446
   posh_u32_t  *p32   = ( posh_u32_t * ) dst;
 
447
   posh_byte_t *p     = ( posh_byte_t * ) dst;
 
448
 
 
449
   p[ 0 ] = ( value & 0xFF );
 
450
   p[ 1 ] = ( value & 0xFF00 ) >> 8;
 
451
   p[ 2 ] = ( value & 0xFF0000 ) >> 16;
 
452
   p[ 3 ] = ( value & 0xFF000000 ) >> 24;
 
453
 
 
454
   return p32 + 1;
 
455
}
 
456
 
 
457
/**
 
458
 * Writes a signed 32-bit value to a little endian buffer
 
459
 
 
460
 @ingroup MemoryBuffer
 
461
 @param dst [out] pointer to the destination buffer, may not be NULL
 
462
 @param value [in] host-endian signed 32-bit value
 
463
 @returns a pointer to the location four bytes after dst
 
464
 @remarks does no validation of the inputs.  This simply calls
 
465
          POSH_WriteU32ToLittle() with appropriate casting.
 
466
*/
 
467
posh_i32_t *
 
468
POSH_WriteI32ToLittle( void *dst, posh_i32_t value )
 
469
{
 
470
   return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value );
 
471
}
 
472
 
 
473
/**
 
474
 * Writes an unsigned 16-bit value to a big endian buffer
 
475
 
 
476
 @ingroup MemoryBuffer
 
477
 @param dst [out] pointer to the destination buffer, may not be NULL
 
478
 @param value [in] host-endian unsigned 16-bit value
 
479
 @returns a pointer to the location two bytes after dst
 
480
 @remarks does no validation of the inputs
 
481
*/
 
482
posh_u16_t *
 
483
POSH_WriteU16ToBig( void *dst, posh_u16_t value )
 
484
{
 
485
   posh_u16_t *p16 = ( posh_u16_t * ) dst;
 
486
   posh_byte_t *p  = ( posh_byte_t * ) dst;
 
487
 
 
488
   p[ 1 ] = ( value & 0xFF );
 
489
   p[ 0 ] = ( value & 0xFF00 ) >> 8;
 
490
 
 
491
   return p16 + 1;
 
492
}
 
493
 
 
494
/**
 
495
 * Writes a signed 16-bit value to a big endian buffer
 
496
 
 
497
 @ingroup MemoryBuffer
 
498
 @param dst [out] pointer to the destination buffer, may not be NULL
 
499
 @param value [in] host-endian signed 16-bit value
 
500
 @returns a pointer to the location two bytes after dst
 
501
 @remarks does no validation of the inputs.  This simply calls
 
502
          POSH_WriteU16ToLittle() with appropriate casting.
 
503
*/
 
504
posh_i16_t *
 
505
POSH_WriteI16ToBig( void *dst, posh_i16_t value )
 
506
{
 
507
   return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value );
 
508
}
 
509
 
 
510
/**
 
511
 * Writes an unsigned 32-bit value to a big endian buffer
 
512
 
 
513
 @ingroup MemoryBuffer
 
514
 @param dst [out] pointer to the destination buffer, may not be NULL
 
515
 @param value [in] host-endian unsigned 32-bit value
 
516
 @returns a pointer to the location four bytes after dst
 
517
 @remarks does no validation of the inputs.
 
518
*/
 
519
posh_u32_t *
 
520
POSH_WriteU32ToBig( void *dst, posh_u32_t value )
 
521
{
 
522
   posh_u32_t *p32 = ( posh_u32_t * ) dst;
 
523
   posh_byte_t *p  = ( posh_byte_t * ) dst;
 
524
 
 
525
   p[ 3 ] = ( value & 0xFF );
 
526
   p[ 2 ] = ( value & 0xFF00 ) >> 8;
 
527
   p[ 1 ] = ( value & 0xFF0000 ) >> 16;
 
528
   p[ 0 ] = ( value & 0xFF000000 ) >> 24;
 
529
 
 
530
   return p32 + 1;
 
531
}
 
532
 
 
533
/**
 
534
 * Writes a signed 32-bit value to a big endian buffer
 
535
 
 
536
 @ingroup MemoryBuffer
 
537
 @param dst [out] pointer to the destination buffer, may not be NULL
 
538
 @param value [in] host-endian signed 32-bit value
 
539
 @returns a pointer to the location four bytes after dst
 
540
 @remarks does no validation of the inputs.  This simply calls
 
541
          POSH_WriteU32ToBig() with appropriate casting.
 
542
*/
 
543
posh_i32_t *
 
544
POSH_WriteI32ToBig( void *dst, posh_i32_t value )
 
545
{
 
546
   return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value );
 
547
}
 
548
 
 
549
#if defined POSH_64BIT_INTEGER
 
550
/**
 
551
 * Writes an unsigned 64-bit value to a little-endian buffer
 
552
 
 
553
 @ingroup SixtyFourBit
 
554
 @param dst [out] pointer to the destination buffer, may not be NULL
 
555
 @param value [in] host-endian unsigned 64-bit value
 
556
 @returns a pointer to the location eight bytes after dst
 
557
 @remarks does no validation of the inputs.
 
558
*/
 
559
posh_u64_t *
 
560
POSH_WriteU64ToLittle( void *dst, posh_u64_t value )
 
561
{
 
562
   posh_u64_t *p64 = ( posh_u64_t * ) dst;
 
563
   posh_byte_t *p  = ( posh_byte_t * ) dst;
 
564
   int i;
 
565
 
 
566
   for ( i = 0; i < 8; i++, value >>= 8 )
 
567
   {
 
568
       p[ i ] = ( posh_byte_t ) ( value & 0xFF );
 
569
   }
 
570
 
 
571
   return p64 + 1;
 
572
}
 
573
 
 
574
/**
 
575
 * Writes a signed 64-bit value to a little-endian buffer
 
576
 
 
577
 @ingroup SixtyFourBit
 
578
 @param dst [out] pointer to the destination buffer, may not be NULL
 
579
 @param value [in] host-endian unsigned 64-bit value
 
580
 @returns a pointer to the location eight bytes after dst
 
581
 @remarks does no validation of the inputs.
 
582
*/
 
583
posh_i64_t *
 
584
POSH_WriteI64ToLittle( void *dst, posh_i64_t value )
 
585
{
 
586
   return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value );
 
587
}
 
588
 
 
589
/**
 
590
 * Writes an unsigned 64-bit value to a big-endian buffer
 
591
 
 
592
 @ingroup SixtyFourBit
 
593
 @param dst [out] pointer to the destination buffer, may not be NULL
 
594
 @param value [in] host-endian unsigned 64-bit value
 
595
 @returns a pointer to the location eight bytes after dst
 
596
 @remarks does no validation of the inputs.
 
597
*/
 
598
posh_u64_t *
 
599
POSH_WriteU64ToBig( void *dst, posh_u64_t value )
 
600
{
 
601
   posh_u64_t *p64 = ( posh_u64_t * ) dst;
 
602
   posh_byte_t *p  = ( posh_byte_t * ) dst;
 
603
   int i;
 
604
 
 
605
   for ( i = 0; i < 8; i++, value >>= 8 )
 
606
   {
 
607
       p[ 7-i ] = ( posh_byte_t ) ( value & 0xFF );
 
608
   }
 
609
 
 
610
   return p64 + 8;
 
611
}
 
612
 
 
613
/**
 
614
 * Writes a signed 64-bit value to a big-endian buffer
 
615
 
 
616
 @ingroup SixtyFourBit
 
617
 @param dst [out] pointer to the destination buffer, may not be NULL
 
618
 @param value [in] host-endian signed 64-bit value
 
619
 @returns a pointer to the location eight bytes after dst
 
620
 @remarks does no validation of the inputs.
 
621
*/
 
622
posh_i64_t *
 
623
POSH_WriteI64ToBig( void *dst, posh_i64_t value )
 
624
{
 
625
   return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value );
 
626
}
 
627
 
 
628
#endif /* POSH_64BIT_INTEGER */
 
629
 
 
630
/* ---------------------------------------------------------------------------*/
 
631
/*                         IN-MEMORY DESERIALIZATION                          */
 
632
/* ---------------------------------------------------------------------------*/
 
633
 
 
634
/** 
 
635
 * Reads an unsigned 16-bit value from a little-endian buffer
 
636
 @ingroup MemoryBuffer
 
637
 @param src [in] source buffer
 
638
 @returns host-endian unsigned 16-bit value
 
639
*/
 
640
posh_u16_t  
 
641
POSH_ReadU16FromLittle( const void *src )
 
642
{
 
643
    posh_u16_t   v = 0;
 
644
    posh_byte_t *p = ( posh_byte_t * ) src;
 
645
 
 
646
    v |= p[ 0 ];
 
647
    v |= ( ( posh_u16_t ) p[ 1 ] ) << 8;
 
648
 
 
649
    return v;
 
650
}
 
651
 
 
652
/** 
 
653
 * Reads a signed 16-bit value from a little-endian buffer
 
654
 @ingroup MemoryBuffer
 
655
 @param src [in] source buffer
 
656
 @returns host-endian signed 16-bit value
 
657
*/
 
658
posh_i16_t  
 
659
POSH_ReadI16FromLittle( const void *src )
 
660
{
 
661
   return ( posh_i16_t ) POSH_ReadU16FromLittle( src );
 
662
}
 
663
 
 
664
/** 
 
665
 * Reads an unsigned 32-bit value from a little-endian buffer
 
666
 @ingroup MemoryBuffer
 
667
 @param src [in] source buffer
 
668
 @returns host-endian unsigned 32-bit value
 
669
*/
 
670
posh_u32_t  
 
671
POSH_ReadU32FromLittle( const void *src )
 
672
{
 
673
    posh_u32_t v = 0;
 
674
    posh_byte_t *p = ( posh_byte_t * ) src;
 
675
 
 
676
    v |= p[ 0 ];
 
677
    v |= ( ( posh_u32_t ) p[ 1 ] ) << 8;
 
678
    v |= ( ( posh_u32_t ) p[ 2 ] ) << 16;
 
679
    v |= ( ( posh_u32_t ) p[ 3 ] ) << 24;
 
680
 
 
681
    return v;
 
682
}
 
683
 
 
684
/** 
 
685
 * Reads a signed 32-bit value from a little-endian buffer
 
686
 @ingroup MemoryBuffer
 
687
 @param src [in] source buffer
 
688
 @returns host-endian signed 32-bit value
 
689
*/
 
690
posh_i32_t  
 
691
POSH_ReadI32FromLittle( const void *src )
 
692
{
 
693
   return ( posh_i32_t ) POSH_ReadU32FromLittle( src );
 
694
}
 
695
 
 
696
 
 
697
/** 
 
698
 * Reads an unsigned 16-bit value from a big-endian buffer
 
699
 @ingroup MemoryBuffer
 
700
 @param src [in] source buffer
 
701
 @returns host-endian unsigned 16-bit value
 
702
*/
 
703
posh_u16_t  
 
704
POSH_ReadU16FromBig( const void *src )
 
705
{
 
706
    posh_u16_t   v = 0;
 
707
    posh_byte_t *p = ( posh_byte_t * ) src;
 
708
 
 
709
    v |= p[ 1 ];
 
710
    v |= ( ( posh_u16_t ) p[ 0 ] ) << 8;
 
711
 
 
712
    return v;
 
713
}
 
714
 
 
715
/** 
 
716
 * Reads a signed 16-bit value from a big-endian buffer
 
717
 @ingroup MemoryBuffer
 
718
 @param src [in] source buffer
 
719
 @returns host-endian signed 16-bit value
 
720
*/
 
721
posh_i16_t  
 
722
POSH_ReadI16FromBig( const void *src )
 
723
{
 
724
   return ( posh_i16_t ) POSH_ReadU16FromBig( src );
 
725
}
 
726
 
 
727
/** 
 
728
 * Reads an unsigned 32-bit value from a big-endian buffer
 
729
 @ingroup MemoryBuffer
 
730
 @param src [in] source buffer
 
731
 @returns host-endian unsigned 32-bit value
 
732
*/
 
733
posh_u32_t  
 
734
POSH_ReadU32FromBig( const void *src )
 
735
{
 
736
    posh_u32_t   v = 0;
 
737
    posh_byte_t *p = ( posh_byte_t * ) src;
 
738
 
 
739
    v |= p[ 3 ];
 
740
    v |= ( ( posh_u32_t ) p[ 2 ] ) << 8;
 
741
    v |= ( ( posh_u32_t ) p[ 1 ] ) << 16;
 
742
    v |= ( ( posh_u32_t ) p[ 0 ] ) << 24;
 
743
 
 
744
    return v;
 
745
}
 
746
 
 
747
/** 
 
748
 * Reads a signed 32-bit value from a big-endian buffer
 
749
 @ingroup MemoryBuffer
 
750
 @param src [in] source buffer
 
751
 @returns host-endian signed 32-bit value
 
752
*/
 
753
posh_i32_t  
 
754
POSH_ReadI32FromBig( const void *src )
 
755
{
 
756
   return POSH_BigI32( (*(const posh_i32_t*)src ) );
 
757
}
 
758
 
 
759
#if defined POSH_64BIT_INTEGER
 
760
 
 
761
/** 
 
762
 * Reads an unsigned 64-bit value from a little-endian buffer
 
763
 @param src [in] source buffer
 
764
 @returns host-endian unsigned 32-bit value
 
765
*/
 
766
posh_u64_t  
 
767
POSH_ReadU64FromLittle( const void *src )
 
768
{
 
769
    posh_u64_t v = 0;
 
770
    posh_byte_t *p = ( posh_byte_t * ) src;
 
771
    int i;
 
772
 
 
773
    for ( i = 0; i < 8; i++ )
 
774
    {
 
775
        v |= ( ( posh_u64_t ) p[ i ] ) << (i*8);
 
776
    }
 
777
 
 
778
    return v;
 
779
}
 
780
 
 
781
/** 
 
782
 * Reads a signed 64-bit value from a little-endian buffer
 
783
 @param src [in] source buffer
 
784
 @returns host-endian signed 32-bit value
 
785
*/
 
786
posh_i64_t  
 
787
POSH_ReadI64FromLittle( const void *src )
 
788
{
 
789
   return ( posh_i64_t ) POSH_ReadU64FromLittle( src );
 
790
}
 
791
 
 
792
/** 
 
793
 * Reads an unsigned 64-bit value from a big-endian buffer
 
794
 @param src [in] source buffer
 
795
 @returns host-endian unsigned 32-bit value
 
796
*/
 
797
posh_u64_t
 
798
POSH_ReadU64FromBig( const void *src )
 
799
{
 
800
    posh_u64_t v = 0;
 
801
    posh_byte_t *p = ( posh_byte_t * ) src;
 
802
    int i;
 
803
 
 
804
    for ( i = 0; i < 8; i++ )
 
805
    {
 
806
        v |= ( ( posh_u64_t ) p[ 7-i ] ) << (i*8);
 
807
    }
 
808
 
 
809
    return v;
 
810
}
 
811
 
 
812
/** 
 
813
 * Reads an signed 64-bit value from a big-endian buffer
 
814
 @param src [in] source buffer
 
815
 @returns host-endian signed 32-bit value
 
816
*/
 
817
posh_i64_t
 
818
POSH_ReadI64FromBig( const void *src )
 
819
{
 
820
   return ( posh_i64_t ) POSH_ReadU64FromBig( src );
 
821
}
 
822
 
 
823
#endif /* POSH_64BIT_INTEGER */
 
824
 
 
825
/* ---------------------------------------------------------------------------*/
 
826
/*                           FLOATING POINT SUPPORT                           */
 
827
/* ---------------------------------------------------------------------------*/
 
828
 
 
829
#if !defined POSH_NO_FLOAT
 
830
 
 
831
/** @ingroup FloatingPoint
 
832
    @param[in] f floating point value
 
833
    @returns a little-endian bit representation of f
 
834
 */
 
835
posh_u32_t
 
836
POSH_LittleFloatBits( float f )
 
837
{
 
838
   union
 
839
   {
 
840
      float f32;
 
841
      posh_u32_t u32;
 
842
   } u;
 
843
 
 
844
   u.f32 = f;
 
845
 
 
846
   return POSH_LittleU32( u.u32 );
 
847
}
 
848
 
 
849
/** 
 
850
 * Extracts raw big-endian bits from a 32-bit floating point value
 
851
 *
 
852
   @ingroup FloatingPoint
 
853
   @param   f [in] floating point value
 
854
   @returns a big-endian bit representation of f
 
855
 */
 
856
posh_u32_t
 
857
POSH_BigFloatBits( float f )
 
858
{
 
859
   union
 
860
   {
 
861
      float f32;
 
862
      posh_u32_t u32;
 
863
   } u;
 
864
 
 
865
   u.f32 = f;
 
866
 
 
867
   return POSH_BigU32( u.u32 );
 
868
}
 
869
 
 
870
/** 
 
871
 * Extracts raw, little-endian bit representation from a 64-bit double.
 
872
 *
 
873
   @param d [in] 64-bit double precision value
 
874
   @param dst [out] 8-byte storage buffer
 
875
   @ingroup FloatingPoint
 
876
   @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB
 
877
 */
 
878
void
 
879
POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] )
 
880
{
 
881
   union
 
882
   {
 
883
      double d64;
 
884
      posh_byte_t bytes[ 8 ];
 
885
   } u;
 
886
 
 
887
   u.d64 = d;
 
888
 
 
889
#if defined POSH_LITTLE_ENDIAN
 
890
   dst[ 0 ] = u.bytes[ 0 ];
 
891
   dst[ 1 ] = u.bytes[ 1 ];
 
892
   dst[ 2 ] = u.bytes[ 2 ];
 
893
   dst[ 3 ] = u.bytes[ 3 ];
 
894
   dst[ 4 ] = u.bytes[ 4 ];
 
895
   dst[ 5 ] = u.bytes[ 5 ];
 
896
   dst[ 6 ] = u.bytes[ 6 ];
 
897
   dst[ 7 ] = u.bytes[ 7 ];
 
898
#else
 
899
   dst[ 0 ] = u.bytes[ 7 ];
 
900
   dst[ 1 ] = u.bytes[ 6 ];
 
901
   dst[ 2 ] = u.bytes[ 5 ];
 
902
   dst[ 3 ] = u.bytes[ 4 ];
 
903
   dst[ 4 ] = u.bytes[ 3 ];
 
904
   dst[ 5 ] = u.bytes[ 2 ];
 
905
   dst[ 6 ] = u.bytes[ 1 ];
 
906
   dst[ 7 ] = u.bytes[ 0 ];
 
907
#endif
 
908
}
 
909
 
 
910
/** 
 
911
 * Creates a double-precision, 64-bit floating point value from a set of raw, 
 
912
 * little-endian bits
 
913
 
 
914
   @ingroup FloatingPoint
 
915
   @param src [in] little-endian byte representation of 64-bit double precision 
 
916
                  floating point value
 
917
   @returns double precision floating point representation of the raw bits
 
918
   @remarks No error checking is performed, so there are no guarantees that the 
 
919
            result is a valid number, nor is there any check to ensure that src is 
 
920
            non-NULL.  BE CAREFUL USING THIS.
 
921
 */
 
922
double
 
923
POSH_DoubleFromBits( const posh_byte_t src[ 8 ] )
 
924
{
 
925
   union
 
926
   {
 
927
      double d64;
 
928
      posh_byte_t bytes[ 8 ];
 
929
   } u;
 
930
 
 
931
#if defined POSH_LITTLE_ENDIAN
 
932
   u.bytes[ 0 ] = src[ 0 ];
 
933
   u.bytes[ 1 ] = src[ 1 ];
 
934
   u.bytes[ 2 ] = src[ 2 ];
 
935
   u.bytes[ 3 ] = src[ 3 ];
 
936
   u.bytes[ 4 ] = src[ 4 ];
 
937
   u.bytes[ 5 ] = src[ 5 ];
 
938
   u.bytes[ 6 ] = src[ 6 ];
 
939
   u.bytes[ 7 ] = src[ 7 ];
 
940
#else
 
941
   u.bytes[ 0 ] = src[ 7 ];
 
942
   u.bytes[ 1 ] = src[ 6 ];
 
943
   u.bytes[ 2 ] = src[ 5 ];
 
944
   u.bytes[ 3 ] = src[ 4 ];
 
945
   u.bytes[ 4 ] = src[ 3 ];
 
946
   u.bytes[ 5 ] = src[ 2 ];
 
947
   u.bytes[ 6 ] = src[ 1 ];
 
948
   u.bytes[ 7 ] = src[ 0 ];
 
949
#endif
 
950
 
 
951
   return u.d64;
 
952
}
 
953
 
 
954
/** 
 
955
 * Creates a floating point number from little endian bits
 
956
 *
 
957
   @ingroup FloatingPoint
 
958
   @param   bits [in] raw floating point bits in little-endian form
 
959
   @returns a floating point number based on the given bit representation
 
960
   @remarks No error checking is performed, so there are no guarantees that the 
 
961
            result is a valid number.  BE CAREFUL USING THIS.
 
962
 */
 
963
float       
 
964
POSH_FloatFromLittleBits( posh_u32_t bits )
 
965
{
 
966
   union
 
967
   {
 
968
      float f32;
 
969
      posh_u32_t u32;
 
970
   } u;
 
971
 
 
972
   u.u32 = bits;
 
973
#if defined POSH_BIG_ENDIAN
 
974
   u.u32 = POSH_SwapU32( u.u32 );
 
975
#endif
 
976
 
 
977
   return u.f32;
 
978
}
 
979
 
 
980
/** 
 
981
 * Creates a floating point number from big-endian bits
 
982
 *
 
983
   @ingroup FloatingPoint
 
984
   @param   bits [in] raw floating point bits in big-endian form
 
985
   @returns a floating point number based on the given bit representation
 
986
   @remarks No error checking is performed, so there are no guarantees that the 
 
987
            result is a valid number.  BE CAREFUL USING THIS.
 
988
 */
 
989
float
 
990
POSH_FloatFromBigBits( posh_u32_t bits )
 
991
{
 
992
   union
 
993
   {
 
994
      float f32;
 
995
      posh_u32_t u32;
 
996
   } u;
 
997
 
 
998
   u.u32 = bits;
 
999
#if defined POSH_LITTLE_ENDIAN
 
1000
   u.u32 = POSH_SwapU32( u.u32 );
 
1001
#endif
 
1002
 
 
1003
   return u.f32;
 
1004
}
 
1005
 
 
1006
#endif /* !defined POSH_NO_FLOAT */