Skip to main content

SIMD-accelerated string search, sort, hashes, fingerprints, & edit distances

Project description

StringZilla 🦖

StringZilla banner

The world wastes a minimum of $100M annually due to inefficient string operations. A typical codebase processes strings character by character, resulting in too many branches and data-dependencies, neglecting 90% of modern CPU's potential. LibC is different. It attempts to leverage SIMD instructions to boost some operations, and is often used by higher-level languages, runtimes, and databases. But it isn't perfect. 1️⃣ First, even on common hardware, including over a billion 64-bit ARM CPUs, common functions like strstr and memmem only achieve 1/3 of the CPU's throughput. 2️⃣ Second, SIMD coverage is inconsistent: acceleration in forward scans does not guarantee speed in the reverse-order search. 3️⃣ At last, most high-level languages can't always use LibC, as the strings are often not NULL-terminated or may contain the Unicode "Zero" character in the middle of the string. That's why StringZilla was created. To provide predictably high performance, portable to any modern platform, operating system, and programming language.

StringZilla Python installs StringZilla Rust installs GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status GitHub Actions Workflow Status StringZilla code size

StringZilla is the GodZilla of string libraries, using SIMD and SWAR to accelerate string operations on modern CPUs. It is up to 10x faster than the default and even other SIMD-accelerated string libraries in C, C++, Python, and other languages, while covering broad functionality. It accelerates exact and fuzzy string matching, edit distance computations, sorting, lazily-evaluated ranges to avoid memory allocations, and even random-string generators.

  • 🐂 C : Upgrade LibC's <string.h> to <stringzilla.h> in C 99
  • 🐉 C++: Upgrade STL's <string> to <stringzilla.hpp> in C++ 11
  • 🐍 Python: Upgrade your str to faster Str
  • 🍎 Swift: Use the String+StringZilla extension
  • 🦀 Rust: Use the StringZilla traits crate
  • 🐚 Shell: Accelerate common CLI tools with sz_ prefix
  • 📚 Researcher? Jump to Algorithms & Design Decisions
  • 💡 Thinking to contribute? Look for "good first issues"
  • 🤝 And check the guide to setup the environment
  • Want more bindings or features? Let me know!

Who is this for?

  • For data-engineers parsing large datasets, like the CommonCrawl, RedPajama, or LAION.
  • For software engineers optimizing strings in their apps and services.
  • For bioinformaticians and search engineers looking for edit-distances for USearch.
  • For DBMS devs, optimizing LIKE, ORDER BY, and GROUP BY operations.
  • For hardware designers, needing a SWAR baseline for strings-processing functionality.
  • For students studying SIMD/SWAR applications to non-data-parallel operations.

Performance

C C++ Python StringZilla
find the first occurrence of a random word from text, ≅ 5 bytes long
strstr 1
x86: 7.4 · arm: 2.0 GB/s
.find
x86: 2.9 · arm: 1.6 GB/s
.find
x86: 1.1 · arm: 0.6 GB/s
sz_find
x86: 10.6 · arm: 7.1 GB/s
find the last occurrence of a random word from text, ≅ 5 bytes long
.rfind
x86: 0.5 · arm: 0.4 GB/s
.rfind
x86: 0.9 · arm: 0.5 GB/s
sz_rfind
x86: 10.8 · arm: 6.7 GB/s
split lines separated by \n or \r 2
strcspn 1
x86: 5.42 · arm: 2.19 GB/s
.find_first_of
x86: 0.59 · arm: 0.46 GB/s
re.finditer
x86: 0.06 · arm: 0.02 GB/s
sz_find_charset
x86: 4.08 · arm: 3.22 GB/s
find the last occurrence of any of 6 whitespaces 2
.find_last_of
x86: 0.25 · arm: 0.25 GB/s
sz_rfind_charset
x86: 0.43 · arm: 0.23 GB/s
Random string from a given alphabet, 20 bytes long 5
rand() % n
x86: 18.0 · arm: 9.4 MB/s
uniform_int_distribution
x86: 47.2 · arm: 20.4 MB/s
join(random.choices(...))
x86: 13.3 · arm: 5.9 MB/s
sz_generate
x86: 56.2 · arm: 25.8 MB/s
Get sorted order, ≅ 8 million English words 6
qsort_r
x86: 3.55 · arm: 5.77 s
std::sort
x86: 2.79 · arm: 4.02 s
numpy.argsort
x86: 7.58 · arm: 13.00 s
sz_sort
x86: 1.91 · arm: 2.37 s
Levenshtein edit distance, ≅ 5 bytes long
via jellyfish 3
x86: 1,550 · arm: 2,220 ns
sz_edit_distance
x86: 99 · arm: 180 ns
Needleman-Wunsch alignment scores, ≅ 10 K aminoacids long
via biopython 4
x86: 257 · arm: 367 ms
sz_alignment_score
x86: 73 · arm: 177 ms

StringZilla has a lot of functionality, most of which is covered by benchmarks across C, C++, Python and other languages. You can find those in the ./scripts directory, with usage notes listed in the CONTRIBUTING.md file. Notably, if the CPU supports misaligned loads, even the 64-bit SWAR backends are faster than either standard library.

Most benchmarks were conducted on a 1 GB English text corpus, with an average word length of 6 characters. The code was compiled with GCC 12, using glibc v2.35. The benchmarks performed on Arm-based Graviton3 AWS c7g instances and r7iz Intel Sapphire Rapids. Most modern Arm-based 64-bit CPUs will have similar relative speedups. Variance withing x86 CPUs will be larger. 1 Unlike other libraries, LibC requires strings to be NULL-terminated. 2 Six whitespaces in the ASCII set are: \t\n\v\f\r. Python's and other standard libraries have specialized functions for those. 3 Most Python libraries for strings are also implemented in C. 4 Unlike the rest of BioPython, the alignment score computation is implemented in C. 5 All modulo operations were conducted with uint8_t to allow compilers more optimization opportunities. The C++ STL and StringZilla benchmarks used a 64-bit Mersenne Twister as the generator. For C, C++, and StringZilla, an in-place update of the string was used. In Python every string had to be allocated as a new object, which makes it less fair. 6 Contrary to the popular opinion, Python's default sorted function works faster than the C and C++ standard libraries. That holds for large lists or tuples of strings, but fails as soon as you need more complex logic, like sorting dictionaries by a string key, or producing the "sorted order" permutation. The latter is very common in database engines and is most similar to numpy.argsort. Current StringZilla solution can be at least 4x faster without loss of generality.

Functionality

StringZilla is compatible with most modern CPUs, and provides a broad range of functionality.

  • works on both Little-Endian and Big-Endian architectures.
  • works on 32-bit and 64-bit hardware architectures.
  • compatible with ASCII and UTF-8 encoding.

Not all features are available across all bindings. Consider contributing, if you need a feature that's not yet implemented.

Maturity C 99 C++ 11 Python Swift Rust
Substring Search 🌳
Character Set Search 🌳
Edit Distances 🧐
Small String Class 🧐
Sorting & Sequence Operations 🚧
Lazy Ranges, Compressed Arrays 🧐
Hashes & Fingerprints 🚧

🌳 parts are used in production. 🧐 parts are in beta. 🚧 parts are under active development, and are likely to break in subsequent releases. ✅ are implemented. ⚪ are considered. ❌ are not intended.

Quick Start: Python 🐍

Python bindings are available on PyPI, and can be installed with pip. You can immediately check the installed version and the used hardware capabilities with following commands:

pip install stringzilla
python -c "import stringzilla; print(stringzilla.__version__)"
python -c "import stringzilla; print(stringzilla.__capabilities__)"

Basic Usage

If you've ever used the Python str, bytes, bytearray, memoryview class, you'll know what to expect. StringZilla's Str class is a hybrid of those two, providing str-like interface to byte-arrays.

from stringzilla import Str, File

text_from_str = Str('some-string') # no copies, just a view
text_from_file = Str(File('some-file.txt')) # memory-mapped file

The File class memory-maps a file from persistent memory without loading its copy into RAM. The contents of that file would remain immutable, and the mapping can be shared by multiple Python processes simultaneously. A standard dataset pre-processing use case would be to map a sizeable textual dataset like Common Crawl into memory, spawn child processes, and split the job between them.

Basic Operations

  • Length: len(text) -> int
  • Indexing: text[42] -> str
  • Slicing: text[42:46] -> Str
  • Substring check: 'substring' in text -> bool
  • Hashing: hash(text) -> int
  • String conversion: str(text) -> str

Advanced Operations

import sys

