sparrow 1.3.0
Loading...
Searching...
No Matches
metadata.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <concepts>
18#include <cstddef>
19#include <cstdint>
20#include <cstring>
21#include <numeric>
22#include <ranges>
23#include <string_view>
24#include <utility>
25
29
30#if defined(__cpp_lib_format)
31# include <format>
32# include <ostream>
33#endif
34
35namespace sparrow
36{
43 using metadata_key = std::string;
44 using metadata_key_const_reference = std::string_view;
45
52 using metadata_value = std::string;
53 using metadata_value_const_reference = std::string_view;
54
61 using metadata_pair = std::pair<metadata_key, metadata_value>;
62 using metadata_pair_const_reference = std::pair<metadata_key_const_reference, metadata_value_const_reference>;
63
77 SPARROW_API int32_t extract_int32(const char*& ptr);
78
79 class key_value_view;
80
96 {
97 public:
98
99 using iterator_category = std::forward_iterator_tag;
100
102 : m_parent(nullptr)
103 , m_index(0)
104 , m_current(nullptr)
105 , m_key()
106 , m_value()
107 {
108 }
109
111 using difference_type = std::ptrdiff_t;
114 using iterator_concept = std::forward_iterator_tag;
115
116
129
141
151
160
171 {
172 return lhs.m_index == rhs.m_index;
173 }
174
175 private:
176
188 SPARROW_API std::string_view extract_string_view();
189
200 SPARROW_API void extract_key_value();
201
202 const key_value_view* m_parent;
203 int32_t m_index;
204 const char* m_current;
205 std::string_view m_key;
206 std::string_view m_value;
207 };
208
230 class key_value_view : public std::ranges::view_interface<key_value_view>
231 {
232 public:
233
244 SPARROW_API key_value_view(const char* ptr);
245
254 [[nodiscard]] SPARROW_API key_value_view_iterator cbegin() const;
255
264 [[nodiscard]] SPARROW_API key_value_view_iterator begin() const;
265
274 [[nodiscard]] SPARROW_API key_value_view_iterator cend() const;
275
284 [[nodiscard]] SPARROW_API key_value_view_iterator end() const;
285
294 [[nodiscard]] SPARROW_API size_t size() const;
295
296 [[nodiscard]] SPARROW_API bool empty() const;
297
298 [[nodiscard]] SPARROW_API key_value_view_iterator find(std::string_view key) const;
299
300 private:
301
302 const char* m_ptr;
303 int32_t m_num_pairs = 0;
304
305 friend key_value_view_iterator;
306 };
307
321
331 template <typename T>
332 concept input_metadata_container = (std::ranges::input_range<T>
333 && std::same_as<std::ranges::range_value_t<T>, metadata_pair>)
334 || std::same_as<T, key_value_view>;
335
366 template <input_metadata_container T>
367 std::string get_metadata_from_key_values(const T& metadata)
368 {
369 // Check that the number of key-value pairs fits in int32_t
370 SPARROW_ASSERT_TRUE(std::cmp_less(metadata.size(), std::numeric_limits<int32_t>::max()));
371 const auto number_of_key_values = static_cast<int32_t>(metadata.size());
372
373 const size_t metadata_size = std::accumulate(
374 metadata.cbegin(),
375 metadata.cend(),
376 size_t(0),
377 [](size_t acc, const auto& pair)
378 {
379 return acc + sizeof(int32_t) // byte length of key
380 + pair.first.size() // number of bytes of key
381 + sizeof(int32_t) // byte length of value
382 + pair.second.size(); // number of bytes of value
383 }
384 );
385 const size_t total_size = sizeof(int32_t) + metadata_size;
386 std::string metadata_buf(total_size, '\0');
387
388 // Use iterators instead of pointer arithmetic to avoid warnings
389 auto metadata_iter = metadata_buf.begin();
390 std::memcpy(&(*metadata_iter), &number_of_key_values, sizeof(int32_t));
391 std::advance(metadata_iter, sizeof(int32_t));
392
393 for (const auto& [key, value] : metadata)
394 {
395 SPARROW_ASSERT_TRUE(std::cmp_less(key.size(), std::numeric_limits<int32_t>::max()));
396 SPARROW_ASSERT_TRUE(std::cmp_less(value.size(), std::numeric_limits<int32_t>::max()));
397
398 const auto key_size = static_cast<int32_t>(key.size());
399 std::memcpy(&(*metadata_iter), &key_size, sizeof(int32_t));
400 std::advance(metadata_iter, sizeof(int32_t));
401
402 sparrow::ranges::copy(key, &(*metadata_iter));
403 std::advance(metadata_iter, key.size());
404
405 const auto value_size = static_cast<int32_t>(value.size());
406 std::memcpy(&(*metadata_iter), &value_size, sizeof(int32_t));
407 std::advance(metadata_iter, sizeof(int32_t));
408
409 sparrow::ranges::copy(value, &(*metadata_iter));
410 std::advance(metadata_iter, value.size());
411 }
412 return metadata_buf;
413 }
414}
415
416
417#if defined(__cpp_lib_format)
418
419
420template <>
421struct std::formatter<sparrow::key_value_view>
422{
423 constexpr auto parse(std::format_parse_context& ctx)
424 {
425 return ctx.begin(); // Simple implementation
426 }
427
428 auto format(const sparrow::key_value_view& array, std::format_context& ctx) const
429 {
430 auto out = ctx.out();
431 *out++ = '<';
432
433 bool first = true;
434 for (const auto& elem : array)
435 {
436 if (!first)
437 {
438 *out++ = ',';
439 *out++ = ' ';
440 }
441 out = std::format_to(out, "({}:{})", elem.first, elem.second);
442 first = false;
443 }
444
445 *out++ = '>';
446 return out;
447 }
448};
449
450namespace sparrow
451{
452 inline std::ostream& operator<<(std::ostream& os, const key_value_view& value)
453 {
454 os << std::format("{}", value);
455 return os;
456 }
457}
458
459#endif
SPARROW_API key_value_view_iterator operator++(int)
Advances the iterator to the next key-value pair.
std::forward_iterator_tag iterator_concept
Definition metadata.hpp:114
SPARROW_API key_value_view_iterator & operator++()
Advances the iterator to the next key-value pair.
metadata_pair_const_reference value_type
Definition metadata.hpp:110
friend bool operator==(const key_value_view_iterator &lhs, const key_value_view_iterator &rhs)
Equality comparison operator for iterators.
Definition metadata.hpp:170
std::forward_iterator_tag iterator_category
Definition metadata.hpp:99
SPARROW_API key_value_view_iterator(const key_value_view &parent, int32_t index)
Constructs an iterator for the given view at the specified index.
SPARROW_API value_type operator*() const
Dereferences the iterator to get the current key-value pair.
Custom view for lazily extracting key-value pairs from a binary buffer.
Definition metadata.hpp:231
SPARROW_API key_value_view_iterator begin() const
Gets iterator to the beginning of the metadata pairs.
SPARROW_API bool empty() const
SPARROW_API size_t size() const
Gets the number of key-value pairs in the metadata.
SPARROW_API key_value_view_iterator find(std::string_view key) const
SPARROW_API key_value_view_iterator end() const
Gets iterator to the end of the metadata pairs.
SPARROW_API key_value_view_iterator cend() const
Gets const iterator to the end of the metadata pairs.
SPARROW_API key_value_view(const char *ptr)
Constructs a view over the given binary metadata buffer.
SPARROW_API key_value_view_iterator cbegin() const
Gets const iterator to the beginning of the metadata pairs.
Concept for input containers that can provide metadata pairs.
Definition metadata.hpp:332
#define SPARROW_API
Definition config.hpp:38
#define SPARROW_ASSERT_TRUE(expr__)
constexpr std::ranges::copy_result< std::ranges::borrowed_iterator_t< R >, O > copy(R &&r, O result)
Definition ranges.hpp:117
SPARROW_API bool operator==(const array &lhs, const array &rhs)
Compares the content of two arrays.
SPARROW_API int32_t extract_int32(const char *&ptr)
Helper function to extract a 32-bit integer from a character buffer.
std::pair< metadata_key_const_reference, metadata_value_const_reference > metadata_pair_const_reference
Definition metadata.hpp:62
std::string get_metadata_from_key_values(const T &metadata)
Converts a container of key-value pairs to binary metadata format.
Definition metadata.hpp:367
std::string_view metadata_value_const_reference
Definition metadata.hpp:53
std::string_view metadata_key_const_reference
Definition metadata.hpp:44
std::ostream & operator<<(std::ostream &os, const nullval_t &)
std::pair< metadata_key, metadata_value > metadata_pair
Type alias for metadata key-value pairs.
Definition metadata.hpp:61
std::string metadata_key
Type alias for metadata keys.
Definition metadata.hpp:43
std::string metadata_value
Type alias for metadata values.
Definition metadata.hpp:52