1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file |
3 | // distributed with this work for additional information |
4 | // regarding copyright ownership. The ASF licenses this file |
5 | // to you under the Apache License, Version 2.0 (the |
6 | // "License"); you may not use this file except in compliance |
7 | // with the License. You may obtain a copy of the License at |
8 | // |
9 | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | // |
11 | // Unless required by applicable law or agreed to in writing, |
12 | // software distributed under the License is distributed on an |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | // KIND, either express or implied. See the License for the |
15 | // specific language governing permissions and limitations |
16 | // under the License. |
17 | |
18 | #ifndef ARROW_TYPE_TRAITS_H |
19 | #define ARROW_TYPE_TRAITS_H |
20 | |
21 | #include <memory> |
22 | #include <type_traits> |
23 | |
24 | #include "arrow/type_fwd.h" |
25 | #include "arrow/util/bit-util.h" |
26 | |
27 | namespace arrow { |
28 | |
29 | // |
30 | // Per-type type traits |
31 | // |
32 | |
33 | template <typename T> |
34 | struct TypeTraits {}; |
35 | |
36 | template <> |
37 | struct TypeTraits<NullType> { |
38 | using ArrayType = NullArray; |
39 | using BuilderType = NullBuilder; |
40 | constexpr static bool is_parameter_free = false; |
41 | }; |
42 | |
43 | template <> |
44 | struct TypeTraits<UInt8Type> { |
45 | using ArrayType = UInt8Array; |
46 | using BuilderType = UInt8Builder; |
47 | using TensorType = UInt8Tensor; |
48 | static constexpr int64_t bytes_required(int64_t elements) { return elements; } |
49 | constexpr static bool is_parameter_free = true; |
50 | static inline std::shared_ptr<DataType> type_singleton() { return uint8(); } |
51 | }; |
52 | |
53 | template <> |
54 | struct TypeTraits<Int8Type> { |
55 | using ArrayType = Int8Array; |
56 | using BuilderType = Int8Builder; |
57 | using TensorType = Int8Tensor; |
58 | static constexpr int64_t bytes_required(int64_t elements) { return elements; } |
59 | constexpr static bool is_parameter_free = true; |
60 | static inline std::shared_ptr<DataType> type_singleton() { return int8(); } |
61 | }; |
62 | |
63 | template <> |
64 | struct TypeTraits<UInt16Type> { |
65 | using ArrayType = UInt16Array; |
66 | using BuilderType = UInt16Builder; |
67 | using TensorType = UInt16Tensor; |
68 | |
69 | static constexpr int64_t bytes_required(int64_t elements) { |
70 | return elements * sizeof(uint16_t); |
71 | } |
72 | constexpr static bool is_parameter_free = true; |
73 | static inline std::shared_ptr<DataType> type_singleton() { return uint16(); } |
74 | }; |
75 | |
76 | template <> |
77 | struct TypeTraits<Int16Type> { |
78 | using ArrayType = Int16Array; |
79 | using BuilderType = Int16Builder; |
80 | using TensorType = Int16Tensor; |
81 | |
82 | static constexpr int64_t bytes_required(int64_t elements) { |
83 | return elements * sizeof(int16_t); |
84 | } |
85 | constexpr static bool is_parameter_free = true; |
86 | static inline std::shared_ptr<DataType> type_singleton() { return int16(); } |
87 | }; |
88 | |
89 | template <> |
90 | struct TypeTraits<UInt32Type> { |
91 | using ArrayType = UInt32Array; |
92 | using BuilderType = UInt32Builder; |
93 | using TensorType = UInt32Tensor; |
94 | |
95 | static constexpr int64_t bytes_required(int64_t elements) { |
96 | return elements * sizeof(uint32_t); |
97 | } |
98 | constexpr static bool is_parameter_free = true; |
99 | static inline std::shared_ptr<DataType> type_singleton() { return uint32(); } |
100 | }; |
101 | |
102 | template <> |
103 | struct TypeTraits<Int32Type> { |
104 | using ArrayType = Int32Array; |
105 | using BuilderType = Int32Builder; |
106 | using TensorType = Int32Tensor; |
107 | |
108 | static constexpr int64_t bytes_required(int64_t elements) { |
109 | return elements * sizeof(int32_t); |
110 | } |
111 | constexpr static bool is_parameter_free = true; |
112 | static inline std::shared_ptr<DataType> type_singleton() { return int32(); } |
113 | }; |
114 | |
115 | template <> |
116 | struct TypeTraits<UInt64Type> { |
117 | using ArrayType = UInt64Array; |
118 | using BuilderType = UInt64Builder; |
119 | using TensorType = UInt64Tensor; |
120 | |
121 | static constexpr int64_t bytes_required(int64_t elements) { |
122 | return elements * sizeof(uint64_t); |
123 | } |
124 | constexpr static bool is_parameter_free = true; |
125 | static inline std::shared_ptr<DataType> type_singleton() { return uint64(); } |
126 | }; |
127 | |
128 | template <> |
129 | struct TypeTraits<Int64Type> { |
130 | using ArrayType = Int64Array; |
131 | using BuilderType = Int64Builder; |
132 | using TensorType = Int64Tensor; |
133 | |
134 | static constexpr int64_t bytes_required(int64_t elements) { |
135 | return elements * sizeof(int64_t); |
136 | } |
137 | constexpr static bool is_parameter_free = true; |
138 | static inline std::shared_ptr<DataType> type_singleton() { return int64(); } |
139 | }; |
140 | |
141 | template <> |
142 | struct TypeTraits<Date64Type> { |
143 | using ArrayType = Date64Array; |
144 | using BuilderType = Date64Builder; |
145 | |
146 | static constexpr int64_t bytes_required(int64_t elements) { |
147 | return elements * sizeof(int64_t); |
148 | } |
149 | constexpr static bool is_parameter_free = true; |
150 | static inline std::shared_ptr<DataType> type_singleton() { return date64(); } |
151 | }; |
152 | |
153 | template <> |
154 | struct TypeTraits<Date32Type> { |
155 | using ArrayType = Date32Array; |
156 | using BuilderType = Date32Builder; |
157 | |
158 | static constexpr int64_t bytes_required(int64_t elements) { |
159 | return elements * sizeof(int32_t); |
160 | } |
161 | constexpr static bool is_parameter_free = true; |
162 | static inline std::shared_ptr<DataType> type_singleton() { return date32(); } |
163 | }; |
164 | |
165 | template <> |
166 | struct TypeTraits<TimestampType> { |
167 | using ArrayType = TimestampArray; |
168 | using BuilderType = TimestampBuilder; |
169 | |
170 | static constexpr int64_t bytes_required(int64_t elements) { |
171 | return elements * sizeof(int64_t); |
172 | } |
173 | constexpr static bool is_parameter_free = false; |
174 | }; |
175 | |
176 | template <> |
177 | struct TypeTraits<Time32Type> { |
178 | using ArrayType = Time32Array; |
179 | using BuilderType = Time32Builder; |
180 | |
181 | static constexpr int64_t bytes_required(int64_t elements) { |
182 | return elements * sizeof(int32_t); |
183 | } |
184 | constexpr static bool is_parameter_free = false; |
185 | }; |
186 | |
187 | template <> |
188 | struct TypeTraits<Time64Type> { |
189 | using ArrayType = Time64Array; |
190 | using BuilderType = Time64Builder; |
191 | |
192 | static constexpr int64_t bytes_required(int64_t elements) { |
193 | return elements * sizeof(int64_t); |
194 | } |
195 | constexpr static bool is_parameter_free = false; |
196 | }; |
197 | |
198 | template <> |
199 | struct TypeTraits<HalfFloatType> { |
200 | using ArrayType = HalfFloatArray; |
201 | using BuilderType = HalfFloatBuilder; |
202 | using TensorType = HalfFloatTensor; |
203 | |
204 | static constexpr int64_t bytes_required(int64_t elements) { |
205 | return elements * sizeof(uint16_t); |
206 | } |
207 | constexpr static bool is_parameter_free = true; |
208 | static inline std::shared_ptr<DataType> type_singleton() { return float16(); } |
209 | }; |
210 | |
211 | template <> |
212 | struct TypeTraits<FloatType> { |
213 | using ArrayType = FloatArray; |
214 | using BuilderType = FloatBuilder; |
215 | using TensorType = FloatTensor; |
216 | |
217 | static constexpr int64_t bytes_required(int64_t elements) { |
218 | return static_cast<int64_t>(elements * sizeof(float)); |
219 | } |
220 | constexpr static bool is_parameter_free = true; |
221 | static inline std::shared_ptr<DataType> type_singleton() { return float32(); } |
222 | }; |
223 | |
224 | template <> |
225 | struct TypeTraits<DoubleType> { |
226 | using ArrayType = DoubleArray; |
227 | using BuilderType = DoubleBuilder; |
228 | using TensorType = DoubleTensor; |
229 | |
230 | static constexpr int64_t bytes_required(int64_t elements) { |
231 | return static_cast<int64_t>(elements * sizeof(double)); |
232 | } |
233 | constexpr static bool is_parameter_free = true; |
234 | static inline std::shared_ptr<DataType> type_singleton() { return float64(); } |
235 | }; |
236 | |
237 | template <> |
238 | struct TypeTraits<Decimal128Type> { |
239 | using ArrayType = Decimal128Array; |
240 | using BuilderType = Decimal128Builder; |
241 | constexpr static bool is_parameter_free = false; |
242 | }; |
243 | |
244 | template <> |
245 | struct TypeTraits<BooleanType> { |
246 | using ArrayType = BooleanArray; |
247 | using BuilderType = BooleanBuilder; |
248 | |
249 | static constexpr int64_t bytes_required(int64_t elements) { |
250 | return BitUtil::BytesForBits(elements); |
251 | } |
252 | constexpr static bool is_parameter_free = true; |
253 | static inline std::shared_ptr<DataType> type_singleton() { return boolean(); } |
254 | }; |
255 | |
256 | template <> |
257 | struct TypeTraits<StringType> { |
258 | using ArrayType = StringArray; |
259 | using BuilderType = StringBuilder; |
260 | constexpr static bool is_parameter_free = true; |
261 | static inline std::shared_ptr<DataType> type_singleton() { return utf8(); } |
262 | }; |
263 | |
264 | template <> |
265 | struct TypeTraits<BinaryType> { |
266 | using ArrayType = BinaryArray; |
267 | using BuilderType = BinaryBuilder; |
268 | constexpr static bool is_parameter_free = true; |
269 | static inline std::shared_ptr<DataType> type_singleton() { return binary(); } |
270 | }; |
271 | |
272 | template <> |
273 | struct TypeTraits<FixedSizeBinaryType> { |
274 | using ArrayType = FixedSizeBinaryArray; |
275 | using BuilderType = FixedSizeBinaryBuilder; |
276 | constexpr static bool is_parameter_free = false; |
277 | }; |
278 | |
279 | template <> |
280 | struct TypeTraits<ListType> { |
281 | using ArrayType = ListArray; |
282 | using BuilderType = ListBuilder; |
283 | constexpr static bool is_parameter_free = false; |
284 | }; |
285 | |
286 | template <> |
287 | struct TypeTraits<StructType> { |
288 | using ArrayType = StructArray; |
289 | using BuilderType = StructBuilder; |
290 | constexpr static bool is_parameter_free = false; |
291 | }; |
292 | |
293 | template <> |
294 | struct TypeTraits<UnionType> { |
295 | using ArrayType = UnionArray; |
296 | constexpr static bool is_parameter_free = false; |
297 | }; |
298 | |
299 | template <> |
300 | struct TypeTraits<DictionaryType> { |
301 | using ArrayType = DictionaryArray; |
302 | constexpr static bool is_parameter_free = false; |
303 | }; |
304 | |
305 | // |
306 | // Useful type predicates |
307 | // |
308 | |
309 | template <typename T> |
310 | using is_number = std::is_base_of<Number, T>; |
311 | |
312 | template <typename T> |
313 | struct has_c_type { |
314 | static constexpr bool value = |
315 | (std::is_base_of<PrimitiveCType, T>::value || std::is_base_of<DateType, T>::value || |
316 | std::is_base_of<TimeType, T>::value || std::is_base_of<TimestampType, T>::value); |
317 | }; |
318 | |
319 | template <typename T> |
320 | struct is_8bit_int { |
321 | static constexpr bool value = |
322 | (std::is_same<UInt8Type, T>::value || std::is_same<Int8Type, T>::value); |
323 | }; |
324 | |
325 | template <typename T> |
326 | using enable_if_8bit_int = typename std::enable_if<is_8bit_int<T>::value>::type; |
327 | |
328 | template <typename T> |
329 | using enable_if_primitive_ctype = |
330 | typename std::enable_if<std::is_base_of<PrimitiveCType, T>::value>::type; |
331 | |
332 | template <typename T> |
333 | using enable_if_date = typename std::enable_if<std::is_base_of<DateType, T>::value>::type; |
334 | |
335 | template <typename T> |
336 | using enable_if_integer = |
337 | typename std::enable_if<std::is_base_of<Integer, T>::value>::type; |
338 | |
339 | template <typename T> |
340 | using enable_if_signed_integer = |
341 | typename std::enable_if<std::is_base_of<Integer, T>::value && |
342 | std::is_signed<typename T::c_type>::value>::type; |
343 | |
344 | template <typename T> |
345 | using enable_if_unsigned_integer = |
346 | typename std::enable_if<std::is_base_of<Integer, T>::value && |
347 | std::is_unsigned<typename T::c_type>::value>::type; |
348 | |
349 | template <typename T> |
350 | using enable_if_floating_point = |
351 | typename std::enable_if<std::is_base_of<FloatingPoint, T>::value>::type; |
352 | |
353 | template <typename T> |
354 | using enable_if_time = typename std::enable_if<std::is_base_of<TimeType, T>::value>::type; |
355 | |
356 | template <typename T> |
357 | using enable_if_timestamp = |
358 | typename std::enable_if<std::is_base_of<TimestampType, T>::value>::type; |
359 | |
360 | template <typename T> |
361 | using enable_if_has_c_type = typename std::enable_if<has_c_type<T>::value>::type; |
362 | |
363 | template <typename T> |
364 | using enable_if_null = typename std::enable_if<std::is_same<NullType, T>::value>::type; |
365 | |
366 | template <typename T> |
367 | using enable_if_binary = |
368 | typename std::enable_if<std::is_base_of<BinaryType, T>::value>::type; |
369 | |
370 | template <typename T> |
371 | using enable_if_boolean = |
372 | typename std::enable_if<std::is_same<BooleanType, T>::value>::type; |
373 | |
374 | template <typename T> |
375 | using enable_if_binary_like = |
376 | typename std::enable_if<std::is_base_of<BinaryType, T>::value || |
377 | std::is_base_of<FixedSizeBinaryType, T>::value>::type; |
378 | |
379 | template <typename T> |
380 | using enable_if_fixed_size_binary = |
381 | typename std::enable_if<std::is_base_of<FixedSizeBinaryType, T>::value>::type; |
382 | |
383 | template <typename T> |
384 | using enable_if_list = typename std::enable_if<std::is_base_of<ListType, T>::value>::type; |
385 | |
386 | template <typename T> |
387 | using enable_if_number = typename std::enable_if<is_number<T>::value>::type; |
388 | |
389 | namespace detail { |
390 | |
391 | // Not all type classes have a c_type |
392 | template <typename T> |
393 | struct as_void { |
394 | using type = void; |
395 | }; |
396 | |
397 | // The partial specialization will match if T has the ATTR_NAME member |
398 | #define GET_ATTR(ATTR_NAME, DEFAULT) \ |
399 | template <typename T, typename Enable = void> \ |
400 | struct GetAttr_##ATTR_NAME { \ |
401 | using type = DEFAULT; \ |
402 | }; \ |
403 | \ |
404 | template <typename T> \ |
405 | struct GetAttr_##ATTR_NAME<T, typename as_void<typename T::ATTR_NAME>::type> { \ |
406 | using type = typename T::ATTR_NAME; \ |
407 | }; |
408 | |
409 | GET_ATTR(c_type, void) |
410 | GET_ATTR(TypeClass, void) |
411 | |
412 | #undef GET_ATTR |
413 | |
414 | } // namespace detail |
415 | |
416 | #define PRIMITIVE_TRAITS(T) \ |
417 | using TypeClass = \ |
418 | typename std::conditional<std::is_base_of<DataType, T>::value, T, \ |
419 | typename detail::GetAttr_TypeClass<T>::type>::type; \ |
420 | using c_type = typename detail::GetAttr_c_type<TypeClass>::type |
421 | |
422 | template <typename T> |
423 | struct IsUnsignedInt { |
424 | PRIMITIVE_TRAITS(T); |
425 | static constexpr bool value = |
426 | std::is_integral<c_type>::value && std::is_unsigned<c_type>::value; |
427 | }; |
428 | |
429 | template <typename T> |
430 | struct IsSignedInt { |
431 | PRIMITIVE_TRAITS(T); |
432 | static constexpr bool value = |
433 | std::is_integral<c_type>::value && std::is_signed<c_type>::value; |
434 | }; |
435 | |
436 | template <typename T> |
437 | struct IsInteger { |
438 | PRIMITIVE_TRAITS(T); |
439 | static constexpr bool value = std::is_integral<c_type>::value; |
440 | }; |
441 | |
442 | template <typename T> |
443 | struct IsFloatingPoint { |
444 | PRIMITIVE_TRAITS(T); |
445 | static constexpr bool value = std::is_floating_point<c_type>::value; |
446 | }; |
447 | |
448 | template <typename T> |
449 | struct IsNumeric { |
450 | PRIMITIVE_TRAITS(T); |
451 | static constexpr bool value = std::is_arithmetic<c_type>::value; |
452 | }; |
453 | |
454 | static inline bool is_integer(Type::type type_id) { |
455 | switch (type_id) { |
456 | case Type::UINT8: |
457 | case Type::INT8: |
458 | case Type::UINT16: |
459 | case Type::INT16: |
460 | case Type::UINT32: |
461 | case Type::INT32: |
462 | case Type::UINT64: |
463 | case Type::INT64: |
464 | return true; |
465 | default: |
466 | break; |
467 | } |
468 | return false; |
469 | } |
470 | |
471 | static inline bool is_floating(Type::type type_id) { |
472 | switch (type_id) { |
473 | case Type::HALF_FLOAT: |
474 | case Type::FLOAT: |
475 | case Type::DOUBLE: |
476 | return true; |
477 | default: |
478 | break; |
479 | } |
480 | return false; |
481 | } |
482 | |
483 | static inline bool is_primitive(Type::type type_id) { |
484 | switch (type_id) { |
485 | case Type::NA: |
486 | case Type::BOOL: |
487 | case Type::UINT8: |
488 | case Type::INT8: |
489 | case Type::UINT16: |
490 | case Type::INT16: |
491 | case Type::UINT32: |
492 | case Type::INT32: |
493 | case Type::UINT64: |
494 | case Type::INT64: |
495 | case Type::HALF_FLOAT: |
496 | case Type::FLOAT: |
497 | case Type::DOUBLE: |
498 | case Type::DATE32: |
499 | case Type::DATE64: |
500 | case Type::TIME32: |
501 | case Type::TIME64: |
502 | case Type::TIMESTAMP: |
503 | case Type::INTERVAL: |
504 | return true; |
505 | default: |
506 | break; |
507 | } |
508 | return false; |
509 | } |
510 | |
511 | static inline bool is_binary_like(Type::type type_id) { |
512 | switch (type_id) { |
513 | case Type::BINARY: |
514 | case Type::STRING: |
515 | return true; |
516 | default: |
517 | break; |
518 | } |
519 | return false; |
520 | } |
521 | |
522 | static inline bool is_dictionary(Type::type type_id) { |
523 | return type_id == Type::DICTIONARY; |
524 | } |
525 | |
526 | } // namespace arrow |
527 | |
528 | #endif // ARROW_TYPE_TRAITS_H |
529 | |