Browse Source

data frame\!

master
boB Rudis 4 years ago
parent
commit
9e6c23407d
No known key found for this signature in database GPG Key ID: 1D7529BE14E2BBA9
  1. 4
      DESCRIPTION
  2. 1
      NAMESPACE
  3. 24
      R/caa-dig.R
  4. 4
      R/caa-package.R
  5. 5
      README.Rmd
  6. 31
      README.md
  7. 7
      inst/tinytest/test_caa.R
  8. 3
      man/caa.Rd
  9. 10
      man/caa_dig.Rd
  10. 4
      src/caa.h
  11. 77
      src/go/src/main/main.c
  12. 57
      src/go/src/main/main.go

4
DESCRIPTION

@ -10,7 +10,7 @@ Authors@R: c(
)
Maintainer: Bob Rudis <bob@rud.is>
Description: Experimental R wrapper for the Go dnscall library. Builds off of work done by
Romain Francois (<https://github.com/rstats-go/gotest>).
Romain Francois (<https://github.com/rstats-go>).
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)

1
NAMESPACE

@ -1,4 +1,5 @@
# Generated by roxygen2: do not edit by hand
export(caa_dig)
importFrom(tibble,as_tibble)
useDynLib(caa)

24
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)
}

4
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 (<https://github.com/rstats-go>)
#'
#' @md
#' @name caa
#' @importFrom tibble as_tibble
#' @keywords internal
#' @author Bob Rudis (bob@@rud.is)
#' @useDynLib caa

5
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

31
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 (<https://github.com/rstats-go/gotest>).
done by Romain Francois (<https://github.com/rstats-go>).
## 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
## <chr> <chr>
## 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
## <chr> <chr>
## 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 <chr>, value <chr>
```
## 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

7
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)

3
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:

10
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")
}

4
src/caa.h

@ -25,6 +25,8 @@ typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#include <R.h>
#include <Rinternals.h>
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
}

77
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<n; i++) {
SET_STRING_ELT(value_vec, i, mkChar(val[i]));
free(val[i]); // allocated on heap on the Go side
}
SEXP out = PROTECT(allocVector(STRSXP, n));
SEXP tag_vec = PROTECT(allocVector(STRSXP, n));
for (int i=0; i<n; i++) {
SET_STRING_ELT(out, i, mkChar(res[i]));
SET_STRING_ELT(tag_vec, i, mkChar(tag[i]));
free(tag[i]); // allocated on heap on the Go side
}
UNPROTECT(1);
free(res);
// make column names
SEXP colnames = PROTECT(allocVector(STRSXP, 2));
SET_STRING_ELT(colnames, 0, mkChar("tag"));
SET_STRING_ELT(colnames, 1, mkChar("value"));
// make row names
SEXP rownames = PROTECT(allocVector(INTSXP, 2));
INTEGER(rownames)[0] = NA_INTEGER;
INTEGER(rownames)[1] = -n;
// the data frame (finally)
SEXP out = PROTECT(allocVector(VECSXP, 2));
setAttrib(out, R_ClassSymbol, ScalarString(mkChar("data.frame")));
SET_VECTOR_ELT(out, 0, tag_vec);
SET_VECTOR_ELT(out, 1, value_vec);
setAttrib(out, R_RowNamesSymbol, rownames);
setAttrib(out, R_NamesSymbol, colnames);
UNPROTECT(5);
return(out);
@ -34,26 +53,14 @@ SEXP R_caa_dig(SEXP x) {
}
//SEXP R_caa_dig(SEXP x) {
//
// SEXP sx = STRING_ELT(x, 0);
// GoString h = { (char*) CHAR(sx), SHORT_VEC_LENGTH(sx) };
//
// char *res = caa_dig(h);
//
// if (res != NULL) {
//
// SEXP out = PROTECT(allocVector(STRSXP, 1));
// SET_STRING_ELT(out, 0, mkChar(res));
// UNPROTECT(1);
//
// free(res);
//
// return(out);
//
// } else {
// return(R_NilValue);
// }
//
//}
//
SEXP R_caa_dig(SEXP x) {
SEXP sx = STRING_ELT(x, 0);
GoString h = { (char*) CHAR(sx), SHORT_VEC_LENGTH(sx) };
SEXP out = caa_dig(h);
return(out);
}

57
src/go/src/main/main.go

@ -5,42 +5,71 @@ package main
#include <R.h>
#include <Rinternals.h>
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() {}

Loading…
Cancel
Save