Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Support] Introduce llvm::formatv() function.
This introduces a new type-safe general purpose formatting library. It provides compile-time type safety, does not require a format specifier (since the type is deduced), and provides mechanisms for extending the format capability to user defined types, and overriding the formatting behavior for existing types. This patch additionally adds documentation for the API to the LLVM programmer's manual. Mailing List Thread: http://lists.llvm.org/pipermail/llvm-dev/2016-October/105836.html Differential Revision: https://reviews.llvm.org/D25587 llvm-svn: 286682
- Loading branch information
Zachary Turner
committed
Nov 11, 2016
1 parent
da6b572
commit 11db264
Showing
17 changed files
with
1,885 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
//===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_SUPPORT_FORMATADAPTERS_H | ||
#define LLVM_SUPPORT_FORMATADAPTERS_H | ||
|
||
#include "llvm/ADT/SmallString.h" | ||
#include "llvm/ADT/StringRef.h" | ||
#include "llvm/Support/FormatCommon.h" | ||
#include "llvm/Support/FormatVariadicDetails.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
namespace llvm { | ||
template <typename T> class AdapterBase { | ||
protected: | ||
explicit AdapterBase(T &&Item) : Item(Item) {} | ||
|
||
T Item; | ||
static_assert(!detail::uses_missing_provider<T>::value, | ||
"Item does not have a format provider!"); | ||
}; | ||
|
||
namespace detail { | ||
template <typename T> class AlignAdapter : public AdapterBase<T> { | ||
AlignStyle Where; | ||
size_t Amount; | ||
|
||
public: | ||
AlignAdapter(T &&Item, AlignStyle Where, size_t Amount) | ||
: AdapterBase(std::forward<T>(Item)), Where(Where), Amount(Amount) {} | ||
|
||
void format(llvm::raw_ostream &Stream, StringRef Style) { | ||
auto Wrapper = detail::build_format_wrapper(std::forward<T>(Item)); | ||
FmtAlign(Wrapper, Where, Amount).format(Stream, Style); | ||
} | ||
}; | ||
|
||
template <typename T> class PadAdapter : public AdapterBase<T> { | ||
size_t Left; | ||
size_t Right; | ||
|
||
public: | ||
PadAdapter(T &&Item, size_t Left, size_t Right) | ||
: AdapterBase(std::forward<T>(Item)), Left(Left), Right(Right) {} | ||
|
||
void format(llvm::raw_ostream &Stream, StringRef Style) { | ||
auto Wrapper = detail::build_format_wrapper(std::forward<T>(Item)); | ||
Stream.indent(Left); | ||
Wrapper.format(Stream, Style); | ||
Stream.indent(Right); | ||
} | ||
}; | ||
|
||
template <typename T> class RepeatAdapter : public AdapterBase<T> { | ||
size_t Count; | ||
|
||
public: | ||
RepeatAdapter(T &&Item, size_t Count) | ||
: AdapterBase(std::forward<T>(Item)), Count(Count) {} | ||
|
||
void format(llvm::raw_ostream &Stream, StringRef Style) { | ||
auto Wrapper = detail::build_format_wrapper(std::forward<T>(Item)); | ||
for (size_t I = 0; I < Count; ++I) { | ||
Wrapper.format(Stream, Style); | ||
} | ||
} | ||
}; | ||
} | ||
|
||
template <typename T> | ||
detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, size_t Amount) { | ||
return detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount); | ||
} | ||
|
||
template <typename T> | ||
detail::PadAdapter<T> fmt_pad(T &&Item, size_t Left, size_t Right) { | ||
return detail::PadAdapter<T>(std::forward<T>(Item), Left, Right); | ||
} | ||
|
||
template <typename T> | ||
detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) { | ||
return detail::RepeatAdapter<T>(std::forward<T>(Item), Count); | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_SUPPORT_FORMATCOMMON_H | ||
#define LLVM_SUPPORT_FORMATCOMMON_H | ||
|
||
#include "llvm/ADT/SmallString.h" | ||
#include "llvm/Support/FormatVariadicDetails.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
namespace llvm { | ||
enum class AlignStyle { Left, Center, Right }; | ||
|
||
struct FmtAlign { | ||
detail::format_wrapper &Wrapper; | ||
AlignStyle Where; | ||
size_t Amount; | ||
|
||
FmtAlign(detail::format_wrapper &Wrapper, AlignStyle Where, size_t Amount) | ||
: Wrapper(Wrapper), Where(Where), Amount(Amount) {} | ||
|
||
void format(raw_ostream &S, StringRef Options) { | ||
// If we don't need to align, we can format straight into the underlying | ||
// stream. Otherwise we have to go through an intermediate stream first | ||
// in order to calculate how long the output is so we can align it. | ||
// TODO: Make the format method return the number of bytes written, that | ||
// way we can also skip the intermediate stream for left-aligned output. | ||
if (Amount == 0) { | ||
Wrapper.format(S, Options); | ||
return; | ||
} | ||
SmallString<64> Item; | ||
raw_svector_ostream Stream(Item); | ||
|
||
Wrapper.format(Stream, Options); | ||
if (Amount <= Item.size()) { | ||
S << Item; | ||
return; | ||
} | ||
|
||
size_t PadAmount = Amount - Item.size(); | ||
switch (Where) { | ||
case AlignStyle::Left: | ||
S << Item; | ||
S.indent(PadAmount); | ||
break; | ||
case AlignStyle::Center: { | ||
size_t X = PadAmount / 2; | ||
S.indent(X); | ||
S << Item; | ||
S.indent(PadAmount - X); | ||
break; | ||
} | ||
default: | ||
S.indent(PadAmount); | ||
S << Item; | ||
break; | ||
} | ||
} | ||
}; | ||
} | ||
|
||
#endif |
Oops, something went wrong.