Skip to content

Commit 0c62a3d

Browse files
committed
distinct text id for keybinds; recursive tests for cage archive
1 parent 50f9599 commit 0c62a3d

File tree

6 files changed

+94
-58
lines changed

6 files changed

+94
-58
lines changed

sources/include/cage-engine/keybinds.h

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ namespace cage
6464
struct CAGE_ENGINE_API KeybindCreateConfig
6565
{
6666
String id;
67+
String guiTextParameter;
68+
uint32 guiTextId = 0;
6769
sint32 eventOrder = 0;
6870
sint32 displayOrder = 0;
6971
ModifiersFlags requiredFlags = ModifiersFlags::None;

sources/libcore/filesystem/archiveCarch.cpp

+42-24
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ namespace cage
7575
{
7676
CAGE_ASSERT(src->mode().read && !src->mode().write && !src->mode().append && !src->mode().textual);
7777

78+
const uint64 srcSize = src->size();
7879
{ // read header
79-
if (src->size() < sizeof(ArchiveHeader))
80+
if (srcSize < sizeof(ArchiveHeader))
8081
return; // isCarch = false
8182
src->seek(0);
8283
src->read(bufferView<char>(arch));
@@ -87,20 +88,20 @@ namespace cage
8788
isCarch = true;
8889
}
8990

90-
{ // validate content size
91-
if (src->size() < arch.contentStart + arch.contentSize)
91+
{ // validate sizes
92+
if (srcSize < arch.contentStart + arch.contentSize)
9293
{
9394
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
9495
CAGE_THROW_ERROR(Exception, "truncated cage archive (content)");
9596
}
96-
}
97-
98-
{ // read files list
99-
if (src->size() < arch.listStart + arch.listSize)
97+
if (srcSize < arch.listStart + arch.listSize)
10098
{
10199
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
102100
CAGE_THROW_ERROR(Exception, "truncated cage archive (list)");
103101
}
102+
}
103+
104+
{ // read files list
104105
src->seek(arch.listStart);
105106
const auto buff = src->read(arch.listSize);
106107
Deserializer des(buff);
@@ -131,6 +132,20 @@ namespace cage
131132
ArchiveCarch(ArchiveCarch &&z) = default;
132133

133134
~ArchiveCarch()
135+
{
136+
try
137+
{
138+
writeChanges();
139+
}
140+
catch (...)
141+
{
142+
CAGE_LOG_THROW(Stringizer() + "error while writing changes to cage archive");
143+
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
144+
throw;
145+
}
146+
}
147+
148+
void writeChanges()
134149
{
135150
if (!src)
136151
return; // already moved-from
@@ -207,18 +222,8 @@ namespace cage
207222
src->write(it.second.newContent);
208223
}
209224

210-
{ // fill the rest of the file with zeros
211-
static constexpr uint64 sz = 16 * 1024;
212-
static constexpr char zeros[sz] = {};
213-
uint64 r = src->size() - src->tell();
214-
while (r > sz)
215-
{
216-
src->write(zeros);
217-
r -= sz;
218-
}
219-
if (r > 0)
220-
src->write({ zeros, zeros + sz });
221-
}
225+
// fill the rest of the file with zeros
226+
writeZeroes(+src, src->size() - src->tell());
222227

223228
// ensure we wrote to the very end of the file
224229
CAGE_ASSERT(src->tell() == src->size());
@@ -271,7 +276,7 @@ namespace cage
271276
{
272277
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
273278
CAGE_LOG_THROW(Stringizer() + "name: " + path);
274-
CAGE_THROW_ERROR(Exception, "cannot create directory inside carch, file already exists");
279+
CAGE_THROW_ERROR(Exception, "cannot create directory inside cage archive, file already exists");
275280
}
276281
if (dirs.count(path))
277282
return; // directory already exists
@@ -318,7 +323,7 @@ namespace cage
318323
{
319324
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
320325
CAGE_LOG_THROW(Stringizer() + "name: " + from);
321-
CAGE_THROW_ERROR(Exception, "source does not exist");
326+
CAGE_THROW_ERROR(Exception, "source file does not exist");
322327
}
323328
if (!copying)
324329
remove(from);
@@ -351,7 +356,7 @@ namespace cage
351356
{
352357
CAGE_ASSERT(!path.empty());
353358
CAGE_ASSERT(isPathValid(path));
354-
CAGE_THROW_CRITICAL(Exception, "reading last modification time of a file inside carch archive is not supported");
359+
CAGE_THROW_CRITICAL(Exception, "reading last modification time of a file inside cage archive is not supported");
355360
}
356361

357362
Holder<File> openFile(const String &path, const FileMode &mode) override;
@@ -378,13 +383,13 @@ namespace cage
378383
if (mode.write)
379384
a->reopenForModification();
380385
if (a->dirs.count(name))
381-
CAGE_THROW_ERROR(Exception, "cannot open file in carch archive, the path is a directory");
386+
CAGE_THROW_ERROR(Exception, "cannot open file in cage archive, the path is a directory");
382387
if (a->files.count(name))
383388
a->throwIfFileLocked(name);
384389
else
385390
{
386391
if (mode.read)
387-
CAGE_THROW_ERROR(Exception, "cannot open file in carch archive, it does not exist");
392+
CAGE_THROW_ERROR(Exception, "cannot open file in cage archive, it does not exist");
388393
a->createDirectoriesNoLock(pathJoin(name, ".."));
389394
}
390395

@@ -575,4 +580,17 @@ namespace cage
575580
ArchiveCarch z(std::move(f));
576581
return z.isCarch ? std::make_shared<ArchiveCarch>(std::move(z)) : std::shared_ptr<ArchiveAbstract>();
577582
}
583+
584+
void writeZeroes(File *f, uint64 size)
585+
{
586+
static constexpr uint64 sz = 16 * 1024;
587+
static constexpr char zeros[sz] = {};
588+
while (size > sz)
589+
{
590+
f->write(zeros);
591+
size -= sz;
592+
}
593+
if (size > 0)
594+
f->write({ zeros, zeros + sz });
595+
}
578596
}

sources/libcore/filesystem/archiveZip.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,20 @@ namespace cage
272272
ArchiveZip(ArchiveZip &&z) = default;
273273

274274
~ArchiveZip()
275+
{
276+
try
277+
{
278+
writeChanges();
279+
}
280+
catch (...)
281+
{
282+
CAGE_LOG_THROW(Stringizer() + "error while writing changes to zip archive");
283+
CAGE_LOG_THROW(Stringizer() + "archive path: " + myPath);
284+
throw;
285+
}
286+
}
287+
288+
void writeChanges()
275289
{
276290
if (!src)
277291
return; // already moved-from
@@ -291,12 +305,7 @@ namespace cage
291305
expectedToWrite += numeric_cast<uint32>(sizeof(CDFileHeader) + f.nameLength + f.newContent.size());
292306
const uint32 needToWrite = originalEOCDPosition - originalCDFilesPosition;
293307
if (needToWrite > expectedToWrite)
294-
{
295-
MemoryBuffer buff;
296-
buff.resize(needToWrite - expectedToWrite);
297-
detail::memset(buff.data(), 0, buff.size());
298-
src->write(buff);
299-
}
308+
writeZeroes(+src, needToWrite - expectedToWrite);
300309
}
301310

302311
// write modified files and update offsets

sources/libcore/filesystem/files.h

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ namespace cage
5656
RecursiveMutex *fsMutex();
5757

5858
Holder<File> newProxyFile(File *f, uintPtr start, uintPtr size);
59+
60+
void writeZeroes(File *f, uint64 size);
5961
}
6062

6163
#endif // guard_files_h_sdrgds45rfgt

sources/libengine/keybinds.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ namespace cage
259259
return maker.result;
260260
}
261261

