Vowpal Wabbit
v_array.h
Go to the documentation of this file.
1 /*
2 Copyright (c) by respective owners including Yahoo!, Microsoft, and
3 individual contributors. All rights reserved. Released under a BSD
4 license as described in the file LICENSE.
5  */
6 
7 #pragma once
8 #define NOMINMAX
9 #include <iostream>
10 #include <algorithm>
11 #include <cstdlib>
12 #include <cstring>
13 #include <cassert>
14 #include <cstdint>
15 
16 #ifdef _WIN32
17 #define __INLINE
18 #else
19 #define __INLINE inline
20 #endif
21 
22 #ifndef VW_NOEXCEPT
23 #include "vw_exception.h"
24 #endif
25 
26 #include "memory.h"
27 
28 const size_t erase_point = ~((1u << 10u) - 1u);
29 
30 template <class T>
31 struct v_array
32 {
33  // private:
34  T* _begin;
35  T* _end;
36 
37  public:
39  size_t erase_count;
40 
41  // enable C++ 11 for loops
42  inline T*& begin() { return _begin; }
43  inline T*& end() { return _end; }
44 
45  inline const T* begin() const { return _begin; }
46  inline const T* end() const { return _end; }
47 
48  inline T* cbegin() const { return _begin; }
49  inline T* cend() const { return _end; }
50 
51  // v_array cannot have a user-defined constructor, because it participates in various unions.
52  // union members cannot have user-defined constructors.
53  // v_array() : _begin(nullptr), _end(nullptr), end_array(nullptr), erase_count(0) {}
54  // ~v_array() {
55  // delete_v();
56  // }
57  T last() const { return *(_end - 1); }
58  T pop() { return *(--_end); }
59  bool empty() const { return _begin == _end; }
60  void decr() { _end--; }
61  void incr()
62  {
63  if (_end == end_array)
64  resize(2 * (end_array - _begin) + 3);
65  _end++;
66  }
67  T& operator[](size_t i) const { return _begin[i]; }
68  inline size_t size() const { return _end - _begin; }
69  void resize(size_t length)
70  {
71  if ((size_t)(end_array - _begin) != length)
72  {
73  size_t old_len = _end - _begin;
74  T* temp = (T*)realloc(_begin, sizeof(T) * length);
75  if ((temp == nullptr) && ((sizeof(T) * length) > 0))
76  {
77  THROW_OR_RETURN("realloc of " << length << " failed in resize(). out of memory?");
78  }
79  else
80  _begin = temp;
81  if (old_len < length && _begin + old_len != nullptr)
82  memset(_begin + old_len, 0, (length - old_len) * sizeof(T));
83  _end = _begin + old_len;
84  end_array = _begin + length;
85  }
86  }
87 
88  void clear()
89  {
90  if (++erase_count & erase_point)
91  {
92  resize(_end - _begin);
93  erase_count = 0;
94  }
95  for (T* item = _begin; item != _end; ++item) item->~T();
96  _end = _begin;
97  }
98  void delete_v()
99  {
100  if (_begin != nullptr)
101  {
102  for (T* item = _begin; item != _end; ++item) item->~T();
103  free(_begin);
104  }
105  _begin = _end = end_array = nullptr;
106  }
107  void push_back(const T& new_ele)
108  {
109  if (_end == end_array)
110  resize(2 * (end_array - _begin) + 3);
111  new (_end++) T(new_ele);
112  }
113  void push_back_unchecked(const T& new_ele) { new (_end++) T(new_ele); }
114 
115  size_t find_sorted(const T& ele) const // index of the smallest element >= ele, return true if element is in the
116  // array
117  {
118  size_t size = _end - _begin;
119  size_t a = 0;
120  size_t b = size;
121  size_t i = (a + b) / 2;
122 
123  while (b - a > 1)
124  {
125  if (_begin[i] < ele) // if a = 0, size = 1, if in while we have b - a >= 1 the loop is infinite
126  a = i;
127  else if (_begin[i] > ele)
128  b = i;
129  else
130  return i;
131 
132  i = (a + b) / 2;
133  }
134 
135  if ((size == 0) || (_begin[a] > ele) || (_begin[a] == ele)) // pusta tablica, nie wchodzi w while
136  return a;
137  else // size = 1, ele = 1, _begin[0] = 0
138  return b;
139  }
140  size_t unique_add_sorted(const T& new_ele)
141  {
142  size_t index = 0;
143  size_t size = _end - _begin;
144  size_t to_move;
145 
146  if (!contain_sorted(new_ele, index))
147  {
148  if (_end == end_array)
149  resize(2 * (end_array - _begin) + 3);
150 
151  to_move = size - index;
152 
153  if (to_move > 0)
154  memmove(_begin + index + 1, _begin + index,
155  to_move * sizeof(T)); // kopiuje to_move*.. bytow z _begin+index do _begin+index+1
156 
157  _begin[index] = new_ele;
158 
159  _end++;
160  }
161 
162  return index;
163  }
164  bool contain_sorted(const T& ele, size_t& index)
165  {
166  index = find_sorted(ele);
167 
168  if (index == this->size())
169  return false;
170 
171  if (_begin[index] == ele)
172  return true;
173 
174  return false;
175  }
176 };
177 
178 template <class T>
180 {
181  return {nullptr, nullptr, nullptr, 0};
182 }
183 
184 template <class T>
185 void copy_array(v_array<T>& dst, const v_array<T>& src)
186 {
187  dst.clear();
188  push_many(dst, src._begin, src.size());
189 }
190 
191 // use to copy arrays of types with non-trivial copy constructors, such as shared_ptr
192 template <class T>
194 {
195  dst.clear();
196  for (T* item = src._begin; item != src._end; ++item) dst.push_back(*item);
197 }
198 
199 template <class T>
200 void copy_array(v_array<T>& dst, const v_array<T>& src, T (*copy_item)(T&))
201 {
202  dst.clear();
203  for (T* item = src._begin; item != src._end; ++item) dst.push_back(copy_item(*item));
204 }
205 
206 template <class T>
207 void push_many(v_array<T>& v, const T* _begin, size_t num)
208 {
209  if (v._end + num >= v.end_array)
210  v.resize(std::max(2 * (size_t)(v.end_array - v._begin) + 3, v._end - v._begin + num));
211 #ifdef _WIN32
212  memcpy_s(v._end, v.size() - (num * sizeof(T)), _begin, num * sizeof(T));
213 #else
214  memcpy(v._end, _begin, num * sizeof(T));
215 #endif
216  v._end += num;
217 }
218 
219 template <class T>
220 void calloc_reserve(v_array<T>& v, size_t length)
221 {
222  v._begin = calloc_or_throw<T>(length);
223  v._end = v._begin;
224  v.end_array = v._begin + length;
225 }
226 
227 template <class T>
229 {
230  if (stack._end != stack._begin)
231  return *(--stack._end);
232  else
233  return v_array<T>();
234 }
235 
236 template <class T>
238 {
239  for (T* e = A._begin; e != A._end; ++e)
240  if (*e == x)
241  return true;
242  return false;
243 }
244 
245 template <class T>
246 std::ostream& operator<<(std::ostream& os, const v_array<T>& v)
247 {
248  os << '[';
249  for (T* i = v._begin; i != v._end; ++i) os << ' ' << *i;
250  os << " ]";
251  return os;
252 }
253 
254 template <class T, class U>
255 std::ostream& operator<<(std::ostream& os, const v_array<std::pair<T, U> >& v)
256 {
257  os << '[';
258  for (std::pair<T, U>* i = v._begin; i != v._end; ++i) os << ' ' << i->first << ':' << i->second;
259  os << " ]";
260  return os;
261 }
262 
264 
265 inline v_string string2v_string(const std::string& s)
266 {
267  v_string res = v_init<unsigned char>();
268  if (!s.empty())
269  push_many(res, (unsigned char*)s.data(), s.size());
270  return res;
271 }
272 
273 inline std::string v_string2string(const v_string& v_s)
274 {
275  std::string res;
276  for (unsigned char* i = v_s._begin; i != v_s._end; ++i) res.push_back(*i);
277  return res;
278 }
void resize(size_t length)
Definition: v_array.h:69
void incr()
Definition: v_array.h:61
T pop()
Definition: v_array.h:58
const size_t erase_point
Definition: v_array.h:28
void copy_array(v_array< T > &dst, const v_array< T > &src)
Definition: v_array.h:185
T * cbegin() const
Definition: v_array.h:48
T *& begin()
Definition: v_array.h:42
v_array< unsigned char > v_string
Definition: v_array.h:263
size_t size() const
Definition: v_array.h:68
T * cend() const
Definition: v_array.h:49
void push_many(v_array< T > &v, const T *_begin, size_t num)
Definition: v_array.h:207
v_array< T > v_init()
Definition: v_array.h:179
void copy_array_no_memcpy(v_array< T > &dst, const v_array< T > &src)
Definition: v_array.h:193
void push_back(const T &new_ele)
Definition: v_array.h:107
size_t find_sorted(const T &ele) const
Definition: v_array.h:115
v_string string2v_string(const std::string &s)
Definition: v_array.h:265
void clear()
Definition: v_array.h:88
T * _end
Definition: v_array.h:35
size_t erase_count
Definition: v_array.h:39
const T * begin() const
Definition: v_array.h:45
void calloc_reserve(v_array< T > &v, size_t length)
Definition: v_array.h:220
const T * end() const
Definition: v_array.h:46
T *& end()
Definition: v_array.h:43
T & operator[](size_t i) const
Definition: v_array.h:67
constexpr uint64_t a
Definition: rand48.cc:11
#define THROW_OR_RETURN(...)
Definition: vw_exception.h:208
bool empty() const
Definition: v_array.h:59
T last() const
Definition: v_array.h:57
void delete_v()
Definition: v_array.h:98
T * _begin
Definition: v_array.h:34
bool v_array_contains(v_array< T > &A, T x)
Definition: v_array.h:237
void decr()
Definition: v_array.h:60
std::string v_string2string(const v_string &v_s)
Definition: v_array.h:273
bool contain_sorted(const T &ele, size_t &index)
Definition: v_array.h:164
size_t unique_add_sorted(const T &new_ele)
Definition: v_array.h:140
void push_back_unchecked(const T &new_ele)
Definition: v_array.h:113
T * end_array
Definition: v_array.h:38