@@ -821,7 +821,7 @@ namespace serialize
821
821
** Read a 64-bit variable-length integer from memory starting at p[0].
822
822
** Return the number of bytes read. The value is stored in *v.
823
823
*/
824
- uint8_t serialize_get_varint ( const unsigned char * p, uint64_t * v )
824
+ inline uint8_t serialize_get_varint ( const unsigned char * p, uint64_t * v )
825
825
{
826
826
uint32_t a, b, s;
827
827
@@ -972,7 +972,7 @@ namespace serialize
972
972
return 9 ;
973
973
}
974
974
975
- uint8_t serialize_get_varint32 ( const unsigned char * p, uint32_t * v )
975
+ inline uint8_t serialize_get_varint32 ( const unsigned char * p, uint32_t * v )
976
976
{
977
977
uint32_t a, b;
978
978
@@ -1094,7 +1094,7 @@ namespace serialize
1094
1094
** Return the number of bytes that will be needed to store the given
1095
1095
** 64-bit integer.
1096
1096
*/
1097
- int serialize_measure_varint ( uint64_t v )
1097
+ inline int serialize_measure_varint ( uint64_t v )
1098
1098
{
1099
1099
int i;
1100
1100
for ( i = 1 ; (v>>=7 ) != 0 ; i++ ) { serialize_assert (i<10 ); }
@@ -1113,7 +1113,7 @@ namespace serialize
1113
1113
Base stream constructor.
1114
1114
*/
1115
1115
1116
- explicit BaseStream () : m_context( NULL ) {}
1116
+ explicit BaseStream () : m_context( NULL ), m_allocator( NULL ) {}
1117
1117
1118
1118
/* *
1119
1119
Set a context on the stream.
@@ -1137,9 +1137,31 @@ namespace serialize
1137
1137
return m_context;
1138
1138
}
1139
1139
1140
+ /* *
1141
+ Set an allocator pointer on the stream.
1142
+ This can be helpful if you want to perform allocations within serialize functions.
1143
+ */
1144
+
1145
+ void SetAllocator ( void * allocator )
1146
+ {
1147
+ m_allocator = allocator;
1148
+ }
1149
+
1150
+ /* *
1151
+ Get the allocator pointer set on the stream.
1152
+
1153
+ @returns The allocator pointer. May be NULL.
1154
+ */
1155
+
1156
+ void * GetAllocator () const
1157
+ {
1158
+ return m_allocator;
1159
+ }
1160
+
1140
1161
private:
1141
1162
1142
1163
void * m_context; // /< The context pointer set on the stream. May be NULL.
1164
+ void * m_allocator; // /< The allocator pointer set on the stream. May be NULL.
1143
1165
};
1144
1166
1145
1167
/* *
@@ -2307,4 +2329,302 @@ namespace serialize
2307
2329
#define write_int_relative serialize_int_relative
2308
2330
}
2309
2331
2332
+ #if SERIALIZE_ENABLE_TESTS
2333
+
2334
+ #include < time.h>
2335
+
2336
+ static void CheckHandler ( const char * condition,
2337
+ const char * function,
2338
+ const char * file,
2339
+ int line )
2340
+ {
2341
+ printf ( " check failed: ( %s ), function %s, file %s, line %d\n " , condition, function, file, line );
2342
+ #ifndef NDEBUG
2343
+ #if defined( __GNUC__ )
2344
+ __builtin_trap ();
2345
+ #elif defined( _MSC_VER )
2346
+ __debugbreak ();
2347
+ #endif
2348
+ #endif
2349
+ exit ( 1 );
2350
+ }
2351
+
2352
+ #define check ( condition ) \
2353
+ do \
2354
+ { \
2355
+ if ( !(condition) ) \
2356
+ { \
2357
+ CheckHandler ( #condition, __FUNCTION__, __FILE__, __LINE__ ); \
2358
+ } \
2359
+ } while (0 )
2360
+
2361
+ void test_endian ()
2362
+ {
2363
+ uint32_t value = 0x11223344 ;
2364
+
2365
+ const char * bytes = (const char *) &value;
2366
+
2367
+ #if SERIALIZE_LITTLE_ENDIAN
2368
+
2369
+ check ( bytes[0 ] == 0x44 );
2370
+ check ( bytes[1 ] == 0x33 );
2371
+ check ( bytes[2 ] == 0x22 );
2372
+ check ( bytes[3 ] == 0x11 );
2373
+
2374
+ #else // #if SERIALIZE_LITTLE_ENDIAN
2375
+
2376
+ check ( bytes[3 ] == 0x44 );
2377
+ check ( bytes[2 ] == 0x33 );
2378
+ check ( bytes[1 ] == 0x22 );
2379
+ check ( bytes[0 ] == 0x11 );
2380
+
2381
+ #endif // #if SERIALIZE_LITTLE_ENDIAN
2382
+ }
2383
+
2384
+ void test_bitpacker ()
2385
+ {
2386
+ const int BufferSize = 256 ;
2387
+
2388
+ uint8_t buffer[BufferSize];
2389
+
2390
+ serialize::BitWriter writer ( buffer, BufferSize );
2391
+
2392
+ check ( writer.GetData () == buffer );
2393
+ check ( writer.GetBitsWritten () == 0 );
2394
+ check ( writer.GetBytesWritten () == 0 );
2395
+ check ( writer.GetBitsAvailable () == BufferSize * 8 );
2396
+
2397
+ writer.WriteBits ( 0 , 1 );
2398
+ writer.WriteBits ( 1 , 1 );
2399
+ writer.WriteBits ( 10 , 8 );
2400
+ writer.WriteBits ( 255 , 8 );
2401
+ writer.WriteBits ( 1000 , 10 );
2402
+ writer.WriteBits ( 50000 , 16 );
2403
+ writer.WriteBits ( 9999999 , 32 );
2404
+ writer.FlushBits ();
2405
+
2406
+ const int bitsWritten = 1 + 1 + 8 + 8 + 10 + 16 + 32 ;
2407
+
2408
+ check ( writer.GetBytesWritten () == 10 );
2409
+ check ( writer.GetBitsWritten () == bitsWritten );
2410
+ check ( writer.GetBitsAvailable () == BufferSize * 8 - bitsWritten );
2411
+
2412
+ const int bytesWritten = writer.GetBytesWritten ();
2413
+
2414
+ check ( bytesWritten == 10 );
2415
+
2416
+ memset ( buffer + bytesWritten, 0 , BufferSize - bytesWritten );
2417
+
2418
+ serialize::BitReader reader ( buffer, bytesWritten );
2419
+
2420
+ check ( reader.GetBitsRead () == 0 );
2421
+ check ( reader.GetBitsRemaining () == bytesWritten * 8 );
2422
+
2423
+ uint32_t a = reader.ReadBits ( 1 );
2424
+ uint32_t b = reader.ReadBits ( 1 );
2425
+ uint32_t c = reader.ReadBits ( 8 );
2426
+ uint32_t d = reader.ReadBits ( 8 );
2427
+ uint32_t e = reader.ReadBits ( 10 );
2428
+ uint32_t f = reader.ReadBits ( 16 );
2429
+ uint32_t g = reader.ReadBits ( 32 );
2430
+
2431
+ check ( a == 0 );
2432
+ check ( b == 1 );
2433
+ check ( c == 10 );
2434
+ check ( d == 255 );
2435
+ check ( e == 1000 );
2436
+ check ( f == 50000 );
2437
+ check ( g == 9999999 );
2438
+
2439
+ check ( reader.GetBitsRead () == bitsWritten );
2440
+ check ( reader.GetBitsRemaining () == bytesWritten * 8 - bitsWritten );
2441
+ }
2442
+
2443
+ void test_bits_required ()
2444
+ {
2445
+ check ( serialize::bits_required ( 0 , 0 ) == 0 );
2446
+ check ( serialize::bits_required ( 0 , 1 ) == 1 );
2447
+ check ( serialize::bits_required ( 0 , 2 ) == 2 );
2448
+ check ( serialize::bits_required ( 0 , 3 ) == 2 );
2449
+ check ( serialize::bits_required ( 0 , 4 ) == 3 );
2450
+ check ( serialize::bits_required ( 0 , 5 ) == 3 );
2451
+ check ( serialize::bits_required ( 0 , 6 ) == 3 );
2452
+ check ( serialize::bits_required ( 0 , 7 ) == 3 );
2453
+ check ( serialize::bits_required ( 0 , 8 ) == 4 );
2454
+ check ( serialize::bits_required ( 0 , 255 ) == 8 );
2455
+ check ( serialize::bits_required ( 0 , 65535 ) == 16 );
2456
+ check ( serialize::bits_required ( 0 , 4294967295 ) == 32 );
2457
+ }
2458
+
2459
+ const int MaxItems = 11 ;
2460
+
2461
+ struct TestData
2462
+ {
2463
+ TestData ()
2464
+ {
2465
+ memset ( this , 0 , sizeof ( TestData ) );
2466
+ }
2467
+
2468
+ int a,b,c;
2469
+ uint32_t d : 8 ;
2470
+ uint32_t e : 8 ;
2471
+ uint32_t f : 8 ;
2472
+ bool g;
2473
+ uint32_t v32;
2474
+ uint64_t v64;
2475
+ int numItems;
2476
+ int items[MaxItems];
2477
+ float float_value;
2478
+ float compressed_float_value;
2479
+ double double_value;
2480
+ uint64_t uint64_value;
2481
+ uint32_t varint32_value;
2482
+ uint64_t varint64_value;
2483
+ int int_relative;
2484
+ uint8_t bytes[17 ];
2485
+ char string[256 ];
2486
+ };
2487
+
2488
+ struct TestContext
2489
+ {
2490
+ int min;
2491
+ int max;
2492
+ };
2493
+
2494
+ struct TestObject
2495
+ {
2496
+ TestData data;
2497
+
2498
+ void Init ()
2499
+ {
2500
+ data.a = 1 ;
2501
+ data.b = -2 ;
2502
+ data.c = 150 ;
2503
+ data.d = 55 ;
2504
+ data.e = 255 ;
2505
+ data.f = 127 ;
2506
+ data.g = true ;
2507
+
2508
+ data.numItems = MaxItems / 2 ;
2509
+ for ( int i = 0 ; i < data.numItems ; ++i )
2510
+ data.items [i] = i + 10 ;
2511
+
2512
+ data.compressed_float_value = 2 .13f ;
2513
+ data.float_value = 3 .1415926f ;
2514
+ data.double_value = 1 / 3.0 ;
2515
+ data.uint64_value = 0x1234567898765432L ;
2516
+ data.varint32_value = 123456 ;
2517
+ data.varint64_value = 123456789101112 ;
2518
+ data.int_relative = 5 ;
2519
+
2520
+ for ( int i = 0 ; i < (int ) sizeof ( data.bytes ); ++i )
2521
+ data.bytes [i] = rand () % 255 ;
2522
+
2523
+ strcpy ( data.string , " hello world!" );
2524
+ }
2525
+
2526
+ template <typename Stream> bool Serialize ( Stream & stream )
2527
+ {
2528
+ const TestContext & context = *(const TestContext*) stream.GetContext ();
2529
+
2530
+ serialize_int ( stream, data.a , context.min , context.max );
2531
+ serialize_int ( stream, data.b , context.min , context.max );
2532
+
2533
+ serialize_int ( stream, data.c , -100 , 10000 );
2534
+
2535
+ serialize_bits ( stream, data.d , 6 );
2536
+ serialize_bits ( stream, data.e , 8 );
2537
+ serialize_bits ( stream, data.f , 7 );
2538
+
2539
+ serialize_align ( stream );
2540
+
2541
+ serialize_bool ( stream, data.g );
2542
+
2543
+ serialize_int ( stream, data.numItems , 0 , MaxItems - 1 );
2544
+ for ( int i = 0 ; i < data.numItems ; ++i )
2545
+ serialize_bits ( stream, data.items [i], 8 );
2546
+
2547
+ serialize_float ( stream, data.float_value );
2548
+
2549
+ serialize_compressed_float ( stream, data.compressed_float_value , 0 , 10 , 0.01 );
2550
+
2551
+ serialize_double ( stream, data.double_value );
2552
+
2553
+ serialize_uint64 ( stream, data.uint64_value );
2554
+
2555
+ serialize_varint32 ( stream, data.varint32_value );
2556
+
2557
+ serialize_varint64 ( stream, data.varint64_value );
2558
+
2559
+ serialize_int_relative ( stream, data.a , data.int_relative );
2560
+
2561
+ serialize_bytes ( stream, data.bytes , sizeof ( data.bytes ) );
2562
+
2563
+ serialize_string ( stream, data.string , sizeof ( data.string ) );
2564
+
2565
+ return true ;
2566
+ }
2567
+
2568
+ bool operator == ( const TestObject & other ) const
2569
+ {
2570
+ return memcmp ( &data, &other.data , sizeof ( TestData ) ) == 0 ;
2571
+ }
2572
+
2573
+ bool operator != ( const TestObject & other ) const
2574
+ {
2575
+ return ! ( *this == other );
2576
+ }
2577
+ };
2578
+
2579
+ void test_stream ()
2580
+ {
2581
+ const int BufferSize = 1024 ;
2582
+
2583
+ uint8_t buffer[BufferSize];
2584
+
2585
+ TestContext context;
2586
+ context.min = -10 ;
2587
+ context.max = +10 ;
2588
+
2589
+ serialize::WriteStream writeStream ( buffer, BufferSize );
2590
+
2591
+ TestObject writeObject;
2592
+ writeObject.Init ();
2593
+ writeStream.SetContext ( &context );
2594
+ writeObject.Serialize ( writeStream );
2595
+ writeStream.Flush ();
2596
+
2597
+ const int bytesWritten = writeStream.GetBytesProcessed ();
2598
+
2599
+ memset ( buffer + bytesWritten, 0 , BufferSize - bytesWritten );
2600
+
2601
+ TestObject readObject;
2602
+ serialize::ReadStream readStream ( buffer, bytesWritten );
2603
+ readStream.SetContext ( &context );
2604
+ readObject.Serialize ( readStream );
2605
+
2606
+ check ( readObject == writeObject );
2607
+ }
2608
+
2609
+ #define RUN_TEST ( test_function ) \
2610
+ do \
2611
+ { \
2612
+ printf ( #test_function " \n " ); \
2613
+ test_function (); \
2614
+ } \
2615
+ while (0 )
2616
+
2617
+ void serialize_test ()
2618
+ {
2619
+ // while ( 1 )
2620
+ {
2621
+ RUN_TEST ( test_endian );
2622
+ RUN_TEST ( test_bitpacker );
2623
+ RUN_TEST ( test_bits_required );
2624
+ RUN_TEST ( test_stream );
2625
+ }
2626
+ }
2627
+
2628
+ #endif // #if SERIALIZE_ENABLE_TESTS
2629
+
2310
2630
#endif // #ifndef SERIALIZE_H
0 commit comments