WPILibC++  2020.3.2-60-g3011ebe
Twine.h
1 //===- Twine.h - Fast Temporary String Concatenation ------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef WPIUTIL_WPI_TWINE_H
11 #define WPIUTIL_WPI_TWINE_H
12 
13 #include "wpi/SmallVector.h"
14 #include "wpi/StringRef.h"
15 #include "wpi/ErrorHandling.h"
16 #include <cassert>
17 #include <cstdint>
18 #include <string>
19 
20 #ifdef _WIN32
21 #pragma warning(push)
22 #pragma warning(disable : 26495)
23 #endif
24 
25 namespace wpi {
26 
27  class raw_ostream;
28 
85  class Twine {
87  enum NodeKind : unsigned char {
90  NullKind,
91 
93  EmptyKind,
94 
96  TwineKind,
97 
99  CStringKind,
100 
102  StdStringKind,
103 
105  StringRefKind,
106 
108  SmallStringKind,
109 
111  CharKind,
112 
114  DecUIKind,
115 
117  DecIKind,
118 
121  DecULKind,
122 
124  DecLKind,
125 
128  DecULLKind,
129 
131  DecLLKind,
132 
135  UHexKind
136  };
137 
138  union Child
139  {
140  const Twine *twine;
141  const char *cString;
142  const std::string *stdString;
143  const StringRef *stringRef;
144  const SmallVectorImpl<char> *smallString;
145  char character;
146  unsigned int decUI;
147  int decI;
148  const unsigned long *decUL;
149  const long *decL;
150  const unsigned long long *decULL;
151  const long long *decLL;
152  const uint64_t *uHex;
153  };
154 
157  Child LHS;
158 
161  Child RHS;
162 
164  NodeKind LHSKind = EmptyKind;
165 
167  NodeKind RHSKind = EmptyKind;
168 
170  explicit Twine(NodeKind Kind) : LHSKind(Kind) {
171  assert(isNullary() && "Invalid kind!");
172  }
173 
175  explicit Twine(const Twine &LHS, const Twine &RHS)
176  : LHSKind(TwineKind), RHSKind(TwineKind) {
177  this->LHS.twine = &LHS;
178  this->RHS.twine = &RHS;
179  assert(isValid() && "Invalid twine!");
180  }
181 
183  explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
184  : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
185  assert(isValid() && "Invalid twine!");
186  }
187 
189  bool isEmpty() const {
190  return getLHSKind() == EmptyKind;
191  }
192 
194  bool isNullary() const {
195  return isNull() || isEmpty();
196  }
197 
199  bool isUnary() const {
200  return getRHSKind() == EmptyKind && !isNullary();
201  }
202 
204  bool isBinary() const {
205  return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
206  }
207 
210  bool isValid() const {
211  // Nullary twines always have Empty on the RHS.
212  if (isNullary() && getRHSKind() != EmptyKind)
213  return false;
214 
215  // Null should never appear on the RHS.
216  if (getRHSKind() == NullKind)
217  return false;
218 
219  // The RHS cannot be non-empty if the LHS is empty.
220  if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind)
221  return false;
222 #if 0 // causes spurious warnings
223  // A twine child should always be binary.
224  if (getLHSKind() == TwineKind &&
225  !LHS.twine->isBinary())
226  return false;
227  if (getRHSKind() == TwineKind &&
228  !RHS.twine->isBinary())
229  return false;
230 #endif
231  return true;
232  }
233 
235  NodeKind getLHSKind() const { return LHSKind; }
236 
238  NodeKind getRHSKind() const { return RHSKind; }
239 
241  void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
242 
244  void printOneChildRepr(raw_ostream &OS, Child Ptr,
245  NodeKind Kind) const;
246 
247  public:
250 
252  /*implicit*/ Twine() {
253  assert(isValid() && "Invalid twine!");
254  }
255 
256  Twine(const Twine &) = default;
257 
263  /*implicit*/ Twine(const char *Str) {
264  if (Str[0] != '\0') {
265  LHS.cString = Str;
266  LHSKind = CStringKind;
267  } else
268  LHSKind = EmptyKind;
269 
270  assert(isValid() && "Invalid twine!");
271  }
272 
274  /*implicit*/ Twine(const std::string &Str) : LHSKind(StdStringKind) {
275  LHS.stdString = &Str;
276  assert(isValid() && "Invalid twine!");
277  }
278 
280  /*implicit*/ Twine(const StringRef &Str) : LHSKind(StringRefKind) {
281  LHS.stringRef = &Str;
282  assert(isValid() && "Invalid twine!");
283  }
284 
286  /*implicit*/ Twine(const SmallVectorImpl<char> &Str)
287  : LHSKind(SmallStringKind) {
288  LHS.smallString = &Str;
289  assert(isValid() && "Invalid twine!");
290  }
291 
293  explicit Twine(char Val) : LHSKind(CharKind) {
294  LHS.character = Val;
295  }
296 
298  explicit Twine(signed char Val) : LHSKind(CharKind) {
299  LHS.character = static_cast<char>(Val);
300  }
301 
303  explicit Twine(unsigned char Val) : LHSKind(CharKind) {
304  LHS.character = static_cast<char>(Val);
305  }
306 
308  explicit Twine(unsigned Val) : LHSKind(DecUIKind) {
309  LHS.decUI = Val;
310  }
311 
313  explicit Twine(int Val) : LHSKind(DecIKind) {
314  LHS.decI = Val;
315  }
316 
318  explicit Twine(const unsigned long &Val) : LHSKind(DecULKind) {
319  LHS.decUL = &Val;
320  }
321 
323  explicit Twine(const long &Val) : LHSKind(DecLKind) {
324  LHS.decL = &Val;
325  }
326 
328  explicit Twine(const unsigned long long &Val) : LHSKind(DecULLKind) {
329  LHS.decULL = &Val;
330  }
331 
333  explicit Twine(const long long &Val) : LHSKind(DecLLKind) {
334  LHS.decLL = &Val;
335  }
336 
337  // FIXME: Unfortunately, to make sure this is as efficient as possible we
338  // need extra binary constructors from particular types. We can't rely on
339  // the compiler to be smart enough to fold operator+()/concat() down to the
340  // right thing. Yet.
341 
343  /*implicit*/ Twine(const char *LHS, const StringRef &RHS)
344  : LHSKind(CStringKind), RHSKind(StringRefKind) {
345  this->LHS.cString = LHS;
346  this->RHS.stringRef = &RHS;
347  assert(isValid() && "Invalid twine!");
348  }
349 
351  /*implicit*/ Twine(const StringRef &LHS, const char *RHS)
352  : LHSKind(StringRefKind), RHSKind(CStringKind) {
353  this->LHS.stringRef = &LHS;
354  this->RHS.cString = RHS;
355  assert(isValid() && "Invalid twine!");
356  }
357 
360  Twine &operator=(const Twine &) = delete;
361 
364  static Twine createNull() {
365  return Twine(NullKind);
366  }
367 
371 
372  // Construct a twine to print \p Val as an unsigned hexadecimal integer.
373  static Twine utohexstr(const uint64_t &Val) {
374  Child LHS, RHS;
375  LHS.uHex = &Val;
376  RHS.twine = nullptr;
377  return Twine(LHS, UHexKind, RHS, EmptyKind);
378  }
379 
383 
385  bool isNull() const {
386  return getLHSKind() == NullKind;
387  }
388 
391  bool isTriviallyEmpty() const {
392  return isNullary();
393  }
394 
397  bool isSingleStringRef() const {
398  if (getRHSKind() != EmptyKind) return false;
399 
400  switch (getLHSKind()) {
401  case EmptyKind:
402  case CStringKind:
403  case StdStringKind:
404  case StringRefKind:
405  case SmallStringKind:
406  case CharKind:
407  return true;
408  default:
409  return false;
410  }
411  }
412 
416 
417  Twine concat(const Twine &Suffix) const;
418 
422 
424  std::string str() const;
425 
427  void toVector(SmallVectorImpl<char> &Out) const;
428 
432  assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
433  switch (getLHSKind()) {
434  default:
435  // unreachable("Out of sync with isSingleStringRef");
436  return StringRef();
437  case EmptyKind: return StringRef();
438  case CStringKind: return StringRef(LHS.cString);
439  case StdStringKind: return StringRef(*LHS.stdString);
440  case StringRefKind: return *LHS.stringRef;
441  case SmallStringKind:
442  return StringRef(LHS.smallString->data(), LHS.smallString->size());
443  case CharKind: return StringRef(&LHS.character, 1);
444  }
445  }
446 
451  if (isSingleStringRef())
452  return getSingleStringRef();
453  toVector(Out);
454  return StringRef(Out.data(), Out.size());
455  }
456 
463 
466  void print(raw_ostream &OS) const;
467 
469  void dump() const;
470 
472  void printRepr(raw_ostream &OS) const;
473 
475  void dumpRepr() const;
476 
478  };
479 
482 
483  inline Twine Twine::concat(const Twine &Suffix) const {
484  // Concatenation with null is null.
485  if (isNull() || Suffix.isNull())
486  return Twine(NullKind);
487 
488  // Concatenation with empty yields the other side.
489  if (isEmpty())
490  return Suffix;
491  if (Suffix.isEmpty())
492  return *this;
493 
494  // Otherwise we need to create a new node, taking care to fold in unary
495  // twines.
496  Child NewLHS, NewRHS;
497  NewLHS.twine = this;
498  NewRHS.twine = &Suffix;
499  NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
500  if (isUnary()) {
501  NewLHS = LHS;
502  NewLHSKind = getLHSKind();
503  }
504  if (Suffix.isUnary()) {
505  NewRHS = Suffix.LHS;
506  NewRHSKind = Suffix.getLHSKind();
507  }
508 
509  return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind);
510  }
511 
512  inline Twine operator+(const Twine &LHS, const Twine &RHS) {
513  return LHS.concat(RHS);
514  }
515 
518 
519  inline Twine operator+(const char *LHS, const StringRef &RHS) {
520  return Twine(LHS, RHS);
521  }
522 
525 
526  inline Twine operator+(const StringRef &LHS, const char *RHS) {
527  return Twine(LHS, RHS);
528  }
529 
530  inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) {
531  RHS.print(OS);
532  return OS;
533  }
534 
536 
537 } // end namespace wpi
538 
539 #ifdef _WIN32
540 #pragma warning(pop)
541 #endif
542 
543 #endif // LLVM_ADT_TWINE_H
wpi::Twine::Twine
Twine(const SmallVectorImpl< char > &Str)
Construct from a SmallString.
Definition: Twine.h:286
wpi::Twine::toStringRef
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition: Twine.h:450
wpi::Twine::dump
void dump() const
Dump the concatenated string represented by this twine to stderr.
wpi::Twine::Twine
Twine(const char *LHS, const StringRef &RHS)
Construct as the concatenation of a C string and a StringRef.
Definition: Twine.h:343
wpi::SmallVectorImpl< char >
wpi::Twine::operator=
Twine & operator=(const Twine &)=delete
Since the intended use of twines is as temporary objects, assignments when concatenating might cause ...
wpi::Twine::Twine
Twine(unsigned char Val)
Construct from an unsigned char.
Definition: Twine.h:303
wpi::Twine::Twine
Twine(signed char Val)
Construct from a signed char.
Definition: Twine.h:298
wpi::Twine::Twine
Twine()
Construct from an empty string.
Definition: Twine.h:252
wpi::Twine::isNull
bool isNull() const
Check for the null twine.
Definition: Twine.h:385
wpi::Twine::Twine
Twine(unsigned Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:308
wpi::Twine::createNull
static Twine createNull()
Create a 'null' string, which is an empty string that always concatenates to form another empty strin...
Definition: Twine.h:364
wpi
WPILib C++ utilities (wpiutil) namespace.
Definition: Endian.h:31
wpi::Twine::isSingleStringRef
bool isSingleStringRef() const
Return true if this twine can be dynamically accessed as a single StringRef value with getSingleStrin...
Definition: Twine.h:397
wpi::SmallVectorTemplateCommon::data
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:158
wpi::Twine::Twine
Twine(const char *Str)
Construct from a C string.
Definition: Twine.h:263
wpi::Twine::Twine
Twine(char Val)
Construct from a char.
Definition: Twine.h:293
wpi::Twine::toNullTerminatedStringRef
StringRef toNullTerminatedStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single null terminated StringRef if it can be represented as such.
wpi::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
wpi::Twine::Twine
Twine(const unsigned long &Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:318
wpi::Twine::printRepr
void printRepr(raw_ostream &OS) const
Write the representation of this twine to the stream OS.
wpi::Twine::Twine
Twine(const unsigned long long &Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:328
wpi::Twine::print
void print(raw_ostream &OS) const
Write the concatenated string represented by this twine to the stream OS.
wpi::Twine::Twine
Twine(const StringRef &Str)
Construct from a StringRef.
Definition: Twine.h:280
wpi::Twine::isTriviallyEmpty
bool isTriviallyEmpty() const
Check if this twine is trivially empty; a false return value does not necessarily mean the twine is e...
Definition: Twine.h:391
wpi::Twine::Twine
Twine(const std::string &Str)
Construct from an std::string.
Definition: Twine.h:274
wpi::Twine::str
std::string str() const
Return the twine contents as a std::string.
wpi::Twine::Twine
Twine(const long long &Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:333
wpi::Twine::dumpRepr
void dumpRepr() const
Dump the representation of this twine to stderr.
wpi::Twine::Twine
Twine(const long &Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:323
wpi::Twine::toVector
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
wpi::Twine::Twine
Twine(const StringRef &LHS, const char *RHS)
Construct as the concatenation of a StringRef and a C string.
Definition: Twine.h:351
wpi::Twine::getSingleStringRef
StringRef getSingleStringRef() const
This returns the twine as a single StringRef.
Definition: Twine.h:431
wpi::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:47
wpi::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:85
wpi::Twine::Twine
Twine(int Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:313