From 5c5e722d536d03f31187949749fb307adbc299d6 Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Mon, 8 Feb 2016 22:03:04 +1000 Subject: [PATCH] Gmt module: Rewrite template structure. Write selectors from ObjectList: BaseM2Type (multiple names), BaseMT2Type (multiple names and unnamed parameter with corresponding type), BaseMD2Type (same as BaseM2Type, but with default value), BaseMTD2Type (same as BaseMT2Type, but with default value). Define these selectors also for bool type. --- modules/gmt/modgmt_func.h | 374 ++++++++++++++++++++++++-------------- 1 file changed, 236 insertions(+), 138 deletions(-) diff --git a/modules/gmt/modgmt_func.h b/modules/gmt/modgmt_func.h index 578d6c6..61effd9 100644 --- a/modules/gmt/modgmt_func.h +++ b/modules/gmt/modgmt_func.h @@ -68,6 +68,29 @@ class Convert2Struct double operator ()(const ObjectString* q, bool* suc) const {double d=0; *suc=(*suc) && str2double(q->Value(),&d); return d;} }; +// Converting Int or Real to bool +template +class Convert2Struct +{ + public: + bool operator ()(const O* q, bool* suc) const {return q->Value()!=0;} +}; +// Converting String to bool +template<> +class Convert2Struct +{ + public: + bool operator ()(const ObjectString* q, bool* suc) const + { + std::string v=q->Value(); + tolower(v); + if("y"==v || "yes"==v || "on"==v || "t"==v || "true"==v || "1"==v) return true; + if("n"==v || "no"==v || "off"==v || "f"==v || "false"==v || "0"==v) return false; + *suc=false; + return false; + } +}; + // Get string template<> class Convert2Struct @@ -76,6 +99,14 @@ class Convert2Struct std::string operator ()(const ObjectString* q, bool* suc) const {return q->Value();} }; +// This class search parameter with specified names in the list, which may be converted to Struct. +// If SearchByType is true, additionaly search unnamed parameter of corresponding Object class (ObjectGMTClass for gmt_struct-derived types, for example). +// Additionally, Policies can be used to check correctness of found parameter. +template +class SearchParameter; +template +class SearchParameterWDef; + // Generic type storage class template class gTypeStorage @@ -83,6 +114,10 @@ class gTypeStorage template class Convertor: public Convert2Struct {}; // Conversion type public: typedef Base2Something Base2Type; + typedef SearchParameter BaseM2Type; + typedef SearchParameter BaseMT2Type; + typedef SearchParameterWDef BaseMD2Type; + typedef SearchParameterWDef BaseMTD2Type; }; // Specific type storage class template @@ -127,15 +162,18 @@ struct SearchHelper } }; -// This class search parameter with specified names in the list, which may be converted to Struct. -// If Struct is derived from gmt_struct, additionaly search unnamed parameter of type ObjectGMTClass -template -class SearchParameter +// Definition without policies +template +class SearchParameter { + typedef typename TypeStorage::Base2Type Base2Struct; + protected: bool exist; // There is at least one parameter with given names bool ok; // True if conversion to corresponding structure was successful and there is only one parameter with given names Struct val; - typedef typename TypeStorage::Base2Type Base2Struct; + SearchParameter() = delete; + SearchParameter(SearchParameter&&) = delete; + SearchParameter(SearchParameter&) = delete; public: // Recursive constructor template @@ -154,7 +192,17 @@ class SearchParameter } } // Bottom of recursion - SearchParameter(const ObjectList* input):exist(false),ok(true) {SearchHelper::value>()(input,&val,&exist,&ok);} + SearchParameter(const ObjectList* input):exist(false),ok(true) {SearchHelper()(input,&val,&exist,&ok);} + // Search by index + SearchParameter(const ObjectList* input, const ObjectList::ListValues::size_type i):exist(false),ok(true) + { + Base2Struct a(input,i); + if(a.Exist()) + { + exist=true; + val=a(&ok); + } + } Struct operator()(bool* suc) const { if(!ok || !exist) *suc=false; @@ -169,101 +217,159 @@ class SearchParameter bool Exist() const {return exist;} }; -// Definitions for double -template<> class TypeStorage: public gTypeStorage {}; -typedef TypeStorage::Base2Type Base2Double; // Copy definition to global namespace -// Definitions for string -template<> class TypeStorage: public gTypeStorage {}; -typedef TypeStorage::Base2Type Base2String; // Copy definition to global namespace - -// This source using Base2Double to get value of parameter. If parameter not exist, fallback to default value. -// Default value can be setted as template parameter or as parameter of constructor. -// We use rational representation of floating point number, because double type values not allowed as template parameter -template -class SourceDefaultVal: public Base2Double +// Definition with policies +template +class SearchParameter: public SearchParameter { - double defval; + SearchParameter() = delete; + SearchParameter(SearchParameter&&) = delete; + SearchParameter(SearchParameter&) = delete; public: - // Constructors without default value - SourceDefaultVal(const ObjectBase* arg):Base2Double(arg),defval(static_cast(num)/denum) {}; - SourceDefaultVal(const ObjectList* input, const std::string& name):Base2Double(input,name),defval(static_cast(num)/denum){}; - SourceDefaultVal(const ObjectList* input, const ObjectList::ListValues::size_type i):Base2Double(input,i),defval(static_cast(num)/denum){}; - // Constructors with default value - SourceDefaultVal(const ObjectBase* arg, double d):Base2Double(arg),defval(d) {}; - SourceDefaultVal(const ObjectList* input, const std::string& name, double d):Base2Double(input,name),defval(d){}; - SourceDefaultVal(const ObjectList* input, const ObjectList::ListValues::size_type i, double d):Base2Double(input,i),defval(d){}; - double operator()(bool* suc) const + using SearchParameter::ok; + using SearchParameter::exist; + // Recursive constructor + template + SearchParameter(const ObjectList* input, Args... args):SearchParameter(input,args...) {} + Struct operator()(bool* suc) const { - if(Exist()) return Base2Double::operator()(suc); - else return defval; + return Policy()(SearchParameter::operator()(suc),suc); + } + Struct operator()(bool* ex, bool* suc) const + { + return Policy()(SearchParameter::operator()(suc),suc); } }; -// This source try to get value of named parameter from list, which may have different names. Only one name must be in list. -template -class SourceMultiInputNames +// SearchParameter with default value +template +class SearchParameterWDef: protected SearchParameter { - bool exist; // There is at least one parameter with given names - bool ok; // True if conversion to Struct was successful and there is only one parameter with given names - Struct val; - typedef typename TypeStorage::Base2Type Base2Struct; + typedef SearchParameter SP; + SearchParameterWDef() = delete; + SearchParameterWDef(SearchParameterWDef&&) = delete; + SearchParameterWDef(SearchParameterWDef&) = delete; public: - // Recursive constructor template - SourceMultiInputNames(const ObjectList* input, const std::string& name, Args... args):SourceMultiInputNames(input,args...) - { - Base2Struct a(input,name); - if(exist && a.Exist()) ok=false; - else if(a.Exist()) - { - exist=true; - ok=true; - val=a(&ok); - } - } - // Bottom of recursion - SourceMultiInputNames(const ObjectList* input, const std::string& name) + SearchParameterWDef(const ObjectList* input, const Struct& def, Args... args):SP(input,args...) { - Base2Struct a(input,name); - exist=a.Exist(); - ok=true; - if(exist) val=a(&ok); + if(!SP::exist) SP::val=def; + SP::exist=true; } - Struct operator()(bool* suc) const + Struct operator()(bool* suc) const {return SP::operator()(suc);} + Struct operator()(bool* ex, bool* suc) const {return SP::operator()(ex,suc);} + bool Exist() const {return true;} +}; + +// SearchParameter with default value setted as class +template +class SearchParameterWDefO: protected SearchParameter +{ + typedef SearchParameter SP; + SearchParameterWDefO() = delete; + SearchParameterWDefO(SearchParameterWDefO&&) = delete; + SearchParameterWDefO(SearchParameterWDefO&) = delete; + public: + template + SearchParameterWDefO(const ObjectList* input, Args... args):SP(input,args...) { - if(!ok || !exist) *suc=false; - return val; + if(!SP::exist) SP::val=DefClass()(); + SP::exist=true; } - bool Exist() const {return exist;} + Struct operator()(bool* suc) const {return SP::operator()(suc);} + Struct operator()(bool* ex, bool* suc) const {return SP::operator()(ex,suc);} + bool Exist() const {return true;} }; -// Simple type for multiple input names -typedef GetDouble > BaseM2Double; +// Class for default double value +// We use rational representation of floating point number, because double type values not allowed as template parameter +template +class DoubleDefaultVal +{ + DoubleDefaultVal(DoubleDefaultVal&&) = delete; + DoubleDefaultVal(DoubleDefaultVal&) = delete; +public: + DoubleDefaultVal(){}; + double operator()() const {return static_cast(num)/denum;} +}; + +// Definitions for double +template<> class TypeStorage: public gTypeStorage {}; +typedef TypeStorage::Base2Type Base2Double; +typedef TypeStorage::BaseM2Type BaseM2Double; +typedef TypeStorage::BaseMT2Type BaseMT2Double; +typedef TypeStorage::BaseMD2Type BaseMD2Double; +typedef TypeStorage::BaseMTD2Type BaseMTD2Double; +// Definitions for bool +template<> class TypeStorage: public gTypeStorage {}; +typedef TypeStorage::Base2Type Base2Bool; +typedef TypeStorage::BaseM2Type BaseM2Bool; +typedef TypeStorage::BaseMT2Type BaseMT2Bool; +typedef TypeStorage::BaseMD2Type BaseMD2Bool; +typedef TypeStorage::BaseMTD2Type BaseMTD2Bool; +// Definitions for string +template<> class TypeStorage: public gTypeStorage {}; +typedef TypeStorage::Base2Type Base2String; +typedef TypeStorage::BaseM2Type BaseM2String; +typedef TypeStorage::BaseMT2Type BaseMT2String; +typedef TypeStorage::BaseMD2Type BaseMD2String; +typedef TypeStorage::BaseMTD2Type BaseMTD2String; // Definitions for ObjectGMTCoord template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Coord; +typedef TypeStorage::BaseM2Type BaseM2Coord; +typedef TypeStorage::BaseMT2Type BaseMT2Coord; +typedef TypeStorage::BaseMD2Type BaseMD2Coord; +typedef TypeStorage::BaseMTD2Type BaseMTD2Coord; // Definitions for ObjectGMTRegion template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Region; +typedef TypeStorage::BaseM2Type BaseM2Region; +typedef TypeStorage::BaseMT2Type BaseMT2Region; +typedef TypeStorage::BaseMD2Type BaseMD2Region; +typedef TypeStorage::BaseMTD2Type BaseMTD2Region; // Definitions for ObjectGMTProjection template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Projection; +typedef TypeStorage::BaseM2Type BaseM2Projection; +typedef TypeStorage::BaseMT2Type BaseMT2Projection; +typedef TypeStorage::BaseMD2Type BaseMD2Projection; +typedef TypeStorage::BaseMTD2Type BaseMTD2Projection; // Definitions for ObjectGMTColor template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Color; +typedef TypeStorage::BaseM2Type BaseM2Color; +typedef TypeStorage::BaseMT2Type BaseMT2Color; +typedef TypeStorage::BaseMD2Type BaseMD2Color; +typedef TypeStorage::BaseMTD2Type BaseMTD2Color; // Definitions for ObjectGMTDash template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Dash; +typedef TypeStorage::BaseM2Type BaseM2Dash; +typedef TypeStorage::BaseMT2Type BaseMT2Dash; +typedef TypeStorage::BaseMD2Type BaseMD2Dash; +typedef TypeStorage::BaseMTD2Type BaseMTD2Dash; // Definitions for ObjectGMTPen template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Pen; +typedef TypeStorage::BaseM2Type BaseM2Pen; +typedef TypeStorage::BaseMT2Type BaseMT2Pen; +typedef TypeStorage::BaseMD2Type BaseMD2Pen; +typedef TypeStorage::BaseMTD2Type BaseMTD2Pen; // Definitions for ObjectGMTFont template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Font; +typedef TypeStorage::BaseM2Type BaseM2Font; +typedef TypeStorage::BaseMT2Type BaseMT2Font; +typedef TypeStorage::BaseMD2Type BaseMD2Font; +typedef TypeStorage::BaseMTD2Type BaseMTD2Font; // Definitions for ObjectGMTLayer template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Layer; +typedef TypeStorage::BaseM2Type BaseM2Layer; +typedef TypeStorage::BaseMT2Type BaseMT2Layer; +typedef TypeStorage::BaseMD2Type BaseMD2Layer; +typedef TypeStorage::BaseMTD2Type BaseMTD2Layer; // Conversion from List to GMTRegion /* @@ -284,11 +390,11 @@ class Convert2Struct { struct gmt_region r; auto size=input->Size(); + bool suc=true; if(1==size) // Cases 1, 2 and 3 { Base2Region region(input,0); - bool suc=true; r=region(&suc); if(!suc) goto fail; // Conversion failed return r; @@ -296,30 +402,39 @@ class Convert2Struct // Case 4 { - OBType type(input->Get("type")); - if(type && r.Convert(type->Value())) return r; // type is one of "global*" string, we can return, becuse upd is irrelevant + std::string type; + bool typeexist=false; + { + Base2String t(input,"type"); + if(t.Exist()) + { + type=t(&suc); + tolower(type); + if(!suc) goto fail; // Conversion failed + typeexist=true; + } + else type="nobbox"; + } + if(r.Convert(type)) return r; // type is one of "global*" string, we can return, becuse upd is irrelevant bool upd; { - SearchParameter updarg(input,"r","region"); - bool suc=true; + BaseMT2Region updarg(input,"r","region"); r=updarg(&upd,&suc); if(upd && !suc) goto fail; // Conversion failed or too many arguments + suc=true; } Base2Coord ixb(input,"xb"), ixe(input,"xe"), iyb(input,"yb"), iye(input,"ye"); - if(!(type.Exist() || ixb.Exist() || ixe.Exist() || iyb.Exist() || iye.Exist() || upd)) goto case5; // No named parameters, no update mode, possibly case 5 - bool suc=true; + if(!(typeexist || ixb.Exist() || ixe.Exist() || iyb.Exist() || iye.Exist() || upd)) goto case5; // No named parameters, no update mode, possibly case 5 struct gmt_coord xb,yb,xe,ye; bool isbbox=upd?(gmt_region::BBOX==r.type):false; - if(type) + if(typeexist) { - std::string s=type->Value(); - tolower(s); - if("bbox"==s) isbbox=true; - if("nobbox"==s) isbbox=false; - if("bbox"!=s && "nobbox"!=s) goto fail; // Unknown type + if("bbox"==type) isbbox=true; + if("nobbox"==type) isbbox=false; + if("bbox"!=type && "nobbox"!=type) goto fail; // Unknown type } if(upd) @@ -329,7 +444,7 @@ class Convert2Struct if(!iyb.Exist()) yb=r.yb; if(!iye.Exist()) ye=r.ye; } - else suc=suc && ixb && ixe && iyb && iye; // In "new" mode all parameters must exists and have correct type + else suc=suc && ixb.Exist() && ixe.Exist() && iyb.Exist() && iye.Exist(); // In "new" mode all parameters must exists if(ixb.Exist()) xb=ixb(&suc); if(ixe.Exist()) xe=ixe(&suc); if(iyb.Exist()) yb=iyb(&suc); @@ -346,17 +461,16 @@ class Convert2Struct bool isbbox=false; if(5==size) { - OBType type(input->At(4)); - if(!type) goto fail; // Unknown fifth parameter - std::string str=type->Value(); + Base2String type(input,4); + std::string str=type(&suc); + if(!suc) goto fail; // Wrong parameter tolower(str); if("bbox"!=str || "nobbox"!=str) goto fail; // Unknown fifth parameter if("bbox"==str) isbbox=true; } Base2Coord ixb(input,0), ixe(input,(isbbox?2:1)), iyb(input,(isbbox?1:2)), iye(input,3); - bool suc=true; struct gmt_coord xb=ixb(&suc),yb=iyb(&suc),xe=ixe(&suc),ye=iye(&suc); - if(ixb && ixe && iyb && iye && suc) + if(suc) { if(!r.Convert(xb,xe,yb,ye,isbbox)) goto fail; // Conversion failed return r; // Case 4 with all parameters @@ -390,9 +504,10 @@ class Convert2Struct public: struct gmt_projection operator()(const ObjectList* input, bool* issuc) const { - typedef GetDouble,PMin<0> > BaseM2Nonneg; + typedef SearchParameter > BaseM2Nonneg; struct gmt_projection p; auto size=input->Size(); + bool suc=true; if(1==size) // Cases 1, and 2 { @@ -408,18 +523,17 @@ class Convert2Struct bool upd; bool changetype=false; { - SearchParameter updarg(input,"p","proj","projection"); - bool suc=true; + BaseMT2Projection updarg(input,"p","proj","projection"); p=updarg(&upd,&suc); if(upd && !suc) goto fail; // Conversion failed or too many arguments + suc=true; } // Try to set type of projection { - SearchParameter type(input,"t","type","projtype"); + BaseM2String type(input,"t","type","projtype"); if(!(type.Exist() || upd)) goto case4; // No named parameter, not update mode, go to case 4 // Check on redundant parameters - bool suc=true; if(type.Exist()) { std::string typestr=type(&suc); @@ -431,9 +545,8 @@ class Convert2Struct // We need the region { - SearchParameter region(input,"r","region"); + BaseMT2Region region(input,"r","region"); if(!(region.Exist() || upd)) goto fail; // Region must be defined in "new" mode - bool suc=true; if(region.Exist()) p.region=region(&suc); if(!suc) goto fail; // Conversion failed } @@ -914,17 +1027,17 @@ class Convert2Struct }; // Helper types -typedef GetDouble,PMin<0>,PMax<255> > Base2RGB; -typedef GetDouble,PMin<0>,PMax<360> > Base2Hue; -typedef GetDouble,PMin<0>,PMax<1> > Base2SV; -typedef GetDouble,PMin<0>,PMax<100> > Base2CMYK; -typedef GetDouble,PMin<0>,PMax<100> > Base2Transp; - -typedef GetDouble,PMin<0>,PMax<255> > BaseM2RGB; -typedef GetDouble,PMin<0>,PMax<360> > BaseM2Hue; -typedef GetDouble,PMin<0>,PMax<1> > BaseM2SV; -typedef GetDouble,PMin<0>,PMax<100> > BaseM2CMYK; -typedef GetDouble,PMin<0>,PMax<100> > BaseM2Transp; +typedef SearchParameterWDefO,false,PMin<0>,PMax<255> > Base2RGB; +typedef SearchParameterWDefO,false,PMin<0>,PMax<360> > Base2Hue; +typedef SearchParameterWDefO,false,PMin<0>,PMax<1 > > Base2SV; +typedef SearchParameterWDefO,false,PMin<0>,PMax<100> > Base2CMYK; +typedef SearchParameterWDefO,false,PMin<0>,PMax<100> > Base2Transp; + +typedef SearchParameter,PMax<255> > BaseM2RGB; +typedef SearchParameter,PMax<360> > BaseM2Hue; +typedef SearchParameter,PMax<1 > > BaseM2SV; +typedef SearchParameter,PMax<100> > BaseM2CMYK; +typedef SearchParameter,PMax<100> > BaseM2Transp; // Converting List to GMTColor /* @@ -964,7 +1077,7 @@ class Convert2Struct bool cmodset=false; bool upd; { - SearchParameter updarg(input,"color"); + BaseMT2Color updarg(input,"color"); bool suc=true; c=updarg(&upd,&suc); if(upd && !suc) goto fail; // Conversion failed or too many arguments @@ -1059,14 +1172,10 @@ class Convert2Struct Base2RGB r(input,0), g(input,1), b(input,2); c.model=gmt_color::RGB; bool suc=true; - if(r && g && b) - { - c.r=r(&suc); - c.g=g(&suc); - c.b=b(&suc); - if(!suc) goto fail; // Parsing error - } - else goto fail; // Something wrong + c.r=r(&suc); + c.g=g(&suc); + c.b=b(&suc); + if(!suc) goto fail; // Parsing error return c; } @@ -1076,15 +1185,11 @@ class Convert2Struct Base2CMYK cc(input,0), m(input,1), y(input,2), k(input,3); c.model=gmt_color::CMYK; bool suc=true; - if(cc && m && y && k) - { - c.cyan=cc(&suc); - c.magenta=m(&suc); - c.yellow=y(&suc); - c.black=k(&suc); - if(!suc) goto fail; // Parsing error - } - else goto fail; // Something wrong + c.cyan=cc(&suc); + c.magenta=m(&suc); + c.yellow=y(&suc); + c.black=k(&suc); + if(!suc) goto fail; // Parsing error return c; } @@ -1095,8 +1200,8 @@ class Convert2Struct }; // Helper types -typedef GetDouble,PMin<0> > Base2Width; -typedef GetDouble,PMin<0> > BaseM2Width; +typedef SearchParameterWDefO,false,PMin<0> > Base2Width; +typedef SearchParameter > BaseM2Width; // Converting List to GMTPen /* @@ -1136,7 +1241,7 @@ class Convert2Struct bool casevalid=false; bool upd; { - SearchParameter updarg(input,"pen","p"); + BaseMT2Pen updarg(input,"pen","p"); bool suc=true; p=updarg(&upd,&suc); if(upd && !suc) goto fail; // Conversion failed or too many arguments @@ -1163,7 +1268,7 @@ class Convert2Struct // Color { - SearchParameter color(input,"color","c"); + BaseMT2Color color(input,"color","c"); if(color.Exist()) { bool suc=true; @@ -1175,7 +1280,7 @@ class Convert2Struct // Dash { - SearchParameter dash(input,"dash","d"); + BaseMT2Dash dash(input,"dash","d"); if(dash.Exist()) { bool suc=true; @@ -1196,13 +1301,10 @@ class Convert2Struct Base2Color c(input,1); Base2Dash d(input,2); bool suc=true; - if(w && c) - { - p.width=w(&suc); - p.color=c(&suc); - } - else goto fail; // Something wrong - if(d) p.dash=d(&suc,p.width); + p.width=w(&suc); + p.color=c(&suc); + if(!suc) goto fail; // Something wrong + p.dash=d(&suc,p.width); if(!suc) goto fail; // Something wrong return p; } @@ -1253,7 +1355,7 @@ class Convert2Struct bool casevalid=false; bool upd; { - SearchParameter updarg(input,"font"); + BaseMT2Font updarg(input,"font"); bool suc=true; f=updarg(&upd,&suc); if(upd && !suc) goto fail; // Conversion failed or too many arguments @@ -1281,7 +1383,7 @@ class Convert2Struct // Family { - SearchParameter family(input,"family","f"); + BaseM2String family(input,"family","f"); if(family.Exist()) { bool suc=true; @@ -1293,7 +1395,7 @@ class Convert2Struct // Color { - SearchParameter color(input,"color","c"); + BaseMT2Color color(input,"color","c"); if(color.Exist()) { bool suc=true; @@ -1313,13 +1415,9 @@ class Convert2Struct Base2String fam(input,1); Base2Color c(input,2); bool suc=true; - if(s && fam) - { - f.size=s(&suc); - f.family=fam(&suc); - } - else goto fail; // Something wrong - if(c) f.color=c(&suc); + f.size=s(&suc); + f.family=fam(&suc); + f.color=c(&suc); if(!suc) goto fail; // Something wrong return f; }