aboutsummaryrefslogtreecommitdiffstats
path: root/util/stream/aligned.h
blob: 015c65dea0dc114acc3127969c662b5a72522bc5 (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_;
};

/** @} */