<div dir="ltr">Stepping back (alot), I'm really unconvinced about the need for this class.<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 20, 2013 at 1:40 PM, Dmitri Gribenko <span dir="ltr"><<a href="mailto:gribozavr@gmail.com" target="_blank" class="cremed">gribozavr@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
I want to propose a new ADT: StringRefNulTerminated.<br>
<br>
The ``StringRefNulTerminated`` class<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
<br>
``StringRefNulTerminated`` is a subclass of ``StringRef`` that represents a<br>
reference to a NUL-terminated string.  It can be safely converted to 'const<br>
char *' without copying the underlying data.  Because it is a subclass of<br>
``StringRef``, slicing implicitly occurs whenever a ``StringRefNulTerminated``<br>
object is passed to an API that requires a ``StringRef``.  Since<br>
``StringRefNulTerminated`` does not contain any extra data, slicing preserves<br>
all the information (except for the fact that the string was NUL-terminated).<br>
<br>
The motivation behind this class is to preserve the information about the NUL<br>
terminator in the string.  With ``StringRef``, this information is lost.  Also,<br>
one can not check if a ``StringRef`` contains a NUL-terminated string, thus it<br>
is required to copy the data to convert from a ``StringRef`` to<br>
``const char *``.<br></blockquote><div><br></div><div style>Everything you describe here is true of a 'const char*'. Why not just pass that through the API layers where it is important to have a C-string representation?</div>
<div style><br></div><div style>pro: It's a lot simpler and more clear about the fact that the code is dealing with a C-string.</div><div style>pro: It doesn't add a whole new class to ADT</div><div style>pro: It doesn't add complexity of understanding how this class and StringRef interact -- we already undrestand how to build a StringRef out of a C-string.</div>
<div style><br></div><div style>con: It requires users who need a StringRef-like API to build a StringRef around it.</div><div style><br></div><div style>This doesn't seem too bad... maybe there are other cons?</div><div>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Example:<br>
<br>
  // Function returning a NUL-terminated string.<br>
  StringRefNulTerminated getAString();<br>
<br>
  StringRefNulTerminated S1 = getAString();<br>
  StringRef S2 = getAString(); // Slicing to a StringRef.<br>
  const char *S3 = getAString().c_str(); // Convert back to a 'const char *'<br>
                                         // without copying data.<br>
  const char *S4 = S1.c_str(); // Same.<br>
<br>
Discussion<br>
^^^^^^^^^^<br>
<br>
The first user of the "convert to const char *" functionality is<br>
libclang that exposes StringRefs via the C API.  It happens that quite<br>
a few C++ APIs in Clang return NUL-terminated strings as StringRefs.<br>
But after a NUL-terminated string is converted to a StringRef, there<br>
is no safe way to recover that bit of information back (currently,<br>
libclang does an out-of-bounds read to check if the StringRef is<br>
NUL-terminated, but it is a bad thing and should be removed).  It is a<br>
waste of memory and CPU cycles to copy StringRefs that are actually<br>
NUL-terminated.<br>
<br>
The only reasonable way to solve this is to carry this bit of<br>
information with the string itself.  I considered two possible<br>
implementations:<br>
<br>
(1) an additional bit in StringRef;<br>
(2) a separate class.<br>
<br>
About (1): we could turn StringRef::Length into a bitfield and free up<br>
a bit to store information about a NUL terminator.  David Blaikie<br>
suggested (on IRC) that it would slow down StringRef::size(), so I did<br>
not consider it further.<br>
<br>
(2) is the proposed implementation.<br>
<br>
About the name: I am not really attached to this name, but I could<br>
only think of two good names:  CStringRef and StringRefNulTerminated.<br>
"CStringRef" is a bit ambigous (is it a typedef for "const char*"?!),<br>
and has only a single character difference from "StringRef", so I<br>
decided to err on the side of verbosity.<br>
<br>
Please review!<br>
<span class="HOEnZb"><font color="#888888"><br>
Dmitri<br>
<br>
--<br>
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if<br>
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <<a href="mailto:gribozavr@gmail.com" class="cremed">gribozavr@gmail.com</a>>*/<br>
</font></span></blockquote></div><br></div></div>