aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/compproto/compressor.h
blob: 0e3a27afd0037e23fb569877bdeb61681596c84a (plain) (blame)
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
#pragma once

#include <util/system/defaults.h>

namespace NCompProto {
    struct TEmpty { 
    }; 

    struct TTable { 
        TTable() { 
            for (size_t i = 0; i < 64; ++i) { 
                CodeBase[i] = 0; 
                CodeMask[i] = 0; 
                Length[i] = 0; 
                PrefLength[i] = 0; 
                Id[i] = 0; 
            } 
        }
        ui32 CodeBase[64]; 
        ui32 CodeMask[64]; 
        ui8 Length[64]; 
        ui8 PrefLength[64]; 
        ui8 Id[64]; 
        enum { 
            PAGE_BOUND = 4096, 
#ifdef WITH_VALGRIND
            SAFE_MODE = 1, 
#else
#if defined(__has_feature) 
#if __has_feature(address_sanitizer) 
            SAFE_MODE = 1,
#else 
            SAFE_MODE = 0,
#endif
#else 
            SAFE_MODE = 0, 
#endif 
#endif 
        }; 
        ui32 inline Decompress(const ui8* codes, ui64& offset) const { 
            codes += (offset >> 3); 
            size_t pageOff = size_t(codes) % PAGE_BOUND; 
            size_t readOff = offset & 7; 
            if (pageOff > PAGE_BOUND - 8 || SAFE_MODE) { 
                size_t off = 8; 
                ui64 res = codes[0]; 
                ++codes;
                ui64 indexCur = ((res + 0x0000) >> readOff) & 63; 
                ui64 indexAlt = ((res + 0xff00) >> readOff) & 63; 
                if (Id[indexCur] != Id[indexAlt]) { 
                    res += (ui64(codes[0]) << off); 
                    ++codes; 
                    off += 8; 
                    indexCur = (res >> readOff) & 63; 
                } 
                ui64 index = indexCur; 
                ui64 length = Length[index]; 
                while (off < readOff + length) { 
                    res += (ui64(codes[0]) << off); 
                    ++codes; 
                    off += 8; 
                } 
                offset += length; 
                ui64 code = res >> readOff; 
                return (((ui32)(code >> PrefLength[index])) & CodeMask[index]) + CodeBase[index]; 
            }
            ui64 code = ((const ui64*)(codes))[0] >> readOff; 
            ui64 index = code & 63; 
            offset += Length[index]; 
            return (((ui32)(code >> PrefLength[index])) & CodeMask[index]) + CodeBase[index];
        }
    }; 

}