Index: llvm/trunk/docs/YamlIO.rst =================================================================== --- llvm/trunk/docs/YamlIO.rst +++ llvm/trunk/docs/YamlIO.rst @@ -798,6 +798,8 @@ static const bool flow = true; } +Flow mappings are subject to line wrapping according to the Output object +configuration. Sequence ======== @@ -845,6 +847,8 @@ structures, then when converted to YAML, a flow sequence of integers will be used (e.g. [ 10, -3, 4 ]). +Flow sequences are subject to line wrapping according to the Output object +configuration. Utility Macros -------------- @@ -908,14 +912,14 @@ The llvm::yaml::Output class is used to generate a YAML document from your in-memory data structures, using traits defined on your data types. -To instantiate an Output object you need an llvm::raw_ostream, and optionally -a context pointer: +To instantiate an Output object you need an llvm::raw_ostream, an optional +context pointer and an optional wrapping column: .. code-block:: c++ class Output : public IO { public: - Output(llvm::raw_ostream &, void *context=NULL); + Output(llvm::raw_ostream &, void *context = NULL, int WrapColumn = 70); Once you have an Output object, you can use the C++ stream operator on it to write your native data as YAML. One thing to recall is that a YAML file @@ -924,6 +928,10 @@ are generating one document and wraps the mapping output with "``---``" and trailing "``...``". +The WrapColumn parameter will cause the flow mappings and sequences to +line-wrap when they go over the supplied column. Pass 0 to completely +suppress the wrapping. + .. code-block:: c++ using llvm::yaml::Output; Index: llvm/trunk/include/llvm/Support/YAMLTraits.h =================================================================== --- llvm/trunk/include/llvm/Support/YAMLTraits.h +++ llvm/trunk/include/llvm/Support/YAMLTraits.h @@ -1114,7 +1114,7 @@ /// class Output : public IO { public: - Output(llvm::raw_ostream &, void *Ctxt=nullptr); + Output(llvm::raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); ~Output() override; bool outputting() override; @@ -1170,6 +1170,7 @@ }; llvm::raw_ostream &Out; + int WrapColumn; SmallVector StateStack; int Column; int ColumnAtFlowStart; Index: llvm/trunk/lib/Support/YAMLTraits.cpp =================================================================== --- llvm/trunk/lib/Support/YAMLTraits.cpp +++ llvm/trunk/lib/Support/YAMLTraits.cpp @@ -404,9 +404,10 @@ // Output //===----------------------------------------------------------------------===// -Output::Output(raw_ostream &yout, void *context) +Output::Output(raw_ostream &yout, void *context, int WrapColumn) : IO(context), Out(yout), + WrapColumn(WrapColumn), Column(0), ColumnAtFlowStart(0), ColumnAtMapFlowStart(0), @@ -529,7 +530,7 @@ bool Output::preflightFlowElement(unsigned, void *&) { if (NeedFlowSequenceComma) output(", "); - if (Column > 70) { + if (WrapColumn && Column > WrapColumn) { output("\n"); for (int i = 0; i < ColumnAtFlowStart; ++i) output(" "); @@ -720,7 +721,7 @@ void Output::flowKey(StringRef Key) { if (StateStack.back() == inFlowMapOtherKey) output(", "); - if (Column > 70) { + if (WrapColumn && Column > WrapColumn) { output("\n"); for (int I = 0; I < ColumnAtMapFlowStart; ++I) output(" "); Index: llvm/trunk/unittests/Support/YAMLIOTest.cpp =================================================================== --- llvm/trunk/unittests/Support/YAMLIOTest.cpp +++ llvm/trunk/unittests/Support/YAMLIOTest.cpp @@ -2074,3 +2074,123 @@ EXPECT_FALSE(yin.error()); EXPECT_TRUE(seq.empty()); } + +struct FlowMap { + llvm::StringRef str1, str2, str3; + FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3) + : str1(str1), str2(str2), str3(str3) {} +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, FlowMap &fm) { + io.mapRequired("str1", fm.str1); + io.mapRequired("str2", fm.str2); + io.mapRequired("str3", fm.str3); + } + + static const bool flow = true; + }; +} +} + +struct FlowSeq { + llvm::StringRef str; + FlowSeq(llvm::StringRef S) : str(S) {} + FlowSeq() = default; +}; + +template <> +struct ScalarTraits { + static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) { + out << value.str; + } + static StringRef input(StringRef scalar, void*, FlowSeq &value) { + value.str = scalar; + return ""; + } + + static bool mustQuote(StringRef S) { return false; } +}; + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq) + +TEST(YAMLIO, TestWrapFlow) { + std::string out; + llvm::raw_string_ostream ostr(out); + FlowMap Map("This is str1", "This is str2", "This is str3"); + std::vector Seq; + Seq.emplace_back("This is str1"); + Seq.emplace_back("This is str2"); + Seq.emplace_back("This is str3"); + + { + // 20 is just bellow the total length of the first mapping field. + // We should wreap at every element. + Output yout(ostr, nullptr, 15); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, \n" + " str2: This is str2, \n" + " str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, \n" + " This is str2, \n" + " This is str3 ]\n" + "...\n"); + out.clear(); + } + { + // 25 will allow the second field to be output on the first line. + Output yout(ostr, nullptr, 25); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, str2: This is str2, \n" + " str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, This is str2, \n" + " This is str3 ]\n" + "...\n"); + out.clear(); + } + { + // 0 means no wrapping. + Output yout(ostr, nullptr, 0); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, This is str2, This is str3 ]\n" + "...\n"); + out.clear(); + } +}