Base refactor

This commit is contained in:
2023-11-14 09:16:48 -06:00
parent 214082d00f
commit 1817dcaf3a
410 changed files with 749 additions and 20823 deletions

View File

@ -1,23 +0,0 @@
# Copyright (c) 2023 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
memory.cpp
UsageLock.cpp
Xml.cpp
)
# Tests
target_sources(dawntests
PRIVATE
memory.cpp
UsageLock.cpp
Xml.cpp
_test_.memory.cpp
)

121
src/dawn/util/Math.hpp Normal file
View File

@ -0,0 +1,121 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnlibs.hpp"
#define MATH_PI 3.1415926535897f
namespace Dawn {
class Math {
/**
* Returns the largest of the two provided int32 numbers.
*
* @param left Left number to get the largest of.
* @param right Right number to get the largest of.
* @return The larger of the two numbers
*/
template<typename T>
static T max(T left, T right) {
return left < right ? right : left;
}
/**
* Returns the smallest of two provided int32 numbers.
*
* @param left Left number to get the smallest of.
* @param right Right number to get the smallest of.
* @return Smaller of the two numbers.
*/
template<typename T>
static T mathMin(T left, T right) {
return left < right ? left : right;
}
/**
* Returns the input value, constrained between the min and max values, so that
* the value cannot underceed the min, and cannot exceed the max.
*
* @param val Value to get the clamp for.
* @param min Minimum clamping value.
* @param max Maximum clamping value.
* @return The value, or the closest clamped value.
*/
template<typename T>
static T mathClamp(T val, T min, T max) {
return mathMin<T>(mathMax<T>(val, min), max);
}
/**
* Returns the absolute value (the non-negative representation of) for the given
* int32 number.Abs values will be -value if value < 0.
*
* @param value Value to get the absolute value for.
* @return The absolute value (-value if value < 0)
*/
template<typename T>
static T mathAbs(T value) {
return value < 0 ? -value : value;
}
/**
* Returns the modulous a result for b. Works for floating point numbers.
*
* @param a Number to modulo against. (a % b)
* @param b Number to modulo with. (a % b)
* @returns The modulo result.
*/
template<typename T>
static inline T mathMod(T value, T modulo) {
return ((value % modulo) + modulo) % modulo;
}
static inline float_t mathMod(float_t value, float_t modulo) {
float_t n = fmod(value, modulo);
return n;
}
/**
* Convert degrees to radians.
*
* @param n Degrees to convert.
* @returns The number in radians.
*/
static float_t mathDeg2Rad(float_t degrees) {
return degrees * (MATH_PI / 180.0f);
}
/**
* Convert radians to degrees.
* @param n Radians to convert.
* @returns The number in degrees.
*/
static float_t mathRad2Deg(float_t n) {
return (n * 180.0f) / MATH_PI;
}
/**
* Round a number to the nearest whole number.
* @param n Number to round.
* @return Rounded number.
*/
template<typename T>
static T mathRound(float_t n) {
return (T)roundf(n);
}
/**
* Rounds the number down to the nearest whole number.
* @param n Number to round down.
* @return Rounded number.
*/
template<typename T>
static T mathFloor(float_t n) {
return (T)floorf(n);
}
};
}

View File

@ -1,28 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "util/UsageLock.hpp"
using namespace Dawn;
UsageLock::UsageLock() {
this->onEmpty = []() {};
this->onFirstLock = []() {};
}
usagelockid_t UsageLock::createLock() {
usagelockid_t lock = this->pool++;
this->locks.push_back(lock);
if(this->locks.size() == 1) this->onFirstLock();
return lock;
}
void UsageLock::removeLock(usagelockid_t lock) {
auto it = std::find(this->locks.begin(), this->locks.end(), lock);
if(it == this->locks.end()) return;
this->locks.erase(it);
this->onLockRemoved(lock);
if(this->locks.size() == 0) this->onEmpty();
}

View File

