Changeset 54

Show
Ignore:
Timestamp:
06/26/08 21:21:29 (4 months ago)
Author:
baxissimo
Message:

Switched array lengths to use packed integers to make the 32/64 bit thing work as long as you don't have your own size_t parameters in your code. Maybe should store all unsigned ints this way?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/doost/util/serializer/archive/BinaryArchive.d

    r53 r54  
    208208            loadNumber(sizeof_length); 
    209209            if (sizeof_length != LengthSizeof) { 
    210                 // TODO: make the 32bit vs 64bit thing work properly 
    211                 throw new ParsingException("Binary data encoded on platform with different size_t!"); 
    212                 // return false; 
     210                // TODO: loading 32bit data on 64 bit platform (or vice versa) 
     211 
     212                // This should work for arrays now, but there still could be  
     213                // problems with saving any other size_t, say you have an index into 
     214                // a list. 
     215 
     216                // I'd make this a warning here if there were a way in doost... 
     217 
     218                //throw new ParsingException 
     219                //  ("Binary data encoded on platform with different size_t!"); 
    213220            } 
    214221 
     
    326333 
    327334    /*************************************************************************** 
     335      Load an unsigned integer value that's stored as a variable number of bytes 
     336 
     337      Thanks to Tom S. aka h3r3tic for this. 
     338     **************************************************************************/ 
     339    bool loadPackedUInteger(VALUE)(ref VALUE value) { 
     340        static assert(is(VALUE==ubyte)|| 
     341                      is(VALUE==ushort)|| 
     342                      is(VALUE==uint)|| 
     343                      is(VALUE==ulong), "Not an unsigned integer"); 
     344        ulong res = 0; 
     345        bool cont = true; 
     346        for (int i = 0; cont; ++i) { 
     347            ubyte part; 
     348            part = storage.get(); 
     349            cont = (part & 0b10000000) != 0; 
     350            res |= (part & 0b01111111) << (i * 7); 
     351        } 
     352        // check for overflow 
     353        if (VALUE.max < res) { 
     354            value = VALUE.max; 
     355            return false;  
     356        } 
     357        value = res; 
     358         
     359        return true; 
     360    } 
     361 
     362    /*************************************************************************** 
     363      Save an unsigned integer as a variable number of bytes. 
     364 
     365      Thanks to Tom S. aka h3r3tic for this. 
     366     **************************************************************************/ 
     367    bool dumpPackedUInteger(VALUE)(VALUE value) { 
     368        static assert(is(VALUE==ubyte)|| 
     369                      is(VALUE==ushort)|| 
     370                      is(VALUE==uint)|| 
     371                      is(VALUE==ulong), "Not an unsigned integer"); 
     372        do { 
     373            ubyte part = value & 127; 
     374            if (value > 0b01111111) part |= 0b10000000; 
     375            value >>= 7; 
     376            storage.put(part); 
     377        } while (value != 0); 
     378 
     379        return true; 
     380    } 
     381 
     382    /*************************************************************************** 
    328383     **************************************************************************/ 
    329384    bool loadChar(VALUE)(ref VALUE value) { 
     
    365420            throw new ParsingException("Array begin marker expected"); 
    366421        } 
    367         if (!loadElement(len)) 
     422        if (!loadPackedUInteger(len)) 
    368423            return false; 
    369424        result.length = len; 
     
    387442    bool dumpArray(VALUE)(ref VALUE value) { 
    388443        storage.put(Marker.arrayBegin); 
    389         storage.put(encode(value.length)); 
     444        dumpPackedUInteger(value.length); 
    390445 
    391446        foreach(v; value) 
     
    414469 
    415470 
    416         if (!loadElement(len)) 
     471        if (!loadPackedUInteger(len)) 
    417472            return false; 
    418473        for(size_t i=0; i<len; i++) { 
     
    439494 
    440495        storage.put(Marker.assocBegin); 
    441         storage.put(encode(value.length)); 
     496        dumpPackedUInteger(value.length); 
    442497        foreach(k,v; value) { 
    443498            dumpElement(k); 
  • trunk/examples/util/serializer/FunctionTest.d

    r51 r54  
    1818import std.date; 
    1919import std.string; 
     20import math=std.math; 
    2021 
    2122import doost.api.Common; 
     
    18241825    input_real = 3.14159_26535_89793_23846_26433_83279_50288_41971_69399; 
    18251826    output = binserializer.dump(input_real); 
    1826     assert(binserializer.load!(real)(output) == input_real); 
     1827    assert(math.abs(binserializer.load!(real)(output) - input_real) < 1e-8); 
    18271828 
    18281829    input_cfloat = 1774 + 12.fi; 
    18291830    output = binserializer.dump(input_cfloat); 
    1830     assert(binserializer.load!(cfloat)(output) == input_cfloat); 
     1831    assert(math.abs(binserializer.load!(cfloat)(output) - input_cfloat) < 1e-8); 
    18311832 
    18321833    input_creal = 1774 + 12i; 
    18331834    output = binserializer.dump(input_creal); 
    1834     assert(binserializer.load!(creal)(output) == input_creal); 
     1835    assert(math.abs(binserializer.load!(creal)(output) - input_creal) < 1e-8); 
    18351836 
    18361837    input_ireal = 1774i; 
    18371838    output = binserializer.dump(input_ireal); 
    1838     assert(binserializer.load!(ireal)(output) == input_ireal); 
     1839    assert(math.abs(binserializer.load!(ireal)(output) - input_ireal) < 1e-8); 
     1840 
    18391841});} 
    18401842 
     
    18871889});} 
    18881890 
     1891 
     1892//------------------------------------------------------------------------------ 
     1893unittest { testCase.execute("load/dump - array sizes", { 
     1894    /* Array lengths are saved as a variable length byte sequence 
     1895       so test here that different byte ranges are actually handled properly 
     1896    */ 
     1897    int[] input; 
     1898 
     1899    ubyte[] output; 
     1900 
     1901    // 1-byte max is 254 
     1902    for (size_t len=0; len<300; len++) { 
     1903        input.length = len; 
     1904        if (len>0) input[len-1] = len-1; 
     1905 
     1906        output = binserializer.dump(input); 
     1907        assert(binserializer.load!(int[])(output) == input); 
     1908    } 
     1909 
     1910    // 2-byte max is ~65_536 
     1911    int lo = 65_530; 
     1912    int hi = 65_540; 
     1913    input.length = hi; // pre alloc 
     1914    input.length = lo; 
     1915    foreach(i,v; input) { v=i; } 
     1916    for (size_t len=lo; len<hi; len++) { 
     1917        input.length = len; 
     1918        input[len-1] = len-1; 
     1919        output = binserializer.dump(input); 
     1920        assert(binserializer.load!(int[])(output) == input); 
     1921    } 
     1922 
     1923});} 
     1924 
     1925 
    18891926//------------------------------------------------------------------------------ 
    18901927 
     
    19191956unittest { testCase.execute("load/dump - static arrays", { 
    19201957    string[6] input_string; 
    1921     real[3] input_real
     1958    double[3] input_double
    19221959    int[4] input_int; 
    19231960    TransparentComposedStruct[3] input_cstruct; 
     
    19351972    assert(binserializer.load!(string[6])(output) == input_string); 
    19361973 
    1937     input_real[0]=3.14; input_real[0]=2.01; input_real[0]=-15.76; 
    1938     output = binserializer.dump(input_real); 
    1939     assert(binserializer.load!(real[6])(output) == input_real); 
     1974    input_double[0]=3.14; input_double[0]=2.01; input_double[0]=-15.76; 
     1975    output = binserializer.dump(input_double); 
     1976    assert(binserializer.load!(double[6])(output) == input_double); 
    19401977 
    19411978    input_cstruct[0]=TransparentComposedStruct([1,2,3,4,5]);