Moves ker/ to ker-project.
This commit is contained in:
parent
3e55654df8
commit
3c647cf405
13 changed files with 5 additions and 1157 deletions
|
@ -1,64 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "fixedstring.hpp"
|
||||
|
||||
class BinaryReader
|
||||
{
|
||||
public:
|
||||
const char * const start;
|
||||
const size_t length;
|
||||
private:
|
||||
size_t current;
|
||||
size_t remaining;
|
||||
public:
|
||||
BinaryReader(const void *src, size_t length) :
|
||||
start(reinterpret_cast<const char *>(src)),
|
||||
length(length),
|
||||
current(0),
|
||||
remaining(length)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void jumpTo(size_t offset)
|
||||
{
|
||||
if(offset > this->length) {
|
||||
return;
|
||||
}
|
||||
this->current = offset;
|
||||
this->remaining = this->length - offset;
|
||||
}
|
||||
|
||||
size_t position() const {
|
||||
return this->current;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T read()
|
||||
{
|
||||
if(this->remaining < sizeof(T)) {
|
||||
return T();
|
||||
}
|
||||
const T *ptr = reinterpret_cast<const T*>(this->start + this->current);
|
||||
this->current += sizeof(T);
|
||||
this->remaining -= sizeof(T);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<>
|
||||
inline FixedString BinaryReader::read<FixedString>()
|
||||
{
|
||||
FixedString str;
|
||||
str.len = this->read<uint32_t>();
|
||||
str.front = this->start + this->current;
|
||||
this->current += str.len;
|
||||
this->remaining -= str.len;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <ker/vector.hpp>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "fixedstring.hpp"
|
||||
|
||||
class BinaryWriter
|
||||
{
|
||||
private:
|
||||
ker::Vector<uint8_t> mData;
|
||||
uint32_t mPointer;
|
||||
public:
|
||||
BinaryWriter() : mData(), mPointer(0)
|
||||
{
|
||||
this->mData.reserve(1024);
|
||||
}
|
||||
|
||||
ker::Vector<uint8_t> &data() { return this->mData; }
|
||||
|
||||
const ker::Vector<uint8_t> &data() const { return this->mData; }
|
||||
|
||||
size_t size() const {
|
||||
return this->mData.length();
|
||||
}
|
||||
|
||||
uint32_t tell() const {
|
||||
return this->mPointer;
|
||||
}
|
||||
|
||||
void rewind() {
|
||||
this->mPointer = 0;
|
||||
}
|
||||
|
||||
void fastForwad() {
|
||||
this->mPointer = this->mData.length();
|
||||
}
|
||||
|
||||
void seek(uint32_t position) {
|
||||
this->mPointer = position;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
uint32_t write(const T &bits)
|
||||
{
|
||||
uint32_t loc = this->mPointer;
|
||||
if((this->mPointer + sizeof(T)) > this->mData.length())
|
||||
{
|
||||
this->mData.resize(this->mPointer + sizeof(T));
|
||||
}
|
||||
this->mPointer += sizeof(T);
|
||||
|
||||
uint8_t *data = &(this->mData[loc]);
|
||||
new (data) T (bits);
|
||||
return loc;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
inline uint32_t BinaryWriter::write<FixedString>(const FixedString &bits)
|
||||
{
|
||||
uint32_t loc = this->write<uint32_t>(bits.len);
|
||||
for(uint32_t k = 0; k < bits.len; k++) {
|
||||
this->write<uint8_t>(bits.front[k]);
|
||||
}
|
||||
return loc;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Enables a shared pointer string implementation that does not reallocate memory on copying
|
||||
*/
|
||||
#define ENABLE_SHARED_STRING
|
|
@ -1,152 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <kernel.h>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "pair.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace ker
|
||||
{
|
||||
template<typename Key, typename Value>
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
typedef Pair<Key, Value> Entry;
|
||||
static Value _default;
|
||||
public:
|
||||
Vector<Entry> contents;
|
||||
public:
|
||||
Dictionary() :
|
||||
contents()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Dictionary(const std::initializer_list<Entry> &items)
|
||||
{
|
||||
for(const Entry &entry : items) {
|
||||
this->contents.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary(const Dictionary &other) :
|
||||
contents(other.contents)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Dictionary(Dictionary &&other) :
|
||||
contents(other.contents)
|
||||
{
|
||||
other.contents = Vector<Entry>();
|
||||
}
|
||||
|
||||
Dictionary & operator = (const Dictionary &other)
|
||||
{
|
||||
this->contents = other.contents;
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t length() const {
|
||||
return this->contents.length();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
this->contents.clear();
|
||||
}
|
||||
|
||||
Value &at(const Key &key)
|
||||
{
|
||||
for(auto &&pair : this->contents)
|
||||
{
|
||||
if(pair.first == key) {
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
return this->add(key, Value());
|
||||
}
|
||||
|
||||
const Value &at(const Key &key) const
|
||||
{
|
||||
static Value _default;
|
||||
for(auto &&pair : this->contents)
|
||||
{
|
||||
if(pair.first == key) {
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
die("Key not found in dictionary.");
|
||||
return _default;
|
||||
}
|
||||
|
||||
Value get(const Key &key) const
|
||||
{
|
||||
if(this->contains(key)) {
|
||||
return this->at(key);
|
||||
} else {
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const Key &key) const
|
||||
{
|
||||
for(const auto &pair : this->contents)
|
||||
{
|
||||
if(pair.first == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Value &add(const Key &key, const Value &value)
|
||||
{
|
||||
if(this->contains(key)) {
|
||||
for(auto &&pair : this->contents)
|
||||
{
|
||||
if(pair.first == key) {
|
||||
pair.second = value;
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
} else {
|
||||
return this->contents.append(Entry(key, value)).second;
|
||||
}
|
||||
}
|
||||
|
||||
Value& operator [](const Key &key)
|
||||
{
|
||||
return this->at(key);
|
||||
}
|
||||
|
||||
const Value& operator [](const Key &key) const
|
||||
{
|
||||
return this->at(key);
|
||||
}
|
||||
|
||||
Entry * begin()
|
||||
{
|
||||
return this->contents.begin();
|
||||
}
|
||||
|
||||
Entry * end()
|
||||
{
|
||||
return this->contents.end();
|
||||
}
|
||||
|
||||
const Entry * begin() const
|
||||
{
|
||||
return this->contents.begin();
|
||||
}
|
||||
|
||||
const Entry * end() const
|
||||
{
|
||||
return this->contents.end();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Key, typename Value>
|
||||
Value Dictionary<Key, Value>::_default = Value();
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define FIXED_STRING_AVAILABLE
|
||||
|
||||
#include <ker/string.hpp>
|
||||
|
||||
struct FixedString
|
||||
{
|
||||
uint32_t len;
|
||||
const char *front;
|
||||
|
||||
FixedString() :
|
||||
len(0),
|
||||
front(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
FixedString(const char *first, uint32_t length) :
|
||||
len(length),
|
||||
front(first)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(_STRING_H)
|
||||
FixedString(const char *str) :
|
||||
len(strlen(str)),
|
||||
front(str)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
#if defined(KER_STRING_AVAILABLE)
|
||||
FixedString(const ker::String &text) :
|
||||
FixedString(text.str(), text.length()) {
|
||||
}
|
||||
explicit operator ker::String() {
|
||||
return ker::String(reinterpret_cast<const uint8_t*>(front), len);
|
||||
}
|
||||
#endif
|
||||
#if defined(_GLIBCXX_STRING)
|
||||
FixedString(const std::string &text) :
|
||||
FixedString(text.c_str(), text.size()) {
|
||||
}
|
||||
explicit operator std::string() {
|
||||
return std::string(front, len);
|
||||
}
|
||||
#endif
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#if defined(CIRCUIT_OS)
|
||||
|
||||
inline void* operator new(size_t, void* __p)
|
||||
{
|
||||
return __p;
|
||||
}
|
||||
|
||||
inline void* operator new[](size_t, void* __p)
|
||||
{
|
||||
return __p;
|
||||
}
|
||||
|
||||
inline void operator delete (void*, void*) { }
|
||||
inline void operator delete[](void*, void*) { }
|
||||
|
||||
#endif
|
|
@ -1,54 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace ker
|
||||
{
|
||||
template<typename First, typename Second>
|
||||
struct Pair
|
||||
{
|
||||
First first;
|
||||
Second second;
|
||||
|
||||
Pair() : first(), second() { }
|
||||
|
||||
Pair(const First &first, const Second &second) :
|
||||
first(first),
|
||||
second(second)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Pair(const Pair &other) :
|
||||
first(other.first),
|
||||
second(other.second)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Pair(Pair &&other) :
|
||||
first(other.first),
|
||||
second(other.second)
|
||||
{
|
||||
other.first = First();
|
||||
other.second = Second();
|
||||
}
|
||||
|
||||
Pair & operator = (const Pair &other)
|
||||
{
|
||||
this->first = other.first;
|
||||
this->second = other.second;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T1, typename T2>
|
||||
static inline bool operator == (const Pair<T1,T2> &lhs, const Pair<T1,T2> &rhs)
|
||||
{
|
||||
return (lhs.first == rhs.first) && (lhs.second == rhs.second);
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
static inline bool operator != (const Pair<T1,T2> &lhs, const Pair<T1,T2> &rhs)
|
||||
{
|
||||
return (lhs.first != rhs.first) || (lhs.second != rhs.second);
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
class ReferenceCounted
|
||||
{
|
||||
public:
|
||||
static int32_t counter;
|
||||
private:
|
||||
size_t mReferenceCount;
|
||||
protected:
|
||||
ReferenceCounted() :
|
||||
mReferenceCount(1)
|
||||
{
|
||||
counter++;
|
||||
}
|
||||
|
||||
virtual ~ReferenceCounted() { counter--; }
|
||||
public:
|
||||
void aquire() {
|
||||
this->mReferenceCount += 1;
|
||||
}
|
||||
|
||||
void release() {
|
||||
this->mReferenceCount -= 1;
|
||||
if(this->mReferenceCount == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,310 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#if defined(CIRCUIT_OS)
|
||||
#include <kstdlib.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#define KER_STRING_AVAILABLE
|
||||
|
||||
namespace ker
|
||||
{
|
||||
class String
|
||||
{
|
||||
private:
|
||||
#if defined(ENABLE_SHARED_STRING)
|
||||
uint32_t *mReferences;
|
||||
#endif
|
||||
uint8_t *mText;
|
||||
size_t mLength;
|
||||
|
||||
#if !defined(ENABLE_SHARED_STRING)
|
||||
void copyFrom(const uint8_t *bytes, size_t length)
|
||||
{
|
||||
if(this->mText != nullptr) {
|
||||
free(this->mText);
|
||||
}
|
||||
this->mText = (uint8_t*)malloc(length + 1);
|
||||
memcpy(this->mText, bytes, length);
|
||||
this->mLength = length;
|
||||
this->mText[this->mLength] = 0; // last byte is always 0
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
#if defined(ENABLE_SHARED_STRING)
|
||||
String() :
|
||||
mReferences(nullptr),
|
||||
mText(nullptr),
|
||||
mLength(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Here just plain copy the string resources and increase the reference counter
|
||||
String(const String &other) :
|
||||
mReferences(other.mReferences),
|
||||
mText(other.mText),
|
||||
mLength(other.mLength)
|
||||
{
|
||||
// Increase reference count
|
||||
if(this->mReferences != nullptr) {
|
||||
*this->mReferences += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Here move the string resources and don't modify reference counter
|
||||
String(String &&other) :
|
||||
mReferences(other.mReferences),
|
||||
mText(other.mText),
|
||||
mLength(other.mLength)
|
||||
{
|
||||
other.mReferences = nullptr;
|
||||
other.mText = nullptr;
|
||||
other.mLength = 0;
|
||||
}
|
||||
|
||||
String(const uint8_t *bytes, size_t length)
|
||||
{
|
||||
// Allocate memory for n bytes + nulltermination + length
|
||||
this->mReferences = static_cast<uint32_t*>(malloc(sizeof(*this->mReferences) + sizeof(uint8_t) * (length + 1)));
|
||||
this->mText = reinterpret_cast<uint8_t *>(&this->mReferences[1]);
|
||||
this->mLength = length;
|
||||
|
||||
// We have a single reference
|
||||
(*this->mReferences) = 1;
|
||||
|
||||
// Initialize string
|
||||
memcpy(this->mText, bytes, length);
|
||||
this->mText[length] = 0;
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
if(this->mReferences != nullptr) {
|
||||
(*this->mReferences) -= 1;
|
||||
if((*this->mReferences) == 0) {
|
||||
// Last reference was released, now destroy the memory.
|
||||
free(this->mReferences);
|
||||
}
|
||||
}
|
||||
this->mReferences = nullptr;
|
||||
this->mText = nullptr;
|
||||
this->mLength = 0;
|
||||
}
|
||||
|
||||
String & operator = (const String &other)
|
||||
{
|
||||
if(this->mReferences == other.mReferences) {
|
||||
// We have copied the string in circles.
|
||||
// Everything is just fine
|
||||
return *this;
|
||||
}
|
||||
if(this->mReferences != nullptr) {
|
||||
*this->mReferences -= 1;
|
||||
if(this->mReferences == 0) {
|
||||
free(this->mReferences);
|
||||
}
|
||||
}
|
||||
|
||||
this->mReferences = other.mReferences;
|
||||
this->mText = other.mText;
|
||||
this->mLength = other.mLength;
|
||||
|
||||
if(this->mReferences != nullptr) {
|
||||
*this->mReferences += 1;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
String() :
|
||||
mText(nullptr),
|
||||
mLength(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
String(const String &other) :
|
||||
String(other.mText, other.mLength)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
String(String &&other) :
|
||||
mText(other.mText),
|
||||
mLength(other.mLength)
|
||||
{
|
||||
other.mText = nullptr;
|
||||
other.mLength = 0;
|
||||
}
|
||||
|
||||
String(const uint8_t *bytes, size_t length) :
|
||||
mText(nullptr),
|
||||
mLength(length)
|
||||
{
|
||||
this->copyFrom(bytes, length);
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
if(this->mText != nullptr) {
|
||||
free(this->mText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String & operator = (const String &other)
|
||||
{
|
||||
this->copyFrom(other.mText, other.mLength);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String(const char *text) :
|
||||
String(text, strlen(text))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
String(const char *bytes, size_t length) :
|
||||
String(reinterpret_cast<const uint8_t *>(bytes), length)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint8_t at(size_t index) const
|
||||
{
|
||||
return this->mText[index];
|
||||
}
|
||||
|
||||
size_t length() const
|
||||
{
|
||||
return this->mLength;
|
||||
}
|
||||
|
||||
bool equals(const String &other) const
|
||||
{
|
||||
#if defined(ENABLE_SHARED_STRING)
|
||||
if(this->mText == other.mText) {
|
||||
// This is a quite useful equality test.
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if(this->mLength != other.mLength) {
|
||||
return false;
|
||||
}
|
||||
return memcmp(this->mText, other.mText, this->mLength) == 0;
|
||||
}
|
||||
|
||||
bool equals(const char *other) const
|
||||
{
|
||||
return strcmp(this->str(), other) == 0;
|
||||
}
|
||||
|
||||
String append(const String &other) const
|
||||
{
|
||||
uint8_t *data = (uint8_t*)malloc(this->mLength + other.mLength);
|
||||
memcpy(&data[0], this->mText, this->mLength);
|
||||
memcpy(&data[this->mLength], other.mText, other.mLength);
|
||||
String cat(data, this->mLength + other.mLength);
|
||||
free(data);
|
||||
return cat;
|
||||
}
|
||||
|
||||
const uint8_t *text() const
|
||||
{
|
||||
static const uint8_t empty[] = { 0 };
|
||||
if(this->mText != nullptr) {
|
||||
return this->mText;
|
||||
} else {
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
const char *str() const
|
||||
{
|
||||
return (char*)this->text();
|
||||
}
|
||||
|
||||
operator const uint8_t *() const
|
||||
{
|
||||
return this->text();
|
||||
}
|
||||
|
||||
operator const char *() const
|
||||
{
|
||||
return this->str();
|
||||
}
|
||||
|
||||
uint8_t & operator [](size_t index)
|
||||
{
|
||||
return this->mText[index];
|
||||
}
|
||||
|
||||
const uint8_t & operator [](size_t index) const
|
||||
{
|
||||
return this->mText[index];
|
||||
}
|
||||
|
||||
bool operator ==(const String &other) const
|
||||
{
|
||||
return this->equals(other);
|
||||
}
|
||||
|
||||
bool operator ==(const char *other) const
|
||||
{
|
||||
return this->equals(other);
|
||||
}
|
||||
|
||||
bool operator !=(const String &other) const
|
||||
{
|
||||
return !this->equals(other);
|
||||
}
|
||||
|
||||
bool operator !=(const char *other) const
|
||||
{
|
||||
return !this->equals(other);
|
||||
}
|
||||
|
||||
String operator +(const String &other) const
|
||||
{
|
||||
return this->append(other);
|
||||
}
|
||||
public:
|
||||
static String concat(const String &lhs, const String &rhs)
|
||||
{
|
||||
return lhs.append(rhs);
|
||||
}
|
||||
/*
|
||||
static String fromNumber(int32_t number, int radix = 10)
|
||||
{
|
||||
static char buffer[64];
|
||||
itoa(number, buffer, radix);
|
||||
return String(buffer);
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
static String from(const T &);
|
||||
};
|
||||
|
||||
|
||||
static inline String operator + (const char *lhs, const String &rhs)
|
||||
{
|
||||
return String::concat(lhs, rhs);
|
||||
}
|
||||
|
||||
static inline String operator + (const String &lhs, const char *rhs)
|
||||
{
|
||||
return String::concat(lhs, rhs);
|
||||
}
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define DO_PRAGMA(x) _Pragma (#x)
|
||||
#define TODO(...) DO_PRAGMA(message ("TODO - " #__VA_ARGS__))
|
||||
#define FIXME(...) DO_PRAGMA(message ("FIX - " #__VA_ARGS__))
|
|
@ -1,252 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <initializer_list>
|
||||
|
||||
#if defined(CIRCUIT_OS)
|
||||
#include "kstdlib.h"
|
||||
#include "new.hpp"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
namespace ker
|
||||
{
|
||||
template<typename T>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
static const size_t initialCap = 32;
|
||||
private:
|
||||
T *mData;
|
||||
size_t mLength;
|
||||
size_t mReserved;
|
||||
public:
|
||||
Vector() :
|
||||
mData(nullptr),
|
||||
mLength(0),
|
||||
mReserved(0)
|
||||
{
|
||||
this->reserve(Vector<T>::initialCap);
|
||||
}
|
||||
|
||||
Vector(const Vector &other) :
|
||||
mData(nullptr),
|
||||
mLength(0),
|
||||
mReserved(0)
|
||||
{
|
||||
this->mLength = other.mLength;
|
||||
if(this->mLength > 0) {
|
||||
this->reserve(this->mLength);
|
||||
for(size_t i = 0; i < this->mLength; i++) {
|
||||
new (&this->mData[i]) T(other.mData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector(Vector &&other) :
|
||||
mData(other.mData),
|
||||
mLength(other.mLength),
|
||||
mReserved(other.mReserved)
|
||||
{
|
||||
other.mData = nullptr;
|
||||
other.mLength = 0;
|
||||
other.mReserved = 0;
|
||||
}
|
||||
|
||||
Vector(const std::initializer_list<T> &init) :
|
||||
Vector()
|
||||
{
|
||||
this->reserve(init.size());
|
||||
for(auto & value : init) {
|
||||
this->append(value);
|
||||
}
|
||||
}
|
||||
|
||||
Vector & operator = (const Vector &other)
|
||||
{
|
||||
this->resize(other.mLength);
|
||||
for(size_t i = 0; i < this->mLength; i++)
|
||||
{
|
||||
this->mData[i] = other.mData[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit Vector(size_t initialReserve) :
|
||||
Vector()
|
||||
{
|
||||
this->reserve(initialReserve);
|
||||
}
|
||||
|
||||
~Vector()
|
||||
{
|
||||
if(this->mData != nullptr) {
|
||||
for(size_t i = 0; i < this->mLength; i++) {
|
||||
this->mData[i].~T();
|
||||
}
|
||||
free(this->mData);
|
||||
}
|
||||
}
|
||||
|
||||
size_t length() const
|
||||
{
|
||||
return this->mLength;
|
||||
}
|
||||
|
||||
T &at(size_t index)
|
||||
{
|
||||
return this->mData[index];
|
||||
}
|
||||
|
||||
const T &at(size_t index) const
|
||||
{
|
||||
return this->mData[index];
|
||||
}
|
||||
|
||||
T& append(const T &value)
|
||||
{
|
||||
this->reserve(this->mLength + 1);
|
||||
new (&this->mData[this->mLength]) T(value);
|
||||
this->mLength += 1;
|
||||
return this->mData[this->mLength - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes the last element.
|
||||
*/
|
||||
void pop()
|
||||
{
|
||||
if(this->length() > 0) {
|
||||
this->resize(this->length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->resize(0);
|
||||
}
|
||||
|
||||
T& insert(size_t index, const T& value)
|
||||
{
|
||||
this->resize(this->mLength + 1);
|
||||
for(int32_t i = this->mLength - 2; i >= static_cast<int32_t>(index); i--) {
|
||||
// Move every item backwards
|
||||
this->mData[i+1] = this->mData[i];
|
||||
}
|
||||
// then override
|
||||
this->mData[index] = value;
|
||||
return this->mData[index];
|
||||
}
|
||||
|
||||
void remove(size_t index)
|
||||
{
|
||||
for(uint32_t i = index; i < this->mLength; i++) {
|
||||
// Move every item backwards
|
||||
this->mData[i] = this->mData[i+1];
|
||||
}
|
||||
// then override
|
||||
this->mData[this->mLength - 1].~T();
|
||||
this->mLength -= 1;
|
||||
}
|
||||
|
||||
void resize(size_t size)
|
||||
{
|
||||
size_t current = this->mLength;
|
||||
this->reserve(size);
|
||||
|
||||
if(current > size) {
|
||||
// "Downgrade"
|
||||
for(int32_t i = static_cast<int32_t>(this->mLength) - 1; i >= static_cast<int32_t>(size); i--) {
|
||||
this->mData[i].~T();
|
||||
}
|
||||
} else {
|
||||
// "Upgrade"
|
||||
for(size_t i = this->mLength; i < size; i++) {
|
||||
new (&this->mData[i]) T ();
|
||||
}
|
||||
}
|
||||
this->mLength = size;
|
||||
}
|
||||
|
||||
void reserve(size_t space)
|
||||
{
|
||||
if(this->mReserved >= space) {
|
||||
return;
|
||||
}
|
||||
if((this->mReserved + initialCap) > space) {
|
||||
space = this->mReserved + initialCap;
|
||||
}
|
||||
const size_t newSize = sizeof(T) * space;
|
||||
|
||||
T *newData = (T*)malloc(newSize);
|
||||
if(this->mData != nullptr) {
|
||||
// Ermahgerd, what a leak. Not obvious but it leaks.
|
||||
// memcpy(newData, this->mData, newSize);
|
||||
// Fix: copy construct all objects into the new memory, then destroy the original data.
|
||||
for(size_t i = 0; i < this->mLength; i++) {
|
||||
new (&newData[i]) T (this->mData[i]);
|
||||
this->mData[i].~T();
|
||||
}
|
||||
|
||||
free(this->mData);
|
||||
}
|
||||
this->mData = newData;
|
||||
this->mReserved = space;
|
||||
}
|
||||
|
||||
T& operator [](size_t idx)
|
||||
{
|
||||
return this->at(idx);
|
||||
}
|
||||
|
||||
const T& operator [](size_t idx) const
|
||||
{
|
||||
return this->at(idx);
|
||||
}
|
||||
|
||||
const T &front() const {
|
||||
return this->mData[0];
|
||||
}
|
||||
|
||||
const T &back() const {
|
||||
return this->mData[this->mLength - 1];
|
||||
}
|
||||
|
||||
T &front() {
|
||||
return this->mData[0];
|
||||
}
|
||||
|
||||
T &back() {
|
||||
return this->mData[this->mLength - 1];
|
||||
}
|
||||
|
||||
T* begin()
|
||||
{
|
||||
return &this->mData[0];
|
||||
}
|
||||
|
||||
T* end()
|
||||
{
|
||||
return &this->mData[this->mLength];
|
||||
}
|
||||
|
||||
const T* begin() const
|
||||
{
|
||||
return &this->mData[0];
|
||||
}
|
||||
|
||||
const T* end() const
|
||||
{
|
||||
return &this->mData[this->mLength];
|
||||
}
|
||||
|
||||
const T *data() const
|
||||
{
|
||||
return &this->mData[0];
|
||||
}
|
||||
};
|
||||
}
|
138
ker/string.cpp
138
ker/string.cpp
|
@ -1,138 +0,0 @@
|
|||
#include <inttypes.h>
|
||||
#include "../include/ker/string.hpp"
|
||||
|
||||
#define SPEC(type) template<> String String::from<type>(const type &val)
|
||||
|
||||
static void reverse(char *str, int length)
|
||||
{
|
||||
int start = 0;
|
||||
int end = length -1;
|
||||
while (start < end)
|
||||
{
|
||||
char tmp = *(str+start);
|
||||
*(str+start) = *(str+end);
|
||||
*(str+end) = tmp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
static char *_itoa(int num, char *str, int base, bool useUnsigned)
|
||||
{
|
||||
int i = 0;
|
||||
int isNegative = 0;
|
||||
|
||||
if(str == nullptr) {
|
||||
static char tmp[64];
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
/* Handle 0 explicitely, otherwise empty string is printed for 0 */
|
||||
if (num == 0)
|
||||
{
|
||||
str[i++] = '0';
|
||||
str[i] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
// In standard itoa(), negative numbers are handled only with
|
||||
// base 10. Otherwise numbers are considered unsigned.
|
||||
if ((useUnsigned == false) && (num < 0) && (base == 10))
|
||||
{
|
||||
isNegative = 1;
|
||||
num = -num;
|
||||
}
|
||||
|
||||
// Process individual digits
|
||||
while (num != 0)
|
||||
{
|
||||
int rem = num % base;
|
||||
str[i++] = (rem > 9)? (rem-10) + 'A' : rem + '0';
|
||||
num = num/base;
|
||||
}
|
||||
|
||||
// If number is negative, append '-'
|
||||
if (isNegative)
|
||||
{
|
||||
str[i++] = '-';
|
||||
}
|
||||
str[i] = '\0'; // Append string terminator
|
||||
|
||||
// Reverse the string
|
||||
reverse(str, i);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
namespace ker
|
||||
{
|
||||
SPEC(bool)
|
||||
{
|
||||
return val ? "true" : "false";
|
||||
}
|
||||
|
||||
SPEC(String)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
SPEC(int8_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, false);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(int16_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, false);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(int32_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, false);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(uint8_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(uint16_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(uint32_t) {
|
||||
static char buffer[16];
|
||||
_itoa(val, buffer, 10, true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
SPEC(float) {
|
||||
(void)val;
|
||||
return "f32";
|
||||
}
|
||||
|
||||
#if defined(CONDUCTANCE_64BIT)
|
||||
|
||||
SPEC(int64_t)
|
||||
{
|
||||
return "i64";
|
||||
}
|
||||
|
||||
SPEC(uint64_t)
|
||||
{
|
||||
return "u64";
|
||||
}
|
||||
|
||||
SPEC(double)
|
||||
{
|
||||
return "f64";
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
13
trainOS.pro
13
trainOS.pro
|
@ -2,6 +2,8 @@ TEMPLATE = app
|
|||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
CONFIG += ker_shared_string
|
||||
CONFIG += ker_standalone
|
||||
|
||||
SOURCES += \
|
||||
src/console.c \
|
||||
|
@ -31,10 +33,6 @@ HEADERS += \
|
|||
include/varargs.h \
|
||||
include/vmm.h \
|
||||
include/timer.h \
|
||||
include/ker/string.hpp \
|
||||
include/ker/pair.hpp \
|
||||
include/ker/vector.hpp \
|
||||
include/ker/dictionary.hpp \
|
||||
include/kstring.h \
|
||||
include/ker/new.hpp \
|
||||
include/dynamic.h \
|
||||
|
@ -42,9 +40,7 @@ HEADERS += \
|
|||
include/serial.h \
|
||||
include/malloc.h \
|
||||
csl/cpustatetype.hpp \
|
||||
csl/io.hpp \
|
||||
include/ker/config.hpp \
|
||||
include/ker/todo.hpp
|
||||
csl/io.hpp
|
||||
|
||||
DISTFILES += \
|
||||
asm/intr_common_handler.S \
|
||||
|
@ -67,8 +63,9 @@ DEPENDPATH += include
|
|||
INCLUDEPATH += $$quote("/home/felix/projects/Electronics/Electronics/Conductance")
|
||||
DEPENDPATH += $$quote("/home/felix/projects/Electronics/Electronics/Conductance")
|
||||
|
||||
|
||||
QMAKE_CFLAGS = -m32 -Dnullptr=0 -std=c11 -Wall -fno-stack-protector -ffreestanding
|
||||
|
||||
QMAKE_LINK = ld
|
||||
QMAKE_LFLAGS = -g -melf_i386 -Tkernel.ld
|
||||
|
||||
include("/home/felix/projects/ker/ker.pri")
|
||||
|
|
Loading…
Reference in a new issue