x: bool = text.contains('substring', start=0, end=sys.maxsize)
x: int = text.find('substring', start=0, end=sys.maxsize)
x: int = text.count('substring', start=0, end=sys.maxsize, allowoverlap=False)
x: str = text.decode(encoding='utf-8', errors='strict')
x: Strs = text.split(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit(separator=' ', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.splitlines(keeplinebreaks=False, maxsplit=sys.maxsize)

It's important to note, that the last function behavior is slightly different from Python's str.splitlines. The native version matches \n, \r, \v or \x0b, \f or \x0c, \x1c, \x1d, \x1e, \x85, \r\n, \u2028, \u2029, including 3x two-bytes-long runes. The StringZilla version matches only \n, \v, \f, \r, \x1c, \x1d, \x1e, \x85, avoiding two-byte-long runes.

Character Set Operations

Python strings don't natively support character set operations. This forces people to use regular expressions, which are slow and hard to read. To avoid the need for re.finditer, StringZilla provides the following interfaces:

x: int = text.find_first_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_of('chars', start=0, end=sys.maxsize)
x: int = text.find_first_not_of('chars', start=0, end=sys.maxsize)
x: int = text.find_last_not_of('chars', start=0, end=sys.maxsize)
x: Strs = text.split_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)
x: Strs = text.rsplit_charset(separator='chars', maxsplit=sys.maxsize, keepseparator=False)

Collection-Level Operations

Once split into a Strs object, you can sort, shuffle, and reorganize the slices, with minimum memory footprint. If all the chunks are located in consecutive memory regions, the memory overhead can be as low as 4 bytes per chunk.

lines: Strs = text.split(separator='\n') # 4 bytes per line overhead for under 4 GB of text
batch: Strs = lines.sample(seed=42) # 10x faster than `random.choices`
lines.shuffle(seed=42) # or shuffle all lines in place and shard with slices
# WIP: lines.sort() # explodes to 16 bytes per line overhead for any length text
# WIP: sorted_order: tuple = lines.argsort() # similar to `numpy.argsort`

Working on RedPajama, addressing 20 Billion annotated english documents, one will need only 160 GB of RAM instead of Terabytes. Once loaded, the data will be memory-mapped, and can be reused between multiple Python processes without copies. And of course, you can use slices to navigate the dataset and shard it between multiple workers.

lines[::3] # every third line
lines[1::1] # every odd line
lines[:-100:-1] # last 100 lines in reverse order

Iterators and Memory Efficiency

Python's operations like split() and readlines() immediately materialize a list of copied parts. This can be very memory-inefficient for large datasets. StringZilla saves a lot of memory by viewing existing memory regions as substrings, but even more memory can be saved by using lazily evaluated iterators.

x: SplitIterator[Str] = text.split_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_iter(separator=' ', keepseparator=False)
x: SplitIterator[Str] = text.split_charset_iter(separator='chars', keepseparator=False)
x: SplitIterator[Str] = text.rsplit_charset_iter(separator='chars', keepseparator=False)

StringZilla can easily be 10x more memory efficient than native Python classes for tokenization. With lazy operations, it practically becomes free.

import stringzilla as sz
%load_ext memory_profiler

text = open("enwik9.txt", "r").read() # 1 GB, mean word length 7.73 bytes
%memit text.split() # increment: 8670.12 MiB (152 ms)
%memit sz.split(text) # increment: 530.75 MiB (25 ms)
%memit sum(1 for _ in sz.split_iter(text)) # increment: 0.00 MiB

Low-Level Python API

Aside from calling the methods on the Str and Strs classes, you can also call the global functions directly on str and bytes instances. Assuming StringZilla CPython bindings are implemented without any intermediate tools like SWIG or PyBind, the call latency should be similar to native classes.

import stringzilla as sz

contains: bool = sz.contains("haystack", "needle", start=0, end=sys.maxsize)
offset: int = sz.find("haystack", "needle", start=0, end=sys.maxsize)
count: int = sz.count("haystack", "needle", start=0, end=sys.maxsize, allowoverlap=False)

Edit Distances

assert sz.edit_distance("apple", "aple") == 1 # skip one ASCII character
assert sz.edit_distance("αβγδ", "αγδ") == 2 # skip two bytes forming one rune
assert sz.edit_distance_unicode("αβγδ", "αγδ") == 1 # one unicode rune

Several Python libraries provide edit distance computation. Most of them are implemented in C, but are not always as fast as StringZilla. Taking a 1'000 long proteins around 10'000 characters long, computing just a 100 distances:

Moreover, you can pass custom substitution matrices to compute the Needleman-Wunsch alignment scores. That task is very common in bioinformatics and computational biology. It's natively supported in BioPython, and its BLOSUM matrices can be converted to StringZilla's format. Alternatively, you can construct an arbitrary 256 by 256 cost matrix using NumPy. Depending on arguments, the result may be equal to the negative Levenshtein distance.

import numpy as np
import stringzilla as sz

costs = np.zeros((256, 256), dtype=np.int8)
costs.fill(-1)
np.fill_diagonal(costs, 0)

assert sz.alignment_score("first", "second", substitution_matrix=costs, gap_score=-1) == -sz.edit_distance(a, b)

Using the same proteins as for Levenshtein distance benchmarks:

§ Example converting from BioPython to StringZilla.
import numpy as np
from Bio import Align
from Bio.Align import substitution_matrices

aligner = Align.PairwiseAligner()
aligner.substitution_matrix = substitution_matrices.load("BLOSUM62")
aligner.open_gap_score = 1
aligner.extend_gap_score = 1

# Convert the matrix to NumPy
subs_packed = np.array(aligner.substitution_matrix).astype(np.int8)
subs_reconstructed = np.zeros((256, 256), dtype=np.int8)

# Initialize all banned characters to a the largest possible penalty
subs_reconstructed.fill(127)
for packed_row, packed_row_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
    for packed_column, packed_column_aminoacid in enumerate(aligner.substitution_matrix.alphabet):
        reconstructed_row = ord(packed_row_aminoacid)
        reconstructed_column = ord(packed_column_aminoacid)
        subs_reconstructed[reconstructed_row, reconstructed_column] = subs_packed[packed_row, packed_column]

# Let's pick two examples for of tri-peptides (made of 3 aminoacids)
glutathione = "ECG" # Need to rebuild human tissue?
thyrotropin_releasing_hormone = "QHP" # Or to regulate your metabolism?

assert sz.alignment_score(
    glutathione,
    thyrotropin_releasing_hormone, 
    substitution_matrix=subs_reconstructed, 
    gap_score=1) == aligner.score(glutathione, thyrotropin_releasing_hormone) # Equal to 6

Serialization

Filesystem

Similar to how File can be used to read a large file, other interfaces can be used to dump strings to disk faster. The Str class has write_to to write the string to a file, and offset_within to obtain integer offsets of substring view in larger string for navigation.

web_archive = Str("<html>...</html><html>...</html>")
_, end_tag, next_doc = web_archive.partition("</html>") # or use `find`
next_doc_offset = next_doc.offset_within(web_archive)
web_archive.write_to("next_doc.html") # no GIL, no copies, just a view

PyArrow

A Str is easy to cast to PyArrow buffers.

from pyarrow import foreign_buffer
from stringzilla import Str

original = "hello"
view = Str(native)
arrow = foreign_buffer(view.address, view.nbytes, view)

That means you can convert Str to pyarrow.Buffer and Strs to pyarrow.Array without extra copies.

Quick Start: C/C++ 🛠️

The C library is header-only, so you can just copy the stringzilla.h header into your project. Same applies to C++, where you would copy the stringzilla.hpp header. Alternatively, add it as a submodule, and include it in your build system.

git submodule add https://github.com/ashvardanian/stringzilla.git

Or using a pure CMake approach:

FetchContent_Declare(stringzilla GIT_REPOSITORY https://github.com/ashvardanian/stringzilla.git)
FetchContent_MakeAvailable(stringzilla)

Last, but not the least, you can also install it as a library, and link against it. This approach is worse for inlining, but brings dynamic runtime dispatch for the most advanced CPU features.

Basic Usage with C 99 and Newer

There is a stable C 99 interface, where all function names are prefixed with sz_. Most interfaces are well documented, and come with self-explanatory names and examples. In some cases, hardware specific overloads are available, like sz_find_avx512 or sz_find_neon. Both are companions of the sz_find, first for x86 CPUs with AVX-512 support, and second for Arm NEON-capable CPUs.

#include <stringzilla/stringzilla.h>

// Initialize your haystack and needle
sz_string_view_t haystack = {your_text, your_text_length};
sz_string_view_t needle = {your_subtext, your_subtext_length};

// Perform string-level operations
sz_size_t substring_position = sz_find(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_avx512(haystack.start, haystack.length, needle.start, needle.length);
sz_size_t substring_position = sz_find_neon(haystack.start, haystack.length, needle.start, needle.length);

// Hash strings
sz_u64_t hash = sz_hash(haystack.start, haystack.length);

// Perform collection level operations
sz_sequence_t array = {your_order, your_count, your_get_start, your_get_length, your_handle};
sz_sort(&array, &your_config);
§ Mapping from LibC to StringZilla.

By design, StringZilla has a couple of notable differences from LibC:

  1. all strings are expected to have a length, and are not necessarily null-terminated.
  2. every operations has a reverse order counterpart.

That way sz_find and sz_rfind are similar to strstr and strrstr in LibC. Similarly, sz_find_byte and sz_rfind_byte replace memchr and memrchr. The sz_find_charset maps to strspn and strcspn, while sz_rfind_charset has no sibling in LibC.

LibC Functionality StringZilla Equivalents
memchr(haystack, needle, haystack_length), strchr sz_find_byte(haystack, haystack_length, needle)
memrchr(haystack, needle, haystack_length) sz_rfind_byte(haystack, haystack_length, needle)
memcmp, strcmp sz_order, sz_equal
strlen(haystack) sz_find_byte(haystack, haystack_length, needle)
strcspn(haystack, needles) sz_rfind_charset(haystack, haystack_length, needles_bitset)
strspn(haystack, needles) sz_find_charset(haystack, haystack_length, needles_bitset)
memmem(haystack, haystack_length, needle, needle_length), strstr sz_find(haystack, haystack_length, needle, needle_length)
memcpy(destination, source, destination_length) sz_copy(destination, source, destination_length)
memmove(destination, source, destination_length) sz_move(destination, source, destination_length)
memset(destination, value, destination_length) sz_fill(destination, destination_length, value)

Basic Usage with C++ 11 and Newer

There is a stable C++ 11 interface available in the ashvardanian::stringzilla namespace. It comes with two STL-like classes: string_view and string. The first is a non-owning view of a string, and the second is a mutable string with a Small String Optimization.

#include <stringzilla/stringzilla.hpp>

namespace sz = ashvardanian::stringzilla;

sz::string haystack = "some string";
sz::string_view needle = sz::string_view(haystack).substr(0, 4);

auto substring_position = haystack.find(needle); // Or `rfind`
auto hash = std::hash<sz::string_view>(haystack); // Compatible with STL's `std::hash`

haystack.end() - haystack.begin() == haystack.size(); // Or `rbegin`, `rend`
haystack.find_first_of(" \w\t") == 4; // Or `find_last_of`, `find_first_not_of`, `find_last_not_of`
haystack.starts_with(needle) == true; // Or `ends_with`
haystack.remove_prefix(needle.size()); // Why is this operation in-place?!
haystack.contains(needle) == true; // STL has this only from C++ 23 onwards
haystack.compare(needle) == 1; // Or `haystack <=> needle` in C++ 20 and beyond

StringZilla also provides string literals for automatic type resolution, similar to STL:

using sz::literals::operator""_sz;
using std::literals::operator""sv;

auto a = "some string"; // char const *
auto b = "some string"sv; // std::string_view
auto b = "some string"_sz; // sz::string_view

Memory Ownership and Small String Optimization

Most operations in StringZilla don't assume any memory ownership. But in addition to the read-only search-like operations StringZilla provides a minimalistic C and C++ implementations for a memory owning string "class". Like other efficient string implementations, it uses the Small String Optimization (SSO) to avoid heap allocations for short strings.

typedef union sz_string_t {
    struct internal {
        sz_ptr_t start;
        sz_u8_t length;
        char chars[SZ_STRING_INTERNAL_SPACE]; /// Ends with a null-terminator.
    } internal;

    struct external {
        sz_ptr_t start;
        sz_size_t length;        
        sz_size_t space; /// The length of the heap-allocated buffer.
        sz_size_t padding;
    } external;

} sz_string_t;

As one can see, a short string can be kept on the stack, if it fits within internal.chars array. Before 2015 GCC string implementation was just 8 bytes, and could only fit 7 characters. Different STL implementations today have different thresholds for the Small String Optimization. Similar to GCC, StringZilla is 32 bytes in size, and similar to Clang it can fit 22 characters on stack. Our layout might be preferential, if you want to avoid branches. If you use a different compiler, you may want to check it's SSO buffer size with a simple Gist.

libstdc++ in GCC 13 libc++ in Clang 17 StringZilla
sizeof(std::string) 32 24 32
Small String Capacity 15 22 22

This design has been since ported to many high-level programming languages. Swift, for example, can store 15 bytes in the String instance itself. StringZilla implements SSO at the C level, providing the sz_string_t union and a simple API for primary operations.

sz_memory_allocator_t allocator;
sz_string_t string;

// Init and make sure we are on stack
sz_string_init(&string);
sz_string_is_on_stack(&string); // == sz_true_k

// Optionally pre-allocate space on the heap for future insertions.
sz_string_grow(&string, 100, &allocator); // == sz_true_k

// Append, erase, insert into the string.
sz_string_expand(&string, 0, "_Hello_", 7, &allocator); // == sz_true_k
sz_string_expand(&string, SZ_SIZE_MAX, "world", 5, &allocator); // == sz_true_k
sz_string_erase(&string, 0, 1);

// Unpacking & introspection.
sz_ptr_t string_start;
sz_size_t string_length;
sz_size_t string_space;
sz_bool_t string_is_external;
sz_string_unpack(string, &string_start, &string_length, &string_space, &string_is_external);
sz_equal(string_start, "Hello_world", 11); // == sz_true_k

// Reclaim some memory.
sz_string_shrink_to_fit(&string, &allocator); // == sz_true_k
sz_string_free(&string, &allocator);

Unlike the conventional C strings, the sz_string_t is allowed to contain null characters. To safely print those, pass the string_length to printf as well.

printf("%.*s\n", (int)string_length, string_start);

What's Wrong with the C++ Standard Library?

C++ Code Evaluation Result Invoked Signature
"Loose"s.replace(2, 2, "vath"s, 1) "Loathe" 🤢 (pos1, count1, str2, pos2)
"Loose"s.replace(2, 2, "vath", 1) "Love" 🥰 (pos1, count1, str2, count2)

StringZilla is designed to be a drop-in replacement for the C++ Standard Templates Library. That said, some of the design decisions of STL strings are highly controversial, error-prone, and expensive. Most notably:

  1. Argument order for replace, insert, erase and similar functions is impossible to guess.
  2. Bounds-checking exceptions for substr-like functions are only thrown for one side of the range.
  3. Returning string copies in substr-like functions results in absurd volume of allocations.
  4. Incremental construction via push_back-like functions goes through too many branches.
  5. Inconsistency between string and string_view methods, like the lack of remove_prefix and remove_suffix.

Check the following set of asserts validating the std::string specification. It's not realistic to expect the average developer to remember the 14 overloads of std::string::replace.

using str = std::string;

assert(str("hello world").substr(6) == "world");
assert(str("hello world").substr(6, 100) == "world"); // 106 is beyond the length of the string, but its OK
assert_throws(str("hello world").substr(100), std::out_of_range);   // 100 is beyond the length of the string
assert_throws(str("hello world").substr(20, 5), std::out_of_range); // 20 is beyond the length of the string
assert_throws(str("hello world").substr(-1, 5), std::out_of_range); // -1 casts to unsigned without any warnings...
assert(str("hello world").substr(0, -1) == "hello world");          // -1 casts to unsigned without any warnings...

assert(str("hello").replace(1, 2, "123") == "h123lo");
assert(str("hello").replace(1, 2, str("123"), 1) == "h23lo");
assert(str("hello").replace(1, 2, "123", 1) == "h1lo");
assert(str("hello").replace(1, 2, "123", 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, str("123"), 1, 1) == "h2lo");
assert(str("hello").replace(1, 2, 3, 'a') == "haaalo");
assert(str("hello").replace(1, 2, {'a', 'b'}) == "hablo");

To avoid those issues, StringZilla provides an alternative consistent interface. It supports signed arguments, and doesn't have more than 3 arguments per function or The standard API and our alternative can be conditionally disabled with SZ_SAFETY_OVER_COMPATIBILITY=1. When it's enabled, the subjectively risky overloads from the Standard will be disabled.

using str = sz::string;

str("a:b").front(1) == "a"; // no checks, unlike `substr`
str("a:b").front(2) == "2"; // take first 2 characters
str("a:b").back(-1) == "b"; // accepting negative indices
str("a:b").back(-2) == ":b"; // similar to Python's `"a:b"[-2:]`
str("a:b").sub(1, -1) == ":"; // similar to Python's `"a:b"[1:-1]`
str("a:b").sub(-2, -1) == ":"; // similar to Python's `"a:b"[-2:-1]`
str("a:b").sub(-2, 1) == ""; // similar to Python's `"a:b"[-2:1]`
"a:b"_sz[{-2, -1}] == ":"; // works on views and overloads `operator[]`

Assuming StringZilla is a header-only library you can use the full API in some translation units and gradually transition to safer restricted API in others. Bonus - all the bound checking is branchless, so it has a constant cost and won't hurt your branch predictor.

Beyond the C++ Standard Library - Learning from Python

Python is arguably the most popular programming language for data science. In part, that's due to the simplicity of its standard interfaces. StringZilla brings some of that functionality to C++.

  • Content checks: isalnum, isalpha, isascii, isdigit, islower, isspace, isupper.
  • Trimming character sets: lstrip, rstrip, strip.
  • Trimming string matches: remove_prefix, remove_suffix.
  • Ranges of search results: splitlines, split, rsplit.
  • Number of non-overlapping substring matches: count.
  • Partitioning: partition, rpartition.

For example, when parsing documents, it is often useful to split it into substrings. Most often, after that, you would compute the length of the skipped part, the offset and the length of the remaining part. This results in a lot of pointer arithmetic and is error-prone. StringZilla provides a convenient partition function, which returns a tuple of three string views, making the code cleaner.

auto parts = haystack.partition(':'); // Matching a character
auto [before, match, after] = haystack.partition(':'); // Structure unpacking
auto [before, match, after] = haystack.partition(char_set(":;")); // Character-set argument
auto [before, match, after] = haystack.partition(" : "); // String argument
auto [before, match, after] = haystack.rpartition(sz::whitespaces); // Split around the last whitespace

Combining those with the split function, one can easily parse a CSV file or HTTP headers.

for (auto line : haystack.split("\r\n")) {
    auto [key, _, value] = line.partition(':');
    headers[key.strip()] = value.strip();
}

Some other extensions are not present in the Python standard library either. Let's go through the C++ functionality category by category.

Some of the StringZilla interfaces are not available even Python's native str class. Here is a sneak peek of the most useful ones.

text.hash(); // -> 64 bit unsigned integer 
text.ssize(); // -> 64 bit signed length to avoid `static_cast<std::ssize_t>(text.size())`
text.contains_only(" \w\t"); // == text.find_first_not_of(char_set(" \w\t")) == npos;
text.contains(sz::whitespaces); // == text.find(char_set(sz::whitespaces)) != npos;

// Simpler slicing than `substr`
text.front(10); // -> sz::string_view
text.back(10); // -> sz::string_view

// Safe variants, which clamp the range into the string bounds
using sz::string::cap;
text.front(10, cap) == text.front(std::min(10, text.size()));
text.back(10, cap) == text.back(std::min(10, text.size()));

// Character set filtering
text.lstrip(sz::whitespaces).rstrip(sz::newlines); // like Python
text.front(sz::whitespaces); // all leading whitespaces
text.back(sz::digits); // all numerical symbols forming the suffix

// Incremental construction
using sz::string::unchecked;
text.push_back('x'); // no surprises here
text.push_back('x', unchecked); // no bounds checking, Rust style
text.try_push_back('x'); // returns `false` if the string is full and the allocation failed

sz::concatenate(text, "@", domain, ".", tld); // No allocations

Splits and Ranges

One of the most common use cases is to split a string into a collection of substrings. Which would often result in StackOverflow lookups and snippets like the one below.

std::vector<std::string> lines = split(haystack, "\r\n"); // string delimiter
std::vector<std::string> words = split(lines, ' '); // character delimiter

Those allocate memory for each string and the temporary vectors. Each allocation can be orders of magnitude more expensive, than even serial for-loop over characters. To avoid those, StringZilla provides lazily-evaluated ranges, compatible with the Range-v3 library.

for (auto line : haystack.split("\r\n"))
    for (auto word : line.split(char_set(" \w\t.,;:!?")))
        std::cout << word << std::endl;

Each of those is available in reverse order as well. It also allows interleaving matches, if you want both inclusions of xx in xxx. Debugging pointer offsets is not a pleasant exercise, so keep the following functions in mind.

  • haystack.[r]find_all(needle, interleaving)
  • haystack.[r]find_all(char_set(""))
  • haystack.[r]split(needle)
  • haystack.[r]split(char_set(""))

For $N$ matches the split functions will report $N+1$ matches, potentially including empty strings. Ranges have a few convenience methods as well:

range.size(); // -> std::size_t
range.empty(); // -> bool
range.template to<std::set<std::sting>>(); 
range.template to<std::vector<std::sting_view>>(); 

Concatenating Strings without Allocations

Another common string operation is concatenation. The STL provides std::string::operator+ and std::string::append, but those are not very efficient, if multiple invocations are performed.

std::string name, domain, tld;
auto email = name + "@" + domain + "." + tld; // 4 allocations

The efficient approach would be to pre-allocate the memory and copy the strings into it.

std::string email;
email.reserve(name.size() + domain.size() + tld.size() + 2);
email.append(name), email.append("@"), email.append(domain), email.append("."), email.append(tld);

That's mouthful and error-prone. StringZilla provides a more convenient concatenate function, which takes a variadic number of arguments. It also overrides the operator| to concatenate strings lazily, without any allocations.

auto email = sz::concatenate(name, "@", domain, ".", tld);   // 0 allocations
auto email = name | "@" | domain | "." | tld;                // 0 allocations
sz::string email = name | "@" | domain | "." | tld;          // 1 allocations

Random Generation

Software developers often need to generate random strings for testing purposes. The STL provides std::generate and std::random_device, that can be used with StringZilla.

sz::string random_string(std::size_t length, char const *alphabet, std::size_t cardinality) {
    sz::string result(length, '\0');
    static std::random_device seed_source; // Expensive to construct - due to system calls
    static std::mt19937 generator(seed_source()); // Also expensive - due to the state size
    std::uniform_int_distribution<std::size_t> distribution(0, cardinality);
    std::generate(result.begin(), result.end(), [&]() { return alphabet[distribution(generator)]; });
    return result;
}

Mouthful and slow. StringZilla provides a C native method - sz_generate and a convenient C++ wrapper - sz::generate. Similar to Python it also defines the commonly used character sets.

auto protein = sz::string::random(300, "ARNDCQEGHILKMFPSTWYV"); // static method
auto dna = sz::basic_string<custom_allocator>::random(3_000_000_000, "ACGT");

dna.randomize("ACGT"); // `noexcept` pre-allocated version
dna.randomize(&std::rand, "ACGT"); // pass any generator, like `std::mt19937`

char uuid[36];
sz::randomize(sz::string_span(uuid, 36), "0123456789abcdef-"); // Overwrite any buffer

Levenshtein Edit Distance and Alignment Scores

Levenshtein and Hamming edit distance are provided for both byte-strings and UTF-8 strings. The latter will output the distance in Unicode code points, not bytes. Needleman-Wunsch alignment scores are only defined for byte-strings.

// Count number of substitutions in same length strings
sz::hamming_distance(first, second[, upper_bound]) -> std::size_t;
sz::hamming_distance_utf8(first, second[, upper_bound]) -> std::size_t;

// Count number of insertions, deletions and substitutions
sz::edit_distance(first, second[, upper_bound[, allocator]]) -> std::size_t;
sz::edit_distance_utf8(first, second[, upper_bound[, allocator]]) -> std::size_t;

// Substitution-parametrized Needleman-Wunsch global alignment score
std::int8_t costs[256][256]; // Substitution costs matrix
sz::alignment_score(first, second, costs[, gap_score[, allocator]) -> std::ptrdiff_t;

Sorting in C and C++

LibC provides qsort and STL provides std::sort. Both have their quarks. The LibC standard has no way to pass a context to the comparison function, that's only possible with platform-specific extensions. Those have different arguments order on every OS.

// Linux: https://linux.die.net/man/3/qsort_r
void qsort_r(void *elements, size_t count, size_t element_width, 
    int (*compare)(void const *left, void const *right, void *context),
    void *context);
// MacOS and FreeBSD: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/qsort_r.3.html
void qsort_r(void *elements, size_t count, size_t element_width, 
    void *context,
    int (*compare)(void *context, void const *left, void const *right));
// Windows conflicts with ISO `qsort_s`: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/qsort-s?view=msvc-170
void qsort_s(id *elements, size_t count, size_t element_width, 
    int (*compare)(void *context, void const *left, void const *right),
    void *context);

C++ generic algorithm is not perfect either. There is no guarantee in the standard that std::sort won't allocate any memory. If you are running on embedded, in real-time or on 100+ CPU cores per node, you may want to avoid that. StringZilla doesn't solve the general case, but hopes to improve the performance for strings. Use sz_sort, or the high-level sz::sorted_order, which can be used sort any collection of elements convertible to sz::string_view.

std::vector<std::string> data({"c", "b", "a"});
std::vector<std::size_t> order = sz::sorted_order(data); //< Simple shortcut

// Or, taking care of memory allocation:
sz::sorted_order(data.begin(), data.end(), order.data(), [](auto const &x) -> sz::string_view { return x; });

Standard C++ Containers with String Keys

The C++ Standard Templates Library provides several associative containers, often used with string keys.

std::map<std::string, int, std::less<std::string>> sorted_words;
std::unordered_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>> words;

The performance of those containers is often limited by the performance of the string keys, especially on reads. StringZilla can be used to accelerate containers with std::string keys, by overriding the default comparator and hash functions.

std::map<std::string, int, sz::string_view_less> sorted_words;
std::unordered_map<std::string, int, sz::string_view_hash, sz::string_view_equal_to> words;

Alternatively, a better approach would be to use the sz::string class as a key. The right hash function and comparator would be automatically selected and the performance gains would be more noticeable if the keys are short.

std::map<sz::string, int> sorted_words;
std::unordered_map<sz::string, int> words;

Compilation Settings and Debugging

SZ_DEBUG:

For maximal performance, the C library does not perform any bounds checking in Release builds. In C++, bounds checking happens only in places where the STL std::string would do it. If you want to enable more aggressive bounds-checking, define SZ_DEBUG before including the header. If not explicitly set, it will be inferred from the build type.

SZ_USE_X86_AVX512, SZ_USE_X86_AVX2, SZ_USE_ARM_NEON:

One can explicitly disable certain families of SIMD instructions for compatibility purposes. Default values are inferred at compile time.

SZ_DYNAMIC_DISPATCH:

By default, StringZilla is a header-only library. But if you are running on different generations of devices, it makes sense to pre-compile the library for all supported generations at once, and dispatch at runtime. This flag does just that and is used to produce the stringzilla.so shared library, as well as the Python bindings.

SZ_USE_MISALIGNED_LOADS:

By default, StringZilla avoids misaligned loads. If supported, it replaces many byte-level operations with word-level ones. Going from char-like types to uint64_t-like ones can significantly accelerate the serial (SWAR) backend. So consider enabling it if you are building for some embedded device.

SZ_AVOID_LIBC and SZ_OVERRIDE_LIBC:

When using the C header-only library one can disable the use of LibC. This may affect the type resolution system on obscure hardware platforms. Moreover, one may let stringzilla override the common symbols like the memcpy and memset with its own implementations. In that case you can use the LD_PRELOAD trick to prioritize it's symbols over the ones from the LibC and accelerate existing string-heavy applications without recompiling them.

SZ_AVOID_STL and SZ_SAFETY_OVER_COMPATIBILITY:

When using the C++ interface one can disable implicit conversions from std::string to sz::string and back. If not needed, the <string> and <string_view> headers will be excluded, reducing compilation time. Moreover, if STL compatibility is a low priority, one can make the API safer by disabling the overloads, which are subjectively error prone.

STRINGZILLA_BUILD_SHARED, STRINGZILLA_BUILD_TEST, STRINGZILLA_BUILD_BENCHMARK, STRINGZILLA_TARGET_ARCH for CMake users:

When compiling the tests and benchmarks, you can explicitly set the target hardware architecture. It's synonymous to GCC's -march flag and is used to enable/disable the appropriate instruction sets. You can also disable the shared library build, if you don't need it.

Quick Start: Rust 🦀

StringZilla is available as a Rust crate, with documentation available on docs.rs/stringzilla. To use the latest crate release in your project, add the following to your Cargo.toml:

[dependencies]
stringzilla = ">=3"

Or if you want to use the latest pre-release version from the repository:

[dependencies]
stringzilla = { git = "https://github.com/ashvardanian/stringzilla", branch = "main-dev" }

Once installed, all of the functionality is available through the stringzilla namespace. Many interfaces will look familiar to the users of the memchr crate.

use stringzilla::sz;

// Identical to `memchr::memmem::find` and `memchr::memmem::rfind` functions
sz::find("Hello, world!", "world") // 7
sz::rfind("Hello, world!", "world") // 7

// Generalizations of `memchr::memrchr[123]`
sz::find_char_from("Hello, world!", "world") // 2
sz::rfind_char_from("Hello, world!", "world") // 11

Unlike memchr, the throughput of stringzilla is high in both normal and reverse-order searches. It also provides no constraints on the size of the character set, while memchr allows only 1, 2, or 3 characters. In addition to global functions, stringzilla provides a StringZilla extension trait:

use stringzilla::StringZilla;

let my_string: String = String::from("Hello, world!");
let my_str = my_string.as_str();
let my_cow_str = Cow::from(&my_string);

// Use the generic function with a String
assert_eq!(my_string.sz_find("world"), Some(7));
assert_eq!(my_string.sz_rfind("world"), Some(7));
assert_eq!(my_string.sz_find_char_from("world"), Some(2));
assert_eq!(my_string.sz_rfind_char_from("world"), Some(11));
assert_eq!(my_string.sz_find_char_not_from("world"), Some(0));
assert_eq!(my_string.sz_rfind_char_not_from("world"), Some(12));

// Same works for &str and Cow<'_, str>
assert_eq!(my_str.sz_find("world"), Some(7));
assert_eq!(my_cow_str.as_ref().sz_find("world"), Some(7));

The library also exposes Levenshtein and Hamming edit-distances for byte-arrays and UTF-8 strings, as well as Needleman-Wunch alignment scores.

use stringzilla::sz;

// Handling arbitrary byte arrays:
sz::edit_distance("Hello, world!", "Hello, world?"); // 1
sz::hamming_distance("Hello, world!", "Hello, world?"); // 1
sz::alignment_score("Hello, world!", "Hello, world?", sz::unary_substitution_costs(), -1); // -1

// Handling UTF-8 strings:
sz::hamming_distance_utf8("αβγδ", "αγγδ") // 1
sz::edit_distance_utf8("façade", "facade") // 1

Quick Start: Swift 🍏

StringZilla can be added as a dependency in the Swift Package Manager. In your Package.swift file, add the following:

dependencies: [
    .package(url: "https://github.com/ashvardanian/stringzilla")
]

The package currently covers only the most basic functionality, but is planned to be extended to cover the full C++ API.

var s = "Hello, world! Welcome to StringZilla. 👋"
s[s.findFirst(substring: "world")!...] // "world! Welcome to StringZilla. 👋")    
s[s.findLast(substring: "o")!...] // "o StringZilla. 👋")
s[s.findFirst(characterFrom: "aeiou")!...] // "ello, world! Welcome to StringZilla. 👋")
s[s.findLast(characterFrom: "aeiou")!...] // "a. 👋")
s[s.findFirst(characterNotFrom: "aeiou")!...] // "Hello, world! Welcome to StringZilla. 👋"
s.editDistance(from: "Hello, world!")! // 29

Algorithms & Design Decisions 📚

StringZilla aims to optimize some of the slowest string operations. Some popular operations, however, like equality comparisons and relative order checking, almost always complete on some of the very first bytes in either string. In such operations vectorization is almost useless, unless huge and very similar strings are considered. StringZilla implements those operations as well, but won't result in substantial speedups.

Exact Substring Search

Substring search algorithms are generally divided into: comparison-based, automaton-based, and bit-parallel. Different families are effective for different alphabet sizes and needle lengths. The more operations are needed per-character - the more effective SIMD would be. The longer the needle - the more effective the skip-tables are. StringZilla uses different exact substring search algorithms for different needle lengths and backends:

  • When no SIMD is available - SWAR (SIMD Within A Register) algorithms are used on 64-bit words.
  • Boyer-Moore-Horspool (BMH) algorithm with Raita heuristic variation for longer needles.
  • SIMD algorithms are randomized to look at different parts of the needle.

On very short needles, especially 1-4 characters long, brute force with SIMD is the fastest solution. On mid-length needles, bit-parallel algorithms are effective, as the character masks fit into 32-bit or 64-bit words. Either way, if the needle is under 64-bytes long, on haystack traversal we will still fetch every CPU cache line. So the only way to improve performance is to reduce the number of comparisons. The snippet below shows how StringZilla accomplishes that for needles of length two.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L1585-L1637

Going beyond that, to long needles, Boyer-Moore (BM) and its variants are often the best choice. It has two tables: the good-suffix shift and the bad-character shift. Common choice is to use the simplified BMH algorithm, which only uses the bad-character shift table, reducing the pre-processing time. We do the same for mid-length needles up to 256 bytes long. That way the stack-allocated shift table remains small.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1774-L1825

In the C++ Standards Library, the std::string::find function uses the BMH algorithm with Raita's heuristic. Before comparing the entire string, it matches the first, last, and the middle character. Very practical, but can be slow for repetitive characters. Both SWAR and SIMD backends of StringZilla have a cheap pre-processing step, where we locate unique characters. This makes the library a lot more practical when dealing with non-English corpora.

https://github.com/ashvardanian/StringZilla/blob/46e957cd4f9ecd4945318dd3c48783dd11323f37/include/stringzilla/stringzilla.h#L1398-L1431

All those, still, have $O(hn)$ worst case complexity. To guarantee $O(h)$ worst case time complexity, the Apostolico-Giancarlo (AG) algorithm adds an additional skip-table. Preprocessing phase is $O(n+sigma)$ in time and space. On traversal, performs from $(h/n)$ to $(3h/2)$ comparisons. It however, isn't practical on modern CPUs. A simpler idea, the Galil-rule might be a more relevant optimizations, if many matches must be found.

Other algorithms previously considered and deprecated:

  • Apostolico-Giancarlo algorithm for longer needles. Control-flow is too complex for efficient vectorization.
  • Shift-Or-based Bitap algorithm for short needles. Slower than SWAR.
  • Horspool-style bad-character check in SIMD backends. Effective only for very long needles, and very uneven character distributions between the needle and the haystack. Faster "character-in-set" check needed to generalize.

§ Reading materials. Exact String Matching Algorithms in Java. SIMD-friendly algorithms for substring searching.

Levenshtein Edit Distance

Levenshtein distance is the best known edit-distance for strings, that checks, how many insertions, deletions, and substitutions are needed to transform one string to another. It's extensively used in approximate string-matching, spell-checking, and bioinformatics.

The computational cost of the Levenshtein distance is $O(n * m)$, where $n$ and $m$ are the lengths of the string arguments. To compute that, the naive approach requires $O(n * m)$ space to store the "Levenshtein matrix", the bottom-right corner of which will contain the Levenshtein distance. The algorithm producing the matrix has been simultaneously studied/discovered by the Soviet mathematicians Vladimir Levenshtein in 1965, Taras Vintsyuk in 1968, and American computer scientists - Robert Wagner, David Sankoff, Michael J. Fischer in the following years. Several optimizations are known:

  1. Space Optimization: The matrix can be computed in $O(min(n,m))$ space, by only storing the last two rows of the matrix.
  2. Divide and Conquer: Hirschberg's algorithm can be applied to decompose the computation into subtasks.
  3. Automata: Levenshtein automata can be effective, if one of the strings doesn't change, and is a subject to many comparisons.
  4. Shift-Or: Bit-parallel algorithms transpose the matrix into a bit-matrix, and perform bitwise operations on it.

The last approach is quite powerful and performant, and is used by the great RapidFuzz library. It's less known, than the others, derived from the Baeza-Yates-Gonnet algorithm, extended to bounded edit-distance search by Manber and Wu in 1990s, and further extended by Gene Myers in 1999 and Heikki Hyyro between 2002 and 2004.

StringZilla introduces a different approach, extensively used in Unum's internal combinatorial optimization libraries. The approach doesn't change the number of trivial operations, but performs them in a different order, removing the data dependency, that occurs when computing the insertion costs. This results in much better vectorization for intra-core parallelism and potentially multi-core evaluation of a single request.

Next design goals:

  • Generalize fast traversals to rectangular matrices.
  • Port x86 AVX-512 solution to Arm NEON.

§ Reading materials. Faster Levenshtein Distances with a SIMD-friendly Traversal Order.

Needleman-Wunsch Alignment Score for Bioinformatics

The field of bioinformatics studies various representations of biological structures. The "primary" representations are generally strings over sparse alphabets:

  • DNA sequences, where the alphabet is {A, C, G, T}, ranging from ~100 characters for short reads to 3 billion for the human genome.
  • RNA sequences, where the alphabet is {A, C, G, U}, ranging from ~50 characters for tRNA to thousands for mRNA.
  • Proteins, where the alphabet is made of 22 amino acids, ranging from 2 characters for dipeptide to 35,000 for Titin, the longest protein.

The shorter the representation, the more often researchers may want to use custom substitution matrices. Meaning that the cost of a substitution between two characters may not be the same for all pairs.

StringZilla adapts the fairly efficient two-row Wagner-Fisher algorithm as a baseline serial implementation of the Needleman-Wunsch score. It supports arbitrary alphabets up to 256 characters, and can be used with either BLOSUM, PAM, or other substitution matrices. It also uses SIMD for hardware acceleration of the substitution lookups. This however, does not yet break the data-dependency for insertion costs, where 80% of the time is wasted. With that solved, the SIMD implementation will become 5x faster than the serial one.

Random Generation

Generating random strings from different alphabets is a very common operation. StringZilla accepts an arbitrary Pseudorandom Number Generator to produce noise, and an array of characters to sample from. Sampling is optimized to avoid integer division, a costly operation on modern CPUs. For that a 768-byte long lookup table is used to perform 2 lookups, 1 multiplication, 2 shifts, and 2 accumulations.

https://github.com/ashvardanian/StringZilla/blob/266c01710dddf71fc44800f36c2f992ca9735f87/include/stringzilla/stringzilla.h#L2490-L2533

Sorting

For lexicographic sorting of strings, StringZilla uses a "hybrid-hybrid" approach with $O(n * log(n))$ and.

  1. Radix sort for first bytes exported into a continuous buffer for locality.
  2. IntroSort on partially ordered chunks to balance efficiency and worst-case performance.
    1. IntroSort begins with a QuickSort.
    2. If the recursion depth exceeds a certain threshold, it switches to a HeapSort.

Next design goals:

  • Generalize to arrays with over 4 billion entries.
  • Algorithmic improvements may yield another 3x performance gain.
  • SIMD-acceleration for the Radix slice.

Hashing

[!WARNING] Hash functions are not cryptographically safe and are currently under active development. They may change in future minor releases.

Choosing the right hashing algorithm for your application can be crucial from both performance and security standpoint. In StringZilla a 64-bit rolling hash function is reused for both string hashes and substring hashes, Rabin-style fingerprints. Rolling hashes take the same amount of time to compute hashes with different window sizes, and are fast to update. Those are not however perfect hashes, and collisions are frequent. StringZilla attempts to use SIMD, but the performance is not yet satisfactory. On Intel Sapphire Rapids, the following numbers can be expected for N-way parallel variants.

  • 4-way AVX2 throughput with 64-bit integer multiplication (no native support): 0.28 GB/s.
  • 4-way AVX2 throughput with 32-bit integer multiplication: 0.54 GB/s.
  • 4-way AVX-512DQ throughput with 64-bit integer multiplication: 0.46 GB/s.
  • 4-way AVX-512 throughput with 32-bit integer multiplication: 0.58 GB/s.
  • 8-way AVX-512 throughput with 32-bit integer multiplication: 0.11 GB/s.

Next design goals:

  • Try gear-hash and other rolling approaches.

Why not CRC32?

Cyclic Redundancy Check 32 is one of the most commonly used hash functions in Computer Science. It has in-hardware support on both x86 and Arm, for both 8-bit, 16-bit, 32-bit, and 64-bit words. The 0x1EDC6F41 polynomial is used in iSCSI, Btrfs, ext4, and the 0x04C11DB7 in SATA, Ethernet, Zlib, PNG. In case of Arm more than one polynomial is supported. It is, however, somewhat limiting for Big Data usecases, which often have to deal with more than 4 Billion strings, making collisions unavoidable. Moreover, the existing SIMD approaches are tricky, combining general purpose computations with specialized instructions, to utilize more silicon in every cycle.

§ Reading materials. Comprehensive derivation of approaches Faster computation for 4 KB buffers on x86 Comparing different lookup tables Great open-source implementations. By Peter Cawley By Stephan Brumme

Other Modern Alternatives

MurmurHash from 2008 by Austin Appleby is one of the best known non-cryptographic hashes. It has a very short implementation and is capable of producing 32-bit and 128-bit hashes. The CityHash from 2011 by Google and the xxHash improve on that, better leveraging the super-scalar nature of modern CPUs and producing 64-bit and 128-bit hashes.

Neither of those functions are cryptographic, unlike MD5, SHA, and BLAKE algorithms. Most of cryptographic hashes are based on the Merkle-Damgård construction, and aren't resistant to the length-extension attacks. Current state of the Art, might be the BLAKE3 algorithm. It's resistant to a broad range of attacks, can process 2 bytes per CPU cycle, and comes with a very optimized official implementation for C and Rust. It has the same 128-bit security level as the BLAKE2, and achieves its performance gains by reducing the number of mixing rounds, and processing data in 1 KiB chunks, which is great for longer strings, but may result in poor performance on short ones.

All mentioned libraries have undergone extensive testing and are considered production-ready. They can definitely accelerate your application, but so may the downstream mixer. For instance, when a hash-table is constructed, the hashes are further shrunk to address table buckets. If the mixer looses entropy, the performance gains from the hash function may be lost. An example would be power-of-two modulo, which is a common mixer, but is known to be weak. One alternative would be the fastrange by Daniel Lemire. Another one is the Fibonacci hash trick using the Golden Ratio, also used in StringZilla.

Unicode, UTF-8, and Wide Characters

Most StringZilla operations are byte-level, so they work well with ASCII and UTF8 content out of the box. In some cases, like edit-distance computation, the result of byte-level evaluation and character-level evaluation may differ. So StringZilla provides following functions to work with Unicode:

  • sz_edit_distance_utf8 - computes the Levenshtein distance between two UTF-8 strings.
  • sz_hamming_distance_utf8 - computes the Hamming distance between two UTF-8 strings.

Java, JavaScript, Python 2, C#, and Objective-C, however, use wide characters (wchar) - two byte long codes, instead of the more reasonable fixed-length UTF32 or variable-length UTF8. This leads to all kinds of offset-counting issues when facing four-byte long Unicode characters. So consider transcoding with simdutf, if you are coming from such environments.

Contributing 👾

Please check out the contributing guide for more details on how to setup the development environment and contribute to this project. If you like this project, you may also enjoy USearch, UCall, UForm, and SimSIMD. 🤗

If you like strings and value efficiency, you may also enjoy the following projects:

  • simdutf - transcoding UTF8, UTF16, and UTF32 LE and BE.
  • hyperscan - regular expressions with SIMD acceleration.
  • pyahocorasick - Aho-Corasick algorithm in Python.
  • rapidfuzz - fast string matching in C++ and Python.

If you are looking for more reading materials on this topic, consider the following:

License 📜

Feel free to use the project under Apache 2.0 or the Three-clause BSD license at your preference.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

stringzilla-3.9.7-cp312-cp312-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.12 Windows ARM64

stringzilla-3.9.7-cp312-cp312-win_amd64.whl (73.0 kB view details)

Uploaded CPython 3.12 Windows x86-64

stringzilla-3.9.7-cp312-cp312-win32.whl (64.4 kB view details)

Uploaded CPython 3.12 Windows x86

stringzilla-3.9.7-cp312-cp312-musllinux_1_2_x86_64.whl (255.6 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp312-cp312-musllinux_1_2_s390x.whl (194.9 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp312-cp312-musllinux_1_2_ppc64le.whl (217.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp312-cp312-musllinux_1_2_i686.whl (200.0 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp312-cp312-musllinux_1_2_aarch64.whl (206.1 kB view details)

Uploaded CPython 3.12 musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (260.2 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.5 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (220.7 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.3 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.5 kB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp312-cp312-macosx_11_0_arm64.whl (74.1 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

stringzilla-3.9.7-cp312-cp312-macosx_10_13_x86_64.whl (74.0 kB view details)

Uploaded CPython 3.12 macOS 10.13+ x86-64

stringzilla-3.9.7-cp312-cp312-macosx_10_13_universal2.whl (113.1 kB view details)

Uploaded CPython 3.12 macOS 10.13+ universal2 (ARM64, x86-64)

stringzilla-3.9.7-cp311-cp311-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.11 Windows ARM64

stringzilla-3.9.7-cp311-cp311-win_amd64.whl (72.9 kB view details)

Uploaded CPython 3.11 Windows x86-64

stringzilla-3.9.7-cp311-cp311-win32.whl (64.3 kB view details)

Uploaded CPython 3.11 Windows x86

stringzilla-3.9.7-cp311-cp311-musllinux_1_2_x86_64.whl (255.1 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp311-cp311-musllinux_1_2_s390x.whl (194.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp311-cp311-musllinux_1_2_ppc64le.whl (217.7 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp311-cp311-musllinux_1_2_i686.whl (200.1 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp311-cp311-musllinux_1_2_aarch64.whl (206.3 kB view details)

Uploaded CPython 3.11 musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (259.5 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (192.6 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (221.2 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (210.7 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (198.3 kB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp311-cp311-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

stringzilla-3.9.7-cp311-cp311-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

stringzilla-3.9.7-cp311-cp311-macosx_10_9_universal2.whl (112.6 kB view details)

Uploaded CPython 3.11 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.7-cp310-cp310-win_arm64.whl (62.8 kB view details)

Uploaded CPython 3.10 Windows ARM64

stringzilla-3.9.7-cp310-cp310-win_amd64.whl (72.7 kB view details)

Uploaded CPython 3.10 Windows x86-64

stringzilla-3.9.7-cp310-cp310-win32.whl (64.2 kB view details)

Uploaded CPython 3.10 Windows x86

stringzilla-3.9.7-cp310-cp310-musllinux_1_2_x86_64.whl (252.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp310-cp310-musllinux_1_2_s390x.whl (191.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp310-cp310-musllinux_1_2_ppc64le.whl (214.9 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp310-cp310-musllinux_1_2_i686.whl (197.8 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp310-cp310-musllinux_1_2_aarch64.whl (203.6 kB view details)

Uploaded CPython 3.10 musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (257.2 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (190.1 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (218.3 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (208.3 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (195.8 kB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp310-cp310-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

stringzilla-3.9.7-cp310-cp310-macosx_10_9_x86_64.whl (73.6 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

stringzilla-3.9.7-cp310-cp310-macosx_10_9_universal2.whl (112.6 kB view details)

Uploaded CPython 3.10 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.7-cp39-cp39-win_arm64.whl (62.9 kB view details)

Uploaded CPython 3.9 Windows ARM64

stringzilla-3.9.7-cp39-cp39-win_amd64.whl (73.1 kB view details)

Uploaded CPython 3.9 Windows x86-64

stringzilla-3.9.7-cp39-cp39-win32.whl (64.3 kB view details)

Uploaded CPython 3.9 Windows x86

stringzilla-3.9.7-cp39-cp39-musllinux_1_2_x86_64.whl (251.4 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp39-cp39-musllinux_1_2_s390x.whl (190.5 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp39-cp39-musllinux_1_2_ppc64le.whl (213.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp39-cp39-musllinux_1_2_i686.whl (196.7 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp39-cp39-musllinux_1_2_aarch64.whl (202.6 kB view details)

Uploaded CPython 3.9 musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (256.0 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (188.8 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (216.9 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (207.1 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (194.7 kB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp39-cp39-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.9 macOS 11.0+ ARM64

stringzilla-3.9.7-cp39-cp39-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.9 macOS 10.9+ x86-64

stringzilla-3.9.7-cp39-cp39-macosx_10_9_universal2.whl (112.5 kB view details)

Uploaded CPython 3.9 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.7-cp38-cp38-win_amd64.whl (72.8 kB view details)

Uploaded CPython 3.8 Windows x86-64

stringzilla-3.9.7-cp38-cp38-win32.whl (64.3 kB view details)

Uploaded CPython 3.8 Windows x86

stringzilla-3.9.7-cp38-cp38-musllinux_1_2_x86_64.whl (250.5 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp38-cp38-musllinux_1_2_s390x.whl (189.3 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp38-cp38-musllinux_1_2_ppc64le.whl (212.8 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp38-cp38-musllinux_1_2_i686.whl (196.0 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp38-cp38-musllinux_1_2_aarch64.whl (201.7 kB view details)

Uploaded CPython 3.8 musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (255.3 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (187.8 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (215.9 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (206.0 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (193.7 kB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp38-cp38-macosx_11_0_arm64.whl (73.9 kB view details)

Uploaded CPython 3.8 macOS 11.0+ ARM64

stringzilla-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl (73.7 kB view details)

Uploaded CPython 3.8 macOS 10.9+ x86-64

stringzilla-3.9.7-cp38-cp38-macosx_10_9_universal2.whl (112.5 kB view details)

Uploaded CPython 3.8 macOS 10.9+ universal2 (ARM64, x86-64)

stringzilla-3.9.7-cp37-cp37m-win_amd64.whl (72.8 kB view details)

Uploaded CPython 3.7m Windows x86-64

stringzilla-3.9.7-cp37-cp37m-win32.whl (64.3 kB view details)

Uploaded CPython 3.7m Windows x86

stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_x86_64.whl (248.9 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_s390x.whl (188.0 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_ppc64le.whl (210.8 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_i686.whl (194.2 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_aarch64.whl (199.4 kB view details)

Uploaded CPython 3.7m musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.8 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (186.1 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.9 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (203.6 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.8 kB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp37-cp37m-macosx_10_9_x86_64.whl (73.5 kB view details)

Uploaded CPython 3.7m macOS 10.9+ x86-64

stringzilla-3.9.7-cp36-cp36m-win_amd64.whl (72.7 kB view details)

Uploaded CPython 3.6m Windows x86-64

stringzilla-3.9.7-cp36-cp36m-win32.whl (64.2 kB view details)

Uploaded CPython 3.6m Windows x86

stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_x86_64.whl (248.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ x86-64

stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_s390x.whl (187.3 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ s390x

stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_ppc64le.whl (210.1 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ppc64le

stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_i686.whl (193.5 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ i686

stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_aarch64.whl (198.7 kB view details)

Uploaded CPython 3.6m musllinux: musl 1.2+ ARM64

stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (253.0 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64 manylinux: glibc 2.28+ x86-64

stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl (185.1 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ s390x manylinux: glibc 2.28+ s390x

stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl (213.5 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ppc64le manylinux: glibc 2.28+ ppc64le

stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl (202.7 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ ARM64 manylinux: glibc 2.28+ ARM64

stringzilla-3.9.7-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl (191.3 kB view details)

Uploaded CPython 3.6m manylinux: glibc 2.17+ i686 manylinux: glibc 2.5+ i686

stringzilla-3.9.7-cp36-cp36m-macosx_10_9_x86_64.whl (73.3 kB view details)

Uploaded CPython 3.6m macOS 10.9+ x86-64

File details

Details for the file stringzilla-3.9.7-cp312-cp312-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-win_arm64.whl
Algorithm Hash digest
SHA256 d7ad78b6b6a7e82e9c31177afcf0c581728ddf44c9e35de3d121ad19536b101e
MD5 3f3b4a339d3e2f490850fcd07908da05
BLAKE2b-256 9cabd3f6c8ffb11ef4a2ab8229b493b079fe8ccfb17a5d323e2c88fb260985a8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 9ae196269f910f55eb7671e399ffd785943cf9847f6d6c1da930f41ff2f59102
MD5 5b5dee32e893964af37ec9ecd1f96e50
BLAKE2b-256 512711d673f451e9905ce15d1fd04c0a375eee165664504bfad2a632e231155b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp312-cp312-win32.whl
  • Upload date:
  • Size: 64.4 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 d93626010883e55eaaf398ee68f18b4439f55fe22a875515c4b481ff54762ac4
MD5 1c6e41423db43584a2c6a3fa9b9e302c
BLAKE2b-256 a3365d6cc0b30c1e5559e13e60a22bae683d75c38e079205f8629e5a30572802

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 dd93141985cf001bd85ce0aa7fd0f7b19dba3d378a14eb92177e1b41bc49347e
MD5 1bf70d0689b4f7d8177f83bd601d9f7b
BLAKE2b-256 289ec11a5673a0e84484ac560dafe981b670c40ccd7c4838ea8860d4a1cf70ff

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 e1606521ae7f893d7be2c479cc3685af68745e0cee37622f8f5ca4bef46925ad
MD5 70ca9b536681fd7254bb09bdaf3bf0d5
BLAKE2b-256 c4741f15e607c8b0f1d4d3f47a506b258ba9ed325aa9ba799d3b4410dfa85a19

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 3540a32fc8091d7ffa4ffdd4c1b1de00b62fb42e57efd5b968c370024eefba15
MD5 5addc15a1ba04bc86fca46c27c5d7f33
BLAKE2b-256 70dc87c0823d2eea5f5656f548560f3c5731b603cb9da775cb5b6d98b838a527

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 9974f30ff1fc99a2356f089fa0a314d8466d3da175db458ed1349ed623d60ec2
MD5 c964cbcfc5ea91e90b7d4bbf9d93c106
BLAKE2b-256 b95d8821a1cb84d678a7988e9777357a31efc8ae10ad43ecd03febf8fe23c0d9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 628d678291f737eb89ea0bea1948c4114baf198d8c3a7c744728f93edbbdd4d4
MD5 0bc39388d8e733cb77af4ab02dd37650
BLAKE2b-256 39fd273aebec0d13e52db32f7e07e31eb1816d072abd95543721c5f32460e7af

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 cc81d67d00cac79dce61c63fd09d69d769fb01f6b74fb2956d96bc46f1756ea2
MD5 0a462bb4b1a21a2a98fef3047dadd3fd
BLAKE2b-256 1b12a3ad7123d0ff1cdda782104dd5355075f8b90ded3971667cdb0dbb570b76

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 ed2d1502ffff6351f9c46dcf3e43c61e3abab729ca19290436d5665ad40e1fdc
MD5 e9f1d61422bc3972eb1d3416af808a5b
BLAKE2b-256 31c57153b10670b4145625a9273990d75b5d979cd553c786a24a33899313f542

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 6a5783f577c22de1b5464c78c3ea22d56687d47f524f9fe13fcfbb33887a6346
MD5 ec9dacec4db0b248cff315c28400832d
BLAKE2b-256 2ab3dbbc14193db2709c84ec1a36c8e4797308e832ea016c3a89b0c86c65a512

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f4da239d0cd235ec41195d41780e338f885786f3aebdd4e6b91c5f70ace00af8
MD5 023954b2f82d7a150f71d8e6da8d3ee5
BLAKE2b-256 0d7c6f9f222bc5053053de0b4e94c48cbe30f09be05d4afecaaee94c00ce383d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c7c5bc562fb1bec4e714b323d543d4f889f1a9066710bf99dc3b872f0a5ac710
MD5 8533963615adc67a536f340a0423b829
BLAKE2b-256 ed2e4df68f4eb9878d87b2cdfb93af260642bc9a639f4d9b6d1fe646ae2b76a6

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bc90fa0455ddf3009810f6ba2fd4d103b458642b0d4ed67ce49a1f86e61f00f7
MD5 6329564c6a73915549f579b455ba63de
BLAKE2b-256 f66fb9a1a337bc99657bca0d663ac4a863886058a2f97066cd019823cccc256e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 066b3050c85d607fbee58d63878d55c83626794d0384bb5d6957760e64c5eace
MD5 40bd5e120b77a6ef59307214b363038b
BLAKE2b-256 1be5bdbd68197647fb2da598a1bfb24dd1ed12a7a18208b4e2038e3b1e0850e5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp312-cp312-macosx_10_13_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp312-cp312-macosx_10_13_universal2.whl
Algorithm Hash digest
SHA256 a65ebb57bd63991e1db87c6746be1e273a9f1f4d6ce337180d13a2df43573490
MD5 aff35c222771651a534133d1362c0a5f
BLAKE2b-256 6d432dbcd729f4dcb7542b740b458ee2076bcf34b231d93a8c0c749d2cce5ef9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-win_arm64.whl
Algorithm Hash digest
SHA256 cf78eedd903730320ac7a54a8403b3375653053ee91e0b74fc4ad7702dd06e7a
MD5 2f0f08e61957d746c1e8d7a9f3e03cf0
BLAKE2b-256 b2026d999e2ca87de891ba8c29f6beb499818c77717f725d3d07c3dc37c463b7

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 ef71454cc0d345b9f6cbe5dc13b98a41b055e1fc4abfac663907a064cfdb4b8c
MD5 510ca014c30f851e2f358bfe19a28292
BLAKE2b-256 78ca38e432fb7d67c53238d96bf863d11bbfced126042f69c0ef6d1348810cdf

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp311-cp311-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 d4e56dc9654193da058002db5d69498c04b13aa5a131be13b4c9ab5004d08408
MD5 744bf9868f93cb2f2ea33dec354ba20f
BLAKE2b-256 b1b08c9850142c410e99fd8770f926bfc7c1affd59f3c3417f0b8bfde4acb6b3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 224c16edb80820bb62a2f01e78e8b2f999629f93849f5803d6cdf5a0f1cc8d1b
MD5 7cb05a2e63f63f1ed1b10d013901973d
BLAKE2b-256 698d6c2c99907f2874f62134938b9c3fe9686f1720bb92abcbd7d77804c3639b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 98fe541c0f880d159b8413de7b604bf1c14a8bd24c1edbfad7a1530d9b2f8ebd
MD5 2730e3a8c742cebd420181b7e1887235
BLAKE2b-256 2bfd41544fe4963fdd532167ad87ef3769d4b92bdbc4d56f972848abd0401e8d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 246c9b40510d6dbd5a96b3495bd5fa27632a33b1f3b802121de940257a505b90
MD5 51ff2a91da673a8298c3cdc2546719b7
BLAKE2b-256 b26436835e002e2a8004964b0ab68282953a3b039df36f91a064c5bb8d7c4b2b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 d29ff6f199f4874b73f5687c5b0802c928cbd6c33366cc263aa124f80d4cdca2
MD5 8808a7f5e600d70c8fdd6b8ec84e6953
BLAKE2b-256 26fd464f3ebc125e3b4a6efe25e6c94a2165b3a77bc1f7d2d9ca82c30a34e762

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 03cc486143cc2ab429c37ec53fef54bd178989590b6de5e14cb18c3fb40ebcf4
MD5 68084ca0db54199af21592c5f103ccbe
BLAKE2b-256 2046cd27ee5ab5fef014c1f89574342428a24d6e2da9d28ba5cfcbabed2c99c3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d533a4375676d96f6adcb61cfd3930ab2fe2c7983675c97e82cde2a8b50c918f
MD5 b4cb43153df35897c6b0e035b3b8811b
BLAKE2b-256 d90465212094fb1bcf7d9aa705389fb8ff0537e417c3ccd006876bb50e380589

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 add091be68b9769674fd493b9db22b07a28d6d3ea5ad67b9ce906fad860cba10
MD5 61f516dabbb100bb1e0fdbcc84e25a26
BLAKE2b-256 826502560a3b1c888839a18525acb29fbe3ff6712f3c1061d72abe5c0147321d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 2d0a9a3e9b7a40c0cc8b9535e1e981d2f1875d1d0f4eeb7d7b5d7ec7618e8cc5
MD5 b52d75c9821a8e50cd5d553d8394c9b2
BLAKE2b-256 45a6e4ce505aedc93d8afe92a5ddba4b84693a490d5427b7251904659df7bebf

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 972a77f0a989f7bfb0731ebc188c004c0bfc1d47455102dde6559d8a90367113
MD5 40de662a68c0a99294bff21d64acf18a
BLAKE2b-256 8ccd097f70cfc2f3f91f067c769b9afeab455f15b68533a7fd726a19c15ac660

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 31d40307403e5cbaf7da4e3943890561e5c643d1e1e38216fda531c1617723aa
MD5 bab253f60082d5c269f3e4c1a0031c11
BLAKE2b-256 d5c926d898a2388b29eef2ef6d264d63d0ba19a6addb63d602fb08a01afe2e1c

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 57d81a01ac6d5ee1160424bd9c5e12098fd6782716689c1be2a5a0ec8408ac0d
MD5 80dffd111f32340b3655c6a4864f2a64
BLAKE2b-256 d35eb5350aea2c2e1450dfebc172c7abbaaf7e2681b6935fac4d0c9669b30f5f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 24cec6dc3edb8ac89e8ae0aa64e5475947cbb45a0679529ee3df4a45ab6649c2
MD5 e128c93f2fa7d5f1be7a1c98f2bd5fe4
BLAKE2b-256 eec87376d74dc5e174d894cc8a5ef96d79b8f8547048b0ab0da37988d43f34ea

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp311-cp311-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp311-cp311-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 78d604a0597c14c8732f2fc1bf94648c2c333bbcd4acb3c1d93da162781653a3
MD5 c11196d862d8f48ba6781aa3a53219b5
BLAKE2b-256 45a36e11cc838523d769dbd7d787b3aab6b470f19dfd113ba618af7c106f84a8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-win_arm64.whl
Algorithm Hash digest
SHA256 131242f53a77d2ae5b9379e4d8af3d7390acadc71e628caa2b339edf03b23991
MD5 38a763f1d032145e4972cbaae25a61c2
BLAKE2b-256 6c1e7e0951fdb53bd37d8b5c629aa476f725b4af83db8e140caf1b771564ecbf

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 fb7bec53d9ff9d1e90cc6425769a5aac03a570dabe39dc89734786e1ba27c203
MD5 4df201110fdf1ece2ae540cd3c6dbeb8
BLAKE2b-256 4499b9ff74277c48fc01e9df94e9f85c2af578a1fd0798e109f79fa38a51d46f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp310-cp310-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 8816bfae11f8e2da750d9868940d767e9a4a52056286a929362486a5fda56562
MD5 906d55d18d02fb82caf77cbdb2960381
BLAKE2b-256 290903055408ecb66a91a6a3ebd71323680e9b6f35ca0fac313c2c1467f81653

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d0457c4ce4bf9a11916b9cb41d3e416f01afa19356133f77b9f90e9395df378b
MD5 5051313fad0834d55862ac63d4b76c78
BLAKE2b-256 d0881379c408309e184fb59d96806dcba5981caabc16bd36978d62067df9864b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 2fcdc4df1bedb94cfcd27ab61a43d8fe1af31ad5ae74687652d8f0d46e0f2ab1
MD5 82edbfb1d6756dce2fbd05fb9a383d32
BLAKE2b-256 d117301ae81183cf3562d350d20aa60e2fec640f47c9d739535570b34bc4da7d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 d1e41041c24c0e327b975134cbc69439ad35445e3c5f4bd297aa51e0014b4d98
MD5 860a5793b7f7a8346a569ceb5fe1e176
BLAKE2b-256 8db8bd881b429fcda1ed8925e218f242fdcf4c668026179ab660914ed689ba0b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 93467e6fc5c323e78e2960daa8ff39f578e1f15c3bd915e72d3a5ffa97b7ec56
MD5 5541aa873e51a92ed74dfa4d1ace34ba
BLAKE2b-256 7b45501b5f452234301af318ac8d79fa8d1b807dc91ead14a9eeae6fae1c9e42

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 60169eca51d2ccc5e29f8425ce7ba8753cd366229e15b4a483ad6afaaaaca8e8
MD5 53872e2b48d8e9912f274706dbbdfeba
BLAKE2b-256 00b3333d69990f92ad0db9c9816706ea53316496a3c869bccbe30fbb70ebbd39

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0f8e7dbaf59b36bca768fbec353689dccf2ebd25d857e1d4c8395b63a7bef5f4
MD5 d1ca815db7f94274346a6ccb06c553a4
BLAKE2b-256 285b3049ff4951682d85b3029ff9c60376fcba29eb791a05d0332da9eb725481

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 2106449275175b6dd8318f7008d06ae56d1e766b9060668f6e8f9771b948eccc
MD5 7b8cfb74397ab26dc08e1f9fdef38266
BLAKE2b-256 353b1b3d7f5c0f9a5d438d41cf5f7cb200c4fca5c9a9b00adb0740ad1feb4a8d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c9c09feb79e93107e9a8571334b26baccac87d45257c7472a8cc4de59f786e83
MD5 1cb8d3d6c0257e3cdf3e3cff1e6167dc
BLAKE2b-256 88be0343d2dd0d627568cab88511df9d09681cebc3205da91f1a5c214956a20e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 415393bc237c83ab2d2f365ec9e8b4e0d4ee3f3c7b73218a4a494b02c93026ae
MD5 5d1e2f3b1e126d8e63db044ef176ecf5
BLAKE2b-256 6cc643487487f3e8ad2f9d150a5c0624286977b354420ff7ae8c7ec174ed14ad

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 7a00a0c4415291477471ad0dc313dad7ad53ce54bce0cc0cf13923f30643f89f
MD5 25e18c98baf5e4545f468738c2b718d3
BLAKE2b-256 4d31b47b6ee728f415240aa2d832af14bca24d5e5fecdba35e87b7c99aeec942

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8066def9239b0fe2ee4bc3ee81c1f6bf1fc6e2452cd6c08c0a09811bb10e674
MD5 4011a6bb1f669785dcc4ff6199ca6e64
BLAKE2b-256 592e6366abc75e255cedc90c99061dbe95ef629636a1a175839df3d9517bac62

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 011f10006aba399f0d9f1a93aac945f2e82d23862333d190f29e3fdf19902025
MD5 7325a4d9f6551a9b98421aa56a7cf2d1
BLAKE2b-256 6e40f4708388b38a2a86aaa5a762364a52773e71576cbed93526d4ac6061f6f3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp310-cp310-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp310-cp310-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 817b658b7b85fb4121ca4db5405956a49e68cf6ebf5ebc995d2a3c3232d16639
MD5 061aca82f9e5454afba20bff3b45e1ad
BLAKE2b-256 e15fe12388ad7f64afd7b4b15e8a2320842e4da810250cdf6002382ab12f3fb9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-win_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-win_arm64.whl
Algorithm Hash digest
SHA256 b646fdbbcde5f5c4229da257839aa44244d999e6cc2bd40edfdada58870a7b17
MD5 c36a15405ba919b95291d92cac0de35a
BLAKE2b-256 dec5a80ab271bf9a7387cb82d14f24a14d910d4252c221cb22b697b22acd5c79

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 b8956beebde587b99fcb83adba3babb5949675db28b5abfb93802802df996484
MD5 fb0e5eb8f1d39fa17e13a269696c6e9a
BLAKE2b-256 2137d98c6aa4734c986888278941ee808b893037344f2287dadf7fea410010f0

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp39-cp39-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-win32.whl
Algorithm Hash digest
SHA256 d54bf03058eb956474e240de195dd694e2e3ec8d20fd59aec9dece4147bffd8f
MD5 eca944234744319838d73cf6b45c735a
BLAKE2b-256 05cc034de920c7397d5a2815c0f2c666ec6e9a92fc6c99c0be2223af7b443256

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c6a91b8bd9d3757bbec642338baa6b2ee0a0fef65025876db5c358ad1562008c
MD5 01068fff3ce8fa04b464e6ded6c37e5a
BLAKE2b-256 0ec634b6ffdf191e3a5425bb9a592cecd74156af260a40f7b1c1699a6855ffca

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 55fffe0dd361fe2d959366c15034ad215d5ec6a188a1cbfd7b9d20db8045d7d6
MD5 3454023e214ead6cd50626a6b8ed9651
BLAKE2b-256 2bf2a33e263aa25097119e51f757f5f226c2ac2cba65ccbbd1d81ff000861f16

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 fd44fff27192cdf8c1fed72c136552384ef384042ec1ee66b59945a992550682
MD5 88c43ac45b1e912360b31e9e1414e042
BLAKE2b-256 41b1402f13cbf6f06e9c8d4c7e988948b2f89205a353210514ec463806c3eb26

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 414312cfe4fa228ec2f89f944139df82cdb6c2bbc503f1792b6e648af065356f
MD5 39c809222f062dffa90ed95f7839e9c8
BLAKE2b-256 6d487f302b1665eca253bf6c3faf7e8886a644a40b7b9f9025d3235524694c95

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 351532747fbf78e4e9e5186e418f88eeb73e82964171f8f6a0e957e925bd2c8b
MD5 d42a382a0cd075bbf8d80ca65924f5bf
BLAKE2b-256 71d4b4278ac2d0ac6c860e34181c3dee911b4dc680376cc1274de4944614f21d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 6460f8eaba0579fc89264b3f05cdb19801d58b710d0cf9631c83aaac0b3016ab
MD5 a4676c3388e8ccdd2c86e75898c2aff2
BLAKE2b-256 8bdeb5510e539a2cda73c5a0d22c92f93d1c1743d752ccd3c92c9be8eff6b9d8

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 e78551965ec84ec33dbccfea369e2b93e6d2ff809b123fb02feb6adab3288024
MD5 cd8dcca9598a4551ddbcbeb5d6c0c9dd
BLAKE2b-256 fe90865d801a85b4441f76a30e4ab94d0d39fe95585783bcdb061aeac2f38f2b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 d34db5e6c56b3c3e895832bb46f151f1339e235f64a444655ac4a7030415e8b1
MD5 a9f01ac3535f6a12f07f2245c0f91107
BLAKE2b-256 13deb117ff5c674111a03e7085dcdb30e8ac42ce04509c689cb613d99ca0e18d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6f735225dba593a9416d40aec34de88621205a3c809eb5d39bc2212008256195
MD5 45db432d72f1e80d9eadd456800add66
BLAKE2b-256 987808a31e38ade31bd366285dfdfb159b1ebc2204590a0afe3ac79d51c8daf4

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 859cdd08031dc930d602d7119c384e1cb5a5cfd830812454677cf498d467ac81
MD5 417464a6f777901e96b3f07641126c2f
BLAKE2b-256 97edaf9231d470c01381377b7c91998fd3e98115d0c19257adf169024ed7619d

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5914b3a1077bcddcfcfc157e14435b6c8dd0b055f175b8c43a886eb55ab3c2cf
MD5 43e5129d7d31eddefa24a658b7946a61
BLAKE2b-256 769a4f17ae9ff54e746c567f22a83d4e642ff2a1694454988eecd66044df9200

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 a61aa2211ff74a846fda1799adeeaa898804807564d86587497e846f72716f1a
MD5 1537c89b7ace2ba4d628e0805c9dc8e8
BLAKE2b-256 62579bfc1874051c77a7051648c71fde00fa4362fe1e2c6de244bfc21114ff18

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp39-cp39-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp39-cp39-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 242af18859f5e0b078fa11b8de85acfa58544ac9ab5caef0b33318a3e7706f3c
MD5 a07c8e3e1ba0c90cb67d0749265c0496
BLAKE2b-256 a9c3634838b7ed2ba68010bf59ed6fe2997403896b9b1c1d715ff70d1ae7c114

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 bc5dc3a3818f82d871f52fe693a25ec70ebdaa5fc403a833b8966a81c295b008
MD5 f039b420cb13b76459b87ae810198712
BLAKE2b-256 e384d42e73fc5e2e142578751a1e2f1020a06781f7b550f8b48f5eac4ada05e4

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp38-cp38-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.8, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-win32.whl
Algorithm Hash digest
SHA256 335f72138ae5c22074655ca981e541f394cfe1a291bca630df7d60724b7810f1
MD5 6fc5118c00fc41f83d9f8ba83221b546
BLAKE2b-256 7525e4d87cd81f2086d9340abe3857dd6e0d145efaa2affd30bc56cca7ad07ba

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 bf402ede2ef8511a197a772510535113a763921ee95e7f1851985f3ca6cae25b
MD5 3c5a499cde00af17b077da743defd855
BLAKE2b-256 402b24910875c3c30b043be43873b142a32cbb193ed9d12285b36949b87a7f30

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 1409430fa6647591bf750ac2e402f25ee2d3d0c92305ff1923f6bbebca46c62b
MD5 b7675153c131c45b1d7671a0c05ee341
BLAKE2b-256 dafe01a535300a480d9acbbd250c718eea395db310cae140803d293d2cb55944

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 4c2e6075805548e4fe9afecd628a93719ee538004d630dad714c69f0ba568c53
MD5 fc96f26d867483b42a2ee4ce60fe98a1
BLAKE2b-256 c6f04531a952ee54821e81d666b5b363c86bbfdadd303009e56b5eb9985279a3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3b81a429fda8fe2191e350ba396c6bf234e7778dd7b4110ae5ca4eb137d93acb
MD5 08cfaa4ad8418bbab6f73aa3db3f8a2a
BLAKE2b-256 b52aaef49b3ca5147298d1884ed9f00e20a56b2b41fbdcdf82d3a1b1f5f51b8c

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0471e3e27b993c02b2287a8508032e099578865edd5be4b8be34de375790836a
MD5 5ffa25ad2cb7fe2e5de4545b9b264b3b
BLAKE2b-256 cbc594d4c7057045c1c3a05a94a095ce6eef8c46dd140311551fe492573d5d47

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 61a5a59d531ab80593a912e62d5cc1dbec9394e029797ddbcbb5632f96de27dc
MD5 18fc861bc5ce541ba084eb2c1ff4fdf9
BLAKE2b-256 e0be8d140f46784287e37f534fe9c65e991cec2aedeb7ae9da8a4bcc64ced42c

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 8e08fabf6f56337b15d326d66afa8e7f2bcee38050c5f2776945de4083a9d2d9
MD5 e9d92b0d30bf7fe3bdcbbaf3f38c5e4a
BLAKE2b-256 249ecae74859ed4aae9fb7aa58f66030bde6b757083acdc42f205223bd316f1b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 49c42b6948190b418c1bbbc8af84ad71d824cc85b01623d2fc7ec677ba75509c
MD5 b7154ef6625bf48e4a7e478d74782c83
BLAKE2b-256 560ead781c7bdb0c12084012464942888989d1480642c34e08508b3b72b3b86f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a860ef99a4ce0f8a729a2fa41270cf12f5d0902e1b83a1a639850abc5da3b0dc
MD5 0dafff134e2361b298492fa8ed864dce
BLAKE2b-256 fde91d5291b5faa4166b60424e260230713110335fd47498aa38a95a157d2741

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 2fe2c2258d96ad04f7c085552650878d1ee01ddf63a4c3ba480e805288383cde
MD5 cb201e14f91f0651663b074dea7607d0
BLAKE2b-256 91d46cf3d0ec6940e5ed4b9b5ea1f23561242d718f732e785776ef9b624c2ae5

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d1371d332eecf0386a1addbb50efdf70234faed785c8b489b45339e625354ccc
MD5 e04e64a60cbeaf4fb5115a14aaebcea7
BLAKE2b-256 51491e97f2f062eaf250be762e1695d59b98fc80a84427f6dd177cc828c8d724

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 da5972c1cd52f9951286e051a0b4b6e3e608490cd2c475e3d99e795ca27e7e36
MD5 93b07eed490a7f51f08fea3198ef0e50
BLAKE2b-256 4d4caed8d01d780bbe6025d811d6b148d397136d8a10ffa494fe1a555bc5292a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp38-cp38-macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp38-cp38-macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 bd10924c9a837d3814970f08f10d5404dffa5a0b0bb8a7b5d2a0765635471d88
MD5 ec78476b17cd1d7cecba83c5368999a4
BLAKE2b-256 434c9c53094799a0fdd00245eaf634937906c881fcf5dbe9b5152e0263d17790

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 77032193f64b1e6246f063b52583cd02498a16ffc897fc804030007955dbce9d
MD5 fc73ab1cb5bd4d5bc0d664bed9847730
BLAKE2b-256 9a68aa95acb49d2151d38be40c6af6231867f0bad2f9d87f86f214183377f75f

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp37-cp37m-win32.whl
  • Upload date:
  • Size: 64.3 kB
  • Tags: CPython 3.7m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-win32.whl
Algorithm Hash digest
SHA256 56666ae11e09ba82e8857a778a8f130eee218e64402c9e785afc721b12ec430e
MD5 226f00a71857395404763e1526e1a22d
BLAKE2b-256 c5824258bd6269a0cf8c32c166b762dead16c7637793be71897aa7d6fec13180

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2349168af019ca57ff51aa9487e967a1a53b9aac2bd4934d44e97c13b6dd2143
MD5 00bd870729e95a4d275fc05d2ea545e5
BLAKE2b-256 d53ce8f7ea6d3586d0545948fd3875efbe7ae35a240ca6401e5b4410ba591d47

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 f4f72e9992e98944f1b6bb866355b1ecd3bee860a815f74097494ca5151effc0
MD5 e415d38bb968a08cdb9596d5d2b511ca
BLAKE2b-256 b6bde6c1a45d9288f1c137aca946f21e0592904ed0ad5d13e8f23535816286a3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 51bf4b84410f64899c7d2e8a8d3fe7ad56af537f5cb94cdca63b13fc09828ca4
MD5 f4e7d596ad99270dc50b3aa51489f170
BLAKE2b-256 3747ef5ad93c1f21ada984891eb1d400be84511fa6e5595d383171dc7747ea77

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 84b1263ff08e1ae95b3095037bf7a82de7d5f8d5ac5c879f6d40fa4277ad0177
MD5 e221df88dd0f264aeb031baae1747df7
BLAKE2b-256 6945bcd373031b3e520242efa82a14bcfef7d12781919717875c0e74a1f56ff0

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f6a0a2a9a68f46e6c1a4ea6a46d63503e7036f26a93cef3a7d99399d489b7851
MD5 9bb6e30045fade46b12665422c7c5bee
BLAKE2b-256 8ae0671d63f5c56d6ada91602b9f757621e98046ecaf6692518b43ffb83a40d3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d7136804ed6a74ab8dde6ac9e38b582b4b1cd0caaa06dc6ed51b22fe974ec950
MD5 4541359d79da7376ee021dcdf5286e4c
BLAKE2b-256 30506aea082e9bdd4c0faeddcd4134890bab8c3fa82ee043bd9782a071d109bd

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 1f828fd83b70fc8c07ad7b80659eeed5043e7f019175020b6a2a8b10bbc7f387
MD5 07c816e91b742192c63ddff420695446
BLAKE2b-256 db82f9f365e128eaea448401a38a014a63da63ac454ca762fd28105e42494e26

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 c97b7318f54c63c032eeb90b34206ea9541daf8796c58f523e33f98c15bfd8ae
MD5 8ffcfbb40675c89394d895caec1bb4c5
BLAKE2b-256 68ded17d060599f352dea59d66253faca945e92437aa37239c637f5fd2ef0d87

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 66e4d8fb8d4fd6fa98d50d468254aa8c1354927ee6238e5777b239801c15027d
MD5 59aff404d80557be21e566dcf739d3be
BLAKE2b-256 08d127d8e13bcff9f9601372613563d44db53c9b774a15614a731374f1f9a665

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 a1d4e10106ba24470ae25077a8053007437c22bef62cd5de53860799c7a717e8
MD5 2bd90a07bacd521af74cb7b246803554
BLAKE2b-256 7487282b92e8b619b4298fa218d8e5403a307b826bb03bb84d1b4395277fc755

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp37-cp37m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 ab58960dffbc15952148d1f9b4282246efc49e484ffcef61dd144fc246bc2044
MD5 e15e67b341b5ac73278bfcdfc5e5dfa7
BLAKE2b-256 6166f374a1b15691891dd32892919c53488733a22ccc2377b1b53a0b427d932b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-win_amd64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 6cbe31da11c05885a39c3fe675e5e71c3481d01f8df291c852115ccb4aa2f697
MD5 699b38995d39d0f8f25594f934ea543d
BLAKE2b-256 c9f3eccdaeda84db91669906216b8809c8dacc1fcc7060daf40c66e80a46dffe

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-win32.whl.

File metadata

  • Download URL: stringzilla-3.9.7-cp36-cp36m-win32.whl
  • Upload date:
  • Size: 64.2 kB
  • Tags: CPython 3.6m, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-win32.whl
Algorithm Hash digest
SHA256 993979b27bc93f715411afaa23fd56295af479107672d8087c270511603da807
MD5 f270a9a090eee87d6511f7aff6b38f3a
BLAKE2b-256 b42057c1b9e63e381d52160313cbbd605948b7085180ef9561033df8c33f2f99

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 032861950f04714ad558973af0e178404f59beeba670124794bc9640fa0fa2e5
MD5 806861463bfb254005cbaac37c1bed27
BLAKE2b-256 65b3ec4665ccbbda2b337696585e9c2fc8745fe74b06834b40d8c36f12e9130a

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_s390x.whl
Algorithm Hash digest
SHA256 aa187fad650e228ae23586ece3575ae96bf86dd58f6a286460bb251b56805abc
MD5 8d284cf577154be27478bc0d5528bf9c
BLAKE2b-256 6649850315cb968ed5c9875e5a81a6147642745192a498b2a20ade9f8fb2728e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_ppc64le.whl
Algorithm Hash digest
SHA256 1fca1e495bcde068b6e9b6704c7117e7a5073f9ce403403f36888a439088ece8
MD5 14ffeb7927516bbf2487b33bb6af154c
BLAKE2b-256 03153d867ad2af717d9307c66549bb0b45d67bb3f52fa7252d4c04d501c2d206

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 ccb8534cc46eaede9667e778a7917b713de82499edef9ab64132d29c69020a23
MD5 c2aab0810d5e9b629e139ef5e23b9566
BLAKE2b-256 0abd8c9b5dabd3b2a3cb07a77bf22fa3fa9663b559e7cdca58fd3ffd6b46de4b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 e705099238d4a0089437883d93a738f9cfe50f1638355ca4bdd8fff44662ab7d
MD5 a0835c1883b6f4cee5852ac878823cdb
BLAKE2b-256 d7203e9f0d6e6a725ba87aa7b34331b944cba84e1f18c754f94cac8bb164a65b

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 329d56649f256a6952b4dd99c0a2a6e13d65f353a18a6a004cfa3bf7b4f94267
MD5 005458c23bda29b692631dfb826f38f5
BLAKE2b-256 152d80e0701dc48efaa917e1e8e4e71c4b3f1233d1eb3740cb840f7168f8062e

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.manylinux_2_28_s390x.whl
Algorithm Hash digest
SHA256 9bcb7df59cc42d996d21219ed2716b40fc13f045f84a1787273333fd35dc7553
MD5 68a6f393208c4ce8ae9caf435cd219f3
BLAKE2b-256 c9c4cdf2c7f1ebf83132785f6fd278f1f58f7bdc7246f6206a46a345f13dd7c9

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.manylinux_2_28_ppc64le.whl
Algorithm Hash digest
SHA256 7aff372e9d5af0189ae314d6144acaeb98675c0ea15077d74b65131c721a5e09
MD5 9cd5d46af8948b236a477d37bdff96f1
BLAKE2b-256 fe76231e0ef5bd01e12b7303d686b37ac2e78d304efda0ad9f0bf14c325e21ee

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 39c65bbca6da5f0834d7a860b145561d2e8e893d5fc67b188e6ab76906a006dc
MD5 6a95104f9ec260251982863ab3bde3ad
BLAKE2b-256 55991ed3938f95a7c2a7479be371fd8a72d49f0f33b278baa2b3621fb61438a3

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 31eaba76658d1e087a6d69c99c9d5aa556440e3576fd77fe99cf763661e3cc1a
MD5 1c3dab4cff68774d4fefc7173045138e
BLAKE2b-256 d3c245b98d2ef62705abd2bc6667adfc2b410095e1b985a0c1ce46df427326e0

See more details on using hashes here.

File details

Details for the file stringzilla-3.9.7-cp36-cp36m-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for stringzilla-3.9.7-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 7711f1c5a9dcccf85e03f61b843071999b53240cbfa46fe874e6c43b749721c3
MD5 8edb92aff963bdc580d3814355a122a7
BLAKE2b-256 7bd5ee5cebce5326172188648381f1ea3d4fa9c6818e1b503448eb9ab5c22669

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page