JSONMemory.h 6.3 KB

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