JSON Voorhees
Killer JSON for C++
Loading...
Searching...
No Matches
basic_view.hpp
Go to the documentation of this file.
1/// \file jsonv/detail/basic_view.hpp
2///
3/// Copyright (c) 2014-2020 by Travis Gockel. All rights reserved.
4///
5/// This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
6/// as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
7/// version.
8///
9/// \author Travis Gockel (travis@gockelhut.com)
10#pragma once
11
12#include <jsonv/config.hpp>
13
14#include <iterator>
15#include <utility>
16
17namespace jsonv::detail
18{
19
20/// A view template used for array and object views of a \c value. This class allows traversing a \c value with a range
21/// based for loop.
22///
23/// \note
24/// A view does nothing to preserve the lifetime of the underlying container, nor does it remain valid if the container
25/// is modified.
26template <typename TIterator,
27 typename TConstIterator = TIterator
28 >
29class basic_view
30{
31public:
32 typedef TIterator iterator;
33 typedef TConstIterator const_iterator;
34 typedef std::reverse_iterator<iterator> reverse_iterator;
35 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
36 typedef typename std::iterator_traits<iterator>::value_type value_type;
37 typedef typename std::iterator_traits<iterator>::reference reference;
38 typedef typename std::iterator_traits<iterator>::pointer pointer;
39
40public:
41 basic_view(iterator begin_, iterator end_) :
42 _begin(begin_),
43 _end(end_)
44 { }
45
47 iterator begin() { return _begin; }
49 const_iterator begin() const { return _begin; }
51 iterator end() { return _end; }
53 const_iterator end() const { return _end; }
54
56 const_iterator cbegin() const { return _begin; }
58 const_iterator cend() const { return _end; }
59
61 reverse_iterator rbegin() { return reverse_iterator(end()); };
63 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
65 reverse_iterator rend() { return reverse_iterator(begin()); }
67 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
68
70 const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
72 const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
73
74private:
75 iterator _begin;
76 iterator _end;
77};
78
79/// Something that owns an object. Used in basic_owning_view to move the value somewhere fixed before getting the
80/// itertors and constructing the base.
81template <typename T>
82class basic_owner
83{
84public:
85 explicit basic_owner(T&& x) :
86 _value(std::move(x))
87 { }
88
89protected:
90 T _value;
91};
92
93/// A form of basic_view that owns the object it is iterating over.
94///
95/// The iterators can refer to the container's address (an array iterator holds a pointer to its \c value), so they
96/// cannot simply be carried along when the view moves. A moved-to view rebuilds them from the container it now owns,
97/// which is why it keeps the functions it was constructed with. For the same reason, an owning view can be moved but
98/// not copied: a copy would own a fresh container while its iterators still pointed into the source's.
99///
100/// A moved-from view is an empty range. It is safe to destroy, assign to, move from again, or iterate (zero times).
101template <typename TContainer,
102 typename TIterator,
103 typename TConstIterator = TIterator
104 >
105class basic_owning_view :
106 private basic_owner<TContainer>,
107 public basic_view<TIterator, TConstIterator>
108{
109 using basic_owner<TContainer>::_value;
110 using view_type = basic_view<TIterator, TConstIterator>;
111
112public:
113 /// A function which finds one end of a container. It must not hold state, so an owning view can keep it.
114 using locate_function = TIterator (*)(TContainer&);
115
116 basic_owning_view(TContainer&& container, locate_function locate_begin, locate_function locate_end) :
117 basic_owner<TContainer>(std::move(container)),
118 view_type(locate_begin(_value), locate_end(_value)),
119 _locate_begin(locate_begin),
120 _locate_end(locate_end)
121 { }
122
123 basic_owning_view(const basic_owning_view&) = delete;
124 basic_owning_view& operator=(const basic_owning_view&) = delete;
125
126 basic_owning_view(basic_owning_view&& src) noexcept :
127 basic_owner<TContainer>(std::move(src._value)),
128 view_type(TIterator(), TIterator()),
129 _locate_begin(nullptr),
130 _locate_end(nullptr)
131 {
132 adopt_view_of(src);
133 }
134
135 basic_owning_view& operator=(basic_owning_view&& src) noexcept
136 {
137 if (this != &src)
138 {
139 _value = std::move(src._value);
140 adopt_view_of(src);
141 }
142
143 return *this;
144 }
145
146private:
147 /// Point this view at the container it now owns, and leave \a src as an empty range. The container has already
148 /// been moved. If \a src was itself moved from, its container is empty and has no ends to find, so this view is
149 /// empty too.
150 void adopt_view_of(basic_owning_view& src) noexcept
151 {
152 _locate_begin = std::exchange(src._locate_begin, nullptr);
153 _locate_end = std::exchange(src._locate_end, nullptr);
154
155 view_type::operator=(_locate_begin ? view_type(_locate_begin(_value), _locate_end(_value))
156 : view_type(TIterator(), TIterator())
157 );
158 src.view_type::operator=(view_type(TIterator(), TIterator()));
159 }
160
161private:
162 locate_function _locate_begin;
163 locate_function _locate_end;
164};
165
166}
Copyright (c) 2014-2020 by Travis Gockel.
#define JSONV_NODISCARD
Warn if the caller discards the result of this function.
Definition config.hpp:143
STL namespace.