Skip to content

Commit

Permalink
Add compare operators to nostd::string_view (open-telemetry#124)
Browse files Browse the repository at this point in the history
* Add compare operators to nostd::string_view

* Added tests
  • Loading branch information
maxgolov authored Jun 29, 2020
1 parent 79b6141 commit aa79d9c
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 7 deletions.
64 changes: 57 additions & 7 deletions api/include/opentelemetry/nostd/string_view.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <algorithm>
#include <cstddef>
#include <cstring>
#include <ostream>
#include <stdexcept>
Expand All @@ -11,6 +12,9 @@
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{

using Traits = std::char_traits<char>;

/**
* Back port of std::string_view to work with pre-cpp-17 compilers.
*
Expand All @@ -20,7 +24,9 @@ namespace nostd
class string_view
{
public:
static constexpr std::size_t npos = static_cast<std::size_t>(-1);
typedef std::size_t size_type;

static constexpr size_type npos = static_cast<size_type>(-1);

string_view() noexcept : length_(0), data_(nullptr) {}

Expand All @@ -30,25 +36,25 @@ class string_view
: length_(str.length()), data_(str.c_str())
{}

string_view(const char *str, size_t len) noexcept : length_(len), data_(str) {}
string_view(const char *str, size_type len) noexcept : length_(len), data_(str) {}

explicit operator std::string() const { return {data_, length_}; }

const char *data() const noexcept { return data_; }

bool empty() const noexcept { return length_ == 0; }

size_t length() const noexcept { return length_; }
size_type length() const noexcept { return length_; }

size_t size() const noexcept { return length_; }
size_type size() const noexcept { return length_; }

const char *begin() const noexcept { return data(); }

const char *end() const noexcept { return data() + length(); }

const char &operator[](std::size_t i) { return *(data() + i); }
const char &operator[](size_type i) { return *(data() + i); }

string_view substr(std::size_t pos, std::size_t n = npos) const
string_view substr(size_type pos, size_type n = npos) const
{
if (pos > length_)
{
Expand All @@ -62,11 +68,55 @@ class string_view
return string_view(data_ + pos, n);
}

int compare(string_view v) const noexcept
{
size_type len = std::min(size(), v.size());
int result = Traits::compare(data(), v.data(), len);
if (result == 0)
result = size() == v.size() ? 0 : (size() < v.size() ? -1 : 1);
return result;
};

int compare(size_type pos1, size_type count1, string_view v) const
{
return substr(pos1, count1).compare(v);
};

int compare(size_type pos1, size_type count1, string_view v, size_type pos2, size_type count2) const
{
return substr(pos1, count1).compare(v.substr(pos2, count2));
};

int compare(const char *s) const
{
return compare(string_view(s));
};

int compare(size_type pos1, size_type count1, const char *s) const
{
return substr(pos1, count1).compare(string_view(s));
};

int compare(size_type pos1, size_type count1, const char *s, size_type count2) const
{
return substr(pos1, count1).compare(string_view(s, count2));
};

bool operator<(const string_view v) const noexcept
{
return compare(v) < 0;
}

bool operator>(const string_view v) const noexcept
{
return compare(v) > 0;
}

private:
// Note: uses the same binary layout as libstdc++'s std::string_view
// See
// https://github.com/gcc-mirror/gcc/blob/e0c554e4da7310df83bb1dcc7b8e6c4c9c5a2a4f/libstdc%2B%2B-v3/include/std/string_view#L466-L467
size_t length_;
size_type length_;
const char *data_;
};

Expand Down
30 changes: 30 additions & 0 deletions api/test/nostd/string_view_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <gtest/gtest.h>

#include "map"

using opentelemetry::nostd::string_view;

TEST(StringViewTest, DefaultConstruction)
Expand Down Expand Up @@ -72,3 +74,31 @@ TEST(StringViewTest, SubstrOutOfRange)
EXPECT_DEATH({ s.substr(10); }, "");
#endif
}

TEST(StringViewTest, Compare)
{
string_view s1 = "aaa";
string_view s2 = "bbb";
string_view s3 = "aaa";

// Equals
EXPECT_EQ(s1, s3);
EXPECT_EQ(s1, s1);

// Less then
EXPECT_LT(s1, s2);

// Greater then
EXPECT_GT(s2, s1);
}

TEST(StringViewTest, MapKeyOrdering)
{
std::map<string_view, size_t> m = {{"bbb", 2}, {"aaa", 1}, {"ccc", 3}};
size_t i = 1;
for (const auto &kv : m)
{
EXPECT_EQ(kv.second, i);
i++;
}
}

0 comments on commit aa79d9c

Please sign in to comment.