Rcpp Version 1.0.14
Loading...
Searching...
No Matches
trimws.h
Go to the documentation of this file.
1// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2//
3// trimws.h: Rcpp R/C++ interface class library -- trimws
4//
5// Copyright (C) 2017 Nathan Russell
6//
7// This file is part of Rcpp.
8//
9// Rcpp is free software: you can redistribute it and/or modify it
10// under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 2 of the License, or
12// (at your option) any later version.
13//
14// Rcpp is distributed in the hope that it will be useful, but
15// WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21
22#ifndef Rcpp__sugar__trimws_h
23#define Rcpp__sugar__trimws_h
24
25#include <string>
26#include <cstring>
27
28namespace Rcpp {
29namespace sugar {
30namespace detail {
31
32
33/* NB: std::isspace is not used because it also counts
34 '\f' and '\v' as whitespace, whereas base::trimws only
35 checks for ' ', '\t', '\r', and '\n' */
36inline bool isws(const char c) {
37 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
38}
39
40inline const char* trim_left(const char* str) {
41 if (!str) {
42 return "";
43 }
44
45 while (isws(*str)) {
46 ++str;
47 }
48
49 return str;
50}
51
52inline const char* trim_right(const char* str, R_len_t sz, std::string* buff) {
53 if (!str) {
54 return "";
55 }
56
57 buff->clear();
58 const char* ptr = str + sz - 1;
59
60 for (; ptr > str && isws(*ptr); --sz, --ptr);
61
62 buff->append(str, sz - isws(*ptr));
63 return buff->c_str();
64}
65
66inline const char* trim_both(const char* str, R_len_t sz, std::string* buff) {
67 if (!str) {
68 return "";
69 }
70
71 buff->clear();
72
73 while (isws(*str)) {
74 ++str; --sz;
75 }
76
77 const char* ptr = str + sz - 1;
78
79 for (; ptr > str && isws(*ptr); --sz, --ptr);
80
81 buff->append(str, sz);
82 return buff->c_str();
83}
84
85
86} // detail
87} // sugar
88
89
90inline Vector<STRSXP> trimws(const Vector<STRSXP>& x, const char* which = "both") {
91 R_xlen_t i = 0, sz = x.size();
93 std::string buffer;
94
95 if (*which == 'b') {
96 for (; i < sz; i++) {
97 if (traits::is_na<STRSXP>(x[i])) {
98 res[i] = x[i];
99 } else {
101 x[i],
102 LENGTH(x[i]),
103 &buffer
104 );
105 }
106 }
107 } else if (*which == 'l') {
108 for (; i < sz; i++) {
109 if (traits::is_na<STRSXP>(x[i])) {
110 res[i] = x[i];
111 } else {
112 res[i] = sugar::detail::trim_left(x[i]);
113 }
114 }
115 } else if (*which == 'r') {
116 for (; i < sz; i++) {
117 if (traits::is_na<STRSXP>(x[i])) {
118 res[i] = x[i];
119 } else {
121 x[i],
122 LENGTH(x[i]),
123 &buffer
124 );
125 }
126 }
127 } else {
128 stop("Invalid `which` argument '%s'!", which);
129 return Vector<STRSXP>::create("Unreachable");
130 }
131
132 return res;
133}
134
135inline Matrix<STRSXP> trimws(const Matrix<STRSXP>& x, const char* which = "both") {
136 R_xlen_t i = 0, sz = x.size();
137 int nr = x.nrow(), nc = x.ncol();
138 Matrix<STRSXP> res = no_init(nr, nc);
139 std::string buffer;
140
141 if (*which == 'b') {
142 for (; i < sz; i++) {
143 if (traits::is_na<STRSXP>(x[i])) {
144 res[i] = x[i];
145 } else {
147 x[i],
148 LENGTH(x[i]),
149 &buffer
150 );
151 }
152 }
153 } else if (*which == 'l') {
154 for (; i < sz; i++) {
155 if (traits::is_na<STRSXP>(x[i])) {
156 res[i] = x[i];
157 } else {
158 res[i] = sugar::detail::trim_left(x[i]);
159 }
160 }
161 } else if (*which == 'r') {
162 for (; i < sz; i++) {
163 if (traits::is_na<STRSXP>(x[i])) {
164 res[i] = x[i];
165 } else {
167 x[i],
168 LENGTH(x[i]),
169 &buffer
170 );
171 }
172 }
173 } else {
174 stop("Invalid `which` argument '%s'!", which);
175 return Matrix<STRSXP>();
176 }
177
178 return res;
179}
180
181inline String trimws(const String& str, const char* which = "both") {
182 std::string buffer;
183
184 if (*which == 'b') {
185 if (traits::is_na<STRSXP>(str.get_sexp())) {
186 return String(str.get_sexp());
187 }
189 str.get_cstring(),
190 LENGTH(str.get_sexp()),
191 &buffer
192 );
193 }
194
195 if (*which == 'l') {
196 if (traits::is_na<STRSXP>(str.get_sexp())) {
197 return String(str.get_sexp());
198 }
199 return sugar::detail::trim_left(str.get_cstring());
200 }
201
202 if (*which == 'r') {
203 if (traits::is_na<STRSXP>(str.get_sexp())) {
204 return String(str.get_sexp());
205 }
207 str.get_cstring(),
208 LENGTH(str.get_sexp()),
209 &buffer
210 );
211 }
212
213 stop("Invalid `which` argument '%s'!", which);
214 return String("Unreachable");
215}
216
217
218} // Rcpp
219
220#endif // Rcpp__sugar__trimws_h
int ncol() const
Definition Matrix.h:94
int nrow() const
Definition Matrix.h:97
R_xlen_t size() const
Definition Vector.h:275
static Vector create()
Definition Vector.h:1121
bool isws(const char c)
Definition trimws.h:36
const char * trim_right(const char *str, R_len_t sz, std::string *buff)
Definition trimws.h:52
const char * trim_both(const char *str, R_len_t sz, std::string *buff)
Definition trimws.h:66
const char * trim_left(const char *str)
Definition trimws.h:40
bool is_na< STRSXP >(SEXP x)
Definition is_na.h:52
Rcpp API.
Definition algo.h:28
void NORET stop(const std::string &message)
Definition exceptions.h:117
no_init_vector no_init(R_xlen_t size)
Definition no_init.h:77
Vector< STRSXP > trimws(const Vector< STRSXP > &x, const char *which="both")
Definition trimws.h:90
T as(SEXP x)
Definition as.h:151