diff options
Diffstat (limited to 'src/libjin/common')
| -rw-r--r-- | src/libjin/common/je_array.hpp | 123 | ||||
| -rw-r--r-- | src/libjin/common/je_common.h | 7 | ||||
| -rw-r--r-- | src/libjin/common/je_exception.cpp | 46 | ||||
| -rw-r--r-- | src/libjin/common/je_exception.h | 45 | ||||
| -rw-r--r-- | src/libjin/common/je_noncopyable.h | 24 | ||||
| -rw-r--r-- | src/libjin/common/je_object.h | 16 | ||||
| -rw-r--r-- | src/libjin/common/je_pool.hpp | 177 | ||||
| -rw-r--r-- | src/libjin/common/je_singleton.hpp | 80 | ||||
| -rw-r--r-- | src/libjin/common/je_stringmap.hpp | 143 | ||||
| -rw-r--r-- | src/libjin/common/je_subsystem.hpp | 78 | ||||
| -rw-r--r-- | src/libjin/common/je_temporary.h | 31 | ||||
| -rw-r--r-- | src/libjin/common/je_types.h | 34 | ||||
| -rw-r--r-- | src/libjin/common/je_utf8.cpp | 42 | ||||
| -rw-r--r-- | src/libjin/common/je_utf8.h | 34 | 
14 files changed, 880 insertions, 0 deletions
diff --git a/src/libjin/common/je_array.hpp b/src/libjin/common/je_array.hpp new file mode 100644 index 0000000..8a5cbf1 --- /dev/null +++ b/src/libjin/common/je_array.hpp @@ -0,0 +1,123 @@ +#ifndef __JE_COMMON_ARRAY_H__ +#define __JE_COMMON_ARRAY_H__ + +namespace JinEngine +{ + +    /// +    /// A array created on heap. +    /// +    template<typename T> +    class Array +    { +    public: +        /// +        /// Array constructor. +        /// +        Array()  +            : length(0) +            , data(nullptr)  +        { +        } + +        /// +        /// Array constructor. +        /// +        /// @param l Length of array. +        /// +        Array(int l) +        { +            length = l; +            data = new T[l]; +        } + +        /// +        /// Array destructor. +        /// +        ~Array() +        { +            delete[] data; +            length = 0; +        } + +        /// +        /// Get address of data. +        ///  +        /// @return Address of data. +        /// +        T* operator &() +        { +            return data; +        } + +        /// +        /// Get specific element of array. +        ///  +        /// @return Element of array. +        /// +        T& operator[](int index) +        { +            return data[index]; +        } + +        /// +        /// Bind data with given data. +        /// +        /// @param data Data pointer. +        /// @param length Length of data. +        /// +        void bind(T* data, int length) +        { +            if (data != nullptr) +                delete data;  +            this->data = data; +            this->length = length; +        } + +        /// +        /// Add an element. +        ///  +        /// @param v Value of element. +        /// +        void add(T value) +        { +            int len = length + 1; +            T* d = new T[len]; +            memcpy(d, data, size()); +            d[length] = value; +            bind(d, len); +        } +  +        /// +        /// Get size of data in byte. +        ///  +        /// @return Size of data in byte. +        /// +        int size() +        { +            return sizeof(T) * length; +        } + +        /// +        /// Get length of data.  +        ///  +        /// @return Count of data. +        /// +        int count() +        { +            return length; +        } + +    private: +        // Disable new and delete. +        void* operator new(size_t t); +        void operator delete(void* ptr); + +        T * data; +        unsigned int length; + +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_common.h b/src/libjin/common/je_common.h new file mode 100644 index 0000000..31b67c6 --- /dev/null +++ b/src/libjin/common/je_common.h @@ -0,0 +1,7 @@ +#ifndef __JE_COMMON_H__ +#define __JE_COMMON_H__ + +#include "je_exception.h" +#include "je_array.hpp" + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_exception.cpp b/src/libjin/common/je_exception.cpp new file mode 100644 index 0000000..5489a42 --- /dev/null +++ b/src/libjin/common/je_exception.cpp @@ -0,0 +1,46 @@ +#include <stdarg.h> + +#include "je_exception.h" + +namespace JinEngine +{ + +    Exception::Exception(const char *fmt, ...) +    { +        va_list args; +        int size_buffer = 256, size_out; +        char *buffer; +        while (true) +        { +            buffer = new char[size_buffer]; +            memset(buffer, 0, size_buffer); + +            va_start(args, fmt); +            size_out = vsnprintf(buffer, size_buffer, fmt, args); +            va_end(args); + +            // see http://perfec.to/vsnprintf/pasprintf.c +            // if size_out ... +            //      == -1             --> output was truncated +            //      == size_buffer    --> output was truncated +            //      == size_buffer-1  --> ambiguous, /may/ have been truncated +            //       > size_buffer    --> output was truncated, and size_out +            //                            bytes would have been written +            if (size_out == size_buffer || size_out == -1 || size_out == size_buffer - 1) +                size_buffer *= 2; +            else if (size_out > size_buffer) +                size_buffer = size_out + 2; // to avoid the ambiguous case +            else +                break; + +            delete[] buffer; +        } +        mMessage = std::string(buffer); +        delete[] buffer; +    } + +    Exception::~Exception() throw() +    { +    } + +} // namespace JinEngine
\ No newline at end of file diff --git a/src/libjin/common/je_exception.h b/src/libjin/common/je_exception.h new file mode 100644 index 0000000..c319ebd --- /dev/null +++ b/src/libjin/common/je_exception.h @@ -0,0 +1,45 @@ +#ifndef __JE_EXCEPTION_H__ +#define __JE_EXCEPTION_H__ + +#include <exception> +#include <string> + +namespace JinEngine +{ + +    /// +    /// Jin Exception. +    /// +    class Exception : public std::exception +    { +    public: + +        ///  +        /// Creates a new Exception according to printf-rules. +        /// +        /// @param fmt The format string (see printf). +        ///  +        Exception(const char *fmt, ...); +        virtual ~Exception() throw(); + +        ///  +        /// Returns a string containing reason for the exception. +        ///  +        /// @return A description of the exception. +        ///  +        inline virtual const char *what() const throw() +        { +            return mMessage.c_str(); +        } + +    private: +        /// +        /// Exception message. +        /// +        std::string mMessage; + +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_noncopyable.h b/src/libjin/common/je_noncopyable.h new file mode 100644 index 0000000..eff7121 --- /dev/null +++ b/src/libjin/common/je_noncopyable.h @@ -0,0 +1,24 @@ +#ifndef __JE_NONCOPYABLE_H__ +#define __JE_NONCOPYABLE_H__ + +namespace JinEngine +{ + +    /// +    /// Class inherites this could not be copied. +    /// +    class Noncopyable +    { +    public: +        Noncopyable(void) { } +        virtual ~Noncopyable(void) { } + +    private: +        Noncopyable(const Noncopyable& other); +        Noncopyable& operator=(const Noncopyable& other); + +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_object.h b/src/libjin/common/je_object.h new file mode 100644 index 0000000..fb8221f --- /dev/null +++ b/src/libjin/common/je_object.h @@ -0,0 +1,16 @@ +#ifndef __JE_OBJECT_H__ +#define __JE_OBJECT_H__ + +namespace JinEngine +{ + +    /// +    /// Base class of all objects in Jin. +    /// +    class Object +    { +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_pool.hpp b/src/libjin/common/je_pool.hpp new file mode 100644 index 0000000..cb96c5b --- /dev/null +++ b/src/libjin/common/je_pool.hpp @@ -0,0 +1,177 @@ +///  +/// An O(1) Object Pool. Original from https://www.codeproject.com/Articles/746630/O-Object-Pool-in-Cplusplus +///  +#ifndef __JE_POOL_H__ +#define __JE_POOL_H__ + +#include <stdlib.h> +#include <iostream> + +#include "je_types.h" + +namespace JinEngine +{ + +    class DefaultMemoryAllocator +    { +    public: +        static inline void *Allocate(size_t size) +        { +            return ::operator new(size, ::std::nothrow); +        } +        static inline void Deallocate(void *pointer, size_t size) +        { +            ::operator delete(pointer); +        } +    }; + +    template<typename T, class TMemoryAllocator = DefaultMemoryAllocator> +    class Pool +    { +    private: +        struct _Node +        { +            void *_memory; +            size_t _capacity; +            _Node *_nextNode; + +            _Node(size_t capacity) +            { +                if (capacity < 1) +                    throw std::invalid_argument("capacity must be at least 1."); + +                _memory = TMemoryAllocator::Allocate(_itemSize * capacity); +                if (_memory == NULL) +                    throw std::bad_alloc(); + +                _capacity = capacity; +                _nextNode = NULL; +            } +            ~_Node() +            { +                TMemoryAllocator::Deallocate(_memory, _itemSize * _capacity); +            } +        }; + +        void *_nodeMemory; +        T *_firstDeleted; +        size_t _countInNode; +        size_t _nodeCapacity; +        _Node _firstNode; +        _Node *_lastNode; +        size_t _maxBlockLength; + +        static const size_t _itemSize; + +        Pool(const Pool<T, TMemoryAllocator> &source); +        void operator = (const Pool<T, TMemoryAllocator> &source); + +        void _AllocateNewNode() +        { +            size_t size = _countInNode; +            if (size >= _maxBlockLength) +                size = _maxBlockLength; +            else +            { +                size *= 2; + +                if (size < _countInNode) +                    throw std::overflow_error("size became too big."); + +                if (size >= _maxBlockLength) +                    size = _maxBlockLength; +            } + +            _Node *newNode = new _Node(size); +            _lastNode->_nextNode = newNode; +            _lastNode = newNode; +            _nodeMemory = newNode->_memory; +            _countInNode = 0; +            _nodeCapacity = size; +        } + +    public: +        explicit Pool(size_t initialCapacity = 32, size_t maxBlockLength = 1000000)  +            : _firstDeleted(NULL) +            , _countInNode(0) +            , _nodeCapacity(initialCapacity) +            , _firstNode(initialCapacity) +            , _maxBlockLength(maxBlockLength) +        { +            if (maxBlockLength < 1) +                throw std::invalid_argument("maxBlockLength must be at least 1."); + +            _nodeMemory = _firstNode._memory; +            _lastNode = &_firstNode; +        } +        ~Pool() +        { +            _Node *node = _firstNode._nextNode; +            while (node) +            { +                _Node *nextNode = node->_nextNode; +                delete node; +                node = nextNode; +            } +        } + +        T *New() +        { +            if (_firstDeleted) +            { +                T *result = _firstDeleted; +                _firstDeleted = *((T **)_firstDeleted); +                new(result) T(); +                return result; +            } + +            if (_countInNode >= _nodeCapacity) +                _AllocateNewNode(); + +            char *address = (char *)_nodeMemory; +            address += _countInNode * _itemSize; +            T *result = new(address) T(); +            _countInNode++; +            return result; +        } + +        // This method is useful if you want to call a non-default constructor. +        // It should be used like this: +        // new (pool.GetNextWithoutInitializing()) ObjectType(... parameters ...); +        T *GetNextWithoutInitializing() +        { +            if (_firstDeleted) +            { +                T *result = (T *)_firstDeleted; +                _firstDeleted = *((T **)_firstDeleted); +                return result; +            } + +            if (_countInNode >= _nodeCapacity) +                _AllocateNewNode(); + +            char *address = (char *)_nodeMemory; +            address += _countInNode * _itemSize; +            _countInNode++; +            return (T *)address; +        } +        void Delete(T *content) +        { +            content->~T(); + +            *((T **)content) = _firstDeleted; +            _firstDeleted = content; +        } +        void DeleteWithoutDestroying(T *content) +        { +            *((T **)content) = _firstDeleted; +            _firstDeleted = content; +        } +    }; + +    template<typename T, class TMemoryAllocator> +    const size_t Pool<T, TMemoryAllocator>::_itemSize = ((sizeof(T) + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *); + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_singleton.hpp b/src/libjin/common/je_singleton.hpp new file mode 100644 index 0000000..d7f52c9 --- /dev/null +++ b/src/libjin/common/je_singleton.hpp @@ -0,0 +1,80 @@ +#ifndef __JE_SINGLETON_H__ +#define __JE_SINGLETON_H__ + +namespace JinEngine +{ + +    /// +    /// Singleton base class. +    /// +    template<class T> +    class Singleton +    { +    public: +        /// +        /// Get singleton.  +        ///  +        /// @param Singleton instance of class. +        /// +        static T* get() +        { +            if (_instance == nullptr) +                _instance = new T; +            return _instance; +        } + +        /// +        /// Destroy instance of singleton. +        /// +        static void destroy() +        { +            delete _instance; +            _instance = nullptr; +        } + +    protected: +        /// +        /// Singleton constructor. +        /// +        Singleton() {}; + +        /// +        /// Singleton destructor. +        /// +        virtual ~Singleton() {}; + +        /// +        /// Singleton instance. +        /// +        static T* _instance; + +    private: +        /// +        /// Singleton copy constructor. +        /// +        /// @param singleton Singleton of class. +        /// +        Singleton(const Singleton& singleton); + +        /// +        /// Singleton assignment. +        /// +        /// @param singleton Singleton of class. +        /// +        Singleton& operator = (const Singleton& singleton); + +    }; + +    /// +    /// Singleton instance. +    /// +    template<class T> T* Singleton<T>::_instance = nullptr; + +    /// +    /// Singleton notation. +    /// +    #define singleton(T) friend Singleton<T> + +} // namespace JinEngine + +#endif // __JE_SINGLETON_H__ diff --git a/src/libjin/common/je_stringmap.hpp b/src/libjin/common/je_stringmap.hpp new file mode 100644 index 0000000..7a3bd80 --- /dev/null +++ b/src/libjin/common/je_stringmap.hpp @@ -0,0 +1,143 @@ +#ifndef __JE_COMMON_SREINGMAP_H__ +#define __JE_COMMON_SREINGMAP_H__ + +namespace JinEngine +{ + +    template<typename T, unsigned SIZE> +    class StringMap +    { +    private: + +        struct Record +        { +            const char * key; +            T value; +            bool set; +            Record() : set(false) {} +        }; + +        const static unsigned MAX = SIZE * 2; + +        Record records[MAX]; +        const char * reverse[SIZE]; + +    public: + +        struct Entry +        { +            const char * key; +            T value; +        }; + +        StringMap(Entry * entries, unsigned num) +        { + +            for (unsigned i = 0; i < SIZE; ++i) +                reverse[i] = 0; + +            unsigned n = num / sizeof(Entry); + +            for (unsigned i = 0; i < n; ++i) +            { +                add(entries[i].key, entries[i].value); +            } +        } + +        bool streq(const char * a, const char * b) +        { +            while (*a != 0 && *b != 0) +            { +                if (*a != *b) +                    return false; +                ++a; +                ++b; +            } + +            return (*a == 0 && *b == 0); +        } + +        bool find(const char * key, T & t) +        { +            //unsigned str_hash = djb2(key); + +            for (unsigned i = 0; i < MAX; ++i) +            { +                //unsigned str_i = (str_hash + i) % MAX; //this isn't used, is this intentional? + +                if (records[i].set && streq(records[i].key, key)) +                { +                    t = records[i].value; +                    return true; +                } +            } + +            return false; +        } + +        bool find(T key, const char *& str) +        { +            unsigned index = (unsigned)key; + +            if (index >= SIZE) +                return false; + +            if (reverse[index] != 0) +            { +                str = reverse[index]; +                return true; +            } +            else +            { +                return false; +            } +        } + +        bool add(const char * key, T value) +        { +            unsigned str_hash = djb2(key); +            bool inserted = false; + +            for (unsigned i = 0; i < MAX; ++i) +            { +                unsigned str_i = (str_hash + i) % MAX; + +                if (!records[str_i].set) +                { +                    inserted = true; +                    records[str_i].set = true; +                    records[str_i].key = key; +                    records[str_i].value = value; +                    break; +                } +            } + +            unsigned index = (unsigned)value; + +            if (index >= SIZE) +            { +                printf("\nConstant %s out of bounds with %i!\n", key, index); +                return false; +            } + +            reverse[index] = key; + +            return inserted; +        } + +        unsigned djb2(const char * key) +        { +            unsigned hash = 5381; +            int c; + +            while ((c = *key++)) +                hash = ((hash << 5) + hash) + c; + +            return hash; +        } + +    }; // StringMap + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_subsystem.hpp b/src/libjin/common/je_subsystem.hpp new file mode 100644 index 0000000..c015bef --- /dev/null +++ b/src/libjin/common/je_subsystem.hpp @@ -0,0 +1,78 @@ +#ifndef __JE_COMMON_SUBSYSTEM_H__ +#define __JE_COMMON_SUBSYSTEM_H__ + +#include "../utils/je_macros.h" + +#include "je_singleton.hpp" + +namespace JinEngine +{ + +    /// +    /// Subsystem class. +    /// +    template<class System> +    class Subsystem : public Singleton<System> +    { +    public:  +        /// +        /// Subsystem setting. +        /// +        struct Setting  +        { +        };  + +        typedef Setting SettingBase;  + +        /// +        /// Initialize subsystem. +        ///  +        /// @param setting Subsystem setting. +        /// @return True if initialize sucessful, otherwise return false. +        /// +        bool init(const SettingBase* setting = nullptr) +        { +            static bool success = initSystem(setting); +            return success; +        } + +        /// +        /// Quit subsystem. +        /// +        void quit() +        { +            // Call only once. +			static char __dummy__ = (quitSystem(), 1); +			Singleton<System>::destroy(); +        } + +    protected: +        singleton(System); + +        /// +        /// Subsystem constructor. +        /// +        Subsystem() {}; + +        ///  +        /// Subsystem destructor. +        /// +        virtual ~Subsystem()  +        { +        }; + +        /// +        /// Initializer callback. +        /// +		virtual bool initSystem(const Setting* setting) = 0; + +        /// +        /// Quit subsystem callback. +        /// +		virtual void quitSystem() = 0; + +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_temporary.h b/src/libjin/common/je_temporary.h new file mode 100644 index 0000000..647bfba --- /dev/null +++ b/src/libjin/common/je_temporary.h @@ -0,0 +1,31 @@ +#ifndef __JE_TEMPORARY_H__ +#define __JE_TEMPORARY_H__ + +namespace JinEngine +{ +     +    /// +    /// Class inherites this clound only be created on stack or static zone. +    /// +    class Temporary +    { +    public: +        Temporary() {}; +        virtual ~Temporary() {}; +/* +    protected: +        void operator delete(void* t) +        { +            if(t != nullptr) +                free(t); +        } +*/ +    private: +        // Disable new operands. +        void* operator new(size_t); + +    }; + +} // namespace JinEngine + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_types.h b/src/libjin/common/je_types.h new file mode 100644 index 0000000..e31ce5e --- /dev/null +++ b/src/libjin/common/je_types.h @@ -0,0 +1,34 @@ +#ifndef __JE_TYPES_H__ +#define __JE_TYPES_H__ +#include <stdint.h> +#include <stdlib.h> +#include <cstring> + +namespace JinEngine +{ + +    typedef int8_t   int8;   ///< Signed integer with a size of 8 bits. Supports values from -128 to 127 +    typedef uint8_t  uint8;  ///< Unsigned integer with a size of 8 bits. Supports values from 0 to 255. +    typedef uint8    byte;   ///< Unsigned integer with 8 bits (1 byte). Supports 256 values from 0 to 255. +    typedef int16_t  int16;  ///< Signed integer with a size of 16 bits. Supports values from -32768 to 32767 +    typedef uint16_t uint16; ///< Unsigned integer with a size of 16 bits. Supports values from 0 to 65535. +    typedef int32_t  int32;  ///< Signed integer with a size of 32 bits. Supports values from -2147483648 to 2147483647. +    typedef uint32_t uint32; ///< Unsigned integer with a size of 32 bits. Supports values from 0 to 4294967295, (2^32 - 1). +    typedef int64_t  int64;  ///< Signed integer with a size of 64 bits. Supports values from -(2^63) to (2^63 - 1). +    typedef uint64_t uint64; ///< Unsigned integer with a size of 64 bits, Supports values from 0 to (2^64 - 1). + +    typedef uint32_t uint; +    typedef int32_t  sint; + +#define Union(name, ...) \ +union _Ctor{                                    \ +    _Ctor() { memset(this, 0, sizeof(*this)); } \ +    __VA_ARGS__;                                \ +} name; + +#define Struct(name, ...) \ +struct {__VA_ARGS__;} name; + +} + +#endif
\ No newline at end of file diff --git a/src/libjin/common/je_utf8.cpp b/src/libjin/common/je_utf8.cpp new file mode 100644 index 0000000..bd7ce94 --- /dev/null +++ b/src/libjin/common/je_utf8.cpp @@ -0,0 +1,42 @@ +#include "../core/je_configuration.h" +#if jin_os == jin_os_windows + +#include "je_utf8.h" + +namespace JinEngine +{ + +    std::string to_utf8(LPCWSTR wstr) +    { +        size_t wide_len = wcslen(wstr) + 1; + +        // Get size in UTF-8. +        int utf8_size = WideCharToMultiByte(CP_UTF8, 0, wstr, wide_len, 0, 0, 0, 0); + +        char * utf8_str = new char[utf8_size]; + +        // Convert to UTF-8. +        int ok = WideCharToMultiByte(CP_UTF8, 0, wstr, wide_len, utf8_str, utf8_size, 0, 0); + +        if (!ok) +        { +            delete[] utf8_str; +        } + +        return ok ? std::string(utf8_str) : std::string(); +    } + +    void replace_char(std::string & str, char find, char replace) +    { +        int length = str.length(); + +        for (int i = 0; i<length; i++) +        { +            if (str[i] == find) +                str[i] = replace; +        } +    } + +} // namespace JinEngine + +#endif // jin_os == jin_os_windows
\ No newline at end of file diff --git a/src/libjin/common/je_utf8.h b/src/libjin/common/je_utf8.h new file mode 100644 index 0000000..d840b75 --- /dev/null +++ b/src/libjin/common/je_utf8.h @@ -0,0 +1,34 @@ +#ifndef __JE_COMMON_UTF8_H__ +#define __JE_COMMON_UTF8_H__ + +#include "../core/je_configuration.h" +#if jin_os == jin_os_windows + +#include <string> +#include <windows.h> + +namespace JinEngine +{ + +    ///  +    /// Convert the wide string to a UTF-8 encoded string. +    ///  +    /// @param wstr The wide-char string. +    /// @return A UTF-8 string. +    ///  +    std::string to_utf8(LPCWSTR wstr); + +    ///  +    /// Replace all occurences of 'find' with 'replace' in a string. +    /// +    /// @param str The string to modify. +    /// @param find The character to match. +    /// @param replace The character to replace matches. +    ///  +    void replace_char(std::string & str, char find, char replace); + +} // namespace JinEngine + +#endif // jin_os == jin_os_windows + +#endif // __JE_COMMON_UTF8_H__  | 
