Line data Source code
1 :
2 : /* Copyright (c) 2007-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Cedric Stalder <cedric.stalder@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "dataIStream.h"
22 :
23 : #include "global.h"
24 : #include "log.h"
25 : #include "node.h"
26 :
27 : #include <pression/data/Compressor.h>
28 : #include <pression/data/CompressorInfo.h>
29 : #include <lunchbox/buffer.h>
30 : #include <lunchbox/debug.h>
31 :
32 : #include <string.h>
33 :
34 : namespace co
35 : {
36 : namespace detail
37 : {
38 3015942 : class DataIStream
39 : {
40 : public:
41 3013371 : explicit DataIStream( const bool swap_ )
42 3013371 : : input( 0 )
43 : , inputSize( 0 )
44 : , position( 0 )
45 3013371 : , swap( swap_ )
46 3004702 : {}
47 :
48 8 : void initCompressor( const CompressorInfo& info )
49 : {
50 8 : if( info == compressorInfo )
51 0 : return;
52 8 : compressorInfo = info;
53 8 : compressor.reset( info.create( ));
54 8 : LBLOG( LOG_OBJECTS ) << "Allocated " << compressorInfo.name <<std::endl;
55 : }
56 :
57 : /** The current input buffer */
58 : const uint8_t* input;
59 :
60 : /** The size of the input buffer */
61 : uint64_t inputSize;
62 :
63 : /** The current read position in the buffer */
64 : uint64_t position;
65 :
66 : CompressorPtr compressor; //!< current decompressor
67 : CompressorInfo compressorInfo; //!< current decompressor data
68 : lunchbox::Bufferb data; //!< decompressed buffer
69 : bool swap; //!< Invoke endian conversion
70 : };
71 : }
72 :
73 1106353 : DataIStream::DataIStream( const bool swap_ )
74 1106353 : : _impl( new detail::DataIStream( swap_ ))
75 1106116 : {}
76 :
77 1910766 : DataIStream::DataIStream( const DataIStream& rhs )
78 1910766 : : _impl( new detail::DataIStream( rhs._impl->swap ))
79 1910764 : {}
80 :
81 6025867 : DataIStream::~DataIStream()
82 : {
83 3016784 : _reset();
84 3015903 : delete _impl;
85 3009083 : }
86 :
87 593785 : DataIStream& DataIStream::operator = ( const DataIStream& rhs )
88 : {
89 593785 : _reset();
90 593796 : setSwapping( rhs.isSwapping( ));
91 593802 : return *this;
92 : }
93 :
94 593966 : void DataIStream::setSwapping( const bool onOff )
95 : {
96 593966 : _impl->swap = onOff;
97 593966 : }
98 :
99 4196299 : bool DataIStream::isSwapping() const
100 : {
101 4196299 : return _impl->swap;
102 : }
103 :
104 3603551 : void DataIStream::_reset()
105 : {
106 3603551 : _impl->input = 0;
107 3603551 : _impl->inputSize = 0;
108 3603551 : _impl->position = 0;
109 3603551 : _impl->swap = false;
110 3603551 : }
111 :
112 3602349 : void DataIStream::_read( void* data, uint64_t size )
113 : {
114 3602349 : if( !_checkBuffer( ))
115 : {
116 0 : LBUNREACHABLE;
117 0 : LBERROR << "No more input data" << std::endl;
118 0 : return;
119 : }
120 :
121 3602352 : LBASSERT( _impl->input );
122 3602352 : if( size > _impl->inputSize - _impl->position )
123 : {
124 0 : LBERROR << "Not enough data in input buffer: need 0x" << std::hex << size
125 0 : << " bytes, 0x" << _impl->inputSize - _impl->position << " left "
126 0 : << std::dec << std::endl;
127 0 : LBUNREACHABLE;
128 : // TODO: Allow reads which are asymmetric to writes by reading from
129 : // multiple blocks here?
130 0 : return;
131 : }
132 :
133 3602352 : memcpy( data, _impl->input + _impl->position, size );
134 3602352 : _impl->position += size;
135 : }
136 :
137 2484667 : const void* DataIStream::getRemainingBuffer( const uint64_t size )
138 : {
139 2484667 : if( !_checkBuffer( ))
140 0 : return 0;
141 :
142 2476868 : LBASSERT( _impl->position + size <= _impl->inputSize );
143 2476943 : if( _impl->position + size > _impl->inputSize )
144 0 : return 0;
145 :
146 2476943 : _impl->position += size;
147 2476943 : return _impl->input + _impl->position - size;
148 : }
149 :
150 2889905 : uint64_t DataIStream::getRemainingBufferSize()
151 : {
152 2889905 : if( !_checkBuffer( ))
153 110 : return 0;
154 :
155 2879837 : return _impl->inputSize - _impl->position;
156 : }
157 :
158 0 : bool DataIStream::wasUsed() const
159 : {
160 0 : return _impl->input != 0;
161 : }
162 :
163 11521403 : bool DataIStream::_checkBuffer()
164 : {
165 14111507 : while( _impl->position >= _impl->inputSize )
166 : {
167 5191508 : CompressorInfo info;
168 2555357 : uint32_t nChunks = 0;
169 2555357 : const void* data = 0;
170 :
171 2555357 : _impl->position = 0;
172 2555357 : _impl->input = 0;
173 2555357 : _impl->inputSize = 0;
174 :
175 2555357 : if( !getNextBuffer( info, nChunks, data, _impl->inputSize ))
176 161 : return false;
177 :
178 2599074 : _impl->input = _decompress( data, info, nChunks, _impl->inputSize );
179 : }
180 8919999 : return true;
181 : }
182 :
183 2599908 : const uint8_t* DataIStream::_decompress( const void* data,
184 : const CompressorInfo& info,
185 : const uint32_t nChunks,
186 : const uint64_t dataSize )
187 : {
188 2599908 : const uint8_t* src = reinterpret_cast< const uint8_t* >( data );
189 2599908 : if( info.name.empty( ))
190 2601173 : return src;
191 :
192 8 : LBASSERT( !info.name.empty( ));
193 : #ifndef CO_AGGRESSIVE_CACHING
194 8 : _impl->data.clear();
195 : #endif
196 8 : _impl->data.reset( dataSize );
197 8 : _impl->initCompressor( info );
198 :
199 16 : std::vector< std::pair< const uint8_t*, size_t >> inputs( nChunks );
200 16 : for( uint32_t i = 0; i < nChunks; ++i )
201 : {
202 8 : const uint64_t size = *reinterpret_cast< const uint64_t* >( src );
203 8 : src += sizeof( uint64_t );
204 :
205 8 : inputs[ i ] = { src, size };
206 8 : src += size;
207 : }
208 :
209 8 : _impl->compressor->decompress( inputs, _impl->data.getData(), dataSize );
210 8 : return _impl->data.getData();
211 : }
212 :
213 66 : }
|