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