OmniSciDB  fe05a0c208
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
misc.h
Go to the documentation of this file.
1 /*
2  * Copyright 2019 OmniSci, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SHARED_MISC_H
18 #define SHARED_MISC_H
19 
20 #include <cstdint>
21 #include <deque>
22 #include <iterator>
23 #include <list>
24 #include <set>
25 #include <unordered_set>
26 #include <vector>
27 
28 namespace {
29 
30 template <typename T>
31 constexpr T power(T const a, T const n) {
32  return n ? a * power(a, n - 1) : static_cast<T>(1);
33 }
34 
35 template <typename T, size_t... Indices>
36 constexpr std::array<T, sizeof...(Indices)> powersOfImpl(
37  T const a,
38  std::index_sequence<Indices...>) {
39  return {power(a, static_cast<T>(Indices))...};
40 }
41 
42 } // namespace
43 
44 namespace shared {
45 
46 // source is destructively appended to the back of destination.
47 // source.empty() is true after call. Return number of elements appended.
48 template <typename T>
49 size_t appendMove(std::vector<T>& destination, std::vector<T>& source) {
50  if (source.empty()) {
51  return 0;
52  } else if (destination.empty()) {
53  destination = std::move(source);
54  return destination.size();
55  } else {
56  size_t const source_size = source.size();
57  destination.reserve(destination.size() + source_size);
58  std::move(std::begin(source), std::end(source), std::back_inserter(destination));
59  source.clear();
60  return source_size;
61  }
62 }
63 
64 template <typename... Ts, typename T>
65 bool dynamic_castable_to_any(T const* ptr) {
66  return (... || dynamic_cast<Ts const*>(ptr));
67 }
68 
69 // Helper to print out contents of simple containers (e.g. vector, list, deque)
70 // including nested containers, e.g. 2d vectors, list of vectors, etc.
71 // Base value_type must be a std::is_scalar_v type, though you can add custom
72 // objects below with a new `else if constexpr` block.
73 // Example: VLOG(1) << "container=" << shared::printContainer(container);
74 template <typename CONTAINER>
76  CONTAINER& container;
77 };
78 
79 template <typename CONTAINER>
81  return {container};
82 }
83 
84 template <typename CONTAINER>
85 struct is_std_container : std::false_type {};
86 template <typename T, typename A>
87 struct is_std_container<std::deque<T, A> > : std::true_type {};
88 template <typename T, typename A>
89 struct is_std_container<std::list<T, A> > : std::true_type {};
90 template <typename T, typename A>
91 struct is_std_container<std::set<T, A> > : std::true_type {};
92 template <typename T, typename A>
93 struct is_std_container<std::unordered_set<T, A> > : std::true_type {};
94 template <typename T, typename A>
95 struct is_std_container<std::vector<T, A> > : std::true_type {};
96 
97 template <typename OSTREAM, typename CONTAINER>
98 OSTREAM& operator<<(OSTREAM& os, PrintContainer<CONTAINER> pc) {
99  if (pc.container.empty()) {
100  return os << "()";
101  } else {
103  os << '(';
104  for (auto& container : pc.container) {
105  os << printContainer(container);
106  }
107  } else {
108  for (auto itr = pc.container.begin(); itr != pc.container.end(); ++itr) {
109  if constexpr (std::is_pointer_v<typename CONTAINER::value_type>) {
110  os << (itr == pc.container.begin() ? '(' : ' ') << (void const*)*itr;
111  } else {
112  os << (itr == pc.container.begin() ? '(' : ' ') << *itr;
113  }
114  }
115  }
116  return os << ')';
117  }
118 }
119 
120 // Same as strftime(buf, max, "%F", tm) but guarantees that the year is
121 // zero-padded to a minimum length of 4. Return the number of characters
122 // written, not including null byte. If max is not large enough, return 0.
123 size_t formatDate(char* buf, size_t const max, int64_t const unixtime);
124 
125 // Same as strftime(buf, max, "%F %T", tm) but guarantees that the year is
126 // zero-padded to a minimum length of 4. Return the number of characters
127 // written, not including null byte. If max is not large enough, return 0.
128 // Requirement: 0 <= dimension <= 9.
129 size_t formatDateTime(char* buf,
130  size_t const max,
131  int64_t const timestamp,
132  int const dimension);
133 
134 // Write unixtime in seconds since epoch as "HH:MM:SS" format.
135 size_t formatHMS(char* buf, size_t const max, int64_t const unixtime);
136 
137 // Result of division where quot is floored and rem is unsigned.
138 struct DivUMod {
139  int64_t quot;
140  int64_t rem;
141 };
142 
143 // Requirement: 0 < den
144 inline DivUMod divUMod(int64_t num, int64_t den) {
145  DivUMod div{num / den, num % den};
146  if (div.rem < 0) {
147  --div.quot;
148  div.rem += den;
149  }
150  return div;
151 }
152 
153 // Requirement: 0 < den.
154 inline uint64_t unsignedMod(int64_t num, int64_t den) {
155  int64_t mod = num % den;
156  if (mod < 0) {
157  mod += den;
158  }
159  return mod;
160 }
161 
162 template <typename T, typename U>
163 inline bool contains(const T& container, const U& element) {
164  if (std::find(container.begin(), container.end(), element) == container.end()) {
165  return false;
166  } else {
167  return true;
168  }
169 }
170 
171 // Return constexpr std::array<T, N> of {1, 10, 100, 1000, ..., 10^(N-1)}.
172 template <typename T, size_t N>
173 constexpr std::array<T, N> powersOf(T const a) {
174  return powersOfImpl<T>(a, std::make_index_sequence<N>{});
175 }
176 
177 // May be constexpr in C++20.
178 template <typename TO, typename FROM>
179 TO reinterpretBits(FROM const from) {
180  union {
181  FROM const from;
182  TO const to;
183  } const u{.from = from};
184  return u.to;
185 }
186 
187 } // namespace shared
188 
189 #endif // SHARED_MISC_H
size_t appendMove(std::vector< T > &destination, std::vector< T > &source)
Definition: misc.h:49
bool contains(const T &container, const U &element)
Definition: misc.h:163
int64_t quot
Definition: misc.h:139
EXTENSION_NOINLINE double power(const double x, const double y)
#define TO
size_t formatDateTime(char *buf, size_t const max, int64_t const timestamp, int const dimension)
Definition: misc.cpp:43
constexpr std::array< T, sizeof...(Indices)> powersOfImpl(T const a, std::index_sequence< Indices...>)
Definition: misc.h:36
size_t formatHMS(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:80
TO reinterpretBits(FROM const from)
Definition: misc.h:179
#define FROM
CONTAINER & container
Definition: misc.h:76
char * to
size_t formatDate(char *buf, size_t const max, int64_t const unixtime)
Definition: misc.cpp:25
uint64_t unsignedMod(int64_t num, int64_t den)
Definition: misc.h:154
int64_t rem
Definition: misc.h:140
bool dynamic_castable_to_any(T const *ptr)
Definition: misc.h:65
PrintContainer< CONTAINER > printContainer(CONTAINER &container)
Definition: misc.h:80
constexpr std::array< T, N > powersOf(T const a)
Definition: misc.h:173
DivUMod divUMod(int64_t num, int64_t den)
Definition: misc.h:144