Skip to content

Commit c280645

Browse files
authored
Merge pull request #198 from ashvardanian/main-dev
Equality Checks & C++ Function Objects
2 parents 30d3e21 + 592034c commit c280645

File tree

5 files changed

+78
-13
lines changed

5 files changed

+78
-13
lines changed

.github/workflows/prerelease.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
fetch-depth: 0
2929
persist-credentials: false
3030
- name: Run TinySemVer
31-
uses: ashvardanian/tinysemver@v2.0.7
31+
uses: ashvardanian/tinysemver@v2.1.1
3232
with:
3333
verbose: "true"
3434
version-file: "VERSION"
@@ -465,7 +465,7 @@ jobs:
465465
if: matrix.os == 'ubuntu-24.04'
466466
uses: docker/setup-qemu-action@v3
467467
- name: Install cibuildwheel
468-
run: python -m pip install cibuildwheel
468+
run: python -m pip install cibuildwheel==2.21.3
469469
- name: Build wheels
470470
run: cibuildwheel --output-dir wheelhouse
471471
env:

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
fetch-depth: 0
2828
persist-credentials: false
2929
- name: Run TinySemVer
30-
uses: ashvardanian/tinysemver@v2.0.7
30+
uses: ashvardanian/tinysemver@v2.1.1
3131
with:
3232
verbose: "true"
3333
version-file: "VERSION"
@@ -93,7 +93,7 @@ jobs:
9393
if: matrix.os == 'ubuntu-24.04' # We only need QEMU for Linux builds
9494
uses: docker/setup-qemu-action@v3
9595
- name: Install cibuildwheel
96-
run: python -m pip install cibuildwheel
96+
run: python -m pip install cibuildwheel==2.21.3
9797
- name: Build wheels
9898
run: cibuildwheel --output-dir wheelhouse
9999
env:

include/stringzilla/stringzilla.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5818,7 +5818,7 @@ SZ_PUBLIC sz_bool_t sz_equal_neon(sz_cptr_t a, sz_cptr_t b, sz_size_t length) {
58185818
a_vec.u8x16 = vld1q_u8((sz_u8_t const *)a);
58195819
b_vec.u8x16 = vld1q_u8((sz_u8_t const *)b);
58205820
uint8x16_t cmp = vceqq_u8(a_vec.u8x16, b_vec.u8x16);
5821-
if (vmaxvq_u8(cmp) != 255) { return sz_false_k; } // Check if all bytes match
5821+
if (vminvq_u8(cmp) != 255) { return sz_false_k; } // Check if all bytes match
58225822
}
58235823

58245824
// Handle remaining bytes

include/stringzilla/stringzilla.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3681,6 +3681,41 @@ bool basic_string<char_type_, allocator_>::try_preparing_replacement(size_type o
36813681
}
36823682
}
36833683

3684+
/**
3685+
* @brief Helper function-like object to order string-view convertible objects with StringZilla.
3686+
* @see Similar to `std::less<std::string_view>`: https://en.cppreference.com/w/cpp/utility/functional/less
3687+
*
3688+
* Unlike the STL analog, doesn't require C++14 or including the heavy `<functional>` header.
3689+
* Can be used to combine STL classes with StringZilla logic, like: `std::map<std::string, int, sz::string_view_less>`.
3690+
*/
3691+
struct string_view_less {
3692+
bool operator()(string_view a, string_view b) const noexcept { return a < b; }
3693+
};
3694+
3695+
/**
3696+
* @brief Helper function-like object to check equality between string-view convertible objects with StringZilla.
3697+
* @see Similar to `std::equal_to<std::string_view>`: https://en.cppreference.com/w/cpp/utility/functional/equal_to
3698+
*
3699+
* Unlike the STL analog, doesn't require C++14 or including the heavy `<functional>` header.
3700+
* Can be used to combine STL classes with StringZilla logic, like:
3701+
* `std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to>`.
3702+
*/
3703+
struct string_view_equal_to {
3704+
bool operator()(string_view a, string_view b) const noexcept { return a == b; }
3705+
};
3706+
3707+
/**
3708+
* @brief Helper function-like object to hash string-view convertible objects with StringZilla.
3709+
* @see Similar to `std::hash<std::string_view>`: https://en.cppreference.com/w/cpp/utility/functional/hash
3710+
*
3711+
* Unlike the STL analog, doesn't require C++14 or including the heavy `<functional>` header.
3712+
* Can be used to combine STL classes with StringZilla logic, like:
3713+
* `std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to>`.
3714+
*/
3715+
struct string_view_hash {
3716+
std::size_t operator()(string_view str) const noexcept { return str.hash(); }
3717+
};
3718+
36843719
/** @brief SFINAE-type used to infer the resulting type of concatenating multiple string together. */
36853720
template <typename... args_types>
36863721
struct concatenation_result {};

