@@ -3504,6 +3504,117 @@ void testErrorImages() {
35043504 testBase64Image (" iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAgMAAAAhHED1AAAAU0lEQVR4Ae3MwQAAAAxFoXnM3/NDvGsBdB8JBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEEQDHGPAW1eyhK0AAAAASUVORK5CYII=" , true , 256 , 256 , " " );
35053505}
35063506
3507+ // defined in lodepng.cpp
3508+ unsigned lode_png_test_bitreader (const unsigned char * data, size_t size, size_t numsteps, const size_t * steps, unsigned * result);
3509+
3510+ void testBitReaderCase (const std::string& bits, const std::vector<size_t >& steps, bool expect_error, bool silent = false ) {
3511+ if (!silent) std::cout << " testBitReaderCase: " << bits << " , #steps: " << steps.size () << std::endl;
3512+ std::vector<unsigned char > data;
3513+ std::vector<bool > bits0;
3514+ size_t bitcount = 0 ;
3515+ for (size_t i = 0 ; i < bits.size (); i++) {
3516+ char c = bits[i];
3517+ if (c != ' 0' && c != ' 1' ) continue ;
3518+ if ((bitcount & 7 ) == 0 ) data.push_back (0 );
3519+ int bit = (c == ' 1' );
3520+ data.back () |= (bit << (bitcount & 7 ));
3521+ bits0.push_back (bit);
3522+ bitcount++;
3523+ }
3524+ std::vector<unsigned > result (steps.size ());
3525+ unsigned ok = lode_png_test_bitreader (data.data (), data.size (), steps.size (), steps.data (), result.data ());
3526+ if (expect_error) {
3527+ assertEquals (0 , ok, " expected it would give an error" );
3528+ return ;
3529+ }
3530+ assertEquals (1 , ok, " expected there would be no error" );
3531+
3532+ std::vector<bool > bits1;
3533+ for (size_t i = 0 ; i < steps.size (); i++) {
3534+ size_t step = steps[i];
3535+ size_t value = result[i];
3536+ for (size_t j = 0 ; j < step; j++) {
3537+ bits1.push_back ((value >> j) & 1 );
3538+ }
3539+ }
3540+ bits0.resize (bits1.size ()); // only test those bits that were actually read for the test
3541+
3542+ assertEquals (bits0, bits1);
3543+ }
3544+
3545+ // This is still using C++98 for lodepng for compatibility, even though I'd love to use C++11 vector initializer lists here.
3546+ // TODO: use modern C++ at least for the unit test
3547+ #define V (arr ) std::vector<size_t >(arr, arr + sizeof (arr) / sizeof (*arr))
3548+
3549+ void testBitReader () {
3550+ std::string zeros = " 0000000000000000000000000000000000000000000000000000000000000000" ;
3551+ testBitReaderCase (" " , std::vector<size_t >(0 ), false );
3552+ { size_t arr[] = {1 }; testBitReaderCase (" 0" , V (arr), false ); }
3553+ { size_t arr[] = {1 }; testBitReaderCase (" 1" , V (arr), false ); }
3554+ { size_t arr[] = {2 }; testBitReaderCase (" 00" , V (arr), false ); }
3555+ { size_t arr[] = {2 }; testBitReaderCase (" 01" , V (arr), false ); }
3556+ { size_t arr[] = {2 }; testBitReaderCase (" 10" , V (arr), false ); }
3557+ { size_t arr[] = {2 }; testBitReaderCase (" 11" , V (arr), false ); }
3558+ { size_t arr[] = {3 }; testBitReaderCase (" 111" , V (arr), false ); }
3559+ { size_t arr[] = {4 }; testBitReaderCase (" 1111" , V (arr), false ); }
3560+ { size_t arr[] = {8 }; testBitReaderCase (" 11111111" , V (arr), false ); }
3561+ { size_t arr[] = {9 }; testBitReaderCase (" 111111111" , V (arr), false ); }
3562+ { size_t arr[] = {9 }; testBitReaderCase (" 11111111" , V (arr), true ); }
3563+ { size_t arr[] = {16 }; testBitReaderCase (" 1111111111111111" , V (arr), false ); }
3564+ { size_t arr[] = {17 }; testBitReaderCase (" 11111111111111111" , V (arr), false ); }
3565+ { size_t arr[] = {17 }; testBitReaderCase (" 1111111111111111" , V (arr), true ); }
3566+ { size_t arr[] = {24 }; testBitReaderCase (" 111111111111111111111111" , V (arr), false ); }
3567+ { size_t arr[] = {25 }; testBitReaderCase (" 1111111111111111111111111" , V (arr), false ); }
3568+ { size_t arr[] = {25 }; testBitReaderCase (" 111111111111111111111111" , V (arr), true ); }
3569+ { size_t arr[] = {31 }; testBitReaderCase (" 1111111111111111111111111111111" , V (arr), false ); }
3570+ { size_t arr[] = {1 , 31 }; testBitReaderCase (" 11111111111111111111111111111111" , V (arr), false ); }
3571+ { size_t arr[] = {31 }; testBitReaderCase (" 111111111111111111111111" , V (arr), true ); }
3572+ { size_t arr[] = {16 , 16 }; testBitReaderCase (" 11111111111111111111111111111111" , V (arr), false ); }
3573+ { size_t arr[] = {1 }; testBitReaderCase (" 0" + zeros, V (arr), false ); }
3574+ { size_t arr[] = {1 }; testBitReaderCase (" 1" + zeros, V (arr), false ); }
3575+ { size_t arr[] = {2 }; testBitReaderCase (" 00" + zeros, V (arr), false ); }
3576+ { size_t arr[] = {2 }; testBitReaderCase (" 01" + zeros, V (arr), false ); }
3577+ { size_t arr[] = {2 }; testBitReaderCase (" 10" + zeros, V (arr), false ); }
3578+ { size_t arr[] = {2 }; testBitReaderCase (" 11" + zeros, V (arr), false ); }
3579+ { size_t arr[] = {3 }; testBitReaderCase (" 111" + zeros, V (arr), false ); }
3580+ { size_t arr[] = {4 }; testBitReaderCase (" 1111" + zeros, V (arr), false ); }
3581+ { size_t arr[] = {8 }; testBitReaderCase (" 11111111" + zeros, V (arr), false ); }
3582+ { size_t arr[] = {9 }; testBitReaderCase (" 111111111" + zeros, V (arr), false ); }
3583+ { size_t arr[] = {16 }; testBitReaderCase (" 1111111111111111" + zeros, V (arr), false ); }
3584+ { size_t arr[] = {17 }; testBitReaderCase (" 11111111111111111" + zeros, V (arr), false ); }
3585+ { size_t arr[] = {24 }; testBitReaderCase (" 111111111111111111111111" + zeros, V (arr), false ); }
3586+ { size_t arr[] = {25 }; testBitReaderCase (" 1111111111111111111111111" + zeros, V (arr), false ); }
3587+ { size_t arr[] = {31 }; testBitReaderCase (" 1111111111111111111111111111111" + zeros, V (arr), false ); }
3588+ { size_t arr[] = {16 , 16 }; testBitReaderCase (" 11111111111111111111111111111111" + zeros, V (arr), false ); }
3589+
3590+ // 128 arbitrary bits
3591+ std::string test = " 10101011110000101110010010000101000100100000111000010010010010010010111100000100100100100000001010111111110001111010101011011001" ;
3592+ for (size_t i = 0 ; i < 32 ; i++) {
3593+ std::cout << " testBitReader loop " << i << std::endl;
3594+ { size_t arr[] = {i}; testBitReaderCase (test, V (arr), false , true ); }
3595+ { size_t arr[] = {i, i}; testBitReaderCase (test, V (arr), false , true ); }
3596+ { size_t arr[] = {i, i, i}; testBitReaderCase (test, V (arr), false , true ); }
3597+ { size_t arr[] = {i, i, i, i}; testBitReaderCase (test, V (arr), false , true ); }
3598+ { size_t arr[] = {1 , i, i, i, i}; testBitReaderCase (test, V (arr), false , true ); }
3599+ { size_t arr[] = {2 , i, i, i, i}; testBitReaderCase (test, V (arr), false , true ); }
3600+ { size_t arr[] = {3 , i, i, i, i}; testBitReaderCase (test, V (arr), false , true ); }
3601+ { size_t arr[] = {31 , 31 , 31 , i}; testBitReaderCase (test, V (arr), false , true ); }
3602+ { size_t arr[] = {i, i, i, i, i, i, i, i}; testBitReaderCase (test + test, V (arr), false , true ); }
3603+ for (size_t j = 0 ; j < 32 ; j++) {
3604+ { size_t arr[] = {i, j}; testBitReaderCase (test, V (arr), false , true ); }
3605+ { size_t arr[] = {i, j, i, j}; testBitReaderCase (test, V (arr), false , true ); }
3606+ { size_t arr[] = {i, i, j, j}; testBitReaderCase (test, V (arr), false , true ); }
3607+ { size_t arr[] = {31 , 31 , i, j}; testBitReaderCase (test, V (arr), false , true ); }
3608+ }
3609+ }
3610+ { size_t arr[] = {1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 }; testBitReaderCase (test, V (arr), false ); }
3611+ { size_t arr[] = {3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 ,3 }; testBitReaderCase (test, V (arr), false ); }
3612+ { size_t arr[] = {1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,31 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 }; testBitReaderCase (test, V (arr), false ); }
3613+ { size_t arr[] = {16 ,1 ,2 ,4 ,7 ,3 ,6 ,28 ,28 ,31 ,1 ,17 ,12 ,1 ,3 ,8 ,3 ,3 ,14 ,21 ,25 ,24 ,1 ,8 ,7 }; testBitReaderCase (test + test + test, V (arr), false ); }
3614+ { size_t arr[] = {5 ,7 ,17 ,15 ,6 ,8 ,4 ,5 ,3 ,11 ,1 ,4 ,4 ,8 ,6 ,4 ,5 ,1 ,6 ,5 ,13 ,8 ,18 ,1 ,1 ,8 ,7 ,2 }; testBitReaderCase (test + test + test, V (arr), false ); }
3615+
3616+ }
3617+
35073618void doMain () {
35083619 // PNG
35093620 testPngSuite ();
@@ -3546,8 +3657,8 @@ void doMain() {
35463657 testCustomDeflate ();
35473658 testCustomZlibDecompress ();
35483659 testCustomInflate ();
3660+ testBitReader ();
35493661 // TODO: add test for huffman code with exactly 0 and 1 symbols present
3550- // TODO: add case where ensureBits25 and ensureBits32 do left shift of 24 with value >= 128
35513662
35523663 // lodepng_util
35533664 testChunkUtil ();
0 commit comments