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 22namespace OHOS { 23namespace MMI { 24StreamBuffer::StreamBuffer(const StreamBuffer &buf) 25{ 26 Clone(buf); 27} 28 29StreamBuffer &StreamBuffer::operator=(const StreamBuffer &other) 30{ 31 Clone(other); 32 return *this; 33} 34 35void StreamBuffer::Reset() 36{ 37 rPos_ = 0; 38 wPos_ = 0; 39 rCount_ = 0; 40 wCount_ = 0; 41 rwErrorStatus_ = ErrorStatus::ERROR_STATUS_OK; 42} 43 44void 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 54bool 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 66bool 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 78bool StreamBuffer::Write(const std::string &buf) 79{ 80 return Write(buf.c_str(), buf.length()+1); 81} 82 83bool StreamBuffer::Read(StreamBuffer &buf) 84{ 85 return buf.Write(Data(), Size()); 86} 87 88bool StreamBuffer::Write(const StreamBuffer &buf) 89{ 90 return Write(buf.Data(), buf.Size()); 91} 92 93bool 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 124bool 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 156bool StreamBuffer::IsEmpty() const 157{ 158 return (rPos_ == wPos_); 159} 160 161size_t StreamBuffer::Size() const 162{ 163 return static_cast<size_t>(wPos_); 164} 165 166int32_t StreamBuffer::UnreadSize() const 167{ 168 return ((wPos_ <= rPos_) ? 0 : (wPos_ - rPos_)); 169} 170 171int32_t StreamBuffer::GetAvailableBufSize() const 172{ 173 return ((wPos_ >= MAX_STREAM_BUF_SIZE) ? 0 : (MAX_STREAM_BUF_SIZE - wPos_)); 174} 175 176bool StreamBuffer::ChkRWError() const 177{ 178 return (rwErrorStatus_ != ErrorStatus::ERROR_STATUS_OK); 179} 180 181const 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 197const char *StreamBuffer::Data() const 198{ 199 return &szBuff_[0]; 200} 201 202const char *StreamBuffer::ReadBuf() const 203{ 204 return &szBuff_[rPos_]; 205} 206 207const char *StreamBuffer::WriteBuf() const 208{ 209 return &szBuff_[wPos_]; 210} 211 212bool StreamBuffer::Clone(const StreamBuffer &buf) 213{ 214 Clean(); 215 return Write(buf.Data(), buf.Size()); 216} 217} // namespace MMI 218} // namespace OHOS 219