From dcd3e11b167853abcf7a9d4230f9af601bbac9c5 Mon Sep 17 00:00:00 2001 From: Noel Berry Date: Sat, 1 Oct 2022 13:29:51 -0700 Subject: [PATCH] Simplify folder sturcture + String refactor 1) Over time the total amount of files has decreased, and so it made sense to just simplify the folder structure and remove all of the subfolders. 2) Refactor the String class to utilize the existing Vector and StackVector classes instead of managing everything itself. --- CMakeLists.txt | 38 +- include/blah.h | 47 +- include/blah/containers/str.h | 321 ------------ include/{blah/app.h => blah_app.h} | 6 +- .../images/aseprite.h => blah_aseprite.h} | 10 +- .../{blah/drawing/batch.h => blah_batch.h} | 14 +- include/{blah/math/calc.h => blah_calc.h} | 3 +- include/{blah/math/color.h => blah_color.h} | 6 +- include/{blah/common.h => blah_common.h} | 43 +- include/{blah/math/ease.h => blah_ease.h} | 4 +- .../{blah/filesystem.h => blah_filesystem.h} | 6 +- include/{blah/images/font.h => blah_font.h} | 12 +- include/{blah/graphics.h => blah_graphics.h} | 15 +- include/{blah/images/image.h => blah_image.h} | 8 +- include/{blah/input.h => blah_input.h} | 8 +- .../{blah/images/packer.h => blah_packer.h} | 16 +- .../{blah/math/spatial.h => blah_spatial.h} | 4 +- .../spritefont.h => blah_spritefont.h} | 10 +- .../stackvector.h => blah_stackvector.h} | 4 +- include/{blah/stream.h => blah_stream.h} | 10 +- include/blah_string.h | 371 +++++++++++++ .../subtexture.h => blah_subtexture.h} | 4 +- include/{blah/time.h => blah_time.h} | 2 +- .../containers/vector.h => blah_vector.h} | 10 +- src/{app.cpp => blah_app.cpp} | 18 +- .../aseprite.cpp => blah_aseprite.cpp} | 16 +- src/{drawing/batch.cpp => blah_batch.cpp} | 40 +- src/{common.cpp => blah_common.cpp} | 6 +- src/{filesystem.cpp => blah_filesystem.cpp} | 17 +- src/{images/font.cpp => blah_font.cpp} | 16 +- src/{graphics.cpp => blah_graphics.cpp} | 5 +- src/{images/image.cpp => blah_image.cpp} | 6 +- src/{input.cpp => blah_input.cpp} | 21 +- src/{images/packer.cpp => blah_packer.cpp} | 3 +- .../spritefont.cpp => blah_spritefont.cpp} | 56 +- src/{stream.cpp => blah_stream.cpp} | 7 +- src/blah_string.cpp | 360 +++++++++++++ .../subtexture.cpp => blah_subtexture.cpp} | 4 +- src/{time.cpp => blah_time.cpp} | 4 +- src/containers/str.cpp | 492 ------------------ src/internal/{internal.h => blah_internal.h} | 4 +- src/internal/{platform.h => blah_platform.h} | 8 +- ...atform_sdl2.cpp => blah_platform_sdl2.cpp} | 16 +- ...form_win32.cpp => blah_platform_win32.cpp} | 14 +- src/internal/{renderer.h => blah_renderer.h} | 6 +- ...erer_d3d11.cpp => blah_renderer_d3d11.cpp} | 8 +- ...er_opengl.cpp => blah_renderer_opengl.cpp} | 10 +- 47 files changed, 1018 insertions(+), 1091 deletions(-) delete mode 100644 include/blah/containers/str.h rename include/{blah/app.h => blah_app.h} (98%) rename include/{blah/images/aseprite.h => blah_aseprite.h} (94%) rename include/{blah/drawing/batch.h => blah_batch.h} (97%) rename include/{blah/math/calc.h => blah_calc.h} (98%) rename include/{blah/math/color.h => blah_color.h} (98%) rename include/{blah/common.h => blah_common.h} (84%) rename include/{blah/math/ease.h => blah_ease.h} (99%) rename include/{blah/filesystem.h => blah_filesystem.h} (96%) rename include/{blah/images/font.h => blah_font.h} (93%) rename include/{blah/graphics.h => blah_graphics.h} (98%) rename include/{blah/images/image.h => blah_image.h} (94%) rename include/{blah/input.h => blah_input.h} (99%) rename include/{blah/images/packer.h => blah_packer.h} (91%) rename include/{blah/math/spatial.h => blah_spatial.h} (99%) rename include/{blah/drawing/spritefont.h => blah_spritefont.h} (95%) rename include/{blah/containers/stackvector.h => blah_stackvector.h} (99%) rename include/{blah/stream.h => blah_stream.h} (97%) create mode 100644 include/blah_string.h rename include/{blah/drawing/subtexture.h => blah_subtexture.h} (96%) rename include/{blah/time.h => blah_time.h} (98%) rename include/{blah/containers/vector.h => blah_vector.h} (97%) rename src/{app.cpp => blah_app.cpp} (96%) rename src/{images/aseprite.cpp => blah_aseprite.cpp} (96%) rename src/{drawing/batch.cpp => blah_batch.cpp} (98%) rename src/{common.cpp => blah_common.cpp} (88%) rename src/{filesystem.cpp => blah_filesystem.cpp} (90%) rename src/{images/font.cpp => blah_font.cpp} (91%) rename src/{graphics.cpp => blah_graphics.cpp} (99%) rename src/{images/image.cpp => blah_image.cpp} (98%) rename src/{input.cpp => blah_input.cpp} (98%) rename src/{images/packer.cpp => blah_packer.cpp} (99%) rename src/{drawing/spritefont.cpp => blah_spritefont.cpp} (89%) rename src/{stream.cpp => blah_stream.cpp} (98%) create mode 100644 src/blah_string.cpp rename src/{drawing/subtexture.cpp => blah_subtexture.cpp} (96%) rename src/{time.cpp => blah_time.cpp} (96%) delete mode 100644 src/containers/str.cpp rename src/internal/{internal.h => blah_internal.h} (92%) rename src/internal/{platform.h => blah_platform.h} (97%) rename src/internal/{platform_sdl2.cpp => blah_platform_sdl2.cpp} (98%) rename src/internal/{platform_win32.cpp => blah_platform_win32.cpp} (99%) rename src/internal/{renderer.h => blah_renderer.h} (96%) rename src/internal/{renderer_d3d11.cpp => blah_renderer_d3d11.cpp} (99%) rename src/internal/{renderer_opengl.cpp => blah_renderer_opengl.cpp} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce2db97..5b7d640 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,25 +6,25 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_library(blah - src/app.cpp - src/filesystem.cpp - src/common.cpp - src/time.cpp - src/input.cpp - src/stream.cpp - src/graphics.cpp - src/containers/str.cpp - src/drawing/batch.cpp - src/drawing/spritefont.cpp - src/drawing/subtexture.cpp - src/images/aseprite.cpp - src/images/font.cpp - src/images/image.cpp - src/images/packer.cpp - src/internal/renderer_opengl.cpp - src/internal/renderer_d3d11.cpp - src/internal/platform_sdl2.cpp - src/internal/platform_win32.cpp + src/blah_app.cpp + src/blah_filesystem.cpp + src/blah_common.cpp + src/blah_time.cpp + src/blah_input.cpp + src/blah_stream.cpp + src/blah_graphics.cpp + src/blah_string.cpp + src/blah_batch.cpp + src/blah_spritefont.cpp + src/blah_subtexture.cpp + src/blah_aseprite.cpp + src/blah_font.cpp + src/blah_image.cpp + src/blah_packer.cpp + src/internal/blah_renderer_opengl.cpp + src/internal/blah_renderer_d3d11.cpp + src/internal/blah_platform_sdl2.cpp + src/internal/blah_platform_win32.cpp ) target_include_directories(blah diff --git a/include/blah.h b/include/blah.h index ed30ef0..554bae1 100644 --- a/include/blah.h +++ b/include/blah.h @@ -1,27 +1,22 @@ #pragma once - -#include "blah/common.h" -#include "blah/app.h" -#include "blah/filesystem.h" -#include "blah/time.h" -#include "blah/input.h" -#include "blah/stream.h" -#include "blah/graphics.h" - -#include "blah/containers/vector.h" -#include "blah/containers/stackvector.h" -#include "blah/containers/str.h" - -#include "blah/drawing/batch.h" -#include "blah/drawing/spritefont.h" -#include "blah/drawing/subtexture.h" - -#include "blah/images/aseprite.h" -#include "blah/images/font.h" -#include "blah/images/image.h" -#include "blah/images/packer.h" - -#include "blah/math/calc.h" -#include "blah/math/spatial.h" -#include "blah/math/color.h" -#include "blah/math/ease.h" \ No newline at end of file +#include "blah_app.h" +#include "blah_aseprite.h" +#include "blah_batch.h" +#include "blah_calc.h" +#include "blah_color.h" +#include "blah_common.h" +#include "blah_ease.h" +#include "blah_filesystem.h" +#include "blah_font.h" +#include "blah_graphics.h" +#include "blah_image.h" +#include "blah_input.h" +#include "blah_packer.h" +#include "blah_spatial.h" +#include "blah_spritefont.h" +#include "blah_stackvector.h" +#include "blah_string.h" +#include "blah_stream.h" +#include "blah_subtexture.h" +#include "blah_time.h" +#include "blah_vector.h" \ No newline at end of file diff --git a/include/blah/containers/str.h b/include/blah/containers/str.h deleted file mode 100644 index 873deda..0000000 --- a/include/blah/containers/str.h +++ /dev/null @@ -1,321 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace Blah -{ - template class StrOf; - using String = StrOf<64>; - using FilePath = StrOf<260>; - - // A simple String implementation - class Str - { - public: - Str() { m_buffer = empty_buffer; m_length = m_capacity = m_local_size = 0; } - Str(const char* start, const char* end = nullptr) : Str() { set(start, end); } - Str(const Str& str) : Str() { set(str); } - - char& operator[](int index) { return data()[index]; } - const char& operator[](int index) const { return data()[index]; } - - // equality operators - bool operator==(const Str& rhs) const; - bool operator!=(const Str& rhs) const; - bool operator==(const char* rhs) const; - bool operator!=(const char* rhs) const; - - // assignment operator - Str& operator=(const Str& rhs) { set(rhs.cstr(), rhs.cstr() + rhs.m_length); return *this; } - Str& operator=(const char* rhs) { set(rhs, nullptr); return *this; } - - // append string - Str& operator+=(const Str& rhs) { return append(rhs); } - - // append cstr - Str& operator+=(const char* rhs) { return append(rhs); } - - // append char - Str& operator+=(const char& rhs) { return append(rhs); } - - // combine string - Str operator+(const Str& rhs) { Str str; str.append(*this).append(rhs); return str; } - - // combine cstr - Str operator+(const char* rhs) { Str str; str.append(*this).append(rhs); return str; } - - // combine char - Str operator+(const char& rhs) { Str str; str.append(*this).append(rhs); return str; } - - // implicit cast to cstr - operator char* () { return cstr(); } - - // implicit cast to cstr - operator const char* () const { return cstr(); } - - // returns a pointer to the null-terminated string buffer - char* cstr() { return data(); } - - // returns a pointer to the null-terminated string buffer - const char* cstr() const { return data(); } - - // returns a pointer to the start of the buffer - const char* begin() const { return data(); } - - // returns a pointer to the end of the buffer - const char* end() const { return data() + m_length; } - - // returns the length of the string - int length() const { return m_length; } - - // returns the capacity of the string - int capacity() const { return m_capacity; } - - // returns the capacity of the string's stack buffer - int stack_capacity() const { return m_local_size; } - - // sets the length of the string. - // this does not set the value of the string! - void set_length(int length); - - // ensures the string has the given capacity - void reserve(int capacity); - - // Returns the unicode value at the given index. - // Assumes the index is a valid utf8 starting point. - u32 utf8_at(int index) const; - - // Returns the byte-length of the utf8 character. - // Assumes the index is a valid utf8 starting point. - int utf8_length(int index) const; - - // appends the given character - Str& append(char c); - - // appends the given unicode character - Str& append(u32 c); - - // appends the given c string - Str& append(const char* start, const char* end = nullptr); - - // appends the given string - Str& append(const Str& str, int start = 0, int end = -1); - - // appends the given formatted string - Str& append_fmt(const char* fmt, ...); - - // appends a utf16 string - Str& append_utf16(const u16* start, const u16* end = nullptr, bool swapEndian = false); - - // trims whitespace - Str& trim(); - - // returns true if the string begins with the given string - bool starts_with(const Str& str, bool ignore_case = false) const { return starts_with(str.cstr(), ignore_case); } - - // returns true if the string begins with the given string - bool equals(const Str& str, bool ignore_case = false) const { return str.length() == length() && starts_with(str.cstr(), ignore_case); } - - // returns true if the string begins with the given string - bool starts_with(const char* str, bool ignore_case = false) const; - - // returns true if the string contains with the given string - bool contains(const Str& str, bool ignore_case = false) const { return contains(str.cstr(), ignore_case); } - - // returns true if the string contains with the given string - bool contains(const char* str, bool ignore_case = false) const; - - // returns true if the string ends with the given string - bool ends_with(const Str& str, bool ignore_case = false) const { return ends_with(str.cstr(), ignore_case); } - - // returns true if the string ends with the given string - bool ends_with(const char* str, bool ignore_case = false) const; - - // returns the first index of the given character, or -1 if it isn't found - int first_index_of(char ch) const; - - // returns the last index of the given character, or -1 if it isn't found - int last_index_of(char ch) const; - - // returns a substring of the string - String substr(int start) const; - - // returns a substring of the string - String substr(int start, int end) const; - - // Splits the string into a vector of strings - Vector split(char ch) const; - - // replaces all occurances of old string with the new string - Str& replace(const Str& old_str, const Str& new_str); - - // replaces all occurances of the given character in the string - Str& replace(char c, char r); - - // checks if the string has a length of 0 - bool empty() const { return m_length <= 0; } - - // clears the string length to 0 - void clear(); - - // clears and disposes the internal string buffer - void dispose(); - - virtual ~Str() - { - if (m_buffer != nullptr && m_buffer != empty_buffer) - delete[] m_buffer; - } - - protected: - Str(int local_size) - { - m_buffer = nullptr; - m_length = 0; - m_capacity = local_size; - m_local_size = local_size; - } - - // returns a pointer to the heap buffer or to our stack allocation - virtual char* data() { return m_buffer; } - - // returns a pointer to the heap buffer or to our stack allocation - virtual const char* data() const { return m_buffer; } - - // assigns the contents of the string - void set(const Str& str) { set(str.cstr(), str.cstr() + str.m_length); } - - // assigns the contents of the string - void set(const char* start, const char* end = nullptr); - - char* m_buffer; - - private: - static char empty_buffer[1]; - int m_length; - int m_capacity; - int m_local_size; - }; - - // combine string - inline Str operator+(const Str& lhs, const Str& rhs) { Str str; str.append(lhs).append(rhs); return str; } - - // A string with a local stack buffer of size T - template - class StrOf : public Str - { - private: - char m_local_buffer[T]; - - public: - StrOf() : Str(T) { m_local_buffer[0] = '\0'; } - StrOf(const char* rhs, const char* end = nullptr) : Str(T) { m_local_buffer[0] = '\0'; set(rhs, end); } - StrOf(const Str& rhs) : Str(T) { m_local_buffer[0] = '\0'; set(rhs); } - StrOf(const StrOf& rhs) : Str(T) { m_local_buffer[0] = '\0'; set(rhs); } - - // assignment operators - StrOf& operator=(const char* rhs) { set(rhs); return *this; } - StrOf& operator=(const Str& rhs) { set(rhs); return *this; } - StrOf& operator=(const StrOf& rhs) { set(rhs); return *this; } - - // either return stack or heap buffer depending on which is in-use - char* data() override { return m_buffer != nullptr ? m_buffer : m_local_buffer; } - const char* data() const override { return m_buffer != nullptr ? m_buffer : m_local_buffer; } - - // creates a string from the format - static StrOf fmt(const char* str, ...); - }; - - template - StrOf StrOf::fmt(const char* fmt, ...) - { - StrOf str; - - int add, diff; - - // determine arg length - va_list args; - va_start(args, fmt); - add = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - // reserve - auto len = str.length(); - str.set_length(len + add); - diff = str.capacity() - len; - if (diff <= 0) diff = 0; - - // print out - va_start(args, fmt); - vsnprintf(str.cstr() + len, (size_t)diff, fmt, args); - va_end(args); - - return str; - } - - struct CaseInsenstiveStringHash - { - std::size_t operator()(const Blah::Str& key) const - { - std::size_t result = 2166136261U; - - for (auto& it : key) - { - if (it >= 'A' && it <= 'Z') - result ^= (static_cast(it) - 'A' + 'a'); - else - result ^= static_cast(it); - result *= 16777619U; - } - - return result; - } - }; - - struct CaseInsenstiveStringCompare - { - bool operator() (const Str& lhs, const Str& rhs) const - { - return lhs.length() == rhs.length() && lhs.starts_with(rhs, true); - } - }; -} - -namespace std -{ - template <> - struct hash - { - std::size_t operator()(const Blah::Str& key) const - { - std::size_t result = 2166136261U; - - for (auto& it : key) - { - result ^= static_cast(it); - result *= 16777619U; - } - - return result; - } - }; - - template - struct hash> - { - std::size_t operator()(const Blah::StrOf& key) const - { - std::size_t result = 2166136261U; - - for (auto& it : key) - { - result ^= static_cast(it); - result *= 16777619U; - } - - return result; - } - }; -} \ No newline at end of file diff --git a/include/blah/app.h b/include/blah_app.h similarity index 98% rename from include/blah/app.h rename to include/blah_app.h index 16b8347..27b370a 100644 --- a/include/blah/app.h +++ b/include/blah_app.h @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include +#include +#include namespace Blah { diff --git a/include/blah/images/aseprite.h b/include/blah_aseprite.h similarity index 94% rename from include/blah/images/aseprite.h rename to include/blah_aseprite.h index 8cf2a3b..ced8a1f 100644 --- a/include/blah/images/aseprite.h +++ b/include/blah_aseprite.h @@ -1,9 +1,9 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/drawing/batch.h b/include/blah_batch.h similarity index 97% rename from include/blah/drawing/batch.h rename to include/blah_batch.h index e0c08d1..5874101 100644 --- a/include/blah/drawing/batch.h +++ b/include/blah_batch.h @@ -1,11 +1,11 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/math/calc.h b/include/blah_calc.h similarity index 98% rename from include/blah/math/calc.h rename to include/blah_calc.h index 4cce4f1..807f1ec 100644 --- a/include/blah/math/calc.h +++ b/include/blah_calc.h @@ -1,6 +1,5 @@ #pragma once -#include -#include +#include namespace Blah { diff --git a/include/blah/math/color.h b/include/blah_color.h similarity index 98% rename from include/blah/math/color.h rename to include/blah_color.h index 424f319..0b82d1a 100644 --- a/include/blah/math/color.h +++ b/include/blah_color.h @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include +#include +#include #define BLAH_HEX_VALUE(n) ((n >= '0' && n <= '9') ? (n - '0') : ((n >= 'A' && n <= 'F') ? (10 + n - 'A') : ((n >= 'a' && n <= 'f') ? (10 + n - 'a') : 0))) diff --git a/include/blah/common.h b/include/blah_common.h similarity index 84% rename from include/blah/common.h rename to include/blah_common.h index d24a9fe..88b7125 100644 --- a/include/blah/common.h +++ b/include/blah_common.h @@ -1,10 +1,29 @@ #pragma once +#include // for in-place constructors, for Vector/StackVector +#include // for std::move, std::forward +#include // for integer types +#include // for std::size_t +#include // for abort +#include // for string format methods +#include // for standard lib math functions used in blah_calc.h -#include // for in-place constructors, for Vector/StackVector -#include // for std::move +// Numeric Types +namespace Blah +{ + using i8 = int8_t; + using i16 = int16_t; + using i32 = int32_t; + using i64 = int64_t; + using u8 = uint8_t; + using u16 = uint16_t; + using u32 = uint32_t; + using u64 = uint64_t; + using f32 = float; + using f64 = double; + using size_t = std::size_t; +} // Aborts -#include // for abort #ifdef _WIN32 #define BLAH_ABORT() do { __debugbreak(); ::exit(1); } while(0) #else @@ -34,24 +53,6 @@ } \ } while(0) -// Numeric Types -#include // for integer types -#include // for size_t type -namespace Blah -{ - using i8 = int8_t; - using i16 = int16_t; - using i32 = int32_t; - using i64 = int64_t; - using u8 = uint8_t; - using u16 = uint16_t; - using u32 = uint32_t; - using u64 = uint64_t; - using f32 = float; - using f64 = double; - using size_t = std::size_t; -} - // Logging namespace Blah { diff --git a/include/blah/math/ease.h b/include/blah_ease.h similarity index 99% rename from include/blah/math/ease.h rename to include/blah_ease.h index 09028d5..dca067c 100644 --- a/include/blah/math/ease.h +++ b/include/blah_ease.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include namespace Blah { diff --git a/include/blah/filesystem.h b/include/blah_filesystem.h similarity index 96% rename from include/blah/filesystem.h rename to include/blah_filesystem.h index bca774d..6c5c01a 100644 --- a/include/blah/filesystem.h +++ b/include/blah_filesystem.h @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include +#include +#include namespace Blah { diff --git a/include/blah/images/font.h b/include/blah_font.h similarity index 93% rename from include/blah/images/font.h rename to include/blah_font.h index 0aedcec..d66d4f9 100644 --- a/include/blah/images/font.h +++ b/include/blah_font.h @@ -1,10 +1,10 @@ #pragma once -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/graphics.h b/include/blah_graphics.h similarity index 98% rename from include/blah/graphics.h rename to include/blah_graphics.h index 1cc752b..7514be9 100644 --- a/include/blah/graphics.h +++ b/include/blah_graphics.h @@ -1,14 +1,15 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include namespace Blah { + class Stream; + class Shader; using ShaderRef = Ref; class Texture; using TextureRef = Ref; class Target; using TargetRef = Ref; diff --git a/include/blah/images/image.h b/include/blah_image.h similarity index 94% rename from include/blah/images/image.h rename to include/blah_image.h index 49c53be..1e04314 100644 --- a/include/blah/images/image.h +++ b/include/blah_image.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/input.h b/include/blah_input.h similarity index 99% rename from include/blah/input.h rename to include/blah_input.h index 5ec2f03..768d7c2 100644 --- a/include/blah/input.h +++ b/include/blah_input.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include // These are generally copied from the SDL2 Scancode Keys, // which are in turn based on the USB standards: diff --git a/include/blah/images/packer.h b/include/blah_packer.h similarity index 91% rename from include/blah/images/packer.h rename to include/blah_packer.h index 638354c..6e57c40 100644 --- a/include/blah/images/packer.h +++ b/include/blah_packer.h @@ -1,12 +1,12 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/math/spatial.h b/include/blah_spatial.h similarity index 99% rename from include/blah/math/spatial.h rename to include/blah_spatial.h index 0c92ee4..aaea9cd 100644 --- a/include/blah/math/spatial.h +++ b/include/blah_spatial.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include namespace Blah { diff --git a/include/blah/drawing/spritefont.h b/include/blah_spritefont.h similarity index 95% rename from include/blah/drawing/spritefont.h rename to include/blah_spritefont.h index fd404a6..8e0fb42 100644 --- a/include/blah/drawing/spritefont.h +++ b/include/blah_spritefont.h @@ -1,9 +1,9 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah/containers/stackvector.h b/include/blah_stackvector.h similarity index 99% rename from include/blah/containers/stackvector.h rename to include/blah_stackvector.h index 594d3d6..2e58d04 100644 --- a/include/blah/containers/stackvector.h +++ b/include/blah_stackvector.h @@ -1,5 +1,5 @@ #pragma once -#include +#include namespace Blah { @@ -10,7 +10,7 @@ namespace Blah class StackVector { private: - char m_buffer[sizeof(T) * Capacity]; + u8 m_buffer[sizeof(T) * Capacity]; int m_count; public: diff --git a/include/blah/stream.h b/include/blah_stream.h similarity index 97% rename from include/blah/stream.h rename to include/blah_stream.h index 434483a..5fc5cf2 100644 --- a/include/blah/stream.h +++ b/include/blah_stream.h @@ -1,9 +1,9 @@ #pragma once -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace Blah { diff --git a/include/blah_string.h b/include/blah_string.h new file mode 100644 index 0000000..55d27a0 --- /dev/null +++ b/include/blah_string.h @@ -0,0 +1,371 @@ +#pragma once +#include +#include +#include + +namespace Blah +{ + class BaseString + { + public: + const char* cstr() const { return s_ptr(); } + char* cstr() { return s_ptr(); } + const char* begin() const { return s_ptr(); } + char* begin() { return s_ptr(); } + const char* end() const { return s_ptr() + length(); } + char* end() { return s_ptr() + length(); } + + char& operator[](int index) + { + BLAH_ASSERT(index >= 0 && index < length(), "Index out of range"); + return s_ptr()[index]; + } + + const char& operator[](int index) const + { + BLAH_ASSERT(index >= 0 && index < length(), "Index out of range"); + return s_ptr()[index]; + } + + operator char* () { return cstr(); } + operator const char* () const { return cstr(); } + + void assign(const char* cstr, const char* cstr_end = nullptr); + void append(const char* cstr, const char* cstr_end = nullptr); + void append(const u16* u16_cstr, const u16* u16_cstr_end = nullptr, bool swap_endian = false); + void append(char ch, int count = 1); + void append(u32 unicode); + void append_fmt(const char* fmt, ...); + + bool starts_with(const char* cstr, bool ignore_case = false) const; + bool ends_with(const char* cstr, bool ignore_case = false) const; + bool contains(const char* cstr, bool ignore_case = false) const; + + int first_index_of(char ch) const; + int last_index_of(char ch) const; + + int length() const + { + int n = s_len() - 1; // reduce by 1 for null-terminator + return (n > 0 ? n : 0); // safety, although due to how StackString is implemented s_len shouldn't ever be less than 1 + } + + bool equals(const char* other, bool ignore_case = false) const; + bool empty() const { return length() == 0; } + void clear() { s_clear(); } + + bool operator==(const char* rhs) const { return equals(rhs); } + bool operator!=(const char* rhs) const { return !(*this == rhs); } + bool operator==(const BaseString& rhs) const { return s_len() == rhs.s_len() && *this == rhs.cstr(); } + bool operator!=(const BaseString& rhs) const { return !(*this == rhs); } + + protected: + virtual void s_clear() = 0; + virtual void s_ensure(int capacity) = 0; + virtual char* s_ptr() = 0; + virtual const char* s_ptr() const = 0; + virtual int s_len() const = 0; + }; + + template + class StackString final : public BaseString + { + public: + StackString() { assign(""); } + StackString(const char* cstr, const char* cstr_end = nullptr) { assign(cstr, cstr_end); } + StackString(const BaseString& other) { assign(other.cstr()); } + + StackString& operator=(const BaseString& rhs) + { + assign(rhs.cstr(), rhs.cstr() + rhs.length()); + return *this; + } + + StackString& operator=(const char* rhs) + { + assign(rhs, nullptr); + return *this; + } + + StackString& operator+=(const BaseString& rhs) + { + append(rhs.cstr()); + return *this; + } + + StackString& operator+=(const char* rhs) + { + append(rhs); + return *this; + } + + StackString& operator+=(const char& rhs) + { + append(rhs); + return *this; + } + + StackString operator+(const BaseString& rhs) + { + StackString str(*this); + str += rhs; + return str; + } + + StackString operator+(const char* rhs) + { + StackString str(*this); + str += rhs; + return str; + } + + StackString operator+(const char& rhs) + { + StackString str(*this); + str += rhs; + return str; + } + + StackString substr(int start, int len = 0) const + { + if (len == 0) len = length() - start; + return StackString(cstr() + start, cstr() + start + len); + } + + StackString trim() const + { + if (length() > 0) + { + const char* s = begin(); + const char* e = end() - 1; + + while (s < e && (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n' || *s == '\v' || *s == '\f')) s++; + while (e > s && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n' || *e == '\v' || *e == '\f')) e--; + + return StackString(s, e + 1); + } + + return StackString(); + } + + Vector split(char ch) const + { + Vector result; + + const char* ptr = s_ptr(); + const char* end = ptr + length(); + const char* last = ptr; + + while (ptr < end) + { + if (*ptr == ch) + { + result.emplace_back(last, ptr); + last = ptr + 1; + } + ptr++; + } + + if (last < ptr) + result.emplace_back(last, ptr); + + return result; + } + + static StackString fmt(const char* fmt, ...) + { + StackString str; + + va_list args; + + // determine arg m_length + va_start(args, fmt); + auto add = vsnprintf(nullptr, 0, fmt, args); + va_end(args); + + if (add <= 0) + return str; + + // reserve (+1 for null-terminator) + auto len = str.length(); + str.s_ensure(len + add + 1); + + // print out + va_start(args, fmt); + vsnprintf(str.s_ptr() + len, add + 1, fmt, args); + va_end(args); + + return str; + } + + protected: + void s_clear() override + { + m_stack_buffer.clear(); + m_heap_buffer.clear(); + s_ensure(1); + } + + void s_ensure(int capacity) override + { + int count = capacity - s_len(); + if (count <= 0) + return; + + // expand heap buffer + if (m_heap_buffer.size() > 0) + { + m_heap_buffer.expand(count); + } + // switch from stack to heap + else if (capacity > StackSize) + { + m_heap_buffer.expand(capacity); + + char* src = m_stack_buffer.data(); + char* len = src + m_stack_buffer.size(); + char* dst = m_heap_buffer.data(); + while (src < len) *(dst++) = *(src++); + } + // expand stack buffer + else + { + m_stack_buffer.expand(count); + } + + *(s_ptr() + s_len() - 1) = '\0'; + } + + char* s_ptr() override + { + return m_heap_buffer.size() > 0 ? m_heap_buffer.data() : m_stack_buffer.data(); + } + + const char* s_ptr() const override + { + return m_heap_buffer.size() > 0 ? m_heap_buffer.data() : m_stack_buffer.data(); + } + + int s_len() const override + { + return m_heap_buffer.size() > 0 ? m_heap_buffer.size() : m_stack_buffer.size(); + } + + private: + Vector m_heap_buffer; + StackVector m_stack_buffer; + }; + + template + StackString operator+(const StackString& lhs, const BaseString& rhs) + { + StackString str(lhs); + str += rhs; + return str; + } + + template + StackString operator+(const StackString& lhs, const char* rhs) + { + StackString str(lhs); + str += rhs; + return str; + } + + template + StackString operator+(const StackString& lhs, const char& rhs) + { + StackString str(lhs); + str += rhs; + return str; + } + + // Stores enough for an empty string on the stack, and afterwards allocates on the heap + using HeapString = StackString<1>; + + // Standard String with a fair amount of stack storage + using String = StackString<64>; + + // Large String with enough stack storage to store FilePaths without allocating. + using FilePath = StackString<260>; + + // Utf8 Utility, to iterate over a string and read utf-8 characters + struct Utf8 + { + const char* str = nullptr; + u32 character = 0; + u32 character_size = 0; + + Utf8() = default; + Utf8(const char* cstr); + + // moves to the next character, returns false if at end of string or an invalid character + bool next(); + }; + + struct CaseInsenstiveStringHash + { + std::size_t operator()(const Blah::BaseString& key) const + { + std::size_t result = 2166136261U; + + for (auto& it : key) + { + if (it >= 'A' && it <= 'Z') + result ^= (static_cast(it) - 'A' + 'a'); + else + result ^= static_cast(it); + result *= 16777619U; + } + + return result; + } + }; + + struct CaseInsenstiveStringCompare + { + bool operator() (const BaseString& lhs, const BaseString& rhs) const + { + return lhs.length() == rhs.length() && lhs.starts_with(rhs, true); + } + }; +} + +// STD Hash Utility, so the String can be used in a set / unordered_map / map + +namespace std +{ + template <> + struct hash + { + std::size_t operator()(const Blah::BaseString& key) const + { + std::size_t result = 2166136261U; + + for (auto& it : key) + { + result ^= static_cast(it); + result *= 16777619U; + } + + return result; + } + }; + + template + struct hash> + { + std::size_t operator()(const Blah::StackString& key) const + { + std::size_t result = 2166136261U; + + for (auto& it : key) + { + result ^= static_cast(it); + result *= 16777619U; + } + + return result; + } + }; +} \ No newline at end of file diff --git a/include/blah/drawing/subtexture.h b/include/blah_subtexture.h similarity index 96% rename from include/blah/drawing/subtexture.h rename to include/blah_subtexture.h index 15211b5..8f1d990 100644 --- a/include/blah/drawing/subtexture.h +++ b/include/blah_subtexture.h @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include namespace Blah { diff --git a/include/blah/time.h b/include/blah_time.h similarity index 98% rename from include/blah/time.h rename to include/blah_time.h index 937a4cd..133e1aa 100644 --- a/include/blah/time.h +++ b/include/blah_time.h @@ -1,5 +1,5 @@ #pragma once -#include +#include namespace Blah { diff --git a/include/blah/containers/vector.h b/include/blah_vector.h similarity index 97% rename from include/blah/containers/vector.h rename to include/blah_vector.h index 0004058..986ec0d 100644 --- a/include/blah/containers/vector.h +++ b/include/blah_vector.h @@ -1,6 +1,5 @@ #pragma once -#include -#include +#include namespace Blah { @@ -182,7 +181,10 @@ namespace Blah if constexpr (std::is_trivially_copyable()) { - memcpy(new_buffer, m_buffer, m_count * sizeof(T)); + u8* src = (u8*)m_buffer; + u8* len = src + m_count * sizeof(T); + u8* dst = (u8*)new_buffer; + while (src < len) *(dst++) = *(src++); } else { @@ -356,4 +358,4 @@ namespace Blah m_count--; return value; } -} +} \ No newline at end of file diff --git a/src/app.cpp b/src/blah_app.cpp similarity index 96% rename from src/app.cpp rename to src/blah_app.cpp index 5b20e90..04f814b 100644 --- a/src/app.cpp +++ b/src/blah_app.cpp @@ -1,9 +1,9 @@ -#include -#include -#include -#include "internal/internal.h" -#include "internal/platform.h" -#include "internal/renderer.h" +#include +#include +#include +#include "internal/blah_internal.h" +#include "internal/blah_platform.h" +#include "internal/blah_renderer.h" #ifdef __EMSCRIPTEN__ #include @@ -400,8 +400,10 @@ void App::set_flag(u32 flag, bool enabled) if (was != app_flags) { - Internal::platform->set_app_flags(app_flags); - Internal::renderer->set_app_flags(app_flags); + if (Internal::platform) + Internal::platform->set_app_flags(app_flags); + if (Internal::renderer) + Internal::renderer->set_app_flags(app_flags); } } diff --git a/src/images/aseprite.cpp b/src/blah_aseprite.cpp similarity index 96% rename from src/images/aseprite.cpp rename to src/blah_aseprite.cpp index ceeabc3..f6f5012 100644 --- a/src/images/aseprite.cpp +++ b/src/blah_aseprite.cpp @@ -1,10 +1,10 @@ -#include -#include -#include +#include +#include +#include #define STBI_NO_STDIO #define STBI_ONLY_ZLIB -#include "../third_party/stb_image.h" +#include "third_party/stb_image.h" using namespace Blah; @@ -133,7 +133,7 @@ void Aseprite::parse_layer(Stream& stream, int frame) layer.alpha = stream.read_u8(Endian::Little); stream.seek(stream.position() + 3); // for future - layer.name.set_length(stream.read_u16(Endian::Little)); + layer.name.append('\0', stream.read_u16(Endian::Little)); stream.read(layer.name.cstr(), layer.name.length()); layer.userdata.color = 0xffffff; @@ -261,7 +261,7 @@ void Aseprite::parse_user_data(Stream& stream, int frame) // has text if (flags & (1 << 0)) { - m_last_userdata->text.set_length(stream.read_u16(Endian::Little)); + m_last_userdata->text.append('\0', stream.read_u16(Endian::Little)); stream.read(m_last_userdata->text.cstr(), m_last_userdata->text.length()); } @@ -287,7 +287,7 @@ void Aseprite::parse_tag(Stream& stream, int frame) tag.color = Color(stream.read_i8(), stream.read_i8(), stream.read_i8(Endian::Little), 255); stream.seek(stream.position() + 1); - tag.name.set_length(stream.read_u16(Endian::Little)); + tag.name.append('\0', stream.read_u16(Endian::Little)); stream.read(tag.name.cstr(), tag.name.length()); tags.push_back(tag); @@ -301,7 +301,7 @@ void Aseprite::parse_slice(Stream& stream, int frame) stream.read_u32(Endian::Little); // reserved String name; - name.set_length(stream.read_u16(Endian::Little)); + name.append('\0', stream.read_u16(Endian::Little)); stream.read(name.cstr(), name.length()); for (int s = 0; s < count; s++) diff --git a/src/drawing/batch.cpp b/src/blah_batch.cpp similarity index 98% rename from src/drawing/batch.cpp rename to src/blah_batch.cpp index 5b07d31..5c4ee3e 100644 --- a/src/drawing/batch.cpp +++ b/src/blah_batch.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include "../internal/internal.h" +#include +#include +#include +#include "internal/blah_internal.h" using namespace Blah; @@ -969,11 +969,11 @@ void Batch::str(const SpriteFont& font, const String& text, const Vec2f& pos, co offset.y -= font.height_of(text) * justify.y; u32 last = 0; - for (int i = 0, l = text.length(); i < l; i += text.utf8_length(i)) + Utf8 utf8(text.cstr()); + int i = 0; + while (utf8.character) { - u32 next = text.utf8_at(i); - - if (next == '\n') + if (utf8.character == '\n') { offset.x = 0; offset.y += font.line_height(); @@ -982,22 +982,24 @@ void Batch::str(const SpriteFont& font, const String& text, const Vec2f& pos, co offset.x -= font.width_of_line(text, i + 1) * justify.x; last = 0; - continue; } - - const auto& ch = font[next]; - if (ch.subtexture.texture) + else { - Vec2f at = offset + ch.offset; + const auto& ch = font[utf8.character]; + if (ch.subtexture.texture) + { + Vec2f at = offset + ch.offset; + if (last) + at.x += font.get_kerning(last, utf8.character); + tex(ch.subtexture, at, color); + } - if (i > 0 && text[i - 1] != '\n') - at.x += font.get_kerning(last, next); - - tex(ch.subtexture, at, color); + offset.x += ch.advance; + last = utf8.character; } - offset.x += ch.advance; - last = next; + i += utf8.character_size; + utf8.next(); } pop_matrix(); diff --git a/src/common.cpp b/src/blah_common.cpp similarity index 88% rename from src/common.cpp rename to src/blah_common.cpp index 768d5ea..d3bc55c 100644 --- a/src/common.cpp +++ b/src/blah_common.cpp @@ -1,7 +1,5 @@ -#include -#include -#include // for logging methods -#include // for sprintf +#include +#include using namespace Blah; diff --git a/src/filesystem.cpp b/src/blah_filesystem.cpp similarity index 90% rename from src/filesystem.cpp rename to src/blah_filesystem.cpp index 76db0b5..f1fc66b 100644 --- a/src/filesystem.cpp +++ b/src/blah_filesystem.cpp @@ -1,5 +1,5 @@ -#include -#include "internal/internal.h" +#include +#include "internal/blah_internal.h" using namespace Blah; @@ -70,7 +70,10 @@ Vector Directory::enumerate(const FilePath& path, bool recursive) { App::Internal::platform->dir_enumerate(list, path.cstr(), recursive); for (auto& it : list) - it.replace('\\', '/'); + { + for (int n = 0; n < it.length(); n ++) + if (it[n] == '\\') it[n] = '/'; + } } return list; @@ -114,10 +117,10 @@ FilePath Path::get_directory_name(const FilePath& path) { FilePath directory = path; while (directory.ends_with("/")) - directory = directory.substr(0, -1); + directory = FilePath(directory.begin(), directory.end() - 1); auto last = directory.last_index_of('/'); if (last >= 0) - directory = directory.substr(0, last + 1); + directory = FilePath(directory.begin(), directory.begin() + last + 1); return directory; } @@ -156,7 +159,7 @@ FilePath Path::normalize(const FilePath& path) for (auto k = normalized.length() - 1; k > 0; k--) if (normalized[k - 1] == '/') { - normalized = normalized.substr(0, k - 1); + normalized = FilePath(normalized.begin(), normalized.begin() + k - 1); could_move_up = true; break; } @@ -181,5 +184,5 @@ FilePath Path::join(const FilePath& a, const FilePath& b) else if (b.length() <= 0) return normalize(a); else - return normalize(FilePath(a).append("/").append(b)); + return normalize(a + "/" + b); } \ No newline at end of file diff --git a/src/images/font.cpp b/src/blah_font.cpp similarity index 91% rename from src/images/font.cpp rename to src/blah_font.cpp index 5ada39e..138ad0f 100644 --- a/src/images/font.cpp +++ b/src/blah_font.cpp @@ -1,15 +1,15 @@ -#include -#include +#include +#include using namespace Blah; #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION -#include "../third_party/stb_truetype.h" +#include "third_party/stb_truetype.h" namespace { - String get_font_name(stbtt_fontinfo* font, int nameId) + String blah_get_font_name(stbtt_fontinfo* font, int name_id) { int length = 0; @@ -18,14 +18,14 @@ namespace STBTT_PLATFORM_ID_MICROSOFT, STBTT_MS_EID_UNICODE_BMP, STBTT_MS_LANG_ENGLISH, - nameId); + name_id); // we want the size in wide chars length /= 2; String str; if (length > 0) - str.append_utf16(ptr, ptr + length, Calc::is_little_endian()); + str.append(ptr, ptr + length, Calc::is_little_endian()); return str; } } @@ -56,8 +56,8 @@ FontRef Font::create(Stream& stream) auto font = FontRef(new Font()); font->m_font = stbtt; font->m_buffer = std::move(buffer); - font->m_family_name = get_font_name(fn, 1); - font->m_style_name = get_font_name(fn, 2); + font->m_family_name = blah_get_font_name(fn, 1); + font->m_style_name = blah_get_font_name(fn, 2); stbtt_GetFontVMetrics(fn, &font->m_ascent, &font->m_descent, &font->m_line_gap); return font; } diff --git a/src/graphics.cpp b/src/blah_graphics.cpp similarity index 99% rename from src/graphics.cpp rename to src/blah_graphics.cpp index c451964..437d87f 100644 --- a/src/graphics.cpp +++ b/src/blah_graphics.cpp @@ -1,5 +1,6 @@ -#include -#include "internal/internal.h" +#include +#include +#include "internal/blah_internal.h" using namespace Blah; diff --git a/src/images/image.cpp b/src/blah_image.cpp similarity index 98% rename from src/images/image.cpp rename to src/blah_image.cpp index 83b5c03..30bf35c 100644 --- a/src/images/image.cpp +++ b/src/blah_image.cpp @@ -1,14 +1,14 @@ -#include +#include using namespace Blah; #define STB_IMAGE_IMPLEMENTATION #define STBI_ONLY_JPEG #define STBI_ONLY_PNG -#include "../third_party/stb_image.h" +#include "third_party/stb_image.h" #define STB_IMAGE_WRITE_IMPLEMENTATION -#include "../third_party/stb_image_write.h" +#include "third_party/stb_image_write.h" namespace { diff --git a/src/input.cpp b/src/blah_input.cpp similarity index 98% rename from src/input.cpp rename to src/blah_input.cpp index e0228ef..aeb5c82 100644 --- a/src/input.cpp +++ b/src/blah_input.cpp @@ -1,11 +1,10 @@ -#include -#include -#include -#include -#include -#include "internal/internal.h" -#include "internal/platform.h" -#include +#include +#include +#include +#include +#include +#include "internal/blah_internal.h" +#include "internal/blah_platform.h" using namespace Blah; @@ -33,9 +32,9 @@ void Input::Internal::init() Input::last_state = g_empty_state; Input::state = g_empty_state; - g_buttons.dispose(); - g_axes.dispose(); - g_sticks.dispose(); + g_buttons = Vector>(); + g_axes = Vector>(); + g_sticks = Vector>(); } void Input::Internal::shutdown() diff --git a/src/images/packer.cpp b/src/blah_packer.cpp similarity index 99% rename from src/images/packer.cpp rename to src/blah_packer.cpp index e0e83be..029f3bc 100644 --- a/src/images/packer.cpp +++ b/src/blah_packer.cpp @@ -1,6 +1,5 @@ -#include +#include #include -#include using namespace Blah; diff --git a/src/drawing/spritefont.cpp b/src/blah_spritefont.cpp similarity index 89% rename from src/drawing/spritefont.cpp rename to src/blah_spritefont.cpp index 00e9a43..9421ae4 100644 --- a/src/drawing/spritefont.cpp +++ b/src/blah_spritefont.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include using namespace Blah; @@ -46,21 +46,25 @@ float SpriteFont::width_of(const String& text) const float line_width = 0; Codepoint last = 0; - for (int i = 0; i < text.length(); i += text.utf8_length(i)) + + Utf8 utf8(text.cstr()); + while (utf8.character) { - if (text[i] == '\n') + if (utf8.character == '\n') { line_width = 0; - continue; + } + else + { + line_width += get_character(utf8.character).advance; + if (last) + line_width += get_kerning(last, utf8.character); + if (line_width > width) + width = line_width; + last = utf8.character; } - auto next = text.utf8_at(i); - line_width += get_character(next).advance; - if (i > 0) - line_width += get_kerning(last, next); - if (line_width > width) - width = line_width; - last = next; + utf8.next(); } return width; @@ -72,18 +76,19 @@ float SpriteFont::width_of_line(const String& text, int start) const if (start >= text.length()) return 0; float width = 0; - Codepoint last = 0; - for (auto i = start; i < text.length(); i += text.utf8_length(i)) - { - if (text[i] == '\n') - return width; - auto next = text.utf8_at(i); - width += get_character(next).advance; - if (i > 0) - width += get_kerning(last, next); - last = next; + Utf8 utf8(text.cstr()); + while (utf8.character) + { + if (utf8.character == '\n') + break; + + width += get_character(utf8.character).advance; + if (last) + width += get_kerning(last, utf8.character); + last = utf8.character; + utf8.next(); } return width; @@ -95,10 +100,13 @@ float SpriteFont::height_of(const String& text) const return 0; float height = line_height(); - for (auto i = 0; i < text.length(); i += text.utf8_length(i)) + + Utf8 utf8(text.cstr()); + while (utf8.character) { - if (text[i] == '\n') + if (utf8.character == '\n') height += line_height(); + utf8.next(); } return height - line_gap; diff --git a/src/stream.cpp b/src/blah_stream.cpp similarity index 98% rename from src/stream.cpp rename to src/blah_stream.cpp index c794f31..5efb744 100644 --- a/src/stream.cpp +++ b/src/blah_stream.cpp @@ -1,6 +1,5 @@ -#include -#include -#include +#include +#include using namespace Blah; @@ -47,7 +46,7 @@ String Stream::read_string(int length) } else { - result.set_length(length); + result.append('\0', length); read(result.cstr(), length); } diff --git a/src/blah_string.cpp b/src/blah_string.cpp new file mode 100644 index 0000000..b24dc9f --- /dev/null +++ b/src/blah_string.cpp @@ -0,0 +1,360 @@ +#include + +using namespace Blah; + +namespace +{ + char blah_to_lower(char c) + { + if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; + return c; + } + + int blah_strlen(const char* cstr) + { + int len = 0; + if (cstr) + while (*(cstr + len) != '\0' && len < INT32_MAX) len++; + return len; + } +} + +void BaseString::assign(const char* cstr, const char* cstr_end) +{ + s_clear(); + append(cstr, cstr_end); +} + +void BaseString::append(const char* cstr, const char* cstr_end) +{ + // make sure values are valid + if (cstr == nullptr || *cstr == '\0') + return; + if (cstr_end == nullptr) + cstr_end = cstr + blah_strlen(cstr); + + // reserve (+1 for null-terminator) + auto len = length(); + s_ensure(len + (cstr_end - cstr) + 1); + + // copy value over to our buffer + char* dst = s_ptr() + len; + while (cstr < cstr_end) + *(dst++) = *(cstr++); +} + +void BaseString::append(const u16* u16_cstr, const u16* u16_cstr_end, bool swap_endian) +{ + // converts utf16 into utf8 + // more info: https://en.wikipedia.org/wiki/UTF-16#Description + + const u16 surrogate_min = 0xd800u; + const u16 surrogate_max = 0xdbffu; + + while ((u16_cstr_end == nullptr && *u16_cstr != 0) || (u16_cstr_end != nullptr && u16_cstr != u16_cstr_end)) + { + u16 next = (*u16_cstr++); + if (swap_endian) + next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8)); + + u32 cp = 0xffff & next; + + if ((cp >= surrogate_min && cp <= surrogate_max)) + { + next = (*u16_cstr++); + if (swap_endian) + next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8)); + + u32 trail = 0xffff & next; + cp = (cp << 10) + trail + 0x10000u - (surrogate_min << 10) - 0xdc00u; + } + + append(cp); + } +} + +void BaseString::append(char ch, int count) +{ + // reserve (+1 for null-terminator) + auto len = length(); + s_ensure(len + count + 1); + + // copy value over to our buffer + char* dst = s_ptr() + len; + char* end = dst + count; + while (dst < end) + *(dst++) = ch; +} + +void BaseString::append(u32 c) +{ + // one octet + if (c < 0x80) + { + append((char)c); + } + // two octets + else if (c < 0x800) + { + append((char)((c >> 6) | 0xc0)); + append((char)((c & 0x3f) | 0x80)); + } + // three octets + else if (c < 0x10000) + { + append((char)((c >> 12) | 0xe0)); + append((char)(((c >> 6) & 0x3f) | 0x80)); + append((char)((c & 0x3f) | 0x80)); + } + // four octets + else + { + append((char)((c >> 18) | 0xf0)); + append((char)(((c >> 12) & 0x3f) | 0x80)); + append((char)(((c >> 6) & 0x3f) | 0x80)); + append((char)((c & 0x3f) | 0x80)); + } +} + +void BaseString::append_fmt(const char* fmt, ...) +{ + va_list args; + + // determine arg m_length + va_start(args, fmt); + auto add = vsnprintf(nullptr, 0, fmt, args); + va_end(args); + + if (add <= 0) + return; + + // reserve (+1 for null-terminator) + auto len = length(); + s_ensure(len + add + 1); + + // print out + va_start(args, fmt); + vsnprintf(s_ptr() + len, add + 1, fmt, args); + va_end(args); +} + +bool BaseString::starts_with(const char* cstr, bool ignore_case) const +{ + if (cstr == nullptr || *cstr == '\0') + return length() == 0; + + const char* ptr = s_ptr(); + + if (ignore_case) + { + while (*cstr != '\0') + { + if (blah_to_lower(*cstr) != blah_to_lower(*ptr)) + return false; + cstr++; ptr++; + } + } + else + { + while (*cstr != '\0') + { + if (*cstr != *ptr) + return false; + cstr++; ptr++; + } + } + + return true; +} + +bool BaseString::ends_with(const char* cstr, bool ignore_case) const +{ + if (cstr == nullptr || *cstr == '\0') + return length() == 0; + + int len = blah_strlen(cstr); + if (len > length()) + return false; + + const char* ptr = s_ptr() + length() - len; + + if (ignore_case) + { + while (*cstr != '\0') + { + if (blah_to_lower(*cstr) != blah_to_lower(*ptr)) + return false; + cstr++; ptr++; + } + } + else + { + while (*cstr != '\0') + { + if (*cstr != *ptr) + return false; + cstr++; ptr++; + } + } + + return true; +} + +bool BaseString::contains(const char* cstr, bool ignore_case) const +{ + if (cstr == nullptr || *cstr == '\0') + return length() == 0; + + int len = blah_strlen(cstr); + if (len > length()) + return false; + + const char* ptr = s_ptr(); + const char* end = s_ptr() + len; + + while (ptr < end) + { + const char* at = ptr; + bool match = true; + + if (ignore_case) + { + while (*cstr != '\0') + { + if (blah_to_lower(*cstr) != blah_to_lower(*at)) + { + match = false; + break; + } + cstr++; at++; + } + } + else + { + while (*cstr != '\0') + { + if (*cstr != *at) + { + match = false; + break; + } + cstr++; at++; + } + } + + if (match) + return true; + } + + return false; +} + +int BaseString::first_index_of(char ch) const +{ + const char* ptr = s_ptr(); + const char* end = ptr + length(); + + while (ptr < end) + { + if (*ptr == ch) + return ptr - s_ptr(); + ptr++; + } + + return -1; +} + +int BaseString::last_index_of(char ch) const +{ + const char* ptr = s_ptr(); + const char* end = ptr + length() - 1; + + while (end >= ptr) + { + if (*end == ch) + return end - s_ptr(); + end--; + } + + return -1; +} + +bool BaseString::equals(const char* other, bool ignore_case) const +{ + const char* a = s_ptr(); const char* b = other; + + if (ignore_case) + { + while (blah_to_lower(*a) == blah_to_lower(*b) && *a != '\0') { a++; b++; } + return blah_to_lower(*a) == blah_to_lower(*b); + } + else + { + while (*a == *b && *a != '\0') { a++; b++; } + return *a == *b; + } +} + +namespace +{ + u32 utf8_character_at(const char* str) + { + u32 charcode = 0; + + int t = (unsigned char)(*(str++)); + if (t < 128) + return t; + + int high_bit_mask = (1 << 6) - 1; + int high_bit_shift = 0; + int total_bits = 0; + int other_bits = 6; + + while ((t & 0xC0) == 0xC0) + { + t <<= 1; + t &= 0xff; + total_bits += 6; + high_bit_mask >>= 1; + high_bit_shift++; + charcode <<= other_bits; + charcode |= ((unsigned char)(*(str++))) & ((1 << other_bits) - 1); + } + charcode |= ((t >> high_bit_shift) & high_bit_mask) << total_bits; + + return charcode; + } + + u32 utf8_character_size(const char* str) + { + char c = *str; + if (c == '\0') + return 0; + if ((c & 0xFE) == 0xFC) + return 6; + if ((c & 0xFC) == 0xF8) + return 5; + if ((c & 0xF8) == 0xF0) + return 4; + if ((c & 0xF0) == 0xE0) + return 3; + if ((c & 0xE0) == 0xC0) + return 2; + return 1; + } +} + +Utf8::Utf8(const char* cstr) + : str(cstr) +{ + character = utf8_character_at(str); + character_size = utf8_character_size(str); +} + +bool Utf8::next() +{ + str += character_size; + character = utf8_character_at(str); + character_size = utf8_character_size(str); + return character_size > 0; +} \ No newline at end of file diff --git a/src/drawing/subtexture.cpp b/src/blah_subtexture.cpp similarity index 96% rename from src/drawing/subtexture.cpp rename to src/blah_subtexture.cpp index 77a9dc5..23e6d07 100644 --- a/src/drawing/subtexture.cpp +++ b/src/blah_subtexture.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include using namespace Blah; diff --git a/src/time.cpp b/src/blah_time.cpp similarity index 96% rename from src/time.cpp rename to src/blah_time.cpp index 417c044..918676c 100644 --- a/src/time.cpp +++ b/src/blah_time.cpp @@ -1,5 +1,5 @@ -#include -#include "internal/internal.h" +#include +#include "internal/blah_internal.h" using namespace Blah; diff --git a/src/containers/str.cpp b/src/containers/str.cpp deleted file mode 100644 index d4421a7..0000000 --- a/src/containers/str.cpp +++ /dev/null @@ -1,492 +0,0 @@ -#include -#include // for strcpy etc -#include // for format methods -#include // for sprintf -#include // toupper - -using namespace Blah; - -char Str::empty_buffer[1] = { '\0' }; - -bool Str::operator==(const Str& rhs) const -{ - return strcmp(cstr(), rhs.cstr()) == 0; -} - -bool Str::operator!=(const Str& rhs) const -{ - return strcmp(cstr(), rhs.cstr()) != 0; -} - -bool Str::operator==(const char* rhs) const -{ - return strcmp(cstr(), rhs) == 0; -} - -bool Str::operator!=(const char* rhs) const -{ - return strcmp(cstr(), rhs) != 0; -} - -void Str::reserve(int size) -{ - int buffer_length = size + 1; - if (buffer_length > m_capacity) - { - if (m_capacity <= 0) - m_capacity = 16; - - while (m_capacity < buffer_length) - m_capacity *= 2; - - // expand from local buffer - if (m_buffer == nullptr) - { - char* local = data(); - m_buffer = new char[m_capacity]; - memcpy(m_buffer, local, m_local_size); - m_buffer[m_local_size] = '\0'; - } - // expand from empty buffer - else if (m_buffer == empty_buffer) - { - m_buffer = new char[m_capacity]; - m_buffer[0] = '\0'; - } - // expand from existing heap buffer - else - { - char* new_buffer = new char[m_capacity]; - memcpy(new_buffer, m_buffer, m_length); - new_buffer[m_length] = '\0'; - delete[] m_buffer; - m_buffer = new_buffer; - } - } -} - -void Str::set_length(int len) -{ - reserve(len); - data()[len] = '\0'; - m_length = len; -} - -u32 Str::utf8_at(int index) const -{ - u32 charcode = 0; - - int t = (unsigned char)(this->operator[](index++)); - if (t < 128) - return t; - - int high_bit_mask = (1 << 6) - 1; - int high_bit_shift = 0; - int total_bits = 0; - int other_bits = 6; - - while ((t & 0xC0) == 0xC0) - { - t <<= 1; - t &= 0xff; - total_bits += 6; - high_bit_mask >>= 1; - high_bit_shift++; - charcode <<= other_bits; - charcode |= ((unsigned char)(this->operator[](index++))) & ((1 << other_bits) - 1); - } - charcode |= ((t >> high_bit_shift) & high_bit_mask) << total_bits; - - return charcode; -} - -int Str::utf8_length(int index) const -{ - auto c = this->operator[](index); - if ((c & 0xFE) == 0xFC) - return 6; - if ((c & 0xFC) == 0xF8) - return 5; - if ((c & 0xF8) == 0xF0) - return 4; - else if ((c & 0xF0) == 0xE0) - return 3; - else if ((c & 0xE0) == 0xC0) - return 2; - return 1; -} - -Str& Str::append(char c) -{ - reserve(m_length + 1); - data()[m_length++] = c; - data()[m_length] = '\0'; - return *this; -} - -Str& Str::append(u32 c) -{ - // one octet - if (c < 0x80) - { - append((char)c); - } - // two octets - else if (c < 0x800) - { - append((char)((c >> 6) | 0xc0)); - append((char)((c & 0x3f) | 0x80)); - } - // three octets - else if (c < 0x10000) - { - append((char)((c >> 12) | 0xe0)); - append((char)(((c >> 6) & 0x3f) | 0x80)); - append((char)((c & 0x3f) | 0x80)); - } - // four octets - else - { - append((char)((c >> 18) | 0xf0)); - append((char)(((c >> 12) & 0x3f) | 0x80)); - append((char)(((c >> 6) & 0x3f) | 0x80)); - append((char)((c & 0x3f) | 0x80)); - } - - return *this; -} - -Str& Str::append(const char* start, const char* end) -{ - if (end == nullptr) - end = start + strlen(start); - - int add = (int)(end - start); - if (add <= 0) - return *this; - - reserve(m_length + add); - memcpy(data() + m_length, start, add); - m_length += add; - data()[m_length] = '\0'; - - return *this; -} - -Str& Str::append(const Str& str, int start, int end) -{ - if (end < 0) end = str.m_length; - if (end > str.m_length) end = str.m_length; - if (start < 0) start = 0; - if (start > end) start = end; - - return append(str.begin() + start, str.begin() + end); -} - -Str& Str::append_fmt(const char* fmt, ...) -{ - int add, diff; - - // determine arg m_length - va_list args; - va_start(args, fmt); - add = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - // reserve - reserve(m_length + add); - diff = m_capacity - m_length; - if (diff <= 0) diff = 0; - - // print out - va_start(args, fmt); - vsnprintf(data() + m_length, (size_t)diff, fmt, args); - va_end(args); - - // increment size - m_length += add; - data()[m_length] = '\0'; - - return *this; -} - -Str& Str::append_utf16(const u16* start, const u16* end, bool swap_endian) -{ - // converts utf16 into utf8 - // more info: https://en.wikipedia.org/wiki/UTF-16#Description - - const u16 surrogate_min = 0xd800u; - const u16 surrogate_max = 0xdbffu; - - while ((end == nullptr && *start != 0) || (end != nullptr && start != end)) - { - u16 next = (*start++); - if (swap_endian) - next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8)); - - u32 cp = 0xffff & next; - - if ((cp >= surrogate_min && cp <= surrogate_max)) - { - next = (*start++); - if (swap_endian) - next = ((next & 0xff) << 8 | ((next & 0xff00) >> 8)); - - u32 trail = 0xffff & next; - cp = (cp << 10) + trail + 0x10000u - (surrogate_min << 10) - 0xdc00u; - } - - append(cp); - } - - return *this; -} - -Str& Str::trim() -{ - if (m_length > 0) - { - const char* s = begin(); - const char* e = end() - 1; - - while (isspace(*s) && s != e) - s++; - while (isspace(*e) && s != e) - e--; - - set(s, e + 1); - } - - return *this; -} - -bool Str::starts_with(const char* str, bool ignoreCase) const -{ - if (str == nullptr) - return m_length == 0; - - int len = (int)strlen(str); - if (len > m_length) - return false; - - const char* a = data(); - const char* b = str; - - if (ignoreCase) - { - for (int n = 0; n < len; n++) - if (tolower(a[n]) != tolower(b[n])) - return false; - } - else - { - for (int n = 0; n < len; n++) - if (a[n] != b[n]) - return false; - } - - return true; -} - -bool Str::contains(const char* str, bool ignoreCase) const -{ - int len = (int)strlen(str); - if (len > m_length || len <= 0) - return false; - - const char* a = data(); - const char* b = str; - - for (int start = 0; start < m_length - len + 1; start++) - { - bool match = true; - - if (ignoreCase) - { - for (int n = 0; n < len && match; n++) - if (tolower(a[start + n]) != tolower(b[n])) - match = false; - } - else - { - for (int n = 0; n < len && match; n++) - if (a[start + n] != b[n]) - match = false; - } - - if (match) - return true; - } - - return false; -} - -bool Str::ends_with(const char* str, bool ignoreCase) const -{ - if (str == nullptr) - return m_length == 0; - - int len = (int)strlen(str); - if (len > m_length || len <= 0) - return false; - - const char* a = data(); - const char* b = str; - - if (ignoreCase) - { - for (int n = m_length - len, i = 0; n < m_length; n++, i++) - if (tolower(a[n]) != tolower(b[i])) - return false; - } - else - { - for (int n = m_length - len, i = 0; n < m_length; n++, i++) - if (a[n] != b[i]) - return false; - } - - return true; -} - -int Str::first_index_of(char ch) const -{ - const char* ptr = data(); - for (int n = 0; n < m_length; n++) - if (ptr[n] == ch) - return n; - return -1; -} - -int Str::last_index_of(char ch) const -{ - const char* ptr = data(); - for (int n = m_length - 1; n >= 0; n--) - if (ptr[n] == ch) - return n; - return -1; -} - -String Str::substr(int start) const -{ - if (start < 0) start = 0; - if (start > m_length) start = m_length; - - return String(data() + start); -} - -String Str::substr(int start, int end) const -{ - if (start < 0) start = 0; - if (start > m_length) start = m_length; - if (end < 0) end = m_length + end; - if (end < start) end = start; - if (end > m_length) end = m_length; - - return Str(data() + start, data() + end); -} - -Vector Str::split(char ch) const -{ - Vector result; - - const char* ptr = data(); - int last = 0; - int index = 1; - - while (index < m_length) - { - if (ptr[index] == ch) - { - result.push_back(substr(last, index)); - last = index + 1; - } - index++; - } - - if (last < index) - result.push_back(substr(last, index)); - - return result; -} - -Str& Str::replace(const Str& os, const Str& ns) -{ - for (int i = 0; i < m_length - os.m_length + 1; i++) - { - if (strncmp(data() + i, os.data(), os.m_length) == 0) - { - if (ns.m_length > os.m_length) - reserve(ns.m_length - os.m_length); - - memmove(data() + i + ns.m_length, data() + i + os.m_length, m_length - i - os.m_length); - memcpy(data() + i, ns.cstr(), ns.m_length); - set_length(m_length + ns.m_length - os.m_length); - i += os.m_length - 1; - } - } - - return *this; -} - -Str& Str::replace(char c, char r) -{ - char* ptr = data(); - for (int n = 0; n < m_length; n++) - if (ptr[n] == c) - ptr[n] = r; - return *this; -} - -void Str::clear() -{ - if (m_capacity > 0) - data()[0] = '\0'; - m_length = 0; -} - -void Str::dispose() -{ - if (m_buffer != nullptr && m_buffer != empty_buffer) - delete[] m_buffer; - - if (m_local_size > 0) - { - m_buffer = nullptr; - m_capacity = m_local_size; - data()[0] = '\0'; - } - else - { - m_buffer = empty_buffer; - m_capacity = 0; - } - - m_length = 0; -} - -void Str::set(const char* start, const char* end) -{ - // find the end - if (end == nullptr) - end = start + strlen(start); - - // make sure it actually contains characters - int len = (int)(end - start); - if (len <= 0) - { - clear(); - } - else - { - m_length = len; - - // reserve - reserve(m_length); - - // copy the data over - char* ptr = data(); - memcpy(ptr, start, m_length); - ptr[m_length] = '\0'; - } -} \ No newline at end of file diff --git a/src/internal/internal.h b/src/internal/blah_internal.h similarity index 92% rename from src/internal/internal.h rename to src/internal/blah_internal.h index fb3e0b5..a856014 100644 --- a/src/internal/internal.h +++ b/src/internal/blah_internal.h @@ -1,6 +1,6 @@ #pragma once -#include "renderer.h" -#include "platform.h" +#include "blah_renderer.h" +#include "blah_platform.h" #define BLAH_ASSERT_RENDERER() BLAH_ASSERT(App::Internal::renderer, "Renderer has not been created") #define BLAH_ASSERT_PLATFORM() BLAH_ASSERT(App::Internal::platform, "Platform has not been created") diff --git a/src/internal/platform.h b/src/internal/blah_platform.h similarity index 97% rename from src/internal/platform.h rename to src/internal/blah_platform.h index 2a25250..e57279c 100644 --- a/src/internal/platform.h +++ b/src/internal/blah_platform.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include -#include +#include +#include +#include +#include namespace Blah { diff --git a/src/internal/platform_sdl2.cpp b/src/internal/blah_platform_sdl2.cpp similarity index 98% rename from src/internal/platform_sdl2.cpp rename to src/internal/blah_platform_sdl2.cpp index d2f3b16..440e354 100644 --- a/src/internal/platform_sdl2.cpp +++ b/src/internal/blah_platform_sdl2.cpp @@ -1,13 +1,13 @@ #ifdef BLAH_PLATFORM_SDL2 -#include "platform.h" -#include "renderer.h" -#include "internal.h" -#include -#include -#include -#include -#include +#include "blah_platform.h" +#include "blah_renderer.h" +#include "blah_internal.h" +#include +#include +#include +#include +#include #include diff --git a/src/internal/platform_win32.cpp b/src/internal/blah_platform_win32.cpp similarity index 99% rename from src/internal/platform_win32.cpp rename to src/internal/blah_platform_win32.cpp index 9f8ead6..2408578 100644 --- a/src/internal/platform_win32.cpp +++ b/src/internal/blah_platform_win32.cpp @@ -3,13 +3,13 @@ // Note: // This is unfinished! It is missing Controller Support! -#include "platform.h" -#include "internal.h" -#include -#include -#include -#include -#include +#include "blah_platform.h" +#include "blah_internal.h" +#include +#include +#include +#include +#include #define WIN32_LEAN_AND_MEAN #include diff --git a/src/internal/renderer.h b/src/internal/blah_renderer.h similarity index 96% rename from src/internal/renderer.h rename to src/internal/blah_renderer.h index 77df783..84e5f92 100644 --- a/src/internal/renderer.h +++ b/src/internal/blah_renderer.h @@ -1,7 +1,7 @@ #pragma once -#include -#include -#include +#include +#include +#include namespace Blah { diff --git a/src/internal/renderer_d3d11.cpp b/src/internal/blah_renderer_d3d11.cpp similarity index 99% rename from src/internal/renderer_d3d11.cpp rename to src/internal/blah_renderer_d3d11.cpp index ac1f215..9521ffe 100644 --- a/src/internal/renderer_d3d11.cpp +++ b/src/internal/blah_renderer_d3d11.cpp @@ -3,10 +3,10 @@ // TODO: // Note the D3D11 Implementation is still a work-in-progress -#include "renderer.h" -#include "internal.h" -#include "platform.h" -#include +#include "blah_renderer.h" +#include "blah_internal.h" +#include "blah_platform.h" +#include #include #include #include diff --git a/src/internal/renderer_opengl.cpp b/src/internal/blah_renderer_opengl.cpp similarity index 99% rename from src/internal/renderer_opengl.cpp rename to src/internal/blah_renderer_opengl.cpp index 71559a7..f2966c3 100644 --- a/src/internal/renderer_opengl.cpp +++ b/src/internal/blah_renderer_opengl.cpp @@ -1,9 +1,9 @@ #ifdef BLAH_RENDERER_OPENGL -#include "renderer.h" -#include "internal.h" -#include "platform.h" -#include +#include "blah_renderer.h" +#include "blah_internal.h" +#include "blah_platform.h" +#include #include #include #include @@ -942,7 +942,7 @@ namespace Blah m_uniforms.push_back(tex_uniform); UniformInfo sampler_uniform; - sampler_uniform.name = String(name).append("_sampler"); + sampler_uniform.name = String(name) + "_sampler"; sampler_uniform.register_index = sampler_uniforms; sampler_uniform.buffer_index = 0; sampler_uniform.array_length = size;