The R Project SVN R-packages

Rev

Blame | Last modification | View Log | Download | RSS feed

#ifndef JSON_MEMORY_H
#define JSON_MEMORY_H

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

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

#if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
    class JSONMemory {
    public:
          static void * json_malloc(size_t siz) json_malloc_attr;
          static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
       static void json_free(void * ptr) json_nothrow;
       static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
    private:
        JSONMemory(void);
    };

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

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

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

    template <typename T> static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
       std::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) json_malloc_attr;
    template <typename T> static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
       #ifdef JSON_DEBUG  //in debug mode, check the results of realloc to be sure it was successful
          void * result = std::realloc(ptr, count * sizeof(T));
          JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
          return (T *)result;
       #else
          return (T *)std::realloc(ptr, count * sizeof(T));
       #endif
    }
#endif

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

    struct auto_expand_node {
    public:
        LIBJSON_OBJECT(auto_expand_node);
       auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
       ~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
       void purge(void) json_nothrow ;
       inline void clear(void) json_nothrow { purge(); mymap.clear(); }
       inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
       inline void remove(void * ptr) json_nothrow {
          JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
          if(json_likely(i != mymap.end())) mymap.erase(i);
       }
       JSON_MAP(void *, JSONNode *) mymap;
    private:
        auto_expand_node(const auto_expand_node &);
        auto_expand_node & operator = (const auto_expand_node &);
    };

    #ifdef JSON_STREAM
       class JSONStream;
       struct auto_expand_stream {
        public:
            LIBJSON_OBJECT(auto_expand_stream);
          auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
          ~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
          void purge(void) json_nothrow ;
          inline void clear(void) json_nothrow { purge(); mymap.clear(); }
          inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
          inline void remove(void * ptr) json_nothrow {
             JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
             if(json_likely(i != mymap.end())) mymap.erase(i);
          }
          JSON_MAP(void *, JSONStream *) mymap;
        private:
            auto_expand_stream(const auto_expand_stream &);
            auto_expand_stream & operator = (const auto_expand_stream &);
       };
    #endif
#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:
            LIBJSON_OBJECT(json_auto)
       json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
       json_auto(size_t count) json_nothrow : ptr(json_malloc<T>(count)){ LIBJSON_CTOR; }
       json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
       ~json_auto(void) json_nothrow {
          libjson_free<T>(ptr);
          LIBJSON_DTOR;
       }
       inline void set(T * p) json_nothrow{
          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) json_nothrow {
    #ifdef JSON_LESS_MEMORY
       json_string().swap(str);
    #else
       str.clear();
    #endif
}

//Shrinks a string
static inline void shrinkString(json_string & str) json_nothrow {
    #ifdef JSON_LESS_MEMORY
        if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
    #endif
}

#endif