1 #include <string.h>
2
3 #include "Rcpp.h"
4
5 #include "ogrsf_frmts.h"
6 #include "wkb.h"
7 #include "gdal.h"
8 #include "gdal_sf_pkg.h"
9
SetupFields(OGRLayer * poLayer,Rcpp::List obj,bool update_layer)10 std::vector<OGRFieldType> SetupFields(OGRLayer *poLayer, Rcpp::List obj, bool update_layer) {
11 std::vector<OGRFieldType> ret(obj.size());
12 Rcpp::CharacterVector cls = obj.attr("colclasses");
13 Rcpp::CharacterVector nm = obj.attr("names");
14 for (int i = 0; i < obj.size(); i++) {
15 if (strcmp(cls[i], "character") == 0)
16 ret[i] = OFTString;
17 else if (strcmp(cls[i], "integer") == 0 || strcmp(cls[i], "logical") == 0)
18 ret[i] = OFTInteger;
19 else if (strcmp(cls[i], "numeric") == 0)
20 ret[i] = OFTReal;
21 else if (strcmp(cls[i], "Date") == 0)
22 ret[i] = OFTDate;
23 else if (strcmp(cls[i], "POSIXct") == 0)
24 ret[i] = OFTDateTime;
25 else if (strcmp(cls[i], "list") == 0) // list with raw vectors; #1721
26 ret[i] = OFTBinary;
27 else { // #nocov start
28 Rcpp::Rcout << "Field " << nm[i] << " of type " << cls[i] << " not supported." << std::endl;
29 Rcpp::stop("Layer creation failed.\n");
30 } // #nocov end
31 OGRFieldDefn oField(nm[i], ret[i]);
32 if (strcmp(cls[i], "logical") == 0)
33 oField.SetSubType(OFSTBoolean);
34 if (!update_layer && poLayer->CreateField(&oField) != OGRERR_NONE) { // #nocov start
35 Rcpp::Rcout << "Creating field " << nm[i] << " failed." << std::endl;
36 Rcpp::stop("Layer creation failed.\n");
37 } // #nocov end
38 }
39 return ret;
40 }
41
42 // this is like an unlist -> dbl, but only does the first 6; if we'd do unlist on the POSIXlt
43 // object, we'd get a character vector...
get_dbl6(Rcpp::List in)44 Rcpp::NumericVector get_dbl6(Rcpp::List in) {
45 Rcpp::NumericVector ret(6);
46 for (int i = 0; i < 6; i++) {
47 Rcpp::NumericVector x = in(i);
48 ret(i) = x(0);
49 }
50 return ret;
51 }
52
SetNull(OGRFeature * poFeature,size_t field)53 void SetNull(OGRFeature *poFeature, size_t field) {
54 #if (GDAL_VERSION_MINOR >= 2 || GDAL_VERSION_MAJOR > 2)
55 poFeature->SetFieldNull(field);
56 #else
57 poFeature->UnsetField(field);
58 #endif
59 }
60
SetFields(OGRFeature * poFeature,std::vector<OGRFieldType> tp,Rcpp::List obj,size_t i,bool shape)61 void SetFields(OGRFeature *poFeature, std::vector<OGRFieldType> tp, Rcpp::List obj, size_t i, bool shape) {
62 Rcpp::CharacterVector nm = obj.attr("names");
63 for (size_t j = 0; j < tp.size(); j++) {
64 if (i == 0 && poFeature->GetFieldIndex(nm[j]) == -1) {
65 Rcpp::Rcout << "Unknown field name `" << nm[j] <<
66 "': updating a layer with improper field name(s)?" << std::endl;
67 Rcpp::stop("Write error\n");
68 }
69 if (j == (size_t) poFeature->GetFieldCount())
70 Rcpp::stop("Impossible: field count reached\n"); // #nocov
71 switch (tp[j]) {
72 case OFTString: {
73 Rcpp::CharacterVector cv;
74 cv = obj[j];
75 if (! Rcpp::CharacterVector::is_na(cv[i])) {
76 if (shape)
77 poFeature->SetField(j, (const char *) cv[i]);
78 else
79 poFeature->SetField(nm[j], (const char *) cv[i]);
80 } else
81 SetNull(poFeature, j);
82 } break;
83 case OFTInteger: {
84 Rcpp::IntegerVector iv;
85 iv = obj[j];
86 if (! Rcpp::IntegerVector::is_na(iv[i])) {
87 if (shape)
88 poFeature->SetField(j, (int) iv[i]);
89 else
90 poFeature->SetField(nm[j], (int) iv[i]);
91 } else
92 SetNull(poFeature, j); // #nocov
93 } break;
94 case OFTReal: {
95 Rcpp::NumericVector nv;
96 nv = obj[j];
97 if (! Rcpp::NumericVector::is_na(nv[i])) {
98 if (shape)
99 poFeature->SetField(j, (double) nv[i]);
100 else
101 poFeature->SetField(nm[j], (double) nv[i]);
102 } else
103 SetNull(poFeature, j);
104 } break;
105 case OFTDate: {
106 Rcpp::NumericVector nv;
107 nv = obj[j];
108 if (Rcpp::NumericVector::is_na(nv[i])) {
109 SetNull(poFeature, j);
110 break;
111 }
112 Rcpp::NumericVector nv0(1);
113 nv0[0] = nv[i];
114 nv0.attr("class") = "Date";
115 Rcpp::Function as_POSIXlt_Date("as.POSIXlt.Date");
116 Rcpp::Function unlist("unlist");
117 Rcpp::NumericVector ret = unlist(as_POSIXlt_Date(nv0)); // use R
118 if (shape)
119 poFeature->SetField(j, 1900 + (int) ret[5], (int) ret[4] + 1, (int) ret[3]);
120 else
121 poFeature->SetField(nm[j], 1900 + (int) ret[5], (int) ret[4] + 1, (int) ret[3]);
122 } break;
123 case OFTDateTime: {
124 Rcpp::NumericVector nv;
125 nv = obj[j];
126 if (Rcpp::NumericVector::is_na(nv[i])) {
127 SetNull(poFeature, j);
128 break;
129 }
130 Rcpp::NumericVector nv0(1);
131 nv0[0] = nv[i];
132 nv0.attr("tzone") = "UTC";
133 Rcpp::Function as_POSIXlt_POSIXct("as.POSIXlt.POSIXct");
134 Rcpp::NumericVector rd = get_dbl6(as_POSIXlt_POSIXct(nv0)); // use R
135 if (shape)
136 poFeature->SetField(j, 1900 + (int) rd[5], (int) rd[4] + 1, // #nocov start
137 (int) rd[3], (int) rd[2], (int) rd[1],
138 (float) rd[0], 100); // nTZFlag: 0=unkown, 1=local, 100=GMT; #nocov end
139 else
140 poFeature->SetField(nm[j], 1900 + (int) rd[5], (int) rd[4] + 1,
141 (int) rd[3], (int) rd[2], (int) rd[1],
142 (float) rd[0], 100); // nTZFlag 0: unkown; 1: local; 100: GMT
143 } break;
144 case OFTBinary:
145 #if GDAL_VERSION_NUM > 3000000
146 {
147 Rcpp::List lv;
148 lv = obj[j];
149 Rcpp::RawVector rv;
150 rv = lv(0);
151 if (rv.size() == 0)
152 SetNull(poFeature, j); // #nocov
153 else {
154 const void *ptr = &(rv[0]);
155 int size = rv.size();
156 poFeature->SetField(j, size, ptr);
157 }
158 } break;
159 #endif
160 default:
161 // we should never get here! // #nocov start
162 Rcpp::Rcout << "field with unsupported type ignored" << std::endl;
163 Rcpp::stop("Layer creation failed.\n");
164 break; // #nocov end
165 }
166 }
167 }
168
169 // [[Rcpp::export]]
CPL_write_ogr(Rcpp::List obj,Rcpp::CharacterVector dsn,Rcpp::CharacterVector layer,Rcpp::CharacterVector driver,Rcpp::CharacterVector dco,Rcpp::CharacterVector lco,Rcpp::List geom,Rcpp::CharacterVector dim,Rcpp::CharacterVector fids,Rcpp::CharacterVector ConfigOptions,bool quiet,Rcpp::LogicalVector append,bool delete_dsn=false,bool delete_layer=false,bool write_geometries=true,int width=80)170 int CPL_write_ogr(Rcpp::List obj, Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer,
171 Rcpp::CharacterVector driver, Rcpp::CharacterVector dco, Rcpp::CharacterVector lco,
172 Rcpp::List geom, Rcpp::CharacterVector dim, Rcpp::CharacterVector fids,
173 Rcpp::CharacterVector ConfigOptions,
174 bool quiet, Rcpp::LogicalVector append, bool delete_dsn = false, bool delete_layer = false,
175 bool write_geometries = true, int width = 80) {
176
177 if (ConfigOptions.size()) {
178 if (ConfigOptions.attr("names") == R_NilValue)
179 Rcpp::stop("config_options should be a character vector with names, as in c(key=\"value\")");
180 Rcpp::CharacterVector names = ConfigOptions.attr("names");
181 for (int i = 0; i < ConfigOptions.size(); i++)
182 CPLSetConfigOption(names[i], ConfigOptions[i]);
183 }
184
185 // init:
186 if (driver.size() != 1 || dsn.size() != 1 || layer.size() != 1)
187 Rcpp::stop("argument dsn, layer or driver not of length 1.\n");
188
189 /* GDALAllRegister(); -- has been done during .onLoad() */
190 // get driver:
191 GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(driver[0]);
192 if (poDriver == NULL) {
193 Rcpp::Rcout << "driver `" << driver[0] << "' not available." << std::endl;
194 Rcpp::stop("Driver not available.\n");
195 }
196
197 // delete data source:
198 if (delete_dsn) {
199 if (poDriver->Delete(dsn[0]) != CE_None) {
200 if (! quiet)
201 Rcpp::Rcout << "Deleting source `" << dsn[0] << "' failed" << std::endl;
202 } else if (! quiet)
203 Rcpp::Rcout << "Deleting source `" << dsn[0] << "' using driver `" << driver[0] << "'" << std::endl;
204 }
205
206 std::vector <char *> options = create_options(dco, quiet);
207 std::vector <char *> drivers = create_options(driver, true);
208
209 // data set:
210 GDALDataset *poDS;
211
212 // delete layer:
213 if (delete_layer && (poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE,
214 drivers.data(), options.data(), NULL)) != NULL) { // don't complain if the layer is not present
215 // find & delete layer:
216 bool deleted = false;
217 for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) {
218 OGRLayer *poLayer = poDS->GetLayer(iLayer);
219 if (poLayer != NULL && EQUAL(poLayer->GetName(), layer[0])) {
220 OGRErr err = poDS->DeleteLayer(iLayer);
221 if (! quiet) {
222 if (err == OGRERR_UNSUPPORTED_OPERATION)
223 Rcpp::Rcout << "Deleting layer not supported by driver `" << driver[0] << "'" // #nocov
224 << std::endl; // #nocov
225 else {
226 Rcpp::Rcout << "Deleting layer `" << layer[0] << "' using driver `" <<
227 driver[0] << "'" << std::endl;
228 }
229 }
230 deleted = (err == OGRERR_NONE);
231 break;
232 }
233 }
234 if (! deleted && ! quiet)
235 Rcpp::Rcout << "Deleting layer `" << layer[0] << "' failed" << std::endl;
236 GDALClose(poDS);
237 }
238
239 // append to ds:
240 if (append[0] == TRUE) { // and not NA_LOGICAL:
241 poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE,
242 drivers.data(), options.data(), NULL);
243 if (poDS == NULL) {
244 if ((poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL,
245 options.data(), NULL)) != NULL) { // exists read-only:
246 GDALClose(poDS);
247 Rcpp::Rcout << "Cannot append to " << dsn[0] <<
248 ": do you have write permission?" << std::endl;
249 Rcpp::stop("Cannot append to existing dataset.\n");
250 } else { // doesn't exist: create
251 if ((poDS = poDriver->Create(dsn[0], 0, 0, 0, GDT_Unknown, options.data())) == NULL) {
252 Rcpp::Rcout << "Creating dataset " << dsn[0] << " failed." << std::endl;
253 Rcpp::stop("Creation failed.\n");
254 }
255 }
256 }
257 if (! quiet)
258 Rcpp::Rcout << "Updating layer `" << layer[0] << "' to data source `" << dsn[0] <<
259 "' using driver `" << driver[0] << "'" << std::endl;
260 } else { // add to existing ds or create new ds:
261 // when append == NA, raise error when it already exists:
262 if (!delete_dsn && !delete_layer && append[0] == NA_LOGICAL &&
263 (poDS = (GDALDataset *) GDALOpenEx(dsn[0],
264 GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, options.data(), NULL)) != NULL &&
265 poDS->GetLayerByName(layer[0]) != NULL) {
266 GDALClose(poDS);
267 Rcpp::Rcout << "Layer " << layer[0] << " in dataset " << dsn[0] << " already exists:\n" <<
268 "use either append=TRUE to append to layer or append=FALSE to overwrite layer" << std::endl;
269 Rcpp::stop("Dataset already exists.\n");
270 }
271
272 if (delete_dsn || (poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE,
273 drivers.data(), options.data(), NULL)) == NULL) {
274 // if dsn does not exist, then create:
275 if ((poDS = poDriver->Create(dsn[0], 0, 0, 0, GDT_Unknown, options.data())) == NULL) {
276 Rcpp::Rcout << "Creating dataset " << dsn[0] << " failed." << std::endl;
277 Rcpp::stop("Creation failed.\n");
278 }
279 }
280 if (! quiet) {
281 Rcpp::Rcout << "Writing layer `" << layer[0] << "' to data source ";
282 if (LENGTH(dsn[0]) > width - (44 + LENGTH(layer[0]) + LENGTH(driver[0])))
283 Rcpp::Rcout << std::endl << " ";
284 Rcpp::Rcout << "`" << dsn[0] << "' using driver `" << driver[0] << "'" << std::endl;
285 }
286 }
287
288 // can & do transaction?
289 bool can_do_transaction = (poDS->TestCapability(ODsCTransactions) == TRUE); // can?
290 bool transaction = false;
291 if (can_do_transaction) { // try to start transaction:
292 unset_error_handler();
293 transaction = (poDS->StartTransaction() == OGRERR_NONE); // do?
294 set_error_handler();
295 if (! transaction) { // failed: #nocov start
296 GDALClose(poDS);
297 return 1; // transaction failed!
298 } // #nocov end
299 }
300
301 // read geometries:
302 OGRSpatialReference *sref = NULL;
303 std::vector<OGRGeometry *> geomv;
304 OGRwkbGeometryType wkbType;
305 if (! write_geometries) { // write an aspatial table, see #1345
306 wkbType = wkbNone;
307 for (int i = 0; i < geom.size(); i++)
308 geomv.push_back(NULL);
309 } else {
310 Rcpp::CharacterVector clsv = geom.attr("class");
311 wkbType = (OGRwkbGeometryType) make_type(clsv[0], dim[0], false, NULL, 0);
312 geomv = ogr_from_sfc(geom, &sref);
313 sref = handle_axis_order(sref);
314 }
315
316 // create layer:
317 options = create_options(lco, quiet);
318 OGRLayer *poLayer = NULL;
319 bool update_layer = false;
320 if ((poLayer = poDS->GetLayerByName(layer[0])) != NULL) {
321 if (!quiet)
322 Rcpp::Rcout << "Updating existing layer " << layer[0] << std::endl;
323 update_layer = true;
324 } else
325 poLayer = poDS->CreateLayer(layer[0], sref, wkbType, options.data());
326 if (sref != NULL)
327 sref->Release();
328 if (poLayer == NULL) {
329 Rcpp::Rcout << "Creating or updating layer " << layer[0] << " failed." << std::endl;
330 GDALClose(poDS);
331 Rcpp::stop("Write error.\n");
332 }
333
334 // write feature attribute fields & geometries:
335 std::vector<OGRFieldType> fieldTypes = SetupFields(poLayer, obj, update_layer);
336 if (! quiet) {
337 Rcpp::Rcout << "Writing " << geomv.size() << " features with " <<
338 fieldTypes.size() << " fields";
339 if (write_geometries)
340 Rcpp::Rcout << " and geometry type " << OGRGeometryTypeToName(wkbType);
341 else
342 Rcpp::Rcout << " without geometries";
343 Rcpp::Rcout << "." << std::endl;
344 }
345
346 for (size_t i = 0; i < geomv.size(); i++) { // create all features & add to layer:
347 OGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());
348 SetFields(poFeature, fieldTypes, obj, i, driver[0] == "ESRI Shapefile");
349 if (write_geometries)
350 poFeature->SetGeometryDirectly(geomv[i]);
351 if (fids.size() > (int) i)
352 poFeature->SetFID(std::stoll(Rcpp::as<std::string>(fids[i]), NULL, 10));
353 if (poLayer->CreateFeature(poFeature) != OGRERR_NONE) {
354 Rcpp::Rcout << "Failed to create feature " << i << " in " << layer[0] << std::endl;
355 // delete layer when failing to create feature
356 OGRErr err = poDS->DeleteLayer(0);
357 GDALClose(poDS);
358 if (err != OGRERR_NONE) { // #nocov start
359 if (err == OGRERR_UNSUPPORTED_OPERATION)
360 Rcpp::Rcout << "Deleting layer not supported by driver `" << driver[0] << "'" << std::endl;
361 else if (! transaction)
362 Rcpp::Rcout << "Deleting layer `" << layer[0] << "' failed" << std::endl;
363 } // #nocov end
364 OGRFeature::DestroyFeature(poFeature);
365 if (transaction)
366 return 1; // try once more, writing to tmp file and copy #nocov
367 else
368 Rcpp::stop("Feature creation failed.\n");
369 }
370 OGRFeature::DestroyFeature(poFeature); // deletes geom[i] as well
371 }
372 if (transaction && poDS->CommitTransaction() != OGRERR_NONE) { // #nocov start
373 poDS->RollbackTransaction();
374 GDALClose(poDS);
375 Rcpp::stop("CommitTransaction() failed.\n");
376 } // #nocov end
377 GDALClose(poDS);
378 if (ConfigOptions.size()) {
379 Rcpp::CharacterVector names = ConfigOptions.attr("names");
380 for (int i = 0; i < ConfigOptions.size(); i++)
381 CPLSetConfigOption(names[i], NULL);
382 }
383 return 0; // all O.K.
384 }
385
386 // delete a data source, or one or more layers within a data source
387 // [[Rcpp::export]]
CPL_delete_ogr(Rcpp::CharacterVector dsn,Rcpp::CharacterVector layer,Rcpp::CharacterVector driver,bool quiet=true)388 int CPL_delete_ogr(Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer,
389 Rcpp::CharacterVector driver, bool quiet = true) {
390
391 // init:
392 if (driver.size() != 1 || dsn.size() != 1)
393 Rcpp::stop("argument dsn or driver not of length 1.\n");
394
395 /* GDALAllRegister(); -- has been done during .onLoad() */
396 // get driver:
397 GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(driver[0]);
398 if (poDriver == NULL) {
399 Rcpp::Rcout << "driver `" << driver[0] << "' not available." << std::endl;
400 Rcpp::stop("Driver not available.\n");
401 }
402
403 // delete data source:
404 if (layer.size() == 0) {
405 if (poDriver->Delete(dsn[0]) != CE_None)
406 Rcpp::Rcout << "Deleting source `" << dsn[0] << "' failed" << std::endl;
407 else if (! quiet)
408 Rcpp::Rcout << "Deleting source `" << dsn[0] << "' using driver `" << driver[0] << "'" << std::endl;
409 return 0;
410 }
411
412 // delete layer(s):
413
414 // data set:
415 GDALDataset *poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL);
416 if (poDS == NULL) {
417 Rcpp::Rcout << "Data source `" << dsn[0] << "' not found" << std::endl;
418 return 1;
419 }
420
421 bool can_do_transaction = (poDS->TestCapability(ODsCTransactions) == TRUE); // can?
422 bool transaction = false;
423 if (can_do_transaction) { // try to start transaction:
424 unset_error_handler();
425 transaction = (poDS->StartTransaction() == OGRERR_NONE); // do?
426 set_error_handler();
427 if (! transaction) { // failed: #nocov start
428 GDALClose(poDS);
429 Rcpp::Rcout << "On data source `" << dsn[0] << "' cannot start transaction" << std::endl;
430 return 1; // transaction failed!
431 } // #nocov end
432 }
433
434 for (int i = 0; i < layer.size(); i++) { // reverse loop order if inefficient?
435 // find & delete layer:
436 for (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) {
437 OGRLayer *poLayer = poDS->GetLayer(iLayer);
438 if (poLayer != NULL && EQUAL(poLayer->GetName(), layer[i])) {
439 OGRErr err = poDS->DeleteLayer(iLayer);
440 if (! quiet) {
441 if (err == OGRERR_UNSUPPORTED_OPERATION)
442 Rcpp::Rcout << "Deleting layer not supported by driver `" << driver[0] << "'" // #nocov
443 << std::endl; // #nocov
444 else {
445 Rcpp::Rcout << "Deleting layer `" << layer[0] << "' using driver `" <<
446 driver[0] << "'" << std::endl;
447 }
448 }
449 if (err != OGRERR_NONE);
450 Rcpp::Rcout << "Deleting layer `" << layer[i] << "' failed" << std::endl;
451 }
452 }
453 }
454 if (transaction && poDS->CommitTransaction() != OGRERR_NONE) { // #nocov start
455 poDS->RollbackTransaction();
456 Rcpp::Rcout << "CommitTransaction() failed." << std::endl;
457 return 1;
458 } // #nocov end
459 GDALClose(poDS);
460 return 0;
461 }
462