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; }