summaryrefslogtreecommitdiff
path: root/src/modules/json/JSONMemory.h
blob: 899d73b6fc960b81219817f22aaded8c2df198cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef JSON_MEMORY_H
#define JSON_MEMORY_H

#include <cstdlib> //for malloc, realloc, and free
#include <cstring> //for memmove
#include "JSONOptions.h"
#include "JSONDebug.h"

#if defined(JSON_DEBUG) || defined(JSON_SAFE)
    #define JSON_FREE_PASSTYPE &
#else
    #define JSON_FREE_PASSTYPE
#endif

#ifdef JSON_MEMORY_CALLBACKS
    class JSONMemory {
    public:
	   static void * json_malloc(size_t siz);
	   static void * json_realloc(void * ptr, size_t siz);
	   static void json_free(void * ptr);
	   static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre);
    };

    template <typename T> static inline T * json_malloc(size_t count){
	   return (T *)JSONMemory::json_malloc(sizeof(T) * count);
    }

    template <typename T> static inline T * json_realloc(T * ptr, size_t count){
	   return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
    }

    template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr){
	   JSONMemory::json_free(ptr);
	   #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
		  ptr = 0;
	   #endif
    }
#else
    template <typename T>
    static inline T * json_malloc(size_t count){
	   #ifdef JSON_DEBUG  //in debug mode, see if the malloc was successful
		  void * result = malloc(count * sizeof(T));
		  JSON_ASSERT(result, JSON_TEXT("out of memory"));
		  #ifdef JSON_NULL_MEMORY
			 memset(result, '\0', count  * sizeof(T));
		  #endif
		  return (T *)result;
	   #else
		  return (T *)malloc(count * sizeof(T));
	   #endif
    }

    template <typename T>
    static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr){
	   free(ptr);
	   #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
		  ptr = 0;
	   #endif
    }

    template <typename T>
    static inline T * json_realloc(T * ptr, size_t count){
	   #ifdef JSON_DEBUG  //in debug mode, check the results of realloc to be sure it was successful
		  void * result = realloc(ptr, count * sizeof(T));
		  JSON_ASSERT(result, JSON_TEXT("out of memory"));
		  #ifdef JSON_NULL_MEMORY
			 memset(result, '\0', count  * sizeof(T));
		  #endif
		  return (T *)result;
	   #else
		  return (T *)realloc(ptr, count * sizeof(T));
	   #endif
    }
#endif

#ifdef JSON_MEMORY_MANAGE
    #include <map>
    class JSONNode;
    struct auto_expand {
	   auto_expand(void) : mymap() {}
	   ~auto_expand(void){ purge(); }
	   void purge(void);
	   inline void clear(void){ purge(); mymap.clear(); }
	   inline void * insert(void * ptr){ mymap[ptr] = ptr; return ptr; }
	   inline void remove(void * ptr){ 
		  std::map<void *, void *>::iterator i = mymap.find(ptr);
		  JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
		  mymap.erase(i);
	   }
	   std::map<void *, void *> mymap;
    };

    struct auto_expand_node {
	   auto_expand_node(void) : mymap() {}
	   ~auto_expand_node(void){ purge(); }
	   void purge(void);
	   inline void clear(void){ purge(); mymap.clear(); }
	   inline JSONNode * insert(JSONNode * ptr){ mymap[ptr] = ptr; return ptr; }
	   inline void remove(void * ptr){ 
		  std::map<void *, JSONNode *>::iterator i = mymap.find(ptr);
		  if(i != mymap.end()) mymap.erase(i);
	   }
	   std::map<void *, JSONNode *> mymap;
    };
#endif

//The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
template <typename T>
class json_auto {
    public:
	   json_auto(void) : ptr(0){}
	   json_auto(size_t count) : ptr(json_malloc<T>(count)) {}
	   ~json_auto(void){
		  libjson_free<T>(ptr);
	   }
	   void set(T * p){
		  ptr = p; 
	   }
	   T * ptr;
    private:
	   json_auto(const json_auto &);
	   json_auto & operator = (const json_auto &);
};

//Clears a string, if required, frees the memory
static inline void clearString(json_string & str){
    #ifdef JSON_LESS_MEMORY
	   json_string().swap(str);
    #else
	   str.clear();
    #endif
}

#endif