262-
const KeybindCreateConfig &validateConfig(const KeybindCreateConfig &config)
262+
KeybindCreateConfig validateConfig(KeybindCreateConfig config)
263263
{
264264
CAGE_ASSERT(!config.id.empty());
265265
CAGE_ASSERT(!findKeybind(config.id)); // must be unique
@@ -268,6 +268,10 @@ namespace cage
268268
CAGE_ASSERT(none(config.devices & KeybindDevicesFlags::WheelRoll) || none(config.devices & KeybindDevicesFlags::WheelScroll)); // these two flags are mutually exclusive
269269
CAGE_ASSERT(none(config.devices & KeybindDevicesFlags::Modifiers) || config.devices == KeybindDevicesFlags::Modifiers); // modifiers is exclusive with all other flags
270270
CAGE_ASSERT(any(config.modes));
271+
if (config.guiTextId == 0)
272+
config.guiTextId = HashString(config.id);
273+
if (config.guiTextParameter.empty())
274+
config.guiTextParameter = config.id;
271275
return config;
272276
}
273277

@@ -291,7 +295,7 @@ namespace cage
291295
class KeybindImpl : public Keybind
292296
{
293297
public:
294-
KeybindImpl(const KeybindCreateConfig &config_, PointerRange<const GenericInput> defaults_, Delegate<bool(const GenericInput &)> event_) : config(validateConfig(config_)), defaults(makeDefaults(config_, defaults_)), textId(HashString(config.id))
298+
KeybindImpl(const KeybindCreateConfig &config_, PointerRange<const GenericInput> defaults_, Delegate<bool(const GenericInput &)> event_) : config(validateConfig(config_)), defaults(makeDefaults(config, defaults_))
295299
{
296300
reset(); // make matchers from the defaults
297301
this->event = event_;
@@ -360,7 +364,6 @@ namespace cage
360364
EventListener<bool(const GenericInput &)> listener;
361365
const std::vector<Matcher> defaults;
362366
std::vector<Matcher> matchers;
363-
const uint32 textId = 0;
364367
bool active = false; // allows tick events
365368
Entity *guiEnt = nullptr;
366369
uint32 assigningIndex = m;
@@ -467,7 +470,9 @@ namespace cage
467470
return true;
468471
}
469472

470-
CAGE_FORCE_INLINE auto cmp() const { return std::tuple<sint32, String, String>(config.displayOrder, textsGet(textId), config.id); }
473+
String name() const { return textsGet(config.guiTextId, config.guiTextParameter); }
474+
475+
CAGE_FORCE_INLINE auto cmp() const { return std::tuple<sint32, String, String>(config.displayOrder, name(), config.id); }
471476
};
472477

