Rcpp Version 1.0.9
String.h
Go to the documentation of this file.
1 
2 // String.h: Rcpp R/C++ interface class library -- single string
3 //
4 // Copyright (C) 2012 - 2020 Dirk Eddelbuettel and Romain Francois
5 // Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and IƱaki Ucar
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__String_h
23 #define Rcpp__String_h
24 
25 #ifndef RCPP_STRING_DEBUG_LEVEL
26 #define RCPP_STRING_DEBUG_LEVEL 0
27 #endif
28 
29 
30 #if RCPP_STRING_DEBUG_LEVEL > 0
31  #define RCPP_STRING_DEBUG_FORMAT "%40s:%4d "
32  #define RCPP_STRING_DEBUG(MSG) Rprintf(RCPP_STRING_DEBUG_FORMAT "%s\n" , ::Rcpp::internal::debug::short_file_name(__FILE__).c_str(), __LINE__, MSG);
33  #define RCPP_STRING_DEBUG_1(fmt, MSG) Rprintf(RCPP_STRING_DEBUG_FORMAT fmt "\n" , ::Rcpp::internal::debug::short_file_name(__FILE__).c_str(), __LINE__, MSG);
34  #define RCPP_STRING_DEBUG_2(fmt, M1, M2) Rprintf(RCPP_STRING_DEBUG_FORMAT fmt "\n" , ::Rcpp::internal::debug::short_file_name(__FILE__).c_str(), __LINE__, M1, M2);
35  #define RCPP_STRING_DEBUG_3(fmt, M1, M2, M3) Rprintf(RCPP_STRING_DEBUG_FORMAT fmt "\n" , ::Rcpp::internal::debug::short_file_name(__FILE__).c_str(), __LINE__, M1, M2, M3);
36 #else
37  #define RCPP_STRING_DEBUG(MSG)
38  #define RCPP_STRING_DEBUG_1(fmt, MSG)
39  #define RCPP_STRING_DEBUG_2(fmt, M1, M2)
40  #define RCPP_STRING_DEBUG_3(fmt, M1, M2, M3)
41 #endif
42 
43 namespace Rcpp {
44 
49  class String {
50  public:
53 
55  String(): data(Rf_mkCharCE("", CE_UTF8)), token(R_NilValue), buffer(), valid(true), buffer_ready(true), enc(CE_UTF8) {
57  RCPP_STRING_DEBUG("String()");
58  }
59 
61  String(const String& s) : data(R_NilValue), token(R_NilValue), buffer(s.buffer), valid(s.valid), buffer_ready(s.buffer_ready), enc(s.enc) {
62  if (!buffer_ready) {
63  data = s.get_sexp();
65  }
66  RCPP_STRING_DEBUG("String(const String&)");
67  }
68 
70  String(SEXP charsxp) : data(R_NilValue), token(R_NilValue) {
71  if (TYPEOF(charsxp) == STRSXP) {
72  data = STRING_ELT(charsxp, 0);
73  } else if (TYPEOF(charsxp) == CHARSXP) {
74  data = charsxp;
75  }
76 
77  if (::Rf_isString(data) && ::Rf_length(data) != 1) {
78  const char* fmt = "Expecting a single string value: "
79  "[type=%s; extent=%i].";
80  throw ::Rcpp::not_compatible(fmt,
81  Rf_type2char(TYPEOF(data)),
82  ::Rf_length(data));
83  }
84 
85  valid = true;
86  buffer_ready = false;
87  enc = Rf_getCharCE(data);
89  RCPP_STRING_DEBUG("String(SEXP)");
90  }
91 
93  String(const StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) {
95  RCPP_STRING_DEBUG("String(const StringProxy&)");
96  }
97 
98  String(const StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) {
100  set_encoding(enc);
101  RCPP_STRING_DEBUG("String(const StringProxy&, cetype_t)");
102  }
103 
105  String(const const_StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) {
107  RCPP_STRING_DEBUG("String(const const_StringProxy&)");
108  }
109 
110  String(const const_StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) {
112  set_encoding(enc);
113  RCPP_STRING_DEBUG("String(const const_StringProxy&, cetype_t)");
114  }
115 
117  String(const std::string& s, cetype_t enc = CE_UTF8) : data(R_NilValue), token(R_NilValue), buffer(s), valid(false), buffer_ready(true), enc(enc) {
118  RCPP_STRING_DEBUG("String(const std::string&, cetype_t)");
119  }
120 #ifdef RCPP_USING_CXX11
122  String(String&& s) : data(s.data), token(s.token), buffer(std::move(s.buffer)), valid(s.valid), buffer_ready(s.buffer_ready), enc(s.enc) {
123  // Erase s.
124  s.data = R_NilValue;
125  s.token = R_NilValue;
126  s.buffer = std::string();
127  s.valid = false;
128  s.buffer_ready = true;
129  s.enc = CE_UTF8;
130  RCPP_STRING_DEBUG("String(String&&)");
131  }
132 
134  String(std::string&& s, cetype_t enc = CE_UTF8) : data(R_NilValue), token(R_NilValue), buffer(s), valid(false), buffer_ready(true), enc(enc) {
135  RCPP_STRING_DEBUG("String(std::string&&, cetype_t)");
136  }
137 #endif
138  String(const std::wstring& s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) {
140  RCPP_STRING_DEBUG("String(const std::wstring&, cetype_t)");
141  }
142 
144  String(const char* s, cetype_t enc = CE_UTF8) : buffer(s), valid(false), buffer_ready(true), enc(enc) {
145  data = R_NilValue;
146  token = R_NilValue;
147  RCPP_STRING_DEBUG("String(const char*, cetype_t)");
148  }
149 
150  String(const wchar_t* s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) {
152  RCPP_STRING_DEBUG("String(const wchar_t* s, cetype_t)");
153  }
154 
156  String(int x) : data(internal::r_coerce<INTSXP,STRSXP>(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) {
158  }
159  String(double x) : data(internal::r_coerce<REALSXP,STRSXP>(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) {
161  }
162  String(bool x) : data(internal::r_coerce<LGLSXP,STRSXP>(x)), token(R_NilValue), valid(true) , buffer_ready(false), enc(CE_UTF8) {
164  }
165  String(Rcomplex x) : data(internal::r_coerce<CPLXSXP,STRSXP>(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) {
167  }
168  String(Rbyte x) : data(internal::r_coerce<RAWSXP,STRSXP>(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) {
170  }
171 
174  data = R_NilValue;
175  token = R_NilValue;
176  }
177 
178 
179  inline String& operator=(int x) {
180  data = internal::r_coerce<INTSXP, STRSXP>(x);
183  valid = true;
184  buffer_ready = false;
185  return *this;
186  }
187  inline String& operator=(double x) {
188  data = internal::r_coerce<REALSXP, STRSXP>(x);
191  valid = true;
192  buffer_ready = false;
193  return *this;
194  }
195  inline String& operator=(Rbyte x) {
196  data = internal::r_coerce<RAWSXP, STRSXP>(x);
199  valid = true;
200  buffer_ready = false;
201  return *this;
202  }
203  inline String& operator=(bool x) {
204  data = internal::r_coerce<LGLSXP, STRSXP>(x);
207  valid = true;
208  buffer_ready = false;
209  return *this;
210  }
211  inline String& operator=(Rcomplex x) {
212  data = internal::r_coerce<CPLXSXP, STRSXP>(x);
215  valid = true;
216  buffer_ready = false;
217  return *this;
218  }
219  inline String& operator=(SEXP x) {
220  if (data != x) {
221  data = x;
224  }
225  valid = true;
226  buffer_ready = false;
227  return *this;
228  }
229  inline String& operator=(const StringProxy& proxy) {
230  SEXP x = proxy.get();
231  if (data != x) {
232  data = x;
235  }
236  valid = true;
237  buffer_ready = false;
238  return *this;
239  }
240  inline String& operator=(const String& other) {
241  if (other.buffer_ready) {
242  // Copy the buffer without creating a SEXP.
243  if (valid) {
245  valid = false;
246  }
247  data = R_NilValue;
248  token = R_NilValue;
249  buffer = other.buffer;
250  buffer_ready = true;
251  enc = other.enc;
252  } else {
253  SEXP x = other.get_sexp();
254  if (data != x) {
255  data = x;
258  }
259  valid = true;
260  buffer_ready = false;
261  }
262  return *this;
263  }
264  inline String& operator=(const std::string& s) {
265  buffer = s;
266  valid = false;
267  buffer_ready = true;
268  return *this;
269  }
270 #ifdef RCPP_USING_CXX11
271  inline String& operator=(String&& other) {
272  data = other.data;
273  token = other.token;
274  buffer = std::move(other.buffer);
275  valid = other.valid;
276  buffer_ready = other.buffer_ready;
277  enc = other.enc;
278  // Erase other.
279  other.data = R_NilValue;
280  other.token = R_NilValue;
281  other.buffer = std::string();
282  other.valid = false;
283  other.buffer_ready = true;
284  other.enc = CE_UTF8;
285  return *this;
286  }
287  inline String& operator=(std::string&& s) {
288  buffer = s;
289  valid = false;
290  buffer_ready = true;
291  return *this;
292  }
293 #endif
294  inline String& operator=(const char* s) {
295  buffer = s;
296  valid = false;
297  buffer_ready = true;
298  return *this;
299  }
300 
301  private:
302  template <typename T>
303  inline String& assign_wide_string(const T& s) {
304  data = internal::make_charsexp(s);
307  valid = true;
308  buffer_ready = false;
309  return *this;
310  }
311 
312  public:
313  inline String& operator=(const std::wstring& s) { return assign_wide_string(s); }
314  inline String& operator=(const wchar_t* s) { return assign_wide_string(s); }
315 
316  inline String& operator+=(const std::string& s) {
317  RCPP_STRING_DEBUG("String::operator+=(std::string)");
318  if (is_na()) return *this;
319  setBuffer(); buffer += s; valid = false;
320  return *this;
321  }
322 
323  inline String& operator+=(const char* s) {
324  RCPP_STRING_DEBUG("String::operator+=(const char*)");
325  if (is_na()) return *this;
326  setBuffer(); buffer += s; valid = false;
327  return *this;
328  }
329  private:
330  template <typename T>
331  inline String& append_wide_string(const T& s) {
332  RCPP_STRING_DEBUG_1("String::operator+=(%s)", DEMANGLE(T));
333  setData();
334  if (is_na()) return *this;
335  const char* buf = CHAR(data);
336  std::wstring tmp(buf, buf + strlen(buf));
337  tmp += s;
338  data = internal::make_charsexp(tmp);
341  valid = true;
342  buffer_ready = false;
343  return *this;
344  }
345 
346  public:
347 
348  inline String& operator+=(const std::wstring& s) { return append_wide_string(s); }
349  inline String& operator+=(const wchar_t* s) { return append_wide_string(s); }
350 
351  inline String& operator+=(const String& other) {
352  RCPP_STRING_DEBUG("String::operator+=(const char*)");
353  if (is_na()) return *this;
354  if (other.is_na()) {
355  data = NA_STRING;
358  valid = true;
359  buffer_ready = false;
360  return *this;
361  }
362  setBuffer(); buffer += other; valid = false;
363  return *this;
364  }
365  inline String& operator+=(const StringProxy& proxy) {
366  RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)");
367  if (is_na()) return *this;
368  SEXP proxy_sexp = proxy;
369  if (proxy_sexp == NA_STRING) {
370  data = NA_STRING;
373  valid = true;
374  buffer_ready = false;
375  return *this;
376  }
377  setBuffer(); buffer += CHAR(proxy_sexp); valid = false;
378  return *this;
379  }
380  inline String& operator+=(const const_StringProxy& proxy) {
381  RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)");
382  if (is_na()) return *this;
383  SEXP proxy_sexp = proxy;
384  if (proxy_sexp == NA_STRING) {
385  data = NA_STRING;
388  valid = true;
389  buffer_ready = false;
390  return *this;
391  }
392  setBuffer(); buffer += CHAR(proxy_sexp); valid = false;
393  return *this;
394  }
395  inline String& operator+=(SEXP x) {
396  RCPP_STRING_DEBUG("String::operator+=(SEXP)");
397  if (is_na()) return *this;
398  if (x == NA_STRING) {
399  data = NA_STRING;
402  valid = true;
403  buffer_ready = false;
404  return *this;
405  }
406  setBuffer(); buffer += CHAR(x); valid = false;
407  return *this;
408  }
409  // inline String& operator+=(int x ) { data += char_nocheck(internal::r_coerce<INTSXP ,STRSXP>(x)); return *this; }
410  // inline String& operator+=(double x ) { data += char_nocheck(internal::r_coerce<REALSXP,STRSXP>(x)); return *this; }
411  // inline String& operator+=(Rbyte x ) { data += char_nocheck(internal::r_coerce<RAWSXP ,STRSXP>(x)); return *this; }
412  // inline String& operator+=(bool x ) { data += char_nocheck(internal::r_coerce<LGLSXP ,STRSXP>(x)); return *this; }
413  // inline String& operator+=(Rcomplex x) { data += char_nocheck(internal::r_coerce<CPLXSXP,STRSXP>(x)); return *this; }
414 
415 
416  inline String& replace_first(const char* s, const char* news) {
417  RCPP_STRING_DEBUG_2("String::replace_first(const char* = '%s' , const char* = '%s')", s, news);
418  if (is_na()) return *this;
419  setBuffer();
420  std::string s2 = std::string(s);
421  size_t index = std::distance(buffer.begin(), std::search(buffer.begin(), buffer.end(), s2.begin(), s2.end()));
422  if (index != std::string::npos) buffer.replace(index, strlen(s), news);
423  valid = false;
424  return *this;
425  }
426  inline String& replace_first(const Rcpp::String& s, const char* news) {
427  // replace NA -> do nothing
428  if (s.is_na()) return *this;
429  return replace_first(s.get_cstring(), news);
430  }
431  inline String& replace_first(const char* s, const Rcpp::String& news) {
432  // replace NA -> do nothing
433  if (news.is_na()) return *this;
434  return replace_first(s, news.get_cstring());
435  }
436  inline String& replace_first(const Rcpp::String& s, const Rcpp::String& news) {
437  // replace NA -> do nothing
438  if (s.is_na() || news.is_na()) return *this;
439  return replace_first(s.get_cstring(), news.get_cstring());
440  }
441 
442  inline String& replace_last(const char* s, const char* news) {
443  RCPP_STRING_DEBUG_2("String::replace_last(const char* = '%s' , const char* = '%s')", s, news);
444  if (is_na()) return *this;
445  setBuffer();
446  std::string s2 = std::string(s);
447  size_t index = std::distance(buffer.begin(), std::find_end(buffer.begin(), buffer.end(), s2.begin(), s2.end()));
448  if (index != std::string::npos) buffer.replace(index, strlen(s), news);
449  valid = false;
450  return *this;
451  }
452  inline String& replace_last(const Rcpp::String& s, const char* news) {
453  // replace NA -> do nothing
454  if (s.is_na()) return *this;
455  return replace_last(s.get_cstring(), news);
456  }
457  inline String& replace_last(const char* s, const Rcpp::String& news) {
458  // replace NA -> do nothing
459  if (news.is_na()) return *this;
460  return replace_last(s, news.get_cstring());
461  }
462  inline String& replace_last(const Rcpp::String& s, const Rcpp::String& news) {
463  // replace NA -> do nothing
464  if (s.is_na() || news.is_na()) return *this;
465  return replace_last(s.get_cstring(), news.get_cstring());
466  }
467 
468 
469  inline String& replace_all(const char* s, const char* news) {
470  RCPP_STRING_DEBUG_2("String::replace_all(const char* = '%s' , const char* = '%s')", s, news);
471  if (is_na()) return *this;
472  setBuffer();
473  std::string s2 = std::string(s);
474  std::string::iterator iter = buffer.begin();
475  while(true) {
476  iter = std::search(iter, buffer.end(), s2.begin(), s2.end());
477  if (iter == buffer.end()) break;
478  size_t index = std::distance(buffer.begin(), iter);
479  if (index != std::string::npos) buffer.replace(index, strlen(s), news);
480  }
481  valid = false;
482  return *this;
483  }
484 
485  template <typename LHS, typename RHS>
486  inline String& replace_all(const LHS& s, const RHS& news) {
487  return replace_all(String(s), String(news));
488  }
489 
490  inline String& replace_all(const Rcpp::String& s, const char* news) {
491  // replace NA -> do nothing
492  if (s.is_na()) return *this;
493  return replace_all(s.get_cstring(), news);
494  }
495  inline String& replace_all(const char* s, const Rcpp::String& news) {
496  // replace NA -> do nothing
497  if (news.is_na()) return *this;
498  return replace_all(s, news.get_cstring());
499  }
500  inline String& replace_all(const Rcpp::String& s, const Rcpp::String& news) {
501  // replace NA -> do nothing
502  if (s.is_na() || news.is_na()) return *this;
503  return replace_all(s.get_cstring(), news.get_cstring());
504  }
505 
506  inline String& push_back(const char* s) {
507  if (is_na()) return *this;
508  setBuffer(); valid = false; buffer += s;
509  return *this;
510  }
511  inline String& push_back(const std::string& s) {
512  return push_back(s.c_str());
513  }
514  inline String& push_back(const Rcpp::String& s) {
515  if (is_na()) return *this;
516  if (s.is_na()) { set_na(); return *this; }
517  return push_back(s.get_cstring());
518  }
519 
520  inline String& push_front(const char* s) {
521  if (is_na()) return *this;
522  setBuffer(); valid = false; buffer = s + buffer;
523  return *this;
524  }
525  inline String& push_front(const std::string& s) {
526  return push_front(s.c_str());
527  }
528  inline String& push_front(const Rcpp::String& s) {
529  if (is_na()) return *this;
530  if (s.is_na()) { set_na(); return *this; }
531  return push_front(s.get_cstring());
532  }
533 
534 
535  inline void set_na() {
536  data = NA_STRING;
539  valid = true;
540  buffer_ready = false;
541  }
542 
543 
544  inline SEXP get_sexp_impl() const {
545 
546  // workaround for h5 package (currently deprecated so updates
547  // to CRAN may not be timely)
548 #ifdef __H5Cpp_H
549  return Rf_mkCharCE(buffer.c_str(), enc);
550 #else
551  if (buffer.find('\0') != std::string::npos)
552  throw embedded_nul_in_string();
553  return Rf_mkCharLenCE(buffer.c_str(), buffer.size(), enc);
554 #endif
555  }
556 
557  inline SEXP get_sexp() const {
558  RCPP_STRING_DEBUG_1("String::get_sexp const (valid = %d) ", valid);
559  return valid ? data : get_sexp_impl();
560  }
561 
562  inline SEXP get_sexp() {
563  RCPP_STRING_DEBUG_1("String::get_sexp (valid = %d) ", valid);
564  setData(); return data;
565  }
566 
567  inline operator std::string() const {
568  return get_cstring();
569  }
570 
571  inline operator std::wstring() const {
572  const char* s = get_cstring();
573  return std::wstring(s, s + strlen(s));
574  }
575 
576  inline const char* get_cstring() const {
577  return buffer_ready ? buffer.c_str() : CHAR(data);
578  }
579 
580  inline cetype_t get_encoding() const {
581  return enc;
582  }
583 
584  inline void set_encoding(cetype_t encoding) {
585  enc = encoding;
586 
587  if (valid) {
588  // TODO: may longjmp on failure to translate?
589  const char* translated = Rf_translateCharUTF8(data);
590  data = Rf_mkCharCE(translated, encoding);
593  } else {
594  data = get_sexp_impl();
596  valid = true;
597  }
598  }
599 
600  bool operator<(const Rcpp::String& other) const {
601  return strcmp(get_cstring(), other.get_cstring()) < 0;
602  }
603 
604  bool operator==(const Rcpp::String& other) const {
605  return get_sexp() == other.get_sexp();
606  }
607  bool operator!=(const Rcpp::String& other) const {
608  return get_sexp() != other.get_sexp();
609  }
610 
611  bool operator==(const StringProxy& other) const {
612  return get_sexp() == other.get();
613  }
614 
615  bool operator!=(const StringProxy& other) const {
616  return get_sexp() != other.get();
617  }
618 
619  bool operator==(const const_StringProxy& other) const {
620  return get_sexp() == other.get();
621  }
622 
623  bool operator!=(const const_StringProxy& other) const {
624  return get_sexp() != other.get();
625  }
626 
627  bool operator>(const Rcpp::String& other) const {
628  return strcmp(get_cstring(), other.get_cstring()) > 0;
629  }
630 
631  bool operator==(SEXP other) const {
632  return get_sexp() == other;
633  }
634 
635  bool operator!=(SEXP other) const {
636  return get_sexp() != other;
637  }
638 
639  private:
640 
642  SEXP data;
643  SEXP token;
644 
646  std::string buffer;
647 
649  bool valid;
650 
653 
655  cetype_t enc;
656 
657  inline bool is_na() const { return data == NA_STRING; }
658  inline void setBuffer() {
659  if (!buffer_ready) {
661  buffer_ready = true;
662  }
663  }
664  inline void setData() {
665  RCPP_STRING_DEBUG("setData");
666  if (!valid) {
667  data = get_sexp_impl();
669  valid = true;
670  }
671  }
672  template <typename T> void append(const T& s) { buffer += s;}
673  };
674 
675  namespace traits{
676  template<> struct r_type_traits<Rcpp::String>{ typedef r_type_RcppString_tag r_category; };
677  template<> struct r_sexptype_traits<Rcpp::String>{ enum{ rtype = STRSXP }; };
678  }
679 
680  namespace internal {
681  template <int RTYPE, template <class> class StoragePolicy>
683  set(s.get_sexp());
684  return *this;
685  }
686 
687  template <int RTYPE>
689  RCPP_DEBUG("string_element_converter::get< Rcpp::String >()")
690  return input.get_sexp();
691  }
692 
693  template <>
694  inline SEXP make_charsexp<Rcpp::String>(const Rcpp::String& s) {
695  return s.get_sexp();
696  }
697 
698  template <int RTYPE, template <class> class StoragePolicy>
699  template <typename T>
701  String tmp = get();
702  tmp += rhs;
703  set(tmp);
704  return *this;
705  }
706 
707  }
708 
709 
710  template <>
711  inline SEXP wrap<Rcpp::String>(const Rcpp::String& object) {
712  RCPP_STRING_DEBUG("wrap<String>()");
713  Shield<SEXP> res(Rf_allocVector(STRSXP, 1));
714  SEXP data = object.get_sexp();
715  SET_STRING_ELT(res, 0, data);
716  return res;
717  }
718 
719  inline bool operator==(const String::StringProxy& lhs, const String& rhs) {
720  return rhs == lhs;
721  }
722 
723  inline bool operator!=(const String::StringProxy& lhs, const String& rhs) {
724  return rhs != lhs;
725  }
726 
727  inline bool operator==(const String::const_StringProxy& lhs, const String& rhs) {
728  return rhs == lhs;
729  }
730 
731  inline bool operator!=(const String::const_StringProxy& lhs, const String& rhs) {
732  return rhs != lhs;
733  }
734 
735 } // Rcpp
736 
738 #if defined(RCPP_USING_CXX11) || defined(HAS_TR1)
739 namespace std
740 {
741 #ifndef RCPP_USING_CXX11
742 namespace tr1 {
743 #endif
744  template <>
745  struct hash<Rcpp::String>
746  {
747  size_t operator()(const Rcpp::String & s) const{
748  return hash<string>()(s.get_cstring());
749  }
750  };
751 #ifndef RCPP_USING_CXX11
752 }
753 #endif
754 }
755 #endif
756 
757 #endif
#define RCPP_STRING_DEBUG_2(fmt, M1, M2)
Definition: String.h:39
#define RCPP_STRING_DEBUG_1(fmt, MSG)
Definition: String.h:38
#define RCPP_STRING_DEBUG(MSG)
Definition: String.h:37
const char * char_nocheck(SEXP)
Definition: routines.h:258
String(Rcomplex x)
Definition: String.h:165
String(const const_StringProxy &proxy)
Definition: String.h:105
void append(const T &s)
Definition: String.h:672
bool buffer_ready
Definition: String.h:652
String & replace_first(const Rcpp::String &s, const char *news)
Definition: String.h:426
String & operator+=(const const_StringProxy &proxy)
Definition: String.h:380
String & operator+=(const String &other)
Definition: String.h:351
bool operator==(const StringProxy &other) const
Definition: String.h:611
String & replace_all(const Rcpp::String &s, const char *news)
Definition: String.h:490
String & replace_last(const char *s, const char *news)
Definition: String.h:442
String & operator=(const wchar_t *s)
Definition: String.h:314
std::string buffer
Definition: String.h:646
String(const char *s, cetype_t enc=CE_UTF8)
Definition: String.h:144
String & push_back(const Rcpp::String &s)
Definition: String.h:514
String & push_front(const Rcpp::String &s)
Definition: String.h:528
bool is_na() const
Definition: String.h:657
String & replace_first(const char *s, const Rcpp::String &news)
Definition: String.h:431
String & operator=(Rcomplex x)
Definition: String.h:211
bool operator>(const Rcpp::String &other) const
Definition: String.h:627
String & push_back(const char *s)
Definition: String.h:506
String & replace_all(const Rcpp::String &s, const Rcpp::String &news)
Definition: String.h:500
bool operator!=(const Rcpp::String &other) const
Definition: String.h:607
String & replace_all(const LHS &s, const RHS &news)
Definition: String.h:486
String & operator=(double x)
Definition: String.h:187
bool operator!=(const const_StringProxy &other) const
Definition: String.h:623
cetype_t get_encoding() const
Definition: String.h:580
void set_encoding(cetype_t encoding)
Definition: String.h:584
const char * get_cstring() const
Definition: String.h:576
String(const StringProxy &proxy)
Definition: String.h:93
String & push_front(const std::string &s)
Definition: String.h:525
String(double x)
Definition: String.h:159
String & replace_last(const Rcpp::String &s, const Rcpp::String &news)
Definition: String.h:462
internal::string_proxy< STRSXP > StringProxy
Definition: String.h:51
String & operator=(const StringProxy &proxy)
Definition: String.h:229
String(const std::string &s, cetype_t enc=CE_UTF8)
Definition: String.h:117
String(SEXP charsxp)
Definition: String.h:70
bool operator==(const const_StringProxy &other) const
Definition: String.h:619
String & operator=(const std::wstring &s)
Definition: String.h:313
cetype_t enc
Definition: String.h:655
internal::const_string_proxy< STRSXP > const_StringProxy
Definition: String.h:52
String & operator=(bool x)
Definition: String.h:203
String(const const_StringProxy &proxy, cetype_t enc)
Definition: String.h:110
String & operator=(int x)
Definition: String.h:179
String(const std::wstring &s, cetype_t enc=CE_UTF8)
Definition: String.h:138
SEXP get_sexp() const
Definition: String.h:557
String & replace_last(const char *s, const Rcpp::String &news)
Definition: String.h:457
String(Rbyte x)
Definition: String.h:168
String & operator+=(const std::string &s)
Definition: String.h:316
bool operator!=(const StringProxy &other) const
Definition: String.h:615
SEXP get_sexp_impl() const
Definition: String.h:544
String(const wchar_t *s, cetype_t enc=CE_UTF8)
Definition: String.h:150
String & operator+=(const wchar_t *s)
Definition: String.h:349
bool operator==(const Rcpp::String &other) const
Definition: String.h:604
String & operator+=(SEXP x)
Definition: String.h:395
String & replace_first(const char *s, const char *news)
Definition: String.h:416
String & operator+=(const std::wstring &s)
Definition: String.h:348
String & push_front(const char *s)
Definition: String.h:520
String & replace_all(const char *s, const char *news)
Definition: String.h:469
bool operator<(const Rcpp::String &other) const
Definition: String.h:600
String & operator=(const String &other)
Definition: String.h:240
String & operator=(SEXP x)
Definition: String.h:219
String & replace_last(const Rcpp::String &s, const char *news)
Definition: String.h:452
String & replace_all(const char *s, const Rcpp::String &news)
Definition: String.h:495
String(const StringProxy &proxy, cetype_t enc)
Definition: String.h:98
String & push_back(const std::string &s)
Definition: String.h:511
SEXP data
Definition: String.h:642
String & assign_wide_string(const T &s)
Definition: String.h:303
bool operator!=(SEXP other) const
Definition: String.h:635
void setData()
Definition: String.h:664
String & operator+=(const char *s)
Definition: String.h:323
String & operator=(const char *s)
Definition: String.h:294
String & operator=(Rbyte x)
Definition: String.h:195
SEXP get_sexp()
Definition: String.h:562
void setBuffer()
Definition: String.h:658
String(bool x)
Definition: String.h:162
String(int x)
Definition: String.h:156
bool operator==(SEXP other) const
Definition: String.h:631
String & operator=(const std::string &s)
Definition: String.h:264
String & operator+=(const StringProxy &proxy)
Definition: String.h:365
String & append_wide_string(const T &s)
Definition: String.h:331
void set_na()
Definition: String.h:535
String & replace_first(const Rcpp::String &s, const Rcpp::String &news)
Definition: String.h:436
String(const String &s)
Definition: String.h:61
SEXP token
Definition: String.h:643
bool valid
Definition: String.h:649
static SEXP get(const T &input)
Definition: converter.h:48
string_proxy & operator=(const string_proxy< RTYPE, StoragePolicy > &other)
Definition: string_proxy.h:57
string_proxy & operator+=(const T &rhs)
#define RCPP_DEBUG(MSG)
Definition: debug.h:43
#define DEMANGLE(__TYPE__)
Definition: exceptions.h:382
Rcpp API.
Definition: algo.h:28
bool operator!=(const Date &d1, const Date &d2)
Definition: Date.h:170
SEXP get(const std::string &name) const
Definition: Environment.h:103
SEXP Rcpp_PreciousPreserve(SEXP object)
Definition: RcppCommon.h:116
void Rcpp_PreciousRelease(SEXP token)
Definition: RcppCommon.h:120
bool operator==(const Date &d1, const Date &d2)
Definition: Date.h:167
Definition: swap.h:25