1 /* 2 Copyright (C) 2011 - 2018 by Sytyi Nick <nsytyi@gmail.com> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 #pragma once 16 17 #include "config_cache.hpp" 18 #include "serialization/parser.hpp" 19 #include "serialization/tag.hpp" 20 #include "serialization/validator.hpp" 21 22 #include <boost/regex.hpp> 23 24 #include <iostream> 25 #include <queue> 26 #include <stack> 27 #include <string> 28 29 class config; 30 31 /** @file 32 * One of the realizations of serialization/validator.hpp abstract validator. 33 */ 34 namespace schema_validation 35 { 36 /** 37 * Realization of serialization/validator.hpp abstract validator. 38 * Based on stack. Uses some stacks to store different info. 39 */ 40 class schema_validator : public abstract_validator 41 { 42 public: 43 virtual ~schema_validator(); 44 45 /** 46 * Initializes validator from file. 47 * Throws abstract_validator::error if any error. 48 */ 49 schema_validator(const std::string& filename); 50 set_create_exceptions(bool value)51 void set_create_exceptions(bool value) 52 { 53 create_exceptions_ = value; 54 } 55 56 virtual void open_tag( 57 const std::string& name, int start_line = 0, const std::string& file = "", bool addittion = false); 58 virtual void close_tag(); 59 virtual void validate(const config& cfg, const std::string& name, int start_line, const std::string& file); 60 virtual void validate_key(const config& cfg, 61 const std::string& name, 62 const std::string& value, 63 int start_line, 64 const std::string& file); 65 66 private: 67 // types section 68 // Just some magic to ensure zero initialization. 69 struct counter 70 { 71 int cnt; counterschema_validation::schema_validator::counter72 counter() 73 : cnt(0) 74 { 75 } 76 }; 77 78 /** Counters are mapped by tag name. */ 79 typedef std::map<std::string, counter> cnt_map; 80 81 /** And counter maps are organize in stack. */ 82 typedef std::stack<cnt_map> cnt_stack; 83 84 enum message_type { WRONG_TAG, EXTRA_TAG, MISSING_TAG, EXTRA_KEY, MISSING_KEY, WRONG_VALUE }; 85 // error_cache 86 87 /** 88 * Messages are cached. 89 * The reason is next: in file where [tag]...[/tag][+tag]...[/tag] 90 * config object will be validated each [/tag]. So message can be as wrong 91 * (when [+tag] section contains missed elements) as duplicated. 92 * 93 * Messages are mapped by config*. That ensures uniqueness. 94 * Also message-maps are organized in stack to avoid memory leaks. 95 */ 96 struct message_info 97 { 98 message_type type; 99 std::string file; 100 int line; 101 int n; 102 std::string tag; 103 std::string key; 104 std::string value; 105 message_infoschema_validation::schema_validator::message_info106 message_info(message_type t, 107 const std::string& file, 108 int line = 0, 109 int n = 0, 110 const std::string& tag = "", 111 const std::string& key = "", 112 const std::string& value = "") 113 : type(t) 114 , file(file) 115 , line(line) 116 , n(n) 117 , tag(tag) 118 , key(key) 119 , value(value) 120 { 121 } 122 }; 123 124 typedef std::deque<message_info> message_list; 125 typedef std::map<const config*, message_list> message_map; 126 127 void print(message_info&); 128 129 /** Reads config from input. */ 130 bool read_config_file(const std::string& filename); 131 132 /** Shows, if validator is initialized with schema file. */ 133 bool config_read_; 134 135 /** Controls the way to print errors. */ 136 bool create_exceptions_; 137 138 /** Root of schema information. */ 139 class_tag root_; 140 141 std::stack<const class_tag*> stack_; 142 143 /** Contains number of children. */ 144 cnt_stack counter_; 145 146 /** Caches error messages. */ 147 std::stack<message_map> cache_; 148 149 /** Type validators. */ 150 std::map<std::string, boost::regex> types_; 151 }; 152 } // namespace schema_validation{ 153