Skip to content

Commit

Permalink
Clean up C++ code (#155)
Browse files Browse the repository at this point in the history
* Use a similar style to pbrohan

Except camelCase...

* Improve header hygiene

* Refactor and created `write_df` [no ci]

So that the list thing (#56) is a for loop
  • Loading branch information
chainsawriot committed Aug 23, 2023
1 parent 967e10a commit ca322d8
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 79 deletions.
14 changes: 2 additions & 12 deletions src/get_sheet_names.cpp
@@ -1,16 +1,6 @@
#include "cpp11.hpp"
#include "cpp11/r_string.hpp"
#include "cpp11/strings.hpp"

#include "rapidxml/rapidxml.hpp"
#include "readxl/zip.cpp"
#include "is_ods.h"


#include <string>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include "read_ods_internals.h"

cpp11::strings get_sheet_names_from_content (rapidxml::xml_node<>* rootNode, const bool include_external_data){

Expand All @@ -19,7 +9,7 @@ cpp11::strings get_sheet_names_from_content (rapidxml::xml_node<>* rootNode, con
int i = 0;
int n = 1;

for (rapidxml::xml_node<>* sheetData = rootNode->first_node("table:table");
for (rapidxml::xml_node<>* sheetData = rootNode->first_node("table:table");
sheetData;
sheetData = sheetData->next_sibling("table:table")){

Expand Down
13 changes: 1 addition & 12 deletions src/read_flat_ods_.cpp
@@ -1,15 +1,6 @@
#include "cpp11.hpp"
#include "cpp11/r_string.hpp"

#include "rapidxml/rapidxml.hpp"
#include "is_ods.h"
#include "read_ods_internals.h"

#include <vector>
#include <string>
#include <fstream>
#include <stdexcept>

[[cpp11::register]]
cpp11::strings read_flat_ods_(const std::string file,
int start_row,
Expand All @@ -20,7 +11,7 @@ cpp11::strings read_flat_ods_(const std::string file,
const bool formula_as_formula) {
if(!is_flat_ods(file)){
throw std::invalid_argument(file + " is not a correct FODS file");
}
}
if(sheet < 1){
throw std::invalid_argument("Cannot have sheet index less than 1");
}
Expand Down Expand Up @@ -94,5 +85,3 @@ cpp11::strings read_flat_ods_(const std::string file,
}
return cell_values;
}


12 changes: 1 addition & 11 deletions src/read_ods_.cpp
@@ -1,14 +1,6 @@
#include "cpp11.hpp"
#include "cpp11/r_string.hpp"

#include "rapidxml/rapidxml.hpp"
#include "is_ods.h"
#include "read_ods_internals.h"

#include <vector>
#include <string>
#include <stdexcept>

[[cpp11::register]]
cpp11::strings read_ods_(const std::string file,
int start_row,
Expand All @@ -19,7 +11,7 @@ cpp11::strings read_ods_(const std::string file,
const bool formula_as_formula) {
if(!is_ods(file)){
throw std::invalid_argument(file + " is not a correct ODS file");
}
}
if(sheet < 1){
throw std::invalid_argument("Cannot have sheet index less than 1");
}
Expand Down Expand Up @@ -80,5 +72,3 @@ cpp11::strings read_ods_(const std::string file,
}
return cell_values;
}


5 changes: 4 additions & 1 deletion src/read_ods_internals.h
Expand Up @@ -7,6 +7,9 @@

#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <stdexcept>

std::string parse_p(rapidxml::xml_node<>* node);
std::string parse_textp(rapidxml::xml_node<>* cell);
Expand All @@ -15,4 +18,4 @@ std::vector<std::vector<rapidxml::xml_node<>*>> find_rows(rapidxml::xml_node<>*
int start_row,
const int stop_row,
int start_col,
const int stop_col);
const int stop_col);
83 changes: 40 additions & 43 deletions src/write_sheet_.cpp
@@ -1,12 +1,6 @@
#include "cpp11.hpp"
#include "cpp11/r_string.hpp"
#include "cpp11/list.hpp"
#include <R.h>
#include <Rinternals.h>
#include <fstream>
#include <iostream>
#include "write_sheet_.h"

void cell_out_ (const cpp11::r_string& value_type, const cpp11::r_string& value, std::ofstream& xml_file) {
void cell_out (const cpp11::r_string& value_type, const cpp11::r_string& value, std::ofstream& xml_file) {
const char* value_type_c = Rf_translateCharUTF8(value_type);
const char* value_c = Rf_translateCharUTF8(value);
xml_file << "<table:table-cell office:value-type=\"";
Expand All @@ -20,76 +14,63 @@ void cell_out_ (const cpp11::r_string& value_type, const cpp11::r_string& value,
xml_file << "</text:p></table:table-cell>\n";
}

void pad_rows_ (const bool& padding, const int& cols, const int& cmax, std::ofstream& xml_file) {
void pad_rows (const bool& padding, const int& cols, const int& cmax, std::ofstream& xml_file) {
if (cols < cmax && padding) {
xml_file << "<table:table-cell table:number-columns-repeated=\"";
xml_file << cmax - cols;
xml_file << "\"/>\n";
}
}

cpp11::strings dimnames_(const cpp11::data_frame& x, bool cols) {
cpp11::strings dimnames(const cpp11::data_frame& x, bool cols) {
// Is there a better way?
cpp11::function dimnames_rfun = cpp11::package("readODS")[".get_sanitized_dimnames"];
return cpp11::writable::strings(static_cast<SEXP>(dimnames_rfun(x, cols)));
}

cpp11::list_of<cpp11::strings> sanitize_(const cpp11::data_frame& x, const cpp11::strings column_types) {
cpp11::list_of<cpp11::strings> sanitize(const cpp11::data_frame& x, const cpp11::strings column_types) {
cpp11::function sanitize_rfun = cpp11::package("readODS")[".sanitize_df"];
return cpp11::writable::list_of<cpp11::strings>(static_cast<SEXP>(sanitize_rfun(x, column_types)));
}

cpp11::strings get_column_types_(const cpp11::data_frame& x) {
cpp11::strings get_column_types(const cpp11::data_frame& x) {
cpp11::function get_column_types_rfun = cpp11::package("readODS")[".get_column_types"];
return cpp11::writable::strings(static_cast<SEXP>(get_column_types_rfun(x)));
}

std::string escape_xml_(const std::string& input) {
std::string escape_xml(const std::string& input) {
cpp11::sexp input_sexp = cpp11::as_sexp(input);
cpp11::function escape_xml_rfun = cpp11::package("readODS")[".escape_xml"];
return cpp11::as_cpp<std::string>(escape_xml_rfun(input_sexp));
}

void write_empty_(const std::string& escaped_sheet, std::ofstream& xml_file, const std::string& header, const std::string& footer) {
xml_file << header;
void write_empty(const std::string& sheet, std::ofstream& xml_file, const std::string& escaped_sheet) {
xml_file << "<table:table table:name=\"";
xml_file << escaped_sheet;
xml_file << "\" table:style-name=\"ta1\">";
xml_file << "</table:table>";
xml_file << footer;
}

[[cpp11::register]]
cpp11::r_string write_sheet_(const std::string& filename,
const cpp11::data_frame& x,
const std::string& sheet,
const bool row_names,
const bool col_names,
const bool na_as_string,
const bool padding,
const std::string& header,
const std::string& footer) {
// TODO: if x.nrow() == 0; just write empty xml
std::ofstream xml_file(filename);
std::string escaped_sheet = escape_xml_(sheet);
bool write_df(const cpp11::data_frame& x, const std::string& sheet, const bool row_names, const bool col_names,
const bool na_as_string, const bool padding, std::ofstream& xml_file) {
std::string escaped_sheet = escape_xml(sheet);
if (x.ncol() == 0 || (x.nrow() == 0 && !col_names && x.ncol() != 0)) {
write_empty_(escaped_sheet, xml_file, header, footer);
return filename;
write_empty(sheet, xml_file, escaped_sheet);
return true;
}
cpp11::strings column_types = get_column_types_(x);
cpp11::strings column_types = get_column_types(x);
cpp11::strings rownames_x, colnames_x;
cpp11::list_of<cpp11::strings> x_list = sanitize_(x, column_types);
cpp11::list_of<cpp11::strings> x_list = sanitize(x, column_types);
if (row_names) {
rownames_x = dimnames_(x, false);
rownames_x = dimnames(x, false);
}
if (col_names) {
colnames_x = dimnames_(x, true);
colnames_x = dimnames(x, true);
}
int rows = col_names ? x_list[0].size() + 1 : x_list[0].size();
int cols = row_names ? column_types.size() + 1 : column_types.size();
int cmax = column_types.size() > 1024 ? 16384 : 1024;
// gen_sheet_tag
xml_file << header;
xml_file << "\n<table:table table:name=\"";
xml_file << escaped_sheet;
xml_file << "\" table:style-name=\"ta1\">\n";
Expand All @@ -101,31 +82,31 @@ cpp11::r_string write_sheet_(const std::string& filename,
if (col_names) {
xml_file << "<table:table-row table:style-name=\"ro1\">";
if (row_names) {
cell_out_("string", "", xml_file);
cell_out("string", "", xml_file);
}
for (int j = 0; j < colnames_x.size(); j++) {
cell_out_("string", colnames_x[j], xml_file);
cell_out("string", colnames_x[j], xml_file);
}
pad_rows_(padding, cols, cmax, xml_file);
pad_rows(padding, cols, cmax, xml_file);
xml_file << "</table:table-row>\n";
}
for (int i = 0; i < x_list[0].size(); i++) {
xml_file << "<table:table-row table:style-name=\"ro1\">\n";
if (row_names) {
cell_out_("string", rownames_x[i], xml_file);
cell_out("string", rownames_x[i], xml_file);
}
for (int j = 0; j < column_types.size(); j++) {
if (x_list[j][i] != NA_STRING) {
cell_out_(column_types[j], x_list[j][i], xml_file);
cell_out(column_types[j], x_list[j][i], xml_file);
continue;
}
if (!na_as_string) {
xml_file << "<table:table-cell/>\n";
continue;
}
cell_out_("string", "NA", xml_file);
cell_out("string", "NA", xml_file);
}
pad_rows_(padding, cols, cmax, xml_file);
pad_rows(padding, cols, cmax, xml_file);
xml_file << "</table:table-row>\n";
}
// pad_columns
Expand All @@ -139,6 +120,22 @@ cpp11::r_string write_sheet_(const std::string& filename,
xml_file << "</table:table-row>\n";
}
xml_file << "</table:table>\n";
return true;
}

[[cpp11::register]]
cpp11::r_string write_sheet_(const std::string& filename,
const cpp11::data_frame& x,
const std::string& sheet,
const bool row_names,
const bool col_names,
const bool na_as_string,
const bool padding,
const std::string& header,
const std::string& footer) {
std::ofstream xml_file(filename);
xml_file << header;
bool success = write_df(x, sheet, row_names, col_names, na_as_string, padding, xml_file);
xml_file << footer;
xml_file << "\n";
xml_file.close();
Expand Down

0 comments on commit ca322d8

Please sign in to comment.