Skip to content

Commit d264fa7

Browse files
authored
Fix #47 (#48)
* NA aware * Fix #47 Still not working * Use R wrapper to filter `NULL` - TODO Ask the Rcpp community what is the best practice to deal with this. ```r bench::mark(url_decode2(rep("Hello%20World", 5000))) ``` Took 1.53ms.
1 parent fc79286 commit d264fa7

File tree

6 files changed

+48
-31
lines changed

6 files changed

+48
-31
lines changed

R/RcppExports.R

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,8 @@ Rcpp_ada_get_protocol <- function(url_vec) {
7777
.Call(`_adaR_Rcpp_ada_get_protocol`, url_vec)
7878
}
7979

80-
#' Function to percent-decode characters in URLs
81-
#'
82-
#' Similar to [utils::URLdecode]
83-
#'
84-
#' @param url a character vector
85-
#' @export
86-
#' @examples
87-
#' url_decode2("Hello%20World")
88-
url_decode2 <- function(url) {
89-
.Call(`_adaR_url_decode2`, url)
80+
Rcpp_url_decode2 <- function(url) {
81+
.Call(`_adaR_Rcpp_url_decode2`, url)
9082
}
9183

9284
url_reverse <- function(urls) {

R/parse.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ ada_url_parse <- function(url, decode = TRUE) {
3030
df
3131
}
3232

33+
#' Function to percent-decode characters in URLs
34+
#'
35+
#' Similar to [utils::URLdecode]
36+
#'
37+
#' @param url a character vector
38+
#' @export
39+
#' @examples
40+
#' url_decode2("Hello%20World")
41+
#' @export
42+
url_decode2 <- function(url) {
43+
if (is.null(url)) {
44+
return(character(0))
45+
}
46+
Rcpp_url_decode2(url)
47+
}
48+
3349
## NA/NULL-aware utils::URLdecode, hopefully without great performance impact
3450
.URLdecode <- function(URL) {
3551
if (is.null(URL)) {

man/url_decode2.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/RcppExports.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,14 @@ BEGIN_RCPP
219219
return rcpp_result_gen;
220220
END_RCPP
221221
}
222-
// url_decode2
223-
CharacterVector url_decode2(const CharacterVector& url);
224-
RcppExport SEXP _adaR_url_decode2(SEXP urlSEXP) {
222+
// Rcpp_url_decode2
223+
CharacterVector Rcpp_url_decode2(CharacterVector& url);
224+
RcppExport SEXP _adaR_Rcpp_url_decode2(SEXP urlSEXP) {
225225
BEGIN_RCPP
226226
Rcpp::RObject rcpp_result_gen;
227227
Rcpp::RNGScope rcpp_rngScope_gen;
228-
Rcpp::traits::input_parameter< const CharacterVector& >::type url(urlSEXP);
229-
rcpp_result_gen = Rcpp::wrap(url_decode2(url));
228+
Rcpp::traits::input_parameter< CharacterVector& >::type url(urlSEXP);
229+
rcpp_result_gen = Rcpp::wrap(Rcpp_url_decode2(url));
230230
return rcpp_result_gen;
231231
END_RCPP
232232
}
@@ -262,7 +262,7 @@ static const R_CallMethodDef CallEntries[] = {
262262
{"_adaR_Rcpp_ada_get_pathname", (DL_FUNC) &_adaR_Rcpp_ada_get_pathname, 1},
263263
{"_adaR_Rcpp_ada_get_search", (DL_FUNC) &_adaR_Rcpp_ada_get_search, 1},
264264
{"_adaR_Rcpp_ada_get_protocol", (DL_FUNC) &_adaR_Rcpp_ada_get_protocol, 1},
265-
{"_adaR_url_decode2", (DL_FUNC) &_adaR_url_decode2, 1},
265+
{"_adaR_Rcpp_url_decode2", (DL_FUNC) &_adaR_Rcpp_url_decode2, 1},
266266
{"_adaR_url_reverse", (DL_FUNC) &_adaR_url_reverse, 1},
267267
{NULL, NULL, 0}
268268
};

src/urldecode.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,8 @@
22

33
using namespace Rcpp;
44

5-
//' Function to percent-decode characters in URLs
6-
//'
7-
//' Similar to [utils::URLdecode]
8-
//'
9-
//' @param url a character vector
10-
//' @export
11-
//' @examples
12-
//' url_decode2("Hello%20World")
13-
// [[Rcpp::export]]
14-
CharacterVector url_decode2(const CharacterVector& url) {
15-
return sapply(url, [](const String& u) {
5+
6+
std::string decode(String u) {
167
std::string input = u;
178
std::string output;
189
size_t i = 0;
@@ -28,9 +19,21 @@ CharacterVector url_decode2(const CharacterVector& url) {
2819
i += 3;
2920
}
3021
}
31-
3222
return output;
33-
});
23+
}
24+
25+
// [[Rcpp::export]]
26+
CharacterVector Rcpp_url_decode2(CharacterVector& url) {
27+
unsigned int input_size = url.size();
28+
CharacterVector output(input_size);
29+
for (unsigned int i = 0; i < input_size; i++) {
30+
if (url[i] == NA_STRING) {
31+
output[i] = NA_STRING;
32+
} else {
33+
output[i] = decode(url[i]);
34+
}
35+
}
36+
return output;
3437
}
3538

3639
std::string str_reverse(std::string x) {
@@ -51,4 +54,4 @@ CharacterVector url_reverse(CharacterVector& urls) {
5154
}
5255

5356
return output;
54-
}
57+
}

tests/testthat/test-urldecode.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ test_that("cpp implementation is correct", {
1818
dec <- "https://www.google.de/maps/@47.6647302,9.1389738,11z?entry=ttu"
1919
expect_equal(url_decode2(enc), dec)
2020
})
21+
22+
test_that("corners", {
23+
expect_error(url_decode2(NULL), NA)
24+
expect_error(url_decode2(NA), NA)
25+
expect_error(url_decode2(c("?q=%E3%83%89%E3%82%A4%E3%83%84", NA))[2], NA)
26+
})

0 commit comments

Comments
 (0)