aboutsummaryrefslogtreecommitdiffstats
path: root/util/stream/aligned.h
blob: 04b420c1db9801642614bf7466f98bd480b09896 (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#pragma once

#include "input.h" 
#include "output.h" 

#include <util/system/yassert.h> 
#include <util/generic/bitops.h> 
 
/** 
 * @addtogroup Streams 
 * @{ 
 */ 
 
/** 
 * Proxy input stream that provides additional functions that make reading 
 * aligned data easier. 
 */ 
class TAlignedInput: public IInputStream {
public:
    TAlignedInput(IInputStream* s)
        : Stream_(s) 
        , Position_(0) 
    {
    }

    /** 
     * Ensures alignment of the position in the input stream by skipping 
     * some input. 
     * 
     * @param alignment                 Alignment. Must be a power of 2. 
     */ 
    void Align(size_t alignment = sizeof(void*)) { 
        Y_ASSERT(IsPowerOf2(alignment));
 
        if (Position_ & (alignment - 1)) { 
            size_t len = alignment - (Position_ & (alignment - 1)); 

            do { 
                len -= DoSkip(len); 
            } while (len); 
        } 
    }
 
private: 
    size_t DoRead(void* ptr, size_t len) override;
    size_t DoSkip(size_t len) override;
    size_t DoReadTo(TString& st, char ch) override;
    ui64 DoReadAll(IOutputStream& out) override;
 
private: 
    IInputStream* Stream_;
    ui64 Position_; 
};

/** 
 * Proxy output stream that provides additional functions that make writing 
 * aligned data easier. 
 */ 
class TAlignedOutput: public IOutputStream {
public:
    TAlignedOutput(IOutputStream* s)
        : Stream_(s) 
        , Position_(0) 
    {
    }

    TAlignedOutput(TAlignedOutput&&) noexcept = default;
    TAlignedOutput& operator=(TAlignedOutput&&) noexcept = default;

    size_t GetCurrentOffset() const { 
        return Position_; 
    }

    /** 
     * Ensures alignment of the position in the output stream by writing 
     * some data. 
     * 
     * @param alignment                 Alignment. Must be a power of 2. 
     */ 
    void Align(size_t alignment = sizeof(void*)) { 
        Y_ASSERT(IsPowerOf2(alignment));
 
        static char unused[sizeof(void*) * 2];
        Y_ASSERT(alignment <= sizeof(unused));
 
        if (Position_ & (alignment - 1)) {
            DoWrite(unused, alignment - (Position_ & (alignment - 1))); 
        }
    }
 
private: 
    void DoWrite(const void* ptr, size_t len) override;
 
private: 
    IOutputStream* Stream_;
    ui64 Position_; 
};

/** @} */