scripts/test.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@
2424
#include <sanitizer/asan_interface.h> // ASAN
2525
#endif
2626

27-
#include <algorithm> // `std::transform`
28-
#include <cstdio> // `std::printf`
29-
#include <cstring> // `std::memcpy`
30-
#include <iterator> // `std::distance`
31-
#include <memory> // `std::allocator`
32-
#include <random> // `std::random_device`
33-
#include <sstream> // `std::ostringstream`
34-
#include <vector> // `std::vector`
27+
#include <algorithm> // `std::transform`
28+
#include <cstdio> // `std::printf`
29+
#include <cstring> // `std::memcpy`
30+
#include <iterator> // `std::distance`
31+
#include <map> // `std::map`
32+
#include <memory> // `std::allocator`
33+
#include <random> // `std::random_device`
34+
#include <sstream> // `std::ostringstream`
35+
#include <unordered_map> // `std::unordered_map`
36+
#include <vector> // `std::vector`
3537

3638
#include <string> // Baseline
3739
#include <string_view> // Baseline
@@ -58,6 +60,14 @@ template class std::basic_string<char>;
5860
template class sz::basic_string<char>;
5961
template class sz::basic_charset<char>;
6062

63+
template class std::vector<sz::string>;
64+
template class std::map<sz::string, int>;
65+
template class std::unordered_map<sz::string, int>;
66+
67+
template class std::vector<sz::string_view>;
68+
template class std::map<sz::string_view, int>;
69+
template class std::unordered_map<sz::string_view, int>;
70+
6171
/**
6272
* @brief Several string processing operations rely on computing integer logarithms.
6373
* Failures in such operations will result in wrong `resize` outcomes and heap corruption.
@@ -394,6 +404,10 @@ static void test_stl_compatibility_for_reads() {
394404
assert(str("12341234") <= str("12341234"));
395405
assert(str("12341234") > str("12241224"));
396406
assert(str("12341234") < str("13241324"));
407+
assert(str("0123456789012345678901234567890123456789012345678901234567890123") ==
408+
str("0123456789012345678901234567890123456789012345678901234567890123"));
409+
assert(str("0123456789012345678901234567890123456789012345678901234567890123") !=
410+
str("0223456789012345678901234567890123456789012345678901234567890123"));
397411

398412
// Comparisons.
399413
assert(str("a") != str("b"));
@@ -1489,6 +1503,21 @@ static void test_sequence_algorithms() {
14891503
}
14901504
}
14911505

1506+
/**
1507+
* @brief Tests constructing STL containers with StringZilla strings.
1508+
*/
1509+
static void test_stl_containers() {
1510+
std::map<sz::string, int> sorted_words_sz;
1511+
std::unordered_map<sz::string, int> words_sz;
1512+
assert(sorted_words_sz.empty());
1513+
assert(words_sz.empty());
1514+
1515+
std::map<std::string, int, sz::string_view_less> sorted_words_stl;
1516+
std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to> words_stl;
1517+
assert(sorted_words_stl.empty());
1518+
assert(words_stl.empty());
1519+
}
1520+
14921521
int main(int argc, char const **argv) {
14931522

14941523
// Let's greet the user nicely
@@ -1539,6 +1568,7 @@ int main(int argc, char const **argv) {
15391568

15401569
// Sequences of strings
15411570
test_sequence_algorithms();
1571+
test_stl_containers();
15421572

15431573
std::printf("All tests passed... Unbelievable!\n");
15441574
return 0;

0 commit comments

Comments
 (0)