diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/compressionctx.h | 40 | ||||
| -rw-r--r-- | lib/embed.cpp | 17 | ||||
| -rw-r--r-- | lib/embed.h | 91 | ||||
| -rw-r--r-- | lib/zstd.cpp (renamed from lib/embed_zstd.cpp) | 15 | 
4 files changed, 121 insertions, 42 deletions
| 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. | 
