diff --git a/.Rbuildignore b/.Rbuildignore index c4dd8fd..b5c32bd 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -6,4 +6,5 @@ parse_stdin$ ^\.Rproj\.user$ ^LICENSE$ ^local -.*tar.gz$ \ No newline at end of file +.*tar.gz$ +^.editorconfig$ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c971b74 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# Matches multiple files with brace expansion notation +# 4 space indentation +[*.{c,cpp,h,hpp,R,r}] +indent_style = space +indent_size = 4 + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab + diff --git a/ChangeLog b/ChangeLog index 1a9b3e6..6cd2704 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2018-10-25 Dirk Eddelbuettel + + * src/parse.cpp (getValue): Support local time + 2018-10-23 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Release 0.1.4 diff --git a/DESCRIPTION b/DESCRIPTION index 68205a0..38f9042 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,15 +1,15 @@ Package: RcppTOML Type: Package Title: 'Rcpp' Bindings to Parser for Tom's Obvious Markup Language -Version: 0.1.4 -Date: 2018-10-23 +Version: 0.1.4.1 +Date: 2018-10-25 Author: Dirk Eddelbuettel Maintainer: Dirk Eddelbuettel Description: The configuration format defined by 'TOML' (which expands to "Tom's Obvious Markup Language") specifies an excellent format (described at ) suitable for both human editing as well as the common uses of a machine-readable format. This package uses 'Rcpp' to - connect the 'cpptoml' parser written by Chase Geigle (in modern C++11) to R. + connect the 'cpptoml' parser written by Chase Geigle (in modern C++11) to R. SystemRequirements: A C++11 compiler; g++ (>= 4.8.*) should be fine. BugReports: https://github.com/eddelbuettel/rcpptoml/issues URL: http://dirk.eddelbuettel.com/code/rcpp.toml.html diff --git a/README.md b/README.md index 3998107..eb3e410 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -## RcppTOML [![Build -Status](https://travis-ci.org/eddelbuettel/rcpptoml.svg)](https://travis-ci.org/eddelbuettel/rcpptoml) [![License](http://img.shields.io/badge/license-GPL%20%28%3E=%202%29-brightgreen.svg?style=flat)](http://www.gnu.org/licenses/gpl-2.0.html) [![CRAN](http://www.r-pkg.org/badges/version/RcppTOML)](https://cran.r-project.org/package=RcppTOML) [![Dependencies](https://tinyverse.netlify.com/badge/RcppTOML)](https://cran.r-project.org/package=RcppTOML) [![Downloads](http://cranlogs.r-pkg.org/badges/RcppTOML?color=brightgreen)](http://www.r-pkg.org/pkg/RcppTOML) +## RcppTOML [![Build Status](https://travis-ci.org/eddelbuettel/rcpptoml.svg)](https://travis-ci.org/eddelbuettel/rcpptoml) [![License](http://img.shields.io/badge/license-GPL%20%28%3E=%202%29-brightgreen.svg?style=flat)](http://www.gnu.org/licenses/gpl-2.0.html) [![CRAN](http://www.r-pkg.org/badges/version/RcppTOML)](https://cran.r-project.org/package=RcppTOML) [![Dependencies](https://tinyverse.netlify.com/badge/RcppTOML)](https://cran.r-project.org/package=RcppTOML) [![Downloads](http://cranlogs.r-pkg.org/badges/RcppTOML?color=brightgreen)](http://www.r-pkg.org/pkg/RcppTOML) Rcpp bindings for [TOML](https://github.com/toml-lang/toml) @@ -12,8 +11,8 @@ useful as it is strongly typed: values come back as integer, double, nesting and arrays are supported as well. This package uses the C++11 implementation written by Chase Geigle in -[cpptoml](https://github.com/skystrife/cpptoml) to implement a parser used by -R. +[cpptoml](https://github.com/skystrife/cpptoml) to provide a parser that can +be used by R. ### Example @@ -82,7 +81,7 @@ List of 5 .. ..$ dc: chr "eqdc10" .. ..$ ip: chr "10.0.0.2" $ title : chr "TOML Example" -R> +R> ``` See the other examples and the [upstream documentation](https://github.com/toml-lang/toml) for more. @@ -113,7 +112,7 @@ drat::addRepo("ghrr") Feature-complete with [TOML v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md), see the [tests/](https://github.com/eddelbuettel/rcpptoml/tree/master/tests) -directory. It parses everything that the underlying +directory. It parses everything that the underlying [cpptoml](https://github.com/skystrife/cpptoml) parses with the same (sole) exception of unicode escape characters in strings. @@ -124,5 +123,3 @@ Dirk Eddelbuettel ### License GPL (>= 2) - - diff --git a/src/parse.cpp b/src/parse.cpp index 3c83705..8e4cf4c 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -2,7 +2,7 @@ // // RcppTOML -- Rcpp bindings to TOML via cpptoml // -// Copyright (C) 2015 - 2017 Dirk Eddelbuettel +// Copyright (C) 2015 - 2018 Dirk Eddelbuettel // // This file is part of RcppTOML // @@ -96,7 +96,7 @@ SEXP getValue(const std::shared_ptr& base, bool escape=true) { if (auto v = base->as()) { std::string s(v->get()); if (escape) { - s = escapeString(s); + s = escapeString(s); } return Rcpp::wrap(s); } else if (auto v = base->as()) { @@ -122,7 +122,7 @@ SEXP getValue(const std::shared_ptr& base, bool escape=true) { tm.tm_hour = s.hour; tm.tm_min = s.minute; tm.tm_sec = s.second; - time_t tt = local_timegm(&tm); + time_t tt = local_timegm(&tm); //tt = tt - s.hour_offset*60*60 - s.minute_offset*60; Rcpp::DatetimeVector dt(1, "UTC"); dt[0] = tt + s.microsecond * 1.0e-6; @@ -136,11 +136,23 @@ SEXP getValue(const std::shared_ptr& base, bool escape=true) { tm.tm_hour = s.hour; tm.tm_min = s.minute; tm.tm_sec = s.second; - time_t tt = local_timegm(&tm); + time_t tt = local_timegm(&tm); tt = tt - s.hour_offset*60*60 - s.minute_offset*60; Rcpp::DatetimeVector dt(1, "UTC"); dt[0] = tt + s.microsecond * 1.0e-6; return Rcpp::wrap(dt); + } else if (auto v = base->as()) { + cpptoml::local_time t(v->get()); + char txt[32]; + if (t.microsecond != 0) { + snprintf(txt, 31, "%02d:%02d:%02d.%d", + t.hour, t.minute, t.second, t.microsecond); + } else { + snprintf(txt, 31, "%02d:%02d:%02d", + t.hour, t.minute, t.second); + } + std::string s(txt); + return Rcpp::wrap(s); } else { Rcpp::warning("Unparsed value, returning null"); return R_NilValue; @@ -155,7 +167,7 @@ void printArray(std::ostream& o, cpptoml::array& arr) { printArray(o, *(*it)->as_array()); else printValue(o, *it); - + if (++it != arr.get().end()) o << ", "; } @@ -164,7 +176,7 @@ void printArray(std::ostream& o, cpptoml::array& arr) { SEXP collapsedList(Rcpp::List ll) { if (ll.length() == 0) return R_NilValue; - Rcpp::List::iterator it = ll.begin(); + Rcpp::List::iterator it = ll.begin(); switch(TYPEOF(*it)) { case REALSXP: { Rcpp::NumericVector v(ll.begin(), ll.end()); @@ -213,14 +225,14 @@ SEXP getArray(const cpptoml::array& arr, bool escape=true) { auto it = arr.get().begin(); while (it != arr.get().end()) { if ((*it)->is_array()) { - sl.push_back(getArray(*(*it)->as_array())); + sl.push_back(getArray(*(*it)->as_array())); nonested = false; } else { sl.push_back(getValue(*it, escape)); nonested = true; } it++; - } + } if (nonested) { return collapsedList(Rcpp::as(sl)); } else { @@ -242,14 +254,14 @@ SEXP getTable(const std::shared_ptr& t, bool verbose=false, bool Rcpp::Rcout << "Array: " << p.first << std::endl; printArray(Rcpp::Rcout, *ga); } - sl.push_back(Rcpp::Named(p.first) = getArray(*ga)); + sl.push_back(Rcpp::Named(p.first) = getArray(*ga)); } else if (p.second->is_value()) { if (verbose) { Rcpp::Rcout << "Value: " << p.first << "\n :"; printValue(Rcpp::Rcout, p.second); Rcpp::Rcout << std::endl; } - sl.push_back(Rcpp::Named(p.first) = getValue(p.second, escape)); + sl.push_back(Rcpp::Named(p.first) = getValue(p.second, escape)); } else if (p.second->is_table_array()) { if (verbose) Rcpp::Rcout << "TableArray: " << p.first << std::endl; Rcpp::StretchyList l; @@ -263,7 +275,7 @@ SEXP getTable(const std::shared_ptr& t, bool verbose=false, bool sl.push_back(Rcpp::Named(p.first) = Rcpp::as(l)); } else { if (verbose) Rcpp::Rcout << "Other: " << p.first << std::endl; - sl.push_back(p.first); + sl.push_back(p.first); } } return Rcpp::as(sl); @@ -296,11 +308,11 @@ Rcpp::List tomlparseImpl(const std::string input, cpptoml::parser p(strstream); g = p.parse(); } - + if (verbose) { - Rcpp::Rcout << "\n" + Rcpp::Rcout << "\n" << (*g) - << "\n" + << "\n" << std::endl; } @@ -328,7 +340,7 @@ Rcpp::List tomlparseImpl(const std::string input, } else if (p.second->is_array()) { auto ga = std::dynamic_pointer_cast(p.second); if (verbose) Rcpp::Rcout << "Array: " << p.first << std::endl; - sl.push_back(Rcpp::Named(p.first) = getArray(*ga)); + sl.push_back(Rcpp::Named(p.first) = getArray(*ga)); } else if (p.second->is_value()) { if (verbose) { @@ -336,13 +348,12 @@ Rcpp::List tomlparseImpl(const std::string input, printValue(Rcpp::Rcout, p.second); Rcpp::Rcout << std::endl; } - sl.push_back(Rcpp::Named(p.first) = getValue(p.second, escape)); - + sl.push_back(Rcpp::Named(p.first) = getValue(p.second, escape)); } else { if (verbose) Rcpp::Rcout << "Other: " << p.first << std::endl; - sl.push_front(p.first); + sl.push_front(p.first); } } - + return Rcpp::as(sl); }