Change script for apply upstream code
[platform/upstream/connectedhomeip.git] / src / lib / support / BufBound.h
1 /*
2  *
3  *    Copyright (c) 2020 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 /**
19  *  @file
20  *    BufBound manages serial writes to a buffer, guarding that the bounds of
21  *     the buffer are not exceeded.
22  *
23  */
24
25 #pragma once
26
27 #include <climits>
28 #include <stdint.h>
29 #include <string.h>
30
31 namespace chip {
32
33 /**
34  *  @class BufBound
35  *
36  *  simple buffer writer
37  */
38 class BufBound
39 {
40 private:
41     uint8_t * mBuf;
42     size_t mSize;
43     size_t mNeeded;
44
45 public:
46     BufBound(uint8_t * buf, size_t len) : mBuf(buf), mSize(len), mNeeded(0) {}
47     BufBound(const BufBound & other) = default;
48
49     /*
50      * @brief append a single byte
51      */
52     BufBound & Put(uint8_t c)
53     {
54         if (mNeeded < mSize)
55         {
56             mBuf[mNeeded] = c;
57         }
58         ++mNeeded;
59         return *this;
60     }
61
62     /*
63      * @brief append a null terminated string, exclude the null term
64      */
65     BufBound & Put(const char * s)
66     {
67         static_assert(CHAR_BIT == 8, "We're assuming char and uint8_t are the same size");
68         while (*s != 0)
69         {
70             Put(static_cast<uint8_t>(*s++));
71         }
72         return *this;
73     }
74     BufBound & Put8(uint8_t c) { return Put(c); }
75
76     BufBound & Put(uint64_t x, size_t size)
77     {
78         while (size-- > 0)
79         {
80             uint8_t c = x & 0xff;
81             Put(c);
82             x >>= 8;
83         }
84         return *this;
85     }
86
87     /*
88      * @brief write integer x into the buffer, least significant byte first
89      */
90     BufBound & Put64(uint64_t x) { return Put(x, sizeof(x)); }
91     BufBound & Put32(uint32_t x) { return Put(x, sizeof(x)); }
92     BufBound & Put16(uint16_t x) { return Put(x, sizeof(x)); }
93
94     BufBound & PutBE(uint64_t x, size_t size)
95     {
96         while (size-- > 0)
97         {
98             uint8_t c = (x >> (size * 8)) & 0xff;
99             Put(c);
100         }
101         return *this;
102     }
103
104     /*
105      * @brief write integer x into the buffer, most significant byte first
106      */
107     BufBound & PutBE64(uint64_t x) { return PutBE(x, sizeof(x)); }
108     BufBound & PutBE32(uint32_t x) { return PutBE(x, sizeof(x)); }
109     BufBound & PutBE16(uint16_t x) { return PutBE(x, sizeof(x)); }
110
111     /*
112      * @brief append a buffer
113      */
114     BufBound & Put(const uint8_t * buf, size_t len) { return Put(reinterpret_cast<const void *>(buf), len); }
115     BufBound & Put(const void * buf, size_t len)
116     {
117         size_t available = Available();
118
119         memmove(mBuf + mNeeded, buf, available < len ? available : len);
120
121         mNeeded += len;
122
123         return *this;
124     }
125
126     /*
127      * @brief number of bytes required to satisfy all calls to Put() so far
128      */
129     size_t Needed() const { return mNeeded; }
130     /*
131      * @brief bytes available
132      */
133     size_t Available() const { return mSize < mNeeded ? 0 : mSize - mNeeded; }
134
135     /*
136      * @brief whether the input fit in the buffer
137      */
138     bool Fit() const
139     {
140         size_t _;
141         return Fit(_);
142     }
143
144     /*
145      * @brief returns whether the input fit in the buffer, outputs what was
146      *        actually written
147      */
148     bool Fit(size_t & actually_written) const
149     {
150         actually_written = mSize >= mNeeded ? mNeeded : mSize;
151         return mSize >= mNeeded;
152     }
153
154     /*
155      * @brief Size of the buffer
156      */
157     size_t Size() const { return mSize; }
158 };
159
160 } // namespace chip