1 /**
2 * Copyright (c) 2014, Timothy Stack
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of Timothy Stack nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @file shared_buffer.hh
30 */
31
32 #ifndef shared_buffer_hh
33 #define shared_buffer_hh
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38
39 #include <string>
40 #include <vector>
41
42 #include "auto_mem.hh"
43 #include "base/lnav_log.hh"
44
45 class shared_buffer;
46
47 struct shared_buffer_ref {
48 public:
shared_buffer_refshared_buffer_ref49 shared_buffer_ref(char *data = nullptr, size_t len = 0)
50 : sb_owner(nullptr), sb_data(data), sb_length(len) {
51 };
52
~shared_buffer_refshared_buffer_ref53 ~shared_buffer_ref() {
54 this->disown();
55 };
56
shared_buffer_refshared_buffer_ref57 shared_buffer_ref(const shared_buffer_ref &other) {
58 this->sb_owner = nullptr;
59 this->sb_data = nullptr;
60 this->sb_length = 0;
61
62 this->copy_ref(other);
63 };
64
65 shared_buffer_ref(shared_buffer_ref &&other) noexcept;
66
operator =shared_buffer_ref67 shared_buffer_ref &operator=(const shared_buffer_ref &other) {
68 if (this != &other) {
69 this->disown();
70 this->copy_ref(other);
71 }
72
73 return *this;
74 };
75
emptyshared_buffer_ref76 bool empty() const {
77 return this->sb_data == nullptr || this->sb_length == 0;
78 };
79
get_datashared_buffer_ref80 const char *get_data() const { return this->sb_data; };
81
get_data_atshared_buffer_ref82 const char *get_data_at(off_t offset) const {
83 return &this->sb_data[offset];
84 };
85
lengthshared_buffer_ref86 size_t length() const { return this->sb_length; };
87
rtrimshared_buffer_ref88 shared_buffer_ref &rtrim(bool pred(char)) {
89 while (this->sb_length > 0 && pred(this->sb_data[this->sb_length - 1])) {
90 this->sb_length -= 1;
91 }
92
93 return *this;
94 }
95
containsshared_buffer_ref96 bool contains(const char *ptr) const {
97 const char *buffer_end = this->sb_data + this->sb_length;
98
99 return (this->sb_data <= ptr && ptr < buffer_end);
100 };
101
get_writable_datashared_buffer_ref102 char *get_writable_data() {
103 if (this->take_ownership()) {
104 return this->sb_data;
105 }
106
107 return nullptr;
108 };
109
110 void share(shared_buffer &sb, char *data, size_t len);
111
112 bool subset(shared_buffer_ref &other, off_t offset, size_t len);
113
114 bool take_ownership();
115
116 void disown();
117
118 private:
119 void copy_ref(const shared_buffer_ref &other);
120
121 auto_mem<char *> sb_backtrace;
122 shared_buffer *sb_owner;
123 char *sb_data;
124 size_t sb_length;
125 };
126
127 class shared_buffer {
128 public:
~shared_buffer()129 ~shared_buffer() {
130 this->invalidate_refs();
131 }
132
add_ref(shared_buffer_ref & ref)133 void add_ref(shared_buffer_ref &ref) {
134 this->sb_refs.push_back(&ref);
135 };
136
invalidate_refs()137 bool invalidate_refs() {
138 bool retval = true;
139
140 while (!this->sb_refs.empty()) {
141 auto iter = this->sb_refs.begin();
142
143 retval = retval && (*iter)->take_ownership();
144 }
145
146 return retval;
147 };
148
149 std::vector<shared_buffer_ref*> sb_refs;
150 };
151
152 struct tmp_shared_buffer {
tmp_shared_buffertmp_shared_buffer153 explicit tmp_shared_buffer(const char *str, size_t len = -1) {
154 if (len == (size_t)-1) {
155 len = strlen(str);
156 }
157
158 this->tsb_ref.share(this->tsb_manager, (char *)str, len);
159 };
160
161 shared_buffer tsb_manager;
162 shared_buffer_ref tsb_ref;
163 };
164
to_string(const shared_buffer_ref & sbr)165 inline std::string to_string(const shared_buffer_ref &sbr)
166 {
167 return {sbr.get_data(), sbr.length()};
168 }
169
170 #endif
171