1 
2 
3 /*
4 A* -------------------------------------------------------------------
5 B* This file contains source code for the PyMOL computer program
6 C* Copyright (c) Schrodinger, LLC.
7 D* -------------------------------------------------------------------
8 E* It is unlawful to modify or remove this copyright notice.
9 F* -------------------------------------------------------------------
10 G* Please see the accompanying LICENSE file for further information.
11 H* -------------------------------------------------------------------
12 I* Additional authors of this source file include:
13 -*
14 -*
15 -*
16 Z* -------------------------------------------------------------------
17 */
18 #ifndef _H_MemoryDebug
19 #define _H_MemoryDebug
20 
21 #include <vector>
22 
23 #include "os_std.h"
24 #include "PyMOLGlobals.h"
25 
26 
27 /* ================================================================
28  * Don't touch below unless you know what you are doing */
29 
30 typedef struct VLARec {
31   ov_size size, unit_size;
32   float grow_factor;
33   bool auto_zero;
34 } VLARec;
35 
36 
37 /* NOTE: in VLACheck, rec is a zero based array index, not a record count */
38 #define VLACheck(ptr,type,rec) VLACheck2<type>(ptr, rec)
39 
40 #define VLAlloc(type,init_size) (type*)VLAMalloc(init_size,sizeof(type),5,0)
41 #define VLACalloc(type,init_size) (type*)VLAMalloc(init_size,sizeof(type),5,1)
42 #define VLASize(ptr,type,size) VLASize2<type>(ptr,size)
43 #define VLASizeForSure(ptr,type,size) VLASizeForSure2<type>(ptr,size)
44 
45 #define VLACopy(ptr,type) (type*)VLANewCopy(ptr);
46 #define VLAInsert(ptr,type,index,count) {ptr=(type*)VLAInsertRaw(ptr,index,count);}
47 #define VLADelete(ptr,type,index,count) {ptr=(type*)VLADeleteRaw(ptr,index,count);}
48 
49 namespace pymol
50 {
51 using ::free;
52 
53 struct default_free {
operatordefault_free54   void operator()(void* ptr) const { free(ptr); }
55 };
56 
malloc(size_t num)57 template <typename T> T* malloc(size_t num)
58 {
59   return (T*) ::malloc(num * sizeof(T));
60 }
61 
calloc(size_t num)62 template <typename T> T* calloc(size_t num)
63 {
64   return (T*) ::calloc(num, sizeof(T));
65 }
66 
realloc(T * ptr,size_t num)67 template <typename T> T* realloc(T* ptr, size_t num)
68 {
69   return (T*) ::realloc(ptr, num * sizeof(T));
70 }
71 } // namespace pymol
72 
73 #define FreeP(ptr) {if(ptr) {mfree(ptr);ptr=NULL;}}
74 #define DeleteP(ptr) {if(ptr) {delete ptr;ptr=NULL;}}
75 #define DeleteAP(ptr) {if(ptr) {delete[] ptr;ptr=NULL;}}
76 
77 void *VLAExpand(void *ptr, ov_size rec);        /* NOTE: rec is index (total-1) */
78 void *MemoryReallocForSure(void *ptr, size_t newSize);
79 void *MemoryReallocForSureSafe(void *ptr, size_t newSize, size_t oldSize);
80 
81 void *VLADeleteRaw(void *ptr, int index, unsigned int count);
82 void *VLAInsertRaw(void *ptr, int index, unsigned int count);
83 
84 void *VLAMalloc(ov_size init_size, ov_size unit_size, unsigned int grow_factor, int auto_zero); /*growfactor 1-10 */
85 
86 void VLAFree(void *ptr);
87 void *VLASetSize(void *ptr, size_t newSize);
88 void *VLASetSizeForSure(void *ptr, size_t newSize);
89 
90 size_t VLAGetSize(const void *ptr);
91 void *VLANewCopy(const void *ptr);
92 void MemoryZero(char *p, char *q);
93 
94 
95 #define mfree pymol::free
96 #define mstrdup strdup
97 #define ReallocForSure(ptr,type,size) (type*)MemoryReallocForSure(ptr,sizeof(type)*(size))
98 
99 
VLAGetByteSize(const void * ptr)100 inline size_t VLAGetByteSize(const void *ptr) {
101   const VLARec *vla = ((const VLARec *) ptr) - 1;
102   return vla->size * vla->unit_size;
103 }
104 
105 /*
106  * Templated version of the `VLACopy` macro
107  */
108 template <typename T>
VLACopy2(const T * vla)109 T * VLACopy2(const T * vla) {
110   return VLACopy((void*)vla, T);
111 }
112 
113 /*
114  * @brief std::vector version of VLACheck. Checks to see if index i is valid for insertion.
115  *        If not, a resize will be attempted.
116  * @param vec: vector whose size will be check for valid insertion at index i
117  * @param i: index for position where an element may be inserted into vec
118  * Note: Use of this function should be limited. Used for safe replacement of VLACheck
119  * Note: This function can throw.
120  */
121 template <typename T>
VecCheck(std::vector<T> & vec,std::size_t i)122 void VecCheck(std::vector<T> &vec, std::size_t i){
123   if(i >= vec.size()){
124     vec.resize(i + 1);
125   }
126 }
127 
128 /**
129  * @brief Similar to VecCheck but constructs objects with arguments. Useful when
130  * no default constructor available.
131  * @tparam T type of elements in vector and also created during resize
132  * @tparam Ts types of T's constructor arguments
133  * @param vec: vector whose size will be check for valid insertion at index i
134  * @param i: index for position where an element may be inserted into vec
135  * @param args: constructor arguments of T
136  */
137 template <typename T, typename... Ts>
VecCheckEmplace(std::vector<T> & vec,std::size_t i,Ts...args)138 void VecCheckEmplace(std::vector<T>& vec, std::size_t i, Ts... args)
139 {
140   vec.reserve(i + 1);
141   for (auto s = vec.size(); s <= i; s++) {
142     vec.emplace_back(args...);
143   }
144 }
145 
146 template <typename T>
VLACheck2(T * & ptr,size_t pos)147 T* VLACheck2(T*& ptr, size_t pos) {
148   if (pos >= ((VLARec*) ptr)[-1].size) {
149     ptr = static_cast<T*>(VLAExpand(ptr, pos));
150   }
151   return ptr;
152 }
153 
154 template <typename T>
VLASize2(T * & ptr,size_t size)155 void VLASize2(T*& ptr, size_t size) {
156   ptr = static_cast<T*>(VLASetSize(ptr, size));
157 }
158 
159 template <typename T>
VLASizeForSure2(T * & ptr,size_t size)160 void VLASizeForSure2(T*& ptr, size_t size) {
161   ptr = static_cast<T*>(VLASetSizeForSure(ptr, size));
162 }
163 
164 template <typename T>
VLAFreeP(T * & ptr)165 void VLAFreeP(T*& ptr) {
166   if (ptr) {
167     VLAFree(ptr);
168     ptr = nullptr;
169   }
170 }
171 
172 #endif
173 
174 // vi:sw=2:expandtab
175