Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / support / BufferWriter.h
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 #pragma once
19
20 #include <climits>
21 #include <stdint.h>
22 #include <string.h>
23
24 namespace chip {
25 namespace Encoding {
26
27 class BufferWriter
28 {
29 public:
30     BufferWriter(uint8_t * buf, size_t len) : mBuf(buf), mSize(len), mNeeded(0) {}
31     BufferWriter(const BufferWriter & other) = default;
32     BufferWriter & operator=(const BufferWriter & other) = default;
33
34     /// Append a null terminated string, exclude the null terminator
35     BufferWriter & Put(const char * s);
36
37     /// Raw append a buffer, regardless of endianess
38     BufferWriter & Put(const void * buf, size_t len);
39
40     /// Append a single byte
41     BufferWriter & Put(uint8_t c);
42
43     BufferWriter & Skip(size_t len)
44     {
45         mNeeded += len;
46         return *this;
47     }
48
49     /// Number of bytes required to satisfy all calls to Put() so far
50     size_t Needed() const { return mNeeded; }
51
52     /// Number of bytes still available for writing
53     size_t Available() const { return mSize < mNeeded ? 0 : mSize - mNeeded; }
54
55     /// Whether the input fit in the buffer
56     bool Fit() const
57     {
58         size_t _;
59         return Fit(_);
60     }
61
62     /// Returns whether the input fit in the buffer, outputs what was actually written
63     bool Fit(size_t & actuallyWritten) const
64     {
65         actuallyWritten = mSize >= mNeeded ? mNeeded : mSize;
66         return mSize >= mNeeded;
67     }
68
69     /// Size of the output buffer
70     size_t Size() const { return mSize; }
71
72     uint8_t * Buffer() { return mBuf; }
73     const uint8_t * Buffer() const { return mBuf; }
74
75 protected:
76     uint8_t * mBuf;
77     size_t mSize;
78     size_t mNeeded;
79 };
80
81 template <class Derived>
82 class EndianBufferWriterBase : public BufferWriter
83 {
84 public:
85     // typed BufferWriter forwards
86
87     Derived & Put(const char * s) { return static_cast<Derived &>(BufferWriter::Put(s)); }
88     Derived & Put(const void * buf, size_t len) { return static_cast<Derived &>(BufferWriter::Put(buf, len)); }
89     Derived & Put(uint8_t c) { return static_cast<Derived &>(BufferWriter::Put(c)); }
90     Derived & Skip(size_t len) { return static_cast<Derived &>(BufferWriter::Skip(len)); }
91
92     // write an integer into a buffer, in an endian specific way
93
94     Derived & Put8(uint8_t c) { return static_cast<Derived *>(this)->Put(c); }
95     Derived & Put16(uint16_t x) { return static_cast<Derived *>(this)->EndianPut(x, sizeof(x)); }
96     Derived & Put32(uint32_t x) { return static_cast<Derived *>(this)->EndianPut(x, sizeof(x)); }
97     Derived & Put64(uint64_t x) { return static_cast<Derived *>(this)->EndianPut(x, sizeof(x)); }
98
99 protected:
100     EndianBufferWriterBase(uint8_t * buf, size_t len) : BufferWriter(buf, len) {}
101     EndianBufferWriterBase(const EndianBufferWriterBase & other) = default;
102     EndianBufferWriterBase & operator=(const EndianBufferWriterBase & other) = default;
103 };
104
105 namespace LittleEndian {
106
107 class BufferWriter : public EndianBufferWriterBase<BufferWriter>
108 {
109 public:
110     BufferWriter(uint8_t * buf, size_t len) : EndianBufferWriterBase<BufferWriter>(buf, len) {}
111     BufferWriter(const BufferWriter & other) = default;
112     BufferWriter & operator=(const BufferWriter & other) = default;
113     BufferWriter & EndianPut(uint64_t x, size_t size);
114 };
115
116 } // namespace LittleEndian
117
118 namespace BigEndian {
119
120 class BufferWriter : public EndianBufferWriterBase<BufferWriter>
121 {
122 public:
123     BufferWriter(uint8_t * buf, size_t len) : EndianBufferWriterBase<BufferWriter>(buf, len) {}
124     BufferWriter(const BufferWriter & other) = default;
125     BufferWriter & operator=(const BufferWriter & other) = default;
126     BufferWriter & EndianPut(uint64_t x, size_t size);
127 };
128
129 } // namespace BigEndian
130
131 } // namespace Encoding
132 } // namespace chip