@ -1,40 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "assert/assert.hpp"
namespace Dawn {
typedef int32_t usagelockid_t;
class UsageLock {
protected:
usagelockid_t pool = 0;
std::vector<usagelockid_t> locks;
public:
std::function<void()> onEmpty;
std::function<void()> onFirstLock;
std::function<void(usagelockid_t)> onLockRemoved;
/**
* Construct a new usage lock object.
*/
UsageLock();
/**
* Creates a new lock.
*
* @return Lock created for this specific instance.
*/
usagelockid_t createLock();
/**
* Removes a lock.
*
* @param lock Lck to remove.
*/
void removeLock(usagelockid_t lock);
};
}

View File

@ -1,288 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "Xml.hpp"
using namespace Dawn;
XmlNode::XmlNode() {
this->child = nullptr;
this->value.clear();
}
bool_t Xml::isWhitespace(char_t c) {
return c == ' ' || c == '\r' || c == '\n' || c == '\t';
}
Xml Xml::load(std::string data) {
size_t j = 0;
Xml xml;
Xml::load(&xml, data, &j);
return xml;
}
void Xml::load(Xml *xml, std::string data, size_t *j) {
char_t c;
int32_t level = 0;
enum XmlParseState doing = XML_PARSE_STATE_DOING_NOTHING;
enum XmlParseState doingBeforeComment;
bool_t insideTag = false;
std::string buffer = "";
std::string attrKey = "";
size_t i = *j;
struct XmlNode childNode;
while(c = data[i++]) {
if(insideTag) {
xml->outerXml += c;
}
switch(doing) {
case XML_PARSE_STATE_DOING_NOTHING:
if(c == '>') continue;
if(c == '<') {
// Parsing comment?
if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') {
doingBeforeComment = doing;
doing = XML_PARSE_STATE_PARSING_COMMENT;
i += 3;
} else if(data[i] == '!' && !insideTag) {
// Likely <!DOCTYPE ...>
while((c = data[i++]) != '>') {
// Nothing needs doing here right now, in future may support doctype
}
continue;
} else if(insideTag) {
if(data[i] == '/') {
doing = XML_PARSE_STATE_PARSING_CLOSE;
continue;
}
} else {
doing = XML_PARSE_STATE_PARSING_TAG_NAME;
level++;
insideTag = true;
xml->outerXml += c;
}
continue;
}
if(insideTag) xml->innerXml += c;
if(Xml::isWhitespace(c)) continue;// NEEDS TO GO?
doing = XML_PARSE_STATE_PARSING_VALUE;
buffer += c;
break;
case XML_PARSE_STATE_PARSING_TAG_NAME:
// Just keep reading until we either hit a space (end of the tag name)
// or a closing tag value, either / or >
if(Xml::isWhitespace(c) || c == '>' || c == '/') {
xml->node = buffer;
buffer = "";
if(c == '/') {
level--;
insideTag = false;
doing = XML_PARSE_STATE_PARSING_CLOSE;
} else {
doing = c == '>' ? XML_PARSE_STATE_PARSING_VALUE : XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE;
}
continue;
}
buffer += c;
break;
case XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE:
// Look until we hit either the end of a tag, or the attribute itself
if(Xml::isWhitespace(c) || c == '>' || c == '/' || c == '=') {
if(c == '>' || c == '/') {
doing = XML_PARSE_STATE_PARSING_VALUE;
if(c == '/') {
level--;
insideTag = false;
doing = XML_PARSE_STATE_PARSING_CLOSE;
}
} else if(c == '=') {
doing = XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE_VALUE;
} else {
doing = XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE;
}
if(buffer.size() > 0) {
attrKey = buffer;
xml->attributes[buffer] = "";
buffer = "";
}
continue;
}
buffer += c;
break;
case XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE_VALUE:
// Keep looking until we find a quote mark
if(Xml::isWhitespace(c)) continue;
if(c == '>' || c == '/') {
doing = XML_PARSE_STATE_DOING_NOTHING;
insideTag = false;
continue;
}
if(c != '"') continue;
doing = XML_PARSE_STATE_PARSING_ATTRIBUTE_VALUE;
break;
case XML_PARSE_STATE_PARSING_ATTRIBUTE_VALUE:
// Parse the attribute value until we find a quote mark.
if(c == '\\') {
c = data[i++];
} else if(c == '"') {
doing = XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE;
xml->attributes[attrKey] = buffer;
buffer = "";
continue;
}
buffer += c;
break;
case XML_PARSE_STATE_PARSING_VALUE:
// Keep parsing child until we find a < for an opening/closing tag.
if(c == '<' && !(data[i] == '<' || data[i-2] == '<')) {
if(buffer.size() > 0) {
childNode.nodeType = XML_NODE_TYPE_TEXT;
childNode.value = buffer;
xml->childNodes.push_back(childNode);
}
// Are we parsing the close tag, or parsing a child?
if(data[i] == '/') {
doing = XML_PARSE_STATE_PARSING_CLOSE;
xml->textContent = buffer;
buffer.clear();
continue;
} else if(data[i] == '!' && data[i+1] == '-' && data[i+2] == '-') {
doingBeforeComment = doing;
doing = XML_PARSE_STATE_PARSING_COMMENT;
i += 3;
continue;
}
// Parsing child
i -= 1;
// @deprecated
auto child = new Xml();
Xml::load(child, data, &i);
xml->children.push_back(child);
childNode = XmlNode();
childNode.nodeType = XML_NODE_TYPE_ELEMENT;
childNode.child = child;
xml->childNodes.push_back(childNode);
// Remove last char since we kinda already parsed it.
xml->innerXml += child->outerXml;
xml->outerXml = xml->outerXml.substr(0, xml->outerXml.size()-1);
xml->outerXml += child->outerXml;
buffer.clear();
continue;
}
xml->innerXml += c;
if(c == '&') {
// Handle special characters. First read ahead to nearest semicolon OR
// nearest closing tag.
std::string sc;
while(c = data[i++]) {
xml->innerXml += c;
if(c == ';') break;
if(c == '<') assertUnreachable("Error decrypting XML/HTML Special Char, encountered end of Node?");//Invalid XML
sc += c;
}
if(sc == "lt") {
buffer += '<';
} else if(sc == "gt") {
buffer += '>';
} else if(sc == "amp") {
buffer += '&';
} else if(sc == "apos") {
buffer += '\'';
} else if(sc == "quot") {
buffer += '"';
} else if(sc == "nbsp") {
buffer += ' ';
} else {
// Try parse as integer
if(sc.size() > 1 && sc[0] == '#') {
int code = std::stoi(sc.substr(1));
buffer += (char)code;
} else {
assertUnreachable("Unknown Special character: %s", sc.c_str());
}
}
} else {
buffer += c;
}
break;
case XML_PARSE_STATE_PARSING_CLOSE:
// Just keep parsing until the tag closer finishes.
if(c != '>') continue;
doing = XML_PARSE_STATE_DOING_NOTHING;
//TODO: Return index or something?
*j = i;
return;
case XML_PARSE_STATE_PARSING_COMMENT:
if(c != '-') continue;
if(data[i] != '-') continue;
if(data[i+1] != '>') continue;
i += 2;
doing = doingBeforeComment;
break;
default:
break;
}
}
*j = i;
}
std::vector<Xml*> Xml::getChildrenOfType(std::string type) {
std::vector<Xml*> children;
auto itChildren = this->children.begin();
while(itChildren != this->children.end()) {
auto child = *itChildren;
if(child->node == type) children.push_back(child);
++itChildren;
}
return children;
}
Xml * Xml::getFirstChildOfType(std::string type) {
auto itChildren = this->children.begin();
while(itChildren != this->children.end()) {
auto child = *itChildren;
if(child->node == type) return child;
++itChildren;
}
return nullptr;
}
Xml::~Xml() {
auto it = this->children.begin();
while(it != this->children.end()) {
Xml *child = *it;
delete child;
++it;
}
}

