unilink  0.4.3
A simple C++ library for unified async communication
safe_data_buffer.cc
Go to the documentation of this file.
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 
18 
19 #include <algorithm>
20 #include <cstring>
21 
22 namespace unilink {
23 namespace memory {
24 
25 // Constructors
26 SafeDataBuffer::SafeDataBuffer(const std::string& data) : data_(data.begin(), data.end()) {
27  validate_construction(data.data(), data.size());
28 }
29 
30 SafeDataBuffer::SafeDataBuffer(std::string_view data) : data_(data.begin(), data.end()) {
31  validate_construction(data.data(), data.size());
32 }
33 
34 SafeDataBuffer::SafeDataBuffer(std::vector<uint8_t> data) : data_(std::move(data)) {
35  // No validation needed for moved vector
36 }
37 
38 SafeDataBuffer::SafeDataBuffer(const uint8_t* data, size_t size) {
39  validate_construction(data, size);
40  if (data && size > 0) {
41  data_.assign(data, data + size);
42  }
43 }
44 
45 SafeDataBuffer::SafeDataBuffer(const char* data, size_t size) {
46  validate_construction(data, size);
47  if (data && size > 0) {
48  data_.assign(reinterpret_cast<const uint8_t*>(data), reinterpret_cast<const uint8_t*>(data) + size);
49  }
50 }
51 
53  validate_construction(span.data(), span.size());
54  if (span.data() && span.size() > 0) {
55  data_.assign(span.begin(), span.end());
56  }
57 }
58 
59 // Access methods
60 std::string SafeDataBuffer::as_string() const { return std::string(data_.begin(), data_.end()); }
61 
62 ConstByteSpan SafeDataBuffer::as_span() const noexcept { return ConstByteSpan(data_.data(), data_.size()); }
63 
64 const uint8_t* SafeDataBuffer::data() const noexcept { return data_.data(); }
65 
66 size_t SafeDataBuffer::size() const noexcept { return data_.size(); }
67 
68 bool SafeDataBuffer::empty() const noexcept { return data_.empty(); }
69 
70 // Safe element access
71 const uint8_t& SafeDataBuffer::operator[](size_t index) const {
72  validate_index(index);
73  return data_[index];
74 }
75 
76 const uint8_t& SafeDataBuffer::at(size_t index) const {
77  validate_index(index);
78  return data_.at(index);
79 }
80 
81 // Comparison operators
82 bool SafeDataBuffer::operator==(const SafeDataBuffer& other) const noexcept { return data_ == other.data_; }
83 
84 bool SafeDataBuffer::operator!=(const SafeDataBuffer& other) const noexcept { return data_ != other.data_; }
85 
86 // Utility methods
87 void SafeDataBuffer::clear() noexcept { data_.clear(); }
88 
89 void SafeDataBuffer::reserve(size_t capacity) { data_.reserve(capacity); }
90 
91 void SafeDataBuffer::resize(size_t new_size) { data_.resize(new_size); }
92 
93 // Validation
94 bool SafeDataBuffer::is_valid() const noexcept {
95  return true; // Always valid after construction
96 }
97 
99  // Additional validation can be added here
100  if (data_.size() > 1024 * 1024 * 100) { // 100MB limit
101  throw std::runtime_error("Buffer size exceeds maximum allowed size");
102  }
103 }
104 
105 // Private helper methods
106 void SafeDataBuffer::validate_index(size_t index) const {
107  if (index >= data_.size()) {
108  throw std::out_of_range("Index " + std::to_string(index) + " is out of range for buffer of size " +
109  std::to_string(data_.size()));
110  }
111 }
112 
113 void SafeDataBuffer::validate_construction(const void* ptr, size_t size) const {
114  if (size > 0 && !ptr) {
115  throw std::invalid_argument("Cannot construct buffer from null pointer with non-zero size");
116  }
117  if (size > 1024 * 1024 * 100) { // 100MB limit
118  throw std::invalid_argument("Buffer size exceeds maximum allowed size");
119  }
120 }
121 
122 // Factory functions
123 namespace safe_buffer_factory {
124 
125 SafeDataBuffer from_string(const std::string& str) { return SafeDataBuffer(str); }
126 
127 SafeDataBuffer from_c_string(const char* str) {
128  if (!str) {
129  return SafeDataBuffer(std::vector<uint8_t>{});
130  }
131  return SafeDataBuffer(str, std::strlen(str));
132 }
133 
134 SafeDataBuffer from_vector(const std::vector<uint8_t>& vec) { return SafeDataBuffer(vec); }
135 
136 SafeDataBuffer from_raw_data(const uint8_t* data, size_t size) { return SafeDataBuffer(data, size); }
137 
139 
140 } // namespace safe_buffer_factory
141 
142 } // namespace memory
143 } // namespace unilink