33 template<
typename TConfig>
34 auto get_child_range(TConfig& cfg,
const std::string& key,
int start,
int count) -> decltype(cfg.child_range(key))
36 auto res = cfg.child_range(key);
43 void resolve_negative_value(
int size,
int&
val)
56 template<const variable_info_type vit>
64 while(static_cast<int>(cfg.child_count(key)) <=
index)
68 return cfg.child(key,
index);
72 const config empty_const_cfg;
86 return empty_const_cfg;
104 template <
typename TVal>
120 template <
typename TVisitor>
121 typename TVisitor::result_type apply_visitor(
const TVisitor& visitor,
typename TVisitor::param_type state)
126 return visitor.from_start(state);
128 return visitor.from_named(state);
130 return visitor.from_indexed(state);
132 return visitor.from_temporary(state);
134 throw std::range_error(
"Failed to convert the TVisitor::param_type type");
137 template <const variable_info_type vit,
typename TResult>
138 class variable_info_visitor
141 typedef TResult result_type;
143 #define DEFAULTHANDLER(name) result_type name(param_type) const { throw invalid_variablename_exception(); }
148 #undef DEFAULTHANDLER
151 template <const variable_info_type vit,
typename TResult>
152 class variable_info_visitor_const
155 typedef TResult result_type;
157 #define DEFAULTHANDLER(name) result_type name(param_type) const { throw invalid_variablename_exception(); }
162 #undef DEFAULTHANDLER
170 int parse_index(
const char* index_str)
173 int res = strtol(index_str, &endptr, 10);
183 template<const variable_info_type vit>
184 class get_variable_key_visitor
185 :
public variable_info_visitor<vit, void>
193 void from_named(
typename get_variable_key_visitor::param_type state)
const
197 state.temp_val_ = state.child_->child_count(state.key_);
203 return do_from_config(get_child_at<vit>(*state.child_, state.key_, 0), state);
206 void from_start(
typename get_variable_key_visitor::param_type state)
const
208 return do_from_config(*state.child_, state);
210 void from_indexed(
typename get_variable_key_visitor::param_type state)
const
213 return do_from_config(get_child_at<vit>(*state.child_, state.key_, state.index_), state);
227 template<const variable_info_type vit>
228 class get_variable_index_visitor
229 :
public variable_info_visitor<vit, void>
232 get_variable_index_visitor(
int n) : n_(n) {}
233 void from_named(
typename get_variable_index_visitor::param_type state)
const
236 resolve_negative_value(state.child_->child_count(state.key_), state.index_);
247 template<const variable_info_type vit>
248 class as_skalar_visitor
249 :
public variable_info_visitor_const<vit, typename maybe_const<vit, config::attribute_value>::type&>
252 typename as_skalar_visitor::result_type from_named(
typename as_skalar_visitor::param_type state)
const
254 return (*state.child_)[state.key_];
257 typename as_skalar_visitor::result_type from_temporary(
typename as_skalar_visitor::param_type state)
const;
262 const config::attribute_value & as_skalar_visitor<vit_const>::from_temporary(as_skalar_visitor::param_type state)
const
264 return state.temp_val_;
267 config::attribute_value & as_skalar_visitor<vit_create_if_not_existent>::from_temporary(as_skalar_visitor::param_type)
const
272 config::attribute_value & as_skalar_visitor<vit_throw_if_not_existent>::from_temporary(as_skalar_visitor::param_type)
const
279 template<const variable_info_type vit>
280 class as_container_visitor
281 :
public variable_info_visitor_const<vit, typename maybe_const<vit, config>::type&>
284 typename as_container_visitor::result_type from_named(
typename as_container_visitor::param_type state)
const
286 return get_child_at<vit>(*state.child_, state.key_, 0);
288 typename as_container_visitor::result_type from_start(
typename as_container_visitor::param_type state)
const
290 return *state.child_;
292 typename as_container_visitor::result_type from_indexed(
typename as_container_visitor::param_type state)
const
294 return get_child_at<vit>(*state.child_, state.key_, state.index_);
300 template<const variable_info_type vit>
301 class as_array_visitor
302 :
public variable_info_visitor_const<vit, typename maybe_const<vit, config::child_itors>::type>
305 typename as_array_visitor::result_type from_named(
typename as_array_visitor::param_type state)
const
307 return get_child_range(*state.child_, state.key_, 0, state.child_->child_count(state.key_));
309 typename as_array_visitor::result_type from_indexed(
typename as_array_visitor::param_type state)
const;
314 if (
int(state.child_->child_count(state.key_)) <= state.index_)
316 return get_child_range(non_empty_const_cfg,
"_", 0, 1);
320 return get_child_range(*state.child_, state.key_, state.index_, 1);
324 config::child_itors as_array_visitor<vit_create_if_not_existent>::from_indexed(as_array_visitor::param_type state)
const
327 get_child_at<vit_create_if_not_existent>(*state.child_, state.key_, state.index_);
328 return get_child_range(*state.child_, state.key_, state.index_, 1);
331 config::child_itors as_array_visitor<vit_throw_if_not_existent>::from_indexed(as_array_visitor::param_type state)
const
334 get_child_at<vit_throw_if_not_existent>(*state.child_, state.key_, state.index_);
335 return get_child_range(*state.child_, state.key_, state.index_, 1);
346 template<const variable_info_type vit,
typename THandler>
347 class as_range_visitor_base
348 :
public variable_info_visitor_const<vit, typename THandler::result_type>
351 as_range_visitor_base(
const THandler&
handler) : handler_(handler) {}
352 typename as_range_visitor_base::result_type from_named(
typename as_range_visitor_base::param_type state)
const
354 return handler_(*state.child_, state.key_, 0, state.child_->child_count(state.key_));
356 typename as_range_visitor_base::result_type from_indexed(
typename as_range_visitor_base::param_type state)
const
358 return this->handler_(*state.child_, state.key_, state.index_, state.index_ + 1);
362 const THandler& handler_;
369 class replace_range_h
373 replace_range_h(std::vector<config>&
source) : datasource_(source) { }
374 result_type operator()(
config& child,
const std::string& key,
int startindex,
int endindex)
const
376 assert(endindex - startindex >= 0);
382 get_child_at<vit_create_if_not_existent>(child, key, endindex - 1);
384 int size_diff = datasource_.size() - (endindex - startindex);
396 for(; index < datasource_.size(); ++
index)
398 child.
child(key, startindex + index).
swap(datasource_[index]);
400 return get_child_range(child, key, startindex, datasource_.size());
403 std::vector<config>& datasource_;
406 class insert_range_h : replace_range_h
410 insert_range_h(std::vector<config>&
source) : replace_range_h(source) { }
412 result_type operator()(
config& child,
const std::string& key,
int startindex,
int )
const
415 return replace_range_h::operator()(child, key, startindex, startindex);
419 class append_range_h : insert_range_h
423 append_range_h(std::vector<config>&
source) : insert_range_h(source) { }
428 return insert_range_h::operator()(child, key, inser_pos, inser_pos );
435 typedef void result_type;
436 merge_range_h(std::vector<config>&
source) : datasource_(source) { }
437 void operator()(
config& child,
const std::string& key,
int startindex,
int )
const
442 for(
int index = 0; index < startindex; ++
index)
447 for(
size_t index = 0; index < datasource_.size(); ++
index)
454 std::vector<config>& datasource_;
460 template<const variable_info_type vit>
461 class clear_value_visitor
462 :
public variable_info_visitor_const<vit, void>
465 clear_value_visitor(
bool only_tables) : only_tables_(only_tables) {}
466 void from_named(
typename clear_value_visitor::param_type state)
const
470 state.child_->remove_attribute(state.key_);
472 state.child_->clear_children(state.key_);
474 void from_indexed(
typename clear_value_visitor::param_type state)
const
476 state.child_->remove_child(state.key_, state.index_);
482 template<const variable_info_type vit>
483 class exists_as_container_visitor
484 :
public variable_info_visitor_const<vit, bool>
487 typename exists_as_container_visitor::result_type from_named(
typename exists_as_container_visitor::param_type state)
const
489 return state.child_->has_child(state.key_);
491 typename exists_as_container_visitor::result_type from_indexed(
typename exists_as_container_visitor::param_type state)
const
493 return state.child_->child_count(state.key_) >
static_cast<size_t>(state.index_);
495 typename exists_as_container_visitor::result_type from_start(
typename exists_as_container_visitor::param_type)
const
499 typename exists_as_container_visitor::result_type from_temporary(
typename exists_as_container_visitor::param_type)
const
506 template<const variable_info_type vit>
522 template<const variable_info_type vit>
527 template<const variable_info_type vit>
531 size_t previous_index = 0;
532 size_t name_size = this->name_.size();
533 for(
size_t loop_index = 0; loop_index < name_size; loop_index++)
535 switch(this->name_[loop_index])
544 apply_visitor(get_variable_key_visitor<vit>(this->name_.substr(previous_index, loop_index-previous_index)), this->state_);
545 previous_index = loop_index + 1;
549 apply_visitor(get_variable_index_visitor<vit>(parse_index(&this->name_[previous_index])), this->state_);
553 if(loop_index < this->name_.length() && this->name_[loop_index] !=
'.')
557 previous_index = loop_index + 1;
563 if(previous_index != this->name_.length() + 1)
567 apply_visitor(get_variable_key_visitor<vit>(this->name_.substr(previous_index)), this->state_);
571 template<const variable_info_type vit>
578 template<const variable_info_type vit>
582 return apply_visitor(as_skalar_visitor<vit>(), this->state_);
585 template<const variable_info_type vit>
589 return apply_visitor(as_container_visitor<vit>(), this->state_);
592 template<const variable_info_type vit>
596 return apply_visitor(as_array_visitor<vit>(), this->state_);
599 template<const variable_info_type vit>
611 return "Cannot resolve variablename '" + this->name_ +
"' for reading.";
617 return "Cannot resolve variablename '" + this->name_ +
"' for writing.";
623 return "Cannot resolve variablename '" + this->name_ +
"' for writing without creating new childs.";
626 template<const variable_info_type vit>
629 this->throw_on_invalid();
630 return apply_visitor(clear_value_visitor<vit>(only_tables), this->state_);
633 template<const variable_info_type vit>
636 this->throw_on_invalid();
637 return apply_visitor(as_range_visitor_base<vit,append_range_h>(append_range_h(childs)), this->state_);
640 template<const variable_info_type vit>
643 this->throw_on_invalid();
644 return apply_visitor(as_range_visitor_base<vit,insert_range_h>(insert_range_h(childs)), this->state_);
647 template<const variable_info_type vit>
650 this->throw_on_invalid();
651 return apply_visitor(as_range_visitor_base<vit,replace_range_h>(replace_range_h(childs)), this->state_);
654 template<const variable_info_type vit>
657 this->throw_on_invalid();
658 apply_visitor(as_range_visitor_base<vit,merge_range_h>(merge_range_h(childs)), this->state_);
661 template<const variable_info_type vit>
664 this->throw_on_invalid();
665 return (this->state_.type_ ==
state_temporary) || ((this->state_.type_ ==
state_named) && this->state_.child_->has_attribute(this->state_.key_));
667 template<const variable_info_type vit>
670 this->throw_on_invalid();
671 return apply_visitor(exists_as_container_visitor<vit>(), this->state_);
bool explicit_index() const
Doesn't throw.
variable_info_detail::maybe_const< vit, config::attribute_value >::type & as_scalar() const
might throw invalid_variablename_exception NOTE: If vit == vit_const, then the lifime of the returned...
#define DEFAULTHANDLER(name)
static thandler * handler
variable_info_detail::maybe_const< vit, config::child_itors >::type as_array() const
might throw invalid_variablename_exception
void merge_array(std::vector< config > childs) const
merges might throw invalid_variablename_exception
bool exists_as_container() const
might throw invalid_variablename_exception
void clear(bool only_tables=false) const
clears the vale this object points to if only_tables = true it will not clear attribute values...
Extends variable_info with methods that can only be applied if vit != vit_const.
config::child_itors replace_array(std::vector< config > childs) const
GLuint const GLfloat * val
std::pair< const_child_iterator, const_child_iterator > const_child_itors
Variant for storing WML attributes.
variable_info(const std::string &varname, t_config &vars)
Doesn't throw.
static bool valid_id(const std::string &id)
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
const size_t max_loop
The maximum number of hexes on a map and items in an array and also used as maximum in wml loops...
void remove_child(const std::string &key, unsigned index)
config & add_child(const std::string &key)
GLuint GLuint GLsizei count
variable_info_detail::maybe_const< vit, config >::type & as_container() const
might throw invalid_variablename_exception
std::pair< child_iterator, child_iterator > child_itors
Information on a WML variable.
unsigned child_count(const std::string &key) const
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
config::child_itors insert_array(std::vector< config > childs) const
std::string get_error_message() const
config::child_itors append_array(std::vector< config > childs) const
void throw_on_invalid() const
bool exists_as_attribute() const
might throw invalid_variablename_exception
A config object defines a single node in a WML file, with access to child nodes.
GLsizei const GLcharARB ** string
GLsizei GLsizei GLchar * source
config & add_child_at(const std::string &key, const config &val, unsigned index)