IdentifierGeneration.hpp
1 #pragma once
2 #include <score/model/Identifier.hpp>
3 #include <score/tools/std/ArrayView.hpp>
4 #include <score/tools/std/Optional.hpp>
5 
6 #include <sys/types.h>
7 
8 #include <score_lib_base_export.h>
9 
10 #include <cstddef>
11 #include <type_traits>
12 #include <vector>
13 
14 namespace score
15 {
19 struct SCORE_LIB_BASE_EXPORT random_id_generator
20 {
25  static int32_t getRandomId();
26  static int32_t getFirstId() { return getRandomId(); }
27 
34  template <typename Vector>
35  static auto getNextId(const Vector& ids)
36  {
37  typename Vector::value_type id{};
38 
39  constexpr auto fnd = [](const auto& ids, const auto& id) noexcept {
40  for(auto& elt : ids)
41  if(elt == id)
42  return true;
43  return false;
44  };
45 
46  do
47  {
48  id = typename Vector::value_type{getRandomId()};
49  } while(fnd(ids, id));
50 
51  return id;
52  }
53 };
54 
58 struct SCORE_LIB_BASE_EXPORT linear_id_generator
59 {
60  static int32_t getFirstId() { return 1; }
61 
62  template <typename Vector>
63  static auto getNextId(const Vector& ids)
64  {
65  auto it = std::max_element(ids.begin(), ids.end());
66  if(it != ids.end())
67  return typename Vector::value_type{getId(*it) + 1};
68  else
69  return typename Vector::value_type{getFirstId()};
70  }
71 
72 private:
73  template <typename T>
74  static int32_t getId(const Id<T>& other)
75  {
76  return other.val();
77  }
78  static int32_t getId(const std::optional<int32_t>& i) { return *i; }
79  static int32_t getId(int32_t i) { return i; }
80 };
81 
83 }
84 template <typename T>
85 auto getStrongId(const std::vector<Id<T>>& v)
86 {
87  return Id<T>{score::id_generator::getNextId(v)};
88 }
89 
90 template <typename T>
91 auto getStrongId(const score::dynvector_impl<Id<T>>& v)
92 {
93  return Id<T>{score::id_generator::getNextId(v)};
94 }
95 
96 template <typename Container>
97  requires(std::is_pointer<typename Container::value_type>::value)
98 auto getStrongId(const Container& v)
100 {
101  using namespace std;
102  using local_id_t
104  vector<int32_t> ids(v.size()); // Map reduce
105 
106  transform(
107  v.begin(), v.end(), ids.begin(),
108  [](const typename Container::value_type& elt) { return elt->id().val(); });
109 
110  return local_id_t{score::id_generator::getNextId(ids)};
111 }
112 
113 template <typename Container>
114  requires(!std::is_pointer<typename Container::value_type>::value)
115 auto getStrongId(const Container& v) -> Id<typename Container::value_type>
116 {
117  using namespace std;
118  auto ids = make_dynarray(int32_t, v.size());
119 
120  transform(
121  v.begin(), v.end(), ids.begin(), [](const auto& elt) { return elt.id().val(); });
122 
123  return Id<typename Container::value_type>{score::id_generator::getNextId(ids)};
124 }
125 
126 template <typename T>
127 auto getStrongIdRange(std::size_t s)
128 {
129  std::vector<Id<T>> vec;
130  vec.reserve(s);
131  vec.emplace_back(score::id_generator::getFirstId());
132 
133  s--;
134  for(std::size_t i = 0; i < s; i++)
135  {
136  vec.push_back(getStrongId(vec));
137  }
138 
139  return vec;
140 }
141 
142 template <typename T, typename Vector>
143 auto getStrongIdRange(std::size_t s, const Vector& existing)
144 {
145  auto existing_size = existing.size();
146  auto total_size = existing_size + s;
147  std::vector<Id<T>> vec;
148  vec.reserve(total_size);
149 
150  // Copy the existing ids
151  std::transform(
152  existing.begin(), existing.end(), std::back_inserter(vec),
153  [](const auto& elt) { return elt.id(); });
154 
155  // Then generate the new ones
156  for(std::size_t i = 0; i < s; i++)
157  {
158  vec.push_back(getStrongId(vec));
159  }
160 
161  return std::vector<Id<T>>(vec.begin() + existing.size(), vec.end());
162 }
163 
164 template <typename T, typename Vector1, typename Vector2>
165 static auto
166 getStrongIdRange2(std::size_t s, const Vector1& existing1, const Vector2& existing2)
167 {
168  std::vector<Id<T>> vec;
169  vec.reserve(s + existing1.size() + existing2.size());
170  std::transform(
171  existing1.begin(), existing1.end(), std::back_inserter(vec),
172  [](const auto& elt) { return elt.id(); });
173  std::transform(
174  existing2.begin(), existing2.end(), std::back_inserter(vec),
175  [](const auto& elt) { return elt->id(); });
176 
177  for(std::size_t i = 0; i < s; i++)
178  {
179  vec.push_back(getStrongId(vec));
180  }
181  auto final
182  = std::vector<Id<T>>(vec.begin() + existing1.size() + existing2.size(), vec.end());
183 
184  return final;
185 }
186 
187 template <typename T, typename Vector>
188 auto getStrongIdRangePtr(std::size_t s, const Vector& existing)
189 {
190  std::vector<Id<T>> vec;
191  vec.reserve(s + existing.size());
192  std::transform(
193  existing.begin(), existing.end(), std::back_inserter(vec),
194  [](const auto& elt) { return elt->id(); });
195 
196  for(; s-- > 0;)
197  {
198  vec.push_back(getStrongId(vec));
199  }
200 
201  return std::vector<Id<T>>(vec.begin() + existing.size(), vec.end());
202 }
The id_base_t class.
Definition: Identifier.hpp:57
Definition: ArrayView.hpp:54
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Generates identifiers for new objects, starting from 1.
Definition: IdentifierGeneration.hpp:59
Generates random identifiers for new objects.
Definition: IdentifierGeneration.hpp:20
static auto getNextId(const Vector &ids)
getNextId
Definition: IdentifierGeneration.hpp:35