From a2e80952c88efeaf709f9034710d9f0a3cfecd9b Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Thu, 2 Nov 2023 20:23:28 -0700 Subject: [PATCH] [Glacier] Add a StringView class and StrSplit method. --- lib/glacier/CMakeLists.txt | 5 +- lib/glacier/container/vector.h | 14 ++++-- lib/glacier/string/str_split.cpp | 17 +++++++ lib/glacier/string/str_split.h | 11 +++++ lib/glacier/string/string.cpp | 4 ++ lib/glacier/string/string.h | 4 ++ lib/glacier/string/string_view.cpp | 73 ++++++++++++++++++++++++++++++ lib/glacier/string/string_view.h | 35 ++++++++++++++ 8 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 lib/glacier/string/str_split.cpp create mode 100644 lib/glacier/string/str_split.h create mode 100644 lib/glacier/string/string_view.cpp create mode 100644 lib/glacier/string/string_view.h diff --git a/lib/glacier/CMakeLists.txt b/lib/glacier/CMakeLists.txt index 895b6de..253a089 100644 --- a/lib/glacier/CMakeLists.txt +++ b/lib/glacier/CMakeLists.txt @@ -1,5 +1,8 @@ add_library(glacier STATIC - string/string.cpp) + string/string.cpp + string/string_view.cpp + string/str_split.cpp + ) target_include_directories(glacier PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/lib/glacier/container/vector.h b/lib/glacier/container/vector.h index 9f2d343..d212ee6 100644 --- a/lib/glacier/container/vector.h +++ b/lib/glacier/container/vector.h @@ -11,10 +11,18 @@ class Vector { Vector() : data_(nullptr), size_(0), capacity_(0) {} Vector(const Vector&) = delete; - // TODO: Implement Move - Vector(Vector&&) = delete; + Vector(Vector&& other) + : data_(other.data_), size_(other.size_), capacity_(other.capacity_) { + other.data_ = nullptr; + other.size_ = 0; + other.capacity_ = 0; + } - ~Vector() { delete[] data_; } + ~Vector() { + if (data_) { + delete[] data_; + } + } // FIXME: Handle downsizing. void Resize(uint64_t capacity); diff --git a/lib/glacier/string/str_split.cpp b/lib/glacier/string/str_split.cpp new file mode 100644 index 0000000..d94be63 --- /dev/null +++ b/lib/glacier/string/str_split.cpp @@ -0,0 +1,17 @@ +#include "glacier/string/str_split.h" + +namespace glcr { + +Vector StrSplit(const StringView& str, char delimiter) { + Vector strings; + uint64_t cur_pos = 0; + uint64_t next_pos = 0; + while ((next_pos = str.find(delimiter, cur_pos)) != str.npos) { + strings.PushBack(str.substr(cur_pos, next_pos - cur_pos)); + cur_pos = next_pos + 1; + } + strings.PushBack(str.substr(cur_pos, str.size() - cur_pos)); + return strings; +} + +} // namespace glcr diff --git a/lib/glacier/string/str_split.h b/lib/glacier/string/str_split.h new file mode 100644 index 0000000..e9e41c8 --- /dev/null +++ b/lib/glacier/string/str_split.h @@ -0,0 +1,11 @@ +#pragma once + +#include "glacier/container/vector.h" +#include "glacier/string/string_view.h" + +namespace glcr { + +// TODO: Add a split that uses a StringView as a delimeter. +Vector StrSplit(const StringView& str, char delimeter); + +} // namespace glcr diff --git a/lib/glacier/string/string.cpp b/lib/glacier/string/string.cpp index 744f2be..c92aa9d 100644 --- a/lib/glacier/string/string.cpp +++ b/lib/glacier/string/string.cpp @@ -26,6 +26,8 @@ String::String(const char* cstr, uint64_t str_len) : length_(str_len) { cstr_[length_] = '\0'; } +String::String(StringView str) : String(str.data(), str.size()) {} + bool String::operator==(const String& other) { if (other.length_ != length_) { return false; @@ -43,4 +45,6 @@ char String::operator[](uint64_t offset) const { return cstr_[offset]; } +String::operator StringView() const { return StringView(cstr_, length_); } + } // namespace glcr diff --git a/lib/glacier/string/string.h b/lib/glacier/string/string.h index f411522..e220395 100644 --- a/lib/glacier/string/string.h +++ b/lib/glacier/string/string.h @@ -2,6 +2,8 @@ #include +#include "glacier/string/string_view.h" + namespace glcr { class String { @@ -9,6 +11,7 @@ class String { String(); String(const char* cstr); String(const char* cstr, uint64_t str_len); + String(StringView str); const char* cstr() const { return cstr_; } uint64_t length() const { return length_; } @@ -16,6 +19,7 @@ class String { bool operator==(const String& str); char operator[](uint64_t offset) const; + operator StringView() const; private: char* cstr_; diff --git a/lib/glacier/string/string_view.cpp b/lib/glacier/string/string_view.cpp new file mode 100644 index 0000000..0295fd0 --- /dev/null +++ b/lib/glacier/string/string_view.cpp @@ -0,0 +1,73 @@ +#include "glacier/string/string_view.h" + +namespace glcr { +namespace { + +uint64_t cstrlen(const char* ptr) { + uint64_t len = 0; + while (ptr[len] != '\0') { + len++; + } + return len; +} + +} // namespace + +StringView::StringView() {} +StringView::StringView(const char* str) : value_(str), size_(cstrlen(str)) {} +StringView::StringView(const char* str, uint64_t count) + : value_(str), size_(count) {} + +const char* StringView::data() const { return value_; } + +uint64_t StringView::size() const { return size_; } + +bool StringView::empty() const { return size_ == 0; } + +char StringView::at(uint64_t pos) const { return value_[pos]; } + +uint64_t StringView::find(char c, uint64_t pos) const { + for (uint64_t i = pos; i < size_; i++) { + if (value_[i] == c) { + return i; + } + } + return npos; +} + +StringView StringView::substr(uint64_t start, uint64_t count) const { + // FIXME: Report an error here maybe. + if (start >= size_) { + return StringView{}; + } + if (start + count > size_) { + count = size_ - start; + } + return StringView(value_ + start, count); +} + +bool operator==(const StringView& str1, const StringView& str2) { + if (str1.empty() && str2.empty()) { + return true; + } + if (str1.size() != str2.size()) { + return false; + } + if (str1.data() == str2.data()) { + // Short circuit if they are the same exact string. + return true; + } + for (uint64_t i = 0; i < str1.size(); i++) { + if (str1.at(i) != str2.at(i)) { + return false; + } + } + + return true; +} + +bool operator!=(const StringView& str1, const StringView& str2) { + return !(str1 == str2); +} + +} // namespace glcr diff --git a/lib/glacier/string/string_view.h b/lib/glacier/string/string_view.h new file mode 100644 index 0000000..7c51f07 --- /dev/null +++ b/lib/glacier/string/string_view.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace glcr { + +class StringView { + public: + static const uint64_t npos = -1; + + StringView(); + StringView(const StringView& other) = default; + StringView(const char* str); + StringView(const char* str, uint64_t count); + + const char* data() const; + uint64_t size() const; + + bool empty() const; + + char at(uint64_t pos) const; + + uint64_t find(char c, uint64_t pos = 0) const; + + StringView substr(uint64_t start, uint64_t count) const; + + private: + const char* value_ = nullptr; + uint64_t size_ = 0; +}; + +bool operator==(const StringView& str1, const StringView& str2); +bool operator!=(const StringView& str1, const StringView& str2); + +} // namespace glcr