Skip to content

Commit c776574

Browse files
committed
add nanoarrow header
1 parent c5d1536 commit c776574

File tree

1 file changed

+302
-0
lines changed

1 file changed

+302
-0
lines changed
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
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+
#include <vector>
19+
20+
#include "nanoarrow.h"
21+
22+
#ifndef NANOARROW_HPP_INCLUDED
23+
#define NANOARROW_HPP_INCLUDED
24+
25+
/// \defgroup nanoarrow_hpp Nanoarrow C++ Helpers
26+
///
27+
/// The utilities provided in this file are intended to support C++ users
28+
/// of the nanoarrow C library such that C++-style resource allocation
29+
/// and error handling can be used with nanoarrow data structures.
30+
/// These utilities are not intended to mirror the nanoarrow C API.
31+
32+
namespace nanoarrow {
33+
34+
namespace internal {
35+
36+
/// \defgroup nanoarrow_hpp-unique_base Base classes for Unique wrappers
37+
///
38+
/// @{
39+
40+
static inline void init_pointer(struct ArrowSchema* data) { data->release = nullptr; }
41+
42+
static inline void move_pointer(struct ArrowSchema* src, struct ArrowSchema* dst) {
43+
ArrowSchemaMove(src, dst);
44+
}
45+
46+
static inline void release_pointer(struct ArrowSchema* data) {
47+
if (data->release != nullptr) {
48+
data->release(data);
49+
}
50+
}
51+
52+
static inline void init_pointer(struct ArrowArray* data) { data->release = nullptr; }
53+
54+
static inline void move_pointer(struct ArrowArray* src, struct ArrowArray* dst) {
55+
ArrowArrayMove(src, dst);
56+
}
57+
58+
static inline void release_pointer(struct ArrowArray* data) {
59+
if (data->release != nullptr) {
60+
data->release(data);
61+
}
62+
}
63+
64+
static inline void init_pointer(struct ArrowArrayStream* data) {
65+
data->release = nullptr;
66+
}
67+
68+
static inline void move_pointer(struct ArrowArrayStream* src,
69+
struct ArrowArrayStream* dst) {
70+
ArrowArrayStreamMove(src, dst);
71+
}
72+
73+
static inline void release_pointer(ArrowArrayStream* data) {
74+
if (data->release != nullptr) {
75+
data->release(data);
76+
}
77+
}
78+
79+
static inline void init_pointer(struct ArrowBuffer* data) { ArrowBufferInit(data); }
80+
81+
static inline void move_pointer(struct ArrowBuffer* src, struct ArrowBuffer* dst) {
82+
ArrowBufferMove(src, dst);
83+
}
84+
85+
static inline void release_pointer(struct ArrowBuffer* data) { ArrowBufferReset(data); }
86+
87+
static inline void init_pointer(struct ArrowBitmap* data) { ArrowBitmapInit(data); }
88+
89+
static inline void move_pointer(struct ArrowBitmap* src, struct ArrowBitmap* dst) {
90+
ArrowBitmapMove(src, dst);
91+
}
92+
93+
static inline void release_pointer(struct ArrowBitmap* data) { ArrowBitmapReset(data); }
94+
95+
static inline void init_pointer(struct ArrowArrayView* data) {
96+
ArrowArrayViewInitFromType(data, NANOARROW_TYPE_UNINITIALIZED);
97+
}
98+
99+
static inline void move_pointer(struct ArrowArrayView* src, struct ArrowArrayView* dst) {
100+
ArrowArrayViewMove(src, dst);
101+
}
102+
103+
static inline void release_pointer(struct ArrowArrayView* data) {
104+
ArrowArrayViewReset(data);
105+
}
106+
107+
/// \brief A unique_ptr-like base class for stack-allocatable objects
108+
/// \tparam T The object type
109+
template <typename T>
110+
class Unique {
111+
public:
112+
/// \brief Construct an invalid instance of T holding no resources
113+
Unique() { init_pointer(&data_); }
114+
115+
/// \brief Move and take ownership of data
116+
Unique(T* data) { move_pointer(data, &data_); }
117+
118+
/// \brief Move and take ownership of data wrapped by rhs
119+
Unique(Unique&& rhs) : Unique(rhs.get()) {}
120+
121+
// These objects are not copyable
122+
Unique(Unique& rhs) = delete;
123+
124+
/// \brief Get a pointer to the data owned by this object
125+
T* get() noexcept { return &data_; }
126+
127+
/// \brief Use the pointer operator to access fields of this object
128+
T* operator->() { return &data_; }
129+
130+
/// \brief Call data's release callback if valid
131+
void reset() { release_pointer(&data_); }
132+
133+
/// \brief Call data's release callback if valid and move ownership of the data
134+
/// pointed to by data
135+
void reset(T* data) {
136+
reset();
137+
move_pointer(data, &data_);
138+
}
139+
140+
/// \brief Move ownership of this object to the data pointed to by out
141+
void move(T* out) { move_pointer(&data_, out); }
142+
143+
~Unique() { reset(); }
144+
145+
protected:
146+
T data_;
147+
};
148+
149+
/// @}
150+
151+
} // namespace internal
152+
153+
/// \defgroup nanoarrow_hpp-unique Unique object wrappers
154+
///
155+
/// The Arrow C Data interface, the Arrow C Stream interface, and the
156+
/// nanoarrow C library use stack-allocatable objects, some of which
157+
/// require initialization or cleanup.
158+
///
159+
/// @{
160+
161+
/// \brief Class wrapping a unique struct ArrowSchema
162+
using UniqueSchema = internal::Unique<struct ArrowSchema>;
163+
164+
/// \brief Class wrapping a unique struct ArrowArray
165+
using UniqueArray = internal::Unique<struct ArrowArray>;
166+
167+
/// \brief Class wrapping a unique struct ArrowArrayStream
168+
using UniqueArrayStream = internal::Unique<struct ArrowArrayStream>;
169+
170+
/// \brief Class wrapping a unique struct ArrowBuffer
171+
using UniqueBuffer = internal::Unique<struct ArrowBuffer>;
172+
173+
/// \brief Class wrapping a unique struct ArrowBitmap
174+
using UniqueBitmap = internal::Unique<struct ArrowBitmap>;
175+
176+
/// \brief Class wrapping a unique struct ArrowArrayView
177+
using UniqueArrayView = internal::Unique<struct ArrowArrayView>;
178+
179+
/// @}
180+
181+
/// \defgroup nanoarrow_hpp-array-stream ArrayStream helpers
182+
///
183+
/// These classes provide simple struct ArrowArrayStream implementations that
184+
/// can be extended to help simplify the process of creating a valid
185+
/// ArrowArrayStream implementation or used as-is for testing.
186+
///
187+
/// @{
188+
189+
/// \brief An empty array stream
190+
///
191+
/// This class can be constructed from an enum ArrowType or
192+
/// struct ArrowSchema and implements a default get_next() method that
193+
/// always marks the output ArrowArray as released. This class can
194+
/// be extended with an implementation of get_next() for a custom
195+
/// source.
196+
class EmptyArrayStream {
197+
public:
198+
/// \brief Create an empty UniqueArrayStream from a struct ArrowSchema
199+
///
200+
/// This object takes ownership of the schema and marks the source schema
201+
/// as released.
202+
static UniqueArrayStream MakeUnique(struct ArrowSchema* schema) {
203+
UniqueArrayStream stream;
204+
(new EmptyArrayStream(schema))->MakeStream(stream.get());
205+
return stream;
206+
}
207+
208+
virtual ~EmptyArrayStream() {}
209+
210+
protected:
211+
UniqueSchema schema_;
212+
struct ArrowError error_;
213+
214+
EmptyArrayStream(struct ArrowSchema* schema) : schema_(schema) {
215+
error_.message[0] = '\0';
216+
}
217+
218+
void MakeStream(struct ArrowArrayStream* stream) {
219+
stream->get_schema = &get_schema_wrapper;
220+
stream->get_next = &get_next_wrapper;
221+
stream->get_last_error = &get_last_error_wrapper;
222+
stream->release = &release_wrapper;
223+
stream->private_data = this;
224+
}
225+
226+
virtual int get_schema(struct ArrowSchema* schema) {
227+
return ArrowSchemaDeepCopy(schema_.get(), schema);
228+
}
229+
230+
virtual int get_next(struct ArrowArray* array) {
231+
array->release = nullptr;
232+
return NANOARROW_OK;
233+
}
234+
235+
virtual const char* get_last_error() { return error_.message; }
236+
237+
private:
238+
static int get_schema_wrapper(struct ArrowArrayStream* stream,
239+
struct ArrowSchema* schema) {
240+
return reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_schema(schema);
241+
}
242+
243+
static int get_next_wrapper(struct ArrowArrayStream* stream, struct ArrowArray* array) {
244+
return reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_next(array);
245+
}
246+
247+
static const char* get_last_error_wrapper(struct ArrowArrayStream* stream) {
248+
return reinterpret_cast<EmptyArrayStream*>(stream->private_data)->get_last_error();
249+
}
250+
251+
static void release_wrapper(struct ArrowArrayStream* stream) {
252+
delete reinterpret_cast<EmptyArrayStream*>(stream->private_data);
253+
}
254+
};
255+
256+
/// \brief Implementation of an ArrowArrayStream backed by a vector of ArrowArray objects
257+
class VectorArrayStream : public EmptyArrayStream {
258+
public:
259+
/// \brief Create a UniqueArrowArrayStream from an existing array
260+
///
261+
/// Takes ownership of the schema and the array.
262+
static UniqueArrayStream MakeUnique(struct ArrowSchema* schema,
263+
struct ArrowArray* array) {
264+
std::vector<UniqueArray> arrays;
265+
arrays.emplace_back(array);
266+
return MakeUnique(schema, std::move(arrays));
267+
}
268+
269+
/// \brief Create a UniqueArrowArrayStream from existing arrays
270+
///
271+
/// This object takes ownership of the schema and arrays.
272+
static UniqueArrayStream MakeUnique(struct ArrowSchema* schema,
273+
std::vector<UniqueArray> arrays) {
274+
UniqueArrayStream stream;
275+
(new VectorArrayStream(schema, std::move(arrays)))->MakeStream(stream.get());
276+
return stream;
277+
}
278+
279+
protected:
280+
VectorArrayStream(struct ArrowSchema* schema, std::vector<UniqueArray> arrays)
281+
: EmptyArrayStream(schema), offset_(0), arrays_(std::move(arrays)) {}
282+
283+
int get_next(struct ArrowArray* array) {
284+
if (offset_ < arrays_.size()) {
285+
arrays_[offset_++].move(array);
286+
} else {
287+
array->release = nullptr;
288+
}
289+
290+
return NANOARROW_OK;
291+
}
292+
293+
private:
294+
std::vector<UniqueArray> arrays_;
295+
int64_t offset_;
296+
};
297+
298+
/// @}
299+
300+
} // namespace nanoarrow
301+
302+
#endif

0 commit comments

Comments
 (0)