llvm.org GIT mirror llvm / 4e7c22a
Add simple support for tags in YAML I/O git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194644 91177308-0d34-0410-b5e6-96231b3b80d8 Nick Kledzik 5 years ago
4 changed file(s) with 121 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
632632 };
633633
634634
635 Tags
636 ----
637
638 The YAML syntax supports tags as a way to specify the type of a node before
639 it is parsed. This allows dynamic types of nodes. But the YAML I/O model uses
640 static typing, so there are limits to how you can use tags with the YAML I/O
641 model. Recently, we added support to YAML I/O for checking/setting the optional
642 tag on a map. Using this functionality it is even possbile to support differnt
643 mappings, as long as they are convertable.
644
645 To check a tag, inside your mapping() method you can use io.mapTag() to specify
646 what the tag should be. This will also add that tag when writing yaml.
647
648
635649 Sequence
636650 ========
637651
329329 virtual void postflightFlowElement(void*) = 0;
330330 virtual void endFlowSequence() = 0;
331331
332 virtual bool mapTag(StringRef Tag, bool Default=false) = 0;
332333 virtual void beginMapping() = 0;
333334 virtual void endMapping() = 0;
334335 virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0;
403404 void mapOptional(const char* Key, T& Val, const T& Default) {
404405 this->processKeyWithDefault(Key, Val, Default, false);
405406 }
406
407
407
408408 private:
409409 template
410410 void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue,
695695
696696 private:
697697 virtual bool outputting();
698 virtual bool mapTag(StringRef, bool);
698699 virtual void beginMapping();
699700 virtual void endMapping();
700701 virtual bool preflightKey(const char *, bool, bool, bool &, void *&);
818819 virtual ~Output();
819820
820821 virtual bool outputting();
822 virtual bool mapTag(StringRef, bool);
821823 virtual void beginMapping();
822824 virtual void endMapping();
823825 virtual bool preflightKey(const char *key, bool, bool, bool &, void *&);
7979
8080 void Input::nextDocument() {
8181 ++DocIterator;
82 }
83
84 bool Input::mapTag(StringRef Tag, bool Default) {
85 StringRef foundTag = CurrentNode->_node->getVerbatimTag();
86 if (foundTag.empty()) {
87 // If no tag found and 'Tag' is the default, say it was found.
88 return Default;
89 }
90 // Return true iff found tag matches supplied tag.
91 return Tag.equals(foundTag);
8292 }
8393
8494 void Input::beginMapping() {
380390 NeedsNewLine = true;
381391 }
382392
393 bool Output::mapTag(StringRef Tag, bool Use) {
394 if (Use) {
395 this->output(" ");
396 this->output(Tag);
397 }
398 return Use;
399 }
400
383401 void Output::endMapping() {
384402 StateStack.pop_back();
385403 }
988988 }
989989 }
990990
991 //===----------------------------------------------------------------------===//
992 // Test document tags
993 //===----------------------------------------------------------------------===//
994
995 struct MyDouble {
996 MyDouble() : value(0.0) { }
997 MyDouble(double x) : value(x) { }
998 double value;
999 };
1000
1001 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble);
1002
1003
1004 namespace llvm {
1005 namespace yaml {
1006 template <>
1007 struct MappingTraits {
1008 static void mapping(IO &io, MyDouble &d) {
1009 if (io.mapTag("!decimal", true)) {
1010 mappingDecimal(io, d);
1011 } else if (io.mapTag("!fraction")) {
1012 mappingFraction(io, d);
1013 }
1014 }
1015 static void mappingDecimal(IO &io, MyDouble &d) {
1016 io.mapRequired("value", d.value);
1017 }
1018 static void mappingFraction(IO &io, MyDouble &d) {
1019 double num, denom;
1020 io.mapRequired("numerator", num);
1021 io.mapRequired("denominator", denom);
1022 // convert fraction to double
1023 d.value = num/denom;
1024 }
1025 };
1026 }
1027 }
1028
1029
1030 //
1031 // Test the reading of two different tagged yaml documents.
1032 //
1033 TEST(YAMLIO, TestTaggedDocuments) {
1034 std::vector docList;
1035 Input yin("--- !decimal\nvalue: 3.0\n"
1036 "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n");
1037 yin >> docList;
1038 EXPECT_FALSE(yin.error());
1039 EXPECT_EQ(docList.size(), 2UL);
1040 EXPECT_EQ(docList[0].value, 3.0);
1041 EXPECT_EQ(docList[1].value, 4.5);
1042 }
1043
1044
1045
1046 //
1047 // Test writing then reading back tagged documents
1048 //
1049 TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
1050 std::string intermediate;
1051 {
1052 MyDouble a(10.25);
1053 MyDouble b(-3.75);
1054 std::vector docList;
1055 docList.push_back(a);
1056 docList.push_back(b);
1057
1058 llvm::raw_string_ostream ostr(intermediate);
1059 Output yout(ostr);
1060 yout << docList;
1061 }
1062
1063 {
1064 Input yin(intermediate);
1065 std::vector docList2;
1066 yin >> docList2;
1067
1068 EXPECT_FALSE(yin.error());
1069 EXPECT_EQ(docList2.size(), 2UL);
1070 EXPECT_EQ(docList2[0].value, 10.25);
1071 EXPECT_EQ(docList2[1].value, -3.75);
1072 }
1073 }
1074
1075
9911076
9921077 //===----------------------------------------------------------------------===//
9931078 // Test error handling