Branch data Line data Source code
1 : : /*
2 : : * Copyright 2025 Jinwoo Sung
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #include "wirestead/memory/safe_data_buffer.hpp"
18 : :
19 : : #include <spdlog/fmt/fmt.h>
20 : :
21 : : #include <algorithm>
22 : : #include <cstring>
23 : :
24 : : namespace wirestead {
25 : : namespace memory {
26 : :
27 : : // Constructors
28 : 8 : SafeDataBuffer::SafeDataBuffer(const std::string& data) : data_(data.begin(), data.end()) {
29 : 4 : validate_construction(data.data(), data.size());
30 : 4 : }
31 : :
32 : 0 : SafeDataBuffer::SafeDataBuffer(std::string_view data) : data_(data.begin(), data.end()) {
33 : 0 : validate_construction(data.data(), data.size());
34 : 0 : }
35 : :
36 : 5 : SafeDataBuffer::SafeDataBuffer(std::vector<uint8_t> data) : data_(std::move(data)) {
37 : : // No validation needed for moved vector
38 : 5 : }
39 : :
40 : 3 : SafeDataBuffer::SafeDataBuffer(const uint8_t* data, size_t size) {
41 : 3 : validate_construction(data, size);
42 [ + - + - ]: 1 : if (data && size > 0) {
43 : 1 : data_.assign(data, data + size);
44 : : }
45 : 3 : }
46 : :
47 : 2 : SafeDataBuffer::SafeDataBuffer(const char* data, size_t size) {
48 : 2 : validate_construction(data, size);
49 [ + - + - ]: 1 : if (data && size > 0) {
50 : 1 : data_.assign(reinterpret_cast<const uint8_t*>(data), reinterpret_cast<const uint8_t*>(data) + size);
51 : : }
52 : 2 : }
53 : :
54 : 158 : SafeDataBuffer::SafeDataBuffer(ConstByteSpan span) {
55 : 158 : validate_construction(span.data(), span.size());
56 [ + + + - : 158 : if (span.data() && span.size() > 0) {
+ + ]
57 : 156 : data_.assign(span.begin(), span.end());
58 : : }
59 : 158 : }
60 : :
61 : : // Access methods
62 : 21 : std::string SafeDataBuffer::as_string() const { return std::string(data_.begin(), data_.end()); }
63 : :
64 : 0 : ConstByteSpan SafeDataBuffer::as_span() const noexcept { return ConstByteSpan(data_.data(), data_.size()); }
65 : :
66 : 56 : const uint8_t* SafeDataBuffer::data() const noexcept { return data_.data(); }
67 : :
68 : 65 : size_t SafeDataBuffer::size() const noexcept { return data_.size(); }
69 : :
70 : 4 : bool SafeDataBuffer::empty() const noexcept { return data_.empty(); }
71 : :
72 : : // Safe element access
73 : 1029 : const uint8_t& SafeDataBuffer::operator[](size_t index) const {
74 : 1029 : validate_index(index);
75 : 1027 : return data_[index];
76 : : }
77 : :
78 : 2 : const uint8_t& SafeDataBuffer::at(size_t index) const {
79 : 2 : validate_index(index);
80 : 1 : return data_.at(index);
81 : : }
82 : :
83 : : // Comparison operators
84 : 1 : bool SafeDataBuffer::operator==(const SafeDataBuffer& other) const noexcept { return data_ == other.data_; }
85 : :
86 : 1 : bool SafeDataBuffer::operator!=(const SafeDataBuffer& other) const noexcept { return data_ != other.data_; }
87 : :
88 : : // Utility methods
89 : 1 : void SafeDataBuffer::clear() noexcept { data_.clear(); }
90 : :
91 : 1 : void SafeDataBuffer::reserve(size_t capacity) { data_.reserve(capacity); }
92 : :
93 : 1 : void SafeDataBuffer::resize(size_t new_size) { data_.resize(new_size); }
94 : :
95 : : // Validation
96 : 1 : bool SafeDataBuffer::valid() const noexcept {
97 : 1 : return true; // Always valid after construction
98 : : }
99 : :
100 : 1 : void SafeDataBuffer::validate() const {
101 : : // Additional validation can be added here
102 [ - + ]: 1 : if (data_.size() > 1024 * 1024 * 100) { // 100MB limit
103 : 0 : throw std::runtime_error("Buffer size exceeds maximum allowed size");
104 : : }
105 : 1 : }
106 : :
107 : : // Private helper methods
108 : 1031 : void SafeDataBuffer::validate_index(size_t index) const {
109 [ + + ]: 1031 : if (index >= data_.size()) {
110 : 3 : throw std::out_of_range(fmt::format("Index {} is out of range for buffer of size {}", index, data_.size()));
111 : : }
112 : 1028 : }
113 : :
114 : 167 : void SafeDataBuffer::validate_construction(const void* ptr, size_t size) const {
115 [ + + + + ]: 167 : if (size > 0 && !ptr) {
116 : 2 : throw std::invalid_argument("Cannot construct buffer from null pointer with non-zero size");
117 : : }
118 [ + + ]: 165 : if (size > 1024 * 1024 * 100) { // 100MB limit
119 : 1 : throw std::invalid_argument("Buffer size exceeds maximum allowed size");
120 : : }
121 : 164 : }
122 : :
123 : : // Factory functions
124 : : namespace safe_buffer_factory {
125 : :
126 : 1 : SafeDataBuffer from_string(const std::string& str) { return SafeDataBuffer(str); }
127 : :
128 : 2 : SafeDataBuffer from_c_string(const char* str) {
129 [ + + ]: 2 : if (!str) {
130 : 1 : return SafeDataBuffer(std::vector<uint8_t>{});
131 : : }
132 : 1 : return SafeDataBuffer(str, std::strlen(str));
133 : : }
134 : :
135 : 1 : SafeDataBuffer from_vector(const std::vector<uint8_t>& vec) { return SafeDataBuffer(vec); }
136 : :
137 : 1 : SafeDataBuffer from_raw_data(const uint8_t* data, size_t size) { return SafeDataBuffer(data, size); }
138 : :
139 : 1 : SafeDataBuffer from_span(ConstByteSpan span) { return SafeDataBuffer(span); }
140 : :
141 : : } // namespace safe_buffer_factory
142 : :
143 : : } // namespace memory
144 : : } // namespace wirestead
|