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 #ifndef LIBPANDABASE_UTILS_BIT_MEMORY_STREAM_H 17 #define LIBPANDABASE_UTILS_BIT_MEMORY_STREAM_H 18 19 #include "utils/bit_memory_region.h" 20 #include "utils/bit_utils.h" 21 22 #include <array> 23 #include <ios> 24 25 namespace panda { 26 27 template <typename Container> 28 class BitMemoryStreamOut { 29 public: BitMemoryStreamOut(Container * data)30 explicit BitMemoryStreamOut(Container *data) : BitMemoryStreamOut(data, 0) {} BitMemoryStreamOut(Container * data,size_t offset)31 BitMemoryStreamOut(Container *data, size_t offset) : data_(data), offset_(offset) {} 32 EnsureSpace(size_t length)33 void EnsureSpace(size_t length) 34 { 35 data_->resize(RoundUp(BitsToBytesRoundUp(offset_ + length), sizeof(uint32_t))); 36 } 37 Write(size_t value,size_t length)38 void Write(size_t value, size_t length) 39 { 40 if (length != 0) { 41 ASSERT(length <= (sizeof(value) * BITS_PER_BYTE)); 42 EnsureSpace(length); 43 BitMemoryRegion region(data_->data(), offset_, length); 44 region.Write(value, 0, length); 45 offset_ += length; 46 } 47 } 48 Write(uint32_t * ptr,size_t payload_length,size_t length)49 void Write(uint32_t *ptr, size_t payload_length, size_t length) 50 { 51 ASSERT(payload_length <= length); 52 if (payload_length != 0) { 53 static constexpr size_t bits_per_word = BITS_PER_UINT32; 54 EnsureSpace(length); 55 BitMemoryRegion region(data_->data(), offset_, length); 56 size_t i = 0; 57 for (; i < payload_length / bits_per_word; i++) { 58 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 59 region.Write(ptr[i], i * bits_per_word, bits_per_word); 60 } 61 size_t remaining_size = payload_length % bits_per_word; 62 if (remaining_size != 0) { 63 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 64 region.Write(ptr[i], i * bits_per_word, payload_length % bits_per_word); 65 } 66 } 67 offset_ += length; 68 } 69 70 virtual ~BitMemoryStreamOut() = default; 71 72 NO_COPY_SEMANTIC(BitMemoryStreamOut); 73 NO_MOVE_SEMANTIC(BitMemoryStreamOut); 74 75 private: 76 Container *data_ {nullptr}; 77 size_t offset_ {0}; 78 }; 79 80 class BitMemoryStreamIn : private BitMemoryRegion<const uint8_t> { 81 public: 82 using BitMemoryRegion::BitMemoryRegion; 83 BitMemoryStreamIn(const uint8_t * data)84 explicit BitMemoryStreamIn(const uint8_t *data) 85 : BitMemoryRegion<const uint8_t>(data, std::numeric_limits<uint32_t>::max()) 86 { 87 } 88 89 template <typename T> Read(size_t length)90 T Read(size_t length) 91 { 92 ASSERT(length <= (sizeof(T) * BITS_PER_BYTE)); 93 T res = BitMemoryRegion::Read<T>(0, length); 94 Advance(length); 95 return res; 96 } 97 ReadRegion(size_t length)98 BitMemoryRegion ReadRegion(size_t length) 99 { 100 auto res = Subregion(0, length); 101 Advance(length); 102 return res; 103 } 104 105 ~BitMemoryStreamIn() override = default; 106 107 NO_COPY_SEMANTIC(BitMemoryStreamIn); 108 NO_MOVE_SEMANTIC(BitMemoryStreamIn); 109 }; 110 111 } // namespace panda 112 113 #endif // LIBPANDABASE_UTILS_BIT_MEMORY_STREAM_H 114