Skip to content

Commit

Permalink
Solved some code review issues (II)
Browse files Browse the repository at this point in the history
  • Loading branch information
torrentg committed Nov 25, 2022
1 parent e810f6b commit 632081f
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 95 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# cstring

**This project is under development.**

cstring is a C++ immutable C-string (aka const char array) with reference counting.
cstring is a C++ immutable C-string (aka `const char array`) with reference counting.

It is a pointer to chars where the pointed memory is prefixed by the ref-counter
(4-bytes) and the string length (4-bytes).
Expand Down Expand Up @@ -52,9 +50,12 @@ make coverage
firefox coverage/index.html &
```

## Authors
## Contributors

* **Gerard Torrent** - _Initial work_ - [torrentg](https://github.com/torrentg/)
| Name | Contribution |
|:-----|:-------------|
| [Gerard Torrent](https://github.com/torrentg/) | Initial work<br/>Code maintainer|
| [Matthieu M.](https://codereview.stackexchange.com/users/8999/matthieu-m) | [Code review](https://codereview.stackexchange.com/questions/281365/an-immutable-c-string-with-ref-counting) |

## License

Expand Down
96 changes: 95 additions & 1 deletion cstring-tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
using namespace std;
using namespace gto;

template<typename C, typename T, typename A>
uint32_t getCounter(basic_cstring<C, T, A> &x) {
const uint32_t *ptr = reinterpret_cast<const uint32_t *>(x.data());
return ptr[-2];
}

TEST_CASE("cstring") {

SUBCASE("sizeof") {
Expand All @@ -18,6 +24,7 @@ TEST_CASE("cstring") {
cstring empty1;
CHECK(empty1.size() == 0);
CHECK(empty1.length() == 0);
CHECK(getCounter(empty1) == 0);
CHECK(std::strlen(empty1.data()) == 0);
{
cstring empty2(nullptr);
Expand Down Expand Up @@ -58,6 +65,7 @@ TEST_CASE("cstring") {
cstring str("abc");
CHECK(str.size() == 3);
CHECK(str.length() == 3);
CHECK(getCounter(str) == 1);
CHECK(string("abc") == str.data());
}
{
Expand All @@ -67,18 +75,26 @@ TEST_CASE("cstring") {
}
{
cstring str1("abc");
CHECK(getCounter(str1) == 1);
cstring str2(str1);
CHECK(getCounter(str1) == 2);
CHECK(getCounter(str2) == 2);
CHECK(str1.data() == str2.data());
}
{
cstring str1("abc");
CHECK(getCounter(str1) == 1);
cstring str2 = str1;
CHECK(getCounter(str1) == 2);
CHECK(getCounter(str2) == 2);
CHECK(str1.data() == str2.data());
}
{
cstring str1("abc");
const char *ptr = str1.data();
CHECK(getCounter(str1) == 1);
cstring str2(std::move(str1));
CHECK(getCounter(str2) == 1);
CHECK(str2.data() == ptr);
}
{
Expand All @@ -90,23 +106,32 @@ TEST_CASE("cstring") {
{
cstring str1("abc");
cstring str2("xyz");
CHECK(getCounter(str1) == 1);
CHECK(getCounter(str2) == 1);
CHECK(str1.data() != str2.data());
str1 = str2;
CHECK(getCounter(str1) == 2);
CHECK(str1.data() == str2.data());
CHECK(str1.data() == string("xyz"));
}
{
cstring str1("abc");
cstring str2;
CHECK(getCounter(str1) == 1);
CHECK(getCounter(str2) == 0);
CHECK(str1.data() != str2.data());
str1 = str2;
CHECK(getCounter(str1) == 0);
CHECK(getCounter(str2) == 0);
CHECK(str1.data() == str2.data());
CHECK(str1.data() == string(""));
}
{
cstring str("abc");
CHECK(getCounter(str) == 1);
auto ptr = str.data();
str = str;
CHECK(getCounter(str) == 1);
CHECK(str.data() == ptr);
}
}
Expand Down Expand Up @@ -134,7 +159,9 @@ TEST_CASE("cstring") {
CHECK(str1.at(1) == 'b');
CHECK(str1[2] == 'c');
CHECK(str1.at(2) == 'c');
CHECK_THROWS(str1.at(3));
CHECK(str1[3] == 0);
CHECK(str1.at(3) == 0);
CHECK_THROWS(str1.at(4));
CHECK(str1.front() == 'a');
CHECK(str1.back() == 'c');
}
Expand All @@ -145,6 +172,13 @@ TEST_CASE("cstring") {
CHECK(std::strcmp(str.c_str(), "abc") == 0);
}

SUBCASE("view") {
CHECK(cstring{}.view().size() == 0);
CHECK(cstring{}.view() == "");
CHECK(cstring{"abc"}.view().size() == 3);
CHECK(cstring{"abc"}.view() == "abc");
}

SUBCASE("iterator") {
cstring str("abc");
auto it = str.cbegin();
Expand Down Expand Up @@ -172,9 +206,14 @@ TEST_CASE("cstring") {
SUBCASE("swap") {
cstring str1("abc");
cstring str2("xyz");
CHECK(str1.data() == std::string("abc"));
CHECK(str2.data() == std::string("xyz"));
str1.swap(str2);
CHECK(str1.data() == std::string("xyz"));
CHECK(str2.data() == std::string("abc"));
swap(str1, str2);
CHECK(str1.data() == std::string("abc"));
CHECK(str2.data() == std::string("xyz"));
}

SUBCASE("substr") {
Expand Down Expand Up @@ -576,3 +615,58 @@ TEST_CASE("cstring") {
}

}

TEST_CASE("wcstring") {

SUBCASE("general") {

CHECK(sizeof(wchar_t) >= 2);
CHECK(alignof(wchar_t) >= 2);

wcstring str1{L"SomeText"};
CHECK(str1.length() == 8);
CHECK(str1.size() == 8);
CHECK(getCounter(str1) == 1);

wcstring str2{L"čřžýáí1"};
CHECK(str2.length() == 7);
CHECK(str2.size() == 7);
CHECK(getCounter(str2) == 1);

CHECK(str1 != str2);
str1 = str2;
CHECK(getCounter(str2) == 2);
CHECK(str1 == str2);

CHECK(std::hash<wcstring>{}(wcstring()) != 0);
CHECK(std::hash<wcstring>{}(wcstring(L"abc")) != 0);
CHECK(std::hash<wcstring>{}(wcstring(L"abc")) == std::hash<wstring>{}(std::wstring(L"abc")));
}

}

TEST_CASE("cstring16") {

SUBCASE("general") {

typedef basic_cstring<char16_t> cstring16;

CHECK(sizeof(char16_t) == 2);

cstring16 str1{u"test"};
CHECK(str1.length() == 4);
CHECK(str1.size() == 4);
CHECK(getCounter(str1) == 1);

cstring16 str2{u"world"};
CHECK(str2.length() == 5);
CHECK(str2.size() == 5);
CHECK(getCounter(str2) == 1);

CHECK(str1 != str2);
str1 = str2;
CHECK(getCounter(str2) == 2);
CHECK(str1 == str2);
}

}
Loading

0 comments on commit 632081f

Please sign in to comment.