Improved validation - Wrong value and missing key errors...

...now show the direct line with key.
This commit is contained in:
Sytyi Nick 2011-08-18 20:12:02 +00:00
parent 7cfc66f39b
commit 0a46a7b8cb
4 changed files with 103 additions and 61 deletions

View file

@ -156,13 +156,13 @@ void parser::parse_element()
elname = tok_->current_token().value;
if (tok_->next_token().type != ']')
error(_("Unterminated [element] tag"));
// Add the element
current_element = &(elements.top().cfg->add_child(elname));
elements.push(element(current_element, elname, tok_->get_start_line(), tok_->get_file()));
if (validator_){
validator_->open_tag(elname,tok_->get_start_line(),
tok_->get_file());
}
// Add the element
current_element = &(elements.top().cfg->add_child(elname));
elements.push(element(current_element, elname, tok_->get_start_line(), tok_->get_file()));
break;
case '+': // [+element]
@ -176,12 +176,16 @@ void parser::parse_element()
// element
if (config &c = elements.top().cfg->child(elname, -1)) {
current_element = &c;
if (validator_){
validator_->open_tag(elname,tok_->get_start_line(),
tok_->get_file(),true);
}
} else {
current_element = &elements.top().cfg->add_child(elname);
}
if (validator_){
validator_->open_tag(elname,tok_->get_start_line(),
tok_->get_file());
current_element = &elements.top().cfg->add_child(elname);
if (validator_){
validator_->open_tag(elname,tok_->get_start_line(),
tok_->get_file());
}
}
elements.push(element(current_element, elname, tok_->get_start_line(), tok_->get_file()));
break;
@ -260,6 +264,11 @@ void parser::parse_variable()
cfg[*curvar] = t_string(buffer);
else
cfg[*curvar] = buffer.value();
if(validator_){
validator_->validate_key (cfg,*curvar,buffer.value(),
tok_->get_start_line (),
tok_->get_file ());
}
buffer = t_string_base();
++curvar;
} else {
@ -316,6 +325,11 @@ void parser::parse_variable()
cfg[*curvar] = t_string(buffer);
else
cfg[*curvar] = buffer.value();
if(validator_){
validator_->validate_key (cfg,*curvar,buffer.value(),
tok_->get_start_line (),
tok_->get_file ());
}
while (++curvar != variables.end()) {
cfg[*curvar] = "";
}

View file

@ -177,8 +177,10 @@ bool schema_validator::read_config_file(const std::string &filename){
* assume they all are on their place due to parser algorithm
* and validation logic
*/
void schema_validator::open_tag(const std::string & name,int start_line,
const std::string &file){
void schema_validator::open_tag(const std::string & name,
int start_line,
const std::string &file,
bool addittion){
if (! stack_.empty()){
const class_tag * tag = NULL;
if (stack_.top()){
@ -187,8 +189,10 @@ void schema_validator::open_tag(const std::string & name,int start_line,
wrong_tag_error(file,start_line,name,stack_.top()->get_name(),
create_exceptions_);
}else{
counter & cnt = counter_.top()[name];
++ cnt.cnt;
if (! addittion){
counter & cnt = counter_.top()[name];
++ cnt.cnt;
}
}
}
stack_.push(tag);
@ -205,10 +209,9 @@ void schema_validator::close_tag(){
//cache_ is cleared in another place.
}
bool schema_validator::validate(const config & cfg, const std::string & name,
void schema_validator::validate(const config & cfg, const std::string & name,
int start_line,
const std::string &file){
bool retval = false;
//close previous errors and print them to output.
message_map::iterator cache_it = cache_.top().begin();
for (;cache_it != cache_.top().end();++cache_it){
@ -224,35 +227,8 @@ bool schema_validator::validate(const config & cfg, const std::string & name,
cache_it->second.clear();
}
// Please note that validating unknown tag keys the result will be false
// Checking all elements counters.
if (!stack_.empty() && stack_.top() && config_read_){
retval = true;
// checking existing keys
foreach (const config::attribute & attr, cfg.attribute_range()){
const class_key * key =stack_.top()->find_key(attr.first);
if (key){
std::map<std::string,boost::regex>::iterator itt =
types_.find(key->get_type());
if (itt!= types_.end()){
boost::smatch sub;
bool res = boost::regex_match(attr.second.str(),
sub,itt->second);
if (!res ) {
cache_.top()[&cfg].push_back(
message_info(WRONG_VALUE,file,start_line,0,
stack_.top()->get_name(),
key->get_name(),
attr.second.str()));
}
}
}
else{
cache_.top()[&cfg].push_back(
message_info(EXTRA_KEY,file,start_line,0,name,
attr.first));
retval = false;
}
}
// Checking all elements counters.
class_tag::all_const_tag_iterators p = stack_.top()->tags();
for (class_tag::const_tag_iterator tag = p.first;
tag != p.second ; ++tag){
@ -261,14 +237,14 @@ bool schema_validator::validate(const config & cfg, const std::string & name,
cache_.top()[&cfg].push_back(
message_info(MISSING_TAG,file,start_line,
tag->second.get_min(),tag->first,"",
stack_.top()->get_name()));
name));
continue;
}
if (tag->second.get_max() < cnt){
cache_.top()[&cfg].push_back(
message_info(EXTRA_TAG,file,start_line,
tag->second.get_max(),tag->first,"",
stack_.top()->get_name()));
name));
}
}
// Checking if all mandatory keys are present
@ -279,12 +255,43 @@ bool schema_validator::validate(const config & cfg, const std::string & name,
if (cfg.get(key->first) == NULL){
cache_.top()[&cfg].push_back(
message_info(MISSING_KEY,file,start_line,0,
stack_.top()->get_name(),key->first ));
name,key->first ));
}
}
}
}
return retval;
}
void schema_validator::validate_key(const config & cfg,
const std::string & name,
const std::string & value,
int start_line,
const std::string &file){
if (!stack_.empty() && stack_.top() && config_read_){
// checking existing keys
const class_key * key =stack_.top()->find_key(name);
if (key){
std::map<std::string,boost::regex>::iterator itt =
types_.find(key->get_type());
if (itt != types_.end()){
boost::smatch sub;
bool res = boost::regex_match(value,sub,itt->second);
if (!res ) {
cache_.top()[&cfg].push_back(
message_info(WRONG_VALUE,file,start_line,0,
stack_.top()->get_name(),
name,value));
}
}
}
else{
cache_.top()[&cfg].push_back(
message_info(EXTRA_KEY,file,start_line,0,
stack_.top()->get_name(),name));
}
}
}
void schema_validator::print(message_info & el){

View file

@ -38,16 +38,20 @@ public:
create_exceptions_ = value;
}
/**
* Prints schema tree to stream
* Usually used to testing, whether schema config was read and expanded
*/
virtual void open_tag(const std::string & name,int start_line=0,
const std::string &file="");
virtual void open_tag(const std::string & name,
int start_line=0,
const std::string &file="",
bool addittion = false);
virtual void close_tag();
virtual bool validate(const config & cfg, const std::string & name,
int start_line, const std::string &file);
virtual void validate(const config & cfg,
const std::string & name,
int start_line,
const std::string &file);
virtual void validate_key(const config & cfg,
const std::string & name,
const std::string & value,
int start_line,
const std::string &file);
private:
// types section
// Just some magic to ensure zero initialization.

View file

@ -50,24 +50,41 @@ public:
* @param start_line Line in file
* @param file Name of file
*/
virtual void open_tag(const std::string & name,int start_line,
const std::string &file) = 0;
virtual void open_tag(const std::string & name,
int start_line,
const std::string &file,
bool addittion = false) = 0;
/**
* As far as parser is built on stack, some realizations can store stack
* too. So they need to know if tag was closed.
*/
virtual void close_tag() = 0;
/**
* Validates config
* Validates config. Checks if all mandatory elements are present.
* What exactly is validated depends on validator realization
* @param cfg Config to be validated.
* @param name Name of tag
* @param start_line Line in file
* @param file Name of file
*/
virtual bool validate(const config & cfg, const std::string & name,
int start_line,
const std::string &file) = 0;
virtual void validate(const config & cfg,
const std::string & name,
int start_line,
const std::string &file) = 0;
/**
* Checks if key is allowed and if its value is valid
* What exactly is validated depends on validator realization
* @param cfg Config to be validated.
* @param name Name of tag
* @param start_line Line in file
* @param file Name of file
*/
virtual void validate_key(const config & cfg,
const std::string & name,
const std::string & value,
int start_line,
const std::string &file) = 0;
/**
* @struct error
* Used to manage with not initialized validators