-
Notifications
You must be signed in to change notification settings - Fork 299
/
Copy pathgdal_read_stream.cpp
154 lines (121 loc) · 4.64 KB
/
gdal_read_stream.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <ogrsf_frmts.h>
#define RCPP_DEFAULT_INCLUDE_CALL false
#include "Rcpp.h"
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
#include <ogr_recordbatch.h>
#include "gdal_read.h"
class GDALStreamWrapper {
public:
static void Make(struct ArrowArrayStream* stream, Rcpp::List shelter,
struct ArrowArrayStream* stream_out) {
stream_out->get_schema = &get_schema_wrap;
stream_out->get_next = &get_next_wrap;
stream_out->get_last_error = &get_last_error_wrap;
stream_out->release = &release_wrap;
stream_out->private_data = new GDALStreamWrapper(stream, shelter);
}
~GDALStreamWrapper() {
stream_.release(&stream_);
GDALDataset* poDS = (GDALDataset*)R_ExternalPtrAddr(shelter_[0]);
GDALClose(poDS);
R_SetExternalPtrAddr(shelter_[0], nullptr);
}
private:
// The parent stream as returned from GDAL
struct ArrowArrayStream stream_;
Rcpp::List shelter_;
GDALStreamWrapper(struct ArrowArrayStream* stream, Rcpp::List shelter):
shelter_(shelter) {
memcpy(&stream_, stream, sizeof(struct ArrowArrayStream));
stream->release = nullptr;
}
int get_schema(struct ArrowSchema* out) {
return stream_.get_schema(&stream_, out);
}
int get_next(struct ArrowArray* out) {
return stream_.get_next(&stream_, out);
}
const char* get_last_error() {
return stream_.get_last_error(&stream_);
}
static int get_schema_wrap(struct ArrowArrayStream* stream, struct ArrowSchema* out) {
return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_schema(out);
}
static int get_next_wrap(struct ArrowArrayStream* stream, struct ArrowArray* out) {
return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_next(out);
}
static const char* get_last_error_wrap(struct ArrowArrayStream* stream) {
return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_last_error();
}
static void release_wrap(struct ArrowArrayStream* stream) {
delete reinterpret_cast<GDALStreamWrapper*>(stream->private_data);
stream->release = nullptr;
}
};
#endif
// [[Rcpp::export]]
Rcpp::List CPL_read_gdal_stream(
Rcpp::RObject stream_xptr,
Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,
Rcpp::CharacterVector query,
Rcpp::CharacterVector options, bool quiet, Rcpp::CharacterVector drivers,
Rcpp::CharacterVector wkt_filter,
bool dsn_exists,
bool dsn_isdb,
Rcpp::CharacterVector fid_column,
int width) {
#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
const char* array_stream_options[] = {"INCLUDE_FID=NO", nullptr};
if (fid_column.size() == 1) {
array_stream_options[0] = "INCLUDE_FID=YES";
}
Rcpp::List prep = CPL_ogr_layer_setup(datasource, layer, query, options,
quiet, drivers,
wkt_filter,
dsn_exists, dsn_isdb, width);
OGRLayer* poLayer = (OGRLayer*)R_ExternalPtrAddr(prep[1]);
auto stream_out = reinterpret_cast<struct ArrowArrayStream*>(
R_ExternalPtrAddr(stream_xptr));
OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
Rcpp::CharacterVector geom_field_name(poFDefn->GetGeomFieldCount());
Rcpp::CharacterVector geom_field_crs(poFDefn->GetGeomFieldCount());
for (int i = 0; i < poFDefn->GetGeomFieldCount(); i++) {
OGRGeomFieldDefn* poGFDefn = poFDefn->GetGeomFieldDefn(i);
if (poGFDefn == nullptr) {
Rcpp::stop("GeomFieldDefn error"); // #nocov
}
const char* name = poGFDefn->GetNameRef();
if (strlen(name) == 0) {
name = "geometry";
}
const OGRSpatialReference* crs = poGFDefn->GetSpatialRef();
Rcpp::String wkt_str = NA_STRING;
if (crs != nullptr) {
char* wkt_out;
crs->exportToWkt(&wkt_out);
wkt_str = wkt_out;
CPLFree(wkt_out);
}
geom_field_name[i] = name;
geom_field_crs[i] = wkt_str;
}
struct ArrowArrayStream stream_temp;
if (!poLayer->GetArrowStream(&stream_temp, array_stream_options)) {
Rcpp::stop("Failed to open ArrayStream from Layer");
}
GDALStreamWrapper::Make(&stream_temp, prep, stream_out);
// The reported feature count is incorrect if there is a query
double num_features;
if (query.size() == 0) {
num_features = (double) poLayer->GetFeatureCount(false);
} else {
num_features = -1;
}
return Rcpp::List::create(
geom_field_name,
geom_field_crs,
Rcpp::NumericVector::create(num_features));
#else
Rcpp::stop("read_stream() requires GDAL >= 3.6");
#endif
}