From a3a6fa88f94d20a61ce4b7f8d7bd19d47de679c5 Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Mon, 3 Oct 2016 13:53:35 +1000 Subject: [PATCH] Gmt module: Error reporting in all Convert functions. --- modules/gmt/modgmt_structs.h | 123 ++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 51 deletions(-) diff --git a/modules/gmt/modgmt_structs.h b/modules/gmt/modgmt_structs.h index 85fba8d..5dd0f85 100644 --- a/modules/gmt/modgmt_structs.h +++ b/modules/gmt/modgmt_structs.h @@ -32,7 +32,7 @@ class GetDouble: public GetDouble GetDouble(Args... args):GetDouble(args...) {}; - double operator()(bool* suc) const {return p(GetDouble::operator()(suc),suc);} + double operator()(bool* suc, std::string& err) const {return p(GetDouble::operator()(suc,err),suc,err);} }; // Bottom of recursion @@ -45,37 +45,57 @@ class GetDouble: public Source GetDouble() = delete; template GetDouble(Args... args):Source(args...) {}; - double operator()(bool* suc) const {return Source::operator()(suc);} + double operator()(bool* suc, std::string& err) const {return Source::operator()(suc, err);} }; // We use rational representation of floating point number, because double type values not allowed as template parameter // Policy to check if value is greater or equal num/denum -template +template class PMin { + static bool Compare(double d1, double d2) {return equal?(d1<=d2):(d1(num)/denum) *suc=false; return v;} + double operator()(double v, bool* suc, std::string& err) const + { + if(Compare(v,static_cast(num)/denum)) + { + *suc=false; + if(err.empty()) err="Value "+ToString(v)+" must be greater "+(equal?"or equal ":"")+"then "+ToString(num)+((denum==1)?"":("/"+ToString(denum))); + } + return v; + } }; // Policy to check if value is lesser or equal num/denum -template +template class PMax { + static bool Compare(double d1, double d2) {return equal?(d1>=d2):(d1>d2);} + public: - double operator()(double v, bool* suc) const {if(v>static_cast(num)/denum) *suc=false; return v;} + double operator()(double v, bool* suc, std::string& err) const + { + if(Compare(v,static_cast(num)/denum)) + { + *suc=false; + if(err.empty()) err="Value "+ToString(v)+" must be lesser "+(equal?"or equal ":"")+"then "+ToString(num)+((denum==1)?"":("/"+ToString(denum))); + } + return v; + } }; // Get double value from string or number class SourceValue { double d; - bool ok; + std::string err; public: - SourceValue(const std::string& s) {ok=str2double(s,&d);} - SourceValue(double s):d(s),ok(true) {} - double operator()(bool* suc) const + SourceValue(const std::string& s) {if(!str2double(s,&d)) err="Can't convert string \""+s+"\" to double value";} + SourceValue(double s):d(s) {} + double operator()(bool* suc, std::string& ierr) const { - if(!ok) *suc=false; + if(!err.empty()) {*suc=false; ierr=err;} return d; } }; @@ -83,7 +103,7 @@ class SourceValue // Helper types for colors typedef GetDouble,PMax<255> > Value2RGB; typedef GetDouble,PMax<360> > Value2Hue; -typedef GetDouble,PMax<1> > Value2SV; +typedef GetDouble,PMax< 1 > > Value2SV; typedef GetDouble,PMax<100> > Value2CMYK; typedef GetDouble,PMax<100> > Value2Transp; // Helper type for pens and dashes @@ -546,17 +566,17 @@ struct gmt_color: public gmt_struct } // Interpret one numeric argument as gray value - bool Convert(double gr) + bool Convert(double gr, std::string& err) { Value2RGB g(gr); bool suc=true; model=GRAY; transparency=0.0; - gray=g(&suc); + gray=g(&suc,err); return suc; } - bool Convert(const std::string& istr) + bool Convert(const std::string& istr, std::string& err) { std::string cstr=istr; tolower(cstr); @@ -573,7 +593,7 @@ struct gmt_color: public gmt_struct cstr=*ci; ci++; Value2Transp t(*ci); - transparency=t(&suc); + transparency=t(&suc,err); if(!suc) return false; // Parse error } } @@ -581,9 +601,9 @@ struct gmt_color: public gmt_struct WordList wl_slash=Split(cstr,"/"),wl_hyphen=Split(cstr,"-"); WordList::size_type slash_size=wl_slash.size(),hyphen_size=wl_hyphen.size(); // Checks - if(slash_size>1 && hyphen_size>1) return false; // Delimiter can be "/" or "-", not both - if(2==slash_size || slash_size>4) return false; // Size can be 1 or 3 for rgb or 4 for cmyk - if(2==hyphen_size || hyphen_size>3) return false; // Size can be 1 or 3 for hsv + if(slash_size>1 && hyphen_size>1) {err="Delimeter of color components must be \"/\" or \"-\", not both"; return false;} + if(2==slash_size || slash_size>4) {err="Number of color components must be 1 for GRAY, 3 for RGB or 4 for CMYK"; return false;} + if(2==hyphen_size || hyphen_size>3) {err="There is 3 color components in HSV model"; return false;} // Gray or name // TODO: Hex representation if(1==slash_size && 1==hyphen_size) @@ -592,7 +612,8 @@ struct gmt_color: public gmt_struct Value2RGB g(cstr); bool suc=true; model=GRAY; - gray=g(&suc); + gray=g(&suc,err); + err="Can't understand string "+cstr+", this is nor color name, nor gray value (0-255)"; return suc; } // RGB @@ -603,9 +624,9 @@ struct gmt_color: public gmt_struct Value2RGB blue(wl_slash.front()); bool suc=true; model=RGB; - r=red(&suc); - g=green(&suc); - b=blue(&suc); + r=red(&suc,err); if(!suc) return suc; + g=green(&suc,err);if(!suc) return suc; + b=blue(&suc,err); return suc; } // HSV @@ -616,9 +637,9 @@ struct gmt_color: public gmt_struct Value2SV v(wl_hyphen.front()); bool suc=true; model=HSV; - hue=h(&suc); - saturation=s(&suc); - value=v(&suc); + hue=h(&suc,err); if(!suc) return suc; + saturation=s(&suc,err);if(!suc) return suc; + value=v(&suc,err); return suc; } // CMYK @@ -630,10 +651,10 @@ struct gmt_color: public gmt_struct Value2CMYK k(wl_slash.front()); bool suc=true; model=CMYK; - cyan=c(&suc); - magenta=m(&suc); - yellow=y(&suc); - black=k(&suc); + cyan=c(&suc,err); if(!suc) return suc; + magenta=m(&suc,err);if(!suc) return suc; + yellow=y(&suc,err); if(!suc) return suc; + black=k(&suc,err); return suc; } } @@ -678,7 +699,7 @@ struct gmt_dash: public gmt_struct operator bool() const {return !dash.empty();} void Clear() {dash.clear(); shift=0.0; wisrel=false;} - bool Convert(const std::string& in, double w=0.0) + bool Convert(const std::string& in, std::string& err, double w=0.0) { Clear(); shift=0; @@ -704,7 +725,7 @@ struct gmt_dash: public gmt_struct { Value2Width s(wl.back()); bool suc=true; - shift=s(&suc); + shift=s(&suc,err); if(!suc) return false; // Parse error dstr=wl.front(); } @@ -714,7 +735,7 @@ struct gmt_dash: public gmt_struct { Value2Width d(i); bool suc=true; - dash.push_back(d(&suc)); + dash.push_back(d(&suc,err)); if(!suc) return false; // Parse error } return true; @@ -732,18 +753,18 @@ struct gmt_pen: public gmt_struct std::string Value() const {return ToString(width/10.0)+"c,"+color.Value()+(dash?(","+dash.Value()):"");} // Interpret one numeric argument as width value - bool Convert(double in) + bool Convert(double in, std::string& err) { Value2Width w(in); bool suc=true; - color.Convert(0); // Black + color.Convert(0,err); // Black dash.Clear(); - width=w(&suc); + width=w(&suc,err); return suc; } // Convert from string - bool Convert(const std::string& istr) + bool Convert(const std::string& istr, std::string& err) { std::string str=istr; WordList::const_iterator ci; @@ -752,7 +773,7 @@ struct gmt_pen: public gmt_struct // Defaults width=default_width; - color.Convert(0); // Black + color.Convert(0,err); // Black dash.Clear(); if(wl.size()>3) return false; // String is [width][,color][,dash] @@ -761,18 +782,18 @@ struct gmt_pen: public gmt_struct { Value2Width w(*ci); bool suc=true; - width=w(&suc); + width=w(&suc,err); if(!suc) return false; // Parse error } if(wl.end()!=ci) ci++; if(wl.end()!=ci && 0!=ci->size()) { - if(!color.Convert(*ci)) return false; // Parse error + if(!color.Convert(*ci,err)) return false; // Parse error } if(wl.end()!=ci) ci++; if(wl.end()!=ci && 0!=ci->size()) { - if(!dash.Convert(*ci,width)) return false; // Parse error + if(!dash.Convert(*ci,err,width)) return false; // Parse error } return true; } @@ -792,18 +813,18 @@ struct gmt_font: public gmt_struct std::string Value() const {return ToString(size)+"p,"+family+","+color.Value();} // Interpret one numeric argument as size of default black font - bool Convert(double in) + bool Convert(double in, std::string& err) { Value2Width s(in); bool suc=true; - color.Convert(0); // Black - size=s(&suc); + color.Convert(0,err); // Black + size=s(&suc,err); family=default_family; return suc; } // Convert from string - bool Convert(const std::string& str) + bool Convert(const std::string& str, std::string& err) { WordList::const_iterator ci; WordList wl=Split(str,",",true); @@ -811,34 +832,34 @@ struct gmt_font: public gmt_struct // Defaults size=default_size; family=default_family; - color.Convert(0); // Black + color.Convert(0,err); // Black - if(wl.size()>3) return false; // String is [size][,family][,color] or [family][,color] + if(wl.size()>3) {err="String "+str+" is not font string"; return false;} // String is [size][,family][,color] or [family][,color] ci=wl.begin(); if(wl.end()!=ci && 0!=ci->size()) { Value2Width s(*ci); bool suc=true; - size=s(&suc); + {std::string fake; size=s(&suc,fake);} if(!suc) // Parse error. check if argument is font name { if(0==families.count(*ci)) return false; // No, argument is not allowed font name family=*ci; - if(wl.size()>2) return false; // If first word is font name, then words count is 1 or 2. + if(wl.size()>2) {err="String "+str+" is not font string"; return false;} // If first word is font name, then words count is 1 or 2. goto read_color; } } if(wl.end()!=ci) ci++; if(wl.end()!=ci && 0!=ci->size()) { - if(0==families.count(*ci)) return false; // Argument is not allowed font name + if(0==families.count(*ci)) {err="Unknown font family: "+(*ci); return false;} // Argument is not allowed font name family=*ci; } read_color: if(wl.end()!=ci) ci++; if(wl.end()!=ci && 0!=ci->size()) { - if(!color.Convert(*ci)) return false; // Parse error + if(!color.Convert(*ci,err)) return false; // Parse error } return true; }