Skip to content

Commit

Permalink
fix next_power_of_two and improve generic_string (#220)
Browse files Browse the repository at this point in the history
* fix next_power_of_two function

* generic_string: add starts_with and ends_with functions

* generic_string: fix starts_with and ends_with functions

handle empty generic_string correctly
lessen code

* generic_string: fix implicit integer conversion

* generic_string: handle empty strings correctly

---------

Co-authored-by: VirtualDeep <75492585+VirtualDeep@users.noreply.github.com>
  • Loading branch information
freshFruict and freshFruict authored May 26, 2024
1 parent 917f589 commit 8255bcd
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 3 deletions.
56 changes: 56 additions & 0 deletions include/cista/containers/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,62 @@ struct generic_string {
return *this;
}

constexpr bool starts_with(generic_string const& s) const noexcept {
return starts_with(s.data(), static_cast<msize_t>(s.size()));
}
constexpr bool starts_with(std::string_view const& sv) const noexcept {
return starts_with(sv.data(), static_cast<msize_t>(sv.size()));
}
constexpr bool starts_with(char const* s) const noexcept {
return starts_with(s, mstrlen(s));
}
constexpr bool starts_with(char const* s, msize_t size_s) const noexcept {
if (size_s > size()) {
return false;
}
if (size_s == 0) {
return true;
}
if (empty()) {
return false;
}
return !std::memcmp(s, data(), size_s);
}
constexpr bool starts_with(char ch) const noexcept {
if (empty()) {
return false;
}
return data()[0] == ch;
}

constexpr bool ends_with(generic_string const& s) const noexcept {
return ends_with(s.data(), static_cast<msize_t>(s.size()));
}
constexpr bool ends_with(std::string_view const& sv) const noexcept {
return ends_with(sv.data(), static_cast<msize_t>(sv.size()));
}
constexpr bool ends_with(char const* s) const noexcept {
return ends_with(s, mstrlen(s));
}
constexpr bool ends_with(char const* s, msize_t size_s) const noexcept {
if (size_s > size()) {
return false;
}
if (size_s == 0) {
return true;
}
if (empty()) {
return false;
}
return !std::memcmp(s, data() + size() - size_s, size_s);
}
constexpr bool ends_with(char ch) const noexcept {
if (size() == 0) {
return false;
}
return data()[size() - 1] == ch;
}

struct heap {
bool is_short_{false};
bool self_allocated_{false};
Expand Down
10 changes: 7 additions & 3 deletions include/cista/next_power_of_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ constexpr TemplateSizeType next_power_of_two(TemplateSizeType n) noexcept {
n |= n >> 1U;
n |= n >> 2U;
n |= n >> 4U;
n |= n >> 8U;
n |= n >> 16U;
if constexpr (sizeof(TemplateSizeType) > 32U) {
if constexpr (sizeof(TemplateSizeType) > 1U) {
n |= n >> 8U;
}
if constexpr (sizeof(TemplateSizeType) > 2U) {
n |= n >> 16U;
}
if constexpr (sizeof(TemplateSizeType) > 4U) {
n |= n >> 32U;
}
++n;
Expand Down
76 changes: 76 additions & 0 deletions test/string_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,79 @@ TEST_CASE("string hash") {
auto h = cista::hash(str, cista::BASE_HASH);
CHECK(cista::BASE_HASH == h);
}

TEST_CASE("string starts_with") {
string s = "abacaba";

CHECK(s.starts_with("abac") == true);
CHECK(s.starts_with("abacaba") == true);
CHECK(s.starts_with("abacaba_") == false);
CHECK(s.starts_with("a") == true);
CHECK(s.starts_with("") == true);
CHECK(s.starts_with("abad") == false);

CHECK(s.starts_with(string{"abac"}) == true);
CHECK(s.starts_with(string{"abacaba"}) == true);
CHECK(s.starts_with(string{"abacaba_"}) == false);
CHECK(s.starts_with(string{"a"}) == true);
CHECK(s.starts_with(string{""}) == true);
CHECK(s.starts_with(string{"abad"}) == false);

CHECK(s.starts_with(std::string{"abac"}) == true);
CHECK(s.starts_with(std::string{"abacaba"}) == true);
CHECK(s.starts_with(std::string{"abacaba_"}) == false);
CHECK(s.starts_with(std::string{"a"}) == true);
CHECK(s.starts_with(std::string{""}) == true);
CHECK(s.starts_with(std::string{"\0", 1}) == false);
CHECK(s.starts_with(std::string{"abad"}) == false);

CHECK(s.starts_with(std::string_view{"abac"}) == true);
CHECK(s.starts_with(std::string_view{"abacaba"}) == true);
CHECK(s.starts_with(std::string_view{"abacaba_"}) == false);
CHECK(s.starts_with(std::string_view{"a"}) == true);
CHECK(s.starts_with(std::string_view{""}) == true);
CHECK(s.starts_with(std::string_view{"\0", 1}) == false);
CHECK(s.starts_with(std::string_view{"abad"}) == false);

CHECK(s.starts_with('a') == true);
CHECK(s.starts_with('b') == false);
CHECK(s.starts_with('\0') == false);
}

TEST_CASE("string ends_with") {
string s = "abacaba";

CHECK(s.ends_with("caba") == true);
CHECK(s.ends_with("abacaba") == true);
CHECK(s.ends_with("abacaba_") == false);
CHECK(s.ends_with("a") == true);
CHECK(s.ends_with("") == true);
CHECK(s.ends_with("daba") == false);

CHECK(s.ends_with(string{"caba"}) == true);
CHECK(s.ends_with(string{"abacaba"}) == true);
CHECK(s.ends_with(string{"abacaba_"}) == false);
CHECK(s.ends_with(string{"a"}) == true);
CHECK(s.ends_with(string{""}) == true);
CHECK(s.ends_with(string{"daba"}) == false);

CHECK(s.ends_with(std::string{"caba"}) == true);
CHECK(s.ends_with(std::string{"abacaba"}) == true);
CHECK(s.ends_with(std::string{"abacaba_"}) == false);
CHECK(s.ends_with(std::string{"a"}) == true);
CHECK(s.ends_with(std::string{""}) == true);
CHECK(s.ends_with(std::string{"\0", 1}) == false);
CHECK(s.ends_with(std::string{"daba"}) == false);

CHECK(s.ends_with(std::string_view{"caba"}) == true);
CHECK(s.ends_with(std::string_view{"abacaba"}) == true);
CHECK(s.ends_with(std::string_view{"abacaba_"}) == false);
CHECK(s.ends_with(std::string_view{"a"}) == true);
CHECK(s.ends_with(std::string_view{""}) == true);
CHECK(s.ends_with(std::string_view{"\0", 1}) == false);
CHECK(s.ends_with(std::string_view{"daba"}) == false);

CHECK(s.ends_with('a') == true);
CHECK(s.ends_with('b') == false);
CHECK(s.ends_with('\0') == false);
}

0 comments on commit 8255bcd

Please sign in to comment.