Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
shared_cow_string.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <boost/container/container_fwd.hpp>
4#include <boost/interprocess/offset_ptr.hpp>
5#include <boost/interprocess/allocators/allocator.hpp>
6
7#include <cstddef>
8#include <cstring>
9#include <algorithm>
10#include <string>
11
13
14namespace chainbase {
15
16 namespace bip = boost::interprocess;
17
19 struct impl {
20 uint32_t reference_count;
21 uint32_t size;
22 char data[0];
23 };
24 public:
25 using allocator_type = bip::allocator<char, pinnable_mapped_file::segment_manager>;
26 using iterator = const char*;
27 using const_iterator = const char*;
28 explicit shared_cow_string(const allocator_type& alloc) : _data(nullptr), _alloc(alloc) {}
29 template<typename Iter>
30 explicit shared_cow_string(Iter begin, Iter end, const allocator_type& alloc) : shared_cow_string(alloc) {
31 std::size_t size = std::distance(begin, end);
32 impl* new_data = (impl*)&*_alloc.allocate(sizeof(impl) + size + 1);
33 new_data->reference_count = 1;
34 new_data->size = size;
35 std::copy(begin, end, new_data->data);
36 new_data->data[size] = '\0';
37 _data = new_data;
38 }
39 explicit shared_cow_string(const char* ptr, std::size_t size, const allocator_type& alloc) : shared_cow_string(alloc) {
40 impl* new_data = (impl*)&*_alloc.allocate(sizeof(impl) + size + 1);
41 new_data->reference_count = 1;
42 new_data->size = size;
43 std::memcpy(new_data->data, ptr, size);
44 new_data->data[size] = '\0';
45 _data = new_data;
46 }
47 explicit shared_cow_string(std::size_t size, boost::container::default_init_t, const allocator_type& alloc) : shared_cow_string(alloc) {
48 impl* new_data = (impl*)&*_alloc.allocate(sizeof(impl) + size + 1);
49 new_data->reference_count = 1;
50 new_data->size = size;
51 new_data->data[size] = '\0';
52 _data = new_data;
53 }
54 shared_cow_string(const shared_cow_string& other) : _data(other._data), _alloc(other._alloc) {
55 if(_data != nullptr) {
56 ++_data->reference_count;
57 }
58 }
59 shared_cow_string(shared_cow_string&& other) : _data(other._data), _alloc(other._alloc) {
60 other._data = nullptr;
61 }
63 *this = shared_cow_string{other};
64 return *this;
65 }
67 if (this != &other) {
68 dec_refcount();
69 _data = other._data;
70 other._data = nullptr;
71 }
72 return *this;
73 }
75 dec_refcount();
76 }
77 void resize(std::size_t new_size, boost::container::default_init_t) {
78 impl* new_data = (impl*)&*_alloc.allocate(sizeof(impl) + new_size + 1);
79 new_data->reference_count = 1;
80 new_data->size = new_size;
81 new_data->data[new_size] = '\0';
82 dec_refcount();
83 _data = new_data;
84 }
85 template<typename F>
86 void resize_and_fill(std::size_t new_size, F&& f) {
87 resize(new_size, boost::container::default_init);
88 static_cast<F&&>(f)(_data->data, new_size);
89 }
90 void assign(const char* ptr, std::size_t size) {
91 impl* new_data = (impl*)&*_alloc.allocate(sizeof(impl) + size + 1);
92 new_data->reference_count = 1;
93 new_data->size = size;
94 if(size)
95 std::memcpy(new_data->data, ptr, size);
96 new_data->data[size] = '\0';
97 dec_refcount();
98 _data = new_data;
99 }
100 void assign(const unsigned char* ptr, std::size_t size) {
101 assign((char*)ptr, size);
102 }
103 const char * data() const {
104 if (_data) return _data->data;
105 else return nullptr;
106 }
107 std::size_t size() const {
108 if (_data) return _data->size;
109 else return 0;
110 }
111 const_iterator begin() const { return data(); }
113 if (_data) return _data->data + _data->size;
114 else return nullptr;
115 }
116 int compare(std::size_t start, std::size_t count, const char* other, std::size_t other_size) const {
117 std::size_t sz = size();
118 if(start > sz) BOOST_THROW_EXCEPTION(std::out_of_range{"shared_cow_string::compare"});
119 count = std::min(count, sz - start);
120 std::size_t cmp_len = std::min(count, other_size);
121 const char* start_ptr = data() + start;
122 int result = std::char_traits<char>::compare(start_ptr, other, cmp_len);
123 if (result != 0) return result;
124 else if (count < other_size) return -1;
125 else if(count > other_size) return 1;
126 else return 0;
127 }
128 bool operator==(const shared_cow_string& rhs) const {
129 return size() == rhs.size() && std::memcmp(data(), rhs.data(), size()) == 0;
130 }
131 bool operator!=(const shared_cow_string& rhs) const { return !(*this == rhs); }
132 const allocator_type& get_allocator() const { return _alloc; }
133 private:
134 void dec_refcount() {
135 if(_data && --_data->reference_count == 0) {
136 _alloc.deallocate((char*)&*_data, sizeof(shared_cow_string) + _data->size + 1);
137 }
138 }
139 bip::offset_ptr<impl> _data;
140 allocator_type _alloc;
141 };
142
143} // namepsace chainbase
bool operator==(const shared_cow_string &rhs) const
shared_cow_string & operator=(const shared_cow_string &other)
shared_cow_string(std::size_t size, boost::container::default_init_t, const allocator_type &alloc)
bip::allocator< char, pinnable_mapped_file::segment_manager > allocator_type
shared_cow_string(Iter begin, Iter end, const allocator_type &alloc)
const allocator_type & get_allocator() const
void assign(const unsigned char *ptr, std::size_t size)
shared_cow_string(const shared_cow_string &other)
void resize_and_fill(std::size_t new_size, F &&f)
void assign(const char *ptr, std::size_t size)
shared_cow_string(const char *ptr, std::size_t size, const allocator_type &alloc)
int compare(std::size_t start, std::size_t count, const char *other, std::size_t other_size) const
shared_cow_string(const allocator_type &alloc)
void resize(std::size_t new_size, boost::container::default_init_t)
shared_cow_string & operator=(shared_cow_string &&other)
bool operator!=(const shared_cow_string &rhs) const
shared_cow_string(shared_cow_string &&other)
int * count
unsigned int uint32_t
Definition stdint.h:126