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__ |