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