View File

@ -1,64 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
#include "util/memory.hpp"
#include "assert/assert.hpp"
#include "util/array.hpp"
namespace Dawn {
enum XmlParseState {
XML_PARSE_STATE_DOING_NOTHING,
XML_PARSE_STATE_PARSING_TAG_NAME,
XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE,
XML_PARSE_STATE_PARSING_ATTRIBUTE_NAME,
XML_PARSE_STATE_LOOKING_FOR_ATTRIBUTE_VALUE,
XML_PARSE_STATE_PARSING_ATTRIBUTE_VALUE,
XML_PARSE_STATE_PARSING_VALUE,
XML_PARSE_STATE_PARSING_CLOSE,
XML_PARSE_STATE_PARSING_COMMENT
};
class Xml;
struct XmlNode;
enum XmlNodeType {
XML_NODE_TYPE_TEXT,
XML_NODE_TYPE_ELEMENT
};
class Xml {
protected:
static bool_t isWhitespace(char_t c);
// @deprecated
std::vector<Xml*> children;
public:
static Xml load(std::string data);
static void load(Xml *xml, std::string data, size_t *j);
std::string node;
std::string innerXml;
std::string outerXml;
std::string textContent;
std::map<std::string, std::string> attributes;
std::vector<struct XmlNode> childNodes;
std::vector<Xml*> getChildrenOfType(std::string type);
Xml * getFirstChildOfType(std::string type);
~Xml();
};
struct XmlNode {
enum XmlNodeType nodeType;
std::string value;
Xml *child;
XmlNode();
};
}

