aboutsummaryrefslogtreecommitdiffstats
path: root/document/src/vespa/document/util/bytebuffer.h
blob: 58a26d7313a9fa76e4037491523853963b88ba8f (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
 * \class document::ByteBuffer
 * \ingroup util
 *
 * \brief Java like bytebuffer class
 *
 * This class wraps a char* buffer with a length and position.
 * It can be used to hide from the user whether the buffer was
 * allocated or not, and can hold a position in the buffer which
 * can be used for streaming-like behaviour.
 *
 * @author Thomas F. Gundersen, �ystein Fledsberg, Einar Rosenvinge
 */
#pragma once

#include <vespa/vespalib/util/alloc.h>

namespace document {

class ByteBuffer
{
public:
    using UP = std::unique_ptr<ByteBuffer>;

    ByteBuffer(const ByteBuffer &);
    ByteBuffer& operator=(const ByteBuffer &) = delete;
    ByteBuffer(ByteBuffer &&) = default;
    ByteBuffer& operator=(ByteBuffer &&) = default;

    ByteBuffer() : ByteBuffer(nullptr, 0) { }
    ~ByteBuffer() = default;

    /**
     * Create a buffer with the given content.
     *
     * @param buffer The buffer to represent.
     * @param len The length of the buffer
     */
    ByteBuffer(const char* buffer, uint32_t len)
        : _buffer(const_cast<char *>(buffer)),
          _len(len),
          _pos(0),
          _ownedBuffer()
    { }

    /**
     * Create a buffer with the given content.
     *
     * @param buffer The buffer to represent.
     * @param len The length of the buffer
     */
    ByteBuffer(vespalib::alloc::Alloc buffer, uint32_t len);
    ByteBuffer(std::unique_ptr<vespalib::alloc::Alloc> buffer, uint32_t len);

    /**
     * Creates a ByteBuffer object from another buffer. allocates
     * a new buffer of same size and copies the content.
     *
     * @param buffer The buffer to copy.
     * @param len The length of the buffer.
     *
     *  @return Returns a newly created bytebuffer object, or nullptr
     *  if buffer was nullptr, or len was <=0.
     */
    static ByteBuffer copyBuffer(const char* buffer, uint32_t len);

    /** @return Returns the buffer pointed to by this object (at position 0) */
    const char* getBuffer() const { return _buffer; }

    /** @return Returns the length of the buffer pointed to by this object. */
    uint32_t getLength() const { return _len; }

    /** @return Returns a pointer to the current position in the buffer. */
    const char* getBufferAtPos() const { return _buffer + _pos; }

    /** @return Returns the index of the current position in the buffer. */
    uint32_t getPos() const { return _pos; }

    /**
     * @return Returns the number of bytes remaining in the buffer - that is,
     *         getLength()-getPos().
    */
    uint32_t getRemaining() const { return _len -_pos; }

    /**
     * Moves the position in the buffer.
     *
     * @param pos The number of bytes to move the position. The new position
     *            will be oldPos + pos. This is the same as doing
     *            setPos(getPos()+pos)
     * @throws BufferOutOfBoundsException;
     */
    void incPos(uint32_t pos);

    void getNumeric(uint8_t & v);
    void getNumericNetwork(int16_t & v);
    void getNumericNetwork(int32_t & v);

    void getNumericNetwork(int64_t & v);
    void getNumeric(int64_t& v);
    void getNumericNetwork(double & v);

    void getChar(char & val) { unsigned char t;getByte(t); val=t; }
    void getByte(uint8_t & v)         { getNumeric(v); }
    void getShortNetwork(int16_t & v) { getNumericNetwork(v); }
    void getIntNetwork(int32_t & v)   { getNumericNetwork(v); }
    void getLongNetwork(int64_t & v)  { getNumericNetwork(v); }
    void getLong(int64_t& v)          { getNumeric(v); }
    void getDoubleNetwork(double & v) { getNumericNetwork(v); }
    void getBytes(void *buffer, uint32_t count);

private:
    template<typename T>
    void getDoubleLongNetwork(T &val);

    void incPosNoCheck(uint32_t pos) { _pos += pos; }

    const char *   _buffer;
    uint32_t       _len;
    uint32_t       _pos;
    std::unique_ptr<vespalib::alloc::Alloc> _ownedBuffer;
};

} // document