aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2020-03-29 22:59:04 +0300
committerAqua-sama <aqua@iserlohn-fortress.net>2020-03-29 22:59:04 +0300
commit13771971cfaef6356ba47668cae6ce25c5c2071f (patch)
treef2706c35edb06cbf43fc18a7c30608dfea67587f
parentChange rcc command line (diff)
downloadrcc-13771971cfaef6356ba47668cae6ce25c5c2071f.tar.xz
Drop dependency on serge-sans-paille/frozen
format: - instead of frozen::unordered_map, create two std::arrays with the aliased names (entries) and respective data (values) libembed: - Resources and CompressedResources convenience classes for raw and compressed resources respectively - Resources can be constexpr in regular usage - Annotate Resources::decompress accordingly
-rw-r--r--.gitmodules3
m---------3rd-party/frozen0
-rw-r--r--lib/compressionctx.h40
-rw-r--r--lib/embed.cpp17
-rw-r--r--lib/embed.h91
-rw-r--r--lib/zstd.cpp (renamed from lib/embed_zstd.cpp)15
-rw-r--r--meson.build3
-rw-r--r--readme.md5
-rw-r--r--scripts/rcc_format.py13
-rw-r--r--scripts/zstd.py2
-rw-r--r--test/main.cpp17
11 files changed, 143 insertions, 63 deletions
diff --git a/.gitmodules b/.gitmodules
index 36e8968..e0954d7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "3rd-party/frozen"]
- path = 3rd-party/frozen
- url = https://github.com/serge-sans-paille/frozen
[submodule "3rd-party/tabler-icons"]
path = 3rd-party/tabler-icons
url = https://github.com/tabler/tabler-icons
diff --git a/3rd-party/frozen b/3rd-party/frozen
deleted file mode 160000
-Subproject 8357f86de5383dde8539734d3a1620ecc70e4a1
diff --git a/lib/compressionctx.h b/lib/compressionctx.h
new file mode 100644
index 0000000..2f3946a
--- /dev/null
+++ b/lib/compressionctx.h
@@ -0,0 +1,40 @@
+#include <span>
+#include <vector>
+
+#pragma once
+
+namespace embed
+{
+
+enum Compression {
+ None,
+ Zstd
+};
+
+class CompressionCtx
+{
+public:
+ virtual ~CompressionCtx() = default;
+ [[nodiscard]] virtual std::vector<uint8_t> decompress(const std::span<const uint8_t> &entry) const = 0;
+};
+
+class ZstdCompressionCtx final : public CompressionCtx
+{
+public:
+ ZstdCompressionCtx(const std::span<const uint8_t> &dictionary);
+ ~ZstdCompressionCtx();
+ [[nodiscard]] std::vector<uint8_t> decompress(const std::span<const uint8_t> &entry) const override;
+};
+
+std::unique_ptr<CompressionCtx> make_compression_ctx(const Compression algo, const std::span<const uint8_t> &dict)
+{
+ switch(algo)
+ {
+ case None:
+ return nullptr;
+ case Zstd:
+ return std::make_unique<ZstdCompressionCtx>(dict);
+ }
+}
+
+} // namespace embed
diff --git a/lib/embed.cpp b/lib/embed.cpp
deleted file mode 100644
index 07af38f..0000000
--- a/lib/embed.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "embed.h"
-
-using namespace embed;
-
-template <>
-Resources<Compression::None>::Resources(const std::span<const unsigned char> &)
-{
-}
-
-template <>
-Resources<Compression::None>::~Resources() = default;
-
-template <>
-[[nodiscard]] std::vector<unsigned char> Resources<Compression::None>::decompress(const std::span<const unsigned char> &entry)
-{
- return { entry.begin(), entry.end() };
-}
diff --git a/lib/embed.h b/lib/embed.h
index bd041ff..b57d830 100644
--- a/lib/embed.h
+++ b/lib/embed.h
@@ -1,29 +1,88 @@
#pragma once
-#include <frozen/string.h>
-#include <frozen/unordered_map.h>
-#include <span>
-#include <vector>
+#include <array>
+#include <string_view>
+#include "compressionctx.h"
namespace embed
{
-enum Compression {
- None,
- Zstd
-};
-
-template <Compression c>
+template <std::size_t N>
class Resources
{
public:
- Resources() = default;
- explicit Resources(const std::span<const unsigned char> &dictionary);
+ constexpr explicit Resources(
+ const std::array<const char *, N> &entries,
+ const std::array<std::span<const uint8_t>, N> &values)
+ : m_entries(entries)
+ , m_values(values)
+ {
+ }
- ~Resources();
+ [[nodiscard]] constexpr int id(const std::string_view &path) const
+ {
+ for(std::size_t i = 0; i < m_entries.size(); ++i) {
+ if(m_entries.at(i) == path)
+ return i;
+ }
+ return -1;
+ }
+ [[nodiscard]] constexpr std::span<const uint8_t> value(const int id_) const
+ {
+ if(id_ == -1)
+ return {};
+ else
+ return m_values.at(id_);
+ }
+ [[nodiscard]] constexpr std::span<const uint8_t> value(const std::string_view &path) const
+ {
+ return value(id(path));
+ }
- [[nodiscard]] std::vector<unsigned char> decompress(const std::span<const unsigned char> &entry);
+ [[deprecated("With no compression, this function returns a copy; use ::value instead")]]
+ [[nodiscard]] std::vector<uint8_t> decompress(const int id_) const
+ {
+ const auto v = value(id_);
+ return { v.begin(), v.end() };
+ }
+ [[deprecated("With no compression, this function returns a copy; use ::value instead")]]
+ [[nodiscard]] std::vector<uint8_t> decompress(const std::string_view &path) const
+ {
+ const auto v = value(path);
+ return { v.begin(), v.end() };
+ }
-}; // class
+protected:
+ const std::array<const char *, N> m_entries;
+ const std::array<std::span<const uint8_t>, N> m_values;
+};
+
+template <std::size_t N>
+class CompressedResources final : public Resources<N>
+{
+public:
+ explicit CompressedResources(
+ const std::array<const char *, N> &entries,
+ const std::array<std::span<const uint8_t>, N> &values,
+ const Compression algo,
+ const std::span<const uint8_t> &dictionary = {})
+ : Resources<N>(entries, values)
+ , m_compression(make_compression_ctx(algo, dictionary))
+ {
+ }
+ ~CompressedResources() = default;
+
+ [[nodiscard]] std::vector<uint8_t> decompress(const int id_) const
+ {
+ return m_compression->decompress(Resources<N>::value(id_));
+ }
+ [[nodiscard]] std::vector<uint8_t> decompress(const std::string_view &path) const
+ {
+ return m_compression->decompress(Resources<N>::value(path));
+ }
+
+protected:
+ const std::unique_ptr<CompressionCtx> m_compression;
+};
-}
+} // namespace embed
diff --git a/lib/embed_zstd.cpp b/lib/zstd.cpp
index d9be35a..d2c27bc 100644
--- a/lib/embed_zstd.cpp
+++ b/lib/zstd.cpp
@@ -1,4 +1,4 @@
-#include "embed.h"
+#include "compressionctx.h"
#include <cassert>
#include <zstd.h>
@@ -6,24 +6,22 @@ using namespace embed;
ZSTD_DDict *dictPtr = nullptr;
-template <>
-Resources<Compression::Zstd>::Resources(const std::span<const unsigned char> &dictionary)
+ZstdCompressionCtx::ZstdCompressionCtx(const std::span<const uint8_t> &dictionary)
{
if(!dictionary.empty()) {
dictPtr = ZSTD_createDDict(dictionary.data(), dictionary.size());
}
}
-template <>
-Resources<Compression::Zstd>::~Resources()
+ZstdCompressionCtx::~ZstdCompressionCtx()
{
if(dictPtr != nullptr) {
ZSTD_freeDDict(dictPtr);
}
}
-template <>
-[[nodiscard]] std::vector<unsigned char> Resources<Compression::Zstd>::decompress(const std::span<const unsigned char> &entry)
+[[nodiscard]]
+std::vector<uint8_t> ZstdCompressionCtx::decompress(const std::span<const uint8_t> &entry) const
{
/* Read the content size from the frame header. For simplicity we require
* that it is always present. By default, zstd will write the content size
@@ -34,8 +32,7 @@ template <>
unsigned long long const rSize = ZSTD_getFrameContentSize(entry.data(), entry.size());
assert(rSize != ZSTD_CONTENTSIZE_ERROR); //, "%s: not compressed by zstd!", fname);
assert(rSize != ZSTD_CONTENTSIZE_UNKNOWN); //, "%s: original size unknown!", fname);
- //data<unsigned char> rBuff(new unsigned char[rSize], rSize, true);
- std::vector<unsigned char> rBuff(rSize);
+ std::vector<uint8_t> rBuff(rSize);
/* Check that the dictionary ID matches.
* If a non-zstd dictionary is used, then both will be zero.
diff --git a/meson.build b/meson.build
index 3cc04f1..d49e251 100644
--- a/meson.build
+++ b/meson.build
@@ -9,8 +9,7 @@ add_project_link_arguments(['-stdlib=libc++'], language : 'cpp')
libzstd = dependency('libzstd')
libembed_sourceset = import('sourceset').source_set()
-libembed_sourceset.add(files('lib/embed.cpp'))
-libembed_sourceset.add(when: libzstd, if_true: [ libzstd, files('lib/embed_zstd.cpp') ] )
+libembed_sourceset.add(when: libzstd, if_true: [ libzstd, files('lib/zstd.cpp') ] )
libembed_conf = libembed_sourceset.apply(configuration_data())
libembed = library('embed',
diff --git a/readme.md b/readme.md
index d75ac34..9c745ff 100644
--- a/readme.md
+++ b/readme.md
@@ -5,10 +5,7 @@ This is a resource compiler for C++, similar to Qt's rcc. It will generate hexdu
### requirements
* rcc tool requires python
* zstd compression requires zstd
-
-libembed:
-* c++20
-* frozen: https://github.com/serge-sans-paille/frozen (constexpr string and unordered_map)
+* c++20 (std::span)
### license
diff --git a/scripts/rcc_format.py b/scripts/rcc_format.py
index d0ab06d..7fcfe34 100644
--- a/scripts/rcc_format.py
+++ b/scripts/rcc_format.py
@@ -37,7 +37,7 @@ def write_header(file, namespace):
def write_item(file, array_name, array_data):
line_items = 0
- print("constexpr unsigned char {}[] = {{".format(array_name), file=file)
+ print("constexpr uint8_t {}[] = {{".format(array_name), file=file)
for byte in array_data[0:len(array_data)]:
line_items+=1
@@ -52,10 +52,15 @@ def write_item(file, array_name, array_data):
print("constexpr size_t {}_len = {};\n".format(array_name, len(array_data)), file=file)
def write_entries(file, resource_list):
- print("constexpr auto entries = frozen::make_unordered_map<frozen::string, std::span<const unsigned char>>({", file=file)
+ print("constexpr std::array entries {", file=file)
for f in resource_list:
- print(" {{ \"{}\", std::span({}, {}_len) }},".format(f.alias, f.variable, f.variable), file=file)
- print("});\n", file=file)
+ print(" \"{}\", ".format(f.alias), file=file)
+ print("};\n", file=file)
+
+ print("constexpr std::array values {", file=file)
+ for f in resource_list:
+ print(" std::span( {}, {}_len ),".format(f.variable, f.variable), file=file)
+ print("};\n", file=file)
def write_footer(file, namespace):
print("\n}} // namespace {}".format(namespace), file=file)
diff --git a/scripts/zstd.py b/scripts/zstd.py
index f85e7da..2cfa149 100644
--- a/scripts/zstd.py
+++ b/scripts/zstd.py
@@ -16,6 +16,8 @@ def zstd(filelist, args):
if args.dict is not None:
write_item(args.output, 'dict', args.dict.read())
print("constexpr auto dictionary = std::span(dict, dict_len);", file=args.output)
+ else:
+ print("constexpr std::span<const uint8_t> dictionary {};", file=args.output)
print("constexpr auto compression = embed::Zstd;", file=args.output)
diff --git a/test/main.cpp b/test/main.cpp
index f17ef67..f18332c 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -3,22 +3,23 @@
#include <cstdio>
#include <cstdlib>
-embed::Resources<zstd_data::compression> zstd_ctx(zstd_data::dictionary);
-
int main(int, char **)
{
- for(const auto &pair : zstd_data::entries) {
- const auto s = staticdata::entries.at(pair.first);
- const auto v = zstd_ctx.decompress(pair.second);
+ constexpr auto size = staticdata::entries.size();
+ constexpr embed::Resources static_ctx(staticdata::entries, staticdata::values);
+ const embed::CompressedResources zstd_ctx(zstd_data::entries, zstd_data::values, zstd_data::compression, zstd_data::dictionary);
+ for(std::size_t i = 0; i < size; ++i) {
+ const auto s = static_ctx.value(i);
+ const auto v = zstd_ctx.decompress(i);
if(s.size() != v.size()) {
- printf("failed comparing sizes at path [%s]\n", pair.first.data());
- printf("s: %li != v: %li\n", s.size(), v.size());
+ printf(" raw data at path [%s] size=%li\n", staticdata::entries.at(i), s.size());
+ printf(" zstd data at path [%s] size=%li\n", zstd_data::entries.at(i), v.size());
return EXIT_FAILURE;
}
if(!std::equal(s.begin(), s.end(), v.begin(), v.end())) {
- printf("failed comparing values at path [%s]\n", pair.first.data());
+ printf("failed comparing values at path [%s]\n", staticdata::entries.at(i));
for(const char &c : s)
printf("%c", c);
for(const char &c : v)