1//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/Twine.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/Config/llvm-config.h"
12#include "llvm/Support/Debug.h"
13#include "llvm/Support/FormatVariadic.h"
14#include "llvm/Support/raw_ostream.h"
15using namespace llvm;
16
17std::string Twine::str() const {
18  // If we're storing only a std::string, just return it.
19  if (LHSKind == StdStringKind && RHSKind == EmptyKind)
20    return *LHS.stdString;
21
22  // If we're storing a formatv_object, we can avoid an extra copy by formatting
23  // it immediately and returning the result.
24  if (LHSKind == FormatvObjectKind && RHSKind == EmptyKind)
25    return LHS.formatvObject->str();
26
27  // Otherwise, flatten and copy the contents first.
28  SmallString<256> Vec;
29  return toStringRef(Vec).str();
30}
31
32void Twine::toVector(SmallVectorImpl<char> &Out) const {
33  raw_svector_ostream OS(Out);
34  print(OS);
35}
36
37StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const {
38  if (isUnary()) {
39    switch (getLHSKind()) {
40    case CStringKind:
41      // Already null terminated, yay!
42      return StringRef(LHS.cString);
43    case StdStringKind: {
44      const std::string *str = LHS.stdString;
45      return StringRef(str->c_str(), str->size());
46    }
47    default:
48      break;
49    }
50  }
51  toVector(Out);
52  Out.push_back(0);
53  Out.pop_back();
54  return StringRef(Out.data(), Out.size());
55}
56
57void Twine::printOneChild(raw_ostream &OS, Child Ptr,
58                          NodeKind Kind) const {
59  switch (Kind) {
60  case Twine::NullKind: break;
61  case Twine::EmptyKind: break;
62  case Twine::TwineKind:
63    Ptr.twine->print(OS);
64    break;
65  case Twine::CStringKind:
66    OS << Ptr.cString;
67    break;
68  case Twine::StdStringKind:
69    OS << *Ptr.stdString;
70    break;
71  case Twine::StringRefKind:
72    OS << *Ptr.stringRef;
73    break;
74  case Twine::SmallStringKind:
75    OS << *Ptr.smallString;
76    break;
77  case Twine::FormatvObjectKind:
78    OS << *Ptr.formatvObject;
79    break;
80  case Twine::CharKind:
81    OS << Ptr.character;
82    break;
83  case Twine::DecUIKind:
84    OS << Ptr.decUI;
85    break;
86  case Twine::DecIKind:
87    OS << Ptr.decI;
88    break;
89  case Twine::DecULKind:
90    OS << *Ptr.decUL;
91    break;
92  case Twine::DecLKind:
93    OS << *Ptr.decL;
94    break;
95  case Twine::DecULLKind:
96    OS << *Ptr.decULL;
97    break;
98  case Twine::DecLLKind:
99    OS << *Ptr.decLL;
100    break;
101  case Twine::UHexKind:
102    OS.write_hex(*Ptr.uHex);
103    break;
104  }
105}
106
107void Twine::printOneChildRepr(raw_ostream &OS, Child Ptr,
108                              NodeKind Kind) const {
109  switch (Kind) {
110  case Twine::NullKind:
111    OS << "null"; break;
112  case Twine::EmptyKind:
113    OS << "empty"; break;
114  case Twine::TwineKind:
115    OS << "rope:";
116    Ptr.twine->printRepr(OS);
117    break;
118  case Twine::CStringKind:
119    OS << "cstring:\""
120       << Ptr.cString << "\"";
121    break;
122  case Twine::StdStringKind:
123    OS << "std::string:\""
124       << Ptr.stdString << "\"";
125    break;
126  case Twine::StringRefKind:
127    OS << "stringref:\""
128       << Ptr.stringRef << "\"";
129    break;
130  case Twine::SmallStringKind:
131    OS << "smallstring:\"" << *Ptr.smallString << "\"";
132    break;
133  case Twine::FormatvObjectKind:
134    OS << "formatv:\"" << *Ptr.formatvObject << "\"";
135    break;
136  case Twine::CharKind:
137    OS << "char:\"" << Ptr.character << "\"";
138    break;
139  case Twine::DecUIKind:
140    OS << "decUI:\"" << Ptr.decUI << "\"";
141    break;
142  case Twine::DecIKind:
143    OS << "decI:\"" << Ptr.decI << "\"";
144    break;
145  case Twine::DecULKind:
146    OS << "decUL:\"" << *Ptr.decUL << "\"";
147    break;
148  case Twine::DecLKind:
149    OS << "decL:\"" << *Ptr.decL << "\"";
150    break;
151  case Twine::DecULLKind:
152    OS << "decULL:\"" << *Ptr.decULL << "\"";
153    break;
154  case Twine::DecLLKind:
155    OS << "decLL:\"" << *Ptr.decLL << "\"";
156    break;
157  case Twine::UHexKind:
158    OS << "uhex:\"" << Ptr.uHex << "\"";
159    break;
160  }
161}
162
163void Twine::print(raw_ostream &OS) const {
164  printOneChild(OS, LHS, getLHSKind());
165  printOneChild(OS, RHS, getRHSKind());
166}
167
168void Twine::printRepr(raw_ostream &OS) const {
169  OS << "(Twine ";
170  printOneChildRepr(OS, LHS, getLHSKind());
171  OS << " ";
172  printOneChildRepr(OS, RHS, getRHSKind());
173  OS << ")";
174}
175
176#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
177LLVM_DUMP_METHOD void Twine::dump() const {
178  print(dbgs());
179}
180
181LLVM_DUMP_METHOD void Twine::dumpRepr() const {
182  printRepr(dbgs());
183}
184#endif
185