1 /* 2 mkvmerge -- utility for splicing together matroska files 3 from component media subtypes 4 5 Distributed under the GPL v2 6 see the file COPYING for details 7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html 8 9 XML helper functions 10 11 Written by Moritz Bunkus <moritz@bunkus.org>. 12 */ 13 14 #pragma once 15 16 #include "common/common_pch.h" 17 18 #include "pugixml.hpp" 19 20 namespace mtx::xml { 21 22 class exception: public mtx::exception { 23 public: what()24 virtual const char *what() const throw() { 25 return "generic XML error"; 26 } 27 }; 28 29 class conversion_x: public exception { 30 protected: 31 std::string m_message; 32 public: conversion_x(std::string const & message)33 conversion_x(std::string const &message) : m_message{message} { } ~conversion_x()34 virtual ~conversion_x() throw() { } 35 what()36 virtual char const *what() const throw() { 37 return m_message.c_str(); 38 } 39 }; 40 41 class invalid_attribute_x: public exception { 42 protected: 43 std::string m_message, m_node, m_attribute; 44 ptrdiff_t m_position; 45 public: invalid_attribute_x(std::string const & node,std::string const & attribute,ptrdiff_t position)46 invalid_attribute_x(std::string const &node, std::string const &attribute, ptrdiff_t position) 47 : m_node(node) 48 , m_attribute(attribute) 49 , m_position(position) 50 { 51 m_message = fmt::format(Y("Invalid attribute '{0}' in node '{1}' at position {2}"), m_attribute, m_node, m_position); 52 } ~invalid_attribute_x()53 virtual ~invalid_attribute_x() throw() { } 54 what()55 virtual char const *what() const throw() { 56 return m_message.c_str(); 57 } 58 }; 59 60 class invalid_child_node_x: public exception { 61 protected: 62 std::string m_message, m_node, m_parent; 63 ptrdiff_t m_position; 64 public: invalid_child_node_x(std::string const & node,std::string const & parent,ptrdiff_t position)65 invalid_child_node_x(std::string const &node, std::string const &parent, ptrdiff_t position) 66 : m_node(node) 67 , m_parent(parent) 68 , m_position(position) 69 { 70 m_message = fmt::format(Y("<{0}> is not a valid child element of <{1}> at position {2}."), m_node, m_parent, m_position); 71 } ~invalid_child_node_x()72 virtual ~invalid_child_node_x() throw() { } 73 what()74 virtual char const *what() const throw() { 75 return m_message.c_str(); 76 } 77 }; 78 79 class duplicate_child_node_x: public exception { 80 protected: 81 std::string m_message, m_node, m_parent; 82 ptrdiff_t m_position; 83 public: duplicate_child_node_x(std::string const & node,std::string const & parent,ptrdiff_t position)84 duplicate_child_node_x(std::string const &node, std::string const &parent, ptrdiff_t position) 85 : m_node(node) 86 , m_parent(parent) 87 , m_position(position) 88 { 89 m_message = fmt::format(Y("Only one instance of <{0}> is allowed beneath <{1}> at position {2}."), m_node, m_parent, m_position); 90 } ~duplicate_child_node_x()91 virtual ~duplicate_child_node_x() throw() { } 92 what()93 virtual char const *what() const throw() { 94 return m_message.c_str(); 95 } 96 }; 97 98 class malformed_data_x: public exception { 99 protected: 100 std::string m_message, m_node; 101 ptrdiff_t m_position; 102 public: 103 malformed_data_x(std::string const &node, ptrdiff_t position, std::string const &details = std::string{}) m_node(node)104 : m_node(node) 105 , m_position(position) 106 { 107 m_message = fmt::format(Y("The tag or attribute '{0}' at position {1} contains invalid or mal-formed data."), m_node, m_position); 108 if (!details.empty()) 109 m_message += " " + details; 110 } ~malformed_data_x()111 virtual ~malformed_data_x() throw() { } 112 what()113 virtual char const *what() const throw() { 114 return m_message.c_str(); 115 } 116 }; 117 118 class out_of_range_x: public exception { 119 protected: 120 std::string m_message, m_node; 121 ptrdiff_t m_position; 122 public: 123 out_of_range_x(std::string const &node, ptrdiff_t position, std::string const &details = std::string{}) m_node(node)124 : m_node(node) 125 , m_position(position) 126 { 127 m_message = fmt::format(Y("The tag or attribute '{0}' at position {1} contains data that is outside its allowed range."), m_node, m_position); 128 if (!details.empty()) 129 m_message += " " + details; 130 } ~out_of_range_x()131 virtual ~out_of_range_x() throw() { } 132 what()133 virtual char const *what() const throw() { 134 return m_message.c_str(); 135 } 136 }; 137 138 class xml_parser_x: public exception { 139 protected: 140 pugi::xml_parse_result m_result; 141 public: xml_parser_x(pugi::xml_parse_result const & result)142 xml_parser_x(pugi::xml_parse_result const &result) : m_result(result) { } what()143 virtual const char *what() const throw() { 144 return "XML parser error"; 145 } result()146 pugi::xml_parse_result const &result() { 147 return m_result; 148 } 149 }; 150 151 std::string escape(const std::string &src); 152 std::string create_node_name(const char *name, const char **atts); 153 154 using document_cptr = std::shared_ptr<pugi::xml_document>; 155 156 document_cptr load_file(std::string const &file_name, unsigned int options = pugi::parse_default, std::optional<int64_t> max_read_size = std::optional<int64_t>{}); 157 158 } 159