<div dir="ltr">Thanks all for your replies.<div><br></div><div><font color="#990000">#define ASCII_MASK (1<<6)<br>bool is_ascii_internal(Rcpp::String xi) {<br>  return (LEVELS(xi.get_sexp()) & ASCII_MASK) != 0;<br>}</font><br></div><div>This is almost exactly the solution I was attempting after reading the src/include/Defn.h file, but was missing LEVELS().</div><div><br></div><div><font color="#990000">Tomas wrote well about it:</font><br>  <a href="https://developer.r-project.org/Blog/public/2020/07/30/windows/utf-8-build-of-r-and-cran-packages/index.html" rel="noreferrer" target="_blank">https://developer.r-project.org/Blog/public/2020/07/30/windows/utf-8-build-of-r-and-cran-packages/index.html</a><br></div><div>That's a great read, thanks for sharing.</div><div><br></div><div><font color="#990000">"One day" this may be easier. Until then the best we can do may be to borrow<br>helper functions from R</font><br></div><div>Agreed with both sentences. Accessing some helper functions from R would help a lot while at the same time maintaining consistency from the time being.</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Feb 18, 2021 at 2:37 PM Travers Ching <<a href="mailto:traversc@gmail.com" target="_blank">traversc@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Kevin and Andrade, <div><br></div><div>I was also once looking for a way to test if strings are ASCII. Although looping over the characters would be fast enough in most cases, it isn't efficient or necessary. </div><div><br></div><div>The IS_ASCII function isn't visible to users and it isn't obvious how one can re-implement the function unless you read R source code. I would agree with Andrade that a function in Rcpp would be helpful. Here's one re-implementation of the internal R function:</div><div><br></div><div>#include <Rcpp.h><br><br>#define ASCII_MASK (1<<6)<br>bool is_ascii_internal(Rcpp::String xi) {<br>  return (LEVELS(xi.get_sexp()) & ASCII_MASK) != 0;<br>}<br><br>// [[Rcpp::export]]<br>bool is_ascii(Rcpp::CharacterVector x) {<br>  return is_ascii_internal(x[0]);<br>}<br></div><div><br></div><div>Travers</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Feb 18, 2021 at 11:18 AM Kevin Ushey <<a href="mailto:kevinushey@gmail.com" target="_blank">kevinushey@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Thu, Feb 18, 2021 at 1:36 AM Andrade Solomon<br>
<<a href="mailto:andradesolomon2011@gmail.com" target="_blank">andradesolomon2011@gmail.com</a>> wrote:<br>
><br>
> Dear list,<br>
><br>
> I see here that Rccp strings have both a get_encoding() and a set_encoding() member functions, which respectively return and accept a cetype_t enum defined in Rinternals.h with options:<br>
>     CE_NATIVE = 0,<br>
>     CE_UTF8   = 1,<br>
>     CE_LATIN1 = 2,<br>
>     CE_BYTES  = 3,<br>
>     CE_SYMBOL = 5,<br>
>     CE_ANY = 99<br>
><br>
> This means that if the String is UTF-8, Latin1 or Bytecode, the String's get_encoding() member function will return 1, 2 or 3, respectively. Experimentally, I see that when I try it with string objects containing only 0 to 127 ASCII characters (with no manually set encoding), the get_encoding() member function returns 0, which means CE_NATIVE in the aforementioned enum. At first, I just assumed that, then, in Rcpp's eyes, ASCII would be considered CE_NATIVE. This could even make sense with what is described in R's Encoding() command help entry, i.e. that "character strings in R can be declared to be encoded in 'latin1' or 'UTF-8' or as 'bytes' (...) ASCII strings will never be marked with a declared encoding, since their representation is the same in all supported encodings". However, I later realized that was not the case: if one creates an object that stores a UTF-8 or Latin-1 string (e.g. x <- "á") then manually drops the encoding (i.e. Encoding(x) <- ""), if that object (i.e. x) was passed to Rcpp its get_encoding() would still return 0 (which suggests that CE_NATIVE corresponds to the "unknown" label returned by the Encoding() command).<br>
><br>
> Note that, in R's official documentation, nothing is said about CE_NATIVE and, conversely, it is explicitly said that "Value CE_ANY is used to indicate a character string that will not need re-encoding – this is used for character strings known to be in ASCII, and can also be used as an input parameter where the intention is that the string is treated as a series of bytes". With this last bit of information in mind, I would then have expected that strings containing simple 0-127 ASCII characters and no manually set encoding, when passed to a Rcpp code would then have their get_encoding() member function return 99 instead of 0 - hence making it easy to check within Rcpp whether a string was ASCII only. That not being the case, my question actually becomes two-folded:<br>
><br>
> 1) why does Rcpp's get_encoding() apparently return 0 instead of 99 for ASCII only text?<br>
<br>
I think this is because this is what R does; e.g.<br>
<br>
    Encoding("ascii")  =>. "unknown"<br>
<br>
As far as I can tell, CE_ANY is used only sparsely by R itself<br>
internally, and isn't really surfaced as a "public" encoding to be<br>
used.<br>
<br>
> 2) is there an established way to properly check within Rcpp whether a Rcpp String is ASCII only (besides obviously looping over each character to check if it's <128) just like it is done in R's C API with the IS_ASCII macro?<br>
<br>
I think this is the most reasonable way forward. If you need something<br>
more complicated or specific, I would honestly just recommend rolling<br>
your own class with the behaviors you need.<br>
<br>
If you think there's a way to make this happen with Rcpp's own String<br>
class, then a pull request would be welcomed.<br>
<br>
> Thanks,<br>
><br>
> Andrade Solomon<br>
><br>
><br>
> _______________________________________________<br>
> Rcpp-devel mailing list<br>
> <a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">Rcpp-devel@lists.r-forge.r-project.org</a><br>
> <a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a><br>
_______________________________________________<br>
Rcpp-devel mailing list<br>
<a href="mailto:Rcpp-devel@lists.r-forge.r-project.org" target="_blank">Rcpp-devel@lists.r-forge.r-project.org</a><br>
<a href="https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel" rel="noreferrer" target="_blank">https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel</a></blockquote></div>
</blockquote></div>