View File

@ -1,27 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include <catch2/catch_test_macros.hpp>
#include "util/memory.hpp"
#include "assert/assert.hpp"
TEST_CASE("memorycallMalloc", "[memory]") {
SECTION("memory isn't null") {
void *p = memoryCallMalloc(10);
REQUIRE(p != nullptr);
REQUIRE(p != NULL);
memoryCallFree(p);
}
SECTION("memory is writeable") {
void *p = memoryCallMalloc(10);
for(int i = 0; i < 10; i++) {
((char*)p)[i] = 'a';
}
REQUIRE(((char*)p)[0] == 'a');
REQUIRE(((char*)p)[9] == 'a');
memoryCallFree(p);
}
}

View File

@ -1,21 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
#include "assert/assert.hpp"
namespace Dawn {
/**
* Append a list on to another list.
*
* @param list Pointer to list that is being appended to.
* @param append Pointer to list that will be appended.
*/
template<typename T>
void vectorAppend(std::vector<T> &list, const std::vector<T> &append) {
list.insert(list.end(), append.begin(), append.end());
}
}

View File

@ -1,15 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
typedef uint_fast8_t flag8_t;
typedef uint_fast16_t flag16_t;
typedef uint_fast32_t flag32_t;
typedef flag32_t flag_t;
#define FLAG_DEFINE(n) (1 << n)

View File

@ -1,11 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#define MACRO_STRINGIFY_RAW(x) #x
#define MACRO_STRINGIFY(x) MACRO_STRINGIFY_RAW(x)
#define MACRO_JOIN(x, y) x ## y

View File

@ -1,119 +0,0 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnlibs.hpp"
#define MATH_PI 3.1415926535897f
namespace Dawn {
/**
* Returns the largest of the two provided int32 numbers.
*
* @param left Left number to get the largest of.
* @param right Right number to get the largest of.
* @return The larger of the two numbers
*/
template<typename T>
static T mathMax(T left, T right) {
return left < right ? right : left;
}
/**
* Returns the smallest of two provided int32 numbers.
*
* @param left Left number to get the smallest of.
* @param right Right number to get the smallest of.
* @return Smaller of the two numbers.
*/
template<typename T>
static T mathMin(T left, T right) {
return left < right ? left : right;
}
/**
* Returns the input value, constrained between the min and max values, so that
* the value cannot underceed the min, and cannot exceed the max.
*
* @param val Value to get the clamp for.
* @param min Minimum clamping value.
* @param max Maximum clamping value.
* @return The value, or the closest clamped value.
*/
template<typename T>
static T mathClamp(T val, T min, T max) {
return mathMin<T>(mathMax<T>(val, min), max);
}
/**
* Returns the absolute value (the non-negative representation of) for the given
* int32 number.Abs values will be -value if value < 0.
*
* @param value Value to get the absolute value for.
* @return The absolute value (-value if value < 0)
*/
template<typename T>
static T mathAbs(T value) {
return value < 0 ? -value : value;
}
/**
* Returns the modulous a result for b. Works for floating point numbers.
*
* @param a Number to modulo against. (a % b)
* @param b Number to modulo with. (a % b)
* @returns The modulo result.
*/
template<typename T>
static inline T mathMod(T value, T modulo) {
return ((value % modulo) + modulo) % modulo;
}
static inline float_t mathMod(float_t value, float_t modulo) {
float_t n = fmod(value, modulo);
return n;
}
/**
* Convert degrees to radians.
*
* @param n Degrees to convert.
* @returns The number in radians.
*/
static float_t mathDeg2Rad(float_t degrees) {
return degrees * (MATH_PI / 180.0f);
}
/**
* Convert radians to degrees.
* @param n Radians to convert.
* @returns The number in degrees.
*/
static float_t mathRad2Deg(float_t n) {
return (n * 180.0f) / MATH_PI;
}
/**
* Round a number to the nearest whole number.
* @param n Number to round.
* @return Rounded number.
*/
template<typename T>
static T mathRound(float_t n) {
return (T)roundf(n);
}
/**
* Rounds the number down to the nearest whole number.
* @param n Number to round down.
* @return Rounded number.
*/
template<typename T>
static T mathFloor(float_t n) {
return (T)floorf(n);
}
}

