Skip to content

Commit 02cbec0

Browse files
committed
setup so tests can be run by a user of the library. add set/get allocator to support yojimbo usage
1 parent 53d6a1f commit 02cbec0

File tree

2 files changed

+326
-291
lines changed

2 files changed

+326
-291
lines changed

serialize.h

Lines changed: 324 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ namespace serialize
821821
** Read a 64-bit variable-length integer from memory starting at p[0].
822822
** Return the number of bytes read. The value is stored in *v.
823823
*/
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 )
825825
{
826826
uint32_t a, b, s;
827827

@@ -972,7 +972,7 @@ namespace serialize
972972
return 9;
973973
}
974974

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 )
976976
{
977977
uint32_t a, b;
978978

@@ -1094,7 +1094,7 @@ namespace serialize
10941094
** Return the number of bytes that will be needed to store the given
10951095
** 64-bit integer.
10961096
*/
1097-
int serialize_measure_varint( uint64_t v )
1097+
inline int serialize_measure_varint( uint64_t v )
10981098
{
10991099
int i;
11001100
for ( i = 1; (v>>=7) != 0; i++ ) { serialize_assert(i<10); }
@@ -1113,7 +1113,7 @@ namespace serialize
11131113
Base stream constructor.
11141114
*/
11151115

1116-
explicit BaseStream() : m_context( NULL ) {}
1116+
explicit BaseStream() : m_context( NULL ), m_allocator( NULL ) {}
11171117

11181118
/**
11191119
Set a context on the stream.
@@ -1137,9 +1137,31 @@ namespace serialize
11371137
return m_context;
11381138
}
11391139

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+
11401161
private:
11411162

11421163
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.
11431165
};
11441166

11451167
/**
@@ -2307,4 +2329,302 @@ namespace serialize
23072329
#define write_int_relative serialize_int_relative
23082330
}
23092331

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+
23102630
#endif // #ifndef SERIALIZE_H

0 commit comments

Comments
 (0)