Skip to content

Commit

Permalink
#77 started incorporating bobs C++ code for the roundtrip work around
Browse files Browse the repository at this point in the history
  • Loading branch information
sckott committed Feb 18, 2016
1 parent 97a0c1a commit bdd0c9e
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 1 deletion.
5 changes: 4 additions & 1 deletion DESCRIPTION
Expand Up @@ -15,12 +15,15 @@ URL: https://github.com/ropensci/geojsonio
BugReports: http://www.github.com/ropensci/geojsonio/issues
LazyData: true
VignetteBuilder: knitr
LinkingTo:
Rcpp (>= 0.12.0)
Depends:
R (>= 2.10)
R (>= 3.02)
Imports:
methods,
stats,
utils,
Rcpp (>= 0.12.3),
sp,
rgdal,
rgeos,
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Expand Up @@ -165,6 +165,7 @@ export(validate)
import(methods)
import(rgeos)
import(sp)
importFrom(Rcpp,evalCpp)
importFrom(V8,new_context)
importFrom(httr,GET)
importFrom(httr,POST)
Expand All @@ -182,3 +183,4 @@ importFrom(rgdal,readOGR)
importFrom(rgdal,writeOGR)
importFrom(stats,setNames)
importFrom(utils,download.file)
useDynLib(geojsonio)
20 changes: 20 additions & 0 deletions R/RcppExports.R
@@ -0,0 +1,20 @@
# This file was generated by Rcpp::compileAttributes
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#' An \code{writeOGR} shim to capture stdout
#'
#' @param obj the \code{Spatial} object to use
#' @param obj_size pls pass in \code{object.size(obj)}
#' @param layer spatial layer to use
#' @param writeOGR pls pass in \code{writeOGR} (no quotes)
#' @return character vector of GeoJSON if all goes well
#' @examples \dontrun{
#' capturedWriteOGR(cities[1:10,],
#' object.size(cities[1:10,]),
#' "cities",
#' writeOGR))
#' }
capturedWriteOGR <- function(obj, obj_size, layer, writeOGR) {
.Call('geojsonio_capturedWriteOGR', PACKAGE = 'geojsonio', obj, obj_size, layer, writeOGR)
}

2 changes: 2 additions & 0 deletions R/geojsonio-package.r
Expand Up @@ -42,6 +42,8 @@
#' @importFrom maptools readShapeSpatial
#' @importFrom rgdal readOGR writeOGR ogrListLayers
#' @importFrom magrittr %>%
#' @importFrom Rcpp evalCpp
#' @useDynLib geojsonio
#' @name geojsonio
#' @author Scott Chamberlain \email{myrmecocystus@@gmail.com}
#' @author Andy Teucher \email{andy.teucher@@gmail.com}
Expand Down
32 changes: 32 additions & 0 deletions man/capturedWriteOGR.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions src/RcppExports.cpp
@@ -0,0 +1,21 @@
// This file was generated by Rcpp::compileAttributes
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#include <Rcpp.h>

using namespace Rcpp;

// capturedWriteOGR
CharacterVector capturedWriteOGR(SEXP obj, int obj_size, SEXP layer, Function writeOGR);
RcppExport SEXP geojsonio_capturedWriteOGR(SEXP objSEXP, SEXP obj_sizeSEXP, SEXP layerSEXP, SEXP writeOGRSEXP) {
BEGIN_RCPP
Rcpp::RObject __result;
Rcpp::RNGScope __rngScope;
Rcpp::traits::input_parameter< SEXP >::type obj(objSEXP);
Rcpp::traits::input_parameter< int >::type obj_size(obj_sizeSEXP);
Rcpp::traits::input_parameter< SEXP >::type layer(layerSEXP);
Rcpp::traits::input_parameter< Function >::type writeOGR(writeOGRSEXP);
__result = Rcpp::wrap(capturedWriteOGR(obj, obj_size, layer, writeOGR));
return __result;
END_RCPP
}
Binary file added src/RcppExports.o
Binary file not shown.
82 changes: 82 additions & 0 deletions src/captured_write_ogr.cpp
@@ -0,0 +1,82 @@
#include <Rcpp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

using namespace Rcpp;

//' An \code{writeOGR} shim to capture stdout
//'
//' @param obj the \code{Spatial} object to use
//' @param obj_size pls pass in \code{object.size(obj)}
//' @param layer spatial layer to use
//' @param writeOGR pls pass in \code{writeOGR} (no quotes)
//' @return character vector of GeoJSON if all goes well
//' @examples \dontrun{
//' capturedWriteOGR(cities[1:10,],
//' object.size(cities[1:10,]),
//' "cities",
//' writeOGR))
//' }
// [[Rcpp::export]]
CharacterVector capturedWriteOGR(SEXP obj,
int obj_size,
SEXP layer,
Function writeOGR) {

// we don't know how big the output is going to be.
// this is the main problem with this approach.
// there is no error checking yet
// i have no idea if this works on Windows
// this was a hack on a commuter train ;-)

// this could cause us to run out of memory
// we need checking for sizes, mem avail and errors

// allocate a buffer to hold the output geojson
// and initialize it so we's sure to have a null term'd string
int MAX_LEN = obj_size * 10 ;
char buffer[MAX_LEN+1];
memset(buffer, 0, sizeof (char) * (MAX_LEN+1));

// now we're going to mess with pipes. the way the VSI stuff
// mangles stdout in gdal means that we can't use nice C++
// redirects and have to resort to file descriptor hacking

int out_pipe[2];
int saved_stdout;

saved_stdout = dup(STDOUT_FILENO);

// ok, there's some error checking if we couldn't even
// get the hack started

if (pipe(out_pipe) != 0 ) { return(NA_STRING); }

dup2(out_pipe[1], STDOUT_FILENO);
close(out_pipe[1]);

// we've setup the capture, so let writeOGR do it's thing
// we are calling R from C since the rgdal folks have not
// exposed anything we can use AFAI can tell

writeOGR(obj, "/vsistdout/", layer, "GeoJSON");

// ok, we let it do it's thing, now make sure we've
// cleatned up after it

fflush(stdout);

// now, get that mess into somet hign we can use

read(out_pipe[0], buffer, MAX_LEN);

// restore order to the universe

dup2(saved_stdout, STDOUT_FILENO);

// say a little prayer

return(wrap(buffer));

}
Binary file added src/captured_write_ogr.o
Binary file not shown.
Binary file added src/geojsonio.so
Binary file not shown.

0 comments on commit bdd0c9e

Please sign in to comment.