YamlWrapper.h (4894B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <yaml.h> 5 #include "winget/Yaml.h" 6 #include "AppInstallerLanguageUtilities.h" 7 #include "AppInstallerSHA256.h" 8 9 #include <iostream> 10 #include <string_view> 11 #include <vector> 12 13 14 namespace AppInstaller::YAML::Wrapper 15 { 16 // A libyaml yaml_document_t. 17 // A parsed document, created by the Parser. 18 struct Document 19 { 20 // Initializes the document. 21 Document(bool init = false); 22 23 Document(const Document&) = delete; 24 Document& operator=(const Document&) = delete; 25 26 Document(Document&&) noexcept = default; 27 Document& operator=(Document&&) noexcept = delete; 28 29 ~Document(); 30 31 yaml_document_t* operator&() { return &m_document; } 32 33 // Indicates that the document should not be deleted, as 34 // it has been handed off to the emitter. 35 void Detach() { m_token = false; } 36 37 // Determines whether the document has a root node. 38 bool HasRoot(); 39 40 // Gets the root node of the document, if it has one. 41 Node GetRoot(); 42 43 // Adds a scalar node to the document. 44 int AddScalar(std::string_view value, ScalarStyle style = ScalarStyle::Any); 45 46 // Adds a sequence node to the document. 47 int AddSequence(); 48 49 // Adds a mapping node to the document. 50 int AddMapping(); 51 52 // Appends a node to the end of the sequence. 53 void AppendSequenceItem(int sequence, int item); 54 55 // Adds a pair to the mapping. 56 void AppendMappingPair(int mapping, int key, int value); 57 58 private: 59 // Gets the node referenced by the index. 60 yaml_node_t* GetNode(yaml_node_item_t index); 61 62 DestructionToken m_token; 63 yaml_document_t m_document; 64 }; 65 66 // A libyaml yaml_parser_t. 67 // The core parser construct for reading bytes directly. 68 struct Parser 69 { 70 Parser(std::string_view input); 71 Parser(std::istream& input, Utility::SHA256::HashBuffer* hashOut = nullptr); 72 73 Parser(const Parser&) = delete; 74 Parser& operator=(const Parser&) = delete; 75 76 Parser(Parser&&) noexcept = default; 77 Parser& operator=(Parser&&) noexcept = delete; 78 79 ~Parser(); 80 81 yaml_parser_t* operator&() { return &m_parser; } 82 83 // Loads the next document from the input, if one exists. 84 Document Load(); 85 86 // Retrieves the input that was used to create the parser with the correct encoding scheme. 87 const std::string& GetEncodedInput() const { return m_input; } 88 89 private: 90 // Determines the type of encoding in use, transforming the input as necessary. 91 void PrepareInput(); 92 93 DestructionToken m_token; 94 yaml_parser_t m_parser; 95 std::string m_input; 96 }; 97 98 // A libyaml yaml_event_t. 99 // The generic event type for. 100 struct Event 101 { 102 Event(const Event&) = delete; 103 Event& operator=(const Event&) = delete; 104 105 Event(Event&&) noexcept = default; 106 Event& operator=(Event&&) noexcept = delete; 107 108 ~Event(); 109 110 yaml_event_t* operator&() { return &m_event; } 111 112 // Indicates that the event should not be deleted, as 113 // it has been handed off to the emitter. 114 void Detach() { m_token = false; } 115 116 // Event creation functions. 117 static Event StreamStart(); 118 static Event StreamEnd(); 119 static Event DocumentStart(); 120 static Event DocumentEnd(); 121 static Event SequenceStart(); 122 static Event SequenceEnd(); 123 static Event MappingStart(); 124 static Event MappingEnd(); 125 126 private: 127 Event() = default; 128 129 DestructionToken m_token; 130 yaml_event_t m_event = {}; 131 }; 132 133 // A libyaml yaml_emitter_t. 134 // Allows YAML to be written out. 135 struct Emitter 136 { 137 Emitter(std::ostream& output); 138 139 Emitter(const Emitter&) = delete; 140 Emitter& operator=(const Emitter&) = delete; 141 142 Emitter(Emitter&&) noexcept = default; 143 Emitter& operator=(Emitter&&) noexcept = delete; 144 145 ~Emitter(); 146 147 yaml_emitter_t* operator&() { return &m_emitter; } 148 149 // Emits and event. 150 void Emit(Event& event); 151 void Emit(Event&& event); 152 153 // Dumps a document to the emitter. 154 void Dump(Document& document); 155 156 // Flushes the emitter. 157 void Flush(); 158 159 private: 160 static int StreamWriteHandler( 161 void* data, 162 unsigned char* buffer, 163 size_t size); 164 165 void ThrowError(); 166 167 DestructionToken m_token; 168 yaml_emitter_t m_emitter; 169 std::ostream* m_outputStream = nullptr; 170 }; 171 }