The Battle for Wesnoth  1.15.2+dev
schema_validator.hpp
Go to the documentation of this file.
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"
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  */
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, bool validate_schema = false);
50 
51  void set_create_exceptions(bool value)
52  {
53  create_exceptions_ = value;
54  }
55 
56  virtual void open_tag(const std::string& name, const config& parent, int start_line = 0, const std::string& file = "", bool addition = false) override;
57  virtual void close_tag() override;
58  virtual void validate(const config& cfg, const std::string& name, int start_line, const std::string& file) override;
59  virtual void validate_key(const config& cfg, const std::string& name, const std::string& value, int start_line, const std::string& file) override;
60 
61 private:
62  // types section
63  // Just some magic to ensure zero initialization.
64  struct counter
65  {
66  int cnt;
68  : cnt(0)
69  {
70  }
71  };
72 
73  /** Counters are mapped by tag name. */
74  typedef std::map<std::string, counter> cnt_map;
75 
76  /** And counter maps are organize in stack. */
77  typedef std::stack<cnt_map> cnt_stack;
78 
79 protected:
81 private:
82  // error_cache
83 
84  /**
85  * Messages are cached.
86  * The reason is next: in file where [tag]...[/tag][+tag]...[/tag]
87  * config object will be validated each [/tag]. So message can be as wrong
88  * (when [+tag] section contains missed elements) as duplicated.
89  *
90  * Messages are mapped by config*. That ensures uniqueness.
91  * Also message-maps are organized in stack to avoid memory leaks.
92  */
93  struct message_info
94  {
96  std::string file;
97  int line;
98  int n;
99  std::string tag;
100  std::string key;
101  std::string value;
102 
103  message_info(message_type t, const std::string& file, int line = 0, int n = 0, const std::string& tag = "", const std::string& key = "", const std::string& value = "")
104  : type(t)
105  , file(file)
106  , line(line)
107  , n(n)
108  , tag(tag)
109  , key(key)
110  , value(value)
111  {
112  }
113  };
114 
115  typedef std::deque<message_info> message_list;
116  typedef std::map<const config*, message_list> message_map;
117 
118  void print(message_info&);
119 
120  /** Reads config from input. */
121  bool read_config_file(const std::string& filename);
122 
123  /** Shows, if validator is initialized with schema file. */
125 
126  /** Controls the way to print errors. */
128 
129  /** Root of schema information. */
131 
132  std::stack<const wml_tag*> stack_;
133 
134  /** Contains number of children. */
135  cnt_stack counter_;
136 
137  /** Caches error messages. */
138  std::stack<message_map> cache_;
139 
140  /** Type validators. */
142 
144 protected:
145  void queue_message(const config& cfg, message_type t, const std::string& file, int line = 0, int n = 0, const std::string& tag = "", const std::string& key = "", const std::string& value = "");
146  const wml_tag& active_tag() const;
147  std::string active_tag_path() const;
148  bool have_active_tag() const;
149  bool is_valid() const {return config_read_;}
150  wml_type::ptr find_type(const std::string& type) const;
151 };
152 
153 // A validator specifically designed for validating a schema
154 // In addition to the usual, it verifies that references within the schema are valid, for example via the [link] tag
156 {
157 public:
159  virtual void open_tag(const std::string& name, const config& parent, int start_line = 0, const std::string& file = "", bool addition = false) override;
160  virtual void close_tag() override;
161  virtual void validate(const config& cfg, const std::string& name, int start_line, const std::string& file) override;
162  virtual void validate_key(const config& cfg, const std::string& name, const std::string& value, int start_line, const std::string& file) override;
163 private:
164  struct reference {
165  reference(const std::string& value, const std::string& file, int line, const std::string& tag)
166  : value_(value)
167  , file_(file)
168  , tag_(tag)
169  , line_(line)
170  {}
171  std::string value_, file_, tag_;
172  int line_;
173  bool match(const std::set<std::string>& with);
174  bool can_find(const wml_tag& root, const config& cfg);
175  bool operator<(const reference& other) const;
176  };
177  std::string current_path() const;
178  std::set<std::string> defined_types_, defined_tag_paths_;
179  std::vector<reference> referenced_types_, referenced_tag_paths_;
180  std::stack<std::string> tag_stack_;
181  std::map<std::string, std::string> links_;
182  std::multimap<std::string, std::string> derivations_;
183  int type_nesting_, condition_nesting_;
184  bool tag_path_exists(const config& cfg, const reference& ref);
185 };
186 
187 } // namespace schema_validation{
std::stack< cnt_map > cnt_stack
And counter maps are organize in stack.
std::stack< const wml_tag * > stack_
bool create_exceptions_
Controls the way to print errors.
message_info(message_type t, const std::string &file, int line=0, int n=0, const std::string &tag="", const std::string &key="", const std::string &value="")
cnt_stack counter_
Contains number of children.
This file contains object "type", which is used to store information about types while annotation par...
std::multimap< std::string, std::string > derivations_
Stores information about tag.
Definition: tag.hpp:46
std::deque< message_info > message_list
This file contains information about validation abstract level interface.
std::map< const config *, message_list > message_map
wml_tag root_
Root of schema information.
std::map< std::string, ptr > map
Definition: type.hpp:41
bool config_read_
Shows, if validator is initialized with schema file.
This file contains object "tag", which is used to store information about tags while annotation parsi...
Used in parsing config file.
Definition: validator.hpp:35
std::stack< message_map > cache_
Caches error messages.
wml_type::map types_
Type validators.
void queue_message(const config &cfg, message_type t, const std::string &file, int line=0, int n=0, const std::string &tag="", const std::string &key="", const std::string &value="")
schema_validator(const std::string &filename, bool validate_schema=false)
Initializes validator from file.
bool read_config_file(const std::string &filename)
Reads config from input.
static bool operator<(const placing_info &a, const placing_info &b)
Definition: game_state.cpp:138
virtual void close_tag() override
As far as parser is built on stack, some realizations can store stack too.
std::shared_ptr< wml_type > ptr
Definition: type.hpp:40
This file contains object "key", which is used to store information about keys while annotation parsi...
double t
Definition: astarsearch.cpp:64
virtual void open_tag(const std::string &name, const config &parent, int start_line=0, const std::string &file="", bool addition=false) override
Is called when parser opens tag.
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:425
Realization of serialization/validator.hpp abstract validator.
wml_type::ptr find_type(const std::string &type) const
std::map< std::string, counter > cnt_map
Counters are mapped by tag name.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
reference(const std::string &value, const std::string &file, int line, const std::string &tag)
virtual void validate_key(const config &cfg, const std::string &name, const std::string &value, int start_line, const std::string &file) override
Checks if key is allowed and if its value is valid What exactly is validated depends on validator rea...
static map_location::DIRECTION n
virtual void validate(const config &cfg, const std::string &name, int start_line, const std::string &file) override
Validates config.
std::map< std::string, std::string > links_