P4C
The P4 Compiler
cstring Class Reference

Public Member Functions

 cstring (const cstring &)=default
 
 cstring (cstring &&)=default
 
 cstring (const std::stringstream &)
 
 cstring (const char *s)
 
 cstring (const std::string &a)
 
template<typename Iter >
 cstring (Iter begin, Iter end)
 
cstring before (const char *at) const
 
const char * c_str () const
 
bool endsWith (const cstring &suffix) const
 
const char * find (int c) const
 
const char * findlast (int c) const
 
char get (unsigned index) const
 
bool isNull () const
 
bool isNullOrEmpty () const
 
 operator const char * () const
 
bool operator!= (const cstring &a) const
 
bool operator!= (const char *a) const
 
bool operator!= (const std::string &a) const
 
cstring operator+= (cstring a)
 
cstring operator+= (const char *a)
 
cstring operator+= (std::string a)
 
cstring operator+= (char a)
 
bool operator< (const cstring &a) const
 
bool operator< (const char *a) const
 
bool operator< (const std::string &a) const
 
bool operator<= (const cstring &a) const
 
bool operator<= (const char *a) const
 
bool operator<= (const std::string &a) const
 
cstringoperator= (const cstring &)=default
 
cstringoperator= (cstring &&)=default
 
cstringoperator= (const char *)
 
cstringoperator= (const std::string &)
 
bool operator== (const cstring &a) const
 
bool operator== (const char *a) const
 
bool operator== (const std::string &a) const
 
bool operator> (const cstring &a) const
 
bool operator> (const char *a) const
 
bool operator> (const std::string &a) const
 
bool operator>= (const cstring &a) const
 
bool operator>= (const char *a) const
 
bool operator>= (const std::string &a) const
 
cstring replace (char find, char replace) const
 
size_t size () const
 
bool startsWith (const cstring &prefix) const
 
cstring substr (size_t start) const
 
cstring substr (size_t start, size_t length) const
 

Static Public Member Functions

static size_t cache_size (size_t &count)
 
template<typename Iterator >
static cstring join (Iterator begin, Iterator end, const char *delim=", ")
 
template<class T >
static cstring make_unique (const T &inuse, cstring base, char sep='.')
 
template<typename T >
static cstring to_cstring (const T &t)
 

Static Public Attributes

static cstring empty = cstring("")
 
static cstring newline = cstring("\n")
 

Detailed Description

A cstring is a reference to a zero-terminated, immutable, interned string. The cstring object itself is not immutable; you can reassign it as required, and it provides a mutable interface that copies the underlying immutable string as needed.

Compared to std::string, these are the benefits that cstring provides:

  • Copying and assignment are cheap. Since cstring only deals with immutable strings, these operations only involve pointer assignment.
  • Comparing cstrings for equality is cheap; interning makes it possible to test for equality using a simple pointer comparison.
  • The immutability of the underlying strings means that it's always safe to change a cstring, even if there are other references to it elsewhere.
  • The API offers a number of handy helper methods that aren't available on std::string.

On the other hand, these are the disadvantages of using cstring:

  • Because cstring deals with immutable strings, any modification requires that the complete string be copied.
  • Interning has an initial cost: converting a const char*, a std::string, or a std::stringstream to a cstring requires copying it. Currently, this happens every time you perform the conversion, whether the string is already interned or not, unless the source is an std::string.
  • Interned strings can never be freed, so they'll stick around for the lifetime of the program.
  • The string interning cstring performs is currently not threadsafe, so you can't safely use cstrings off the main thread.

Given these tradeoffs, the general rule of thumb to follow is that you should try to convert strings to cstrings early and keep them in that form. That way, you benefit from cheaper copying, assignment, and equality testing in as many places as possible, and you avoid paying the cost of repeated conversion.

However, when you're building or mutating a string, you should use std::string. Convert to a cstring only when the string is in its final form. This ensures that you don't pay the time and space cost of interning every intermediate version of the string.

Note that cstring has implicit conversions to and from other string types. This is convenient, but in performance-sensitive code it's good to be aware that mixing the two types of strings can trigger a lot of implicit copies.

Member Function Documentation

§ cache_size()

size_t cstring::cache_size ( size_t &  count)
static
Returns
the total size in bytes of all interned strings. is set to the total number of interned strings.