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