Large diffs are not rendered by default.

@@ -1,9 +1,12 @@
#include <Rcpp.h>
using namespace Rcpp;

#include "readstat.h"
#include "haven_types.h"

#include "cpp11/doubles.hpp"
#include "cpp11/strings.hpp"
#include "cpp11/integers.hpp"
#include "cpp11/sexp.hpp"
#include "cpp11/list.hpp"

ssize_t data_writer(const void *data, size_t len, void *ctx);

inline const char* string_utf8(SEXP x, int i) {
@@ -34,8 +37,8 @@ inline readstat_measure_e measureType(SEXP x) {
}
}

inline int displayWidth(RObject x) {
RObject display_width_obj = x.attr("display_width");
inline int displayWidth(cpp11::sexp x) {
cpp11::sexp display_width_obj(x.attr("display_width"));
switch(TYPEOF(display_width_obj)) {
case INTSXP:
return INTEGER(display_width_obj)[0];
@@ -50,17 +53,17 @@ class Writer {
FileExt ext_;
FileVendor vendor_;

List x_;
cpp11::list x_;
readstat_writer_t* writer_;
FILE* pOut_;

public:
Writer(FileExt ext, List x, CharacterVector pathEnc): ext_(ext), vendor_(extVendor(ext)), x_(x) {
Writer(FileExt ext, cpp11::list x, cpp11::strings pathEnc): ext_(ext), vendor_(extVendor(ext)), x_(x) {
std::string path(Rf_translateChar(pathEnc[0]));

pOut_ = fopen(path.c_str(), "wb");
if (pOut_ == NULL)
stop("Failed to open '%s' for writing", path);
cpp11::stop("Failed to open '%s' for writing", path.c_str());

writer_ = readstat_writer_init();
checkStatus(readstat_set_data_writer(writer_, data_writer));
@@ -85,7 +88,7 @@ class Writer {
readstat_writer_set_table_name(writer_, name.c_str());
}

void setFileLabel(RObject label) {
void setFileLabel(cpp11::sexp label) {
if (label == R_NilValue)
return;

@@ -97,23 +100,23 @@ class Writer {
if (p == 0)
return;

CharacterVector names(as<CharacterVector>(x_.attr("names")));
cpp11::strings names(x_.attr("names"));

// Define variables
for (int j = 0; j < p; ++j) {
RObject col = x_[j];
cpp11::sexp col = x_[j];
VarType type = numType(col);

const char* name = string_utf8(names, j);
const char* format = var_format(col, type);

switch(TYPEOF(col)) {
case LGLSXP: defineVariable(as<IntegerVector>(col), name, format); break;
case INTSXP: defineVariable(as<IntegerVector>(col), name, format); break;
case REALSXP: defineVariable(as<NumericVector>(col), name, format); break;
case STRSXP: defineVariable(as<CharacterVector>(col), name, format); break;
case LGLSXP: defineVariable(cpp11::integers(cpp11::safe[Rf_coerceVector](col, INTSXP)), name, format); break;
case INTSXP: defineVariable(cpp11::integers(col), name, format); break;
case REALSXP: defineVariable(cpp11::doubles(col), name, format); break;
case STRSXP: defineVariable(cpp11::strings(col), name, format); break;
default:
stop("Variables of type %s not supported yet",
cpp11::stop("Variables of type %s not supported yet",
Rf_type2char(TYPEOF(col)));
}
}
@@ -139,7 +142,7 @@ class Writer {
for (int i = 0; i < n; ++i) {
checkStatus(readstat_begin_row(writer_));
for (int j = 0; j < p; ++j) {
RObject col = x_[j];
cpp11::sexp col(x_[j]);
readstat_variable_t* var = readstat_get_variable(writer_, j);

switch (TYPEOF(col)) {
@@ -175,18 +178,18 @@ class Writer {

// Define variables ----------------------------------------------------------

const char* var_label(RObject x) {
RObject label = x.attr("label");
const char* var_label(cpp11::sexp x) {
cpp11::sexp label(x.attr("label"));

if (label == R_NilValue)
return NULL;

return string_utf8(label, 0);
}

const char* var_format(RObject x, VarType varType) {
const char* var_format(cpp11::sexp x, VarType varType) {
// Use attribute, if present
RObject format = x.attr(formatAttribute(vendor_));
cpp11::sexp format(x.attr(formatAttribute(vendor_).c_str()));
if (format != R_NilValue)
return string_utf8(format, 0);

@@ -217,19 +220,19 @@ class Writer {
return NULL;
}

void defineVariable(IntegerVector x, const char* name, const char* format = NULL) {
void defineVariable(cpp11::integers x, const char* name, const char* format = NULL) {
readstat_label_set_t* labelSet = NULL;
if (Rf_inherits(x, "factor")) {
labelSet = readstat_add_label_set(writer_, READSTAT_TYPE_INT32, name);

CharacterVector levels = as<CharacterVector>(x.attr("levels"));
cpp11::strings levels(x.attr("levels"));
for (int i = 0; i < levels.size(); ++i)
readstat_label_int32_value(labelSet, i + 1, string_utf8(levels, i));
} else if (Rf_inherits(x, "haven_labelled") && TYPEOF(x.attr("labels")) != NILSXP) {
labelSet = readstat_add_label_set(writer_, READSTAT_TYPE_INT32, name);

IntegerVector values = as<IntegerVector>(x.attr("labels"));
CharacterVector labels = as<CharacterVector>(values.attr("names"));
cpp11::integers values(x.attr("labels"));
cpp11::strings labels(values.attr("names"));

for (int i = 0; i < values.size(); ++i)
readstat_label_int32_value(labelSet, values[i], string_utf8(labels, i));
@@ -244,13 +247,13 @@ class Writer {
readstat_variable_set_display_width(var, displayWidth(x));
}

void defineVariable(NumericVector x, const char* name, const char* format = NULL) {
void defineVariable(cpp11::doubles x, const char* name, const char* format = NULL) {
readstat_label_set_t* labelSet = NULL;
if (Rf_inherits(x, "haven_labelled") && TYPEOF(x.attr("labels")) != NILSXP) {
labelSet = readstat_add_label_set(writer_, READSTAT_TYPE_DOUBLE, name);

NumericVector values = as<NumericVector>(x.attr("labels"));
CharacterVector labels = as<CharacterVector>(values.attr("names"));
cpp11::doubles values(x.attr("labels"));
cpp11::strings labels(values.attr("names"));

for (int i = 0; i < values.size(); ++i)
readstat_label_double_value(labelSet, values[i], string_utf8(labels, i));
@@ -281,13 +284,13 @@ class Writer {
}
}

void defineVariable(CharacterVector x, const char* name, const char* format = NULL) {
void defineVariable(cpp11::strings x, const char* name, const char* format = NULL) {
readstat_label_set_t* labelSet = NULL;
if (Rf_inherits(x, "haven_labelled") && TYPEOF(x.attr("labels")) != NILSXP) {
labelSet = readstat_add_label_set(writer_, READSTAT_TYPE_STRING, name);

CharacterVector values = as<CharacterVector>(x.attr("labels"));
CharacterVector labels = as<CharacterVector>(values.attr("names"));
cpp11::strings values(x.attr("labels"));
cpp11::strings labels(values.attr("names"));

for (int i = 0; i < values.size(); ++i)
readstat_label_string_value(labelSet, string_utf8(values, i), string_utf8(labels, i));
@@ -339,7 +342,7 @@ class Writer {
void checkStatus(readstat_error_t err) {
if (err == 0) return;

stop("Writing failure: %s.", readstat_error_message(err));
cpp11::stop("Writing failure: %s.", readstat_error_message(err));
}

ssize_t write(const void *data, size_t len) {
@@ -351,29 +354,29 @@ ssize_t data_writer(const void *data, size_t len, void *ctx) {
return ((Writer*) ctx)->write(data, len);
}

// [[Rcpp::export]]
void write_sav_(List data, CharacterVector path, bool compress) {
[[cpp11::export]]
void write_sav_(cpp11::list data, cpp11::strings path, bool compress) {
Writer writer(HAVEN_SAV, data, path);
if (compress)
writer.setCompression(READSTAT_COMPRESS_BINARY);
writer.write();
}

// [[Rcpp::export]]
void write_dta_(List data, CharacterVector path, int version, RObject label) {
[[cpp11::export]]
void write_dta_(cpp11::list data, cpp11::strings path, int version, cpp11::sexp label) {
Writer writer(HAVEN_DTA, data, path);
writer.setVersion(version);
writer.setFileLabel(label);
writer.write();
}

// [[Rcpp::export]]
void write_sas_(List data, CharacterVector path) {
[[cpp11::export]]
void write_sas_(cpp11::list data, cpp11::strings path) {
Writer(HAVEN_SAS7BDAT, data, path).write();
}

// [[Rcpp::export]]
void write_xpt_(List data, CharacterVector path, int version, std::string name) {
[[cpp11::export]]
void write_xpt_(cpp11::list data, cpp11::strings path, int version, std::string name) {
Writer writer(HAVEN_XPT, data, path);
writer.setVersion(version);
writer.setName(name);

This file was deleted.

@@ -0,0 +1,158 @@
// Generated by cpp11: do not edit by hand

#include "cpp11/declarations.hpp"


// DfReader.cpp
cpp11::list df_parse_sas_file(cpp11::list spec_b7dat, cpp11::list spec_b7cat, std::string encoding, std::string catalog_encoding, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_sas_file(SEXP spec_b7dat, SEXP spec_b7cat, SEXP encoding, SEXP catalog_encoding, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_sas_file(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec_b7dat)), cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec_b7cat)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<std::string>(catalog_encoding)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_sas_raw(cpp11::list spec_b7dat, cpp11::list spec_b7cat, std::string encoding, std::string catalog_encoding, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_sas_raw(SEXP spec_b7dat, SEXP spec_b7cat, SEXP encoding, SEXP catalog_encoding, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_sas_raw(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec_b7dat)), cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec_b7cat)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<std::string>(catalog_encoding)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_xpt_file(cpp11::list spec, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_xpt_file(SEXP spec, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_xpt_file(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_xpt_raw(cpp11::list spec, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_xpt_raw(SEXP spec, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_xpt_raw(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_dta_file(cpp11::list spec, std::string encoding, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_dta_file(SEXP spec, SEXP encoding, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_dta_file(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_dta_raw(cpp11::list spec, std::string encoding, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_dta_raw(SEXP spec, SEXP encoding, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_dta_raw(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_sav_file(cpp11::list spec, std::string encoding, bool user_na, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_sav_file(SEXP spec, SEXP encoding, SEXP user_na, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_sav_file(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<bool>(user_na)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_sav_raw(cpp11::list spec, std::string encoding, bool user_na, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_sav_raw(SEXP spec, SEXP encoding, SEXP user_na, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_sav_raw(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<bool>(user_na)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_por_file(cpp11::list spec, std::string encoding, bool user_na, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_por_file(SEXP spec, SEXP encoding, SEXP user_na, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_por_file(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<bool>(user_na)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfReader.cpp
cpp11::list df_parse_por_raw(cpp11::list spec, std::string encoding, bool user_na, std::vector<std::string> cols_skip, long n_max, long rows_skip, std::string name_repair);
extern "C" SEXP _haven_df_parse_por_raw(SEXP spec, SEXP encoding, SEXP user_na, SEXP cols_skip, SEXP n_max, SEXP rows_skip, SEXP name_repair) {
BEGIN_CPP11
return cpp11::as_sexp(df_parse_por_raw(cpp11::unmove(cpp11::as_cpp<cpp11::list>(spec)), cpp11::unmove(cpp11::as_cpp<std::string>(encoding)), cpp11::unmove(cpp11::as_cpp<bool>(user_na)), cpp11::unmove(cpp11::as_cpp<std::vector<std::string>>(cols_skip)), cpp11::unmove(cpp11::as_cpp<long>(n_max)), cpp11::unmove(cpp11::as_cpp<long>(rows_skip)), cpp11::unmove(cpp11::as_cpp<std::string>(name_repair))));
END_CPP11
}
// DfWriter.cpp
void write_sav_(cpp11::list data, cpp11::strings path, bool compress);
extern "C" SEXP _haven_write_sav_(SEXP data, SEXP path, SEXP compress) {
BEGIN_CPP11
write_sav_(cpp11::unmove(cpp11::as_cpp<cpp11::list>(data)), cpp11::unmove(cpp11::as_cpp<cpp11::strings>(path)), cpp11::unmove(cpp11::as_cpp<bool>(compress)));
return R_NilValue;
END_CPP11
}
// DfWriter.cpp
void write_dta_(cpp11::list data, cpp11::strings path, int version, cpp11::sexp label);
extern "C" SEXP _haven_write_dta_(SEXP data, SEXP path, SEXP version, SEXP label) {
BEGIN_CPP11
write_dta_(cpp11::unmove(cpp11::as_cpp<cpp11::list>(data)), cpp11::unmove(cpp11::as_cpp<cpp11::strings>(path)), cpp11::unmove(cpp11::as_cpp<int>(version)), cpp11::unmove(cpp11::as_cpp<cpp11::sexp>(label)));
return R_NilValue;
END_CPP11
}
// DfWriter.cpp
void write_sas_(cpp11::list data, cpp11::strings path);
extern "C" SEXP _haven_write_sas_(SEXP data, SEXP path) {
BEGIN_CPP11
write_sas_(cpp11::unmove(cpp11::as_cpp<cpp11::list>(data)), cpp11::unmove(cpp11::as_cpp<cpp11::strings>(path)));
return R_NilValue;
END_CPP11
}
// DfWriter.cpp
void write_xpt_(cpp11::list data, cpp11::strings path, int version, std::string name);
extern "C" SEXP _haven_write_xpt_(SEXP data, SEXP path, SEXP version, SEXP name) {
BEGIN_CPP11
write_xpt_(cpp11::unmove(cpp11::as_cpp<cpp11::list>(data)), cpp11::unmove(cpp11::as_cpp<cpp11::strings>(path)), cpp11::unmove(cpp11::as_cpp<int>(version)), cpp11::unmove(cpp11::as_cpp<std::string>(name)));
return R_NilValue;
END_CPP11
}

extern "C" {
/* .Call calls */
extern SEXP _haven_df_parse_dta_file(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_dta_raw(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_por_file(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_por_raw(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_sas_file(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_sas_raw(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_sav_file(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_sav_raw(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_xpt_file(SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_df_parse_xpt_raw(SEXP, SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_write_dta_(SEXP, SEXP, SEXP, SEXP);
extern SEXP _haven_write_sas_(SEXP, SEXP);
extern SEXP _haven_write_sav_(SEXP, SEXP, SEXP);
extern SEXP _haven_write_xpt_(SEXP, SEXP, SEXP, SEXP);
extern SEXP is_tagged_na_(SEXP, SEXP);
extern SEXP na_tag_(SEXP);
extern SEXP tagged_na_(SEXP);

static const R_CallMethodDef CallEntries[] = {
{"_haven_df_parse_dta_file", (DL_FUNC) &_haven_df_parse_dta_file, 6},
{"_haven_df_parse_dta_raw", (DL_FUNC) &_haven_df_parse_dta_raw, 6},
{"_haven_df_parse_por_file", (DL_FUNC) &_haven_df_parse_por_file, 7},
{"_haven_df_parse_por_raw", (DL_FUNC) &_haven_df_parse_por_raw, 7},
{"_haven_df_parse_sas_file", (DL_FUNC) &_haven_df_parse_sas_file, 8},
{"_haven_df_parse_sas_raw", (DL_FUNC) &_haven_df_parse_sas_raw, 8},
{"_haven_df_parse_sav_file", (DL_FUNC) &_haven_df_parse_sav_file, 7},
{"_haven_df_parse_sav_raw", (DL_FUNC) &_haven_df_parse_sav_raw, 7},
{"_haven_df_parse_xpt_file", (DL_FUNC) &_haven_df_parse_xpt_file, 5},
{"_haven_df_parse_xpt_raw", (DL_FUNC) &_haven_df_parse_xpt_raw, 5},
{"_haven_write_dta_", (DL_FUNC) &_haven_write_dta_, 4},
{"_haven_write_sas_", (DL_FUNC) &_haven_write_sas_, 2},
{"_haven_write_sav_", (DL_FUNC) &_haven_write_sav_, 3},
{"_haven_write_xpt_", (DL_FUNC) &_haven_write_xpt_, 4},
{"is_tagged_na_", (DL_FUNC) &is_tagged_na_, 2},
{"na_tag_", (DL_FUNC) &na_tag_, 1},
{"tagged_na_", (DL_FUNC) &tagged_na_, 1},
{NULL, NULL, 0}
};
}



extern "C" void R_init_haven(DllInfo* dll){
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);

}

@@ -1,6 +1,6 @@
#include <Rcpp.h>
#include <cmath>
#include "haven_types.h"
#include <cpp11/protect.hpp>

FileVendor extVendor(FileExt ext) {
switch (ext) {
@@ -11,8 +11,10 @@ FileVendor extVendor(FileExt ext) {
case HAVEN_SAS7BCAT:
case HAVEN_XPT: return HAVEN_SAS;
default:
Rcpp::stop("Unknown file extension");
cpp11::stop("Unknown file extension");
}
/* not actually reached */
return HAVEN_SAS;
}

std::string formatAttribute(FileVendor vendor) {
@@ -1,8 +1,9 @@
#ifndef __HAVEN_TYPES__
#define __HAVEN_TYPES__

#include <Rcpp.h>
#include <cmath>
#include <string>
#include <cpp11/R.hpp>

enum FileVendor {
HAVEN_SPSS,
@@ -1,7 +1,7 @@
context("connections")

test_that("connections are read", {
file_conn <- file("hadley.sas7bdat")
file_conn <- file(test_path("hadley.sas7bdat"))
expect_identical(read_sas(file_conn), read_sas("hadley.sas7bdat"))
})