summaryrefslogtreecommitdiffstats
path: root/include/opentracing/string_view.h
blob: a30eb7fe79ce414b0e3fcfeb38c5a1ef94c56734 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef OPENTRACING_STRING_VIEW_H
#define OPENTRACING_STRING_VIEW_H

#include <opentracing/version.h>
#include <algorithm>
#include <cstring>
#include <ostream>
#include <string>

// ===========
// string_view.h
// ===========
// class string_view - Constant reference to an external string
//
// -----------------
// String References
// -----------------
// This string references is a simplified version of the boost::string_ref.
// Its purpose is to avoid a number of efficiency problems that appear
// commonly when interacting with 'std::string' and c-strings.
//
// See the boost documentation for more background:
// http://www.boost.org/doc/libs/master/libs/utility/doc/html/string_ref.html
//
// -----
// Note:
// -----
// Although we have the ability to use wide string refs, there are side
// effects in exposing an OpenTracing interface that works with narrow and wide
// strings at the same time. Storage on the implementation will have a 'native'
// format.
//
// Exposing references to that format avoid copies means clients would be
// dependent on that format. If they're dependent on that detail and then switch
// out the implementation to a different format, there would be lots of code
// that breaks if it was expecting wstring and starts receiving string all of a
// sudden. That design issue still needs to be addressed.

namespace opentracing {
BEGIN_OPENTRACING_ABI_NAMESPACE
// ===============
// class string_view
// ===============
// Represent a constant reference to an external character array. The external
// array need not be null-terminated, if explicitly created with a known length.
//
// This class does not own the data. It is expected to be used in situations
// where the character data resides in some other buffer, whose lifetime extends
// past that of the string_view. For this reason, it is not in general safe to
// store a string_view.

class string_view {
 public:
  // Construct an empty string_view
  string_view() noexcept : data_(nullptr), length_(0) {}

  // create string reference from const character pointer
  string_view(const char* str) noexcept
      : data_(str), length_(std::strlen(str)) {}

  // Create constant string reference from pointer and length
  string_view(const std::basic_string<char>& str) noexcept
      : data_(str.c_str()), length_(str.length()) {}

  // Create constant string reference from pointer and length
  string_view(const char* str, size_t len) noexcept
      : data_(str), length_(len) {}

  // Implicit conversion to std::string
  operator std::string() const { return {data_, length_}; }

  // Return address of the referenced string
  const char* data() const noexcept { return data_; }

  // Returns true if `length_` == 0
  bool empty() const noexcept { return length_ == 0; }

  // Return the length of the referenced string
  size_t length() const noexcept { return length_; }
  size_t size() const noexcept { return length_; }

  // Returns a RandomAccessIterator to the first element.
  const char* begin() const noexcept { return data(); }

  // Returns a RandomAccessIterator for the last element.
  const char* end() const noexcept { return data() + length(); }

  // Returns the character in the i-th position.
  const char& operator[](std::size_t i) { return *(data() + i); }

 private:
  const char* data_;  // Pointer to external storage
  size_t length_;     // Length of data pointed to by 'data_'
};

inline bool operator==(string_view lhs, string_view rhs) noexcept {
  return lhs.length() == rhs.length() &&
         std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data());
}

inline bool operator==(string_view lhs, const std::string& rhs) noexcept {
  return lhs == string_view(rhs);
}

inline bool operator==(const std::string& lhs, string_view rhs) noexcept {
  return string_view(lhs) == rhs;
}

inline bool operator==(string_view lhs, const char* rhs) noexcept {
  return lhs == string_view(rhs);
}

inline bool operator==(const char* lhs, string_view rhs) noexcept {
  return string_view(lhs) == rhs;
}

inline bool operator!=(string_view lhs, string_view rhs) noexcept {
  return !(lhs == rhs);
}

inline bool operator!=(string_view lhs, const std::string& rhs) noexcept {
  return !(lhs == rhs);
}

inline bool operator!=(const std::string& lhs, string_view rhs) noexcept {
  return !(lhs == rhs);
}

inline bool operator!=(string_view lhs, const char* rhs) noexcept {
  return !(lhs == rhs);
}

inline bool operator!=(const char* lhs, string_view rhs) noexcept {
  return !(lhs == rhs);
}

inline std::ostream& operator<<(std::ostream& os,
                                const opentracing::string_view& ref) {
  return os.write(ref.data(), static_cast<std::streamsize>(ref.length()));
}
END_OPENTRACING_ABI_NAMESPACE
}  // namespace opentracing

#endif  // OPENTRACING_STRING_VIEW_H