You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.7 KiB
171 lines
4.7 KiB
// Copyright The OpenTelemetry Authors |
|
// SPDX-License-Identifier: Apache-2.0 |
|
|
|
#pragma once |
|
|
|
#include <cstring> |
|
#include <utility> |
|
|
|
#include "opentelemetry/context/context_value.h" |
|
#include "opentelemetry/nostd/shared_ptr.h" |
|
#include "opentelemetry/nostd/string_view.h" |
|
#include "opentelemetry/nostd/variant.h" |
|
#include "opentelemetry/version.h" |
|
|
|
OPENTELEMETRY_BEGIN_NAMESPACE |
|
namespace context |
|
{ |
|
|
|
// The context class provides a context identifier. Is built as a linked list |
|
// of DataList nodes and each context holds a shared_ptr to a place within |
|
// the list that determines which keys and values it has access to. All that |
|
// come before and none that come after. |
|
class Context |
|
{ |
|
|
|
public: |
|
Context() = default; |
|
// Creates a context object from a map of keys and identifiers, this will |
|
// hold a shared_ptr to the head of the DataList linked list |
|
template <class T> |
|
Context(const T &keys_and_values) noexcept |
|
: head_{nostd::shared_ptr<DataList>{new DataList(keys_and_values)}} |
|
{} |
|
|
|
// Creates a context object from a key and value, this will |
|
// hold a shared_ptr to the head of the DataList linked list |
|
Context(nostd::string_view key, ContextValue value) noexcept |
|
: head_{nostd::shared_ptr<DataList>{new DataList(key, value)}} |
|
{} |
|
|
|
// Accepts a new iterable and then returns a new context that |
|
// contains the new key and value data. It attaches the |
|
// exisiting list to the end of the new list. |
|
template <class T> |
|
Context SetValues(T &values) noexcept |
|
{ |
|
Context context = Context(values); |
|
nostd::shared_ptr<DataList> last = context.head_; |
|
while (last->next_ != nullptr) |
|
{ |
|
last = last->next_; |
|
} |
|
last->next_ = head_; |
|
return context; |
|
} |
|
|
|
// Accepts a new iterable and then returns a new context that |
|
// contains the new key and value data. It attaches the |
|
// exisiting list to the end of the new list. |
|
Context SetValue(nostd::string_view key, ContextValue value) noexcept |
|
{ |
|
Context context = Context(key, value); |
|
context.head_->next_ = head_; |
|
return context; |
|
} |
|
|
|
// Returns the value associated with the passed in key. |
|
context::ContextValue GetValue(const nostd::string_view key) const noexcept |
|
{ |
|
for (DataList *data = head_.get(); data != nullptr; data = data->next_.get()) |
|
{ |
|
if (key.size() == data->key_length_) |
|
{ |
|
if (std::memcmp(key.data(), data->key_, data->key_length_) == 0) |
|
{ |
|
return data->value_; |
|
} |
|
} |
|
} |
|
return ContextValue{}; |
|
} |
|
|
|
// Checks for key and returns true if found |
|
bool HasKey(const nostd::string_view key) const noexcept |
|
{ |
|
return !nostd::holds_alternative<nostd::monostate>(GetValue(key)); |
|
} |
|
|
|
bool operator==(const Context &other) const noexcept { return (head_ == other.head_); } |
|
|
|
private: |
|
// A linked list to contain the keys and values of this context node |
|
struct DataList |
|
{ |
|
char *key_ = nullptr; |
|
|
|
nostd::shared_ptr<DataList> next_{nullptr}; |
|
|
|
size_t key_length_ = 0UL; |
|
|
|
ContextValue value_; |
|
|
|
DataList() = default; |
|
|
|
// Builds a data list off of a key and value iterable and returns the head |
|
template <class T> |
|
DataList(const T &keys_and_vals) |
|
{ |
|
bool first = true; |
|
auto *node = this; |
|
for (auto &iter : keys_and_vals) |
|
{ |
|
if (first) |
|
{ |
|
*node = DataList(iter.first, iter.second); |
|
first = false; |
|
} |
|
else |
|
{ |
|
node->next_ = nostd::shared_ptr<DataList>(new DataList(iter.first, iter.second)); |
|
node = node->next_.get(); |
|
} |
|
} |
|
} |
|
|
|
// Builds a data list with just a key and value, so it will just be the head |
|
// and returns that head. |
|
DataList(nostd::string_view key, const ContextValue &value) |
|
{ |
|
key_ = new char[key.size()]; |
|
key_length_ = key.size(); |
|
std::memcpy(key_, key.data(), key.size() * sizeof(char)); |
|
next_ = nostd::shared_ptr<DataList>{nullptr}; |
|
value_ = value; |
|
} |
|
|
|
DataList(const DataList &other) |
|
: key_(new char[other.key_length_]), |
|
next_(other.next_), |
|
key_length_(other.key_length_), |
|
value_(other.value_) |
|
{ |
|
std::memcpy(key_, other.key_, other.key_length_ * sizeof(char)); |
|
} |
|
|
|
DataList &operator=(DataList &&other) noexcept |
|
{ |
|
key_length_ = other.key_length_; |
|
value_ = std::move(other.value_); |
|
next_ = std::move(other.next_); |
|
|
|
key_ = other.key_; |
|
other.key_ = nullptr; |
|
|
|
return *this; |
|
} |
|
|
|
~DataList() |
|
{ |
|
if (key_ != nullptr) |
|
{ |
|
delete[] key_; |
|
} |
|
} |
|
}; |
|
|
|
// Head of the list which holds the keys and values of this context |
|
nostd::shared_ptr<DataList> head_; |
|
}; |
|
} // namespace context |
|
OPENTELEMETRY_END_NAMESPACE
|
|
|