diff options
author | Alexis211 <alexis211@gmail.com> | 2009-10-20 19:23:33 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-10-20 19:23:33 +0200 |
commit | 768ada13917aeda373e6ff5fee21faf90c963746 (patch) | |
tree | 9e26d7d65e1693d1a7f9fd93c9fd33b41d175464 /Source/Library/Common | |
parent | 6ec4b3d31080f90393e72989d559cfb76eff6f9d (diff) | |
parent | 9836acd720988af30250c2c1ec18d618664dea4e (diff) | |
download | Melon-768ada13917aeda373e6ff5fee21faf90c963746.tar.gz Melon-768ada13917aeda373e6ff5fee21faf90c963746.zip |
Merge branch 'usermode_syscalls'
Conflicts:
Source/Kernel/Makefile
Diffstat (limited to 'Source/Library/Common')
25 files changed, 1769 insertions, 0 deletions
diff --git a/Source/Library/Common/BasicString.class.cpp b/Source/Library/Common/BasicString.class.cpp new file mode 100644 index 0000000..ceab60b --- /dev/null +++ b/Source/Library/Common/BasicString.class.cpp @@ -0,0 +1,175 @@ +#include <Vector.class.h> + +#define FREE if (m_string != 0) delete m_string; +#define ALLOC m_string = new T[m_length]; +#define VRFY if (m_length == 0) { m_string = NULL; return; } + +using namespace CMem; + +template <typename T> +BasicString<T>::BasicString() { + m_string = NULL; + m_length = 0; +} + +template <typename T> +BasicString<T>::BasicString(const T* string, u32int length) { + m_string = NULL; + affect(string, length); +} + +template <typename T> +BasicString<T>::BasicString(const BasicString<T> &other) { + m_string = NULL; + affect(other); +} + +template <typename T> +BasicString<T>::BasicString(const T value, u32int count) { + m_string = NULL; + affect(value, count); +} + +template <typename T> +BasicString<T>::~BasicString() { + FREE; +} + +template <typename T> +void BasicString<T>::affect(const BasicString<T> &other) { + FREE; + m_length = other.m_length; + VRFY; + ALLOC; + memcpy((u8int*)m_string, (u8int*)(other.m_string), m_length * sizeof(T)); +} + +template <typename T> +void BasicString<T>::affect(const T* string, u32int length) { + FREE; + m_length = length; + VRFY; + ALLOC; + memcpy((u8int*)string, (u8int*)string, m_length * sizeof(T)); +} + +template <typename T> +void BasicString<T>::affect(const T value, u32int count) { + FREE; + m_length = count; + VRFY; + ALLOC; + for (u32int i = 0; i < count; i++) { + m_string[i] = value; + } +} + +template <typename T> +bool BasicString<T>::compare(const BasicString<T> &other) const { + if (m_length != other.m_length) return false; + for (u32int i = 0; i < m_length; i++) { + if (m_string[i] != other.m_string[i]) return false; + } + return true; +} + +template <typename T> +bool BasicString<T>::compare(const T* string, u32int length) const { + if (m_length != length) return false; + for (u32int i = 0; i < m_length; i++) { + if (m_string[i] != string[i]) return false; + } + return true; +} + +template <typename T> +BasicString<T> &BasicString<T>::append(const BasicString<T> &other) { + T* newdata = new T[m_length + other.m_length]; + for (u32int i = 0; i < m_length; i++) { + newdata[i] = m_string[i]; + } + for (u32int i = 0; i < other.m_length; i++) { + newdata[i + m_length] = other.m_string[i]; + } + FREE; + m_string = newdata; + m_length += other.m_length; + return *this; +} + +template <typename T> +BasicString<T> &BasicString<T>::append(const T* string, u32int length) { + T* newdata = new T[m_length + length]; + for (u32int i = 0; i < m_length; i++) { + newdata[i] = m_string[i]; + } + for (u32int i = 0; i < length; i++) { + newdata[i + m_length] = string[i]; + } + FREE; + m_string = newdata; + m_length += length; + return *this; +} + +template <typename T> +BasicString<T> &BasicString<T>::append(const T other) { + T* newdata = new T[m_length + 1]; + for (u32int i = 0; i < m_length; i++) { + newdata[i] = m_string[i]; + } + FREE; + m_string = newdata; + m_string[m_length] = other; + m_length++; + return *this; +} + +template <typename T> +BasicString<T> BasicString<T>::concat(const BasicString<T> &other) const { + BasicString<T> ret(*this); + return (ret.append(other)); +} + +template <typename T> +BasicString<T> BasicString<T>::concat(const T* string, u32int length) const { + BasicString<T> ret(*this); + return (ret.append(string, length)); +} + +template <typename T> +BasicString<T> BasicString<T>::concat(const T other) const { + BasicString<T> ret(*this); + return (ret.append(other)); +} + +template <typename T> +void BasicString<T>::clear() { + FREE; + m_string = 0; + m_length = 0; +} + +template <typename T> +Vector< BasicString<T> > BasicString<T>::split(T sep) const { + Vector< BasicString<T> > ret; + ret.push(BasicString<T>()); + for (u32int i = 0; i < m_length; i++) { + if (m_string[i] == sep) { + ret.push(BasicString<T>()); + } else { + ret.back().append(m_string[i]); + } + } + return ret; +} + +template <typename T> +BasicString<T> BasicString<T>::substr(s32int start, u32int size) { + if (start < 0) start = m_length - start; + BasicString<T> ret; + ret.m_string = new T[size + 1]; + ret.m_length = size; + memcpy((u8int*)ret.m_string, (u8int*)(&m_string[start]), size * sizeof(T)); + return ret; +} diff --git a/Source/Library/Common/BasicString.class.h b/Source/Library/Common/BasicString.class.h new file mode 100644 index 0000000..17055e8 --- /dev/null +++ b/Source/Library/Common/BasicString.class.h @@ -0,0 +1,53 @@ +#ifndef DEF_BASICSTRING_CLASS_H +#define DEF_BASICSTRING_CLASS_H + +#include <common.h> + +template <typename T> class Vector; + +template <typename T> +class BasicString { + protected: + T *m_string; + u32int m_length; + + public: + BasicString(); + BasicString(const T* string, u32int length); + BasicString(const BasicString<T> &other); + BasicString(const T, u32int count = 1); + virtual ~BasicString(); + + void affect(const BasicString<T> &other); + void affect(const T* string, u32int length); + void affect(const T value, u32int count = 1); + void operator= (const BasicString<T> &other) { affect(other); } + + bool compare(const BasicString<T> &other) const; + bool compare(const T* string, u32int length) const; + bool operator== (const BasicString<T> &other) const { return compare(other); } + bool operator!= (const BasicString<T> &other) const { return !compare(other); } + + BasicString<T>& append(const BasicString<T> &other); + BasicString<T>& append(const T* string, u32int length); + BasicString<T>& append(const T other); + BasicString<T>& operator+= (const BasicString<T> &other) { return append(other); } + BasicString<T>& operator+= (const T other) { return append(other); } + + BasicString<T> concat(const BasicString<T> &other) const; + BasicString<T> concat(const T* string, u32int length) const; + BasicString<T> concat(const T other) const; + + T& operator[] (int index) const { return m_string[index]; } + + u32int size() const { return m_length; } + void clear(); + bool empty() const { return m_length == 0; } + + Vector< BasicString<T> > split(T sep) const; + BasicString<T> substr(s32int start, u32int size); +}; + +#include "BasicString.class.cpp" + +#endif diff --git a/Source/Library/Common/Bitset.class.cpp b/Source/Library/Common/Bitset.class.cpp new file mode 100644 index 0000000..a8d7ec8 --- /dev/null +++ b/Source/Library/Common/Bitset.class.cpp @@ -0,0 +1,62 @@ +#include "Bitset.class.h" + +Bitset::Bitset() { +} + +Bitset::Bitset(u32int size) { + init(size, (u32int*)Mem::alloc(INDEX_FROM_BIT(size))); +} + +Bitset::Bitset(u32int size, u32int *ptr) { + init(size, ptr); +} + +Bitset::~Bitset() { + Mem::free(m_data); +} + +void Bitset::init(u32int size, u32int *ptr) { + m_size = size; + m_data = ptr; + for (u32int i = 0; i < INDEX_FROM_BIT(m_size); i++) { + m_data[i] = 0; + } + m_usedCount = 0; +} + +void Bitset::setBit(u32int number) { + u32int idx = INDEX_FROM_BIT(number); + u32int off = OFFSET_FROM_BIT(number); + m_data[idx] |= (0x1 << off); + m_usedCount++; +} + +void Bitset::clearBit(u32int number) { + u32int idx = INDEX_FROM_BIT(number); + u32int off = OFFSET_FROM_BIT(number); + m_data[idx] &= ~(0x1 << off); + m_usedCount--; +} + +bool Bitset::testBit(u32int number) { + u32int idx = INDEX_FROM_BIT(number); + u32int off = OFFSET_FROM_BIT(number); + return (m_data[idx] & (0x1 << off)); +} + +u32int Bitset::firstFreeBit() { + for (u32int i = 0; i < INDEX_FROM_BIT(m_size); i++) { + if (m_data[i] != 0xFFFFFFFF) { + for (int j = 0; j < 32; j++) { + if (!(m_data[i] & (0x1 << j))) { + return (i * 4 * 8) + j; + } + } + } + } + return (u32int) - 1; +} + +u32int Bitset::usedBits() { + return m_usedCount; +} diff --git a/Source/Library/Common/Bitset.class.h b/Source/Library/Common/Bitset.class.h new file mode 100644 index 0000000..8a0707d --- /dev/null +++ b/Source/Library/Common/Bitset.class.h @@ -0,0 +1,31 @@ +#ifndef DEF_BITSET_CLASS_H +#define DEF_BITSET_CLASS_H + +#include <common.h> + +#define INDEX_FROM_BIT(a) (a/(8*4)) +#define OFFSET_FROM_BIT(a) (a%(8*4)) + +class Bitset { + private: + u32int m_size; + u32int *m_data; + u32int m_usedCount; + + public: + Bitset(); + Bitset(u32int size); + Bitset(u32int size, u32int *ptr); + ~Bitset(); + + void init(u32int size, u32int *ptr); + + void setBit(u32int number); + void clearBit(u32int number); + bool testBit(u32int number); + u32int firstFreeBit(); + + u32int usedBits(); +}; + +#endif diff --git a/Source/Library/Common/ByteArray.class.cpp b/Source/Library/Common/ByteArray.class.cpp new file mode 100644 index 0000000..2a42702 --- /dev/null +++ b/Source/Library/Common/ByteArray.class.cpp @@ -0,0 +1,59 @@ +#include "ByteArray.class.h" + +//Define size of a uchar_repr_t +#define CHARSZ(x) (x.c[0] == 0 ? 0 : (x.c[1] == 0 ? 1 : (x.c[2] == 0 ? 2 : (x.c[3] == 0 ? 3 : 4)))) + +using namespace CMem; + +ByteArray::ByteArray(const char* c) : BasicString<u8int>() { + m_length = strlen(c); + memcpy(m_string, (u8int*)c, m_length); +} + +void ByteArray::affect(const String &string, u8int encoding) { + m_length = 0; + for (u32int i = 0; i < string.size(); i++) { + uchar_repr_t a = string[i].encode(encoding); + m_length += CHARSZ(a); + } + if (m_string != 0) delete m_string; + if (m_length == 0) { + m_string = 0; + return; + } + m_string = new u8int[m_length]; + u32int x = 0; + for (u32int i = 0; i < string.size(); i++) { + uchar_repr_t a = string[i].encode(encoding); + memcpy(m_string + x, (u8int*)a.c, CHARSZ(a)); + x += CHARSZ(a); + } +} + +void ByteArray::resize(u32int size) { + if (size == m_length) return; + if (size == 0) { + delete m_string; + m_length = 0; + m_string = 0; + } + u8int *nd = new u8int[size]; + if (size < m_length) { + memcpy(nd, m_string, size); + } else { + memcpy(nd, m_string, m_length); + memset(nd + m_length, 0, size - m_length); + } + delete m_string; + m_string = nd; + m_length = size; +} + +String ByteArray::toString (u8int encoding) { + char* c = new char[m_length + 1]; + memcpy((u8int*)c, m_string, m_length); + c[m_length] = 0; //Add NULL terminator + String r(c, encoding); + delete c; + return r; +} diff --git a/Source/Library/Common/ByteArray.class.h b/Source/Library/Common/ByteArray.class.h new file mode 100644 index 0000000..339e0d4 --- /dev/null +++ b/Source/Library/Common/ByteArray.class.h @@ -0,0 +1,27 @@ +#ifndef DEF_BYTEARRAY_CLASS_H +#define DEF_BYTEARRAY_CLASS_H + +#include <String.class.h> + +class ByteArray : public BasicString<u8int> { + public: + ByteArray() : BasicString<u8int>() {} + ByteArray(const BasicString<u8int> &bs) : BasicString<u8int>() { + m_length = bs.size(); + m_string = new u8int[m_length]; + for (u32int i = 0; i < m_length; i++) + m_string[i] = bs[i]; + } + ByteArray(const ByteArray& other) : BasicString<u8int>(other) {} + ByteArray(const char* c); + ByteArray(u32int size) : BasicString<u8int>((u8int)0, size) {} + ByteArray(const String &string, u8int encoding = UE_UTF8) : BasicString<u8int>() { affect(string, encoding); } + + void affect(const String& string, u8int encoding = UE_UTF8); + void resize(u32int size); + + String toString(u8int encoding = UE_UTF8); + operator u8int* () { return m_string; } +}; + +#endif diff --git a/Source/Library/Common/CMem.ns.cpp b/Source/Library/Common/CMem.ns.cpp new file mode 100644 index 0000000..37cdf0c --- /dev/null +++ b/Source/Library/Common/CMem.ns.cpp @@ -0,0 +1,35 @@ +#include <common.h> + +namespace CMem { + +//Standard C functions +u8int *memcpy(u8int *dest, const u8int *src, int count) { + for (int i = 0; i < count; i++) { + dest[i] = src[i]; + } + return dest; +} + +u8int *memset(u8int *dest, u8int val, int count) { + for (int i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +u16int *memsetw(u16int *dest, u16int val, int count) { + for (int i = 0; i < count; i++) { + dest[i] = val; + } + return dest; +} + +u32int strlen(const char *str) { + u32int i = 0; + while (str[i]) { + i++; + } + return i; +} + +} diff --git a/Source/Library/Common/CMem.ns.h b/Source/Library/Common/CMem.ns.h new file mode 100644 index 0000000..f0c15da --- /dev/null +++ b/Source/Library/Common/CMem.ns.h @@ -0,0 +1,17 @@ +#ifdef DEF_COMMON + +#ifndef DEF_CMEM_NS_H +#define DEF_CMEM_NS_H + +//This namespace contains basic memory managment functions + +namespace CMem { + u8int *memcpy(u8int *dest, const u8int *src, int count); + u8int *memset(u8int *dest, u8int val, int count); + u16int *memsetw(u16int *dest, u16int val, int count); + u32int strlen(const char *str); +} + +#endif + +#endif diff --git a/Source/Library/Common/Heap-index.class.cpp b/Source/Library/Common/Heap-index.class.cpp new file mode 100644 index 0000000..3280736 --- /dev/null +++ b/Source/Library/Common/Heap-index.class.cpp @@ -0,0 +1,51 @@ +#include "Heap.class.h" + +/* + * Implementation of the functions for managing heap index + */ + +void Heap::insertIntoIndex(heap_header_t *e) { + //If index is full, return + if ((m_index.size * sizeof(heap_header_t*) + (u32int)m_index.data) >= m_start) return; + + u32int iterator = 0; + while (iterator < m_index.size && m_index.data[iterator]->size < e->size) { + if (m_index.data[iterator] == e) return; + iterator++; + } + if (iterator == m_index.size) { + m_index.data[m_index.size++] = e; + } else { + u32int pos = iterator; + iterator = m_index.size; + while (iterator > pos) { + m_index.data[iterator] = m_index.data[iterator - 1]; + iterator--; + } + m_index.size++; + m_index.data[pos] = e; + } +} + +u32int Heap::findIndexEntry(heap_header_t *e) { + for (u32int i = 0; i < m_index.size; i++) { + if (m_index.data[i] == e) + return i; + } + return (u32int) - 1; +} + +void Heap::removeFromIndex(u32int idx) { + m_index.size--; + while (idx < m_index.size) { + m_index.data[idx] = m_index.data[idx + 1]; + idx++; + } +} + +void Heap::removeFromIndex(heap_header_t *e) { + u32int i = findIndexEntry(e); + if (i != (u32int) - 1) { + removeFromIndex(i); + } +} diff --git a/Source/Library/Common/Heap.class.cpp b/Source/Library/Common/Heap.class.cpp new file mode 100644 index 0000000..34e4dc4 --- /dev/null +++ b/Source/Library/Common/Heap.class.cpp @@ -0,0 +1,232 @@ +#include "Heap.class.h" + +#ifdef THIS_IS_MELON_KERNEL +#include <MemoryManager/PageDirectory.class.h> +#define ALLOC(x) m_pagedir->allocFrame(x, m_user, m_rw) +#define FREE(x) m_pagedir->freeFrame(x) +#else +#define ALLOC(x) m_process.allocPage(x) +#define FREE(x) m_process.freePage(x) +#endif + +#ifdef THIS_IS_MELON_KERNEL +Heap::Heap() : m_mutex(MUTEX_FALSE) { +#else +Heap::Heap() : m_mutex(MUTEX_FALSE), m_process(Process::get()) { +#endif + m_usable = false; + m_index.data = 0; + m_index.size = 0; +} + +Heap::~Heap() { + //TODO (optionnal) : free pages. +} + +#ifdef THIS_IS_MELON_KERNEL +void Heap::create(u32int start, u32int size, u32int idxsize, PageDirectory* pagedir, bool user, bool rw) { +#else +void Heap::create(u32int start, u32int size, u32int idxsize) { +#endif + if (m_usable) return; + + if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; + if (size & 0x0FFF) size = (size & 0xFFFFF000) + 0x1000; + m_start = start + idxsize; //m_start is start of real data, start is start of index. + m_end = start + size; + +#ifdef THIS_IS_MELON_KERNEL + m_pagedir = pagedir; + m_user = user; + m_rw = rw; +#endif + + //Allocate frames for heap + for (u32int i = start ; i < m_end; i += 0x1000) { + ALLOC(i); + } +#ifdef THIS_IS_MELON_KERNEL + m_pagedir->switchTo(); +#endif + + m_index.data = (heap_header_t **)start; //Set index start. start == start of all heap + m_index.size = 0; + + heap_header_t *hole = (heap_header_t*) m_start; //m_start == start of data + hole->size = (m_end - m_start); + hole->magic = HEAP_MAGIC; + hole->is_hole = true; + + heap_footer_t *hole_footer = (heap_footer_t*) (m_end - sizeof(heap_footer_t)); + hole_footer->header = hole; + hole_footer->magic = HEAP_MAGIC; + + insertIntoIndex(hole); + + m_usable = true; + m_free = (m_end - m_start); + + m_mutex.unlock(); +} + +void Heap::expand(u32int quantity) { + if (quantity & 0x00000FFF) + quantity = (quantity & 0xFFFFF000) + 0x1000; + + u32int newEnd = m_end + quantity; + + for (u32int i = m_end; i < newEnd; i++) { + ALLOC(i); + } + + heap_footer_t *last_footer = (heap_footer_t*) (m_end - sizeof(heap_footer_t)); + heap_header_t *last_header = last_footer->header; + if (last_header->is_hole) { //Last block of heap is a hole, update its size + removeFromIndex(last_header); + last_header->size += quantity; + + last_footer = (heap_footer_t*) (newEnd - sizeof(heap_footer_t)); + + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + insertIntoIndex(last_header); + } else { //Last block is not a hole. Just add a new hole at the end + last_header = (heap_header_t*)m_end; + last_footer = (heap_footer_t*) (newEnd - sizeof(heap_footer_t)); + + last_header->is_hole = true; + last_header->magic = HEAP_MAGIC; + last_header->size = quantity; + + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + + insertIntoIndex(last_header); + } + + m_end = newEnd; + m_free += quantity; +} + +void Heap::contract() { //Automatically work out how much we can contract + heap_footer_t *last_footer = (heap_footer_t*) (m_end - sizeof(heap_footer_t)); + heap_header_t *last_header = last_footer->header; + if (last_header->is_hole == false) return; //We need a hole at end of heap + + u32int quantity = 0; + while ((m_end - m_start) - quantity > HEAP_MIN_SIZE and + (last_header->size - quantity) > 0x1000) //Always keep at least 0x1000 free at end + quantity += 0x1000; + if (quantity == 0) return; + + u32int newEnd = m_end - quantity; + m_free -= quantity; + + removeFromIndex(last_header); + last_header->size -= quantity; + last_footer = (heap_footer_t*)((u32int)last_footer - quantity); + last_footer->magic = HEAP_MAGIC; + last_footer->header = last_header; + insertIntoIndex(last_header); + + for (u32int i = newEnd; i < m_end; i += 0x1000) { + FREE(i); + } + + m_end = newEnd; +} + +void *Heap::alloc(u32int sz, bool no_expand) { + m_mutex.waitLock(); + + u32int newsize = sz + sizeof(heap_header_t) + sizeof(heap_footer_t); + u32int iterator = 0; + while (iterator < m_index.size) { + if (m_index.data[iterator]->size >= newsize) break; + iterator++; + } + if (iterator == m_index.size) { //No hole is big enough + if (no_expand) { + m_mutex.unlock(); + return 0; + } + expand((sz & 0xFFFFF000) + 0x1000); + m_mutex.unlock(); + return alloc(sz, true); //Recurse call + } + + heap_header_t *loc = m_index.data[iterator]; + heap_footer_t *footer = (heap_footer_t*)((u32int)loc + loc->size - sizeof(heap_footer_t)); + loc->is_hole = false; //Update current header + + removeFromIndex(loc); + + //Here we create a new hole after currently allocated block, but only if we have enough space. If we don't, we simply allocate a bigger block so that we don't loose space + if (loc->size > (newsize + sizeof(heap_header_t) + sizeof(heap_footer_t))) { + loc->size = newsize; //Update header for return block + + heap_footer_t *newfooter = (heap_footer_t*)((u32int)loc + newsize - sizeof(heap_footer_t)); //Write footer for return block + newfooter->header = loc; + newfooter->magic = HEAP_MAGIC; + + heap_header_t *nextloc = (heap_header_t*)((u32int)loc + newsize); //Write header for new hole + nextloc->is_hole = true; + nextloc->magic = HEAP_MAGIC; + nextloc->size = ((u32int)footer - (u32int)nextloc + sizeof(heap_footer_t)); + + footer->header = nextloc; //Write footer for new hole + footer->magic = HEAP_MAGIC; + + insertIntoIndex(nextloc); + } + + m_free -= loc->size; + + m_mutex.unlock(); + + return (void*)((u32int)loc + sizeof(heap_header_t)); +} + +void Heap::free(void *ptr) { + if (ptr == 0) return; + + heap_header_t *header = (heap_header_t*) ((u32int)ptr - sizeof(heap_header_t)); + heap_footer_t *footer = (heap_footer_t*)((u32int)header + header->size - sizeof(heap_footer_t)); + if (header->magic != HEAP_MAGIC or footer->magic != HEAP_MAGIC) return; + + m_mutex.waitLock(); + + m_free += header->size; + + //Unify left + heap_footer_t *prev_footer = (heap_footer_t*)((u32int)header - sizeof(heap_footer_t)); + if (prev_footer->magic == HEAP_MAGIC && prev_footer->header->is_hole) { + header = prev_footer->header; + removeFromIndex(header); + + footer->header = header; + header->size = ((u32int)footer - (u32int)header + sizeof(heap_footer_t)); + } + + //Unify right + heap_header_t *next_header = (heap_header_t*)((u32int)footer + sizeof(heap_footer_t)); + if (next_header->magic == HEAP_MAGIC && next_header->is_hole) { + removeFromIndex(next_header); + footer = (heap_footer_t*)((u32int)footer + next_header->size); + + footer->header = header; + header->size = ((u32int)footer - (u32int)header + sizeof(heap_footer_t)); + } + + header->is_hole = true; + + insertIntoIndex(header); + + if ((u32int)footer == (m_end - sizeof(heap_footer_t)) and + header->size >= 0x2000 and (m_end - m_start > HEAP_MIN_SIZE)) { + contract(); + } + + m_mutex.unlock(); +} diff --git a/Source/Library/Common/Heap.class.h b/Source/Library/Common/Heap.class.h new file mode 100644 index 0000000..f5895c7 --- /dev/null +++ b/Source/Library/Common/Heap.class.h @@ -0,0 +1,92 @@ +#ifndef DEF_HEAP_CLASS_H +#define DEF_HEAP_CLASS_H + +#include <common.h> +#include <Mutex.class.h> + +//Heap minimum size : 2M +#define HEAP_MIN_SIZE 0x00200000 +//Heap magic number, for verifications +#define HEAP_MAGIC 0xBEEF1337 + +struct heap_header_t { + u32int magic; + bool is_hole; + u32int size; +}; + +struct heap_footer_t { + u32int magic; + heap_header_t *header; +}; + +struct heap_index_t { + heap_header_t **data; + u32int size; +}; + +#ifdef THIS_IS_MELON_KERNEL +class PageDirectory; +#else +#include <Binding/Process.class.h> +#endif + +class Heap { + private: + u32int m_free, m_start, m_end; + bool m_usable; + heap_index_t m_index; +#ifdef THIS_IS_MELON_KERNEL + bool m_user, m_rw; + PageDirectory* m_pagedir; +#else + Process m_process; +#endif + + Mutex m_mutex; + + void insertIntoIndex(heap_header_t *e); + u32int findIndexEntry(heap_header_t *e); + void removeFromIndex(u32int idx); + void removeFromIndex(heap_header_t *e); + + void expand(u32int quantity); + void contract(); //Quantity is automatically calculated + + public: + Heap(); + ~Heap(); + +#ifdef THIS_IS_MELON_KERNEL + void create(u32int start, u32int size, u32int idxsize, PageDirectory* pagedir, bool user, bool rw); +#else + void create(u32int start, u32int size, u32int idxsize); +#endif + + void* alloc(u32int sz, bool no_expand = false); + void free(void* ptr); + + bool usable() { + m_mutex.waitLock(); + bool ret = m_usable; + m_mutex.unlock(); + return ret; + } + + u32int size() { + m_mutex.waitLock(); + u32int ret = m_end - m_start; + m_mutex.unlock(); + return ret; + } + + u32int free() { + m_mutex.waitLock(); + u32int ret = m_free; + m_mutex.unlock(); + return ret; + } +}; + + +#endif diff --git a/Source/Library/Common/Mutex.class.cpp b/Source/Library/Common/Mutex.class.cpp new file mode 100644 index 0000000..2e9a63c --- /dev/null +++ b/Source/Library/Common/Mutex.class.cpp @@ -0,0 +1,45 @@ +#include "Mutex.class.h" + +#ifdef THIS_IS_MELON_KERNEL +#include <TaskManager/Task.ns.h> +#endif + +#ifdef THIS_IS_MELON_USERLAND +#include <Binding/Thread.class.h> +#endif + +u32int atomic_exchange(u32int* ptr, u32int newval) { + u32int r; + asm volatile("xchg (%%ecx), %%eax" : "=a"(r) : "c"(ptr), "a"(newval)); + return r; +} + +Mutex::Mutex(u32int locked) { + m_locked = locked; +} + +bool Mutex::lock() { + if (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE) return false; //The lock was already locked + return true; +} + +void Mutex::waitLock() { + while (atomic_exchange(&m_locked, MUTEX_TRUE) == MUTEX_TRUE) { +#ifdef THIS_IS_MELON_KERNEL + if (Task::currThread() != 0) Task::currThread()->sleep(10); //Wait 10ms + else return; +#endif + +#ifdef THIS_IS_MELON_USERLAND + Thread::get().sleep(10); +#endif + } +} + +void Mutex::unlock() { + m_locked = MUTEX_FALSE; +} + +bool Mutex::locked() { + return m_locked; +} diff --git a/Source/Library/Common/Mutex.class.h b/Source/Library/Common/Mutex.class.h new file mode 100644 index 0000000..1e3f63d --- /dev/null +++ b/Source/Library/Common/Mutex.class.h @@ -0,0 +1,21 @@ +#ifndef DEF_MUTEX_CLASS_H +#define DEF_MUTEX_CLASS_H + +#include <common.h> + +#define MUTEX_FALSE 0 +#define MUTEX_TRUE 1 + +class Mutex { + private: + u32int m_locked; + + public: + Mutex(u32int locked = MUTEX_FALSE); + bool lock(); //Locks the mutex if it is not locked. Returns true if mutex could be locked, false if already locked + void waitLock(); //Locks the mutex, waiting for it to be unlocked before if necessary + void unlock(); + bool locked(); +}; + +#endif diff --git a/Source/Library/Common/OrderedArray.class.cpp b/Source/Library/Common/OrderedArray.class.cpp new file mode 100644 index 0000000..8b8f24f --- /dev/null +++ b/Source/Library/Common/OrderedArray.class.cpp @@ -0,0 +1,54 @@ +template <typename T> +OrderedArray<T>::OrderedArray(u32int max_size) { + m_array = (T*)Memory::alloc(max_size * sizeof(T*)); + m_size = 0; + m_maxSize = max_size; +} + +template <typename T> +OrderedArray<T>::OrderedArray(T **addr, u32int max_size) { + m_array = addr; + memset((u8int*)addr, 0, max_size * sizeof(T*)); + m_size = 0; + m_maxSize = max_size; +} + +template <typename T> +OrderedArray<T>::~OrderedArray() { + //Free memory +} + +template <typename T> +void OrderedArray<T>::insert(T *element) { + if (m_size == m_maxSize) return; //Array is full + u32int iterator = 0; + while (iterator < m_size && *(m_array[iterator]) < *element) { + iterator++; + } + if (iterator == m_size) { + m_array[m_size++] = element; + } else { + u32int pos = iterator; + while (iterator < m_size) { + iterator++; + m_array[iterator] = m_array[iterator - 1]; + } + m_size++; + m_array[pos] = element; + } +} + +template <typename T> +T *OrderedArray<T>::lookup(int index) { + return m_array[index]; +} + +template <typename T> +void OrderedArray<T>::remove(int index) { + m_size--; + while (index < m_size) { + m_array[index] = m_array[index + 1]; + index++; + } +} + diff --git a/Source/Library/Common/OrderedArray.class.h b/Source/Library/Common/OrderedArray.class.h new file mode 100644 index 0000000..3091249 --- /dev/null +++ b/Source/Library/Common/OrderedArray.class.h @@ -0,0 +1,29 @@ +#ifndef DEF_ORDARRAY_CLASS +#define DEF_ORDARRAY_CLASS + +#include <common.h> + +template <typename T> +class OrderedArray { + private: + T *m_array[]; + u32int m_size; + u32int m_maxSize; + + public: + OrderedArray(u32int max_size); + OrderedArray(T **addr, u32int max_size); + ~OrderedArray(); + + u32int size() { return m_size; } + + void insert(T *element); + T *lookup(int index); + void remove(int index); + + T *operator[] (int index) { return lookup(index); } +}; + +#include "OrderedArray.class.cpp" + +#endif diff --git a/Source/Library/Common/Rand.ns.cpp b/Source/Library/Common/Rand.ns.cpp new file mode 100644 index 0000000..e568678 --- /dev/null +++ b/Source/Library/Common/Rand.ns.cpp @@ -0,0 +1,18 @@ +#include "Rand.ns.h" + +namespace Rand { + +u32int m = 2073741824, a = 50000, b = 1534; +u64int current = RANDOM_SEED; + +u64int rand() { + current = (u32int)(a*current + b); + while (current > m) current -= m; + return current; +} + +u64int max() { + return m; +} + +} diff --git a/Source/Library/Common/Rand.ns.h b/Source/Library/Common/Rand.ns.h new file mode 100644 index 0000000..71d4f60 --- /dev/null +++ b/Source/Library/Common/Rand.ns.h @@ -0,0 +1,12 @@ +#ifndef DEF_RAND_NS_H +#define DEF_RAND_NS_H + +#include <common.h> + +namespace Rand { + u64int rand(); + u64int max(); +} + +#endif + diff --git a/Source/Library/Common/SimpleList.class.h b/Source/Library/Common/SimpleList.class.h new file mode 100644 index 0000000..7b731db --- /dev/null +++ b/Source/Library/Common/SimpleList.class.h @@ -0,0 +1,72 @@ +#ifndef DEF_SIMPLELIST_CLASS_H +#define DEF_SIMPLELIST_CLASS_H + +#include <common.h> + +/* This class implements a singly linked list. It is also used to represent one of its elements. */ + +template <typename T> +class SimpleList { + protected: + T m_value; + SimpleList<T>* m_next; + + public: + SimpleList(const T& value, SimpleList<T>* next = 0) : m_value(value), m_next(next) {} + ~SimpleList() { + if (m_next != 0) + delete m_next; + } + + T& v() { return m_value; } + T& operator* () { return m_value; } + + SimpleList<T>* cons(const T& value) { + return new SimpleList<T>(value, this); + } + + SimpleList<T>* next() { + return m_next; + } + + SimpleList<T>* last() { + if (m_next == 0) return this; + return m_next->last(); + } + + SimpleList<T>* delThis() { + SimpleList<T>* ret = m_next; + Mem::free(this); + return ret; + } + + void delNext() { + if (m_next == 0) return; + SimpleList<T>* temp = m_next; + m_next = m_next->m_next; + Mem::free(temp); + } + + SimpleList<T>* removeOnce(const T& value) { + if (value == m_value) return delThis(); + for (SimpleList<T> *iter = this; iter->next() != 0; iter = iter->next()) { + if (iter->next()->v() == value) { + iter->delNext(); + break; + } + } + return this; + } + + bool isEnd() { + return m_next == 0; + } + + u32int size() { + if (m_next == 0) + return 0; + return m_next->size() + 1; + } +}; + +#endif diff --git a/Source/Library/Common/String.class.cpp b/Source/Library/Common/String.class.cpp new file mode 100644 index 0000000..ac0eba0 --- /dev/null +++ b/Source/Library/Common/String.class.cpp @@ -0,0 +1,201 @@ +#include "String.class.h" +#include <Vector.class.h> + +using namespace CMem; //strlen and memcpy + +String String::hex(u32int number) { + String ret; + ret.m_length = 10; + ret.m_string = new WChar[11]; + ret.m_string[0] = '0'; + ret.m_string[1] = 'x'; + ret.m_string[10] = 0; + + char hexdigits[] = "0123456789ABCDEF"; + for (unsigned int j = 0; j < 8; j++) { + ret.m_string[j + 2] = hexdigits[(number & 0xF0000000) >> 28]; + number = number << 4; + } + return ret; +} + +String String::number(s32int number) { + if (number == 0) return String("0"); + bool negative = false; + if (number < 0) { + negative = true; + number = 0 - number; + } + u32int order = 0, temp = number; + char numbers[] = "0123456789"; + while (temp > 0) { + order++; + temp /= 10; + } + + String ret; + ret.m_length = order; + ret.m_string = new WChar[order + 1]; + + for (u32int i = order; i > 0; i--) { + ret.m_string[i - 1] = numbers[number % 10]; + number /= 10; + } + + ret.m_string[order] = 0; + + if (negative) return String("-") += ret; + + return ret; +} + +String String::unserialize(u32int w) { + u32int* a = (u32int*)w; + String ret; + ret.m_length = a[0]; + ret.m_string = (WChar*)Mem::alloc(a[0] * sizeof(WChar)); + for (u32int i = 0; i < a[0]; i++) { + ret[i] = a[i + 1]; + } + return ret; +} + +u32int String::serialize() const { + u32int* x = (u32int*)Mem::mkXchgSpace((m_length + 1) * sizeof(u32int)); + x[0] = m_length; + for (u32int i = 0; i < m_length; i++) { + x[i + 1] = m_string[i]; + } + return (u32int)x; +} + +String::String(const char* string, u8int encoding) { + m_string = 0; + m_length = 0; + affect(string, encoding); +} + +void String::affect (const char* string, u8int encoding) { + m_length = WChar::utfLen(string, encoding); + if (m_string != 0) delete [] m_string; + if (m_length == 0) { + m_string = 0; + return; + } + m_string = new WChar[m_length + 1]; + int i = 0, l = strlen(string), c = 0; + while (i < l) { + i += m_string[c].affect(string + i, encoding); + c++; + } + m_string[m_length] = 0; +} + +bool String::compare (const char* string, u8int encoding) const { + if (m_length != WChar::utfLen(string, encoding)) return false; + int i = 0, l = strlen(string), c = 0; + WChar tmp; + while (i < l) { + i += tmp.affect(string + i, encoding); + if (m_string[c] != tmp) return false; + c++; + } + return true; +} + +String& String::append (const char* other, u8int encoding) { + WChar* newdata = new WChar[m_length + WChar::utfLen(other, encoding) + 1]; + for (u32int i = 0; i < m_length; i++) { + newdata[i] = m_string[i]; + } + int i = 0, l = strlen(other), c = 0; + while (i < l) { + i += newdata[c + m_length].affect(other + i, encoding); + c++; + } + if (m_string != 0) delete [] m_string; + m_string = newdata; + m_length += strlen(other); + m_string[m_length] = 0; + return *this; +} + +String String::concat (const String &other) const { //Can be optimized + String ret(*this); + return (ret += other); +} + +String String::concat (const char* other, u8int encoding) const { //Can be optimized + String ret(*this); + return (ret.append(other, encoding)); +} + +String String::concat (WChar other) const { + String ret(*this); + return (ret += other); +} + +s64int String::toInt() const { + if (m_string == 0) return 0; + s32int pos = 0; + s64int number = 0; + bool negative = false; + if (m_string[0].value == '-') { + negative = true; + pos = 1; + } + while (m_string[pos] >= '0' && m_string[pos] <= '9') { + number *= 10; + number += (m_string[pos].value - '0'); + pos++; + } + if (negative) return 0 - number; + return number; +} + +u64int String::toInt16() const { + if (m_string == 0) return 0; + u32int pos = 0; + u64int number = 0; + if (m_string[0].value == '0' && m_string[1].value == 'x') pos = 2; + while (1) { + char c = m_string[pos]; + pos++; + if (c >= 'a' && c <= 'f') c -= ('a' - 'A'); //To uppercase + if (c >= '0' && c <= '9') { + number *= 16; + number += (c - '0'); + continue; + } + if (c >= 'A' && c <= 'F') { + number *= 16; + number += (c - 'A' + 10); + continue; + } + break; + } + return number; +} + +Vector<String> String::split(WChar c) const { + Vector<String> ret; + ret.push(String("")); + for (u32int i = 0; i < m_length; i++) { + if (m_string[i] == c) { + ret.push(String("")); + } else { + ret.back() += m_string[i]; + } + } + return ret; +} + +String String::substr(s32int start, u32int size) { + if (start < 0) start = m_length - start; + String ret; + ret.m_string = new WChar[size + 1]; + ret.m_length = size; + memcpy((u8int*)ret.m_string, (const u8int*)(m_string + start), size * sizeof(WChar)); + ret.m_string[size] = 0; + return ret; +} diff --git a/Source/Library/Common/String.class.h b/Source/Library/Common/String.class.h new file mode 100644 index 0000000..0d48ce6 --- /dev/null +++ b/Source/Library/Common/String.class.h @@ -0,0 +1,49 @@ +#ifndef DEF_STRING_CLASS +#define DEF_STRING_CLASS + +#include <BasicString.class.h> +#include <WChar.class.h> + +class String : public BasicString<WChar> { + public: + static String hex(u32int number); + static String number(s32int number); + + static String unserialize(u32int w); + u32int serialize() const; + + String(const char* string, u8int encoding = UE_UTF8); + String() : BasicString<WChar>() {} + String(const String &other) : BasicString<WChar> (other) {} + + void affect(const char* string, u8int encoding = UE_UTF8); + void operator= (const char* other) { affect(other); } + void operator= (const String& other) { BasicString<WChar>::affect(other); } + + bool compare(const char* string, u8int encoding = UE_UTF8) const; + bool operator== (const char* other) const { return compare(other); } + bool operator!= (const char* other) { return !compare(other); } + bool operator== (const String& other) const { return BasicString<WChar>::compare(other); } + bool operator!= (const String& other) const { return !BasicString<WChar>::compare(other); } + + String& append(const char* other, u8int encoding = UE_UTF8); + String &operator+= (const String &other) { BasicString<WChar>::append(other); return *this; } + String &operator+= (const char* other) { return append(other); } + String &operator+= (WChar other) { BasicString<WChar>::append(other); return *this; } + + String concat(const String &other) const; + String concat(const char* other, u8int encoding = UE_UTF8) const; + String concat(WChar other) const; + String operator+ (const String &other) const { return concat(other); } + String operator+ (const char* other) const { return concat(other); } + String operator+ (WChar other) const { return concat(other); } + + s64int toInt() const; //Convert from DEC + u64int toInt16() const; //Convert from HEX + + Vector<String> split(WChar c) const; + + String substr(s32int start, u32int size); +}; + +#endif diff --git a/Source/Library/Common/Vector.class.cpp b/Source/Library/Common/Vector.class.cpp new file mode 100644 index 0000000..c546a42 --- /dev/null +++ b/Source/Library/Common/Vector.class.cpp @@ -0,0 +1,135 @@ +using namespace CMem; //strlen and memcpy + +#define DELDATA if (m_data != NULL and m_size != 0) { \ + for (u32int i = 0; i < m_size; i++) { \ + m_data[i].~T(); \ + } \ + Mem::free(m_data); \ +} + +template <typename T> +Vector<T>::Vector() { + //DEBUG_HEX((u32int)this); DEBUG(" NEW EMPTY"); + //DEBUG_HEX(sizeof(T)); DEBUG(" sizeof(T)"); + m_data = 0; + m_size = 0; +} + +template <typename T> +Vector<T>::Vector(u32int size) { + //DEBUG_HEX((u32int)this); DEBUG(" NEW ZERO"); + m_data = new T[size]; + m_size = size; +} + +template <typename T> +Vector<T>::Vector(u32int size, const T& value) { + //DEBUG_HEX((u32int)this); DEBUG(" NEW FILLED"); + //m_data = (T*)Mem::alloc(size * sizeof(T)); + m_data = new T[size]; + m_size = size; + for (u32int i = 0; i < m_size; i++) { + new (&m_data[i]) T(value); + } + /*for (u32int i = 0; i < size; i++) { + m_data[i] = new(&m_data[i]) T(value); + }*/ +} + +template <typename T> +Vector<T>::Vector(const Vector<T> &other) { + //DEBUG_HEX((u32int)this); DEBUG(" COPY REF"); + m_size = other.m_size; + m_data = (T*)Mem::alloc(m_size * sizeof(T)); + for (u32int i = 0; i < m_size; i++) { + new(&m_data[i]) T(other.m_data[i]); + } +} + +template <typename T> +Vector<T>& Vector<T>::operator= (const Vector<T> &other) { + //DEBUG_HEX((u32int)this); DEBUG(" COPY EQ"); + DELDATA; + m_size = other.m_size; + m_data = (T*)Mem::alloc(m_size * sizeof(T)); + for (u32int i = 0; i < m_size; i++) { + new(&m_data[i]) T(other.m_data[i]); + } + return *this; +} + +template <typename T> +Vector<T>::~Vector() { + //DEBUG_HEX((u32int)this); DEBUG(" DELETE"); + DELDATA; + //if (m_data != 0) delete[] m_data; +} + +template <typename T> +T& Vector<T>::operator[] (u32int index) const { + return m_data[index]; +} + +template <typename T> +void Vector<T>::push(const T& element) { + T* newdata = (T*)Mem::alloc((m_size + 1) * sizeof(T)); + if (m_size != 0 and m_data != 0) { + memcpy((u8int*)newdata, (const u8int*) m_data, m_size * sizeof(T)); + } + new(&newdata[m_size]) T(element); //Construct by copy + //newdata[m_size] = element; + m_size++; + Mem::free(m_data); + m_data = newdata; +} + +/* template <typename T> +void Vector<T>::push(T& element) { + T* newdata = (T*)Memory::alloc((m_size + 1) * sizeof(T)); + memcpy((u8int*)newdata, (const u8int*) m_data, m_size * sizeof(T)); + //memcpy((u8int*)newdata + (m_size * sizeof(T)), (const u8int*) element, sizeof(T)); //Copy + new(&newdata[m_size]) T(element); //Construct by copy + m_size++; + Memory::free(m_data); + m_data = newdata; +} */ + +template <typename T> +void Vector<T>::pop() { + m_size--; + //delete(&m_data[m_size], &m_data[m_size]); //implicitly call destructor with placement delete + m_data[m_size].~T(); //Call destructor + T* newdata = (T*)Mem::alloc(m_size * sizeof(T)); + memcpy((u8int*)newdata, (const u8int*) m_data, m_size * sizeof(T)); + Mem::free(m_data); + m_data = newdata; +} + +template <typename T> +T& Vector<T>::back() const { + return m_data[m_size - 1]; +} + +template <typename T> +T& Vector<T>::front() const { + return m_data[0]; +} + + +template <typename T> +u32int Vector<T>::size() const { + return m_size; +} + +template <typename T> +bool Vector<T>::empty() const { + return m_size == 0; +} + +template <typename T> +void Vector<T>::clear() { + if (empty()) return; + DELDATA + m_data = 0; + m_size = 0; +} diff --git a/Source/Library/Common/Vector.class.h b/Source/Library/Common/Vector.class.h new file mode 100644 index 0000000..436e2f9 --- /dev/null +++ b/Source/Library/Common/Vector.class.h @@ -0,0 +1,36 @@ +#ifndef DEF_VECTOR_CLASS +#define DEF_VECTOR_CLASS + +#include <common.h> + +template <typename T> +class Vector { + private: + T *m_data; + u32int m_size; + + public: + Vector(); + Vector(u32int size); + Vector(u32int size, const T& value); + Vector(const Vector<T> &other); + Vector<T>& operator= (const Vector<T> &other); + ~Vector(); + + T& operator[] (u32int index) const; + + void push(const T& element); + //void push(T& element); + void pop(); + + T& back() const; + T& front() const; + + u32int size() const; + bool empty() const; + void clear(); +}; + +#include "Vector.class.cpp" + +#endif diff --git a/Source/Library/Common/WChar.class.cpp b/Source/Library/Common/WChar.class.cpp new file mode 100644 index 0000000..5485bb8 --- /dev/null +++ b/Source/Library/Common/WChar.class.cpp @@ -0,0 +1,155 @@ +#include "WChar.class.h" + +#ifdef THIS_IS_MELON_KERNEL +using namespace CMem; +#endif + +#ifdef THIS_IS_MELON_USERLAND +using namespace CMem; +#endif + +WChar WChar::CP437[] = { //These are the UTF8 equivalents for the 128 extra characters of code page 437 + "Ç", "ü", "é", "â", "ä", "à", "å", "ç", "ê", "ë", "è", "ï", "î", "ì", "Ä", "Å", + "É", "æ", "Æ", "ô", "ö", "ò", "û", "ù", "ÿ", "Ö", "Ü", "¢", "£", "¥", "₧", "ƒ", + "á", "í", "ó", "ú", "ñ", "Ñ", "ª", "º", "¿", "⌐", "¬", "½", "¼", "¡", "«", "»", + "░", "▒", "▓", "│", "┤", "╡", "╢", "╖", "╕", "╣", "║", "╗", "╝", "╜", "╛", "┐", + "└", "┴", "┬", "├", "─", "┼", "╞", "╟", "╚", "╔", "╩", "╦", "╠", "═", "╬", "¤", + "╨", "╤", "╥", "╙", "╘", "╒", "╓", "╫", "╪", "┘", "┌", "█", "▄", "▌", "▐", "▀", + "α", "ß", "Γ", "π", "Σ", "σ", "µ", "τ", "Φ", "Θ", "Ω", "δ", "∞", "φ", "ε", "∩", + "≡", "±", "≥", "≤", "⌠", "⌡", "÷", "≈", "°", "∙", "·", "√", "ⁿ", "²", "■", "⍽" +}; + +WChar::WChar() { + value = 0; +} + +WChar::WChar(char c) { + affectAscii(c); +} + +WChar::WChar(const char* c, u8int encoding) { + if (encoding == UE_UTF8) affectUtf8(c); + if (encoding == UE_UTF16) affectUtf16(c); + if (encoding == UE_UTF32) affectUtf32(c); +} + +u32int WChar::ucharLen(const char* c, u8int encoding) { + if (encoding == UE_UTF8) { + if ((c[0] & 0x80) == 0) return 1; + else if ((c[0] & 0xE0) == 0xC0) return 2; + else if ((c[0] & 0xF0) == 0xE0) return 3; + else if ((c[0] & 0xF8) == 0xF0) return 4; + else return 1; + } else if (encoding == UE_UTF16) { + if ((c[0] & 0xFC) == 0xD8 and (c[2] & 0xFC) == 0xDC) return 4; + else return 2; + } else if (encoding == UE_UTF32) { + return 4; + } + return 1; +} + +u32int WChar::utfLen(const char* c, u8int encoding) { + int i = 0, l = strlen(c), co = 0; + while (i < l) { + i += ucharLen(c + i, encoding); + co++; + } + return co; +} + +void WChar::affectAscii(char c) { + if (c >= 0) value = c; + else value = CP437[c + 128]; +} + +u32int WChar::affectUtf8(const char* c) { //Returns the number of bytes for the character + if ((c[0] & 0x80) == 0) { + value = c[0]; //0x80 = 10000000b + return 1; + } + if ((c[0] & 0xE0) == 0xC0) { // 11100000b, 11000000b + value = ((c[0] & 0x1F) << 6) | (c[1] & 0x3F); + if (value < 128) value = 0; //Bad value + return 2; + } + if ((c[0] & 0xF0) == 0xE0) { // 11110000b, 11100000b + value = ((c[0] & 0x0F) << 12) | ((c[1] & 0x3F) << 6) | (c[2] & 0x3F); + if (value < 2048) value = 0; //Bad value + if (value >= 0xD800 and value <= 0xDFFF) value = 0; //These values are unallowed + if (value >= 0xFFFE and value <= 0xFFFF) value = 0; + return 3; + } + if ((c[0] & 0xF8) == 0xF0) { // 11111000b, 11110000b + value = ((c[0] & 0x0E) << 18) | ((c[1] & 0x3F) << 12) | ((c[2] & 0x3F) << 6) | (c[3] & 0x3F); + if (value < 65536) value = 0; //Bad value + return 4; + } + value = 0; //Something wrong happenned + return 1; +} + +u32int WChar::affectUtf16(const char* c) { + if ((c[0] & 0xFC) == 0xD8 and // 11111100b, 11011000b + (c[2] & 0xFC) == 0xDC) { // 11111100b, 11011100b + u32int w = ((c[0] & 0x03) << 2) | ((c[1] & 0xC0) >> 6); + u32int x = (c[1] & 0x3F); + u32int y = ((c[2] & 0x03) << 8) | (c[2]); + value = ((w + 1) << 16) | (x << 10) | y; + if (value >= 0xD800 and value <= 0xDFFF) value = 0; //These values are unallowed + if (value >= 0xFFFE and value <= 0xFFFF) value = 0; + return 4; + } else { + value = (c[0] << 8) | (c[1]); + if (value >= 0xD800 and value <= 0xDFFF) value = 0; //These values are unallowed + if (value >= 0xFFFE and value <= 0xFFFF) value = 0; + return 2; + } +} + +u32int WChar::affectUtf32(const char* c) { + value = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; + if (value >= 0xD800 and value <= 0xDFFF) value = 0; //These values are unallowed + if (value >= 0xFFFE and value <= 0xFFFF) value = 0; + return 4; +} + +u8int WChar::toAscii() { + if (value < 128) return (char)value; + for (int i = 0; i < 128; i++) { + if (CP437[i] == value) return (i + 128); + } + return '?'; +} + +uchar_repr_t WChar::toUtf8() { + uchar_repr_t r; + r.i = 0; + if (value < 128) { + r.c[0] = value; + } else if (value < 4096) { + r.c[0] = 0xC0 | ((value & 0x07C0) >> 6); + r.c[1] = 0x80 | (value & 0x3F); + } else if (value < 65536) { + r.c[0] = 0xE0 | ((value & 0xF000) >> 12); + r.c[1] = 0x80 | ((value & 0x0FC0) >> 6); + r.c[2] = 0x80 | (value & 0x003F); + } else { + r.c[0] = 0xF0 | ((value & 0x1C0000) >> 18); + r.c[1] = 0x80 | ((value & 0x3F000) >> 12); + r.c[2] = 0x80 | ((value & 0x0FC0) >> 6); + r.c[3] = 0x80 | (value & 0x003F); + } + return r; +} + +//TODO : code WChar::toUtf16 + +uchar_repr_t WChar::toUtf32() { + uchar_repr_t r; + r.c[0] = (value >> 24) & 0xFF; + r.c[1] = (value >> 16) & 0xFF; + r.c[2] = (value >> 8) & 0xFF; + r.c[3] = value & 0xFF; + return r; +} diff --git a/Source/Library/Common/WChar.class.h b/Source/Library/Common/WChar.class.h new file mode 100644 index 0000000..3eca3d3 --- /dev/null +++ b/Source/Library/Common/WChar.class.h @@ -0,0 +1,89 @@ +#ifndef DEF_UCHAR_CLASS_H +#define DEF_UCHAR_CLASS_H + +#include <types.h> + +#ifndef THIS_IS_NOT_MELON +#include <common.h> +#endif + +enum { + UE_UTF8, + UE_UTF16, + UE_UTF32, +}; + +union uchar_repr_t { + char c[4]; + u32int i; +}; + +struct WChar { + u32int value; + static WChar CP437[]; //Codepage 437, used for conversion from/to ascii + + WChar(); //Creates a null character + WChar(char c); //From ascii character + WChar(const char* c, u8int encoding = UE_UTF8); //From utf8 string + + static u32int ucharLen(const char* c, u8int encoding = UE_UTF8); //Returns count of bytes in one unicode character + static u32int utfLen(const char* c, u8int encoding = UE_UTF8); //Returns count of utf8 characters in string + + void affectAscii(char c); + u32int affectUtf8(const char* c); + u32int affectUtf16(const char* c); + u32int affectUtf32(const char* c); + + u32int affect(const char* c, u8int encoding = UE_UTF8) { + if (encoding == UE_UTF8) return affectUtf8(c); + if (encoding == UE_UTF16) return affectUtf16(c); + if (encoding == UE_UTF32) return affectUtf32(c); + affectAscii(c[0]); //Default case :/ + return 1; + } + + u8int toAscii(); + + uchar_repr_t toUtf8(); + uchar_repr_t toUtf16(); + uchar_repr_t toUtf32(); + + uchar_repr_t encode(u8int encoding = UE_UTF8) { + if (encoding == UE_UTF8) return toUtf8(); + //if (encoding == UE_UTF16) return toUtf16(); + if (encoding == UE_UTF32) return toUtf32(); + uchar_repr_t x; + x.c[0] = toAscii(); + return x; + } + + inline WChar operator+ (u32int other) { + WChar r; + r.value = value + other; + return r; + } + inline WChar operator- (u32int other) { + WChar r; + r.value = value - other; + return r; + } + inline WChar& operator+= (u32int other) { + value += other; + return *this; + } + inline WChar& operator-= (u32int other) { + value -= other; + return *this; + } + inline bool operator== (u32int other) { + return value == other; + } + inline u32int operator= (u32int v) { + value = v; + return v; + } + + inline operator u32int () { return value; } +}; + +#endif diff --git a/Source/Library/Common/types.h b/Source/Library/Common/types.h new file mode 100644 index 0000000..ca6f73d --- /dev/null +++ b/Source/Library/Common/types.h @@ -0,0 +1,19 @@ +#ifndef DEF_TYPES_WTF_H +#define DEF_TYPES_WTF_H + +//This file defines base types. It's made to be used also by C programs + +typedef unsigned int addr_t; +typedef unsigned long long u64int; +typedef unsigned int u32int; +typedef unsigned short u16int; +typedef unsigned char u8int; +typedef long long s64int; +typedef int s32int; +typedef short s16int; +typedef char s8int; + +#define U64 unsigned long long +#define S64 long long + +#endif |