summaryrefslogtreecommitdiffstats
path: root/source/core/slang-deflate-compression-system.cpp
blob: 6c75de9e496f2ca53e91a47452b8dea53426b1ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "slang-deflate-compression-system.h"

#include "../../slang-com-helper.h"
#include "../../slang-com-ptr.h"

// We don't want compress #define to clash 
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES 1

#include "../../external/miniz/miniz.h"
#include "../../external/miniz/miniz_common.h"
#include "../../external/miniz/miniz_tdef.h"
#include "../../external/miniz/miniz_tinfl.h"

#include "slang-blob.h"

namespace Slang
{

// Allocate static const storage for the various interface IDs that the Slang API needs to expose

class DeflateCompressionSystemImpl : public RefObject, public ICompressionSystem
{
public:
    // ISlangUnknown 
    // override ref counting, as singleton
    SLANG_IUNKNOWN_QUERY_INTERFACE

    SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; }
    SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; }

    // ICompressionSystem
    virtual SLANG_NO_THROW CompressionSystemType SLANG_MCALL getSystemType() SLANG_OVERRIDE { return CompressionSystemType::Deflate; }
    virtual SLANG_NO_THROW SlangResult SLANG_MCALL compress(const CompressionStyle* style, const void* src, size_t srcSizeInBytes, ISlangBlob** outBlob) SLANG_OVERRIDE;
    virtual SLANG_NO_THROW SlangResult SLANG_MCALL decompress(const void* compressed, size_t compressedSizeInBytes, size_t decompressedSizeInBytes, void* outDecompressed) SLANG_OVERRIDE;

protected:

    ICompressionSystem* getInterface(const Guid& guid);
};

ICompressionSystem* DeflateCompressionSystemImpl::getInterface(const Guid& guid)
{
    return (guid == ISlangUnknown::getTypeGuid() || guid == ICompressionSystem::getTypeGuid()) ? static_cast<ICompressionSystem*>(this) : nullptr;
}

SlangResult DeflateCompressionSystemImpl::compress(const CompressionStyle* style, const void* src, size_t srcSizeInBytes, ISlangBlob** outBlob)
{
    SLANG_UNUSED(style);

    size_t compressedSizeInBytes;

    const int flags = 0;
    void* compressed = tdefl_compress_mem_to_heap(src, srcSizeInBytes, &compressedSizeInBytes, flags);

    if (!compressed)
    {
        return SLANG_FAIL;
    }

    ScopedAllocation alloc;
    alloc.attach(compressed, compressedSizeInBytes);

    auto blob = RawBlob::moveCreate(alloc);
    *outBlob = blob.detach();
    return SLANG_OK;
}

SlangResult DeflateCompressionSystemImpl::decompress(const void* compressed, size_t compressedSizeInBytes, size_t decompressedSizeInBytes, void* outDecompressed)
{
    const int flags = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;

    size_t size = tinfl_decompress_mem_to_mem(outDecompressed, decompressedSizeInBytes, compressed ,compressedSizeInBytes, flags);
    if (size == TINFL_DECOMPRESS_MEM_TO_MEM_FAILED)
    {
        return SLANG_FAIL;
    }

    return SLANG_OK;
}

/* static */ICompressionSystem* DeflateCompressionSystem::getSingleton()
{
    static DeflateCompressionSystemImpl impl;
    return &impl;
}

} // namespace Slang