1use ::rdll::*;
2use ::storage::*;
3use ::traits::*;
4use ::rtype::*;
5use ::protect::stackp::*;
6use error::*;
7use error::REKind::NotCompatible;
8use std::ops::Range;
9use util::*;
10use super::CharVec;
11use vector::IntVec;
12
13pub type RList = RListM<Preserve>;
14
15
16impl<T: SEXPbucket> RListM<T> {
17 pub fn new(x: SEXP) -> RResult<RListM<T>> {
18
19 if RTYPEOF(x) != VECSXP {
20 return rerror(NotCompatible("expecting a list".into()));
21 }
22
23 Ok(RListM { data: T::new(x) })
24 }
25 pub fn alloc(x: usize) -> RListM<T> {
26 RListM { data: T::new(unsafe { Rf_allocVector(VECSXP, x as R_xlen_t) }) }
27 }
28 pub fn alloc_matrix(x: usize, y: usize) -> RListM<T> {
29 RListM {
30 data: T::new(unsafe {
31 Rf_allocMatrix(VECSXP,
32 x as ::std::os::raw::c_int,
33 y as ::std::os::raw::c_int)
34 }),
35 }
36 }
37 pub fn at(&self, ind: usize) -> Option<SEXP> {
38 unsafe {
39 if Rf_xlength(self.s()) <= ind as R_xlen_t {
40 return None;
41 }
42 Some(VECTOR_ELT(self.s(), ind as R_xlen_t))
43 }
44 }
45 pub unsafe fn uat(&self, ind: usize) -> SEXP {
46 VECTOR_ELT(self.s(), ind as R_xlen_t)
47 }
48 pub unsafe fn uset<TT: ToSEXP>(&mut self, ind: usize, value: TT) {
49 SET_VECTOR_ELT(self.s(), ind as R_xlen_t, value.s());
50 }
51 pub fn set<TT: ToSEXP>(&mut self, ind: usize, value: TT) -> RResult<()> {
52 unsafe {
53 if Rf_xlength(self.s()) <= ind as R_xlen_t {
54 return rraise("index out of bound");
55 }
56 SET_VECTOR_ELT(self.s(), ind as R_xlen_t, value.s());
57 Ok(())
58 }
59 }
60 pub fn range(&self, ind: Range<usize>) -> Option<Vec<SEXP>> {
61 unsafe {
62 if Rf_xlength(self.s()) <= ind.end as R_xlen_t {
63 return None;
64 }
65 let mut vecs = Vec::with_capacity((ind.end - ind.start) as usize);
66 for ii in ind {
67 vecs.push(VECTOR_ELT(self.s(), ii as R_xlen_t));
68 }
69 Some(vecs)
70 }
71 }
72 pub fn is_duplicated(&self, from_last: bool) -> R_xlen_t {
73 let last = if from_last {
74 Rboolean::TRUE
75 } else {
76 Rboolean::FALSE
77 };
78 unsafe { Rf_any_duplicated(self.s(), last) }
79 }
80 pub fn as_data_frame(&mut self)->RResult<()>{
81 if self.rsize() == 0{
82 unsafe{
83 Rf_setAttrib(self.s(), R_NamesSymbol, Rf_allocVector(STRSXP, 0));
84 Rf_setAttrib(self.s(), R_RowNamesSymbol, Rf_allocVector(INTSXP, 0));
85 Rf_setAttrib(self.s(), R_ClassSymbol, Rf_mkString(c_str("data.frame").as_ptr()));
86 }
87 return Ok(());
88 }
89 unsafe{
90 if self.namesexp() == R_NilValue{
91 let mut colname = CharVec::alloc(self.rsize() as usize);
92 for ii in 0..(self.rsize() as usize){
93 colname.uset(ii, &format!("col{}", ii+1));
94 }
95 self.uset_name(&colname);
96 }
97 let colsize : usize = Rf_xlength(self.uat(0)) as usize ;
98 for ii in 0..(self.rsize() as usize){
99 if colsize != Rf_xlength(self.uat(ii)) as usize {
100 return rraise("not all colunm are the same length.");
101 }
102 }
103 let mut rowname = IntVec::alloc(colsize as usize);
104 for ii in 0..(self.rsize() as usize){
105 rowname.uset(ii, (ii as ::std::os::raw::c_int)+1);
106 }
107 Rf_setAttrib(self.s(), R_RowNamesSymbol, rowname.s());
108 Rf_setAttrib(self.s(), R_ClassSymbol, Rf_mkString(c_str("data.frame").as_ptr()));
109 Ok(())
110 }
111 }
112}
113
114#[cfg_attr(feature = "dev",allow(explicit_counter_loop))]
115impl<T: SEXPbucket, E: UIntoR + Clone> From<Vec<E>> for RListM<T> {
116 fn from(x: Vec<E>) -> RListM<T> {
117 let size_x = x.len();
118 unsafe {
119 let rvec = Shield::new(Rf_allocVector(VECSXP, size_x as R_xlen_t));
120 let mut xs = 0;
121 for ii in x {
122 SET_VECTOR_ELT(rvec.s(), xs, Shield::new(ii.uintor()).s());
123 xs += 1;
124 }
125 RListM { data: T::new(rvec.s()) }
126 }
127 }
128}
129
130impl<T: SEXPbucket> URNew for RListM<T> {
145 unsafe fn urnew(x: SEXP) -> Self {
146 RListM { data: T::new(x) }
147 }
148}
149
150impl<T: SEXPbucket> RNew for RListM<T> {
151 fn rnew(x: SEXP) -> RResult<Self> {
152 Self::new(x)
153 }
154}
155
156impl<T: SEXPbucket> RSize for RListM<T> {
157 fn rsize(&self) -> R_xlen_t {
158 unsafe { Rf_xlength(self.s()) }
159 }
160}
161
162gen_traits_sexp!(RListM);
163
164
165impl<T: SEXPbucket> RName for RListM<T> {}
166impl<T: SEXPbucket> RDim for RListM<T> {
167 type Output = SEXP;
168}
169
170#[derive(Debug)]
171pub struct RListIter<T: SEXPbucket> {
172 size: R_xlen_t,
173 next: R_xlen_t,
174 ty: RListM<T>,
175}
176
177impl<T: SEXPbucket> Iterator for RListIter<T> {
178 type Item = SEXP;
180
181 fn next(&mut self) -> Option<SEXP> {
183 if self.next < self.size {
186 self.next += 1;
187 unsafe { Some(VECTOR_ELT(self.ty.s(), self.next - 1)) }
188 } else {
189 None
190 }
191
192 }
193}
194
195impl<T: SEXPbucket> IntoIterator for RListM<T> {
196 type Item = SEXP;
197 type IntoIter = RListIter<T>;
198
199 fn into_iter(self) -> Self::IntoIter {
200 RListIter {
201 size: self.rsize(),
202 next: 0,
203 ty: self,
204 }
205 }
206}
207
208impl<T: SEXPbucket> ExactSizeIterator for RListIter<T> {
209 fn len(&self) -> usize {
211 self.size as usize
212 }
213}
214
215#[macro_export]
218macro_rules! replace_expr {
219 ($_t:expr, $sub:expr) => {$sub};
220}
221
222#[macro_export]
225macro_rules! rlist {
226 ($($tts:expr),*) => {
227 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
229
230 let mut res = RList::alloc(size as usize);
232 unsafe{
233 let mut x = 0;
234 $(
235 x += 1;
237 res.uset(x-1, $tts.intor()?);
238
239 )*
240 }
241 res
242 }
243 };
244
245 ($($id:ident ~ $tts:expr),*) => {
246 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
248
249 let mut res = RList::alloc(size as usize);
251 let mut name = CharVec::alloc(size as usize);
252 unsafe{
253 let mut x = 0;
254 $(
255 x += 1;
257 res.uset(x-1, $tts.intor()?);
258 name.uset(x-1, stringify!($id));
259 )*
260 }
261 unsafe{Rf_setAttrib(res.s(), R_NamesSymbol,name.s());}
262 res
263 }
264 }
265}
266
267#[macro_export]
271macro_rules! urlist {
272 ($($tts:expr),*) => {
273 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
275
276 let mut res = RList::alloc(size as usize);
278 let mut x = 0;
279 $(
280 x += 1;
282 res.uset(x-1, $tts.uintor());
283
284 )*
285 res
286 }
287 };
288 ($($id:ident ~ $tts:expr),*) => {
289 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
291
292 let mut res = RList::alloc(size as usize);
294 let mut name = CharVec::alloc(size as usize);
295
296 let mut x = 0;
297 $(
298 x += 1;
300 res.uset(x-1, $tts.uintor());
301 name.uset(x-1, stringify!($id));
302 )*
303
304 Rf_setAttrib(res.s(), R_NamesSymbol,name.s());
305 res
306 }
307 }
308}