Il semblerait que la validation des données soit l'une des tâches de base de la programmation, qui se rencontrera au début de l'apprentissage d'un langage avec "Hello world!", Et sous une forme ou une autre sera présente dans de nombreux projets matures. Cependant, Google ne donne toujours aucun résultat pertinent lorsqu'il tente de trouver une bibliothèque de validation de données C ++ générique open source.
Dans le meilleur des cas, il existe soit des outils pour vérifier le code C ++ lui-même, soit des bibliothèques pour valider certains formats, par exemple, comme JSON ou XML . Il semble que soit les développeurs implémentent la validation des données manuellement pour chaque cas, soit les outils de validation sont créés pour un projet spécifique et sont mal adaptés à une utilisation en tant que bibliothèques à usage général.
- C++ GUI-, .
, C++ , , :
- ;
- , ;
- , , .
.., , , ? — , .
, , :
- ;
- ;
- .
, , , . . , — , , SQL. , , — .
cpp-validator header-only C++ C++14/C++17. cpp-validator
Boost.Hana.
cpp-validator
.
- :
- ;
- , :
- ;
- getter;
- ;
- , .
- - , .
- - , , .
- AND, OR NOT.
- ALL ANY.
- (lazy operands).
- .
- :
- ;
- , , , ..
- :
- , ;
- ;
- ().
- , :
- ;
- , ;
- ;
- ;
- .
- , Clang, GCC, MSVC Windows, Linux, macOS, iOS, Android.
cpp-validator
:
- , , - ;
- ;
- , , .
//
auto container_validator=validator(
_[size](eq,1), // 1
_["field1"](exists,true), // "field1"
_["field1"](ne,"undefined") // "field1" "undefined"
);
//
std::map<std::string,std::string> map1={{"field1","value1"}};
validate(map1,container_validator);
// ,
error_report err;
std::map<std::string,std::string> map2={{"field2","value2"}};
validate(map2,container_validator,err);
if (err)
{
std::cerr<<err.message()<<std::endl;
/* :
field1 must exist
*/
}
// ,
try
{
std::map<std::string,std::string> map3={{"field1","undefined"}};
validate(map3,container_validator);
}
catch(const validation_error& ex)
{
std::cerr<<ex.what()<<std::endl;
/* :
field1 must be not equal to undefined
*/
}
cpp-validator
, , - , , , , .
cpp-validator
GitHub https://github.com/evgeniums/cpp-validator — 1.0.2. Boost 1.0.
, .
//
auto v=validator(gt,100); // 100
//
error err;
//
validate(90,v,err);
if (err)
{
//
}
//
validate(200,v,err);
if (!err)
{
//
}
//
auto v=validator(gt,100); // 100
try
{
validate(200,v); //
validate(90,v); //
}
catch (const validation_error& err)
{
std::cerr << err.what() << std::endl;
/* :
must be greater than 100
*/
}
//
auto v=validator(gt,100); // 100
//
int value1=90;
if (!v.apply(value1))
{
//
}
int value2=200;
if (v.apply(value2))
{
//
}
// : 15 "sample string"
auto v=validator(
length(lt,15),
value(gte,"sample string")
);
//
std::string str1="sample";
if (!v.apply(str1))
{
// sample , sample string
}
std::string str2="sample string+";
if (v.apply(str2))
{
//
}
std::string str3="too long sample string";
if (!v.apply(str3))
{
// , 15
}
, ,
// : [95,100]
auto v=validator(in,interval(95,100));
//
error_report err;
//
size_t val=90;
validate(val,v,err);
if (err)
{
std::cerr << err.message() << std::endl;
/* :
must be in interval [95,100]
*/
}
//
auto v=validator(
_["field1"](gte,"xxxxxx")
^OR^
_["field1"](size(gte,100) ^OR^ value(gte,"zzzzzzzzzzzz"))
);
//
error_report err;
std::map<std::string,std::string> test_map={{"field1","value1"}};
validate(test_map,v,err);
if (err)
{
std::cerr << err.message() << std::endl;
/* :
field1 must be greater than or equal to xxxxxx OR size of field1 must be greater than or equal to 100 OR field1 must be greater than or equal to zzzzzzzzzzzz
*/
}
//
auto v=validator(
_["field1"][1](in,range({10,20,30,40,50})),
_["field1"][2](lt,100),
_["field2"](exists,false),
_["field3"](empty(flag,true))
);
//
error_report err;
std::map<std::string,std::map<size_t,size_t>> nested_map={
{"field1",{{1,5},{2,50}}},
{"field3",{}}
};
validate(nested_map,v,err);
if (err)
{
std::cerr << err.message() << std::endl;
/* :
element #1 of field1 must be in range [10, 20, 30, 40, 50]
*/
}
// getter
struct Foo
{
bool red_color() const
{
return true;
}
};
// red_color
DRACOSHA_VALIDATOR_PROPERTY_FLAG(red_color,"Must be red","Must be not red");
// red_color
auto v=validator(
_[red_color](flag,false)
);
//
error_report err;
Foo foo_instance;
validate(foo_instance,v,err);
if (err)
{
std::cerr << err.message() << std::endl;
/* :
"Must be not red"
*/
}
-
// setter
struct Foo
{
std::string bar_value;
uint32_t other_value;
size_t some_size;
void set_bar_value(std::string val)
{
bar_value=std::move(val);
}
};
using namespace DRACOSHA_VALIDATOR_NAMESPACE;
//
DRACOSHA_VALIDATOR_PROPERTY(bar_value);
DRACOSHA_VALIDATOR_PROPERTY(other_value);
// set_member_t bar_value Foo
DRACOSHA_VALIDATOR_NAMESPACE_BEGIN
template <>
struct set_member_t<Foo,DRACOSHA_VALIDATOR_PROPERTY_TYPE(bar_value)>
{
template <typename ObjectT, typename MemberT, typename ValueT>
void operator() (
ObjectT& obj,
MemberT&&,
ValueT&& val
) const
{
obj.set_bar_value(std::forward<ValueT>(val));
}
};
DRACOSHA_VALIDATOR_NAMESPACE_END
//
auto v=validator(
_[bar_value](ilex_ne,"UNKNOWN"), // " "
_[other_value](gte,1000) // 1000
);
Foo foo_instance;
error_report err;
// bar_value foo_instance
set_validated(foo_instance,bar_value,"Hello world",v,err);
if (!err)
{
// bar_value foo_instance
}
// bar_value foo_instance
set_validated(foo_instance,bar_value,"unknown",v,err);
if (err)
{
//
std::cerr << err.message() << std::endl;
/* :
bar_value must be not equal to UNKNOWN
*/
}
- -
#include <iostream>
#include <dracosha/validator/validator.hpp>
#include <dracosha/validator/validate.hpp>
using namespace DRACOSHA_VALIDATOR_NAMESPACE;
namespace validator_ns {
// getter "x"
DRACOSHA_VALIDATOR_PROPERTY(GetX);
// GetX
auto MyClassValidator=validator(
/*
"x" - , GetX;
interval.open() -
*/
_[GetX]("x")(in,interval(0,500,interval.open()))
);
}
using namespace validator_ns;
//
class MyClass {
double x;
public:
// -
MyClass(double _x) : x(_x) {
validate(*this,MyClassValidator);
}
// Getter
double GetX() const noexcept
{
return _x;
}
// Setter -
void SetX(double _x) {
validate(_[validator_ns::GetX],_x,MyClassValidator);
x = _x;
}
};
int main()
{
//
try {
MyClass obj1{100.0}; // ok
}
catch (const validation_error& err)
{
}
//
try {
MyClass obj2{1000.0}; //
}
catch (const validation_error& err)
{
std::cerr << err.what() << std::endl;
/*
:
x must be in interval(0,500)
*/
}
MyClass obj3{100.0};
//
try {
obj3.SetX(200.0); // ok
}
catch (const validation_error& err)
{
}
//
try {
obj3.SetX(1000.0); //
}
catch (const validation_error& err)
{
std::cerr << err.what() << std::endl;
/*
:
x must be in interval (0,500)
*/
}
return 0;
}
// ,
phrase_translator tr;
tr["password"]={
{""},
{"",grammar_ru::roditelny_padezh}
};
tr["hyperlink"]={
{{"",grammar_ru::zhensky_rod}},
{{"",grammar_ru::zhensky_rod},grammar_ru::roditelny_padezh}
};
tr["words"]={
{{"",grammar_ru::mn_chislo}}
};
/*
validator_translator_ru() tr
*/
auto tr1=extend_translator(validator_translator_ru(),tr);
//
std::map<std::string,std::string> m1={
{"password","123456"},
{"hyperlink","zzzzzzzzz"}
};
//
std::string rep;
auto ra1=make_reporting_adapter(m1,make_reporter(rep,make_formatter(tr1)));
//
auto v1=validator(
_["words"](exists,true)
);
if (!v1.apply(ra1))
{
std::cerr<<rep<<std::endl;
/*
:
*/
}
rep.clear();
auto v2=validator(
_["hyperlink"](eq,"https://www.boost.org")
);
if (!v2.apply(ra1))
{
std::cerr<<rep<<std::endl;
/*
:
https://www.boost.org
*/
}
rep.clear();
auto v3=validator(
_["password"](length(gt,7))
);
if (!v3.apply(ra1))
{
std::cerr<<rep<<std::endl;
/*
:
7
*/
}
rep.clear();
auto v4=validator(
_["hyperlink"](length(lte,7))
);
if (!v4.apply(ra1))
{
std::cerr<<rep<<std::endl;
/*
:
7
*/
}
rep.clear();