Skip to content

Commit

Permalink
first shot at interfacing udunits2 directly
Browse files Browse the repository at this point in the history
  • Loading branch information
edzer committed Jan 10, 2018
1 parent 96ae9bb commit 0f7c92f
Show file tree
Hide file tree
Showing 11 changed files with 251 additions and 8 deletions.
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ Authors@R: c(person("Edzer", "Pebesma", role = c("aut", "cre"), email = "edzer.p
Depends:
R (>= 3.0.0)
Imports:
udunits2 (>= 0.13)
Rcpp
LinkingTo:
Rcpp
Suggests:
NISTunits,
measurements,
Expand Down
3 changes: 2 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,6 @@ export(units_options)
export(valid_udunits)
export(valid_udunits_prefixes)
import(stats)
import(udunits2)
import(utils)
importFrom(Rcpp,evalCpp)
useDynLib(units)
15 changes: 15 additions & 0 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

udunits_init <- function(path, warn_on_failure = FALSE) {
.Call('_units_udunits_init', PACKAGE = 'units', path, warn_on_failure)
}

R_ut_parse <- function(name) {
.Call('_units_R_ut_parse', PACKAGE = 'units', name)
}

R_ut_format <- function(p, names = FALSE, definition = FALSE) {
.Call('_units_R_ut_format', PACKAGE = 'units', p, names, definition)
}

6 changes: 0 additions & 6 deletions R/conversion.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
NULL
#' @import utils
#' @import stats
#' @import udunits2
NULL

# Helper functions for testing if we can convert and how using either
# user-defined conversion functions or udunits.
are_convertible <- function(from, to) {
Expand Down
9 changes: 9 additions & 0 deletions R/init.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#' @import utils
#' @import stats
#' @importFrom Rcpp evalCpp
#' @useDynLib units
NULL

.onLoad = function(libname, pkgname) {
udunits_init(character(0), TRUE)
}
2 changes: 2 additions & 0 deletions src/Makevars.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PKG_CPPFLAGS = @UD_CPPFLAGS@
PKG_LIBS = @LIBS@
16 changes: 16 additions & 0 deletions src/Makevars.win
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
PKG_CPPFLAGS = -I../windows/udunits-2.2.20/include
PKG_LIBS = -L../windows/udunits-2.2.20/lib${R_ARCH} \
-ludunits2 -lexpat

all: clean winlibs

winlibs:
"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" "../tools/winlibs.R"
mkdir -p ../inst
rm -Rf ../inst/share
cp -r ../windows/udunits-2.2.20/share ../inst/

clean:
rm -Rf $(SHLIB) $(OBJECTS)

.PHONY: all winlibs clean
55 changes: 55 additions & 0 deletions src/RcppExports.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#include <Rcpp.h>

using namespace Rcpp;

// udunits_init
LogicalVector udunits_init(CharacterVector path, bool warn_on_failure);
RcppExport SEXP _units_udunits_init(SEXP pathSEXP, SEXP warn_on_failureSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< CharacterVector >::type path(pathSEXP);
Rcpp::traits::input_parameter< bool >::type warn_on_failure(warn_on_failureSEXP);
rcpp_result_gen = Rcpp::wrap(udunits_init(path, warn_on_failure));
return rcpp_result_gen;
END_RCPP
}
// R_ut_parse
XPtr< std::vector<void *> > R_ut_parse(CharacterVector name);
RcppExport SEXP _units_R_ut_parse(SEXP nameSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< CharacterVector >::type name(nameSEXP);
rcpp_result_gen = Rcpp::wrap(R_ut_parse(name));
return rcpp_result_gen;
END_RCPP
}
// R_ut_format
CharacterVector R_ut_format(SEXP p, bool names, bool definition);
RcppExport SEXP _units_R_ut_format(SEXP pSEXP, SEXP namesSEXP, SEXP definitionSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< SEXP >::type p(pSEXP);
Rcpp::traits::input_parameter< bool >::type names(namesSEXP);
Rcpp::traits::input_parameter< bool >::type definition(definitionSEXP);
rcpp_result_gen = Rcpp::wrap(R_ut_format(p, names, definition));
return rcpp_result_gen;
END_RCPP
}

static const R_CallMethodDef CallEntries[] = {
{"_units_udunits_init", (DL_FUNC) &_units_udunits_init, 2},
{"_units_R_ut_parse", (DL_FUNC) &_units_R_ut_parse, 1},
{"_units_R_ut_format", (DL_FUNC) &_units_R_ut_format, 3},
{NULL, NULL, 0}
};

RcppExport void R_init_units(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
35 changes: 35 additions & 0 deletions src/io.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <R.h>
#include <udunits2.h>
#include <stdio.h> /* FILENAME_MAX */

#include "io.h"

/* From the enum comments in udunits2.h */
const char * ut_status_strings[] = {
"Success",
"An argument violates the function's contract",
"Unit, prefix, or identifier already exists",
"No such unit exists",
"Operating-system error. See \"errno\".",
"The units belong to different unit-systems",
"The operation on the unit(s) is meaningless",
"The unit-system doesn't have a unit named \"second\"",
"An error occurred while visiting a unit",
"A unit can't be formatted in the desired manner",
"string unit representation contains syntax error",
"string unit representation contains unknown word",
"Can't open argument-specified unit database",
"Can't open environment-specified unit database",
"Can't open installed, default, unit database",
"Error parsing unit specification"
};

void handle_error(const char *calling_function) {
ut_status stat;
stat = ut_get_status();
error("Error in function %s: %s", calling_function, ut_status_strings[stat]);
}

void r_error_fn(const char* fmt, va_list args) {
Rvprintf(fmt, args);
}
2 changes: 2 additions & 0 deletions src/io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void r_error_fn(const char* fmt, va_list args);
void handle_error(const char *calling_function);
112 changes: 112 additions & 0 deletions src/udunits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
modified from: https://github.com/pacificclimate/Rudunits2
(c) James Hiebert <[email protected]>
Pacific Climate Impacts Consortium
August, 16, 2010
Functions to support the R interface to the udunits (API version 2) library
*/

#include "Rcpp.h"
using namespace Rcpp;

#include <R.h>
#include <udunits2.h>
#include <stdio.h> /* FILENAME_MAX */

ut_system *sys = NULL;
static ut_encoding enc;

extern "C" {
#include "io.h"
}

// [[Rcpp::export]]
LogicalVector udunits_init(CharacterVector path, bool warn_on_failure = false) {

LogicalVector ret(1);
ut_set_error_message_handler((ut_error_message_handler) r_error_fn);
if (sys != NULL)
ut_free_system(sys);

sys = NULL;
ut_set_error_message_handler(ut_ignore);
for (int i = 0; i < path.size(); i++) {
sys = ut_read_xml(path[i]);
if (sys != NULL)
break;
}
if (sys == NULL)
sys = ut_read_xml(NULL);
ut_set_error_message_handler((ut_error_message_handler) r_error_fn);
if (sys == NULL) {
if (warn_on_failure)
handle_error("udunit_init");
ret[0] = false;
} else
ret[0] = true;
enc = UT_UTF8;
return ret;
}

LogicalVector R_ut_has_system(List foo) {
LogicalVector ret(1);
if (sys != NULL)
ret(0) = true;
else
ret(0) = false;
return ret;
}

typedef std::vector<void *> ut_vec;

void finalize_ut(ut_vec *v) {
for (int i = 0; i < v->size(); i++)
ut_free((ut_unit *) ((*v)[i]));
}

// typedef XPtr<ut_vec,PreserveStorage,finalize_ut> XPtrUT;
typedef XPtr<ut_vec> XPtrUT;

// [[Rcpp::export]]
XPtr< std::vector<void *> > R_ut_parse(CharacterVector name) {
ut_vec *v = new ut_vec;
Rcout << name[0] << std::endl;
ut_unit *u = ut_parse(sys, name[0], enc);
if (u == NULL) {
switch (ut_get_status()) {
case UT_BAD_ARG:
case UT_SYNTAX:
case UT_UNKNOWN:
case UT_OS:
handle_error("R_ut_parse");
}
}
// error checking ...
v->push_back(u);
XPtrUT p(v);
return(p);
}

// [[Rcpp::export]]
CharacterVector R_ut_format(SEXP p, bool names = false, bool definition = false) {
XPtr< std::vector<void *> > ptr(p);
int opt = enc;
if (names)
opt = opt | UT_NAMES;
if (definition)
opt = opt | UT_DEFINITION;
char buf[256];
int i = ut_format((ut_unit *) (*ptr)[0], buf, 256, opt);
if (i == -1) {
switch (ut_get_status()) {
UT_BAD_ARG:
UT_CANT_FORMAT:
handle_error("R_ut_format");
break;
default:;
}
}
return CharacterVector::create(buf);
}

0 comments on commit 0f7c92f

Please sign in to comment.