View File

@ -1,60 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "memory.hpp"
#include "assert/assert.hpp"
void * memoryAllocate(const size_t size) {
assertTrue(size >= 0, "memoryAllocate: size must be greater than 0 or equal to.");
void *x = (void *)memoryCallMalloc(size);
assertNotNull(x, "memoryAllocate: Failed to allocate memory");
return x;
}
void * memoryAllocateEmpty(const size_t count, const size_t size) {
assertTrue(count >= 0, "memoryAllocateEmpty: count must be greater than or equal to 0");
assertTrue(size >= 0, "memoryAllocateEmpty: size must be greater than or equal to 0");
void *x = (void *)memoryCallCalloc(count, size);
assertNotNull(x, "memoryAllocateEmpty: Failed to allocate memory");
return x;
}
void memoryFree(void *pointer) {
memoryCallFree(pointer);
}
void * memoryReallocate(void *ptr, size_t newSize) {
assertTrue(newSize >= 0, "memoryReallocate: newSize must be greater than or equal to 0");
return memoryCallRealloc(ptr, newSize);
}
void memoryCopy(void *source, void *destination, size_t size) {
assertNotNull(source, "memoryCopy: source must not be null");
assertNotNull(destination, "memoryCopy: destination must not be null");
assertTrue(destination != source, "memoryCopy: destination must not be source");
assertTrue(size > 0, "memoryCopy: size must be greater than 0");
memcpy(destination, source, size);
}
int32_t memoryCompare(const void *left, const void *right, const size_t size) {
assertTrue(left != right, "memoryCompare: left must not be right");
assertTrue(size > 0, "memoryCompare: size must be greater than 0");
return memcmp(left, right, size);
}
void memorySet(void *dest, uint8_t data, size_t length) {
assertNotNull(dest, "memorySet: dest must not be null");
assertTrue(length > 0, "memorySet: length must be greater than 0");
memset(dest, data, length);
}
void memoryInit() {
}
void memoryDispose() {
}

View File

