1 /*
2 * Compression utility header
3 * 
4 * Copyright:
5 * (C) 2014 Jack Lloyd
6 * (C) 2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 
12 module botan.compression.compress_utils;
13 
14 import memutils.hashmap;
15 import botan.utils.mem_ops;
16 import botan.compression.compress;
17 import memutils.unique;
18 
19 /*
20 * Allocation Size Tracking Helper for Zlib/Bzlib/LZMA
21 */
22 class CompressionAllocInfo
23 {
24 public:
25     extern(C) static void* malloc(T)(void* self, T n, T size) nothrow
26     {
27         return (cast(CompressionAllocInfo)self).doMalloc(n, size);
28     }
29     
30 	extern(C) static void free(void* self, void* ptr) nothrow
31     {
32         (cast(CompressionAllocInfo)self).doFree(ptr);
33     }
34     
35 private:
36     void* doMalloc(size_t n, size_t size) nothrow
37     {
38         import core.stdc.stdlib : malloc;
39         const size_t total_sz = n * size;
40         
41         void* ptr = malloc(total_sz);
42         try m_current_allocs[ptr] = total_sz;
43 		catch(Exception e) assert(false, e.msg);
44         return ptr;
45     }
46     void doFree(void* ptr) nothrow
47     {
48         if (ptr)
49         {
50             import core.stdc.stdlib : free;
51 			size_t* sz;
52 			try sz = ptr in m_current_allocs;
53 			catch (Exception e) assert(false, e.msg);
54             if (sz is null)
55                 assert(false, "CompressionAllocInfo.free got pointer not allocated by us");
56             
57             clearMem(ptr, *sz);
58             free(ptr);
59             try m_current_allocs.remove(ptr);
60 			catch (Exception e) assert(false, e.msg);
61         }
62     }
63     
64     HashMap!(void*, size_t) m_current_allocs;
65 }
66 
67 /**
68 * Wrapper for Zlib/Bzlib/LZMA stream types
69 */
70 abstract class ZlibStyleStream(Stream, ByteType) : CompressionStream
71 {
72 public:
73     override void nextIn(ubyte* b, size_t len)
74     {
75         m_stream.next_in = cast(ByteType*)(b);
76         m_stream.avail_in = cast(uint)len;
77     }
78     
79     override void nextOut(ubyte* b, size_t len)
80     {
81         m_stream.next_out = cast(ByteType*)(b);
82         m_stream.avail_out = cast(uint)len;
83     }
84     
85     override size_t availIn() const { return m_stream.avail_in; }
86     
87     override size_t availOut() const { return m_stream.avail_out; }
88     
89     this()
90     {
91         clearMem(&m_stream, 1);
92         m_allocs = new CompressionAllocInfo;
93     }
94     
95     ~this()
96     {
97         clearMem(&m_stream, 1);
98         m_allocs.free();
99     }
100     
101 protected:
102     alias stream_t = Stream;
103     
104     stream_t* streamp() { return &m_stream; }
105     
106     CompressionAllocInfo alloc() { return m_allocs.get(); }
107 private:
108     stream_t m_stream;
109     Unique!CompressionAllocInfo m_allocs;
110 }