.. _program_listing_file_include_opentelemetry_common_kv_properties.h: Program Listing for File kv_properties.h ======================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/opentelemetry/common/kv_properties.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2021, OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #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/shared_ptr.h" #include "opentelemetry/nostd/string_view.h" #include "opentelemetry/nostd/unique_ptr.h" #include "opentelemetry/version.h" #include #include 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()) : 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) { 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 { return key_.get(); } // Gets the value associated with this entry. nostd::string_view GetValue() const { return value_.get(); } // Sets the value for this entry. This overrides the previous value. void SetValue(nostd::string_view value) { value_ = CopyStringToPointer(value); } private: // Store key and value as raw char pointers to avoid using std::string. nostd::unique_ptr key_; nostd::unique_ptr 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 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(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 entries_; public: // Create Key-value list of given size // @param size : Size of list. KeyValueProperties(size_t size) : num_entries_(0), max_num_entries_(size), entries_(new Entry[size]) {} // Create Empty Key-Value list KeyValueProperties() : num_entries_(0), max_num_entries_(0), entries_(nullptr) {} template ::value>::type> KeyValueProperties(const T &keys_and_values) : 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) { 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 callback) const { 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 { 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