Skip to content

Commit bc007af

Browse files
committed
Merge branch 'ListOf'
2 parents 55bd98a + 9659f16 commit bc007af

File tree

7 files changed

+139
-65
lines changed

7 files changed

+139
-65
lines changed

inst/include/Rcpp/Vector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ namespace Rcpp{
6565
#include <Rcpp/vector/LazyVector.h>
6666
#include <Rcpp/vector/swap.h>
6767

68+
#include <Rcpp/vector/ChildVector.h>
6869
#include <Rcpp/vector/ListOf.h>
6970

7071
#endif

inst/include/Rcpp/traits/traits.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ struct int2type { enum { value = I }; };
4949
#include <Rcpp/traits/has_na.h>
5050
#include <Rcpp/traits/storage_type.h>
5151
#include <Rcpp/traits/r_sexptype_traits.h>
52-
#include <Rcpp/traits/storage_type.h>
5352
#include <Rcpp/traits/r_type_traits.h>
5453
#include <Rcpp/traits/un_pointer.h>
5554
#include <Rcpp/traits/is_pointer.h>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// ChildVector.h: Rcpp R/C++ interface class library -- vector children of lists
2+
//
3+
// Copyright (C) 2014 Dirk Eddelbuettel, Romain Francois and Kevin Ushey
4+
//
5+
// This file is part of Rcpp.
6+
//
7+
// Rcpp is free software: you can redistribute it and/or modify it
8+
// under the terms of the GNU General Public License as published by
9+
// the Free Software Foundation, either version 2 of the License, or
10+
// (at your option) any later version.
11+
//
12+
// Rcpp is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
// GNU General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License
18+
// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
19+
20+
#ifndef Rcpp__Vector__ChildVector__h
21+
#define Rcpp__Vector__ChildVector__h
22+
23+
namespace Rcpp {
24+
25+
template <typename T>
26+
class ChildVector : public T {
27+
28+
public:
29+
30+
ChildVector(SEXP data_, SEXP parent_, int i_):
31+
T(data_),
32+
parent(parent_),
33+
i(i_) {}
34+
35+
ChildVector(const ChildVector& other):
36+
T(other),
37+
parent(other.parent),
38+
i(other.i) {}
39+
40+
inline ChildVector& operator=(const ChildVector& other) {
41+
if (this != &other) {
42+
this->set__(other);
43+
if (parent != NULL && !Rf_isNull(parent)) {
44+
SET_VECTOR_ELT(parent, i, other);
45+
}
46+
}
47+
return *this;
48+
}
49+
50+
inline ChildVector& operator=(const T& other) {
51+
this->set__(other);
52+
if (parent != NULL && !Rf_isNull(parent)) {
53+
SET_VECTOR_ELT(parent, i, other);
54+
}
55+
return *this;
56+
}
57+
58+
template <typename U>
59+
inline ChildVector& operator=(const U& other) {
60+
Shield<SEXP> wrapped( wrap(other) );
61+
T vec = as<T>(wrapped);
62+
this->set__(vec);
63+
if (parent != NULL && !Rf_isNull(parent)) {
64+
SET_VECTOR_ELT(parent, i, vec);
65+
}
66+
return *this;
67+
}
68+
69+
private:
70+
SEXP parent;
71+
int i;
72+
};
73+
74+
} // namespace Rcpp
75+
76+
#endif
77+

inst/include/Rcpp/vector/ListOf.h

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ class ListOf {
5252

5353
// subsetting operators
5454

55-
T operator[](int i) {
56-
return list[i];
55+
ChildVector<T> operator[](int i) {
56+
return ChildVector<T>(list[i], list, i);
5757
}
5858

59-
const T operator[](int i) const {
60-
return list[i];
59+
const ChildVector<T> operator[](int i) const {
60+
return ChildVector<T>(list[i], list, i);
6161
}
6262

63-
T operator[](const std::string& str) {
64-
return list[str];
63+
ChildVector<T> operator[](const std::string& str) {
64+
return ChildVector<T>(list[str], list, list.findName(str));
6565
}
6666

67-
const T operator[](const std::string& str) const {
68-
return list[str];
67+
const ChildVector<T> operator[](const std::string& str) const {
68+
return ChildVector<T>(list[str], list, list.findName(str));
6969
}
7070

7171
// iteration operators pass down to list
@@ -90,45 +90,16 @@ class ListOf {
9090
return list.size() ;
9191
}
9292

93-
class ListOfProxy {
94-
95-
public:
96-
ListOfProxy(List& list_): list(list_) {};
97-
98-
List::Proxy operator[](int i) {
99-
return List::Proxy(list, i);
100-
}
101-
102-
List::Proxy operator[](const char* str) {
103-
std::vector<std::string> names = as< std::vector<std::string> >(list.attr("names"));
104-
for (int i=0; i < list.size(); ++i) {
105-
if (names[i] == str) {
106-
return List::Proxy(list, i);
107-
}
108-
}
109-
std::stringstream ss;
110-
ss << "No name '" << str << "' in the names of the list supplied";
111-
stop(ss.str());
112-
return List::Proxy(list, -1);
113-
}
114-
115-
private:
116-
ListOfProxy() {};
117-
118-
List& list;
119-
};
120-
121-
friend class ListOfProxy;
122-
123-
// lhs access
124-
friend ListOfProxy lhs(ListOf& x) {
125-
return ListOfProxy(x.list);
93+
inline List get() const {
94+
return list;
12695
}
12796

12897
// conversion operators
12998
operator SEXP() const { return wrap(list); }
13099
operator List() const { return list; }
131100

101+
private:
102+
132103
List list;
133104

134105
}; // ListOf<T>
@@ -147,12 +118,12 @@ class Sapply;
147118

148119
template <typename T, typename Function>
149120
List lapply(const ListOf<T>& t, Function fun) {
150-
return lapply(t.list, fun);
121+
return lapply(t.get(), fun);
151122
}
152123

153124
template <typename T, typename Function>
154125
T sapply(const ListOf<T>& t, Function fun) {
155-
return sapply(t.list, fun);
126+
return sapply(t.get(), fun);
156127
}
157128

158129
} // Rcpp

inst/include/Rcpp/vector/Vector.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,21 @@ class Vector :
511511
return false ;
512512
}
513513

514+
int findName(const std::string& name) const {
515+
SEXP names = RCPP_GET_NAMES(Storage::get__());
516+
if (Rf_isNull(names)) stop("'names' attribute is null");
517+
int n = Rf_length(names);
518+
for (int i=0; i < n; ++i) {
519+
if (strcmp(name.c_str(), CHAR(STRING_ELT(names, i))) == 0) {
520+
return i;
521+
}
522+
}
523+
std::stringstream ss;
524+
ss << "no name '" << name << "' found";
525+
stop(ss.str());
526+
return -1;
527+
}
528+
514529

515530
protected:
516531
inline int* dims() const {

inst/unitTests/cpp/ListOf.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ NumericVector test_sapply_sum(NVList x) {
2525

2626
// [[Rcpp::export]]
2727
NVList test_assign(NVList x, NumericVector y, CharacterVector z) {
28-
lhs(x)[1] = y;
29-
lhs(x)[2] = 1;
28+
x[1] = y;
29+
x[2] = 1;
3030
return x;
3131
}
3232

3333
// [[Rcpp::export]]
3434
NVList test_assign_names(NVList x) {
35-
lhs(x)["a"] = x["b"];
35+
x["a"] = x["b"];
3636
return x;
3737
}
3838

@@ -55,7 +55,7 @@ NumericVector test_mult(NVList x) {
5555
typedef ListOf<CharacterVector> CVList;
5656
// [[Rcpp::export]]
5757
CVList test_char(CVList x) {
58-
lhs(x)[0] = "apple";
58+
x[0] = "apple";
5959
return x;
6060
}
6161

@@ -82,3 +82,9 @@ NVList test_binary_ops(NVList x) {
8282
x[0] <= x[1]
8383
);
8484
}
85+
86+
// [[Rcpp::export]]
87+
int test_sub_calls(NVList x) {
88+
int sz = x[0].size() + x[1].size() + x[2].size();
89+
return sz;
90+
}

inst/unitTests/runit.ListOf.R

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,48 +18,53 @@
1818
.runThisTest <- Sys.getenv("RunAllRcppTests") == "yes"
1919

2020
if (.runThisTest) {
21-
21+
2222
.setUp <- Rcpp:::unitTestSetup("ListOf.cpp")
23-
23+
2424
x <- list( c(1, 5), c(2, 6), c(3, 7) )
25-
26-
test.identity <- function() {
25+
26+
test.ListOf.identity <- function() {
2727
checkIdentical(
2828
test_identity(setNames(x, c('a', 'b', 'c'))),
2929
setNames(x, c('a', 'b', 'c'))
3030
)
3131
}
32-
33-
test.lapply.sum <- function() {
32+
33+
test.ListOf.lapply.sum <- function() {
3434
x <- list( c(1, 5), c(2, 6), c(3, 7) )
3535
checkIdentical( test_lapply_sum(x), lapply(x, sum) )
3636
}
37-
38-
test.sapply.sum <- function() {
37+
38+
test.ListOf.sapply.sum <- function() {
3939
x <- list( c(1, 5), c(2, 6), c(3, 7) )
4040
checkIdentical( test_sapply_sum(x), sapply(x, sum) )
4141
}
42-
43-
test.assign <- function() {
42+
43+
test.ListOf.assign <- function() {
44+
x <- list( c(1, 5), c(2, 6), c(3, 7) )
4445
test_assign(x, 100, "apple")
4546
checkIdentical( x[[2]], 100 )
4647
}
47-
48-
test.assign.names <- function() {
48+
49+
test.ListOf.assign.names <- function() {
4950
x <- setNames(list(1, 2, 3), c('a', 'b', 'c'))
5051
test_assign_names(x)
5152
checkIdentical( x[["a"]], x[["b"]] )
5253
}
53-
54-
test.arith <- function() {
54+
55+
test.ListOf.arith <- function() {
5556
checkIdentical(test_add(list(1, 2, 3)), 6)
5657
checkIdentical(test_add_subtract(list(1, 2, 3)), 0)
5758
checkIdentical(test_mult( list(1, 2, 3) ), 6)
5859
checkIdentical(test_char( list("banana") ), list("apple"))
5960
}
60-
61-
test.assign.names <- function() {
61+
62+
test.ListOf.assign.names <- function() {
6263
checkException(test_assign_names(list(alpha=1, beta=2, gamma=3)))
6364
}
64-
65+
66+
test.ListOf.sub.calls <- function() {
67+
checkEquals(test_sub_calls( list(1, 2, 3) ), 3)
68+
}
69+
6570
}

0 commit comments

Comments
 (0)