Commit c28eb691 authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

XMLVTK reader: fixed reading of binary encoded and compressed VTU files created by Paraview

parent f53de445
Loading
Loading
Loading
Loading
+19 −17
Original line number Diff line number Diff line
@@ -183,18 +183,6 @@ protected:
      return vector;
   }

   template< typename HeaderType >
   static std::size_t
   readBlockSize( const char* block )
   {
      std::pair<std::size_t, std::unique_ptr<std::uint8_t[]>> decoded_data = base64::decode( block, base64::get_encoded_length(sizeof(HeaderType)) );
      if( decoded_data.first != sizeof(HeaderType) )
         throw MeshReaderError( "XMLVTK", "base64-decoding failed - mismatched data size in the binary header (read "
                                          + std::to_string(decoded_data.first) + " bytes, expected " + std::to_string(sizeof(HeaderType)) + " bytes)" );
      const HeaderType* blockSize = reinterpret_cast<const HeaderType*>(decoded_data.second.get());
      return *blockSize;
   }

   template< typename HeaderType, typename T >
   VariantVector
   readBinaryBlock( const char* block ) const
@@ -204,12 +192,26 @@ protected:
         ++block;

      if( compressor == "" ) {
         const std::size_t blockSize = readBlockSize< HeaderType >( block );
         block += base64::get_encoded_length(sizeof(HeaderType));
         std::pair<std::size_t, std::unique_ptr<std::uint8_t[]>> decoded_data = base64::decode( block, base64::get_encoded_length(blockSize) );
         std::vector<T> vector( decoded_data.first / sizeof(T) );
         std::size_t data_size = 0;
         const T* data_ptr = nullptr;
         std::pair<std::size_t, std::unique_ptr<std::uint8_t[]>> decoded_data = base64::decode( block, std::strlen(block) );

         // check if block size was decoded separately (so decoding stopped after block size due to padding)
         if( decoded_data.first == sizeof(HeaderType) ) {
            const std::size_t header_length = base64::get_encoded_length(sizeof(HeaderType));
            const HeaderType block_size = *reinterpret_cast<const HeaderType*>(decoded_data.second.get());
            decoded_data = base64::decode( block + header_length, base64::get_encoded_length(block_size) );
            data_size = decoded_data.first / sizeof(T);
            data_ptr = reinterpret_cast<const T*>(decoded_data.second.get());
         }
         else {
            data_size = *reinterpret_cast<const HeaderType*>(decoded_data.second.get()) / sizeof(T);
            data_ptr = reinterpret_cast<const T*>(decoded_data.second.get() + sizeof(HeaderType));
         }

         std::vector<T> vector( data_size );
         for( std::size_t i = 0; i < vector.size(); i++ )
            vector[i] = reinterpret_cast<const T*>(decoded_data.second.get())[i];
            vector[i] = data_ptr[i];
         return vector;
      }
      else if( compressor == "vtkZLibDataCompressor" ) {
+14 −10
Original line number Diff line number Diff line
@@ -123,11 +123,13 @@ decompress_block(const char* data)
    if (compression_header[0] != 1)
        throw std::length_error("unexpected number of compressed blocks: "
                                + std::to_string(compression_header[0]));
    if (compression_header[1] != compression_header[2])
        throw std::logic_error("inconsistent block sizes in the compression header: "
                               + std::to_string(compression_header[1]) + " vs "
                               + std::to_string(compression_header[2]));
    const HeaderType data_size = compression_header[1] / sizeof(T);
    // Note: for short arrays, paraview 5.9 creates files with:
    //       num_blocks == 1, block_size == 32768, last_block_size == [the actual data size]
    //if (compression_header[1] != compression_header[2])
    //    throw std::logic_error("inconsistent block sizes in the compression header: "
    //                           + std::to_string(compression_header[1]) + " vs "
    //                           + std::to_string(compression_header[2]));
    const HeaderType data_size = compression_header[2] / sizeof(T);
    const HeaderType compressed_data_length = base64::get_encoded_length(compression_header[3]);

    // decode the data
@@ -162,11 +164,13 @@ decompress_block(std::istream& input_stream)
    if (compression_header[0] != 1)
        throw std::length_error("unexpected number of compressed blocks: "
                                + std::to_string(compression_header[0]));
    if (compression_header[1] != compression_header[2])
        throw std::logic_error("inconsistent block sizes in the compression header: "
                               + std::to_string(compression_header[1]) + " vs "
                               + std::to_string(compression_header[2]));
    const HeaderType data_size = compression_header[1] / sizeof(T);
    // Note: for short arrays, paraview 5.9 creates files with:
    //       num_blocks == 1, block_size == 32768, last_block_size == [the actual data size]
    //if (compression_header[1] != compression_header[2])
    //    throw std::logic_error("inconsistent block sizes in the compression header: "
    //                           + std::to_string(compression_header[1]) + " vs "
    //                           + std::to_string(compression_header[2]));
    const HeaderType data_size = compression_header[2] / sizeof(T);
    const HeaderType compressed_data_length = base64::get_encoded_length(compression_header[3]);

    // read the compressed data