1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
//===--- PrefixMap.cpp - Out-of-line helpers for the PrefixMap structure --===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/PrefixMap.h"
#include "swift/Basic/QuotedString.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Compiler.h"
using namespace swift;
#if __has_attribute(may_alias) || LLVM_GNUC_PREREQ(3, 0, 0)
#define LLVM_MAY_ALIAS __attribute__((may_alias))
#else
#define LLVM_MAY_ALIAS
#endif
namespace {
enum class ChildKind { Left, Right, Further, Root };
// We'd like the dump routine to be present in all builds, but it's
// a pretty large amount of code, most of which is not sensitive to the
// actual key and value data. If we try to have a common implementation,
// we're left with the problem of describing the layout of a node when
// that's technically instantiation-specific. Redefining the struct here
// is technically an aliasing violation, but we can just tell the compilers
// that actually use TBAA that this is okay.
typedef struct _Node Node;
struct LLVM_MAY_ALIAS _Node {
// If you change the layout in the header, you'll need to change it here.
// (This comment is repeated there.)
Node *Left, *Right, *Further;
};
class TreePrinter {
llvm::raw_ostream &Out;
void (&PrintNodeData)(llvm::raw_ostream &out, void *node);
SmallString<40> Indent;
public:
TreePrinter(llvm::raw_ostream &out,
void (&printNodeData)(llvm::raw_ostream &out, void *node))
: Out(out), PrintNodeData(printNodeData) {}
struct IndentScope {
TreePrinter *Printer;
size_t OldLength;
IndentScope(TreePrinter *printer, StringRef indent)
: Printer(printer), OldLength(printer->Indent.size()) {
Printer->Indent += indent;
}
~IndentScope() { Printer->Indent.resize(OldLength); }
};
void print(Node *node, ChildKind childKind) {
// The top-level indents here create the line to the node we're
// trying to print.
if (node->Left) {
IndentScope ms(this, (childKind == ChildKind::Left ||
childKind == ChildKind::Root) ? " " : "| ");
print(node->Left, ChildKind::Left);
}
{
Out << Indent;
if (childKind == ChildKind::Root) {
Out << "+- ";
} else if (childKind == ChildKind::Left) {
Out << "/- ";
} else if (childKind == ChildKind::Right) {
Out << "\\- ";
} else if (childKind == ChildKind::Further) {
Out << "\\-> ";
}
PrintNodeData(Out, node);
Out << '\n';
}
if (node->Further || node->Right) {
IndentScope ms(this, (childKind == ChildKind::Right ||
childKind == ChildKind::Further ||
childKind == ChildKind::Root) ? " " : "| ");
if (node->Further) {
// Further indent, and include the line to the right child if
// there is one.
IndentScope is(this, node->Right ? "| " : " ");
print(node->Further, ChildKind::Further);
}
if (node->Right) {
print(node->Right, ChildKind::Right);
}
}
}
};
} // end anonymous namespace
void swift::printOpaquePrefixMap(raw_ostream &out, void *_root,
void (*printNodeData)(raw_ostream &out, void *node)) {
auto root = reinterpret_cast<Node*>(_root);
if (!root) {
out << "(empty)\n";
return;
}
TreePrinter(out, *printNodeData).print(root, ChildKind::Root);
}
void PrefixMapKeyPrinter<char>::print(raw_ostream &out, ArrayRef<char> key) {
out << QuotedString(StringRef(key.data(), key.size()));
}
void PrefixMapKeyPrinter<unsigned char>::print(raw_ostream &out,
ArrayRef<unsigned char> key) {
out << '\'';
for (auto byte : key) {
if (byte < 16) out << '0';
out.write_hex(byte);
}
out << '\'';
}
|