@ -1,103 +0,0 @@
/**
* Copyright (c) 2022 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dawnlibs.hpp"
#define DAWN_MEMORY_TRACKING 1
static void * memoryCallMalloc(const size_t size) {
return malloc(size);
}
static void * memoryCallCalloc(const size_t num, const size_t size) {
return calloc(num, size);
}
static void memoryCallFree(void *p) {
free(p);
}
static void * memoryCallRealloc(void *p, size_t newSize) {
return realloc(p, newSize);
}
/**
* Allocate some space in memory to use for your needs. Memory allocation may
* change how it functions later on to keep things nice and efficient. For now
* this is just an API forward for malloc.
*
* @param size Size of the array you wish to buffer.
* @return Pointer to the space in memory to use.
*/
template<typename T>
T * memoryAllocate(const size_t size) {
return (T*)memoryCallMalloc(size * sizeof(T));
}
/**
* Allocate space in memory, where all values are set to 0 (in binary space).
*
* @param count Count of elements to allocate.
* @param size Size of each element to allocate.
* @return Pointer to the space in memory to use.
*/
void * memoryAllocateEmpty(const size_t count, const size_t size);
/**
* Free some previously allocated memory space.
* @param pointer Pointer in memory to free.
*/
void memoryFree(void *pointer);
/**
* Reallocate a part of memory. Reallocation simply creates a new buffer that
* will take all of the existing contents and then free's the original buffer.
*
* @param pointer Pointer to pointer in memory that you wish to re-allocate.
* @param newSize The new size of the buffer.
* @return Pointer to the new buffer.
*/
void * memoryReallocate(void *pointer, size_t newSize);
/**
* Copies data from one buffer to another. Typically used for array operations.
*
* @param source Source pointer.
* @param destination Destination buffer.
* @param size Size in bytes of data to copy.
*/
void memoryCopy(void *source, void *destination, size_t size);
/**
* Compares the data within two memory banks. Shorthand for memcpy.
*
* @param left Left item to compare.
* @param right Right item to compare.
* @param size Count of bytes to compare.
* @return 0 for equal, <0 for left being greater, >0 for right being greater.
*/
int32_t memoryCompare(const void *left, const void *right, const size_t size);
/**
* Fill destination with a repeating set of bytes.
*
* @param dest Destination pointer in memory.
* @param data Data byte to write.
* @param length How many times to write that byte.
*/
void memorySet(void *dest, uint8_t data, size_t length);
/**
* Initializes the memory management system.
*/
void memoryInit();
/**
* Disposes of the memory management system.
*/
void memoryDispose();

View File

