aboutsummaryrefslogtreecommitdiff
path: root/source/10-common/Utils.hpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2023-09-20 23:58:58 -0700
committerrtk0c <[email protected]>2023-09-20 23:58:58 -0700
commitf138311d2d2e0cc9ba0496d523bb46f2c1c9fb73 (patch)
treef96100a813a4ffb28dcd074455d3a2f8ee426430 /source/10-common/Utils.hpp
Copy from the PlasticSCM repo, replace vendored glm wtih conan
Diffstat (limited to 'source/10-common/Utils.hpp')
-rw-r--r--source/10-common/Utils.hpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/source/10-common/Utils.hpp b/source/10-common/Utils.hpp
new file mode 100644
index 0000000..668261b
--- /dev/null
+++ b/source/10-common/Utils.hpp
@@ -0,0 +1,77 @@
+#pragma once
+
+#include <robin_hood.h>
+#include <cstdio>
+#include <cstring>
+#include <filesystem>
+#include <glm/glm.hpp>
+#include <string>
+#include <string_view>
+
+namespace Utils {
+
+enum IoMode {
+ Read,
+ WriteTruncate,
+ WriteAppend,
+};
+
+FILE* OpenCstdioFile(const std::filesystem::path& path, IoMode mode, bool binary = false);
+FILE* OpenCstdioFile(const char* path, IoMode mode, bool binary = false);
+
+/// Retrieve a whole line (marked by `\n` or EOF) into the buffer. If the line ends with EOF, two things happen:
+/// 1. a `\n` character is appended to the line content, emulating as-if the line ended with `\n`.
+/// 2. `false` is returned
+/// Otherwise, `true` is returned.
+///
+/// Empty lines are not skipped at all, including the very last empty line if it exists.
+bool ReadCstdioLine(FILE* file, std::string& buffer);
+/// Same as the other overload, except working with a fixed-size buffer.
+/// NOTE: this also gives the length of the line compared to `std::fgets`.
+/// `std::fgets` requires us to run `std::strlen` on the output again to find the length
+bool ReadCstdioLine(FILE* file, char* buffer, size_t bufferSize, size_t* outLineLength = nullptr);
+
+std::string ReadFileAsString(const std::filesystem::path& path);
+
+constexpr float Abs(float v) noexcept {
+ return v < 0.0f ? -v : v;
+}
+
+bool InRangeInclusive(int n, int lower, int upper);
+bool LineContains(glm::ivec2 p1, glm::ivec2 p2, glm::ivec2 candidate);
+
+bool IsColinear(glm::ivec2 p1, glm::ivec2 p2);
+
+template <typename T>
+void HashCombine(std::size_t& seed, const T& v) {
+ seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
+std::string MakeRandomNumberedName(const char* tag);
+
+} // namespace Utils
+
+struct StringHash {
+ using is_transparent = void;
+
+ std::size_t operator()(const std::string& key) const { return robin_hood::hash_bytes(key.c_str(), key.size()); }
+ std::size_t operator()(std::string_view key) const { return robin_hood::hash_bytes(key.data(), key.size()); }
+ std::size_t operator()(const char* key) const { return robin_hood::hash_bytes(key, std::strlen(key)); }
+};
+
+struct StringEqual {
+ using is_transparent = int;
+
+ bool operator()(std::string_view lhs, const std::string& rhs) const {
+ const std::string_view view = rhs;
+ return lhs == view;
+ }
+
+ bool operator()(const char* lhs, const std::string& rhs) const {
+ return std::strcmp(lhs, rhs.c_str()) == 0;
+ }
+
+ bool operator()(const std::string& lhs, const std::string& rhs) const {
+ return lhs == rhs;
+ }
+};