@@ -61,36 +61,18 @@ namespace Rcpp{
6161 }
6262
6363 // By definition, the number of rows in a data.frame is contained
64- // in its row.names attribute. If it has row names of the form 1:n,
65- // they will be stored as {NA_INTEGER, -<nrow>}. Unfortunately,
66- // getAttrib(df, R_RowNamesSymbol) will force an expansion of that
67- // compact form thereby allocating a huge vector when we just want
68- // the row.names. Hence this workaround.
69- inline int nrow () const {
70- #if R_VERSION >= R_Version(4, 6, 0)
71- Shield<SEXP> v = R_mapAttrib (Parent::get__ (), get_row_count, R_NilValue);
72- if (v != NULL && TYPEOF (v) == INTSXP) {
73- return INTEGER (v)[0 ];
74- } else {
75- // TODO: error?
76- return NA_INTEGER;
77- }
78- #else
79- SEXP rn = R_NilValue ;
80- SEXP att = ATTRIB ( Parent::get__ () ) ;
81- while ( att != R_NilValue ){
82- if ( TAG (att) == R_RowNamesSymbol ) {
83- rn = CAR (att) ;
84- break ;
85- }
86- att = CDR (att) ;
87- }
88- if (Rf_isNull (rn))
89- return 0 ;
90- if (TYPEOF (rn) == INTSXP && LENGTH (rn) == 2 && INTEGER (rn)[0 ] == NA_INTEGER)
91- return std::abs (INTEGER (rn)[1 ]);
92- return LENGTH (rn);
93- #endif
64+ // in its row.names attribute. Since R 3.5.0 this is returned as a
65+ // compact sequence from which we can just take the length
66+ // Shield<SEXP> rn = Rf_getAttrib(Parent::get__(), R_RowNamesSymbol);
67+ // return Rf_xlength(rn);
68+ // But as this makes an allocation an even simpler check on length as
69+ // discussed in #1430 is also possible and preferable. We also switch
70+ // to returning R_xlen_t which as upcast from int is safe
71+ inline R_xlen_t nrow () const {
72+ SEXP x = Parent::get__ ();
73+ // We can simplify: zero row DFs have no names, else length of all vector same
74+ // by design constraint so can use vector length for desired row count
75+ return (XLENGTH (x) == 0 ) ? 0 : XLENGTH (VECTOR_ELT (x, 0 ));
9476 }
9577
9678 template <typename T>
@@ -118,8 +100,8 @@ namespace Rcpp{
118100 }
119101
120102 // Offer multiple variants to accomodate both old interface here and signatures in other classes
121- inline int nrows () const { return DataFrame_Impl::nrow (); }
122- inline int rows () const { return DataFrame_Impl::nrow (); }
103+ inline R_xlen_t nrows () const { return DataFrame_Impl::nrow (); }
104+ inline R_xlen_t rows () const { return DataFrame_Impl::nrow (); }
123105
124106 inline R_xlen_t ncol () const { return DataFrame_Impl::length (); }
125107 inline R_xlen_t cols () const { return DataFrame_Impl::length (); }
0 commit comments