1 /*
2  * Copyright (c) 2021-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 
18 #include <algorithm>
19 
20 namespace OHOS {
21 namespace Msdp {
StreamBuffer(const StreamBuffer & buf)22 StreamBuffer::StreamBuffer(const StreamBuffer &buf)
23 {
24     Clone(buf);
25 }
26 
operator =(const StreamBuffer & buffer)27 StreamBuffer &StreamBuffer::operator=(const StreamBuffer &buffer)
28 {
29     Clone(buffer);
30     return *this;
31 }
32 
Reset()33 void StreamBuffer::Reset()
34 {
35     wPos_ = 0;
36     rPos_ = 0;
37     wCount_ = 0;
38     rCount_ = 0;
39     rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK;
40 }
41 
Clean()42 void StreamBuffer::Clean()
43 {
44     Reset();
45     errno_t ret = memset_sp(&szBuff_, sizeof(szBuff_), 0, sizeof(szBuff_));
46     if (ret != EOK) {
47         FI_HILOGE("Call memset_s failed");
48         return;
49     }
50 }
51 
SeekReadPos(int32_t n)52 bool StreamBuffer::SeekReadPos(int32_t n)
53 {
54     int32_t pos = rPos_ + n;
55     if (pos < 0 || pos > wPos_) {
56         FI_HILOGE("The position in the calculation is not as expected, pos:%{public}d, [0, %{public}d]",
57             pos, wPos_);
58         return false;
59     }
60     rPos_ = pos;
61     return true;
62 }
63 
Write(const std::string & buf)64 bool StreamBuffer::Write(const std::string &buf)
65 {
66     return Write(buf.c_str(), buf.length() + 1);
67 }
68 
Read(std::string & buf)69 bool StreamBuffer::Read(std::string &buf)
70 {
71     if (rPos_ == wPos_) {
72         FI_HILOGE("Not enough memory to read, errCode:%{public}d", STREAM_BUF_READ_FAIL);
73         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
74         return false;
75     }
76     buf = ReadBuf();
77     rPos_ = rPos_ + static_cast<int32_t>(buf.length()) + 1;
78     return (buf.length() > 0);
79 }
80 
Write(const StreamBuffer & buf)81 bool StreamBuffer::Write(const StreamBuffer &buf)
82 {
83     return Write(buf.Data(), buf.Size());
84 }
85 
Read(StreamBuffer & buf)86 bool StreamBuffer::Read(StreamBuffer &buf)
87 {
88     return buf.Write(Data(), Size());
89 }
90 
Read(char * buf,size_t size)91 bool StreamBuffer::Read(char *buf, size_t size)
92 {
93     if (ChkRWError()) {
94         FI_HILOGE("Read and write status is error");
95         return false;
96     }
97     if (buf == nullptr) {
98         FI_HILOGE("Invalid input parameter buf:nullptr, errCode:%{public}d", PARAM_INPUT_INVALID);
99         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
100         return false;
101     }
102     if (size == 0) {
103         FI_HILOGE("Invalid input parameter size:%{public}zu, errCode:%{public}d", size, PARAM_INPUT_INVALID);
104         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
105         return false;
106     }
107     if (rPos_ + static_cast<int32_t>(size) > wPos_) {
108         FI_HILOGE("Memory out of bounds on read, errCode:%{public}d", MEM_OUT_OF_BOUNDS);
109         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
110         return false;
111     }
112     errno_t ret = memcpy_sp(buf, size, ReadBuf(), size);
113     if (ret != EOK) {
114         FI_HILOGE("Failed to call memcpy_sp, errCode:%{public}d", MEMCPY_SEC_FUN_FAIL);
115         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_READ;
116         return false;
117     }
118 
119     rCount_ += 1;
120     rPos_ += static_cast<int32_t>(size);
121     return true;
122 }
123 
Write(const char * buf,size_t size)124 bool StreamBuffer::Write(const char *buf, size_t size)
125 {
126     if (ChkRWError()) {
127         FI_HILOGE("Read and write status is error");
128         return false;
129     }
130     if (buf == nullptr) {
131         FI_HILOGE("Invalid input parameter, buf:nullptr, errCode:%{public}d", PARAM_INPUT_INVALID);
132         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
133         return false;
134     }
135     if (size == 0) {
136         FI_HILOGE("Invalid input parameter, size:%{public}zu, errCode:%{public}d", size, PARAM_INPUT_INVALID);
137         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
138         return false;
139     }
140     if (wPos_ + static_cast<int32_t>(size) > MAX_STREAM_BUF_SIZE) {
141         FI_HILOGE("The write length exceeds buffer, wIdx:%{public}d, size:%{public}zu, maxBufSize:%{public}d, "
142             "errCode:%{public}d", wPos_, size, MAX_STREAM_BUF_SIZE, MEM_OUT_OF_BOUNDS);
143         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
144         return false;
145     }
146     errno_t ret = memcpy_sp(&szBuff_[wPos_], GetAvailableBufSize(), buf, size);
147     if (ret != EOK) {
148         FI_HILOGE("Failed to call memcpy_sp, errCode:%{public}d", MEMCPY_SEC_FUN_FAIL);
149         rwErrorStatus_ = ErrorStatus::ERROR_STATUS_WRITE;
150         return false;
151     }
152     wPos_ += static_cast<int32_t>(size);
153     wCount_ += 1;
154     return true;
155 }
156 
empty() const157 bool StreamBuffer::empty() const
158 {
159     return (rPos_ == wPos_);
160 }
161 
Size() const162 size_t StreamBuffer::Size() const
163 {
164     return static_cast<size_t>(wPos_);
165 }
166 
ResidualSize() const167 int32_t StreamBuffer::ResidualSize() const
168 {
169     return ((wPos_ <= rPos_) ? 0 : (wPos_ - rPos_));
170 }
171 
ChkRWError() const172 bool StreamBuffer::ChkRWError() const
173 {
174     return (rwErrorStatus_ != ErrorStatus::ERROR_STATUS_OK);
175 }
176 
GetAvailableBufSize() const177 int32_t StreamBuffer::GetAvailableBufSize() const
178 {
179     return ((wPos_ >= MAX_STREAM_BUF_SIZE) ? 0 : (MAX_STREAM_BUF_SIZE - wPos_));
180 }
181 
GetErrorStatusRemark() const182 const std::string &StreamBuffer::GetErrorStatusRemark() const
183 {
184     static const std::vector<std::pair<ErrorStatus, std::string>> remark {
185         { ErrorStatus::ERROR_STATUS_OK, "OK" },
186         { ErrorStatus::ERROR_STATUS_READ, "READ_ERROR" },
187         { ErrorStatus::ERROR_STATUS_WRITE, "WRITE_ERROR" }
188     };
189     static const std::string invalidStatus { "UNKNOWN" };
190 
191     auto tIter = std::find_if(remark.cbegin(), remark.cend(),
192         [this](const auto &item) {
193             return (item.first == rwErrorStatus_);
194         });
195     return (tIter != remark.cend() ? tIter->second : invalidStatus);
196 }
197 
Data() const198 const char *StreamBuffer::Data() const
199 {
200     return &szBuff_[0];
201 }
202 
ReadBuf() const203 const char *StreamBuffer::ReadBuf() const
204 {
205     return &szBuff_[rPos_];
206 }
207 
Clone(const StreamBuffer & buf)208 bool StreamBuffer::Clone(const StreamBuffer &buf)
209 {
210     Clean();
211     return Write(buf.Data(), buf.Size());
212 }
213 } // namespace Msdp
214 } // namespace OHOS
215