@ -1,204 +0,0 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "util/string.hpp"
namespace Dawn {
static inline std::string rawParser(std::string v, std::string *error) {
return v;
};
static inline std::string stringParser(std::string v, std::string *error) {
// Replace slashes and quotes
v = stringReplaceAll(v, "\\", "\\\\\\");
v = stringReplaceAll(v, "\"", "\\\"");
// Newlines.
v = stringReplaceAll(v, "\n", "\\n");
return "\"" + v + "\"";
};
static inline std::string floatParser(std::string v, std::string *error) {
v = stringTrim(v);
// Make sure number contains decimal
if(v.find(".") == std::string::npos) {
v += ".0";
}
// Make sure number contains a number before the decimal
if(v.find(".") == 0) {
v = "0" + v;
}
// Make sure ends with f
if(v.find("f") == std::string::npos) {
v += "f";
}
return v;
};
static inline std::string intParser(std::string v, std::string *error) {
v = stringTrim(v);
return v;
}
static inline std::string boolParser(std::string v, std::string *error) {
v = stringTrim(v);
if(v == "true") return "true";
if(v == "false") return "false";
*error = "Invalid bool value: " + v;
return std::string("");
}
static inline std::string vec2Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 2) {
*error = "Invalid vec2 value: " + v;
return std::string("");
}
return std::string(
"glm::vec2(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) +
")"
);
};
static inline std::string vec3Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 3) {
*error = "Invalid vec3 value: " + v;
return std::string("");
}
return std::string(
"glm::vec3(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) + ", " +
floatParser(split[2], error) +
")"
);
};
static inline std::string vec6Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 6) {
*error = "Invalid vec6 value: " + v;
return std::string("");
}
return std::string(
"glm::vec6(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) + ", " +
floatParser(split[2], error) + ", " +
floatParser(split[3], error) + ", " +
floatParser(split[4], error) + ", " +
floatParser(split[5], error) +
")"
);
};
static inline std::string vec4Parser(std::string v, std::string *error) {
// Split string by comma into two strings that we pass into float
auto split = stringSplit(v, ",");
if(split.size() != 4) {
*error = "Invalid vec4 value: " + v + " (incorrect split len " + std::to_string(split.size()) + ")";
return std::string("");
}
return std::string(
"glm::vec4(" +
floatParser(split[0], error) + ", " +
floatParser(split[1], error) + ", " +
floatParser(split[2], error) + ", " +
floatParser(split[3], error) +
")"
);
};
static inline std::string colorParser(std::string v, std::string *error) {
return "Color::fromString(" + stringParser(v, error) + ")";
};
static inline std::string uiComponentAlignParser(std::string v, std::string *error) {
v = stringToLowercase(v);
if(v.find("left") != std::string::npos) return "UI_COMPONENT_ALIGN_START";
if(v.find("center") != std::string::npos) return "UI_COMPONENT_ALIGN_MIDDLE";
if(v.find("right") != std::string::npos) return "UI_COMPONENT_ALIGN_END";
if(v.find("top") != std::string::npos) return "UI_COMPONENT_ALIGN_START";
if(v.find("bottom") != std::string::npos) return "UI_COMPONENT_ALIGN_END";
if(v.find("stretch") != std::string::npos) return "UI_COMPONENT_ALIGN_STRETCH";
if(v.find("start") != std::string::npos) return "UI_COMPONENT_ALIGN_START";
if(v.find("middle") != std::string::npos) return "UI_COMPONENT_ALIGN_MIDDLE";
if(v.find("end") != std::string::npos) return "UI_COMPONENT_ALIGN_END";
*error = "Invalid UIComponentAlign value: " + v;
return "";
}
static inline std::string uiComponentAlignUnitParser(std::string v, std::string *error) {
v = stringToLowercase(v);
if(v.find("scale") != std::string::npos) return "UI_COMPONENT_ALIGN_UNIT_SCALE";
if(v.find("percent") != std::string::npos) return "UI_COMPONENT_ALIGN_UNIT_PERCENT";
if(v.find("ratio") != std::string::npos) return "UI_COMPONENT_ALIGN_UNIT_RATIO";
*error = "Invalid UIComponentAlignUnit value: " + v;
return "";
}
static inline std::string uiLabelTextAlignParser(std::string v, std::string *error) {
v = stringToLowercase(v);
if(v.find("left") != std::string::npos) return "UI_LABEL_TEXT_ALIGN_LEFT";
if(v.find("center") != std::string::npos) return "UI_LABEL_TEXT_ALIGN_CENTER";
if(v.find("right") != std::string::npos) return "UI_LABEL_TEXT_ALIGN_RIGHT";
*error = "Invalid UILabelTextAlign value: " + v;
return "";
}
static inline std::function<std::string(std::string, std::string*)> parserFromTypeName(std::string type) {
std::function<std::string(std::string, std::string*)> parser = rawParser;
if(type.find("string") != std::string::npos) {
parser = stringParser;
} else if(type.find("float") != std::string::npos) {
parser = floatParser;
} else if(type.find("Color") != std::string::npos) {
parser = colorParser;
} else if(type.find("vec2") != std::string::npos) {
parser = vec2Parser;
} else if(type.find("vec3") != std::string::npos) {
parser = vec3Parser;
} else if(type.find("vec4") != std::string::npos) {
parser = vec4Parser;
} else if(type == "int32_t" || type == "int" || type == "uint32_t" || type == "uint") {
parser = intParser;
} else if(type == "bool_t") {
parser = boolParser;
} else if(type == "flag_t") {
parser = rawParser;
} else if(type.starts_with("enum")) {
// Handle Enum Cases
if(type.ends_with("UIComponentAlign")) {
parser = uiComponentAlignParser;
} else if(type.ends_with("UIComponentAlignUnit")) {
parser = uiComponentAlignUnitParser;
} else if(type.ends_with("UILabelTextAlign")) {
parser = uiLabelTextAlignParser;
} else {
parser = rawParser;
}
} else if(type.find("*") == (type.size() - 1)) {
type = type.substr(0, type.size() - 1);
parser = rawParser;
} else {
throw std::string("Invalid parser type");
}
return parser;
}
}

View File

@ -1,53 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
#include "util/mathutils.hpp"
namespace Dawn {
/**
* Seed the random number generator
* @param seed Seed to use for the seeded random number generator.
*/
static void randSeed(int32_t seed) {
srand(seed);
}
static int32_t randomGeneratei32() {
return (int32_t)rand();
}
/**
* Generates a random number.
* @returns A random number.
*/
template<typename T>
static T randomGenerate() {
return (T)((float_t)randomGeneratei32() * MATH_PI);
}
////////////////////////////////////////////////////////////////////////////////
/**
* Clamps a random number generation.
*
* @param min Minimum value to generate from. (Inclusive)
* @param max Maximum value to generate to. (Exclusive)
* @return Random number between min and max.
*/
template<typename T>
static inline T randRange(T min, T max) {
return mathMod<T>(randomGenerate<T>(), (max - min)) + min;
}
static inline float_t randRange(float_t min, float_t max) {
return mathMod(randomGenerate<float_t>(), (max - min)) + min;
}
static inline glm::vec2 randRange(glm::vec2 min, glm::vec2 max) {
return glm::vec2(randRange(min.x, max.x), randRange(min.y, max.y));
}
}

