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_STL_H |
19 | #define ARROW_STL_H |
20 | |
21 | #include <memory> |
22 | #include <string> |
23 | #include <tuple> |
24 | #include <vector> |
25 | |
26 | #include "arrow/type.h" |
27 | |
28 | namespace arrow { |
29 | |
30 | class Schema; |
31 | |
32 | namespace stl { |
33 | |
34 | /// Traits meta class to map standard C/C++ types to equivalent Arrow types. |
35 | template <typename T> |
36 | struct ConversionTraits {}; |
37 | |
38 | #define ARROW_STL_CONVERSION(c_type, ArrowType_) \ |
39 | template <> \ |
40 | struct ConversionTraits<c_type> { \ |
41 | static std::shared_ptr<DataType> arrow_type() { \ |
42 | return std::make_shared<ArrowType_>(); \ |
43 | } \ |
44 | constexpr static bool nullable = false; \ |
45 | }; |
46 | |
47 | ARROW_STL_CONVERSION(bool, BooleanType) |
48 | ARROW_STL_CONVERSION(int8_t, Int8Type) |
49 | ARROW_STL_CONVERSION(int16_t, Int16Type) |
50 | ARROW_STL_CONVERSION(int32_t, Int32Type) |
51 | ARROW_STL_CONVERSION(int64_t, Int64Type) |
52 | ARROW_STL_CONVERSION(uint8_t, UInt8Type) |
53 | ARROW_STL_CONVERSION(uint16_t, UInt16Type) |
54 | ARROW_STL_CONVERSION(uint32_t, UInt32Type) |
55 | ARROW_STL_CONVERSION(uint64_t, UInt64Type) |
56 | ARROW_STL_CONVERSION(float, FloatType) |
57 | ARROW_STL_CONVERSION(double, DoubleType) |
58 | ARROW_STL_CONVERSION(std::string, StringType) |
59 | |
60 | template <typename value_c_type> |
61 | struct ConversionTraits<std::vector<value_c_type>> { |
62 | static std::shared_ptr<DataType> arrow_type() { |
63 | return list(ConversionTraits<value_c_type>::arrow_type()); |
64 | } |
65 | constexpr static bool nullable = false; |
66 | }; |
67 | |
68 | /// Build an arrow::Schema based upon the types defined in a std::tuple-like structure. |
69 | /// |
70 | /// While the type information is available at compile-time, we still need to add the |
71 | /// column names at runtime, thus these methods are not constexpr. |
72 | template <typename Tuple, std::size_t N = std::tuple_size<Tuple>::value> |
73 | struct SchemaFromTuple { |
74 | using Element = typename std::tuple_element<N - 1, Tuple>::type; |
75 | |
76 | // Implementations that take a vector-like object for the column names. |
77 | |
78 | /// Recursively build a vector of arrow::Field from the defined types. |
79 | /// |
80 | /// In most cases MakeSchema is the better entrypoint for the Schema creation. |
81 | static std::vector<std::shared_ptr<Field>> MakeSchemaRecursion( |
82 | const std::vector<std::string>& names) { |
83 | std::vector<std::shared_ptr<Field>> ret = |
84 | SchemaFromTuple<Tuple, N - 1>::MakeSchemaRecursion(names); |
85 | std::shared_ptr<DataType> type = ConversionTraits<Element>::arrow_type(); |
86 | ret.push_back(field(names[N - 1], type, ConversionTraits<Element>::nullable)); |
87 | return ret; |
88 | } |
89 | |
90 | /// Build a Schema from the types of the tuple-like structure passed in as template |
91 | /// parameter assign the column names at runtime. |
92 | /// |
93 | /// An example usage of this API can look like the following: |
94 | /// |
95 | /// \code{.cpp} |
96 | /// using TupleType = std::tuple<int, std::vector<std::string>>; |
97 | /// std::shared_ptr<Schema> schema = |
98 | /// SchemaFromTuple<TupleType>::MakeSchema({"int_column", "list_of_strings_column"}); |
99 | /// \endcode |
100 | static std::shared_ptr<Schema> MakeSchema(const std::vector<std::string>& names) { |
101 | return std::make_shared<Schema>(MakeSchemaRecursion(names)); |
102 | } |
103 | |
104 | // Implementations that take a tuple-like object for the column names. |
105 | |
106 | /// Recursively build a vector of arrow::Field from the defined types. |
107 | /// |
108 | /// In most cases MakeSchema is the better entrypoint for the Schema creation. |
109 | template <typename NamesTuple> |
110 | static std::vector<std::shared_ptr<Field>> MakeSchemaRecursionT( |
111 | const NamesTuple& names) { |
112 | std::vector<std::shared_ptr<Field>> ret = |
113 | SchemaFromTuple<Tuple, N - 1>::MakeSchemaRecursionT(names); |
114 | std::shared_ptr<DataType> type = ConversionTraits<Element>::arrow_type(); |
115 | ret.push_back( |
116 | field(std::get<N - 1>(names), type, ConversionTraits<Element>::nullable)); |
117 | return ret; |
118 | } |
119 | |
120 | /// Build a Schema from the types of the tuple-like structure passed in as template |
121 | /// parameter assign the column names at runtime. |
122 | /// |
123 | /// An example usage of this API can look like the following: |
124 | /// |
125 | /// \code{.cpp} |
126 | /// using TupleType = std::tuple<int, std::vector<std::string>>; |
127 | /// std::shared_ptr<Schema> schema = |
128 | /// SchemaFromTuple<TupleType>::MakeSchema({"int_column", "list_of_strings_column"}); |
129 | /// \endcode |
130 | template <typename NamesTuple> |
131 | static std::shared_ptr<Schema> MakeSchema(const NamesTuple& names) { |
132 | return std::make_shared<Schema>(MakeSchemaRecursionT<NamesTuple>(names)); |
133 | } |
134 | }; |
135 | |
136 | template <typename Tuple> |
137 | struct SchemaFromTuple<Tuple, 0> { |
138 | static std::vector<std::shared_ptr<Field>> MakeSchemaRecursion( |
139 | const std::vector<std::string>& names) { |
140 | std::vector<std::shared_ptr<Field>> ret; |
141 | ret.reserve(names.size()); |
142 | return ret; |
143 | } |
144 | |
145 | template <typename NamesTuple> |
146 | static std::vector<std::shared_ptr<Field>> MakeSchemaRecursionT( |
147 | const NamesTuple& names) { |
148 | std::vector<std::shared_ptr<Field>> ret; |
149 | ret.reserve(std::tuple_size<NamesTuple>::value); |
150 | return ret; |
151 | } |
152 | }; |
153 | /// @endcond |
154 | |
155 | } // namespace stl |
156 | } // namespace arrow |
157 | |
158 | #endif // ARROW_STL_H |
159 | |