1 #include "vctrs.h"
2 #include "type-data-frame.h"
3 #include "utils.h"
4 #include "slice.h"
5 
vec_raw_size(SEXP x)6 static inline R_len_t vec_raw_size(SEXP x) {
7   SEXP dimensions = r_dim(x);
8 
9   if (dimensions == R_NilValue || Rf_length(dimensions) == 0) {
10     return Rf_length(x);
11   }
12 
13   if (TYPEOF(dimensions) != INTSXP) {
14     Rf_errorcall(R_NilValue, "Corrupt vector, `dim` attribute is not an integer vector.");
15   }
16 
17   R_len_t size = INTEGER(dimensions)[0];
18 
19   return size;
20 }
21 
22 
23 // [[ include("vctrs.h") ]]
vec_size(SEXP x)24 R_len_t vec_size(SEXP x) {
25   int nprot = 0;
26 
27   struct vctrs_proxy_info info = vec_proxy_info(x);
28   PROTECT_PROXY_INFO(&info, &nprot);
29 
30   SEXP data = info.proxy;
31 
32   R_len_t size;
33   switch (info.type) {
34   case vctrs_type_null:
35     size = 0;
36     break;
37   case vctrs_type_logical:
38   case vctrs_type_integer:
39   case vctrs_type_double:
40   case vctrs_type_complex:
41   case vctrs_type_character:
42   case vctrs_type_raw:
43   case vctrs_type_list:
44     size = vec_raw_size(data);
45     break;
46 
47   case vctrs_type_dataframe:
48     size = df_size(data);
49     break;
50 
51   default:
52     stop_scalar_type(x, NULL);
53 }
54 
55   UNPROTECT(nprot);
56   return size;
57 }
58 // [[ register() ]]
vctrs_size(SEXP x)59 SEXP vctrs_size(SEXP x) {
60   return Rf_ScalarInteger(vec_size(x));
61 }
62 
list_sizes(SEXP x)63 SEXP list_sizes(SEXP x) {
64   if (!vec_is_list(x)) {
65     Rf_errorcall(R_NilValue, "`x` must be a list.");
66   }
67 
68   R_len_t size = vec_size(x);
69 
70   SEXP out = PROTECT(Rf_allocVector(INTSXP, size));
71   int* p_out = INTEGER(out);
72 
73   for (R_len_t i = 0; i < size; ++i) {
74     SEXP elt = VECTOR_ELT(x, i);
75     p_out[i] = vec_size(elt);
76   }
77 
78   UNPROTECT(1);
79   return out;
80 }
81 
82 // [[ register() ]]
vctrs_list_sizes(SEXP x)83 SEXP vctrs_list_sizes(SEXP x) {
84   return list_sizes(x);
85 }
86 
df_rownames_size(SEXP x)87 R_len_t df_rownames_size(SEXP x) {
88   for (SEXP attr = ATTRIB(x); attr != R_NilValue; attr = CDR(attr)) {
89     if (TAG(attr) != R_RowNamesSymbol) {
90       continue;
91     }
92 
93     return rownames_size(CAR(attr));
94   }
95 
96   return -1;
97 }
98 
99 // For performance, avoid Rf_getAttrib() because it automatically transforms
100 // the rownames into an integer vector
df_size(SEXP x)101 R_len_t df_size(SEXP x) {
102   R_len_t n = df_rownames_size(x);
103 
104   if (n < 0) {
105     Rf_errorcall(R_NilValue, "Corrupt data frame: row.names are missing");
106   }
107 
108   return n;
109 }
110 // Supports bare lists as well
df_raw_size(SEXP x)111 R_len_t df_raw_size(SEXP x) {
112   R_len_t n = df_rownames_size(x);
113   if (n >= 0) {
114     return n;
115   }
116 
117   return df_raw_size_from_list(x);
118 }
119 
120 // [[ include("vctrs.h") ]]
df_raw_size_from_list(SEXP x)121 R_len_t df_raw_size_from_list(SEXP x) {
122   if (Rf_length(x) >= 1) {
123     return vec_size(VECTOR_ELT(x, 0));
124   } else {
125     return 0;
126   }
127 }
128 
129 // [[ register() ]]
vctrs_df_size(SEXP x)130 SEXP vctrs_df_size(SEXP x) {
131   return r_int(df_raw_size(x));
132 }
133 
134 
135 // [[ include("vctrs.h") ]]
vec_recycle(SEXP x,R_len_t size,struct vctrs_arg * x_arg)136 SEXP vec_recycle(SEXP x, R_len_t size, struct vctrs_arg* x_arg) {
137   if (x == R_NilValue) {
138     return R_NilValue;
139   }
140 
141   R_len_t n_x = vec_size(x);
142 
143   if (n_x == size) {
144     return x;
145   }
146 
147   if (n_x == 1L) {
148     SEXP i = PROTECT(compact_rep(1, size));
149     SEXP out = vec_slice_impl(x, i);
150 
151     UNPROTECT(1);
152     return out;
153   }
154 
155   stop_recycle_incompatible_size(n_x, size, x_arg);
156 }
157 
158 // [[ register() ]]
vctrs_recycle(SEXP x,SEXP size_obj,SEXP x_arg)159 SEXP vctrs_recycle(SEXP x, SEXP size_obj, SEXP x_arg) {
160   if (x == R_NilValue || size_obj == R_NilValue) {
161     return R_NilValue;
162   }
163 
164   size_obj = PROTECT(vec_cast(size_obj, vctrs_shared_empty_int, args_empty, args_empty));
165   R_len_t size = r_int_get(size_obj, 0);
166   UNPROTECT(1);
167 
168   struct vctrs_arg x_arg_ = vec_as_arg(x_arg);
169 
170   return vec_recycle(x, size, &x_arg_);
171 }
172 
173 // [[ include("vctrs.h") ]]
vec_recycle_fallback(SEXP x,R_len_t size,struct vctrs_arg * x_arg)174 SEXP vec_recycle_fallback(SEXP x, R_len_t size, struct vctrs_arg* x_arg) {
175   if (x == R_NilValue) {
176     return R_NilValue;
177   }
178 
179   R_len_t x_size = vec_size(x);
180 
181   if (x_size == size) {
182     return x;
183   }
184 
185   if (x_size == 1) {
186     SEXP subscript = PROTECT(Rf_allocVector(INTSXP, size));
187     r_int_fill(subscript, 1, size);
188 
189     SEXP out = vec_slice_fallback(x, subscript);
190 
191     UNPROTECT(1);
192     return out;
193   }
194 
195   stop_recycle_incompatible_size(x_size, size, x_arg);
196 }
197 
198 
199 // [[ include("utils.h") ]]
size_validate(SEXP size,const char * arg)200 R_len_t size_validate(SEXP size, const char* arg) {
201   size = vec_cast(size, vctrs_shared_empty_int, args_empty, args_empty);
202 
203   if (Rf_length(size) != 1) {
204     Rf_errorcall(R_NilValue, "`%s` must be a single integer.", arg);
205   }
206 
207   int out = r_int_get(size, 0);
208 
209   if (out == NA_INTEGER) {
210     Rf_errorcall(R_NilValue, "`%s` can't be missing.", arg);
211   }
212 
213   return out;
214 }
215