Browse Source

Gmt module: Error reporting in all Convert functions.

gmtdatadir
Michael Uleysky 8 years ago
parent
commit
a3a6fa88f9
  1. 123
      modules/gmt/modgmt_structs.h

123
modules/gmt/modgmt_structs.h

@ -32,7 +32,7 @@ class GetDouble<Source, Policy, Policies...>: public GetDouble<Source, Policies.
GetDouble(GetDouble&) = delete;
template<class... Args>
GetDouble(Args... args):GetDouble<Source,Policies...>(args...) {};
double operator()(bool* suc) const {return p(GetDouble<Source,Policies...>::operator()(suc),suc);}
double operator()(bool* suc, std::string& err) const {return p(GetDouble<Source,Policies...>::operator()(suc,err),suc,err);}
};
// Bottom of recursion
@ -45,37 +45,57 @@ class GetDouble<Source>: public Source
GetDouble() = delete;
template<class... Args>
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<int32_t num, uint32_t denum=1>
template<int32_t num, uint32_t denum=1, bool equal=true>
class PMin
{
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<double>(num)/denum) *suc=false; return v;}
double operator()(double v, bool* suc, std::string& err) const
{
if(Compare(v,static_cast<double>(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<int32_t num, uint32_t denum=1>
template<int32_t num, uint32_t denum=1, bool equal=true>
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<double>(num)/denum) *suc=false; return v;}
double operator()(double v, bool* suc, std::string& err) const
{
if(Compare(v,static_cast<double>(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<SourceValue,PMin<0>,PMax<255> > Value2RGB;
typedef GetDouble<SourceValue,PMin<0>,PMax<360> > Value2Hue;
typedef GetDouble<SourceValue,PMin<0>,PMax<1> > Value2SV;
typedef GetDouble<SourceValue,PMin<0>,PMax< 1 > > Value2SV;
typedef GetDouble<SourceValue,PMin<0>,PMax<100> > Value2CMYK;
typedef GetDouble<SourceValue,PMin<0>,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;
}

Loading…
Cancel
Save