Add support for boolean values in filters, and reading of boolean
values from PostGIS data sources.
This commit is contained in:
parent
e1ea0a72db
commit
37eeb870cc
5 changed files with 167 additions and 9 deletions
77
include/mapnik/boolean_filter.hpp
Normal file
77
include/mapnik/boolean_filter.hpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2008 Tom Hughes
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
//$Id$
|
||||
|
||||
#ifndef BOOLEAN_FILTER_HPP
|
||||
#define BOOLEAN_FILTER_HPP
|
||||
// mapnik
|
||||
#include <mapnik/filter.hpp>
|
||||
#include <mapnik/expression.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
template <typename FeatureT>
|
||||
struct boolean_filter : public filter<FeatureT>
|
||||
{
|
||||
|
||||
boolean_filter(expression<FeatureT> const& exp)
|
||||
: filter<FeatureT>(),
|
||||
exp_(exp.clone()) {}
|
||||
|
||||
boolean_filter(boolean_filter const& other)
|
||||
: filter<FeatureT>(),
|
||||
exp_(other.exp_->clone()) {}
|
||||
|
||||
bool pass(FeatureT const& feature) const
|
||||
{
|
||||
return exp_->get_value(feature).to_bool();
|
||||
}
|
||||
|
||||
void accept(filter_visitor<FeatureT>& v)
|
||||
{
|
||||
exp_->accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
filter<FeatureT>* clone() const
|
||||
{
|
||||
return new boolean_filter(*this);
|
||||
}
|
||||
std::string to_string() const
|
||||
{
|
||||
return exp_->to_string();
|
||||
}
|
||||
~boolean_filter()
|
||||
{
|
||||
delete exp_;
|
||||
}
|
||||
|
||||
private:
|
||||
expression<FeatureT>* exp_;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //BOOLEAN_FILTER_HPP
|
|
@ -45,6 +45,9 @@ namespace mapnik {
|
|||
class literal : public expression<FeatureT>
|
||||
{
|
||||
public:
|
||||
literal(bool val)
|
||||
: expression<FeatureT>(),
|
||||
value_(val) {}
|
||||
literal(int val)
|
||||
: expression<FeatureT>(),
|
||||
value_(val) {}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <mapnik/expression.hpp>
|
||||
#include <mapnik/filter.hpp>
|
||||
#include <mapnik/regex_filter.hpp>
|
||||
#include <mapnik/boolean_filter.hpp>
|
||||
#include <mapnik/logical.hpp>
|
||||
|
||||
// boost
|
||||
|
@ -60,6 +61,24 @@ namespace mapnik
|
|||
using std::clog;
|
||||
using std::stack;
|
||||
|
||||
template <typename FeatureT>
|
||||
struct push_boolean
|
||||
{
|
||||
push_boolean(stack<shared_ptr<expression<FeatureT> > >& exprs)
|
||||
: exprs_(exprs) {}
|
||||
|
||||
void operator() (std::string const& val) const
|
||||
{
|
||||
if (val == "true")
|
||||
exprs_.push(shared_ptr<expression<FeatureT> >
|
||||
( new literal<FeatureT>(true)));
|
||||
else if (val == "false")
|
||||
exprs_.push(shared_ptr<expression<FeatureT> >
|
||||
( new literal<FeatureT>(false)));
|
||||
}
|
||||
stack<shared_ptr<expression<FeatureT> > >& exprs_;
|
||||
};
|
||||
|
||||
template <typename FeatureT>
|
||||
struct push_integer
|
||||
{
|
||||
|
@ -203,7 +222,31 @@ namespace mapnik
|
|||
stack<shared_ptr<filter<FeatureT> > >& filters_;
|
||||
stack<shared_ptr<expression<FeatureT> > >& exprs_;
|
||||
};
|
||||
|
||||
|
||||
template <typename FeatureT>
|
||||
struct compose_boolean_filter
|
||||
{
|
||||
compose_boolean_filter(stack<shared_ptr<filter<FeatureT> > >& filters,
|
||||
stack<shared_ptr<expression<FeatureT> > >& exprs)
|
||||
: filters_(filters),exprs_(exprs) {}
|
||||
|
||||
template <typename Iter>
|
||||
void operator() (Iter,Iter) const
|
||||
{
|
||||
if (exprs_.size()>=1)
|
||||
{
|
||||
shared_ptr<expression<FeatureT> > exp = exprs_.top();
|
||||
exprs_.pop();
|
||||
if (exp)
|
||||
{
|
||||
filters_.push(shared_ptr<filter<FeatureT> >(new boolean_filter<FeatureT>(*exp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
stack<shared_ptr<filter<FeatureT> > >& filters_;
|
||||
stack<shared_ptr<expression<FeatureT> > >& exprs_;
|
||||
};
|
||||
|
||||
template <typename FeatureT>
|
||||
struct compose_and_filter
|
||||
{
|
||||
|
@ -297,7 +340,8 @@ namespace mapnik
|
|||
func2_op = "min","max";
|
||||
spatial_op = "Equals","Disjoint","Touches","Within","Overlaps",
|
||||
"Crosses","Intersects","Contains","DWithin","Beyond","BBOX";
|
||||
|
||||
boolean_const = "true","false";
|
||||
|
||||
chset_t BaseChar (L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E"
|
||||
L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217"
|
||||
L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE"
|
||||
|
@ -368,18 +412,20 @@ namespace mapnik
|
|||
| L':'
|
||||
| CombiningChar
|
||||
| Extender;
|
||||
|
||||
|
||||
boolean = boolean_const [push_boolean<FeatureT>(self.exprs)];
|
||||
|
||||
number = strict_real_p [push_real<FeatureT>(self.exprs)]
|
||||
| int_p [push_integer<FeatureT>(self.exprs)];
|
||||
|
||||
string_ = confix_p(L'\'',(*lex_escape_ch_p)
|
||||
[push_string<FeatureT>(self.exprs,self.tr)],
|
||||
L'\'');
|
||||
|
||||
|
||||
property = L'[' >> ( (Letter | L'_' | L':')
|
||||
>> *NameChar )[push_property<FeatureT>(self.exprs)] >> L']';
|
||||
|
||||
literal = number | string_ | property;
|
||||
literal = boolean | number | string_ | property;
|
||||
|
||||
function = literal | ( func1_op >> L'('>> literal >> L')') |
|
||||
(func2_op >> L'(' >> literal >> L','>> literal >> L')');
|
||||
|
@ -415,7 +461,9 @@ namespace mapnik
|
|||
| ( L"<>" >> relation)
|
||||
[compose_filter<FeatureT,not_equals<value> >(self.filters,self.exprs)]);
|
||||
|
||||
not_expr = equation | *(str_p(L"not") >> equation)[compose_not_filter<FeatureT>(self.filters)];
|
||||
cond_expr = equation | (expression)[compose_boolean_filter<FeatureT>(self.filters,self.exprs)];
|
||||
|
||||
not_expr = cond_expr | *(str_p(L"not") >> cond_expr)[compose_not_filter<FeatureT>(self.filters)];
|
||||
|
||||
and_expr = not_expr >> *(L"and" >> not_expr)[compose_and_filter<FeatureT>(self.filters)];
|
||||
|
||||
|
@ -429,12 +477,14 @@ namespace mapnik
|
|||
BOOST_SPIRIT_DEBUG_RULE( expression );
|
||||
BOOST_SPIRIT_DEBUG_RULE( relation );
|
||||
BOOST_SPIRIT_DEBUG_RULE( equation );
|
||||
BOOST_SPIRIT_DEBUG_RULE( cond_expr );
|
||||
BOOST_SPIRIT_DEBUG_RULE( not_expr );
|
||||
BOOST_SPIRIT_DEBUG_RULE( and_expr );
|
||||
BOOST_SPIRIT_DEBUG_RULE( or_expr );
|
||||
|
||||
BOOST_SPIRIT_DEBUG_RULE( filter_statement );
|
||||
BOOST_SPIRIT_DEBUG_RULE( literal );
|
||||
BOOST_SPIRIT_DEBUG_RULE( boolean );
|
||||
BOOST_SPIRIT_DEBUG_RULE( number );
|
||||
BOOST_SPIRIT_DEBUG_RULE( string_ );
|
||||
BOOST_SPIRIT_DEBUG_RULE( property );
|
||||
|
@ -453,12 +503,14 @@ namespace mapnik
|
|||
boost::spirit::rule<ScannerT> expression;
|
||||
boost::spirit::rule<ScannerT> relation;
|
||||
boost::spirit::rule<ScannerT> equation;
|
||||
boost::spirit::rule<ScannerT> cond_expr;
|
||||
boost::spirit::rule<ScannerT> not_expr;
|
||||
boost::spirit::rule<ScannerT> and_expr;
|
||||
boost::spirit::rule<ScannerT> or_expr;
|
||||
|
||||
boost::spirit::rule<ScannerT> filter_statement;
|
||||
boost::spirit::rule<ScannerT> literal;
|
||||
boost::spirit::rule<ScannerT> boolean;
|
||||
boost::spirit::rule<ScannerT> number;
|
||||
boost::spirit::rule<ScannerT> string_;
|
||||
boost::spirit::rule<ScannerT> property;
|
||||
|
@ -467,6 +519,7 @@ namespace mapnik
|
|||
symbols<string> func1_op;
|
||||
symbols<string> func2_op;
|
||||
symbols<string> spatial_op;
|
||||
symbols<string> boolean_const;
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
// mapnik
|
||||
#include <mapnik/unicode.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
// boost
|
||||
#include <boost/variant.hpp>
|
||||
// stl
|
||||
|
@ -38,7 +39,7 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
typedef boost::variant<int,double,UnicodeString> value_base;
|
||||
typedef boost::variant<bool,int,double,UnicodeString> value_base;
|
||||
|
||||
namespace impl {
|
||||
struct equals
|
||||
|
@ -328,7 +329,22 @@ namespace mapnik {
|
|||
return lhs / rhs;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct to_bool : public boost::static_visitor<bool>
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
bool operator() (T val) const
|
||||
{
|
||||
throw config_error("Boolean value expected");
|
||||
}
|
||||
|
||||
bool operator() (bool val) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
struct to_string : public boost::static_visitor<std::string>
|
||||
{
|
||||
|
||||
|
@ -492,6 +508,11 @@ namespace mapnik {
|
|||
return base_;
|
||||
}
|
||||
|
||||
bool to_bool() const
|
||||
{
|
||||
return boost::apply_visitor(impl::to_bool(),base_);
|
||||
}
|
||||
|
||||
std::string to_expression_string() const
|
||||
{
|
||||
return boost::apply_visitor(impl::to_expression_string(),base_);
|
||||
|
|
|
@ -111,7 +111,11 @@ feature_ptr postgis_featureset::next()
|
|||
const char* buf=rs_->getValue(pos);
|
||||
int oid = rs_->getTypeOID(pos);
|
||||
|
||||
if (oid==23) //int4
|
||||
if (oid==16) //bool
|
||||
{
|
||||
boost::put(*feature,name,buf[0] != 0);
|
||||
}
|
||||
else if (oid==23) //int4
|
||||
{
|
||||
int val = int4net(buf);
|
||||
boost::put(*feature,name,val);
|
||||
|
|
Loading…
Add table
Reference in a new issue