473478
bool guiUpdateGlobal(uintPtr ptr, const GenericInput &in)
@@ -488,7 +493,7 @@ namespace cage
488493
String Keybind::name() const
489494
{
490495
const KeybindImpl *impl = (const KeybindImpl *)this;
491-
return textsGet(impl->textId, impl->config.id);
496+
return impl->name();
492497
}
493498

494499
String Keybind::value() const
@@ -636,7 +641,7 @@ namespace cage
636641
auto _ = g->verticalTable(2);
637642
for (KeybindImpl *k : tmp)
638643
{
639-
g->label().update([k](Entity *e) { e->value<GuiTextFormatComponent>().color = k->active ? Vec3(0.5, 0.9, 1) : Vec3::Nan(); }).text(k->textId, k->config.id);
644+
g->label().update([k](Entity *e) { e->value<GuiTextFormatComponent>().color = k->active ? Vec3(0.5, 0.9, 1) : Vec3::Nan(); }).text(k->config.guiTextId, k->config.guiTextParameter);
640645
keybindsGuiWidget(g, k);
641646
}
642647
}

sources/test-core/archivesRecursion.cpp

+22-22
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ namespace
3131

3232
void threadEntry(uint32 thrId, uint32)
3333
{
34-
pathCreateArchiveZip(Stringizer() + "testdir/concurrent.zip/" + thrId + ".zip");
34+
pathCreateArchiveCarch(Stringizer() + "testdir/concurrent.carch/" + thrId + ".carch");
3535
for (uint32 iter = 0; iter < 10; iter++)
3636
{
3737
{
3838
ScopeLock lck(barrier);
3939
}
40-
const String name = Mode == 0 ? Stringizer() + "testdir/concurrent.zip/" + ((iter + thrId) % ThreadsCount) + ".zip/" + randomRange(0, 3) + ".bin" : Stringizer() + "testdir/concurrent.zip/" + randomRange(0, 3) + ".zip/" + ((iter + thrId) % ThreadsCount) + ".bin";
40+
const String name = Mode == 0 ? Stringizer() + "testdir/concurrent.carch/" + ((iter + thrId) % ThreadsCount) + ".carch/" + randomRange(0, 3) + ".bin" : Stringizer() + "testdir/concurrent.carch/" + randomRange(0, 3) + ".carch/" + ((iter + thrId) % ThreadsCount) + ".bin";
4141
const PathTypeFlags pf = pathType(name);
4242
if (any(pf & PathTypeFlags::File))
4343
{
@@ -61,8 +61,8 @@ namespace
6161

6262
void run()
6363
{
64-
pathRemove("testdir/concurrent.zip");
65-
pathCreateArchiveZip("testdir/concurrent.zip");
64+
pathRemove("testdir/concurrent.carch");
65+
pathCreateArchiveCarch("testdir/concurrent.carch");
6666
threadPool->run();
6767
}
6868
};
@@ -79,49 +79,49 @@ void testArchivesRecursion()
7979
String p = "testdir";
8080
for (uint32 i = 0; i < 5; i++)
8181
{
82-
p = pathJoin(p, Stringizer() + i + ".zip");
83-
pathCreateArchiveZip(p);
82+
p = pathJoin(p, Stringizer() + i + ".carch");
83+
pathCreateArchiveCarch(p);
8484
}
8585
CAGE_TEST(none(pathType("testdir") & PathTypeFlags::Archive));
8686
CAGE_TEST(any(pathType("testdir") & PathTypeFlags::Directory));
87-
CAGE_TEST(any(pathType("testdir/0.zip") & PathTypeFlags::Archive));
88-
CAGE_TEST(none(pathType("testdir/0.zip") & PathTypeFlags::Directory));
89-
CAGE_TEST(any(pathType("testdir/0.zip/1.zip") & PathTypeFlags::Archive));
90-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip") & PathTypeFlags::Directory));
91-
CAGE_TEST(any(pathType("testdir/0.zip/1.zip/2.zip") & PathTypeFlags::Archive));
92-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip/2.zip") & PathTypeFlags::Directory));
87+
CAGE_TEST(any(pathType("testdir/0.carch") & PathTypeFlags::Archive));
88+
CAGE_TEST(none(pathType("testdir/0.carch") & PathTypeFlags::Directory));
89+
CAGE_TEST(any(pathType("testdir/0.carch/1.carch") & PathTypeFlags::Archive));
90+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch") & PathTypeFlags::Directory));
91+
CAGE_TEST(any(pathType("testdir/0.carch/1.carch/2.carch") & PathTypeFlags::Archive));
92+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch/2.carch") & PathTypeFlags::Directory));
9393
}
9494

9595
{
9696
CAGE_TESTCASE("create file inside each archive");
9797
String p = "testdir";
9898
for (uint32 i = 0; i < 5; i++)
9999
{
100-
p = pathJoin(p, Stringizer() + i + ".zip");
100+
p = pathJoin(p, Stringizer() + i + ".carch");
101101
Holder<File> f = writeFile(pathJoin(p, "welcome"));
102102
f->writeLine("hello");
103103
f->close();
104104
}
105-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::Archive));
106-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::Directory));
107-
CAGE_TEST(any(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::File));
105+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::Archive));
106+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::Directory));
107+
CAGE_TEST(any(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::File));
108108
}
109109

