112 static const uint8_t MAGIC[8] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
114 if(
m_image.size() < 512 || std::memcmp(
m_image.data(), MAGIC, 8 ) != 0 )
115 THROW_IO_ERROR(
_(
"Not an Easy-PC / DesignSpark file: no compound file signature." ) );
120 return std::make_unique<CFB::CompoundFileReader>(
m_image.data(),
m_image.size() );
123 auto raw = [&]( uint32_t aId )
125 const CFB::COMPOUND_FILE_ENTRY* entry = guarded(
131 if( !entry || entry->nameLen < 2 || entry->nameLen > 64 || entry->nameLen % 2 )
132 corrupt( wxString::Format( wxS(
"directory entry %u" ), aId ) );
137 std::set<uint32_t> visited;
139 auto add = [&]( uint32_t aId )
141 if( !visited.insert( aId ).second )
142 corrupt( wxString::Format( wxS(
"directory entry %u is reached twice" ), aId ) );
144 const CFB::COMPOUND_FILE_ENTRY* entry = raw( aId );
150 std::vector<uint32_t> storages = { 0 };
153 while( !storages.empty() )
155 uint32_t storage = storages.back();
158 std::vector<uint32_t>& members =
m_children[storage];
159 std::vector<uint32_t> stack;
160 uint32_t
id = raw( storage )->childID;
162 while(
id != NOSTREAM || !stack.empty() )
164 for( ;
id != NOSTREAM;
id = raw(
id )->leftSiblingID )
166 stack.push_back(
id );
170 uint32_t node = stack.back();
172 members.push_back( node );
175 storages.push_back( node );
177 id = raw( node )->rightSiblingID;
215 corrupt( wxString::Format( wxS(
"directory entry %u is not a stream" ), aStream.
Id ) );
217 const CFB::COMPOUND_FILE_ENTRY* entry =
m_reader->GetEntry( aStream.
Id );
218 uint64_t size =
m_reader->GetStreamSize( entry );
221 corrupt( wxString::Format( wxS(
"stream %u is larger than the file" ), aStream.
Id ) );
223 std::vector<uint8_t> out(
static_cast<size_t>( size ) );
229 m_reader->ReadFile( entry, 0,
reinterpret_cast<char*
>( out.data() ), out.size() );
263 std::vector<uint8_t> data = entry ?
ReadStream( *entry ) : std::vector<uint8_t>();
267 if( data.size() >= 4 )
270 std::memcpy( bytes, data.data(), 4 );
271 std::memcpy( bytes, data.data() + 4, std::min<size_t>( data.size() - 4, 4 ) );
272 value = boost::endian::load_little_s32( bytes );
275 return value == 0 ? 1 : value;
wxString result
Test unit parsing edge cases and error handling.