The Battle for Wesnoth  1.15.12+dev
type.cpp
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 /**
16  * @file
17  * Implementation of type.hpp.
18  */
19 
21 
22 #include "config.hpp"
23 #include <optional>
24 
25 namespace schema_validation
26 {
27 
28 std::shared_ptr<wml_type> wml_type::from_config(const config& cfg)
29 {
30  std::optional<config::const_child_itors> composite_range;
31  std::shared_ptr<wml_type> type;
32  if(cfg.has_child("union")) {
33  type = std::make_shared<wml_type_union>(cfg["name"]);
34  composite_range.emplace(cfg.child("union").child_range("type"));
35  } else if(cfg.has_child("intersection")) {
36  type = std::make_shared<wml_type_intersection>(cfg["name"]);
37  composite_range.emplace(cfg.child("intersection").child_range("type"));
38  } else if(cfg.has_child("list")) {
39  const config& list_cfg = cfg.child("list");
40  int list_min = list_cfg["min"].to_int();
41  int list_max = list_cfg["max"].str() == "infinite" ? -1 : list_cfg["max"].to_int(-1);
42  if(list_max < 0) list_max = INT_MAX;
43  type = std::make_shared<wml_type_list>(cfg["name"], list_cfg["split"].str("\\s*,\\s*"), list_min, list_max);
44  composite_range.emplace(list_cfg.child_range("element"));
45  } else if(cfg.has_attribute("value")) {
46  type = std::make_shared<wml_type_simple>(cfg["name"], cfg["value"]);
47  } else if(cfg.has_attribute("link")) {
48  type = std::make_shared<wml_type_alias>(cfg["name"], cfg["link"]);
49  }
50  if(composite_range) {
51  auto composite_type = std::dynamic_pointer_cast<wml_type_composite>(type);
52  for(const config& elem : *composite_range) {
53  composite_type->add_type(wml_type::from_config(elem));
54  }
55  }
56  return type;
57 }
58 
59 bool wml_type_simple::matches(const std::string& value, const map&) const
60 {
61  boost::smatch sub;
62  return boost::regex_match(value, sub, pattern_);
63 }
64 
65 bool wml_type_alias::matches(const std::string& value, const map& type_map) const
66 {
67  if(!cached_) {
68  auto it = type_map.find(link_);
69  if(it == type_map.end()) {
70  // TODO: Error message about the invalid type?
71  return false;
72  }
73  cached_ = it->second;
74  }
75  return cached_->matches(value, type_map);
76 }
77 
78 bool wml_type_union::matches(const std::string& value, const map& type_map) const
79 {
80  for(const auto& type : subtypes_) {
81  if(type->matches(value, type_map)) {
82  return true;
83  }
84  }
85  return false;
86 }
87 
88 bool wml_type_intersection::matches(const std::string& value, const map& type_map) const
89 {
90  for(const auto& type : subtypes_) {
91  if(!type->matches(value, type_map)) {
92  return false;
93  }
94  }
95  return true;
96 }
97 
98 bool wml_type_list::matches(const std::string& value, const map& type_map) const
99 {
100  boost::sregex_token_iterator it(value.begin(), value.end(), split_, -1), end;
101  int n = 0;
102  bool result = std::all_of(it, end, [this, &type_map, &n](const boost::ssub_match& match){
103  // Not sure if this is necessary?
104  if(!match.matched) return true;
105  n++;
106  return this->wml_type_union::matches(std::string(match.first, match.second), type_map);
107  });
108  return result && n >= min_ && n <= max_;
109 }
110 
111 } // namespace schema_validation
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:414
This file contains object "type", which is used to store information about types while annotation par...
bool has_attribute(config_key_type key) const
Definition: config.cpp:207
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
Definition: config.cpp:406
child_itors child_range(config_key_type key)
Definition: config.cpp:356
Definitions for the interface to Wesnoth Markup Language (WML).
std::map< std::string, ptr > map
Definition: type.hpp:41
static std::shared_ptr< wml_type > from_config(const config &cfg)
Definition: type.cpp:28
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:98
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:78
static const char * match(MatchState *ms, const char *s, const char *p)
Definition: lstrlib.cpp:567
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:88
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:65
static map_location::DIRECTION n
bool matches(const std::string &value, const map &type_map) const override
Definition: type.cpp:59
Stores information about a schema type.
Definition: type.hpp:74
void add_type(std::shared_ptr< wml_type > type)
Definition: type.hpp:79