| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- #pragma once
- #include "opentelemetry/common/key_value_iterable_view.h"
- #include "opentelemetry/common/string_util.h"
- #include "opentelemetry/nostd/function_ref.h"
- #include "opentelemetry/nostd/string_view.h"
- #include "opentelemetry/nostd/unique_ptr.h"
- #include "opentelemetry/version.h"
- #include <cstring>
- #include <string>
- #include <type_traits>
- OPENTELEMETRY_BEGIN_NAMESPACE
- namespace common
- {
- // Constructor parameter for KeyValueStringTokenizer
- struct KeyValueStringTokenizerOptions
- {
- char member_separator = ',';
- char key_value_separator = '=';
- bool ignore_empty_members = true;
- };
- // Tokenizer for key-value headers
- class KeyValueStringTokenizer
- {
- public:
- KeyValueStringTokenizer(
- nostd::string_view str,
- const KeyValueStringTokenizerOptions &opts = KeyValueStringTokenizerOptions()) noexcept
- : str_(str), opts_(opts), index_(0)
- {}
- static nostd::string_view GetDefaultKeyOrValue()
- {
- static std::string default_str = "";
- return default_str;
- }
- // Returns next key value in the string header
- // @param valid_kv : if the found kv pair is valid or not
- // @param key : key in kv pair
- // @param key : value in kv pair
- // @returns true if next kv pair was found, false otherwise.
- bool next(bool &valid_kv, nostd::string_view &key, nostd::string_view &value) noexcept
- {
- valid_kv = true;
- while (index_ < str_.size())
- {
- bool is_empty_pair = false;
- size_t end = str_.find(opts_.member_separator, index_);
- if (end == std::string::npos)
- {
- end = str_.size() - 1;
- }
- else if (end == index_) // empty pair. do not update end
- {
- is_empty_pair = true;
- }
- else
- {
- end--;
- }
- auto list_member = StringUtil::Trim(str_, index_, end);
- if (list_member.size() == 0 || is_empty_pair)
- {
- // empty list member
- index_ = end + 2 - is_empty_pair;
- if (opts_.ignore_empty_members)
- {
- continue;
- }
- valid_kv = true;
- key = GetDefaultKeyOrValue();
- value = GetDefaultKeyOrValue();
- return true;
- }
- auto key_end_pos = list_member.find(opts_.key_value_separator);
- if (key_end_pos == std::string::npos)
- {
- // invalid member
- valid_kv = false;
- }
- else
- {
- key = list_member.substr(0, key_end_pos);
- value = list_member.substr(key_end_pos + 1);
- }
- index_ = end + 2;
- return true;
- }
- // no more entries remaining
- return false;
- }
- // Returns total number of tokens in header string
- size_t NumTokens() const noexcept
- {
- size_t cnt = 0, begin = 0;
- while (begin < str_.size())
- {
- ++cnt;
- size_t end = str_.find(opts_.member_separator, begin);
- if (end == std::string::npos)
- {
- break;
- }
- begin = end + 1;
- }
- return cnt;
- }
- // Resets the iterator
- void reset() noexcept { index_ = 0; }
- private:
- nostd::string_view str_;
- KeyValueStringTokenizerOptions opts_;
- size_t index_;
- };
- // Class to store fixed size array of key-value pairs of string type
- class KeyValueProperties
- {
- // Class to store key-value pairs of string types
- public:
- class Entry
- {
- public:
- Entry() : key_(nullptr), value_(nullptr) {}
- // Copy constructor
- Entry(const Entry ©)
- {
- key_ = CopyStringToPointer(copy.key_.get());
- value_ = CopyStringToPointer(copy.value_.get());
- }
- // Copy assignment operator
- Entry &operator=(Entry &other)
- {
- key_ = CopyStringToPointer(other.key_.get());
- value_ = CopyStringToPointer(other.value_.get());
- return *this;
- }
- // Move contructor and assignment operator
- Entry(Entry &&other) = default;
- Entry &operator=(Entry &&other) = default;
- // Creates an Entry for a given key-value pair.
- Entry(nostd::string_view key, nostd::string_view value)
- {
- key_ = CopyStringToPointer(key);
- value_ = CopyStringToPointer(value);
- }
- // Gets the key associated with this entry.
- nostd::string_view GetKey() const noexcept { return key_.get(); }
- // Gets the value associated with this entry.
- nostd::string_view GetValue() const noexcept { return value_.get(); }
- // Sets the value for this entry. This overrides the previous value.
- void SetValue(nostd::string_view value) noexcept { value_ = CopyStringToPointer(value); }
- private:
- // Store key and value as raw char pointers to avoid using std::string.
- nostd::unique_ptr<const char[]> key_;
- nostd::unique_ptr<const char[]> value_;
- // Copies string into a buffer and returns a unique_ptr to the buffer.
- // This is a workaround for the fact that memcpy doesn't accept a const destination.
- nostd::unique_ptr<const char[]> CopyStringToPointer(nostd::string_view str)
- {
- char *temp = new char[str.size() + 1];
- memcpy(temp, str.data(), str.size());
- temp[str.size()] = '\0';
- return nostd::unique_ptr<const char[]>(temp);
- }
- };
- // Maintain the number of entries in entries_.
- size_t num_entries_;
- // Max size of allocated array
- size_t max_num_entries_;
- // Store entries in a C-style array to avoid using std::array or std::vector.
- nostd::unique_ptr<Entry[]> entries_;
- public:
- // Create Key-value list of given size
- // @param size : Size of list.
- KeyValueProperties(size_t size) noexcept
- : num_entries_(0), max_num_entries_(size), entries_(new Entry[size])
- {}
- // Create Empty Key-Value list
- KeyValueProperties() noexcept : num_entries_(0), max_num_entries_(0), entries_(nullptr) {}
- template <class T, class = typename std::enable_if<detail::is_key_value_iterable<T>::value>::type>
- KeyValueProperties(const T &keys_and_values) noexcept
- : num_entries_(0),
- max_num_entries_(keys_and_values.size()),
- entries_(new Entry[max_num_entries_])
- {
- for (auto &e : keys_and_values)
- {
- Entry entry(e.first, e.second);
- (entries_.get())[num_entries_++] = std::move(entry);
- }
- }
- // Adds new kv pair into kv properties
- void AddEntry(nostd::string_view key, nostd::string_view value) noexcept
- {
- if (num_entries_ < max_num_entries_)
- {
- Entry entry(key, value);
- (entries_.get())[num_entries_++] = std::move(entry);
- }
- }
- // Returns all kv pair entries
- bool GetAllEntries(
- nostd::function_ref<bool(nostd::string_view, nostd::string_view)> callback) const noexcept
- {
- for (size_t i = 0; i < num_entries_; i++)
- {
- auto &entry = (entries_.get())[i];
- if (!callback(entry.GetKey(), entry.GetValue()))
- {
- return false;
- }
- }
- return true;
- }
- // Return value for key if exists, return false otherwise
- bool GetValue(nostd::string_view key, std::string &value) const noexcept
- {
- for (size_t i = 0; i < num_entries_; i++)
- {
- auto &entry = (entries_.get())[i];
- if (entry.GetKey() == key)
- {
- const auto &entry_value = entry.GetValue();
- value = std::string(entry_value.data(), entry_value.size());
- return true;
- }
- }
- return false;
- }
- size_t Size() const noexcept { return num_entries_; }
- };
- } // namespace common
- OPENTELEMETRY_END_NAMESPACE
|