110110
{
111111
CAGE_TESTCASE("read file inside each archive");
112112
String p = "testdir";
113113
for (uint32 i = 0; i < 5; i++)
114114
{
115-
p = pathJoin(p, Stringizer() + i + ".zip");
115+
p = pathJoin(p, Stringizer() + i + ".carch");
116116
Holder<File> f = readFile(pathJoin(p, "welcome"));
117117
String l;
118118
CAGE_TEST(f->readLine(l));
119119
CAGE_TEST(l == "hello");
120120
f->close();
121121
}
122-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::Archive));
123-
CAGE_TEST(none(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::Directory));
124-
CAGE_TEST(any(pathType("testdir/0.zip/1.zip/2.zip/welcome") & PathTypeFlags::File));
122+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::Archive));
123+
CAGE_TEST(none(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::Directory));
124+
CAGE_TEST(any(pathType("testdir/0.carch/1.carch/2.carch/welcome") & PathTypeFlags::File));
125125
}
126126

127127
{
@@ -131,7 +131,7 @@ void testArchivesRecursion()
131131
String p = "testdir";
132132
for (uint32 i = 0; i < 5; i++)
133133
{
134-
p = pathJoin(p, Stringizer() + i + ".zip");
134+
p = pathJoin(p, Stringizer() + i + ".carch");
135135
Holder<void> tmp = detail::pathKeepOpen(p); // ensure the archive is open
136136
CAGE_TEST_THROWN(readFile(p));
137137
}
@@ -141,7 +141,7 @@ void testArchivesRecursion()
141141
String p = "testdir";
142142
for (uint32 i = 0; i < 5; i++)
143143
{
144-
p = pathJoin(p, Stringizer() + i + ".zip");
144+
p = pathJoin(p, Stringizer() + i + ".carch");
145145
CAGE_TEST(readFile(p));
146146
}
147147
}

0 commit comments

Comments
 (0)