LLVM: lib/Support/JSON.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
17#include
18#include
19#include
20
21namespace llvm {
22namespace json {
23
25 return try_emplace(K, nullptr).first->getSecond();
26}
28 return try_emplace(std::move(K), nullptr).first->getSecond();
29}
33 return nullptr;
34 return &I->second;
35}
39 return nullptr;
40 return &I->second;
41}
43 if (auto *V = get(K))
44 return V->getAsNull();
45 return std::nullopt;
46}
48 if (auto *V = get(K))
49 return V->getAsBoolean();
50 return std::nullopt;
51}
53 if (auto *V = get(K))
54 return V->getAsNumber();
55 return std::nullopt;
56}
58 if (auto *V = get(K))
59 return V->getAsInteger();
60 return std::nullopt;
61}
63 if (auto *V = get(K))
64 return V->getAsString();
65 return std::nullopt;
66}
68 if (auto *V = get(K))
69 return V->getAsObject();
70 return nullptr;
71}
73 if (auto *V = get(K))
74 return V->getAsObject();
75 return nullptr;
76}
78 if (auto *V = get(K))
79 return V->getAsArray();
80 return nullptr;
81}
83 if (auto *V = get(K))
84 return V->getAsArray();
85 return nullptr;
86}
88 if (LHS.size() != RHS.size())
89 return false;
90 for (const auto &L : LHS) {
91 auto R = RHS.find(L.first);
92 if (R == RHS.end() || L.second != R->second)
93 return false;
94 }
95 return true;
96}
97
99 V.reserve(Elements.size());
100 for (const Value &V : Elements) {
102 back().moveFrom(std::move(V));
103 }
104}
105
108
109void Value::copyFrom(const Value &M) {
110 Type = M.Type;
111 switch (Type) {
112 case T_Null:
113 case T_Boolean:
114 case T_Double:
115 case T_Integer:
116 case T_UINT64:
117 memcpy(&Union, &M.Union, sizeof(Union));
118 break;
119 case T_StringRef:
120 create(M.as<StringRef>());
121 break;
122 case T_String:
123 createstd::string(M.asstd::string());
124 break;
125 case T_Object:
127 break;
128 case T_Array:
129 createjson::Array(M.as<json::Array>());
130 break;
131 }
132}
133
134void Value::moveFrom(const Value &&M) {
135 Type = M.Type;
136 switch (Type) {
137 case T_Null:
138 case T_Boolean:
139 case T_Double:
140 case T_Integer:
141 case T_UINT64:
142 memcpy(&Union, &M.Union, sizeof(Union));
143 break;
144 case T_StringRef:
145 create(M.as());
146 break;
147 case T_String:
148 createstd::string(std::move(M.asstd::string()));
149 M.Type = T_Null;
150 break;
151 case T_Object:
152 createjson::Object(std::move(M.asjson::Object()));
153 M.Type = T_Null;
154 break;
155 case T_Array:
156 createjson::Array(std::move(M.asjson::Array()));
157 M.Type = T_Null;
158 break;
159 }
160}
161
162void Value::destroy() {
163 switch (Type) {
164 case T_Null:
165 case T_Boolean:
166 case T_Double:
167 case T_Integer:
168 case T_UINT64:
169 break;
170 case T_StringRef:
171 as().~StringRef();
172 break;
173 case T_String:
174 asstd::string().~basic_string();
175 break;
176 case T_Object:
177 asjson::Object().~Object();
178 break;
179 case T_Array:
180 asjson::Array().~Array();
181 break;
182 }
183}
184
186 if (L.kind() != R.kind())
187 return false;
188 switch (L.kind()) {
190 return *L.getAsNull() == *R.getAsNull();
192 return *L.getAsBoolean() == *R.getAsBoolean();
194
195
196
197
198 if (L.Type == Value::T_Integer || R.Type == Value::T_Integer)
199 return L.getAsInteger() == R.getAsInteger();
200 return *L.getAsNumber() == *R.getAsNumber();
202 return *L.getAsString() == *R.getAsString();
204 return *L.getAsArray() == *R.getAsArray();
206 return *L.getAsObject() == *R.getAsObject();
207 }
209}
210
212
213 unsigned Count = 0;
215 for (P = this; P->Parent != nullptr; P = P->Parent)
216 ++Count;
218
219 R->ErrorMessage = Msg;
220 R->ErrorPath.resize(Count);
221 auto It = R->ErrorPath.begin();
222 for (P = this; P->Parent != nullptr; P = P->Parent)
223 *It++ = P->Seg;
224}
225
227 std::string S;
229 OS << (ErrorMessage.empty() ? "invalid JSON contents" : ErrorMessage);
230 if (ErrorPath.empty()) {
231 if (!Name.empty())
232 OS << " when parsing " << Name;
233 } else {
234 OS << " at " << (Name.empty() ? "(root)" : Name);
235 for (const Path::Segment &S : llvm::reverse(ErrorPath)) {
236 if (S.isField())
237 OS << '.' << S.field();
238 else
239 OS << '[' << S.index() << ']';
240 }
241 }
243}
244
246 std::vector<const Object::value_type *> Elements;
247 for (const auto &E : O)
248 Elements.push_back(&E);
251 return L->first < R->first;
252 });
253 return Elements;
254}
255
256
257
258
260 switch (V.kind()) {
262 JOS.rawValue(V.getAsArray()->empty() ? "[]" : "[ ... ]");
263 break;
265 JOS.rawValue(V.getAsObject()->empty() ? "{}" : "{ ... }");
266 break;
269 if (S.size() < 40) {
271 } else {
273 Truncated.append("...");
274 JOS.value(Truncated);
275 }
276 break;
277 }
278 default:
280 }
281}
282
283
284
286 switch (V.kind()) {
289 for (const auto &I : *V.getAsArray())
291 });
292 break;
295 for (const auto *KV : sortedElements(*V.getAsObject())) {
296 JOS.attributeBegin(KV->first);
297 abbreviate(KV->second, JOS);
298 JOS.attributeEnd();
299 }
300 });
301 break;
302 default:
304 }
305}
306
309
310
311
312
314
315
316
317 auto HighlightCurrent = [&] {
318 std::string Comment = "error: ";
319 Comment.append(ErrorMessage.data(), ErrorMessage.size());
322 };
323 if (Path.empty())
324 return HighlightCurrent();
325 const Segment &S = Path.back();
326 if (S.isField()) {
327
329 const Object *O = V.getAsObject();
330 if (!O || !O->get(FieldName))
331 return HighlightCurrent();
336 Recurse(KV->second, Path.drop_back(), Recurse);
337 else
340 }
341 });
342 } else {
343
344 const Array *A = V.getAsArray();
345 if ( || S.index() >= A->size())
346 return HighlightCurrent();
348 unsigned Current = 0;
349 for (const auto &V : *A) {
350 if (Current++ == S.index())
351 Recurse(V, Path.drop_back(), Recurse);
352 else
354 }
355 });
356 }
357 };
358 PrintValue(R, ErrorPath, PrintValue);
359}
360
361namespace {
362
363class Parser {
364public:
366 : Start(JSON.begin()), P(JSON.begin()), End(JSON.end()) {}
367
368 bool checkUTF8() {
369 size_t ErrOffset;
371 return true;
372 P = Start + ErrOffset;
373 return parseError("Invalid UTF-8 sequence");
374 }
375
376 bool parseValue(Value &Out);
377
378 bool assertEnd() {
379 eatWhitespace();
381 return true;
382 return parseError("Text after end of document");
383 }
384
385 Error takeError() {
387 return std::move(*Err);
388 }
389
390private:
391 void eatWhitespace() {
392 while (P != End && (*P == ' ' || *P == '\r' || *P == '\n' || *P == '\t'))
393 ++P;
394 }
395
396
397 bool parseNumber(char First, Value &Out);
398 bool parseString(std::string &Out);
399 bool parseUnicode(std::string &Out);
400 bool parseError(const char *Msg);
401
402 char next() { return P == End ? 0 : *P++; }
403 char peek() { return P == End ? 0 : *P; }
404 static bool isNumber(char C) {
405 return C == '0' || C == '1' || C == '2' || C == '3' || C == '4' ||
406 C == '5' || C == '6' || C == '7' || C == '8' || C == '9' ||
407 C == 'e' || C == 'E' || C == '+' || C == '-' || C == '.';
408 }
409
410 std::optional Err;
411 const char *Start, *P, *End;
412};
413}
414
415bool Parser::parseValue(Value &Out) {
416 eatWhitespace();
418 return parseError("Unexpected EOF");
419 switch (char C = next()) {
420
421 case 'n':
422 Out = nullptr;
423 return (next() == 'u' && next() == 'l' && next() == 'l') ||
424 parseError("Invalid JSON value (null?)");
425 case 't':
426 Out = true;
427 return (next() == 'r' && next() == 'u' && next() == 'e') ||
428 parseError("Invalid JSON value (true?)");
429 case 'f':
430 Out = false;
431 return (next() == 'a' && next() == 'l' && next() == 's' && next() == 'e') ||
432 parseError("Invalid JSON value (false?)");
433 case '"': {
434 std::string S;
435 if (parseString(S)) {
436 Out = std::move(S);
437 return true;
438 }
439 return false;
440 }
441 case '[': {
443 Array &A = *Out.getAsArray();
444 eatWhitespace();
445 if (peek() == ']') {
446 ++P;
447 return true;
448 }
449 for (;;) {
450 A.emplace_back(nullptr);
451 if (!parseValue(A.back()))
452 return false;
453 eatWhitespace();
454 switch (next()) {
455 case ',':
456 eatWhitespace();
457 continue;
458 case ']':
459 return true;
460 default:
461 return parseError("Expected , or ] after array element");
462 }
463 }
464 }
465 case '{': {
467 Object &O = *Out.getAsObject();
468 eatWhitespace();
469 if (peek() == '}') {
470 ++P;
471 return true;
472 }
473 for (;;) {
474 if (next() != '"')
475 return parseError("Expected object key");
476 std::string K;
477 if (!parseString(K))
478 return false;
479 eatWhitespace();
480 if (next() != ':')
481 return parseError("Expected : after object key");
482 eatWhitespace();
483 if (!parseValue(O[std::move(K)]))
484 return false;
485 eatWhitespace();
486 switch (next()) {
487 case ',':
488 eatWhitespace();
489 continue;
490 case '}':
491 return true;
492 default:
493 return parseError("Expected , or } after object property");
494 }
495 }
496 }
497 default:
498 if (isNumber(C))
499 return parseNumber(C, Out);
500 return parseError("Invalid JSON value");
501 }
502}
503
504bool Parser::parseNumber(char First, Value &Out) {
505
506 SmallString<24> S;
507 S.push_back(First);
508 while (isNumber(peek()))
509 S.push_back(next());
510 char *End;
511
512
513
514 errno = 0;
515 int64_t I = std::strtoll(S.c_str(), &End, 10);
516 if (End == S.end() && errno != ERANGE) {
517 Out = int64_t(I);
518 return true;
519 }
520
521
522
523 if (First != '-') {
524 errno = 0;
525 uint64_t UI = std::strtoull(S.c_str(), &End, 10);
526 if (End == S.end() && errno != ERANGE) {
527 Out = UI;
528 return true;
529 }
530 }
531
532 Out = std::strtod(S.c_str(), &End);
533 return End == S.end() || parseError("Invalid JSON value (number?)");
534}
535
536bool Parser::parseString(std::string &Out) {
537
538 for (char C = next(); C != '"'; C = next()) {
540 return parseError("Unterminated string");
542 return parseError("Control character in string");
544 Out.push_back(C);
545 continue;
546 }
547
548 switch (C = next()) {
549 case '"':
550 case '\\':
551 case '/':
552 Out.push_back(C);
553 break;
554 case 'b':
555 Out.push_back('\b');
556 break;
557 case 'f':
558 Out.push_back('\f');
559 break;
560 case 'n':
561 Out.push_back('\n');
562 break;
563 case 'r':
564 Out.push_back('\r');
565 break;
566 case 't':
567 Out.push_back('\t');
568 break;
569 case 'u':
570 if (!parseUnicode(Out))
571 return false;
572 break;
573 default:
574 return parseError("Invalid escape sequence");
575 }
576 }
577 return true;
578}
579
581 if (Rune < 0x80) {
582 Out.push_back(Rune & 0x7F);
583 } else if (Rune < 0x800) {
584 uint8_t FirstByte = 0xC0 | ((Rune & 0x7C0) >> 6);
585 uint8_t SecondByte = 0x80 | (Rune & 0x3F);
586 Out.push_back(FirstByte);
587 Out.push_back(SecondByte);
588 } else if (Rune < 0x10000) {
589 uint8_t FirstByte = 0xE0 | ((Rune & 0xF000) >> 12);
590 uint8_t SecondByte = 0x80 | ((Rune & 0xFC0) >> 6);
591 uint8_t ThirdByte = 0x80 | (Rune & 0x3F);
592 Out.push_back(FirstByte);
593 Out.push_back(SecondByte);
594 Out.push_back(ThirdByte);
595 } else if (Rune < 0x110000) {
596 uint8_t FirstByte = 0xF0 | ((Rune & 0x1F0000) >> 18);
597 uint8_t SecondByte = 0x80 | ((Rune & 0x3F000) >> 12);
598 uint8_t ThirdByte = 0x80 | ((Rune & 0xFC0) >> 6);
599 uint8_t FourthByte = 0x80 | (Rune & 0x3F);
600 Out.push_back(FirstByte);
601 Out.push_back(SecondByte);
602 Out.push_back(ThirdByte);
603 Out.push_back(FourthByte);
604 } else {
606 }
607}
608
609
610
611
612
613bool Parser::parseUnicode(std::string &Out) {
614
615 auto Invalid = [&] { Out.append( {'\xef', '\xbf', '\xbd'}); };
616
617 auto Parse4Hex = [this](uint16_t &Out) -> bool {
618 Out = 0;
619 char Bytes[] = {next(), next(), next(), next()};
620 for (unsigned char C : Bytes) {
621 if (!std::isxdigit(C))
622 return parseError("Invalid \\u escape sequence");
623 Out <<= 4;
624 Out |= (C > '9') ? (C & ~0x20) - 'A' + 10 : (C - '0');
625 }
626 return true;
627 };
629 if (!Parse4Hex(First))
630 return false;
631
632
633 while (true) {
634
635 if (LLVM_LIKELY(First < 0xD800 || First >= 0xE000)) {
637 return true;
638 }
639
640
643 return true;
644 }
645
646
647
649 Invalid();
650 return true;
651 }
652 P += 2;
654 if (!Parse4Hex(Second))
655 return false;
656
657 if (LLVM_UNLIKELY(Second < 0xDC00 || Second >= 0xE000)) {
658 Invalid();
659 First = Second;
660 continue;
661 }
662
663 encodeUtf8(0x10000 | ((First - 0xD800) << 10) | (Second - 0xDC00), Out);
664 return true;
665 }
666}
667
668bool Parser::parseError(const char *Msg) {
669 int Line = 1;
670 const char *StartOfLine = Start;
671 for (const char *X = Start; X < P; ++X) {
672 if (*X == 0x0A) {
674 StartOfLine = X + 1;
675 }
676 }
677 Err.emplace(
678 std::make_unique(Msg, Line, P - StartOfLine, P - Start));
679 return false;
680}
681
683 Parser P(JSON);
685 if (P.checkUTF8())
687 if (P.assertEnd())
688 return std::move(E);
689 return P.takeError();
690}
692
694
696 return true;
697
700 return true;
701
702 if (ErrOffset)
703 *ErrOffset = Rest - Data;
704 return false;
705}
706
708
709 std::vector Codepoints(S.size());
710 const UTF8 *In8 = reinterpret_cast<const UTF8 *>(S.data());
711 UTF32 *Out32 = Codepoints.data();
714 Codepoints.resize(Out32 - Codepoints.data());
715 std::string Res(4 * Codepoints.size(), 0);
716 const UTF32 *In32 = Codepoints.data();
717 UTF8 *Out8 = reinterpret_cast<UTF8 *>(&Res[0]);
718 ConvertUTF32toUTF8(&In32, In32 + Codepoints.size(), &Out8, Out8 + Res.size(),
720 Res.resize(reinterpret_cast<char *>(Out8) - Res.data());
721 return Res;
722}
723
725 OS << '\"';
726 for (unsigned char C : S) {
727 if (C == 0x22 || C == 0x5C)
728 OS << '\\';
729 if (C >= 0x20) {
731 continue;
732 }
733 OS << '\\';
734 switch (C) {
735
736 case '\t':
737 OS << 't';
738 break;
739 case '\n':
740 OS << 'n';
741 break;
742 case '\r':
743 OS << 'r';
744 break;
745 default:
746 OS << 'u';
748 break;
749 }
750 }
751 OS << '\"';
752}
753
755 switch (V.kind()) {
757 valueBegin();
758 OS << "null";
759 return;
761 valueBegin();
762 OS << (*V.getAsBoolean() ? "true" : "false");
763 return;
765 valueBegin();
766 if (V.Type == Value::T_Integer)
767 OS << *V.getAsInteger();
768 else if (V.Type == Value::T_UINT64)
769 OS << *V.getAsUINT64();
770 else
771 OS << format("%.*g", std::numeric_limits::max_digits10,
772 *V.getAsNumber());
773 return;
775 valueBegin();
776 quote(OS, *V.getAsString());
777 return;
779 return array([&] {
780 for (const Value &E : *V.getAsArray())
782 });
784 return object([&] {
786 attribute(E->first, E->second);
787 });
788 }
789}
790
791void llvm::json::OStream::valueBegin() {
792 assert(Stack.back().Ctx != Object && "Only attributes allowed here");
793 if (Stack.back().HasValue) {
794 assert(Stack.back().Ctx != Singleton && "Only one value allowed here");
795 OS << ',';
796 }
797 if (Stack.back().Ctx == Array)
798 newline();
799 flushComment();
800 Stack.back().HasValue = true;
801}
802
804 assert(PendingComment.empty() && "Only one comment per value!");
805 PendingComment = Comment;
806}
807
808void OStream::flushComment() {
809 if (PendingComment.empty())
810 return;
811 OS << (IndentSize ? "/* " : "/*");
812
813 while (!PendingComment.empty()) {
814 auto Pos = PendingComment.find("*/");
816 OS << PendingComment;
817 PendingComment = "";
818 } else {
819 OS << PendingComment.take_front(Pos) << "* /";
820 PendingComment = PendingComment.drop_front(Pos + 2);
821 }
822 }
823 OS << (IndentSize ? " */" : "*/");
824
825 if (Stack.size() > 1 && Stack.back().Ctx == Singleton) {
826 if (IndentSize)
827 OS << ' ';
828 } else {
829 newline();
830 }
831}
832
833void llvm::json::OStream::newline() {
834 if (IndentSize) {
835 OS.write('\n');
836 OS.indent(Indent);
837 }
838}
839
841 valueBegin();
842 Stack.emplace_back();
843 Stack.back().Ctx = Array;
844 Indent += IndentSize;
845 OS << '[';
846}
847
850 Indent -= IndentSize;
851 if (Stack.back().HasValue)
852 newline();
853 OS << ']';
854 assert(PendingComment.empty());
855 Stack.pop_back();
856 assert(!Stack.empty());
857}
858
860 valueBegin();
861 Stack.emplace_back();
862 Stack.back().Ctx = Object;
863 Indent += IndentSize;
864 OS << '{';
865}
866
869 Indent -= IndentSize;
870 if (Stack.back().HasValue)
871 newline();
872 OS << '}';
873 assert(PendingComment.empty());
874 Stack.pop_back();
875 assert(!Stack.empty());
876}
877
880 if (Stack.back().HasValue)
881 OS << ',';
882 newline();
883 flushComment();
884 Stack.back().HasValue = true;
885 Stack.emplace_back();
886 Stack.back().Ctx = Singleton;
889 } else {
890 assert(false && "Invalid UTF-8 in attribute key");
892 }
893 OS.write(':');
894 if (IndentSize)
895 OS.write(' ');
896}
897
899 assert(Stack.back().Ctx == Singleton);
900 assert(Stack.back().HasValue && "Attribute must have a value");
901 assert(PendingComment.empty());
902 Stack.pop_back();
904}
905
907 valueBegin();
908 Stack.emplace_back();
909 Stack.back().Ctx = RawValue;
910 return OS;
911}
912
914 assert(Stack.back().Ctx == RawValue);
915 Stack.pop_back();
916}
917
918}
919}
920
923 unsigned IndentAmount = 0;
924 if (.empty() && Options.getAsInteger(10, IndentAmount))
925 llvm_unreachable("json::Value format options should be an integer");
927}
928
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
#define LLVM_LIKELY(EXPR)
Given that RA is a live value
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file supports working with JSON data.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool peek(struct InternalInstruction *insn, uint8_t &byte)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
static constexpr size_t npos
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An Array is a JSON array, which contains heterogeneous JSON values.
void emplace_back(Args &&...A)
json::OStream allows writing well-formed JSON without materializing all structures as json::Value ahe...
void object(Block Contents)
Emit an object whose elements are emitted in the provided Block.
void rawValue(llvm::function_ref< void(raw_ostream &)> Contents)
Emit an externally-serialized value.
void attributeBegin(llvm::StringRef Key)
raw_ostream & rawValueBegin()
void comment(llvm::StringRef)
Emit a JavaScript comment associated with the next printed value.
void array(Block Contents)
Emit an array whose elements are emitted in the provided Block.
void value(const Value &V)
Emit a self-contained value (number, string, vector etc).
ObjectKey is a used to capture keys in Object.
An Object is a JSON object, which maps strings to heterogenous JSON values.
std::optional< bool > getBoolean(StringRef K) const
Value & operator[](const ObjectKey &K)
std::optional< double > getNumber(StringRef K) const
const json::Object * getObject(StringRef K) const
std::optional< llvm::StringRef > getString(StringRef K) const
Storage::value_type value_type
std::optional< int64_t > getInteger(StringRef K) const
std::optional< std::nullptr_t > getNull(StringRef K) const
std::pair< iterator, bool > try_emplace(const ObjectKey &K, Ts &&... Args)
iterator find(StringRef K)
const json::Array * getArray(StringRef K) const
The root is the trivial Path to the root value.
void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
Error getError() const
Returns the last error reported, or else a generic error.
A "cursor" marking a position within a Value.
void report(llvm::StringLiteral Message)
Records that the value at the current path is invalid.
A Value is an JSON value of unknown type.
@ Number
Number values can store both int64s and doubles at full precision, depending on what they were constr...
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
static void abbreviateChildren(const Value &V, OStream &JOS)
static void abbreviate(const Value &V, OStream &JOS)
bool isUTF8(llvm::StringRef S, size_t *ErrOffset=nullptr)
Returns true if S is valid UTF-8, which is required for use as JSON.
std::vector< const Object::value_type * > sortedElements(const Object &O)
static void quote(llvm::raw_ostream &OS, llvm::StringRef S)
std::string fixUTF8(llvm::StringRef S)
Replaces invalid UTF-8 sequences in S with the replacement character (U+FFFD).
static void encodeUtf8(uint32_t Rune, std::string &Out)
This is an optimization pass for GlobalISel generic memory operations.
ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart, const UTF8 *sourceEnd, UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags)
Convert a partial UTF8 sequence to UTF32.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
ConversionResult ConvertUTF32toUTF8(const UTF32 **sourceStart, const UTF32 *sourceEnd, UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags)
Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd)