1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "stream_buffer.h"
17
18namespace OHOS {
19namespace Sensors {
20StreamBuffer::StreamBuffer(const StreamBuffer &buf)
21{
22    Clone(buf);
23}
24
25StreamBuffer &StreamBuffer::operator=(const StreamBuffer &other)
26{
27    Clone(other);
28    return *this;
29}
30
31void StreamBuffer::Reset()
32{
33#ifdef OHOS_BUILD_ENABLE_RUST
34    StreamBufferReset(streamBufferPtr_.get());
35#else
36    rPos_ = 0;
37    wPos_ = 0;
38    rCount_ = 0;
39    wCount_ = 0;
40    rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK;
41#endif // OHOS_BUILD_ENABLE_RUST
42}
43
44void StreamBuffer::Clean()
45{
46#ifdef OHOS_BUILD_ENABLE_RUST
47    StreamBufferClean(streamBufferPtr_.get());
48#else
49    Reset();
50    errno_t ret = memset_sp(&szBuff_, sizeof(szBuff_), 0, sizeof(szBuff_));
51    if (ret != EOK) {
52        SEN_HILOGE("Call memset_s fail");
53        return;
54    }
55#endif // OHOS_BUILD_ENABLE_RUST
56}
57
58bool StreamBuffer::Read(std::string &buf)
59{
60#ifdef OHOS_BUILD_ENABLE_RUST
61    const int32_t ERROR_STATUS_READ = 1;
62    if (StreamBufferGetRpos(streamBufferPtr_.get()) == StreamBufferGetWpos(streamBufferPtr_.get())) {
63        SEN_HILOGE("Not enough memory to read, errCode:%{public}d", STREAM_BUF_READ_FAIL);
64        StreamBufferSetRwErrStatus(streamBufferPtr_.get(), ERROR_STATUS_READ);
65        return false;
66    }
67    buf = ReadBuf();
68    StreamBufferSetRpos(streamBufferPtr_.get(),
69        StreamBufferGetRpos(streamBufferPtr_.get()) + static_cast<int32_t>(buf.length()) + 1);
70    return (buf.length() > 0);
71#else
72    if (rPos_ == wPos_) {
73        SEN_HILOGE("Not enough memory to read");
74        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
75        return false;
76    }
77    buf = ReadBuf();
78    rPos_ += buf.length() + 1;
79    return (buf.length() > 0);
80#endif // OHOS_BUILD_ENABLE_RUST
81}
82
83bool StreamBuffer::Write(const std::string &buf)
84{
85    return Write(buf.c_str(), buf.length()+1);
86}
87
88bool StreamBuffer::Read(StreamBuffer &buf)
89{
90#ifdef OHOS_BUILD_ENABLE_RUST
91    return StreamBufferRead(streamBufferPtr_.get(), buf.streamBufferPtr_.get());
92#else
93    return buf.Write(Data(), Size());
94#endif // OHOS_BUILD_ENABLE_RUST
95}
96
97bool StreamBuffer::Write(const StreamBuffer &buf)
98{
99#ifdef OHOS_BUILD_ENABLE_RUST
100    return StreamBufferWrite(streamBufferPtr_.get(), buf.streamBufferPtr_.get());
101#else
102    return Write(buf.Data(), buf.Size());
103#endif // OHOS_BUILD_ENABLE_RUST
104}
105
106bool StreamBuffer::Read(char *buf, size_t size)
107{
108#ifdef OHOS_BUILD_ENABLE_RUST
109    return StreamBufferReadChar(streamBufferPtr_.get(), buf, size);
110#else
111    if (ChkRWError()) {
112        return false;
113    }
114    if (buf == nullptr) {
115        SEN_HILOGE("Invalid input parameter, buf is nullptr");
116        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
117        return false;
118    }
119    if (size == 0) {
120        SEN_HILOGE("Invalid input parameter, size:%{public}zu", size);
121        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
122        return false;
123    }
124    if (rPos_ + size > wPos_) {
125        SEN_HILOGE("Memory out of bounds on read");
126        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
127        return false;
128    }
129    errno_t ret = memcpy_sp(buf, size, ReadBuf(), size);
130    if (ret != EOK) {
131        SEN_HILOGE("Failed to call memcpy_sp");
132        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
133        return false;
134    }
135    rPos_ += size;
136    ++rCount_;
137    return true;
138#endif // OHOS_BUILD_ENABLE_RUST
139}
140
141bool StreamBuffer::Write(const char *buf, size_t size)
142{
143#ifdef OHOS_BUILD_ENABLE_RUST
144    return StreamBufferWriteChar(streamBufferPtr_.get(), buf, size);
145#else
146    if (ChkRWError()) {
147        return false;
148    }
149    if (buf == nullptr) {
150        SEN_HILOGE("Invalid input parameter, buf is nullptr");
151        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
152        return false;
153    }
154    if (size == 0) {
155        SEN_HILOGE("Invalid input parameter, size:%{public}zu", size);
156        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
157        return false;
158    }
159    if (wPos_ + size > MAX_STREAM_BUF_SIZE) {
160        SEN_HILOGE("The write length exceeds buffer. wPos:%{public}zu, size:%{public}zu, maxBufSize:%{public}zu",
161                   wPos_, size, MAX_STREAM_BUF_SIZE);
162        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
163        return false;
164    }
165    errno_t ret = memcpy_sp(&szBuff_[wPos_], GetAvailableBufSize(), buf, size);
166    if (ret != EOK) {
167        SEN_HILOGE("Failed to call memcpy_sp");
168        rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
169        return false;
170    }
171    wPos_ += size;
172    ++wCount_;
173    return true;
174#endif // OHOS_BUILD_ENABLE_RUST
175}
176
177const char *StreamBuffer::ReadBuf() const
178{
179#ifdef OHOS_BUILD_ENABLE_RUST
180    return StreamBufferReadBuf(streamBufferPtr_.get());
181#else
182    return &szBuff_[rPos_];
183#endif // OHOS_BUILD_ENABLE_RUST
184}
185
186bool StreamBuffer::Clone(const StreamBuffer &buf)
187{
188    Clean();
189#ifdef OHOS_BUILD_ENABLE_RUST
190    return Write(StreamBufferData(buf.streamBufferPtr_.get()), StreamBufferSize(buf.streamBufferPtr_.get()));
191#else
192    return Write(buf.Data(), buf.Size());
193#endif // OHOS_BUILD_ENABLE_RUST
194}
195#ifndef OHOS_BUILD_ENABLE_RUST
196
197bool StreamBuffer::ChkRWError() const
198{
199    return (rwErrorStatus_ != ErrorStatus::ERROR_STATUS_OK);
200}
201
202bool StreamBuffer::SeekReadPos(size_t n)
203{
204    size_t pos = rPos_ + n;
205    if (pos > wPos_) {
206        SEN_HILOGE("The position in the calculation is not as expected. pos:%{public}zu, [0, %{public}zu]", pos, wPos_);
207        return false;
208    }
209    rPos_ = pos;
210    return true;
211}
212
213bool StreamBuffer::IsEmpty() const
214{
215    return (rPos_ == wPos_);
216}
217
218size_t StreamBuffer::Size() const
219{
220#ifdef OHOS_BUILD_ENABLE_RUST
221    return StreamBufferSize(&rustStreamBuffer_);
222#else
223    return wPos_;
224#endif // OHOS_BUILD_ENABLE_RUST
225}
226
227size_t StreamBuffer::UnreadSize() const
228{
229    return ((wPos_ <= rPos_) ? 0 : (wPos_ - rPos_));
230}
231
232size_t StreamBuffer::GetAvailableBufSize() const
233{
234    return ((wPos_ >= MAX_STREAM_BUF_SIZE) ? 0 : (MAX_STREAM_BUF_SIZE - wPos_));
235}
236
237const std::string &StreamBuffer::GetErrorStatusRemark() const
238{
239#ifdef OHOS_BUILD_ENABLE_RUST
240    return StreamBufferGetErrorStatusRemark(streamBufferPtr_.get());
241#else
242    static const std::vector<std::pair<ErrorStatus, std::string>> remark {
243        {ErrorStatus::ERROR_STATUS_OK, "OK"},
244        {ErrorStatus::ERROR_STATUS_READ, "READ_ERROR"},
245        {ErrorStatus::ERROR_STATUS_WRITE, "WRITE_ERROR"},
246    };
247    static const std::string invalidStatus { "UNKNOWN" };
248    auto tIter = std::find_if(remark.cbegin(), remark.cend(), [this](const auto &item) {
249        return (item.first == rwErrorStatus_);
250    });
251    return (tIter != remark.cend() ? tIter->second : invalidStatus);
252#endif // OHOS_BUILD_ENABLE_RUST
253}
254
255const char *StreamBuffer::Data() const
256{
257#ifdef OHOS_BUILD_ENABLE_RUST
258    return StreamBufferData(&rustStreamBuffer_);
259#else
260    return &szBuff_[0];
261#endif // OHOS_BUILD_ENABLE_RUST
262}
263
264const char *StreamBuffer::WriteBuf() const
265{
266    return &szBuff_[wPos_];
267}
268#endif // OHOS_BUILD_ENABLE_RUST
269} // namespace Sensors
270} // namespace OHOS
271