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