File include/jrf/read.h changed (mode: 100644) (index cb2c8fd..a3e5842) |
1 |
1 |
#pragma once |
#pragma once |
2 |
|
|
|
3 |
2 |
#include "jrf.h" |
#include "jrf.h" |
4 |
3 |
#include "zip.h" |
#include "zip.h" |
5 |
4 |
#include <jlib/io_agent_mem_ro.h> |
#include <jlib/io_agent_mem_ro.h> |
6 |
5 |
#include <jlib/fs.h> |
#include <jlib/fs.h> |
7 |
6 |
|
|
8 |
|
namespace jrf::details |
|
9 |
|
{ |
|
10 |
|
template<typename IO = jl::io_agent> |
|
11 |
|
[[nodiscard]] inline Result read(IO *p_io, ResourceType type, |
|
12 |
|
ResourceUnion *p_ru) |
|
13 |
|
{ |
|
14 |
|
switch(type) |
|
15 |
|
{ |
|
16 |
|
case ResourceType::IMAGE: return p_ru->image .read(p_io); |
|
17 |
|
case ResourceType::VERTICES: return p_ru->vertices.read(p_io); |
|
18 |
|
case ResourceType::INDICES: return p_ru->indices .read(p_io); |
|
19 |
|
case ResourceType::MESH: return p_ru->mesh .read(p_io); |
|
20 |
|
case ResourceType::MODEL: return p_ru->model .read(p_io); |
|
21 |
|
case ResourceType::SCENE: return p_ru->scene .read(p_io); |
|
22 |
|
default: return Result::UNKNOWN_RESOURCE_TYPE; |
|
23 |
|
} |
|
24 |
|
} |
|
|
7 |
|
namespace jrf::details { |
|
8 |
|
template<typename IO = jl::io_agent> |
|
9 |
|
[[nodiscard]] inline |
|
10 |
|
Result read(IO *p_io, ResourceType type, ResourceUnion *p_ru) { |
|
11 |
|
switch(type) { |
|
12 |
|
case ResourceType::IMAGE: return p_ru->image .read(p_io); |
|
13 |
|
case ResourceType::VERTICES: return p_ru->vertices.read(p_io); |
|
14 |
|
case ResourceType::INDICES: return p_ru->indices .read(p_io); |
|
15 |
|
case ResourceType::MESH: return p_ru->mesh .read(p_io); |
|
16 |
|
case ResourceType::MODEL: return p_ru->model .read(p_io); |
|
17 |
|
case ResourceType::SCENE: return p_ru->scene .read(p_io); |
|
18 |
|
default: return Result::UNKNOWN_RESOURCE_TYPE; |
|
19 |
|
} |
|
20 |
|
} |
25 |
21 |
} |
} |
26 |
22 |
namespace jrf |
namespace jrf |
27 |
23 |
{ |
{ |
28 |
|
template<typename IO = jl::io_agent> |
|
29 |
|
[[nodiscard]] inline Result read(IO *p_mediator, ResourceUnion *p_ru) |
|
30 |
|
{ |
|
31 |
|
EntryHeader header; |
|
32 |
|
|
|
33 |
|
if (not p_mediator->read(&header, sizeof (EntryHeader))) |
|
34 |
|
return MEDIATOR_ERROR; |
|
35 |
|
if (header.magic != MAGIC.integer) |
|
36 |
|
return Result::FILE_WRONG_HEADER; |
|
37 |
|
return details::read(p_mediator, header.type, p_ru); |
|
38 |
|
} |
|
39 |
|
|
|
40 |
|
template<ResourceType RT, typename IO = jl::io_agent> |
|
41 |
|
[[nodiscard]] inline Result read(IO *p_io, |
|
42 |
|
typename Resource<RT>::T *p_resource) |
|
43 |
|
{ |
|
44 |
|
EntryHeader header; |
|
45 |
|
|
|
46 |
|
if (not p_io->read(&header, sizeof (EntryHeader))) |
|
47 |
|
return MEDIATOR_ERROR; |
|
48 |
|
if (header.magic != MAGIC.integer) |
|
49 |
|
return Result::FILE_WRONG_HEADER; |
|
50 |
|
if (header.type != RT) |
|
51 |
|
return Result::RESOURCE_TYPE_MISMATCH; |
|
52 |
|
return p_resource->read(p_io); |
|
53 |
|
} |
|
54 |
|
|
|
55 |
|
template<ResourceType RT> |
|
56 |
|
[[nodiscard]] inline Result read(typename Resource<RT>::T *p_resource, |
|
57 |
|
const char *p_file_path) |
|
58 |
|
{ |
|
59 |
|
char *f_data; |
|
60 |
|
uint64_t fsize; |
|
61 |
|
if (not jl::fs::read_file(p_file_path, &f_data, &fsize)) |
|
62 |
|
return Result::FILE_OPEN_ERROR; |
|
63 |
|
|
|
64 |
|
jl::io_agent_mem_ro m; |
|
65 |
|
m.init(f_data, fsize); |
|
66 |
|
auto res = read<RT>(&m, p_resource); |
|
67 |
|
jl::deallocate(&f_data); |
|
68 |
|
if (res == Result::MEDIATOR_ERROR) |
|
69 |
|
if (m.is_end()) |
|
70 |
|
return Result::FILE_UNEXPECTED_EOF; |
|
71 |
|
return res; |
|
72 |
|
} |
|
73 |
|
|
|
74 |
|
template<ResourceType RT> |
|
75 |
|
[[nodiscard]] inline Result read(typename Resource<RT>::T *p_resource, |
|
76 |
|
const char *p_zip_path, const char *p_fpath_in_zip) |
|
77 |
|
{ |
|
78 |
|
ZipArchive zip; |
|
79 |
|
auto zres = zip.open(p_zip_path); |
|
80 |
|
if (zres != ZipResult::SUCCESS) |
|
81 |
|
return Result::ZIP_ERROR; |
|
82 |
|
|
|
83 |
|
char *f_data; |
|
84 |
|
uint64_t fsize; |
|
85 |
|
zres = ZipSubFile::read_whole_file(&zip, p_fpath_in_zip, &f_data, &fsize); |
|
86 |
|
(void)zip.close(); |
|
87 |
|
if (zres != ZipResult::SUCCESS) |
|
88 |
|
return Result::ZIP_ERROR; |
|
89 |
|
|
|
90 |
|
jl::io_agent_mem_ro m; |
|
91 |
|
m.init(f_data, fsize); |
|
92 |
|
auto res = read<RT>(&m, p_resource); |
|
93 |
|
jl::deallocate(&f_data); |
|
94 |
|
if (res == Result::MEDIATOR_ERROR) |
|
95 |
|
if (m.is_end()) |
|
96 |
|
return Result::FILE_UNEXPECTED_EOF; |
|
97 |
|
return res; |
|
98 |
|
} |
|
|
24 |
|
template<typename IO = jl::io_agent> [[nodiscard]] inline |
|
25 |
|
Result read(IO *p_mediator, ResourceUnion *p_ru) { |
|
26 |
|
EntryHeader header; |
|
27 |
|
if (not p_mediator->read(&header, sizeof (EntryHeader))) |
|
28 |
|
return MEDIATOR_ERROR; |
|
29 |
|
if (header.magic != MAGIC.integer) |
|
30 |
|
return Result::FILE_WRONG_HEADER; |
|
31 |
|
return details::read(p_mediator, header.type, p_ru); |
|
32 |
|
} |
|
33 |
|
template<ResourceType RT, typename IO = jl::io_agent> [[nodiscard]] inline |
|
34 |
|
Result read(IO *p_io, typename Resource<RT>::T *p_resource) { |
|
35 |
|
EntryHeader header; |
|
36 |
|
if (not p_io->read(&header, sizeof (EntryHeader))) |
|
37 |
|
return MEDIATOR_ERROR; |
|
38 |
|
if (header.magic != MAGIC.integer) |
|
39 |
|
return Result::FILE_WRONG_HEADER; |
|
40 |
|
if (header.type != RT) |
|
41 |
|
return Result::RESOURCE_TYPE_MISMATCH; |
|
42 |
|
return p_resource->read(p_io); |
|
43 |
|
} |
|
44 |
|
template<ResourceType RT> [[nodiscard]] inline |
|
45 |
|
Result read(typename Resource<RT>::T *p_resource, const char *p_file_path) { |
|
46 |
|
char *f_data; |
|
47 |
|
uint64_t fsize; |
|
48 |
|
if (not jl::fs::read_file(p_file_path, &f_data, &fsize)) |
|
49 |
|
return Result::FILE_OPEN_ERROR; |
|
50 |
|
jl::io_agent_mem_ro m; |
|
51 |
|
m.init(f_data, fsize); |
|
52 |
|
auto res = read<RT>(&m, p_resource); |
|
53 |
|
jl::deallocate(&f_data); |
|
54 |
|
if (res == Result::MEDIATOR_ERROR) |
|
55 |
|
if (m.is_end()) |
|
56 |
|
return Result::FILE_UNEXPECTED_EOF; |
|
57 |
|
return res; |
|
58 |
|
} |
99 |
59 |
|
|
100 |
|
//single path - file path, two paths - zip and file in zip |
|
101 |
|
template<typename ... PATHS> |
|
102 |
|
[[nodiscard]] inline Result read(ResourceType type, ResourceUnion *p_ru, |
|
103 |
|
PATHS ... paths) |
|
104 |
|
{ |
|
105 |
|
switch(type) |
|
106 |
|
{ |
|
107 |
|
case ResourceType::IMAGE: |
|
108 |
|
return read<ResourceType::IMAGE> (&p_ru->image, paths...); |
|
109 |
|
case ResourceType::VERTICES: |
|
110 |
|
return read<ResourceType::VERTICES>(&p_ru->vertices, paths...); |
|
111 |
|
case ResourceType::INDICES: |
|
112 |
|
return read<ResourceType::INDICES> (&p_ru->indices, paths...); |
|
113 |
|
case ResourceType::MESH: |
|
114 |
|
return read<ResourceType::MESH> (&p_ru->mesh, paths...); |
|
115 |
|
case ResourceType::MODEL: |
|
116 |
|
return read<ResourceType::MODEL> (&p_ru->model, paths...); |
|
117 |
|
case ResourceType::SCENE: |
|
118 |
|
return read<ResourceType::SCENE> (&p_ru->scene, paths...); |
|
119 |
|
default: return Result::UNKNOWN_RESOURCE_TYPE; |
|
120 |
|
} |
|
121 |
|
} |
|
|
60 |
|
template<ResourceType RT> [[nodiscard]] inline |
|
61 |
|
Result read(typename Resource<RT>::T *p_resource, |
|
62 |
|
const char *p_zip_path, const char *p_fpath_in_zip) { |
|
63 |
|
ZipArchive zip; |
|
64 |
|
auto zres = zip.open(p_zip_path); |
|
65 |
|
if (zres != ZipResult::SUCCESS) |
|
66 |
|
return Result::ZIP_ERROR; |
|
67 |
|
char *f_data; |
|
68 |
|
uint64_t fsize; |
|
69 |
|
zres = ZipSubFile::read_whole_file(&zip, p_fpath_in_zip, &f_data, &fsize); |
|
70 |
|
(void)zip.close(); |
|
71 |
|
if (zres != ZipResult::SUCCESS) |
|
72 |
|
return Result::ZIP_ERROR; |
|
73 |
|
jl::io_agent_mem_ro m; |
|
74 |
|
m.init(f_data, fsize); |
|
75 |
|
auto res = read<RT>(&m, p_resource); |
|
76 |
|
jl::deallocate(&f_data); |
|
77 |
|
if (res == Result::MEDIATOR_ERROR) |
|
78 |
|
if (m.is_end()) |
|
79 |
|
return Result::FILE_UNEXPECTED_EOF; |
|
80 |
|
return res; |
|
81 |
|
} |
|
82 |
|
//single path - file path, two paths - zip and file in zip |
|
83 |
|
template<typename ... PATHS> [[nodiscard]] inline |
|
84 |
|
Result read(ResourceType type, ResourceUnion *p_ru, PATHS ... paths) { |
|
85 |
|
switch(type) { |
|
86 |
|
case ResourceType::IMAGE: |
|
87 |
|
return read<ResourceType::IMAGE> (&p_ru->image, paths...); |
|
88 |
|
case ResourceType::VERTICES: |
|
89 |
|
return read<ResourceType::VERTICES>(&p_ru->vertices, paths...); |
|
90 |
|
case ResourceType::INDICES: |
|
91 |
|
return read<ResourceType::INDICES> (&p_ru->indices, paths...); |
|
92 |
|
case ResourceType::MESH: |
|
93 |
|
return read<ResourceType::MESH> (&p_ru->mesh, paths...); |
|
94 |
|
case ResourceType::MODEL: |
|
95 |
|
return read<ResourceType::MODEL> (&p_ru->model, paths...); |
|
96 |
|
case ResourceType::SCENE: |
|
97 |
|
return read<ResourceType::SCENE> (&p_ru->scene, paths...); |
|
98 |
|
default: return Result::UNKNOWN_RESOURCE_TYPE; |
|
99 |
|
} |
|
100 |
|
} |
122 |
101 |
} |
} |
File include/jrf/scene.h changed (mode: 100644) (index 5d2f1a0..d3c6f31) |
1 |
1 |
#pragma once |
#pragma once |
2 |
|
|
|
3 |
2 |
#include "model.h" |
#include "model.h" |
4 |
3 |
#include <jlib/array.h> |
#include <jlib/array.h> |
5 |
4 |
|
|
|
... |
... |
namespace jrf { struct Scene; struct SceneEntry; } |
7 |
6 |
|
|
8 |
7 |
struct jrf::SceneEntry |
struct jrf::SceneEntry |
9 |
8 |
{ |
{ |
10 |
|
struct Options { |
|
11 |
|
void set_default() |
|
12 |
|
{ |
|
13 |
|
pos = {}; |
|
14 |
|
shift = {}; |
|
15 |
|
transform = {}; |
|
16 |
|
transform[0] = transform[5] = transform[10] = transform[15] = 1; |
|
17 |
|
} |
|
18 |
|
|
|
19 |
|
jl::array<float, 3> pos; ///< position |
|
20 |
|
jl::array<int32_t,3> shift; ///< shift of position |
|
21 |
|
jl::array<float, 16> transform; ///< transformation matrix 4x4 |
|
22 |
|
}; |
|
23 |
|
|
|
24 |
|
void destroy() { model_path.destroy(); } |
|
25 |
|
|
|
26 |
|
Options options; |
|
27 |
|
jl::string model_path; |
|
28 |
|
|
|
29 |
|
template<typename IO = jl::io_agent> |
|
30 |
|
[[nodiscard]] Result read(IO *p_mediator) |
|
31 |
|
{ |
|
32 |
|
Result res = read_str(p_mediator, &model_path); |
|
33 |
|
if (res != Result::SUCCESS) |
|
34 |
|
return res; |
|
35 |
|
|
|
36 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
37 |
|
if (not p_io->read_items(&options.pos)) |
|
38 |
|
goto CANCEL; |
|
39 |
|
if (not p_io->read_items(&options.shift)) |
|
40 |
|
goto CANCEL; |
|
41 |
|
if (not p_io->read_items(&options.transform)) |
|
42 |
|
goto CANCEL; |
|
43 |
|
|
|
44 |
|
return Result::SUCCESS; |
|
45 |
|
|
|
|
9 |
|
template<typename IO = jl::io_agent> [[nodiscard]] |
|
10 |
|
Result read(IO *p_mediator) { |
|
11 |
|
Result res = read_str(p_mediator, &model_path); |
|
12 |
|
if (res != Result::SUCCESS) |
|
13 |
|
return res; |
|
14 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
15 |
|
if (not p_io->read_items(&options.pos)) |
|
16 |
|
goto CANCEL; |
|
17 |
|
if (not p_io->read_items(&options.shift)) |
|
18 |
|
goto CANCEL; |
|
19 |
|
if (not p_io->read_items(&options.transform)) |
|
20 |
|
goto CANCEL; |
|
21 |
|
return Result::SUCCESS; |
46 |
22 |
CANCEL: destroy(); |
CANCEL: destroy(); |
47 |
|
return Result::MEDIATOR_ERROR; |
|
48 |
|
} |
|
49 |
|
template<typename IO = jl::io_agent> |
|
50 |
|
[[nodiscard]] Result write(IO *p_mediator) const |
|
51 |
|
{ |
|
52 |
|
if (p_mediator->write(model_path.begin(), model_path.size()) |
|
53 |
|
!= int64_t(model_path.size())) |
|
54 |
|
return Result::MEDIATOR_ERROR; |
|
55 |
|
|
|
56 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
57 |
|
if (not p_io->write_items(&options.pos)) |
|
58 |
|
return Result::MEDIATOR_ERROR; |
|
59 |
|
if (not p_io->write_items(&options.shift)) |
|
60 |
|
return Result::MEDIATOR_ERROR; |
|
61 |
|
if (not p_io->write_items(&options.transform)) |
|
62 |
|
return Result::MEDIATOR_ERROR; |
|
63 |
|
|
|
64 |
|
return Result::SUCCESS; |
|
65 |
|
} |
|
|
23 |
|
return Result::MEDIATOR_ERROR; |
|
24 |
|
} |
|
25 |
|
template<typename IO = jl::io_agent> [[nodiscard]] |
|
26 |
|
Result write(IO *p_mediator) const { |
|
27 |
|
if (p_mediator->write(model_path.begin(), model_path.size()) |
|
28 |
|
!= int64_t(model_path.size())) |
|
29 |
|
return Result::MEDIATOR_ERROR; |
|
30 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
31 |
|
if (not p_io->write_items(&options.pos)) |
|
32 |
|
return Result::MEDIATOR_ERROR; |
|
33 |
|
if (not p_io->write_items(&options.shift)) |
|
34 |
|
return Result::MEDIATOR_ERROR; |
|
35 |
|
if (not p_io->write_items(&options.transform)) |
|
36 |
|
return Result::MEDIATOR_ERROR; |
|
37 |
|
return Result::SUCCESS; |
|
38 |
|
} |
|
39 |
|
struct Options { |
|
40 |
|
void set_default() { |
|
41 |
|
pos = {}; |
|
42 |
|
shift = {}; |
|
43 |
|
transform = {}; |
|
44 |
|
transform[0] = transform[5] = transform[10] = transform[15] = 1; |
|
45 |
|
} |
|
46 |
|
jl::array<float, 3> pos; ///< position |
|
47 |
|
jl::array<int32_t,3> shift; ///< shift of position |
|
48 |
|
jl::array<float, 16> transform; ///< transformation matrix 4x4 |
|
49 |
|
}; |
|
50 |
|
void destroy() { |
|
51 |
|
model_path.destroy(); |
|
52 |
|
} |
|
53 |
|
Options options; |
|
54 |
|
jl::string model_path; |
66 |
55 |
}; |
}; |
67 |
|
|
|
68 |
|
|
|
69 |
56 |
struct jrf::Scene |
struct jrf::Scene |
70 |
57 |
{ |
{ |
71 |
|
struct Options { |
|
72 |
|
void set_default_value() { *this = {}; } |
|
73 |
|
jl::array<int32_t, 3> shift; ///< global shift of scene |
|
74 |
|
int32_t shift_po2; ///< Power of two |
|
75 |
|
}; |
|
76 |
|
|
|
77 |
|
Options options; |
|
78 |
|
jl::rarray<SceneEntry> entries; |
|
79 |
|
|
|
80 |
|
void destroy() { entries.destroy(&SceneEntry::destroy); } |
|
81 |
|
|
|
82 |
|
template<typename IO = jl::io_agent> |
|
83 |
|
[[nodiscard]] Result read(IO *p_mediator) |
|
84 |
|
{ |
|
85 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
86 |
|
if (not p_io->read_items(&options.shift)) |
|
87 |
|
return Result::MEDIATOR_ERROR; |
|
88 |
|
if (not p_io->read_items(&options.shift_po2)) |
|
89 |
|
return Result::MEDIATOR_ERROR; |
|
90 |
|
|
|
91 |
|
uint64_t entry_count; |
|
92 |
|
if (not p_io->read_items(&entry_count)) |
|
93 |
|
return Result::MEDIATOR_ERROR; |
|
94 |
|
|
|
95 |
|
if (entry_count == 0) { |
|
96 |
|
entries.init(); |
|
97 |
|
return Result::SUCCESS; |
|
98 |
|
} |
|
99 |
|
if (not entries.init(entry_count)) |
|
100 |
|
return Result::ALLOCATION_FAIL; |
|
101 |
|
|
|
102 |
|
for (uint64_t i = 0; i < entry_count; ++i) |
|
103 |
|
{ |
|
104 |
|
Result res = entries[i].read(p_mediator); |
|
105 |
|
if (res != Result::SUCCESS) |
|
106 |
|
{ |
|
107 |
|
while(i > 0) |
|
108 |
|
entries[--i].destroy(); |
|
109 |
|
entries.destroy(); |
|
110 |
|
return res; |
|
111 |
|
} |
|
112 |
|
} |
|
113 |
|
return Result::SUCCESS; |
|
114 |
|
} |
|
115 |
|
|
|
116 |
|
template<typename IO = jl::io_agent> |
|
117 |
|
[[nodiscard]] Result write(IO *p_mediator) const |
|
118 |
|
{ |
|
119 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
120 |
|
if (not p_io->write_items(&options.shift)) |
|
121 |
|
return Result::MEDIATOR_ERROR; |
|
122 |
|
if (not p_io->write_items(&options.shift_po2)) |
|
123 |
|
return Result::MEDIATOR_ERROR; |
|
124 |
|
|
|
125 |
|
size_t entry_count = entries.count(); |
|
126 |
|
if (not p_io->write_items(&entry_count)) |
|
127 |
|
return Result::MEDIATOR_ERROR; |
|
128 |
|
|
|
129 |
|
for (auto &e : entries) { |
|
130 |
|
Result res = e.write(p_mediator); |
|
131 |
|
if (res != Result::SUCCESS) |
|
132 |
|
return res; |
|
133 |
|
} |
|
134 |
|
return Result::SUCCESS; |
|
135 |
|
} |
|
|
58 |
|
void destroy() { |
|
59 |
|
entries.destroy(&SceneEntry::destroy); |
|
60 |
|
} |
|
61 |
|
template<typename IO = jl::io_agent> [[nodiscard]] |
|
62 |
|
Result read(IO *p_mediator) { |
|
63 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
64 |
|
if (not p_io->read_items(&options.shift)) |
|
65 |
|
return Result::MEDIATOR_ERROR; |
|
66 |
|
if (not p_io->read_items(&options.shift_po2)) |
|
67 |
|
return Result::MEDIATOR_ERROR; |
|
68 |
|
uint64_t entry_count; |
|
69 |
|
if (not p_io->read_items(&entry_count)) |
|
70 |
|
return Result::MEDIATOR_ERROR; |
|
71 |
|
if (entry_count == 0) { |
|
72 |
|
entries.init(); |
|
73 |
|
return Result::SUCCESS; |
|
74 |
|
} |
|
75 |
|
if (not entries.init(entry_count)) |
|
76 |
|
return Result::ALLOCATION_FAIL; |
|
77 |
|
for (uint64_t i = 0; i < entry_count; ++i) { |
|
78 |
|
Result res = entries[i].read(p_mediator); |
|
79 |
|
if (res != Result::SUCCESS) { |
|
80 |
|
while(i > 0) |
|
81 |
|
entries[--i].destroy(); |
|
82 |
|
entries.destroy(); |
|
83 |
|
return res; |
|
84 |
|
} |
|
85 |
|
} |
|
86 |
|
return Result::SUCCESS; |
|
87 |
|
} |
|
88 |
|
template<typename IO = jl::io_agent> [[nodiscard]] |
|
89 |
|
Result write(IO *p_mediator) const { |
|
90 |
|
auto *p_io = jl::io_agent_p_alt_cast(p_mediator); |
|
91 |
|
if (not p_io->write_items(&options.shift)) |
|
92 |
|
return Result::MEDIATOR_ERROR; |
|
93 |
|
if (not p_io->write_items(&options.shift_po2)) |
|
94 |
|
return Result::MEDIATOR_ERROR; |
|
95 |
|
size_t entry_count = entries.count(); |
|
96 |
|
if (not p_io->write_items(&entry_count)) |
|
97 |
|
return Result::MEDIATOR_ERROR; |
|
98 |
|
for (auto &e : entries) { |
|
99 |
|
Result res = e.write(p_mediator); |
|
100 |
|
if (res != Result::SUCCESS) |
|
101 |
|
return res; |
|
102 |
|
} |
|
103 |
|
return Result::SUCCESS; |
|
104 |
|
} |
|
105 |
|
struct Options { |
|
106 |
|
void set_default_value() { *this = {}; } |
|
107 |
|
jl::array<int32_t, 3> shift; ///< global shift of scene |
|
108 |
|
int32_t shift_po2; ///< Power of two |
|
109 |
|
}; |
|
110 |
|
Options options; |
|
111 |
|
jl::rarray<SceneEntry> entries; |
136 |
112 |
}; |
}; |
File include/jrf/zip.h changed (mode: 100644) (index 4c3cb1d..29300cd) |
1 |
1 |
#pragma once |
#pragma once |
2 |
|
|
|
3 |
2 |
#include <zip.h> |
#include <zip.h> |
4 |
3 |
#include <jlib/allocate.h> |
#include <jlib/allocate.h> |
5 |
4 |
|
|
6 |
|
enum ZipResult : int |
|
7 |
|
{ |
|
8 |
|
SUCCESS, |
|
9 |
|
ENTRY_CHANGED = ZIP_ER_CHANGED, |
|
10 |
|
CLOSE_FAILED = ZIP_ER_CLOSE, |
|
11 |
|
UNSUPPORTED_COMPRESSION_METHED = ZIP_ER_COMPNOTSUPP, |
|
12 |
|
INVALID_COMPRESSED_DATA = ZIP_ER_COMPRESSED_DATA, |
|
13 |
|
CRC_ERROR = ZIP_ER_CRC, |
|
14 |
|
ENTRY_DELETED = ZIP_ER_DELETED, |
|
15 |
|
UNSUPPORTED_ENCRYPTION_METHOD = ZIP_ER_ENCRNOTSUPP, |
|
16 |
|
PREMATURE_EOF = ZIP_ER_EOF, |
|
17 |
|
EXIST = ZIP_ER_EXISTS, |
|
18 |
|
ARCHIVE_INCONSISTENT = ZIP_ER_INCONS, |
|
19 |
|
INTERNAL_ERROR = ZIP_ER_INTERNAL, |
|
20 |
|
RESOURCE_IN_USE = ZIP_ER_INUSE, |
|
21 |
|
INVALID_ARGUMENT = ZIP_ER_INVAL, |
|
22 |
|
ALLOCATION_FAIL = ZIP_ER_MEMORY, |
|
23 |
|
UNSUPPORTED_MULTI_DISK = ZIP_ER_MULTIDISK, |
|
24 |
|
FILE_MISSING = ZIP_ER_NOENT, |
|
25 |
|
PASSWORD_NOT_PROVIDED = ZIP_ER_NOPASSWD, |
|
26 |
|
NOT_A_ZIP = ZIP_ER_NOZIP, |
|
27 |
|
CANT_OPEN_FILE = ZIP_ER_OPEN, |
|
28 |
|
UNSUPPORTED_OPERATION = ZIP_ER_OPNOTSUPP, |
|
29 |
|
READ_ONLY_ARCHIVE = ZIP_ER_RDONLY, |
|
30 |
|
READ_ERROR = ZIP_ER_READ, |
|
31 |
|
CANT_REMOVE_FILE = ZIP_ER_REMOVE, |
|
32 |
|
RENAME_FAIL = ZIP_ER_RENAME, |
|
33 |
|
SEEK_FAIL = ZIP_ER_SEEK, |
|
34 |
|
TELL_FAIL = ZIP_ER_TELL, |
|
35 |
|
TEMP_FILE_CREATE_FAIL = ZIP_ER_TMPOPEN, |
|
36 |
|
WRITE_FAIL = ZIP_ER_WRITE, |
|
37 |
|
PASSWORD_WRONG = ZIP_ER_WRONGPASSWD, |
|
38 |
|
FILE_CLOSED = ZIP_ER_ZIPCLOSED, |
|
39 |
|
ZLIB_ERROR = ZIP_ER_ZLIB, |
|
|
5 |
|
enum ZipResult : int { |
|
6 |
|
SUCCESS, |
|
7 |
|
ENTRY_CHANGED = ZIP_ER_CHANGED, |
|
8 |
|
CLOSE_FAILED = ZIP_ER_CLOSE, |
|
9 |
|
UNSUPPORTED_COMPRESSION_METHED = ZIP_ER_COMPNOTSUPP, |
|
10 |
|
INVALID_COMPRESSED_DATA = ZIP_ER_COMPRESSED_DATA, |
|
11 |
|
CRC_ERROR = ZIP_ER_CRC, |
|
12 |
|
ENTRY_DELETED = ZIP_ER_DELETED, |
|
13 |
|
UNSUPPORTED_ENCRYPTION_METHOD = ZIP_ER_ENCRNOTSUPP, |
|
14 |
|
PREMATURE_EOF = ZIP_ER_EOF, |
|
15 |
|
EXIST = ZIP_ER_EXISTS, |
|
16 |
|
ARCHIVE_INCONSISTENT = ZIP_ER_INCONS, |
|
17 |
|
INTERNAL_ERROR = ZIP_ER_INTERNAL, |
|
18 |
|
RESOURCE_IN_USE = ZIP_ER_INUSE, |
|
19 |
|
INVALID_ARGUMENT = ZIP_ER_INVAL, |
|
20 |
|
ALLOCATION_FAIL = ZIP_ER_MEMORY, |
|
21 |
|
UNSUPPORTED_MULTI_DISK = ZIP_ER_MULTIDISK, |
|
22 |
|
FILE_MISSING = ZIP_ER_NOENT, |
|
23 |
|
PASSWORD_NOT_PROVIDED = ZIP_ER_NOPASSWD, |
|
24 |
|
NOT_A_ZIP = ZIP_ER_NOZIP, |
|
25 |
|
CANT_OPEN_FILE = ZIP_ER_OPEN, |
|
26 |
|
UNSUPPORTED_OPERATION = ZIP_ER_OPNOTSUPP, |
|
27 |
|
READ_ONLY_ARCHIVE = ZIP_ER_RDONLY, |
|
28 |
|
READ_ERROR = ZIP_ER_READ, |
|
29 |
|
CANT_REMOVE_FILE = ZIP_ER_REMOVE, |
|
30 |
|
RENAME_FAIL = ZIP_ER_RENAME, |
|
31 |
|
SEEK_FAIL = ZIP_ER_SEEK, |
|
32 |
|
TELL_FAIL = ZIP_ER_TELL, |
|
33 |
|
TEMP_FILE_CREATE_FAIL = ZIP_ER_TMPOPEN, |
|
34 |
|
WRITE_FAIL = ZIP_ER_WRITE, |
|
35 |
|
PASSWORD_WRONG = ZIP_ER_WRONGPASSWD, |
|
36 |
|
FILE_CLOSED = ZIP_ER_ZIPCLOSED, |
|
37 |
|
ZLIB_ERROR = ZIP_ER_ZLIB, |
40 |
38 |
}; |
}; |
41 |
|
|
|
42 |
|
[[nodiscard]] inline int * zip_result_ptr(ZipResult *p_r) { return reinterpret_cast<int*>(p_r); } |
|
43 |
|
[[nodiscard]] inline ZipResult * zip_result_ptr(int *p_r) { return reinterpret_cast<ZipResult*>(p_r); } |
|
44 |
|
[[nodiscard]] inline ZipResult zip_result_int(int r) { return static_cast<ZipResult>(r); } |
|
45 |
|
[[nodiscard]] inline int zip_result_int(ZipResult r) { return static_cast<int>(r); } |
|
46 |
|
|
|
|
39 |
|
[[nodiscard]] inline int * zip_result_ptr(ZipResult *p_r) { |
|
40 |
|
return reinterpret_cast<int*>(p_r); |
|
41 |
|
} |
|
42 |
|
[[nodiscard]] inline ZipResult * zip_result_ptr(int *p_r) { |
|
43 |
|
return reinterpret_cast<ZipResult*>(p_r); |
|
44 |
|
} |
|
45 |
|
[[nodiscard]] inline ZipResult zip_result_int(int r) { |
|
46 |
|
return static_cast<ZipResult>(r); |
|
47 |
|
} |
|
48 |
|
[[nodiscard]] inline int zip_result_int(ZipResult r) { |
|
49 |
|
return static_cast<int>(r); |
|
50 |
|
} |
47 |
51 |
using ZipIndex = int64_t; |
using ZipIndex = int64_t; |
48 |
52 |
|
|
49 |
|
struct ZipStat |
|
50 |
|
{ |
|
51 |
|
enum Flag |
|
52 |
|
{ |
|
53 |
|
NAME = ZIP_STAT_NAME, |
|
54 |
|
INDEX = ZIP_STAT_INDEX, |
|
55 |
|
SIZE = ZIP_STAT_SIZE, |
|
56 |
|
COMPRESSED_SIZE = ZIP_STAT_COMP_SIZE, |
|
57 |
|
MODIFICATION_TIME = ZIP_STAT_MTIME, |
|
58 |
|
CRC = ZIP_STAT_CRC, |
|
59 |
|
COMPRESSION_METHOD = ZIP_STAT_COMP_METHOD, |
|
60 |
|
ENCRYPTION_METHOD = ZIP_STAT_ENCRYPTION_METHOD, |
|
61 |
|
FLAGS = ZIP_STAT_FLAGS |
|
62 |
|
}; |
|
63 |
|
|
|
64 |
|
inline void init() { zip_stat_init(&stat); } |
|
65 |
|
|
|
66 |
|
inline void _valid(Flag f) { stat.valid |= f; } |
|
67 |
|
inline void name(const char* p) { stat.name = p; _valid(NAME); } |
|
68 |
|
inline void index(uint64_t i) { stat.index = i; _valid(INDEX); } |
|
69 |
|
inline void size(uint64_t s) { stat.size = s; _valid(SIZE); } |
|
70 |
|
inline void compressed_size(uint64_t cs) { stat.comp_size = cs; _valid(COMPRESSED_SIZE); } |
|
71 |
|
inline void modification_time(time_t t) { stat.mtime = t; _valid(MODIFICATION_TIME); } |
|
72 |
|
inline void crc(uint32_t crc) { stat.crc = crc; _valid(CRC); } |
|
73 |
|
inline void compression_method(uint16_t cm) { stat.comp_method = cm; _valid(COMPRESSION_METHOD); } |
|
74 |
|
inline void encryption_method(uint16_t em) { stat.encryption_method = em; _valid(ENCRYPTION_METHOD); } |
|
75 |
|
|
|
76 |
|
|
|
77 |
|
[[nodiscard]] inline bool valid(Flag f) { return stat.valid & f; } |
|
78 |
|
[[nodiscard]] inline const char* name() { return valid(NAME) ? stat.name : nullptr; } |
|
79 |
|
[[nodiscard]] inline uint64_t index() { return valid(INDEX) ? stat.index : 0; } |
|
80 |
|
[[nodiscard]] inline uint64_t size() { return valid(SIZE) ? stat.size : 0; } |
|
81 |
|
[[nodiscard]] inline uint64_t compressed_size() { return valid(COMPRESSED_SIZE) ? stat.comp_size : 0; } |
|
82 |
|
[[nodiscard]] inline time_t modification_time() { return valid(MODIFICATION_TIME) ? stat.mtime : 0; } |
|
83 |
|
[[nodiscard]] inline uint32_t crc() { return valid(CRC) ? stat.crc : 0; } |
|
84 |
|
[[nodiscard]] inline uint16_t compression_method() { return valid(COMPRESSION_METHOD) ? stat.comp_method : 0; } |
|
85 |
|
[[nodiscard]] inline uint16_t encryption_method() { return valid(ENCRYPTION_METHOD) ? stat.encryption_method : 0; } |
|
86 |
|
|
|
87 |
|
zip_stat_t stat; |
|
|
53 |
|
struct ZipStat { |
|
54 |
|
enum Flag { |
|
55 |
|
NAME = ZIP_STAT_NAME, |
|
56 |
|
INDEX = ZIP_STAT_INDEX, |
|
57 |
|
SIZE = ZIP_STAT_SIZE, |
|
58 |
|
COMPRESSED_SIZE = ZIP_STAT_COMP_SIZE, |
|
59 |
|
MODIFICATION_TIME = ZIP_STAT_MTIME, |
|
60 |
|
CRC = ZIP_STAT_CRC, |
|
61 |
|
COMPRESSION_METHOD = ZIP_STAT_COMP_METHOD, |
|
62 |
|
ENCRYPTION_METHOD = ZIP_STAT_ENCRYPTION_METHOD, |
|
63 |
|
FLAGS = ZIP_STAT_FLAGS |
|
64 |
|
}; |
|
65 |
|
void init() { |
|
66 |
|
zip_stat_init(&stat); |
|
67 |
|
} |
|
68 |
|
void name(const char* p) { |
|
69 |
|
stat.name = p; |
|
70 |
|
set_valid(NAME); |
|
71 |
|
} |
|
72 |
|
void index(uint64_t i) { |
|
73 |
|
stat.index = i; set_valid(INDEX); |
|
74 |
|
} |
|
75 |
|
void size(uint64_t s) { |
|
76 |
|
stat.size = s; set_valid(SIZE); |
|
77 |
|
} |
|
78 |
|
void compressed_size(uint64_t cs) { |
|
79 |
|
stat.comp_size = cs; set_valid(COMPRESSED_SIZE); |
|
80 |
|
} |
|
81 |
|
void modification_time(time_t t) { |
|
82 |
|
stat.mtime = t; set_valid(MODIFICATION_TIME); |
|
83 |
|
} |
|
84 |
|
void crc(uint32_t crc) { |
|
85 |
|
stat.crc = crc; set_valid(CRC); |
|
86 |
|
} |
|
87 |
|
void compression_method(uint16_t cm) { |
|
88 |
|
stat.comp_method = cm; set_valid(COMPRESSION_METHOD); |
|
89 |
|
} |
|
90 |
|
void encryption_method(uint16_t em) { |
|
91 |
|
stat.encryption_method = em; set_valid(ENCRYPTION_METHOD); |
|
92 |
|
} |
|
93 |
|
[[nodiscard]] bool is_valid(Flag f) { |
|
94 |
|
return stat.valid & f; |
|
95 |
|
} |
|
96 |
|
[[nodiscard]] const char* name() { |
|
97 |
|
return is_valid(NAME) ? stat.name : nullptr; |
|
98 |
|
} |
|
99 |
|
[[nodiscard]] uint64_t index() { |
|
100 |
|
return is_valid(INDEX) ? stat.index : 0; |
|
101 |
|
} |
|
102 |
|
[[nodiscard]] uint64_t size() { |
|
103 |
|
return is_valid(SIZE) ? stat.size : 0; |
|
104 |
|
} |
|
105 |
|
[[nodiscard]] uint64_t compressed_size() { |
|
106 |
|
return is_valid(COMPRESSED_SIZE) ? stat.comp_size : 0; |
|
107 |
|
} |
|
108 |
|
[[nodiscard]] time_t modification_time() { |
|
109 |
|
return is_valid(MODIFICATION_TIME) ? stat.mtime : 0; |
|
110 |
|
} |
|
111 |
|
[[nodiscard]] uint32_t crc() { |
|
112 |
|
return is_valid(CRC) ? stat.crc : 0; |
|
113 |
|
} |
|
114 |
|
[[nodiscard]] uint16_t compression_method() { |
|
115 |
|
return is_valid(COMPRESSION_METHOD) ? stat.comp_method : 0; |
|
116 |
|
} |
|
117 |
|
[[nodiscard]] uint16_t encryption_method() { |
|
118 |
|
return is_valid(ENCRYPTION_METHOD) ? stat.encryption_method : 0; |
|
119 |
|
} |
|
120 |
|
zip_stat_t stat; |
|
121 |
|
|
|
122 |
|
private: |
|
123 |
|
void set_valid(Flag f) { |
|
124 |
|
stat.valid |= f; |
|
125 |
|
} |
88 |
126 |
}; |
}; |
89 |
|
|
|
90 |
127 |
using ZipError = zip_error; |
using ZipError = zip_error; |
91 |
128 |
|
|
92 |
129 |
struct ZipSource |
struct ZipSource |
93 |
130 |
{ |
{ |
94 |
|
[[nodiscard]] ZipResult create(const void *p_data, uint64_t byte_count, int free_data_bool) |
|
95 |
|
{ |
|
96 |
|
zip_error_t es; |
|
97 |
|
p = zip_source_buffer_create(p_data, byte_count, free_data_bool, &es); |
|
98 |
|
return zip_result_int(es.zip_err); |
|
99 |
|
} |
|
100 |
|
[[nodiscard]] ZipResult create(const char *file_path, uint64_t start_offset, int64_t byte_count_or_0_if_whole_file) |
|
101 |
|
{ |
|
102 |
|
zip_error_t es; |
|
103 |
|
p = zip_source_file_create(file_path, start_offset, byte_count_or_0_if_whole_file, &es); |
|
104 |
|
return zip_result_int(es.zip_err); |
|
105 |
|
} |
|
106 |
|
|
|
107 |
|
void destroy() |
|
108 |
|
{ |
|
109 |
|
zip_source_free(p); |
|
110 |
|
} |
|
|
131 |
|
[[nodiscard]] ZipResult |
|
132 |
|
create(const void *p_data, uint64_t byte_count, int free_data_bool) { |
|
133 |
|
zip_error_t es; |
|
134 |
|
p = zip_source_buffer_create(p_data, byte_count, free_data_bool, &es); |
|
135 |
|
return zip_result_int(es.zip_err); |
|
136 |
|
} |
|
137 |
|
[[nodiscard]] ZipResult |
|
138 |
|
create(const char *file_path, uint64_t start_offset, |
|
139 |
|
int64_t byte_count_or_0_if_whole_file) { |
|
140 |
|
zip_error_t es; |
|
141 |
|
p = zip_source_file_create(file_path, start_offset, byte_count_or_0_if_whole_file, &es); |
|
142 |
|
return zip_result_int(es.zip_err); |
|
143 |
|
} |
|
144 |
|
void destroy() { |
|
145 |
|
zip_source_free(p); |
|
146 |
|
} |
111 |
147 |
// mingw macro |
// mingw macro |
112 |
148 |
#undef ERROR |
#undef ERROR |
113 |
|
enum Cmd { |
|
114 |
|
OPEN, /* prepare for reading */ |
|
115 |
|
READ, /* read data */ |
|
116 |
|
CLOSE, /* reading is done */ |
|
117 |
|
STAT, /* get meta information */ |
|
118 |
|
ERROR, /* get error information */ |
|
119 |
|
FREE, /* cleanup and free resources */ |
|
120 |
|
SEEK, /* set position for reading */ |
|
121 |
|
TELL, /* get read position */ |
|
122 |
|
BEGIN_WRITE, /* prepare for writing */ |
|
123 |
|
COMMIT_WRITE, /* writing is done */ |
|
124 |
|
ROLLBACK_WRITE, /* discard written changes */ |
|
125 |
|
WRITE, /* write data */ |
|
126 |
|
SEEK_WRITE, /* set position for writing */ |
|
127 |
|
TELL_WRITE, /* get write position */ |
|
128 |
|
SUPPORTS, /* check whether source supports command */ |
|
129 |
|
REMOVE, /* remove file */ |
|
130 |
|
GET_COMPRESSION_FLAGS, /* get compression flags, internal only */ |
|
131 |
|
BEGIN_WRITE_CLONING, /* like BEGIN_WRITE, but keep part of original file */ |
|
132 |
|
COUNT // cmd count |
|
133 |
|
}; |
|
134 |
|
|
|
135 |
|
template<typename T> |
|
136 |
|
using PF_Callback = int64_t (*)(T *p_userdata, void *p_data, uint64_t length, Cmd cmd); |
|
137 |
|
template<typename T> |
|
138 |
|
using PF_CallbackCmd = int64_t (*)(T *p_userdata, void *p_data, uint64_t length); |
|
139 |
|
|
|
140 |
|
template<typename T> |
|
141 |
|
using PF_CallbackCmdOpen = int64_t (*)(T *p_userdata); |
|
142 |
|
template<typename T> |
|
143 |
|
using PF_CallbackCmdStat = int64_t (*)(T *p_userdata, ZipStat *p_data); |
|
144 |
|
template<typename T> |
|
145 |
|
using PF_CallbackCmdError = int64_t (*)(T *p_userdata, ZipError *p_data); |
|
146 |
|
|
|
147 |
|
template<typename T> |
|
148 |
|
struct CallbacksCmd |
|
149 |
|
{ |
|
150 |
|
//read from source |
|
151 |
|
PF_CallbackCmdOpen<T> OPEN; |
|
152 |
|
PF_CallbackCmd<T> READ; |
|
153 |
|
PF_CallbackCmd<T> CLOSE; |
|
154 |
|
PF_CallbackCmdStat<T> STAT; |
|
155 |
|
PF_CallbackCmdError<T> ERROR; |
|
156 |
|
|
|
157 |
|
//read from source with seeking |
|
158 |
|
PF_CallbackCmd<T> SEEK; |
|
159 |
|
PF_CallbackCmd<T> TELL; |
|
160 |
|
|
|
161 |
|
|
|
162 |
|
//write |
|
163 |
|
PF_CallbackCmd<T> BEGIN_WRITE; |
|
164 |
|
PF_CallbackCmd<T> COMMIT_WRITE; |
|
165 |
|
PF_CallbackCmd<T> ROLLBACK_WRITE; |
|
166 |
|
PF_CallbackCmd<T> SEEK_WRITE; |
|
167 |
|
PF_CallbackCmd<T> TELL_WRITE; |
|
168 |
|
PF_CallbackCmd<T> REMOVE; |
|
169 |
|
|
|
170 |
|
|
|
171 |
|
//unknown |
|
172 |
|
PF_CallbackCmd<T> WRITE; |
|
173 |
|
PF_CallbackCmd<T> FREE; |
|
174 |
|
PF_CallbackCmd<T> GET_COMPRESSION_FLAGS; |
|
175 |
|
PF_CallbackCmd<T> BEGIN_WRITE_CLONING; |
|
176 |
|
}; |
|
177 |
|
|
|
178 |
|
|
|
179 |
|
template<typename T> |
|
180 |
|
[[nodiscard]] ZipResult create(PF_Callback<T> pf_callback, void *p_userdata) |
|
181 |
|
{ |
|
182 |
|
zip_error_t es; |
|
183 |
|
p = zip_source_function_create(reinterpret_cast<zip_source_callback>(pf_callback), p_userdata, &es); |
|
184 |
|
return zip_result_int(es.zip_err); |
|
185 |
|
} |
|
186 |
|
|
|
187 |
|
template<typename T> |
|
188 |
|
struct CmdData |
|
189 |
|
{ |
|
190 |
|
CallbacksCmd<T> pf_cmds; |
|
191 |
|
T *p_userdata; |
|
192 |
|
}; |
|
193 |
|
|
|
194 |
|
static int64_t cmd_choose(CmdData<void> *p_userdata, void *p_data, uint64_t length, Cmd cmd) |
|
195 |
|
{ |
|
196 |
|
auto *p_ud = reinterpret_cast<CmdData<void>*>(p_userdata); |
|
197 |
|
switch(cmd) |
|
198 |
|
{ |
|
199 |
|
#define ARGS p_ud->p_userdata, p_data, length |
|
200 |
|
#define ARGS1 p_ud->p_userdata |
|
201 |
|
#define ARGS2(x) p_ud->p_userdata, reinterpret_cast<x*>(p_data) |
|
202 |
|
#define C(x, args) case Cmd::x : if (p_ud->pf_cmds.x != nullptr) \ |
|
203 |
|
return p_ud->pf_cmds.x(args); \ |
|
204 |
|
else return -1; |
|
205 |
|
|
|
206 |
|
C(OPEN, ARGS1) |
|
207 |
|
C(READ, ARGS) |
|
208 |
|
C(CLOSE, ARGS) |
|
209 |
|
C(STAT, ARGS2(ZipStat)) |
|
210 |
|
C(ERROR, ARGS2(ZipError)) |
|
211 |
|
C(FREE, ARGS) |
|
212 |
|
C(SEEK, ARGS) |
|
213 |
|
C(TELL, ARGS) |
|
214 |
|
C(BEGIN_WRITE, ARGS) |
|
215 |
|
C(COMMIT_WRITE, ARGS) |
|
216 |
|
C(ROLLBACK_WRITE, ARGS) |
|
217 |
|
C(WRITE, ARGS) |
|
218 |
|
C(SEEK_WRITE, ARGS) |
|
219 |
|
C(TELL_WRITE, ARGS) |
|
220 |
|
|
|
|
149 |
|
enum Cmd { |
|
150 |
|
OPEN, /* prepare for reading */ |
|
151 |
|
READ, /* read data */ |
|
152 |
|
CLOSE, /* reading is done */ |
|
153 |
|
STAT, /* get meta information */ |
|
154 |
|
ERROR, /* get error information */ |
|
155 |
|
FREE, /* cleanup and free resources */ |
|
156 |
|
SEEK, /* set position for reading */ |
|
157 |
|
TELL, /* get read position */ |
|
158 |
|
BEGIN_WRITE, /* prepare for writing */ |
|
159 |
|
COMMIT_WRITE, /* writing is done */ |
|
160 |
|
ROLLBACK_WRITE, /* discard written changes */ |
|
161 |
|
WRITE, /* write data */ |
|
162 |
|
SEEK_WRITE, /* set position for writing */ |
|
163 |
|
TELL_WRITE, /* get write position */ |
|
164 |
|
SUPPORTS, /* check whether source supports command */ |
|
165 |
|
REMOVE, /* remove file */ |
|
166 |
|
GET_COMPRESSION_FLAGS, /* get compression flags, internal only */ |
|
167 |
|
BEGIN_WRITE_CLONING, /* like BEGIN_WRITE, but keep part of original file */ |
|
168 |
|
COUNT // cmd count |
|
169 |
|
}; |
|
170 |
|
template<typename T> |
|
171 |
|
using PF_Callback = int64_t(*)(T*p_userdata,void*p_data,uint64_t length, Cmd); |
|
172 |
|
template<typename T> |
|
173 |
|
using PF_CallbackCmd = int64_t(*)(T*p_userdata,void*p_data,uint64_t length); |
|
174 |
|
|
|
175 |
|
template<typename T> |
|
176 |
|
using PF_CallbackCmdOpen = int64_t(*)(T*p_userdata); |
|
177 |
|
template<typename T> |
|
178 |
|
using PF_CallbackCmdStat = int64_t(*)(T*p_userdata,ZipStat*p_data); |
|
179 |
|
template<typename T> |
|
180 |
|
using PF_CallbackCmdError = int64_t(*)(T*p_userdata,ZipError*p_data); |
|
181 |
|
|
|
182 |
|
template<typename T> |
|
183 |
|
struct CallbacksCmd { |
|
184 |
|
//read from source |
|
185 |
|
PF_CallbackCmdOpen<T> OPEN; |
|
186 |
|
PF_CallbackCmd<T> READ; |
|
187 |
|
PF_CallbackCmd<T> CLOSE; |
|
188 |
|
PF_CallbackCmdStat<T> STAT; |
|
189 |
|
PF_CallbackCmdError<T> ERROR; |
|
190 |
|
//read from source with seeking |
|
191 |
|
PF_CallbackCmd<T> SEEK; |
|
192 |
|
PF_CallbackCmd<T> TELL; |
|
193 |
|
//write |
|
194 |
|
PF_CallbackCmd<T> BEGIN_WRITE; |
|
195 |
|
PF_CallbackCmd<T> COMMIT_WRITE; |
|
196 |
|
PF_CallbackCmd<T> ROLLBACK_WRITE; |
|
197 |
|
PF_CallbackCmd<T> SEEK_WRITE; |
|
198 |
|
PF_CallbackCmd<T> TELL_WRITE; |
|
199 |
|
PF_CallbackCmd<T> REMOVE; |
|
200 |
|
//unknown |
|
201 |
|
PF_CallbackCmd<T> WRITE; |
|
202 |
|
PF_CallbackCmd<T> FREE; |
|
203 |
|
PF_CallbackCmd<T> GET_COMPRESSION_FLAGS; |
|
204 |
|
PF_CallbackCmd<T> BEGIN_WRITE_CLONING; |
|
205 |
|
}; |
|
206 |
|
template<typename T> [[nodiscard]] |
|
207 |
|
ZipResult create(PF_Callback<T> pf_callback, void *p_userdata) { |
|
208 |
|
zip_error_t es; |
|
209 |
|
auto callback = reinterpret_cast<zip_source_callback>(pf_callback); |
|
210 |
|
p = zip_source_function_create(callback, p_userdata, &es); |
|
211 |
|
return zip_result_int(es.zip_err); |
|
212 |
|
} |
|
213 |
|
template<typename T> |
|
214 |
|
struct CmdData { |
|
215 |
|
CallbacksCmd<T> pf_cmds; |
|
216 |
|
T *p_userdata; |
|
217 |
|
}; |
|
218 |
|
|
|
219 |
|
#define ARGS \ |
|
220 |
|
p_ud->p_userdata, p_data, length |
|
221 |
|
#define ARGS1 \ |
|
222 |
|
p_ud->p_userdata |
|
223 |
|
#define ARGS2(x) \ |
|
224 |
|
p_ud->p_userdata, reinterpret_cast<x*>(p_data) |
|
225 |
|
#define C(x, args) \ |
|
226 |
|
case Cmd::x : \ |
|
227 |
|
if (p_ud->pf_cmds.x != nullptr) \ |
|
228 |
|
return p_ud->pf_cmds.x(args); \ |
|
229 |
|
else return -1; |
221 |
230 |
#define B(x) zip_source_cmd_t(p_ud->pf_cmds.x == nullptr ? x : x) |
#define B(x) zip_source_cmd_t(p_ud->pf_cmds.x == nullptr ? x : x) |
222 |
|
case Cmd::SUPPORTS: {auto val = zip_source_make_command_bitmap(B(OPEN),B(READ),B(CLOSE),B(STAT),B(ERROR), |
|
223 |
|
B(FREE),B(SEEK),B(TELL),B(BEGIN_WRITE), |
|
224 |
|
B(COMMIT_WRITE),B(ROLLBACK_WRITE),B(WRITE), |
|
225 |
|
B(SEEK_WRITE),B(TELL_WRITE),B(REMOVE), |
|
226 |
|
B(GET_COMPRESSION_FLAGS),B(BEGIN_WRITE_CLONING), |
|
227 |
|
SUPPORTS); |
|
228 |
|
return val;} |
|
229 |
|
#undef B |
|
230 |
231 |
|
|
231 |
|
C(REMOVE, ARGS) |
|
232 |
|
C(GET_COMPRESSION_FLAGS, ARGS) |
|
233 |
|
C(BEGIN_WRITE_CLONING, ARGS) |
|
234 |
|
default: return -1; |
|
|
232 |
|
static int64_t |
|
233 |
|
cmd_choose(CmdData<void> *p_userdata, void *p_data, uint64_t length, Cmd cmd){ |
|
234 |
|
auto *p_ud = reinterpret_cast<CmdData<void>*>(p_userdata); |
|
235 |
|
switch(cmd) { |
|
236 |
|
C(OPEN, ARGS1) |
|
237 |
|
C(READ, ARGS) |
|
238 |
|
C(CLOSE, ARGS) |
|
239 |
|
C(STAT, ARGS2(ZipStat)) |
|
240 |
|
C(ERROR, ARGS2(ZipError)) |
|
241 |
|
C(FREE, ARGS) |
|
242 |
|
C(SEEK, ARGS) |
|
243 |
|
C(TELL, ARGS) |
|
244 |
|
C(BEGIN_WRITE, ARGS) |
|
245 |
|
C(COMMIT_WRITE, ARGS) |
|
246 |
|
C(ROLLBACK_WRITE, ARGS) |
|
247 |
|
C(WRITE, ARGS) |
|
248 |
|
C(SEEK_WRITE, ARGS) |
|
249 |
|
C(TELL_WRITE, ARGS) |
|
250 |
|
case Cmd::SUPPORTS: { |
|
251 |
|
auto val = zip_source_make_command_bitmap( |
|
252 |
|
B(OPEN),B(READ),B(CLOSE),B(STAT),B(ERROR),B(FREE),B(SEEK),B(TELL), |
|
253 |
|
B(BEGIN_WRITE),B(COMMIT_WRITE),B(ROLLBACK_WRITE),B(WRITE), |
|
254 |
|
B(SEEK_WRITE),B(TELL_WRITE),B(REMOVE),B(GET_COMPRESSION_FLAGS), |
|
255 |
|
B(BEGIN_WRITE_CLONING),SUPPORTS); |
|
256 |
|
return val; |
|
257 |
|
} |
|
258 |
|
C(REMOVE, ARGS) |
|
259 |
|
C(GET_COMPRESSION_FLAGS, ARGS) |
|
260 |
|
C(BEGIN_WRITE_CLONING, ARGS) |
|
261 |
|
default: return -1; |
|
262 |
|
#undef B |
235 |
263 |
#undef C |
#undef C |
236 |
264 |
#undef ARGS |
#undef ARGS |
237 |
265 |
#undef ARGS1 |
#undef ARGS1 |
238 |
266 |
#undef ARGS2 |
#undef ARGS2 |
239 |
|
} |
|
240 |
|
} |
|
241 |
|
|
|
242 |
|
|
|
243 |
|
template<typename T> |
|
244 |
|
[[nodiscard]] ZipResult create(CmdData<T> *p_data) |
|
245 |
|
{ |
|
246 |
|
zip_error_t es; |
|
247 |
|
p = zip_source_function_create(reinterpret_cast<zip_source_callback>(cmd_choose), p_data, &es); |
|
248 |
|
return p != nullptr ? ZipResult::SUCCESS : zip_result_int(es.zip_err); |
|
249 |
|
} |
|
250 |
|
|
|
251 |
|
zip_source_t *p; |
|
|
267 |
|
} |
|
268 |
|
} |
|
269 |
|
template<typename T> [[nodiscard]] |
|
270 |
|
ZipResult create(CmdData<T> *p_data) { |
|
271 |
|
zip_error_t es; |
|
272 |
|
p = zip_source_function_create(reinterpret_cast<zip_source_callback>(cmd_choose), p_data, &es); |
|
273 |
|
return p != nullptr ? ZipResult::SUCCESS : zip_result_int(es.zip_err); |
|
274 |
|
} |
|
275 |
|
zip_source_t *p; |
252 |
276 |
}; |
}; |
253 |
|
|
|
254 |
|
struct ZipArchive |
|
255 |
|
{ |
|
256 |
|
struct OpenFlag |
|
257 |
|
{ |
|
258 |
|
enum { |
|
259 |
|
CHECK_FILE = ZIP_CHECKCONS, |
|
260 |
|
CREATE_IF_FILE_MISSING = ZIP_CREATE, |
|
261 |
|
ERROR_IF_FILE_EXIST = ZIP_EXCL, |
|
262 |
|
CLEAR_IF_FILE_EXIST = ZIP_TRUNCATE, |
|
263 |
|
READ_ONLY = ZIP_RDONLY |
|
264 |
|
}; |
|
265 |
|
}; |
|
266 |
|
using OpenMask = int; |
|
267 |
|
|
|
268 |
|
enum Encoding { |
|
269 |
|
GUESS = ZIP_FL_ENC_GUESS, |
|
270 |
|
UTF8 = ZIP_FL_ENC_UTF_8, |
|
271 |
|
CP433 = ZIP_FL_ENC_CP437, |
|
272 |
|
}; |
|
273 |
|
|
|
274 |
|
[[nodiscard]] ZipResult open(const char *path, OpenMask flags) |
|
275 |
|
{ |
|
276 |
|
ZipResult res; |
|
277 |
|
p = zip_open(path, flags, zip_result_ptr(&res)); |
|
278 |
|
|
|
279 |
|
if (p != nullptr) |
|
280 |
|
res = ZipResult::SUCCESS, p_error_info = zip_get_error(p); |
|
281 |
|
|
|
282 |
|
return res; |
|
283 |
|
} |
|
284 |
|
|
|
285 |
|
[[nodiscard]] ZipResult open(const char *path) |
|
286 |
|
{ |
|
287 |
|
return open(path, 0); |
|
288 |
|
} |
|
289 |
|
|
|
290 |
|
[[nodiscard]] ZipResult create(const char *path) |
|
291 |
|
{ |
|
292 |
|
return open(path, OpenFlag::CREATE_IF_FILE_MISSING | OpenFlag::ERROR_IF_FILE_EXIST); |
|
293 |
|
} |
|
294 |
|
|
|
295 |
|
[[nodiscard]] ZipResult rewrite(const char *path) |
|
296 |
|
{ |
|
297 |
|
return open(path, OpenFlag::CREATE_IF_FILE_MISSING | OpenFlag::CLEAR_IF_FILE_EXIST); |
|
298 |
|
} |
|
299 |
|
|
|
300 |
|
[[nodiscard]] ZipResult close() |
|
301 |
|
{ |
|
302 |
|
return zip_result_int(zip_close(p)); |
|
303 |
|
} |
|
304 |
|
|
|
305 |
|
[[nodiscard]] ZipResult create_directory(Encoding encoding, const char* name, ZipIndex *p_index_dst) |
|
306 |
|
{ |
|
307 |
|
*p_index_dst = zip_dir_add(p, name, encoding); |
|
308 |
|
return *p_index_dst == -1 ? zip_result_int(p_error_info->zip_err) : ZipResult::SUCCESS; |
|
309 |
|
} |
|
310 |
|
|
|
311 |
|
[[nodiscard]] ZipResult create_file(const char *name, ZipSource src, Encoding encoding, bool rewrite, |
|
312 |
|
ZipIndex *p_index_dst) |
|
313 |
|
{ |
|
314 |
|
*p_index_dst = zip_file_add(p, name, src.p, encoding | (rewrite ? ZIP_FL_OVERWRITE : 0)); |
|
315 |
|
return *p_index_dst == -1 ? zip_result_int(p_error_info->zip_err) : ZipResult::SUCCESS; |
|
316 |
|
} |
|
317 |
|
|
|
318 |
|
[[nodiscard]] ZipResult file_stat(const char* name, ZipStat *p_stat) |
|
319 |
|
{ |
|
320 |
|
if (zip_stat(p, name, 0, &p_stat->stat) == 0) |
|
321 |
|
return ZipResult::SUCCESS; |
|
322 |
|
return zip_result_int(p_error_info->zip_err); |
|
323 |
|
} |
|
324 |
|
|
|
325 |
|
zip_t *p; |
|
326 |
|
zip_error_t *p_error_info; |
|
|
277 |
|
struct ZipArchive { |
|
278 |
|
struct OpenFlag { |
|
279 |
|
enum { |
|
280 |
|
CHECK_FILE = ZIP_CHECKCONS, |
|
281 |
|
CREATE_IF_FILE_MISSING = ZIP_CREATE, |
|
282 |
|
ERROR_IF_FILE_EXIST = ZIP_EXCL, |
|
283 |
|
CLEAR_IF_FILE_EXIST = ZIP_TRUNCATE, |
|
284 |
|
READ_ONLY = ZIP_RDONLY |
|
285 |
|
}; |
|
286 |
|
}; |
|
287 |
|
using OpenMask = int; |
|
288 |
|
|
|
289 |
|
enum Encoding { |
|
290 |
|
GUESS = ZIP_FL_ENC_GUESS, |
|
291 |
|
UTF8 = ZIP_FL_ENC_UTF_8, |
|
292 |
|
CP433 = ZIP_FL_ENC_CP437, |
|
293 |
|
}; |
|
294 |
|
[[nodiscard]] ZipResult open(const char *path, OpenMask flags) { |
|
295 |
|
ZipResult res; |
|
296 |
|
p = zip_open(path, flags, zip_result_ptr(&res)); |
|
297 |
|
if (p != nullptr) |
|
298 |
|
res = ZipResult::SUCCESS, p_error_info = zip_get_error(p); |
|
299 |
|
return res; |
|
300 |
|
} |
|
301 |
|
[[nodiscard]] ZipResult open(const char *path) { |
|
302 |
|
return open(path, 0); |
|
303 |
|
} |
|
304 |
|
[[nodiscard]] ZipResult create(const char *path) { |
|
305 |
|
auto f = OpenFlag::CREATE_IF_FILE_MISSING | OpenFlag::ERROR_IF_FILE_EXIST; |
|
306 |
|
return open(path, f); |
|
307 |
|
} |
|
308 |
|
[[nodiscard]] ZipResult rewrite(const char *path) { |
|
309 |
|
auto f = OpenFlag::CREATE_IF_FILE_MISSING | OpenFlag::CLEAR_IF_FILE_EXIST; |
|
310 |
|
return open(path, f); |
|
311 |
|
} |
|
312 |
|
[[nodiscard]] ZipResult close() { |
|
313 |
|
return zip_result_int(zip_close(p)); |
|
314 |
|
} |
|
315 |
|
[[nodiscard]] ZipResult |
|
316 |
|
create_directory(Encoding encoding, const char* name, ZipIndex *p_index_dst) { |
|
317 |
|
*p_index_dst = zip_dir_add(p, name, encoding); |
|
318 |
|
return *p_index_dst == -1 ? zip_result_int(p_error_info->zip_err) : ZipResult::SUCCESS; |
|
319 |
|
} |
|
320 |
|
[[nodiscard]] ZipResult |
|
321 |
|
create_file(const char *name, ZipSource src, Encoding encoding, bool rewrite, |
|
322 |
|
ZipIndex *p_index_dst) { |
|
323 |
|
auto f = encoding | (rewrite ? ZIP_FL_OVERWRITE : 0); |
|
324 |
|
*p_index_dst = zip_file_add(p, name, src.p, f); |
|
325 |
|
if (*p_index_dst == -1) |
|
326 |
|
return zip_result_int(p_error_info->zip_err); |
|
327 |
|
else |
|
328 |
|
return ZipResult::SUCCESS; |
|
329 |
|
} |
|
330 |
|
[[nodiscard]] ZipResult file_stat(const char* name, ZipStat *p_stat) { |
|
331 |
|
if (zip_stat(p, name, 0, &p_stat->stat) == 0) |
|
332 |
|
return ZipResult::SUCCESS; |
|
333 |
|
return zip_result_int(p_error_info->zip_err); |
|
334 |
|
} |
|
335 |
|
zip_t *p; |
|
336 |
|
zip_error_t *p_error_info; |
327 |
337 |
}; |
}; |
328 |
|
|
|
329 |
|
struct ZipSubFile |
|
330 |
|
{ |
|
331 |
|
struct OpenFlag |
|
332 |
|
{ |
|
333 |
|
enum { |
|
334 |
|
READ_COMPRESSED = ZIP_FL_COMPRESSED, |
|
335 |
|
// Read the original data from the zip archive, ignoring any changes made to the file. |
|
336 |
|
READ_UNCHANGED_FLAG = ZIP_FL_UNCHANGED |
|
337 |
|
}; |
|
338 |
|
}; |
|
339 |
|
using OpenMask = int; |
|
340 |
|
|
|
341 |
|
[[nodiscard]] ZipResult open(ZipArchive *p_za, const char *name) |
|
342 |
|
{ |
|
343 |
|
p = zip_fopen(p_za->p, name, 0); |
|
344 |
|
return p == nullptr ? zip_result_int(p_za->p_error_info->zip_err) : ZipResult::SUCCESS; |
|
345 |
|
} |
|
346 |
|
[[nodiscard]] ZipResult open(ZipArchive *p_za, uint64_t file_index) |
|
347 |
|
{ |
|
348 |
|
p = zip_fopen_index(p_za->p, file_index, 0); |
|
349 |
|
return p == nullptr ? zip_result_int(p_za->p_error_info->zip_err) : ZipResult::SUCCESS; |
|
350 |
|
} |
|
351 |
|
[[nodiscard]] ZipResult close() |
|
352 |
|
{ |
|
353 |
|
return zip_result_int(zip_fclose(p)); |
|
354 |
|
} |
|
355 |
|
|
|
356 |
|
[[nodiscard]] bool read(void *p_dst, uint64_t byte_count) |
|
357 |
|
{ |
|
358 |
|
return zip_fread(p, p_dst, byte_count) != -1; |
|
359 |
|
} |
|
360 |
|
|
|
361 |
|
[[nodiscard]] static inline ZipResult read_whole_file(ZipArchive *p_za, const char *p_name, |
|
362 |
|
char **pp_dst, uint64_t *p_fsize) |
|
363 |
|
{ |
|
364 |
|
ZipStat stat; |
|
365 |
|
auto res = p_za->file_stat(p_name, &stat); |
|
366 |
|
if (res != ZipResult::SUCCESS) |
|
367 |
|
return res; |
|
368 |
|
|
|
369 |
|
auto f_i = stat.index(); |
|
370 |
|
*p_fsize = stat.size(); |
|
371 |
|
|
|
372 |
|
|
|
373 |
|
ZipSubFile zfile; |
|
374 |
|
res = zfile.open(p_za, f_i); |
|
375 |
|
if (res != ZipResult::SUCCESS) |
|
376 |
|
return res; |
|
377 |
|
|
|
378 |
|
|
|
379 |
|
*pp_dst = reinterpret_cast<char*>(malloc(*p_fsize)); |
|
380 |
|
bool readed = zfile.read(*pp_dst, *p_fsize); |
|
381 |
|
|
|
382 |
|
(void)zfile.close(); |
|
383 |
|
if (not readed) |
|
384 |
|
{ |
|
385 |
|
jl::deallocate(pp_dst); |
|
386 |
|
return ZipResult::READ_ERROR; |
|
387 |
|
} |
|
388 |
|
return ZipResult::SUCCESS; |
|
389 |
|
} |
|
390 |
|
|
|
391 |
|
zip_file_t *p; |
|
|
338 |
|
struct ZipSubFile { |
|
339 |
|
struct OpenFlag { |
|
340 |
|
enum { |
|
341 |
|
READ_COMPRESSED = ZIP_FL_COMPRESSED, |
|
342 |
|
// Read the original data from the zip archive, ignoring any changes made to the file. |
|
343 |
|
READ_UNCHANGED_FLAG = ZIP_FL_UNCHANGED |
|
344 |
|
}; |
|
345 |
|
}; |
|
346 |
|
using OpenMask = int; |
|
347 |
|
|
|
348 |
|
[[nodiscard]] ZipResult open(ZipArchive *p_za, const char *name) { |
|
349 |
|
p = zip_fopen(p_za->p, name, 0); |
|
350 |
|
if (p == nullptr) |
|
351 |
|
return zip_result_int(p_za->p_error_info->zip_err); |
|
352 |
|
else |
|
353 |
|
return ZipResult::SUCCESS; |
|
354 |
|
} |
|
355 |
|
[[nodiscard]] ZipResult open(ZipArchive *p_za, uint64_t file_index) { |
|
356 |
|
p = zip_fopen_index(p_za->p, file_index, 0); |
|
357 |
|
if (p == nullptr) |
|
358 |
|
return zip_result_int(p_za->p_error_info->zip_err); |
|
359 |
|
else |
|
360 |
|
return ZipResult::SUCCESS; |
|
361 |
|
} |
|
362 |
|
[[nodiscard]] ZipResult close() { |
|
363 |
|
return zip_result_int(zip_fclose(p)); |
|
364 |
|
} |
|
365 |
|
[[nodiscard]] bool read(void *p_dst, uint64_t byte_count) { |
|
366 |
|
return zip_fread(p, p_dst, byte_count) != -1; |
|
367 |
|
} |
|
368 |
|
[[nodiscard]] static ZipResult |
|
369 |
|
read_whole_file(ZipArchive *p_za, const char *p_name, char **pp_dst, |
|
370 |
|
uint64_t *p_fsize) { |
|
371 |
|
ZipStat stat; |
|
372 |
|
auto res = p_za->file_stat(p_name, &stat); |
|
373 |
|
if (res != ZipResult::SUCCESS) |
|
374 |
|
return res; |
|
375 |
|
auto f_i = stat.index(); |
|
376 |
|
*p_fsize = stat.size(); |
|
377 |
|
ZipSubFile zfile; |
|
378 |
|
res = zfile.open(p_za, f_i); |
|
379 |
|
if (res != ZipResult::SUCCESS) |
|
380 |
|
return res; |
|
381 |
|
*pp_dst = reinterpret_cast<char*>(malloc(*p_fsize)); |
|
382 |
|
bool readed = zfile.read(*pp_dst, *p_fsize); |
|
383 |
|
(void)zfile.close(); |
|
384 |
|
if (not readed) { |
|
385 |
|
jl::deallocate(pp_dst); |
|
386 |
|
return ZipResult::READ_ERROR; |
|
387 |
|
} |
|
388 |
|
return ZipResult::SUCCESS; |
|
389 |
|
} |
|
390 |
|
zip_file_t *p; |
392 |
391 |
}; |
}; |
393 |
|
|
|