From 9e6c23407d4d62505691c9a243c75230d50a4261 Mon Sep 17 00:00:00 2001 From: hrbrmstr Date: Sat, 7 Mar 2020 06:48:56 -0500 Subject: [PATCH] data frame\! --- DESCRIPTION | 4 ++- NAMESPACE | 1 + R/caa-dig.R | 24 ++++++++++++++- R/caa-package.R | 4 ++- README.Rmd | 5 ++++ README.md | 31 ++++++++++++++----- inst/tinytest/test_caa.R | 7 +++-- man/caa.Rd | 3 +- man/caa_dig.Rd | 10 +++++++ src/caa.h | 4 ++- src/go/src/main/main.c | 77 ++++++++++++++++++++++++++---------------------- src/go/src/main/main.go | 57 ++++++++++++++++++++++++++--------- 12 files changed, 163 insertions(+), 64 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f042f8e..59b0ce8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -10,7 +10,7 @@ Authors@R: c( ) Maintainer: Bob Rudis Description: Experimental R wrapper for the Go dnscall library. Builds off of work done by - Romain Francois (). + Romain Francois (). URL: https://git.rud.is/hrbrmstr/caa BugReports: https://git.rud.is/hrbrmstr/caa/issues Encoding: UTF-8 @@ -18,6 +18,8 @@ License: MIT + file LICENSE SystemRequirements: go, GNU make Suggests: covr, tinytest +Imports: + tibble Depends: R (>= 3.2.0) Roxygen: list(markdown = TRUE) diff --git a/NAMESPACE b/NAMESPACE index 8ca8953..e6714cb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,4 +1,5 @@ # Generated by roxygen2: do not edit by hand export(caa_dig) +importFrom(tibble,as_tibble) useDynLib(caa) diff --git a/R/caa-dig.R b/R/caa-dig.R index f801e2f..9ba4f8f 100644 --- a/R/caa-dig.R +++ b/R/caa-dig.R @@ -2,8 +2,30 @@ #' #' @param x domain name #' @export +#' @return data frame (tibble) #' @examples +#' # one record back #' caa_dig("google.com") +#' +#' # multiple +#' caa::caa_dig("www.comodo.com") +#' +#' # none (lookup error) +#' caa::caa_dig("www.comodo.comm") caa_dig <- function(x) { - .Call("R_caa_dig", x, PACKAGE = "caa") + + out <- .Call("R_caa_dig", x, PACKAGE = "caa") + + if (length(out) == 0) { + + data.frame( + tag = character(0), + value = character(0), + stringsAsFactors = FALSE + ) -> out + + } + + as_tibble(out) + } diff --git a/R/caa-package.R b/R/caa-package.R index bf61e19..6fd4970 100644 --- a/R/caa-package.R +++ b/R/caa-package.R @@ -1,9 +1,11 @@ #' R Wrapper for the Go dnscaa Library #' -#' Experimental R wrapper for the Go dnscaa library. +#' Experimental R wrapper for the Go dnscall library. Builds off of work done by +#' Romain Francois () #' #' @md #' @name caa +#' @importFrom tibble as_tibble #' @keywords internal #' @author Bob Rudis (bob@@rud.is) #' @useDynLib caa diff --git a/README.Rmd b/README.Rmd index 60dd9e6..fcf7ab2 100644 --- a/README.Rmd +++ b/README.Rmd @@ -40,9 +40,14 @@ packageVersion("caa") ``` ```{r ex-1} +# one record caa_dig("google.com") +# multiple caa_dig("www.comodo.com") + +# none (lookup error) +caa_dig("www.comodo.comm") ``` ## caa Metrics diff --git a/README.md b/README.md index 188cd75..280692f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ R Wrapper for the Go dnscaa Library ## Description Experimental R wrapper for the Go dnscall library. Builds off of work -done by Romain Francois (). +done by Romain Francois (). ## What’s Inside The Tin @@ -51,30 +51,45 @@ packageVersion("caa") ``` ``` r +# one record caa_dig("google.com") -## [1] "pki.goog" +## # A tibble: 1 x 2 +## tag value +## +## 1 issue pki.goog +# multiple caa_dig("www.comodo.com") -## [1] "digicert.com" "mailto:sslabuse@comodoca.com" "comodoca.com" +## # A tibble: 3 x 2 +## tag value +## +## 1 issue digicert.com +## 2 iodef mailto:sslabuse@comodoca.com +## 3 issue comodoca.com + +# none (lookup error) +caa_dig("www.comodo.comm") +## # A tibble: 0 x 2 +## # … with 2 variables: tag , value ``` ## caa Metrics | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | | :----------------- | -------: | ---: | -----: | ---: | ----------: | ---: | -------: | ---: | -| Go | 1293 | 0.92 | 374709 | 0.95 | 40514 | 0.95 | 39884 | 0.95 | +| Go | 1293 | 0.92 | 374722 | 0.95 | 40522 | 0.95 | 39892 | 0.95 | | Assembly | 69 | 0.05 | 10426 | 0.03 | 1258 | 0.03 | 1424 | 0.03 | | XML | 1 | 0.00 | 4780 | 0.01 | 228 | 0.01 | 13 | 0.00 | | HTML | 10 | 0.01 | 2214 | 0.01 | 441 | 0.01 | 16 | 0.00 | | Bourne Shell | 5 | 0.00 | 798 | 0.00 | 113 | 0.00 | 429 | 0.01 | -| C | 6 | 0.00 | 332 | 0.00 | 103 | 0.00 | 100 | 0.00 | +| C | 6 | 0.00 | 351 | 0.00 | 111 | 0.00 | 80 | 0.00 | | Dockerfile | 3 | 0.00 | 91 | 0.00 | 27 | 0.00 | 23 | 0.00 | | Bourne Again Shell | 2 | 0.00 | 72 | 0.00 | 12 | 0.00 | 6 | 0.00 | -| C/C++ Header | 1 | 0.00 | 47 | 0.00 | 27 | 0.00 | 10 | 0.00 | +| C/C++ Header | 1 | 0.00 | 48 | 0.00 | 28 | 0.00 | 10 | 0.00 | | YAML | 2 | 0.00 | 45 | 0.00 | 0 | 0.00 | 0 | 0.00 | | make | 2 | 0.00 | 25 | 0.00 | 7 | 0.00 | 4 | 0.00 | -| Rmd | 1 | 0.00 | 10 | 0.00 | 17 | 0.00 | 30 | 0.00 | -| R | 3 | 0.00 | 7 | 0.00 | 2 | 0.00 | 15 | 0.00 | +| R | 3 | 0.00 | 15 | 0.00 | 8 | 0.00 | 25 | 0.00 | +| Rmd | 1 | 0.00 | 11 | 0.00 | 18 | 0.00 | 33 | 0.00 | ## Code of Conduct diff --git a/inst/tinytest/test_caa.R b/inst/tinytest/test_caa.R index dfee2ec..c5cb9ed 100644 --- a/inst/tinytest/test_caa.R +++ b/inst/tinytest/test_caa.R @@ -1,4 +1,7 @@ -# Placeholder with simple test -expect_equal(caa_dig("google.com"), "pki.goog") +res <- caa_dig("google.com") +expect_equal(res$value, "pki.goog") +expect_equal(nrow(caa::caa_dig("www.comodo.com")), 3) + +expect_equal(nrow(caa::caa_dig("www.comodo.comm")), 0) diff --git a/man/caa.Rd b/man/caa.Rd index b696bc3..bc713c9 100644 --- a/man/caa.Rd +++ b/man/caa.Rd @@ -6,7 +6,8 @@ \alias{caa-package} \title{R Wrapper for the Go dnscaa Library} \description{ -Experimental R wrapper for the Go dnscaa library. +Experimental R wrapper for the Go dnscall library. Builds off of work done by +Romain Francois (\url{https://github.com/rstats-go}) } \seealso{ Useful links: diff --git a/man/caa_dig.Rd b/man/caa_dig.Rd index 3d8334a..cb8e51e 100644 --- a/man/caa_dig.Rd +++ b/man/caa_dig.Rd @@ -9,9 +9,19 @@ caa_dig(x) \arguments{ \item{x}{domain name} } +\value{ +data frame (tibble) +} \description{ Retrieve the CAA record values for a domain (if any) } \examples{ +# one record back caa_dig("google.com") + +# multiple +caa::caa_dig("www.comodo.com") + +# none (lookup error) +caa::caa_dig("www.comodo.comm") } diff --git a/src/caa.h b/src/caa.h index 820626e..f7cb41f 100644 --- a/src/caa.h +++ b/src/caa.h @@ -25,6 +25,8 @@ typedef struct { const char *p; ptrdiff_t n; } _GoString_; #include #include + SEXP MakeDF(int n, char** tag, char** val); + #line 1 "cgo-generated-wrapper" @@ -77,7 +79,7 @@ extern "C" { #endif -extern char** caa_dig(GoString p0, int* p1); +extern SEXP caa_dig(GoString p0); #ifdef __cplusplus } diff --git a/src/go/src/main/main.c b/src/go/src/main/main.c index ae71407..333e2ef 100644 --- a/src/go/src/main/main.c +++ b/src/go/src/main/main.c @@ -7,24 +7,43 @@ #define SHORT_VEC_LENGTH(x) (((VECSEXP) (x))->vecsxp.length) -SEXP R_caa_dig(SEXP x) { - - SEXP sx = STRING_ELT(x, 0); +SEXP MakeDF(int n, char** tag, char** val) { - GoString h = { (char*) CHAR(sx), SHORT_VEC_LENGTH(sx) }; - - int n = 0; - char **res = caa_dig(h, &n); + if (val != NULL) { - if (res != NULL) { + SEXP value_vec = PROTECT(allocVector(STRSXP, n)); + for (int i=0; i #include + SEXP MakeDF(int n, char** tag, char** val); + */ import "C" -//import "fmt" +import "log" +import "io/ioutil" import "unsafe" import "github.com/weppos/dnscaa" +// import "fmt" + //export caa_dig -func caa_dig(hostname string, n *C.int) **C.char { +func caa_dig(hostname string) C.SEXP { records, err := dnscaa.Lookup(hostname) - if err != nil { - return nil + if ((err != nil) || (len(records) == 0)) { + return(C.R_NilValue) } else { - goResult := []string{} + // go slices for our columns + + val := []string{} + tag := []string{} for _, r := range records { - goResult = append(goResult, r.Value) + val = append(val, r.Value) + tag = append(tag, r.Tag) + } + + // ugly setup & population code for turning those slices + // into char** so we can pass them to the C code which + // will make an R data frame + + // allocate the array of char* pointers + val_arr := C.malloc(C.size_t(len(val)) * C.size_t(unsafe.Sizeof(uintptr(0)))) + val_go := (*[1<<30 - 1]*C.char)(val_arr) // https://stackoverflow.com/questions/48756732/what-does-1-30c-yourtype-do-exactly-in-cgo + + // populate the array + for idx, elem := range val { + val_go[idx] = C.CString(elem) } - cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0)))) - a := (*[1<<30 - 1]*C.char)(cArray) + tag_arr := C.malloc(C.size_t(len(tag)) * C.size_t(unsafe.Sizeof(uintptr(0)))) + tag_go := (*[1<<30 - 1]*C.char)(tag_arr) - for idx, substring := range goResult { - a[idx] = C.CString(substring) + for idx, elem := range tag { + tag_go[idx] = C.CString(elem) } - *n = C.int(len(goResult)) + // how many things + n := C.int(len(val)) - //out := records[0].Value - //return(C.CString(out)) + // clean up after calling the data frame maker + defer C.free(unsafe.Pointer(val_arr)) + defer C.free(unsafe.Pointer(tag_arr)) - return (**C.char)(cArray) + return(C.MakeDF(n, (**C.char)(tag_arr), (**C.char)(val_arr))); } + +} + +func init() { + log.SetOutput(ioutil.Discard) } func main() {}