Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
Package.cpp
1/*
2Copyright (C) 2013,2018,2021,2025 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#include <fstream>
18#include <cstdio>
19#include <stdexcept>
20#include <sstream>
21#include <regex>
22#include "zlib.h"
23#include "aeongames/Package.hpp"
24#include "aeongames/CRC.hpp"
25
26namespace AeonGames
27{
28#if 0
29#define CHUNK 16384
30 /* Decompress from file source to memory dest until stream ends or EOF.
31 read_inflated_data() returns Z_OK on success, Z_MEM_ERROR if memory
32 could not be allocated for processing, Z_DATA_ERROR if the deflate data is
33 invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
34 the version of the library linked do not match, or Z_ERRNO if there
35 is an error reading or writing the files. */
36 static int read_inflated_data ( FILE* source, uint8_t* buffer, uint32_t buffer_size )
37 {
38 int ret;
39 z_stream strm;
40 unsigned char in[CHUNK];
41
42 /* allocate inflate state */
43 strm.zalloc = Z_NULL;
44 strm.zfree = Z_NULL;
45 strm.opaque = Z_NULL;
46 strm.avail_in = 0;
47 strm.next_in = Z_NULL;
48 ret = inflateInit ( &strm );
49 if ( ret != Z_OK )
50 {
51 return ret;
52 }
53 strm.avail_out = buffer_size;
54 strm.next_out = buffer;
55
56 /* decompress until deflate stream ends or end of file */
57 do
58 {
59 strm.avail_in = static_cast<uInt> ( fread ( in, 1, CHUNK, source ) );
60 if ( ferror ( source ) )
61 {
62 ( void ) inflateEnd ( &strm );
63 return Z_ERRNO;
64 }
65 if ( strm.avail_in == 0 )
66 {
67 break;
68 }
69 strm.next_in = in;
70 ret = inflate ( &strm, Z_NO_FLUSH );
71 assert ( ret != Z_STREAM_ERROR ); /* state not clobbered */
72 switch ( ret )
73 {
74 case Z_NEED_DICT:
75 ret = Z_DATA_ERROR; /* and fall through */
76 case Z_DATA_ERROR:
77 case Z_MEM_ERROR:
78 ( void ) inflateEnd ( &strm );
79 return ret;
80 }
81 /* done when inflate() says it's done */
82 }
83 while ( ret != Z_STREAM_END );
84 /* clean up and return */
85 ( void ) inflateEnd ( &strm );
86 return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
87 }
88#endif
89 Package::Package ( const std::string& aPath ) : mPath {aPath}, mIndexTable {}
90 {
91 if ( std::filesystem::is_directory ( mPath ) )
92 {
93 static const std::string format ( "/" );
94 static const std::regex separator ( "\\\\+" );
95 for ( auto& i : std::filesystem::recursive_directory_iterator ( mPath ) )
96 {
97 if ( std::filesystem::is_regular_file ( i ) )
98 {
99 std::string location{std::regex_replace ( std::filesystem::relative ( i, mPath ).string(), separator, format ) };
100 mIndexTable[crc32i ( location.data(), location.size() )] = location;
101 }
102 }
103 }
104 }
105
106 Package::~Package() = default;
107 Package::Package ( Package&& aPackage ) noexcept :
108 mPath ( aPackage.mPath ),
109 mIndexTable ( std::move ( aPackage.mIndexTable ) ) {}
110
111 const std::filesystem::path& Package::GetPath() const
112 {
113 return mPath;
114 }
115 const std::unordered_map<uint32_t, std::string>& Package::GetIndexTable() const
116 {
117 return mIndexTable;
118 }
119 size_t Package::GetFileSize ( uint32_t crc ) const
120 {
121 if ( std::filesystem::is_directory ( mPath ) )
122 {
123 auto it = mIndexTable.find ( crc );
124 if ( it != mIndexTable.end() )
125 {
126 return std::filesystem::file_size ( mPath / it->second );
127 }
128 }
129 return 0;
130 }
131 size_t Package::GetFileSize ( const std::string& aFilename ) const
132 {
133 return GetFileSize ( crc32i ( aFilename.data(), aFilename.size() ) );
134 }
135 void Package::LoadFile ( const std::string& aFilename, void* buffer, size_t buffer_size ) const
136 {
137 LoadFile ( crc32i ( aFilename.data(), aFilename.size() ), buffer, buffer_size );
138 }
139 void Package::LoadFile ( uint32_t crc, void* buffer, size_t buffer_size ) const
140 {
141 if ( std::filesystem::is_directory ( mPath ) )
142 {
143 auto it = mIndexTable.find ( crc );
144 if ( it != mIndexTable.end() )
145 {
146 std::ifstream file;
147 file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
148 file.open ( mPath / it->second, std::ifstream::in | std::ifstream::binary );
149 file.read ( reinterpret_cast<char*> ( buffer ), buffer_size );
150 file.close();
151 }
152 }
153 }
154}
Header for the PKG file specification.
DLL const std::filesystem::path & GetPath() const
Get the path associated with this package.
Definition Package.cpp:111
DLL size_t GetFileSize(uint32_t crc) const
Definition Package.cpp:119
DLL void LoadFile(uint32_t crc, void *buffer, size_t buffer_size) const
Definition Package.cpp:139
DLL ~Package()
Destructor.
DLL const std::unordered_map< uint32_t, std::string > & GetIndexTable() const
Get the package index table.
Definition Package.cpp:115
DLL Package(const std::string &aPath)
Construct a Package from a file path.
Definition Package.cpp:89
<- This is here just for the literals
Definition AABB.hpp:31
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
Definition CRC.cpp:27