1use ::rdll::*;
2use ::storage::*;
3use ::traits::*;
4use ::rtype::*;
5use ::protect::stackp::*;
6use error::*;
7use error::REKind::NotCompatible;
8use std::ops::Range;
9use std::ffi::*;
10use util::c_str;
11
12
13pub type CharVec = CharVecM<Preserve>;
14
15impl<T: SEXPbucket> CharVecM<T> {
16 pub fn new(x: SEXP) -> RResult<CharVecM<T>> {
17 if RTYPEOF(x) != STRSXP {
18 return rerror(NotCompatible("expecting a string vector".into()));
19 }
20 Ok(CharVecM { data: T::new(x) })
21 }
22 pub fn alloc(x: usize) -> CharVecM<T> {
23 CharVecM { data: T::new(unsafe { Rf_allocVector(STRSXP, x as R_xlen_t) }) }
24 }
25 pub fn alloc_matrix(x: usize, y: usize) -> CharVecM<T> {
26 CharVecM {
27 data: T::new(unsafe {
28 Rf_allocMatrix(STRSXP,
29 x as ::std::os::raw::c_int,
30 y as ::std::os::raw::c_int)
31 }),
32 }
33 }
34 pub unsafe fn uat(&self, ind: usize) -> Result<String, IntoStringError> {
35 CStr::from_ptr(R_CHAR(STRING_ELT(self.s(), ind as R_xlen_t))).to_owned().into_string()
36 }
37 pub unsafe fn uset(&mut self, ind: usize, value: &str) {
38 SET_STRING_ELT(self.s(),
39 ind as R_xlen_t,
40 Shield::new(Rf_mkChar(c_str(value).as_ptr())).s())
41 }
42 pub fn at(&self, ind: usize) -> RResult<String> {
43 unsafe {
44 if Rf_xlength(self.s()) <= ind as R_xlen_t {
45 return rraise("index out of bound");
46 }
47 Ok(try!(CStr::from_ptr(R_CHAR(STRING_ELT(self.s(), ind as R_xlen_t)))
48 .to_owned()
49 .into_string()))
50 }
51 }
52 pub fn set(&mut self, ind: usize, value: &str) -> RResult<()> {
53 unsafe {
54 if Rf_xlength(self.s()) <= ind as R_xlen_t {
55 return rraise("index out of bound");
56 }
57
58 SET_STRING_ELT(self.s(),
59 ind as R_xlen_t,
60 Shield::new(Rf_mkChar(c_str(value).as_ptr())).s());
61 Ok(())
62 }
63 }
64 pub unsafe fn atc(&self, ind: usize) -> RResult<CString> {
65 if Rf_xlength(self.s()) <= ind as R_xlen_t {
66 return rraise("index out of bound");
67 }
68 Ok(CStr::from_ptr(R_CHAR(STRING_ELT(self.s(), ind as R_xlen_t))).to_owned())
69 }
70 pub unsafe fn uatc(&self, ind: usize) -> CString {
71 CStr::from_ptr(R_CHAR(STRING_ELT(self.s(), ind as R_xlen_t))).to_owned()
72 }
73 pub unsafe fn usetc<D:ToSEXP>(&mut self, ind: usize, value: D) {
74 SET_STRING_ELT(self.s(),
75 ind as R_xlen_t,
76 value.s())
77 }
78 pub fn setc<D:ToSEXP>(&mut self, ind: usize, value: D) -> RResult<()> {
79 unsafe {
80 if Rf_xlength(self.s()) <= ind as R_xlen_t {
81 return rraise("index out of bound");
82 }
83 if RTYPEOF(self.s()) == CHARSXP || self.s() == R_NaString{
84 return rraise("not a CHARSXP");
85 }
86 SET_STRING_ELT(self.s(),
87 ind as R_xlen_t,
88 value.s());
89 Ok(())
90 }
91 }
92 pub fn range(&self, ind: Range<usize>) -> Option<Vec<CString>> {
93 unsafe {
94 if Rf_xlength(self.s()) <= ind.end as R_xlen_t {
95 return None;
96 }
97 let mut vecs = Vec::with_capacity((ind.end - ind.start) as usize);
98 for ii in ind {
99 vecs.push(CStr::from_ptr(R_CHAR(STRING_ELT(self.s(), ii as R_xlen_t))).to_owned());
100 }
101 Some(vecs)
102 }
103 }
104 pub fn is_duplicated(&self, from_last: bool) -> R_xlen_t {
105 let last = if from_last {
106 Rboolean::TRUE
107 } else {
108 Rboolean::FALSE
109 };
110 unsafe { Rf_any_duplicated(self.s(), last) }
111 }
112}
113
114
115#[cfg_attr(feature = "dev",allow(explicit_counter_loop))]
116impl<T: SEXPbucket, E: Into<CString> + Clone> From<Vec<E>> for CharVecM<T> {
117 fn from(x: Vec<E>) -> CharVecM<T> {
118 let size_x = x.len();
119 unsafe {
120 let rvec = Shield::new(Rf_allocVector(STRSXP, size_x as R_xlen_t));
121 let mut xs = 0;
122 for ii in x {
123 SET_STRING_ELT(rvec.s(), xs, Shield::new(Rf_mkChar(ii.into().as_ptr())).s());
124 xs += 1;
125 }
126 CharVecM { data: T::new(rvec.s()) }
127 }
128 }
129}
130
131impl<T: SEXPbucket> From<CharVecM<T>> for Vec<CString> {
132 fn from(x: CharVecM<T>) -> Vec<CString> {
133 unsafe {
134 let lens = Rf_xlength(x.s());
135 let mut vecs = Vec::with_capacity(lens as usize);
136 for ii in 0..lens {
137 vecs.push(CString::urnew(STRING_ELT(x.s(), ii)));
138 }
139 vecs
140 }
141 }
142}
143
144impl<T: SEXPbucket> URNew for CharVecM<T> {
145 unsafe fn urnew(x: SEXP) -> Self {
146 CharVecM { data: T::new(x) }
147 }
148}
149
150impl<T: SEXPbucket> RNew for CharVecM<T> {
151 fn rnew(x: SEXP) -> RResult<Self> {
152 Self::new(x)
153 }
154}
155
156impl<T: SEXPbucket> RSize for CharVecM<T> {
157 fn rsize(&self) -> R_xlen_t {
158 unsafe { Rf_xlength(self.s()) }
159 }
160}
161
162gen_traits_sexp!(CharVecM);
163
164
165impl<T: SEXPbucket> RName for CharVecM<T> {}
166impl<T: SEXPbucket> RDim for CharVecM<T> {
167 type Output = CString;
168}
169
170#[derive(Debug)]
171pub struct CharVecIter<T: SEXPbucket> {
172 size: R_xlen_t,
173 next: R_xlen_t,
174 ty: CharVecM<T>,
175}
176
177impl<T: SEXPbucket> Iterator for CharVecIter<T> {
178 type Item = CString;
180
181 fn next(&mut self) -> Option<CString> {
183 if self.next < self.size {
186 self.next += 1;
187 unsafe { Some(CString::urnew(STRING_ELT(self.ty.s(), self.next - 1))) }
188 } else {
189 None
190 }
191
192 }
193}
194
195impl<T: SEXPbucket> IntoIterator for CharVecM<T> {
196 type Item = CString;
197 type IntoIter = CharVecIter<T>;
198
199 fn into_iter(self) -> Self::IntoIter {
200 CharVecIter {
201 size: self.rsize(),
202 next: 0,
203 ty: self,
204 }
205 }
206}
207
208impl<T: SEXPbucket> ExactSizeIterator for CharVecIter<T> {
209 fn len(&self) -> usize {
211 self.size as usize
212 }
213}
214
215
216#[macro_export]
219macro_rules! charvec {
220 ($($tts:expr),*) => {
221 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
223
224 let mut res = CharVec::alloc(size as usize);
226 unsafe{
227 let mut x = 0;
228 $(
229 x += 1;
231 let xi = try!(::std::ffi::CString::new($tts));
232 let tmp : SEXP = $crate::protect::stackp::Shield::new(RCharM::<NoProtect>::from(xi).s()).s();
233 res.usetc(x-1,tmp);
234
235 )*
236 }
237 res
238 }
239 };
240
241 ($($id:ident ~ $tts:expr),*) => {
242 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
244
245 let mut res = CharVec::alloc(size as usize);
247 let mut name = CharVec::alloc(size as usize);
248 unsafe{
249 let mut x = 0;
250 $(
251 x += 1;
253 let xi = try!(::std::ffi::CString::new($tts));
254 let tmp : SEXP = $crate::protect::stackp::Shield::new(RCharM::<NoProtect>::from(xi).s()).s();
255 res.usetc(x-1,tmp);
256 name.uset(x-1, stringify!($id));
257 )*
258 }
259 unsafe{Rf_setAttrib(res.s(), R_NamesSymbol,name.s());}
260 res
261 }
262 }
263}
264
265#[macro_export]
268macro_rules! ucharvec {
269 ($($tts:expr),*) => {
270 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
272
273 let mut res = CharVec::alloc(size as usize);
275 let mut x = 0;
276 $(
277 x += 1;
279 res.uset(x-1, $tts);
280
281 )*
282 res
283 }
284 };
285 ($($id:ident ~ $tts:expr),*) => {
286 {let size = <[()]>::len(&[$(replace_expr!($tts, ())),*]);
288
289 let mut res = CharVec::alloc(size as usize);
291 let mut name = CharVec::alloc(size as usize);
292
293 let mut x = 0;
294 $(
295 x += 1;
297 res.uset(x-1, $tts);
298 name.uset(x-1, stringify!($id));
299 )*
300
301 Rf_setAttrib(res.s(), R_NamesSymbol,name.s());
302 res
303 }
304 }
305}