1 #pragma once
2 
3 #include <cpp11/as.hpp>
4 #include <cpp11/function.hpp>
5 #include <cpp11/list.hpp>
6 #include <cpp11/raws.hpp>
7 
8 // We need to undefine these here as they may be previously defined in windows headers
9 #undef TRUE
10 #undef FALSE
11 #include <cpp11/logicals.hpp>
12 
13 #ifdef VROOM_USE_CONNECTIONS_API
14 
15 // clang-format off
16 #ifdef __clang__
17 # pragma clang diagnostic push
18 # pragma clang diagnostic ignored "-Wkeyword-macro"
19 #endif
20 #define class class_name
21 #define private private_ptr
22 #include <R_ext/Connections.h>
23 #undef class
24 #undef private
25 #ifdef __clang__
26 # pragma clang diagnostic pop
27 #endif
28 // clang-format on
29 
30 #if R_CONNECTIONS_VERSION != 1
31 #error "Missing or unsupported connection API in R"
32 #endif
33 
34 #if R_VERSION < R_Version(3, 3, 0)
35 /* R before 3.3.0 didn't have R_GetConnection() */
36 extern "C" {
37 
38 extern Rconnection getConnection(int n);
R_GetConnection(SEXP sConn)39 static Rconnection R_GetConnection(SEXP sConn) {
40   return getConnection(Rf_asInteger(sConn));
41 }
42 }
43 
44 #endif
45 
46 #else
47 
48 #pragma once
49 
R_GetConnection(SEXP con)50 inline SEXP R_GetConnection(SEXP con) { return con; }
51 
R_ReadConnection(SEXP con,void * buf,size_t n)52 inline size_t R_ReadConnection(SEXP con, void* buf, size_t n) {
53   static auto readBin = cpp11::package("base")["readBin"];
54 
55   cpp11::raws res(
56       readBin(con, cpp11::writable::raws(static_cast<R_xlen_t>(0)), n));
57   memcpy(buf, RAW(res), res.size());
58 
59   return res.size();
60 }
61 
R_WriteConnection(SEXP con,void * buf,size_t n)62 inline size_t R_WriteConnection(SEXP con, void* buf, size_t n) {
63   static auto writeBin = cpp11::package("base")["writeBin"];
64 
65   cpp11::writable::raws payload(n);
66   memcpy(RAW(payload), buf, n);
67 
68   writeBin(payload, con);
69 
70   return n;
71 }
72 
73 #endif
74 
con_description(SEXP con)75 inline std::string con_description(SEXP con) {
76   static auto summary_connection = cpp11::package("base")["summary.connection"];
77   return cpp11::as_cpp<std::string>(cpp11::list(summary_connection(con))[0]);
78 }
79 
is_open(SEXP con)80 inline bool is_open(SEXP con) {
81   static auto isOpen = cpp11::package("base")["isOpen"];
82 
83   cpp11::logicals res(isOpen(con));
84 
85   return res[0];
86 }
87