1 #ifndef JSON_MEMORY_H
2 #define JSON_MEMORY_H
3 
4 #include <cstdlib> //for malloc, realloc, and free
5 #include <cstring> //for memmove
6 #include "JSONDebug.h"
7 
8 #if defined(JSON_DEBUG) || defined(JSON_SAFE)
9     #define JSON_FREE_PASSTYPE &
10 #else
11     #define JSON_FREE_PASSTYPE
12 #endif
13 
14 #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
15     class JSONMemory {
16     public:
17 		  static void * json_malloc(size_t siz) json_malloc_attr;
18 	      static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
19 	   static void json_free(void * ptr) json_nothrow;
20 	   static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
21     private:
22         JSONMemory(void);
23     };
24 
25     template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
json_malloc(size_t count)26     template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
27 	   return (T *)JSONMemory::json_malloc(sizeof(T) * count);
28     }
29 
30     template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
json_realloc(T * ptr,size_t count)31     template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
32        return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
33     }
34 
libjson_free(T * JSON_FREE_PASSTYPE ptr)35     template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
36 	   JSONMemory::json_free(ptr);
37 	   #if defined(JSON_DEBUG) || defined(JSON_SAFE)  //in debug or safe mode, set the pointer to 0 so that it can't be used again
38 		  ptr = 0;
39 	   #endif
40     }
41 #else
42 
43     template <typename T> static inline T * json_malloc(size_t count) json_malloc_attr;
json_malloc(size_t count)44     template <typename T> static inline T * json_malloc(size_t count) json_nothrow {
45 	   #ifdef JSON_DEBUG  //in debug mode, see if the malloc was successful
46 		  void * result = std::malloc(count * sizeof(T));
47 		  JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
48 		  #ifdef JSON_NULL_MEMORY
49 			 std::memset(result, '\0', count  * sizeof(T));
50 		  #endif
51 		  return (T *)result;
52 	   #else
53 		  return (T *)std::malloc(count * sizeof(T));
54 	   #endif
55     }
56 
libjson_free(T * JSON_FREE_PASSTYPE ptr)57     template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
58 	   std::free(ptr);
59 	   #if defined(JSON_DEBUG) || defined(JSON_SAFE)  //in debug or safe mode, set the pointer to 0 so that it can't be used again
60 		  ptr = 0;
61 	   #endif
62     }
63 
64     template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
json_realloc(T * ptr,size_t count)65     template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
66 	   #ifdef JSON_DEBUG  //in debug mode, check the results of realloc to be sure it was successful
67 		  void * result = std::realloc(ptr, count * sizeof(T));
68 		  JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
69 		  return (T *)result;
70 	   #else
71 		  return (T *)std::realloc(ptr, count * sizeof(T));
72 	   #endif
73     }
74 #endif
75 
76 #ifdef JSON_MEMORY_MANAGE
77     #include <map>
78     class JSONNode;
79     struct auto_expand {
80     public:
81 		LIBJSON_OBJECT(auto_expand);
auto_expandauto_expand82 	   auto_expand(void) json_nothrow : mymap(){ LIBJSON_CTOR;}
~auto_expandauto_expand83 	   ~auto_expand(void) json_nothrow { purge(); LIBJSON_DTOR; }
84 	   void purge(void) json_nothrow;
clearauto_expand85 	   inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand86 	   inline void * insert(void * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand87 	   inline void remove(void * ptr) json_nothrow {
88 		  JSON_MAP(void *, void *)::iterator i = mymap.find(ptr);
89 		  JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
90 		  mymap.erase(i);
91 	   }
92 	   JSON_MAP(void *, void *) mymap;
93     private:
94         auto_expand(const auto_expand &);
95         auto_expand & operator = (const auto_expand &);
96     };
97 
98     struct auto_expand_node {
99     public:
100 		LIBJSON_OBJECT(auto_expand_node);
auto_expand_nodeauto_expand_node101 	   auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_nodeauto_expand_node102 	   ~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
103 	   void purge(void) json_nothrow ;
clearauto_expand_node104 	   inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand_node105 	   inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand_node106 	   inline void remove(void * ptr) json_nothrow {
107 		  JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
108 		  if(json_likely(i != mymap.end())) mymap.erase(i);
109 	   }
110 	   JSON_MAP(void *, JSONNode *) mymap;
111     private:
112         auto_expand_node(const auto_expand_node &);
113         auto_expand_node & operator = (const auto_expand_node &);
114     };
115 
116     #ifdef JSON_STREAM
117 	   class JSONStream;
118 	   struct auto_expand_stream {
119         public:
120 			LIBJSON_OBJECT(auto_expand_stream);
auto_expand_streamauto_expand_stream121 		  auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
~auto_expand_streamauto_expand_stream122 		  ~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
123 		  void purge(void) json_nothrow ;
clearauto_expand_stream124 		  inline void clear(void) json_nothrow { purge(); mymap.clear(); }
insertauto_expand_stream125 		  inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
removeauto_expand_stream126 		  inline void remove(void * ptr) json_nothrow {
127 			 JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
128 			 if(json_likely(i != mymap.end())) mymap.erase(i);
129 		  }
130 		  JSON_MAP(void *, JSONStream *) mymap;
131         private:
132             auto_expand_stream(const auto_expand_stream &);
133             auto_expand_stream & operator = (const auto_expand_stream &);
134 	   };
135     #endif
136 #endif
137 
138 //The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
139 template <typename T>
140 class json_auto {
141     public:
142 		LIBJSON_OBJECT(json_auto);
json_auto(void)143 	   json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
json_auto(size_t count)144 	   json_auto(size_t count) json_nothrow : ptr(json_malloc<T>(count)){ LIBJSON_CTOR; }
json_auto(T * arg)145 	   json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
~json_auto(void)146 	   ~json_auto(void) json_nothrow {
147 		  libjson_free<T>(ptr);
148 		  LIBJSON_DTOR;
149 	   }
set(T * p)150 	   inline void set(T * p) json_nothrow{
151 		  ptr = p;
152 	   }
153 	   T * ptr;
154     private:
155 	   json_auto(const json_auto &);
156 	   json_auto & operator =(const json_auto &);
157 };
158 
159 //Clears a string, if required, frees the memory
clearString(json_string & str)160 static inline void clearString(json_string & str) json_nothrow {
161     #ifdef JSON_LESS_MEMORY
162 	   json_string().swap(str);
163     #else
164 	   str.clear();
165     #endif
166 }
167 
168 //Shrinks a string
shrinkString(json_string & str)169 static inline void shrinkString(json_string & str) json_nothrow {
170     #ifdef JSON_LESS_MEMORY
171         if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
172     #endif
173 }
174 
175 #endif
176