mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
132 lines
4.1 KiB
C++
132 lines
4.1 KiB
C++
//===--- 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 LLVM_MAY_ALIAS;
|
|
struct _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 << '\'';
|
|
}
|