{"id":13730275,"url":"https://github.com/sawickiap/str_view","last_synced_at":"2026-01-14T19:11:56.212Z","repository":{"id":107076604,"uuid":"140573302","full_name":"sawickiap/str_view","owner":"sawickiap","description":"Null-termination-aware string-view class for C++","archived":false,"fork":false,"pushed_at":"2025-07-27T18:28:13.000Z","size":65,"stargazers_count":25,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-27T20:40:23.949Z","etag":null,"topics":["null-terminator","string","view"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sawickiap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-11T12:39:57.000Z","updated_at":"2025-07-27T18:26:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"480a5fbc-0132-4e17-aefa-a6df181b0afa","html_url":"https://github.com/sawickiap/str_view","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sawickiap/str_view","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawickiap%2Fstr_view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawickiap%2Fstr_view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawickiap%2Fstr_view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawickiap%2Fstr_view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sawickiap","download_url":"https://codeload.github.com/sawickiap/str_view/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawickiap%2Fstr_view/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28431691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T18:57:19.464Z","status":"ssl_error","status_checked_at":"2026-01-14T18:52:48.501Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["null-terminator","string","view"],"created_at":"2024-08-03T02:01:12.624Z","updated_at":"2026-01-14T19:11:56.203Z","avatar_url":"https://github.com/sawickiap.png","language":"C++","readme":"# str_view\n\nNull-termination-aware string-view class for C++.\n\nAuthor: Adam Sawicki - https://asawicki.info\u003cbr\u003e\nVersion: 2.1.1, 2025-07-27\u003cbr\u003e\nLicense: MIT\n\nDocumentation: see below and comments in the code of `str_view.hpp` file.\n\n# Introduction\n\nstr_view is a small library for C++.\nIt offers a convenient and optimized class that represents view into a character string.\nIt has a form of a single header file: `str_view.hpp`, which you can just add to your project.\nAll the members are defined as `inline`, so no compilation of additional CPP files or linking with additional libraries is required.\n\nstr_view depends only on standard C and C++ library.\nIt has been developed and tested under Windows using Microsoft Visual Studio 2019, but it should work in other compilers and platforms as well. If you find any compatibility issues, please let me know.\nIt works in both 32-bit and 64-bit code.\n\nThe class is defined as `str_view_template`, because it's a template that can be parametrized with character types. Two typedefs are provided:\n\n- `str_view` - compatible with `char` and `std::string` (single-byte or UTF-8 strings).\n- `wstr_view` - compatible with `wchar_t` and `std::wstring` (2-byte UTF-16 strings, also called Unicode in WinAPI).\n\nAll the examples below use `str_view`, but everything what is described here applies also to `wstr_view` and Unicode strings.\n\nAn object of `str_view` class represents a view into an externally owned character string, or piece of thereof. It stores pointer to its beginning and its length. The original string must remain alive and unchanged as long as the view object is alive and points to it. Otherwise behavior is undefined.\n\nString pointed by `str_view` is immutable. It means it is possible to only read properties (like length) and characters of the pointer string, but not to alter it in any way through the view, either its length or individual characters. Defining `str_view` object as `const` only means that the view itself is immutable and cannot be changed to point to a different string.\n\nIt is best used for passing parameters into library functions that can take strings of unknown origin. Let's consider an example library function:\n\n```cpp\nvoid Foo(const str_view\u0026 v);\n```\n\n# Creating string view\n\nThere are multiple ways in which a string view object can be constructed, as there are multiple overloaded constructors. None of them are marked as `explicit`, so implicit conversion is allowed.\n\n## Basic construction\n\nDefault constructor initializes valid, but empty string (one with length of 0).\n\n```cpp\nFoo(str_view()); // Passed \"\"\n```\n\nView can be created from a null-terminated string. It can be either string literal...\n\n```cpp\nFoo(\"Ala ma kota\"); // Passed \"Ala ma kota\"\n```\n\n...or dynamically created C string.\n\n```cpp\nchar sz[32];\nsprintf_s(sz, \"Number is %i\", 7);\nFoo(sz); // Passed \"Number is 7\"\n```\n\nView can also be created from STL string.\n\n```cpp\nstd::string str = \"Ala ma kota\";\nFoo(str); // Passed \"Ala ma kota\"\n```\n\nThe class also supports copy constructor, move constructor, assignment operator, move assignment operator, `swap` method and global `swap` function.\n\n## Advanced construction\n\nPassing `null` as source pointer is also valid. It initializes view to an empty string.\n\n```cpp\nFoo(str_view(nullptr)); // Passed \"\"\n```\n\nView can also be created from an array of characters, by specifying pointer to first character and length (number of characters). Such string doesn't need to be null-terminated.\n\n```cpp\nchar array[4] = { 'A', 'B', 'C', 'D' };\nFoo(str_view(array,\n    4)); // length\n// Passed \"ABCD\"\n```\n\nView can be created to point to only a piece of original string.\n\n```cpp\nconst char* sz = \"Ala ma kota\";\nFoo(str_view(sz + 4,\n    2)); // length\n// Passed \"ma\"\n```\n\nIt can also point to a piece of STL string. No copy is performed. The view object still refers to the original string.\n\n```cpp\nstd::string str = \"Ala ma kota\";\nFoo(str_view(str,\n    4, // offset\n    2)); // length\n// Passed \"ma\"\n```\n\nThe class offers powerful `substr` method that returns a new view, which may point to a piece of source view.\n\n```cpp\nstr_view orig = \"Ala ma kota\";\nFoo(orig.substr(\n    4)); // offset\n// Passed \"ma kota\" - substring from offset 4 to the end.\n\nFoo(orig.substr(\n    0, // offset\n    3)); // length\n// Passed \"Ala\" - substring limited to 3 characters.\n\nFoo(orig.substr(\n    4, // offset\n    2)); // length\n// Passed \"ma\"\n```\n\n# Using string view\n\n`str_view` class offers a convenient set of methods and operators similar to `std::string` and `std::string_view` from C++17, but it's not fully compatible with any of them.\n\nCall `length()` to retrieve length of string view (number of charecters). Alternative name is `size()`, but personally I don't recommend it because its name may be misleading - it may suggest size in bytes not in characters.\n\n`empty()` method returns `true` when the string is empty (has length of 0). It may be more efficient than `length()`.\n\n`data()` method returns a pointer to the underlying character array. Characters are always laid out sequentially in memory, so the pointer may be used as normal C array.\n\n`begin()` and `end()` methods return pointers to the first character and to the character following the last character of the view, respectively. Together they form a range that may be used e.g. with STL algorithms that expect a pair of iterators. They also enable usage of range-based for loop.\n\n```cpp\nstr_view v = str_view(\"Ala ma kota\");\n// Prints \"Ala ma kota\"\nfor(char ch : v)\n    printf(\"%c\", ch);\n```\n\nIndividual characters can be read using overloaded `operator[]`. Alternative syntax is `at()` method. None of them perform range checking, for performance reasons.\n\nFirst character can also be fetched using `front()` method, and last character is returned by `back()` method.\n\nPointed string can be copied to a specified destination array of characters using method `copy_to()`, or to an STL string using method `to_string()`.\n\nString views can be compared lexicographically using all comparison operators, like `==`, `!=`, `\u003c`, `\u003c=` etc. There is also more powerful method `compare()` which returns negative integer, zero, or positive integer, depending on the result of the comparison. Comparison can be made case-insensitive.\n\n```cpp\nstr_view v1 = str_view(\"aaa\");\nstr_view v2 = str_view(\"BBB\");\nint r = v1.compare(v2,\n    false); // case_sensitive\n// r is -1 because v1 goes before v2 when compared in case-insensitive way.\n```\n\nString view can also be searched and checked using methods: `starts_with()` and `ends_with()` (also supports case-insensitive comparison), `find()`, `rfind()`, `find_first_of()`, `find_last_of()`, `find_first_not_of()`, `find_last_not_of()`.\n\nLast but not least, because strings in a C++ program often need to end up as null-terminated C strings to be passed to some external libraries, the class offers `c_str()` method similar to `std::string` that returns pointer to such null-terminated string. It may be either pointer to the original string if it's null terminated, or an internal copy. The copy is valid as long as `str_view` object is alive and it's not modified to point to a different string or using any of its non-`const` methods. It is owned by the string view object and automatically destroyed.\n\n```cpp\nstr_view v = str_view(\"Ala ma kota\");\nstr_view sub_v = v.substr(4, 2);\nprintf(\"sub_v is: %s\", sub_v.c_str()); // Prints \"sub_v is: ma\"\n```\n\n# Performance\n\nUnique feature of this library is that a string view is \"null-termination-aware\" - it not only remembers pointer and length of the referred string, but also the way it was created to avoid unnecessary operations and lazily evaluate those that are requested.\n\n- If it was created from a null-terminated string:\n  - `c_str()` trivially returns pointer to the original string.\n  - Length is unknown and it is calculated upon first call to `length()`.\n- On the other hand, if it was created from a string that is not null-terminated:\n  - Length is explicitly known, so `length()` trivially returns it.\n  - `c_str()` creates a local, null-terminated copy of the string upon first call.\n\nExample 1: View created from a null-terminated string.\n\n```cpp\nconst char* sz = \"Ala ma kota\";\nstr_view v = str_view(sz);\n\n// empty() peeks only first character. Length still unknown.\nprintf(\"Empty: %s\\n\", v.empty() ? \"true\" : \"false\"); // Prints \"Empty: false\"\n// length() calculates length on first call.\nprintf(\"Length: %zu\\n\", v.length()); // Prints \"Length: 11\"\n// c_str() trivially returns original pointer.\nprintf(\"String is: %s\\n\", v.c_str()); // Prints \"Ala ma kota\"\n```\n\nExample 2: View created from a STL string.\n\n```cpp\nstd::string s = \"Ala ma kota\";\nstr_view v = str_view(s);\n\n// c_str() returns pointer returned from original s.c_str().\nprintf(\"String is: %s\\n\", v.c_str());\n// Length is explicitly known from s, so empty() trivially checks if it's not 0.\nprintf(\"Empty: %s\\n\", v.empty() ? \"true\" : \"false\");\n// Length is explicitly known from s, so length() trivially returns it.\nprintf(\"Length: %zu\\n\", v.length());\n```\n\nExample 3: View created from character array that is not null-terminated.\n\n```cpp\nconst char* sz = \"Ala ma kota\";\nstr_view v = str_view(sz + 4, 2);\n\n// c_str() creates and returns local, null-terminated copy.\nprintf(\"String is: %s\\n\", v.c_str()); // Prints \"ma\"\n// Length is explicitly known, so empty() trivially checks if it's not 0.\nprintf(\"Empty: %s\\n\", v.empty() ? \"true\" : \"false\"); // Prints \"Empty: false\"\n// Length is explicitly known, so length() trivially returns it.\nprintf(\"Length: %zu\\n\", v.length()); // Prints \"Length: 2\"\n```\n\nThis optimization also works with substrings:\n\n```cpp\nstr_view vFull = str_view(\"Ala ma kota\");\nstr_view vBegin = vFull.substr(\n    0, // offset\n    3); // length\n\n// Substring is not null-terminated. c_str() creates and returns local, null-terminated copy.\nprintf(\"String is: %s\\n\", vBegin.c_str()); // Prints \"Ala\"\n// Length is explicitly known, so empty() trivially checks if it's not 0.\nprintf(\"Empty: %s\\n\", vBegin.empty() ? \"true\" : \"false\"); // Prints \"Empty: false\"\n// Length is explicitly known, so length() trivially returns it.\nprintf(\"Length: %zu\\n\", vBegin.length()); // Prints \"Length: 3\"\n```\n\n```cpp\nstr_view vFull = str_view(\"Ala ma kota\");\nstr_view vEnd = vFull.substr(\n    7); // offset\n\n// Substring is null-terminated. c_str() returns original pointer, adjusted by offset.\nprintf(\"String is: %s\\n\", vEnd.c_str()); // Prints \"kota\"\n// Length is still unknown. empty() peeks only first character.\nprintf(\"Empty: %s\\n\", vEnd.empty() ? \"true\" : \"false\"); // Prints \"Empty: false\"\n// length() calculates length on first call.\nprintf(\"Length: %zu\\n\", vEnd.length()); // Prints \"Length: 4\"\n```\n\n# Thread-safety\n\nThe library has no global state, so separate string view objects are safe to be used from different threads simultaneously. However, a single string view object is NOT safe to be used from multiple threads simultaneously! A copy of such object must be made for every thread that needs it. Note this is a difference comparing to version 1 of the library. Atomics are no longer used for performance reason. Even `const` methods can modify internal mutable state of the object, e.g. calculate length or create a null-terminated copy on first use.\n","funding_links":[],"categories":["C++"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsawickiap%2Fstr_view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsawickiap%2Fstr_view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsawickiap%2Fstr_view/lists"}