View File

@ -1,168 +0,0 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "assert/assert.hpp"
/**
* Finds the next instance of a character within a string, safely (with a
* limit). The returned pointer will be NULL if not found, or a pointer to a
* point within the string where the instance is.
*
* @param haystack String to search.
* @param needle Character to search for.
* @param limit Max length you want to search for to limit yourself to.
* @return Pointer to the character found, or NULL if not found.
*/
static inline char * stringFindNext(
char *haystack,
char needle,
size_t limit
) {
char *p;
assertNotNull(haystack, "String find haystack cannot be null");
assertTrue(limit > 0, "String find limit must be greater than 0");
for(p = haystack; (size_t)(p - haystack) < limit; p++) {
if(*p == needle) return p;
assertFalse(*p == '\0', "String find limit reached");
}
return NULL;
}
/**
* Splits a string into a vector of strings, using a delimiter.
*
* @param s String to split.
* @param delim Delimiter to split by.
* @return Vector of strings.
*/
static inline std::vector<std::string> stringSplit(
const std::string &s,
const std::string delim
) {
size_t posStart = 0, posEnd, delimLength = delim.length();
std::string token;
std::vector<std::string> res;
while((posEnd = s.find(delim, posStart)) != std::string::npos) {
token = s.substr(posStart, posEnd - posStart);
posStart = posEnd + delimLength;
res.push_back (token);
}
res.push_back(s.substr(posStart));
return res;
}
/**
* Trims the whitespace from the left side of a string.
*
* @param i Input string to trim.
* @return Trimmed string.
*/
static inline std::string stringLTrim(const std::string &i) {
std::string s = i;
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
return s;
}
/**
* Trims the whitespace from the right side of a string.
*
* @param i Input string to trim.
* @return Trimmed string.
*/
static inline std::string stringRTrim(const std::string &i) {
std::string s = i;
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
return s;
}
/**
* Trims the whitespace from both sides of a string.
*
* @param s Input string to trim.
* @return Trimmed string.
*/
static inline std::string stringTrim(const std::string &s) {
return stringLTrim(stringRTrim(s));
}
/**
* Checks if a string contains another string.
*
* @param haystack String to scan.
* @param needle String to search for.
* @return True if the string is found, false otherwise.
*/
static inline bool_t stringIncludes(const std::string &haystack, const std::string &needle) {
return haystack.find(needle) != std::string::npos;
}
/**
* Converts an entire string to lowercase.
*
* @param str String to convert.
* @return A new string with all lowercase characters.
*/
static inline std::string stringToLowercase(const std::string &str) {
std::string data = str;
std::transform(
data.begin(),
data.end(),
data.begin(),
[](char c) {
return std::tolower(c);
}
);
return data;
}
/**
* Replace all instances of a string with another string within a string.
*
* @param str String to replace the contents of.
* @param needle Needle to look for.
* @param replace String to replace the needle with.
* @return A new string instance with the replacements made.
*/
static inline std::string stringReplaceAll(
const std::string &str,
const std::string &needle,
const std::string &replace
) {
std::string newString = str;
size_t startPos = 0;
while((startPos = newString.find(needle, startPos)) != std::string::npos) {
newString.replace(startPos, needle.length(), replace);
startPos += replace.length();
}
return newString;
}
/**
* Joins a vector of strings into a single string, using a delimiter.
*
* @param strings Vector of strings to join.
* @param delim Delimiter to join the strings with.
*/
static inline std::string stringJoin(
const std::vector<std::string> &strings,
const std::string &delim
) {
std::string result;
for(size_t i = 0; i < strings.size(); i++) {
if(i > 0) result += delim;
result += strings[i];
}
return result;
}