Rework of ScriptResolver to binary handling. Now also serialises the type database to the stream, simplifying it's api.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -2,23 +2,30 @@
|
||||
#define PKMNLIB_FILEBYTECODESTREAM_HPP
|
||||
#include <angelscript.h>
|
||||
#include <cstdio>
|
||||
#include "IPkmnBinaryStream.hpp"
|
||||
|
||||
class FileByteCodeStream : public asIBinaryStream {
|
||||
class FileByteCodeStream : public IPkmnBinaryStream {
|
||||
private:
|
||||
FILE* _file;
|
||||
size_t _readPosition = 0;
|
||||
|
||||
public:
|
||||
explicit FileByteCodeStream(FILE* file) : _file(file) {}
|
||||
explicit FileByteCodeStream(FILE* file, size_t bound) : IPkmnBinaryStream(bound), _file(file) {}
|
||||
|
||||
int Write(const void* ptr, asUINT size) {
|
||||
int Write(const void* ptr, asUINT size) override {
|
||||
if (size == 0)
|
||||
return 0;
|
||||
return fwrite(ptr, size, 1, _file);
|
||||
}
|
||||
int Read(void* ptr, asUINT size) {
|
||||
int Read(void* ptr, asUINT size) override {
|
||||
if (size == 0)
|
||||
return 0;
|
||||
return fread(ptr, size, 1, _file);
|
||||
if (_readPosition + size >= _angelScriptBound) {
|
||||
size = _angelScriptBound - _readPosition;
|
||||
}
|
||||
auto diff = fread(ptr, size, 1, _file);
|
||||
_readPosition += diff;
|
||||
return diff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#ifndef PKMNLIB_IPKMNBINARYSTREAM_HPP
|
||||
#define PKMNLIB_IPKMNBINARYSTREAM_HPP
|
||||
|
||||
#include <Arbutils/Collections/Dictionary.hpp>
|
||||
#include <Arbutils/ConstString.hpp>
|
||||
#include <CreatureLib/Battling/ScriptHandling/ScriptCategory.hpp>
|
||||
#include <angelscript.h>
|
||||
|
||||
class IPkmnBinaryStream : public asIBinaryStream {
|
||||
protected:
|
||||
size_t _angelScriptBound;
|
||||
|
||||
IPkmnBinaryStream(size_t angelScriptBound) : _angelScriptBound(angelScriptBound) {}
|
||||
|
||||
public:
|
||||
virtual void WriteTypes(const Dictionary<ScriptCategory, Dictionary<ConstString, AngelScriptTypeInfo*>>& types) {
|
||||
// We serialize our types in the format
|
||||
// "[category(byte)][name(str)]\2[decl(str)]\2[name(str)]\2[decl(str)]\1[category(byte)]...."
|
||||
|
||||
ScriptCategory categoryArr[1];
|
||||
for (const auto& dic : types) {
|
||||
// Write the category
|
||||
categoryArr[0] = dic.first;
|
||||
Write(categoryArr, sizeof(ScriptCategory));
|
||||
for (const auto& inner : dic.second) {
|
||||
// Write the script name
|
||||
Write(inner.first.c_str(), sizeof(char) * inner.first.Length());
|
||||
// Write the divider
|
||||
Write("\2", sizeof(char));
|
||||
// Write the declaration of the script
|
||||
auto decl = inner.second->GetDecl();
|
||||
Write(decl, sizeof(char) * strlen(decl));
|
||||
// Write another divider.
|
||||
Write("\2", sizeof(char));
|
||||
}
|
||||
// Write the divider between categories.
|
||||
Write("\1", sizeof(char));
|
||||
}
|
||||
}
|
||||
virtual Dictionary<ScriptCategory, Dictionary<ConstString, uint32_t>> ReadTypes() {
|
||||
_angelScriptBound = SIZE_MAX;
|
||||
Dictionary<ScriptCategory, Dictionary<ConstString, uint32_t>> types;
|
||||
ScriptCategory categoryArr[1];
|
||||
while (true) {
|
||||
// Every inner database starts with the category, of known size. Read that.
|
||||
auto read = Read(categoryArr, sizeof(ScriptCategory));
|
||||
// If we haven't read anything, we are finished.
|
||||
if (read == 0) {
|
||||
break;
|
||||
}
|
||||
Dictionary<ConstString, uint32_t> innerDb;
|
||||
|
||||
// We don't know the sizes of the name and decl. Allocate 128 characters for them, as that should be enough.
|
||||
char name[128];
|
||||
char decl[128];
|
||||
size_t pos = 0;
|
||||
bool isDecl = false;
|
||||
|
||||
while (true) {
|
||||
// Keep reading characters
|
||||
char cArr[1];
|
||||
Read(cArr, sizeof(char));
|
||||
auto c = cArr[0];
|
||||
// If we find a '\1' separator
|
||||
if (c == '\1') {
|
||||
// and if we were reading the decl
|
||||
if (isDecl) {
|
||||
// Insert the name and decl into the dictionary. Close off the decl with eof as well.
|
||||
decl[pos] = '\0';
|
||||
innerDb.Insert(Arbutils::CaseInsensitiveConstString(name),
|
||||
Arbutils::CaseInsensitiveConstString::GetHash(decl));
|
||||
}
|
||||
// If we have found \1, we are done with the current category, so break.
|
||||
break;
|
||||
}
|
||||
// If we find a '\2' separator, we need to toggle between writing to name and writing to decl. If we
|
||||
// were writing a decl, also insert the name and decl into the dictionary.
|
||||
if (c == '\2') {
|
||||
if (isDecl) {
|
||||
// Insert the name and decl into the dictionary. Close off the decl with eof as well.
|
||||
decl[pos] = '\0';
|
||||
innerDb.Insert(Arbutils::CaseInsensitiveConstString(name),
|
||||
Arbutils::CaseInsensitiveConstString::GetHash(decl));
|
||||
// Reset our position and toggle back to name.
|
||||
pos = 0;
|
||||
isDecl = false;
|
||||
continue;
|
||||
} else {
|
||||
// Close of the name with eof, reset position and toggle to decl.
|
||||
name[pos] = '\0';
|
||||
pos = 0;
|
||||
isDecl = true;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// If we haven't found any control character, just add the character to the thing we are writing to,
|
||||
// and increment the position.
|
||||
if (isDecl) {
|
||||
decl[pos++] = c;
|
||||
} else {
|
||||
name[pos++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
types.Insert(categoryArr[0], innerDb);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PKMNLIB_IPKMNBINARYSTREAM_HPP
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <angelscript.h>
|
||||
#include <vector>
|
||||
|
||||
class MemoryByteCodeStream : public asIBinaryStream {
|
||||
class MemoryByteCodeStream : public IPkmnBinaryStream {
|
||||
private:
|
||||
uint8_t* _out;
|
||||
size_t _index = 0;
|
||||
@@ -13,12 +13,15 @@ private:
|
||||
#define MEM_STEPS 256
|
||||
|
||||
public:
|
||||
MemoryByteCodeStream() : _out((uint8_t*)malloc(MEM_STEPS * sizeof(uint8_t))), _capacity(MEM_STEPS){};
|
||||
MemoryByteCodeStream(uint8_t* in, size_t size) : _out(in), _size(size) {}
|
||||
MemoryByteCodeStream()
|
||||
: IPkmnBinaryStream(SIZE_MAX), _out((uint8_t*)malloc(MEM_STEPS * sizeof(uint8_t))), _capacity(MEM_STEPS){};
|
||||
MemoryByteCodeStream(uint8_t* in, size_t size) : IPkmnBinaryStream(SIZE_MAX), _out(in), _size(size) {}
|
||||
|
||||
uint8_t* GetOut() const { return _out; }
|
||||
size_t GetWrittenSize() const { return _size; }
|
||||
|
||||
void SetAngelScriptBound(size_t bound) noexcept { _angelScriptBound = bound; }
|
||||
|
||||
int Write(const void* ptr, asUINT size) final {
|
||||
if (size == 0)
|
||||
return 0;
|
||||
@@ -38,6 +41,14 @@ public:
|
||||
_size += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
void WriteToPosition(const void* ptr, asUINT size, size_t position) {
|
||||
auto start = reinterpret_cast<const uint8_t*>(ptr);
|
||||
for (asUINT index = 0; index < size; index++) {
|
||||
_out[position + index] = *(start + index);
|
||||
}
|
||||
}
|
||||
|
||||
int Read(void* ptr, asUINT size) final {
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user