KiCad PCB EDA Suite
asset_archive.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <wx/tarstrm.h>
21 #include <wx/wfstream.h>
22 #include <wx/zstream.h>
23 
24 #include <asset_archive.h>
25 
26 
27 ASSET_ARCHIVE::ASSET_ARCHIVE( const wxString& aFilePath, bool aLoadNow ) :
28  m_filePath( aFilePath )
29 {
30  if( aLoadNow )
31  Load();
32 }
33 
34 
36 {
37  // We don't support hot-reloading yet
38  if( !m_fileInfoCache.empty() )
39  return false;
40 
41  wxFFileInputStream zipFile( m_filePath );
42 
43  if( !zipFile.IsOk() )
44  return false;
45 
46  wxZlibInputStream stream( zipFile, wxZLIB_GZIP );
47  wxTarInputStream tarStream( stream );
48  wxTarEntry* entry;
49 
50  // Avoid realloc while reading: we're not going to get better than 2:1 compression
51  m_cache.resize( 2 * zipFile.GetLength() );
52 
53  size_t offset = 0;
54 
55  while( ( entry = tarStream.GetNextEntry() ) )
56  {
57  if( entry->IsDir() )
58  {
59  delete entry;
60  continue;
61  }
62 
63  size_t length = entry->GetSize();
64 
65  FILE_INFO fi;
66  fi.offset = offset;
67  fi.length = length;
68 
69  if( offset + length > m_cache.size() )
70  m_cache.resize( m_cache.size() * 2 );
71 
72  tarStream.Read( &m_cache[offset], length );
73 
74  m_fileInfoCache[entry->GetName()] = fi;
75 
76  offset += length;
77 
78  delete entry;
79  }
80 
81  m_cache.resize( offset );
82 
83  return true;
84 }
85 
86 
87 long ASSET_ARCHIVE::GetFileContents( const wxString& aFilePath, const unsigned char* aDest,
88  size_t aMaxLen )
89 {
90  wxFAIL_MSG( "Unimplemented" );
91  return 0;
92 }
93 
94 
95 long ASSET_ARCHIVE::GetFilePointer( const wxString& aFilePath, const unsigned char** aDest )
96 {
97  if( aFilePath.IsEmpty() )
98  return -1;
99 
100  wxASSERT( aDest );
101 
102  if( !m_fileInfoCache.count( aFilePath ) )
103  return -1;
104 
105  const FILE_INFO& fi = m_fileInfoCache.at( aFilePath );
106 
107  *aDest = &m_cache[fi.offset];
108 
109  return fi.length;
110 }
long GetFileContents(const wxString &aFilePath, const unsigned char *aDest, size_t aMaxLen)
Retrieves a file with the given path from the cached archive.
wxString m_filePath
Path to the source archive file.
Definition: asset_archive.h:75
std::unordered_map< wxString, FILE_INFO > m_fileInfoCache
Cache of file info for a given file path.
Definition: asset_archive.h:69
std::vector< unsigned char > m_cache
The full file contents.
Definition: asset_archive.h:72
ASSET_ARCHIVE(const wxString &aFilePath, bool aLoadNow=true)
long GetFilePointer(const wxString &aFilePath, const unsigned char **aDest)
Retrieves a pointer to a file with the given path from the cached archive.