WPILibC++  unspecified
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 LLVM_ADT_TWINE_H
11 #define LLVM_ADT_TWINE_H
12 
13 #include "llvm/SmallVector.h"
14 #include "llvm/StringRef.h"
15 #include <cassert>
16 #include <string>
17 
18 #include <stdint.h>
19 
20 namespace llvm {
21  class raw_ostream;
22 
79  class Twine {
81  enum NodeKind : unsigned char {
84  NullKind,
85 
87  EmptyKind,
88 
90  TwineKind,
91 
93  CStringKind,
94 
96  StdStringKind,
97 
99  StringRefKind,
100 
102  SmallStringKind,
103 
105  CharKind,
106 
108  DecUIKind,
109 
111  DecIKind,
112 
115  DecULKind,
116 
118  DecLKind,
119 
122  DecULLKind,
123 
125  DecLLKind,
126 
129  UHexKind
130  };
131 
132  union Child
133  {
134  const Twine *twine;
135  const char *cString;
136  const std::string *stdString;
137  const StringRef *stringRef;
138  const SmallVectorImpl<char> *smallString;
139  char character;
140  unsigned int decUI;
141  int decI;
142  const unsigned long *decUL;
143  const long *decL;
144  const unsigned long long *decULL;
145  const long long *decLL;
146  const uint64_t *uHex;
147  };
148 
149  private:
152  Child LHS;
155  Child RHS;
157  NodeKind LHSKind;
159  NodeKind RHSKind;
160 
161  private:
163  explicit Twine(NodeKind Kind)
164  : LHSKind(Kind), RHSKind(EmptyKind) {
165  assert(isNullary() && "Invalid kind!");
166  }
167 
169  explicit Twine(const Twine &LHS, const Twine &RHS)
170  : LHSKind(TwineKind), RHSKind(TwineKind) {
171  this->LHS.twine = &LHS;
172  this->RHS.twine = &RHS;
173  assert(isValid() && "Invalid twine!");
174  }
175 
177  explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind)
178  : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) {
179  assert(isValid() && "Invalid twine!");
180  }
181 
184  Twine &operator=(const Twine &Other) = delete;
185 
187  bool isNull() const {
188  return getLHSKind() == NullKind;
189  }
190 
192  bool isEmpty() const {
193  return getLHSKind() == EmptyKind;
194  }
195 
197  bool isNullary() const {
198  return isNull() || isEmpty();
199  }
200 
202  bool isUnary() const {
203  return getRHSKind() == EmptyKind && !isNullary();
204  }
205 
207  bool isBinary() const {
208  return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
209  }
210 
213  bool isValid() const {
214  // Nullary twines always have Empty on the RHS.
215  if (isNullary() && getRHSKind() != EmptyKind)
216  return false;
217 
218  // Null should never appear on the RHS.
219  if (getRHSKind() == NullKind)
220  return false;
221 
222  // The RHS cannot be non-empty if the LHS is empty.
223  if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind)
224  return false;
225 
226  // A twine child should always be binary.
227  if (getLHSKind() == TwineKind &&
228  !LHS.twine->isBinary())
229  return false;
230  if (getRHSKind() == TwineKind &&
231  !RHS.twine->isBinary())
232  return false;
233 
234  return true;
235  }
236 
238  NodeKind getLHSKind() const { return LHSKind; }
239 
241  NodeKind getRHSKind() const { return RHSKind; }
242 
244  void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
245 
247  void printOneChildRepr(raw_ostream &OS, Child Ptr,
248  NodeKind Kind) const;
249 
250  public:
253 
255  /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) {
256  assert(isValid() && "Invalid twine!");
257  }
258 
259  Twine(const Twine &) = default;
260 
266  /*implicit*/ Twine(const char *Str)
267  : RHSKind(EmptyKind) {
268  if (Str[0] != '\0') {
269  LHS.cString = Str;
270  LHSKind = CStringKind;
271  } else
272  LHSKind = EmptyKind;
273 
274  assert(isValid() && "Invalid twine!");
275  }
276 
278  /*implicit*/ Twine(const std::string &Str)
279  : LHSKind(StdStringKind), RHSKind(EmptyKind) {
280  LHS.stdString = &Str;
281  assert(isValid() && "Invalid twine!");
282  }
283 
285  /*implicit*/ Twine(const StringRef &Str)
286  : LHSKind(StringRefKind), RHSKind(EmptyKind) {
287  LHS.stringRef = &Str;
288  assert(isValid() && "Invalid twine!");
289  }
290 
292  /*implicit*/ Twine(const SmallVectorImpl<char> &Str)
293  : LHSKind(SmallStringKind), RHSKind(EmptyKind) {
294  LHS.smallString = &Str;
295  assert(isValid() && "Invalid twine!");
296  }
297 
299  explicit Twine(char Val)
300  : LHSKind(CharKind), RHSKind(EmptyKind) {
301  LHS.character = Val;
302  }
303 
305  explicit Twine(signed char Val)
306  : LHSKind(CharKind), RHSKind(EmptyKind) {
307  LHS.character = static_cast<char>(Val);
308  }
309 
311  explicit Twine(unsigned char Val)
312  : LHSKind(CharKind), RHSKind(EmptyKind) {
313  LHS.character = static_cast<char>(Val);
314  }
315 
317  explicit Twine(unsigned Val)
318  : LHSKind(DecUIKind), RHSKind(EmptyKind) {
319  LHS.decUI = Val;
320  }
321 
323  explicit Twine(int Val)
324  : LHSKind(DecIKind), RHSKind(EmptyKind) {
325  LHS.decI = Val;
326  }
327 
329  explicit Twine(const unsigned long &Val)
330  : LHSKind(DecULKind), RHSKind(EmptyKind) {
331  LHS.decUL = &Val;
332  }
333 
335  explicit Twine(const long &Val)
336  : LHSKind(DecLKind), RHSKind(EmptyKind) {
337  LHS.decL = &Val;
338  }
339 
341  explicit Twine(const unsigned long long &Val)
342  : LHSKind(DecULLKind), RHSKind(EmptyKind) {
343  LHS.decULL = &Val;
344  }
345 
347  explicit Twine(const long long &Val)
348  : LHSKind(DecLLKind), RHSKind(EmptyKind) {
349  LHS.decLL = &Val;
350  }
351 
352  // FIXME: Unfortunately, to make sure this is as efficient as possible we
353  // need extra binary constructors from particular types. We can't rely on
354  // the compiler to be smart enough to fold operator+()/concat() down to the
355  // right thing. Yet.
356 
358  /*implicit*/ Twine(const char *LHS, const StringRef &RHS)
359  : LHSKind(CStringKind), RHSKind(StringRefKind) {
360  this->LHS.cString = LHS;
361  this->RHS.stringRef = &RHS;
362  assert(isValid() && "Invalid twine!");
363  }
364 
366  /*implicit*/ Twine(const StringRef &LHS, const char *RHS)
367  : LHSKind(StringRefKind), RHSKind(CStringKind) {
368  this->LHS.stringRef = &LHS;
369  this->RHS.cString = RHS;
370  assert(isValid() && "Invalid twine!");
371  }
372 
375  static Twine createNull() {
376  return Twine(NullKind);
377  }
378 
382 
383  // Construct a twine to print \p Val as an unsigned hexadecimal integer.
384  static Twine utohexstr(const uint64_t &Val) {
385  Child LHS, RHS;
386  LHS.uHex = &Val;
387  RHS.twine = nullptr;
388  return Twine(LHS, UHexKind, RHS, EmptyKind);
389  }
390 
394 
397  bool isTriviallyEmpty() const {
398  return isNullary();
399  }
400 
403  bool isSingleStringRef() const {
404  if (getRHSKind() != EmptyKind) return false;
405 
406  switch (getLHSKind()) {
407  case EmptyKind:
408  case CStringKind:
409  case StdStringKind:
410  case StringRefKind:
411  case SmallStringKind:
412  case CharKind:
413  return true;
414  default:
415  return false;
416  }
417  }
418 
422 
423  Twine concat(const Twine &Suffix) const;
424 
428 
430  std::string str() const;
431 
433  void toVector(SmallVectorImpl<char> &Out) const;
434 
438  assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
439  switch (getLHSKind()) {
440  default:
441  // unreachable("Out of sync with isSingleStringRef");
442  return StringRef();
443  case EmptyKind: return StringRef();
444  case CStringKind: return StringRef(LHS.cString);
445  case StdStringKind: return StringRef(*LHS.stdString);
446  case StringRefKind: return *LHS.stringRef;
447  case SmallStringKind:
448  return StringRef(LHS.smallString->data(), LHS.smallString->size());
449  case CharKind: return StringRef(&LHS.character, 1);
450  }
451  }
452 
457  if (isSingleStringRef())
458  return getSingleStringRef();
459  toVector(Out);
460  return StringRef(Out.data(), Out.size());
461  }
462 
469 
472  void print(raw_ostream &OS) const;
473 
475  void dump() const;
476 
478  void printRepr(raw_ostream &OS) const;
479 
481  void dumpRepr() const;
482 
484  };
485 
488 
489  inline Twine Twine::concat(const Twine &Suffix) const {
490  // Concatenation with null is null.
491  if (isNull() || Suffix.isNull())
492  return Twine(NullKind);
493 
494  // Concatenation with empty yields the other side.
495  if (isEmpty())
496  return Suffix;
497  if (Suffix.isEmpty())
498  return *this;
499 
500  // Otherwise we need to create a new node, taking care to fold in unary
501  // twines.
502  Child NewLHS, NewRHS;
503  NewLHS.twine = this;
504  NewRHS.twine = &Suffix;
505  NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
506  if (isUnary()) {
507  NewLHS = LHS;
508  NewLHSKind = getLHSKind();
509  }
510  if (Suffix.isUnary()) {
511  NewRHS = Suffix.LHS;
512  NewRHSKind = Suffix.getLHSKind();
513  }
514 
515  return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind);
516  }
517 
518  inline Twine operator+(const Twine &LHS, const Twine &RHS) {
519  return LHS.concat(RHS);
520  }
521 
524 
525  inline Twine operator+(const char *LHS, const StringRef &RHS) {
526  return Twine(LHS, RHS);
527  }
528 
531 
532  inline Twine operator+(const StringRef &LHS, const char *RHS) {
533  return Twine(LHS, RHS);
534  }
535 
536  inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) {
537  RHS.print(OS);
538  return OS;
539  }
540 
542 }
543 
544 #endif
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition: Twine.cpp:25
Twine(signed char Val)
Construct from a signed char.
Definition: Twine.h:305
Twine(const char *Str)
Construct from a C string.
Definition: Twine.h:266
bool isSingleStringRef() const
Return true if this twine can be dynamically accessed as a single StringRef value with getSingleStrin...
Definition: Twine.h:403
Twine(const unsigned long long &Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:341
Definition: Path.inc:31
Twine(const StringRef &LHS, const char *RHS)
Construct as the concatenation of a StringRef and a C string.
Definition: Twine.h:366
Twine(const SmallVectorImpl< char > &Str)
Construct from a SmallString.
Definition: Twine.h:292
void dump() const
Dump the concatenated string represented by this twine to stderr.
Definition: Twine.cpp:163
void dumpRepr() const
Dump the representation of this twine to stderr.
Definition: Twine.cpp:167
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:15
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
StringRef getSingleStringRef() const
This returns the twine as a single StringRef.
Definition: Twine.h:437
Twine(char Val)
Construct from a char.
Definition: Twine.h:299
Twine()
Construct from an empty string.
Definition: Twine.h:255
Twine(const long long &Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:347
void printRepr(raw_ostream &OS) const
Write the representation of this twine to the stream OS.
Definition: Twine.cpp:155
static Twine createNull()
Create a &#39;null&#39; string, which is an empty string that always concatenates to form another empty strin...
Definition: Twine.h:375
Twine(const StringRef &Str)
Construct from a StringRef.
Definition: Twine.h:285
Twine(unsigned char Val)
Construct from an unsigned char.
Definition: Twine.h:311
StringRef toStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single StringRef if it can be represented as such.
Definition: Twine.h:456
Twine(const std::string &Str)
Construct from an std::string.
Definition: Twine.h:278
Twine(int Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:323
Twine(unsigned Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:317
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:134
Twine(const long &Val)
Construct a twine to print Val as a signed decimal integer.
Definition: Twine.h:335
Twine(const char *LHS, const StringRef &RHS)
Construct as the concatenation of a C string and a StringRef.
Definition: Twine.h:358
StringRef toNullTerminatedStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single null terminated StringRef if it can be represented as such...
Definition: Twine.cpp:30
void print(raw_ostream &OS) const
Write the concatenated string represented by this twine to the stream OS.
Definition: Twine.cpp:150
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:397
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:33
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:42
Twine(const unsigned long &Val)
Construct a twine to print Val as an unsigned decimal integer.
Definition: Twine.h:329