1 /** 2 * Copyright (c) 2007-2019, 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 auto_mem.hh 30 */ 31 32 #ifndef lnav_auto_mem_hh 33 #define lnav_auto_mem_hh 34 35 #include <string.h> 36 #include <unistd.h> 37 #include <stdlib.h> 38 39 #include <exception> 40 41 #include "base/result.h" 42 43 typedef void (*free_func_t)(void *); 44 45 /** 46 * Resource management class for memory allocated by a custom allocator. 47 * 48 * @param T The object type. 49 * @param auto_free The function to call to free the managed object. 50 */ 51 template<class T, free_func_t default_free = free> 52 class auto_mem { 53 public: auto_mem(T * ptr=nullptr)54 explicit auto_mem(T *ptr = nullptr) 55 : am_ptr(ptr), am_free_func(default_free) { 56 }; 57 58 auto_mem(const auto_mem &am) = delete; 59 60 template<typename F> auto_mem(F free_func)61 explicit auto_mem(F free_func) noexcept 62 : am_ptr(nullptr), am_free_func((free_func_t)free_func) { }; 63 auto_mem(auto_mem && other)64 auto_mem(auto_mem &&other) noexcept 65 : am_ptr(other.release()), 66 am_free_func(other.am_free_func) { 67 }; 68 ~auto_mem()69 ~auto_mem() { 70 this->reset(); 71 }; 72 operator T*() const73 operator T *() const { return this->am_ptr; }; 74 operator =(T * ptr)75 auto_mem &operator =(T *ptr) 76 { 77 this->reset(ptr); 78 return *this; 79 }; 80 81 auto_mem &operator=(auto_mem &) = delete; 82 operator =(auto_mem && am)83 auto_mem &operator =(auto_mem && am) noexcept 84 { 85 this->reset(am.release()); 86 this->am_free_func = am.am_free_func; 87 return *this; 88 }; 89 release()90 T *release() 91 { 92 T *retval = this->am_ptr; 93 94 this->am_ptr = nullptr; 95 return retval; 96 }; 97 in() const98 T *in() const 99 { 100 return this->am_ptr; 101 }; 102 out()103 T **out() 104 { 105 this->reset(); 106 return &this->am_ptr; 107 }; 108 reset(T * ptr=nullptr)109 void reset(T *ptr = nullptr) 110 { 111 if (this->am_ptr != ptr) { 112 if (this->am_ptr != nullptr) { 113 this->am_free_func((void *)this->am_ptr); 114 } 115 this->am_ptr = ptr; 116 } 117 }; 118 119 private: 120 T * am_ptr; 121 void (*am_free_func)(void *); 122 }; 123 124 template<typename T, void(*free_func) (T *)> 125 class static_root_mem { 126 public: static_root_mem()127 static_root_mem() { 128 memset(&this->srm_value, 0, sizeof(T)); 129 }; 130 ~static_root_mem()131 ~static_root_mem() { free_func(&this->srm_value); }; 132 operator ->() const133 const T *operator->() const { return &this->srm_value; }; 134 in() const135 const T &in() const { return this->srm_value; }; 136 inout()137 T *inout() { 138 free_func(&this->srm_value); 139 memset(&this->srm_value, 0, sizeof(T)); 140 return &this->srm_value; 141 }; 142 143 private: operator =(T &)144 static_root_mem &operator =(T &) { return *this; }; 145 operator =(static_root_mem &)146 static_root_mem &operator =(static_root_mem &) { return *this; }; 147 148 T srm_value; 149 }; 150 151 class auto_buffer { 152 public: alloc(size_t size)153 static auto_buffer alloc(size_t size) { 154 return auto_buffer{ (char *) malloc(size), size }; 155 } 156 auto_buffer(auto_buffer && other)157 auto_buffer(auto_buffer&& other) noexcept 158 : ab_buffer(other.ab_buffer), ab_size(other.ab_size) { 159 other.ab_buffer = nullptr; 160 other.ab_size = 0; 161 } 162 ~auto_buffer()163 ~auto_buffer() { 164 free(this->ab_buffer); 165 this->ab_buffer = nullptr; 166 this->ab_size = 0; 167 } 168 in()169 char *in() { 170 return this->ab_buffer; 171 } 172 release()173 std::pair<char *, size_t> release() { 174 auto retval = std::make_pair(this->ab_buffer, this->ab_size); 175 176 this->ab_buffer = nullptr; 177 this->ab_size = 0; 178 return retval; 179 } 180 size() const181 size_t size() const { 182 return this->ab_size; 183 } 184 expand_by(size_t amount)185 void expand_by(size_t amount) { 186 if (amount == 0) { 187 return; 188 } 189 auto new_size = this->ab_size + amount; 190 auto new_buffer = (char *) realloc(this->ab_buffer, new_size); 191 192 if (new_buffer == nullptr) { 193 throw std::bad_alloc(); 194 } 195 196 this->ab_buffer = new_buffer; 197 this->ab_size = new_size; 198 } 199 shrink_to(size_t new_size)200 auto_buffer& shrink_to(size_t new_size) { 201 this->ab_size = new_size; 202 return *this; 203 } 204 private: auto_buffer(char * buffer,size_t size)205 auto_buffer(char *buffer, size_t size) : ab_buffer(buffer), ab_size(size) { 206 } 207 208 char *ab_buffer; 209 size_t ab_size; 210 }; 211 212 struct text_auto_buffer { 213 auto_buffer inner; 214 }; 215 216 struct blob_auto_buffer { 217 auto_buffer inner; 218 }; 219 220 #endif 221