Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for boolean values in filters, and reading of boolean
values from PostGIS data sources.
  • Loading branch information
tomhughes committed Feb 27, 2008
1 parent e1ea0a7 commit 37eeb87
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 9 deletions.
77 changes: 77 additions & 0 deletions include/mapnik/boolean_filter.hpp
@@ -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
3 changes: 3 additions & 0 deletions include/mapnik/expression.hpp
Expand Up @@ -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) {}
Expand Down
65 changes: 59 additions & 6 deletions include/mapnik/filter_parser.hpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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')');
Expand Down Expand Up @@ -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)];

Expand All @@ -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 );
Expand All @@ -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;
Expand All @@ -467,6 +519,7 @@ namespace mapnik
symbols<string> func1_op;
symbols<string> func2_op;
symbols<string> spatial_op;
symbols<string> boolean_const;


};
Expand Down
25 changes: 23 additions & 2 deletions include/mapnik/value.hpp
Expand Up @@ -26,6 +26,7 @@

// mapnik
#include <mapnik/unicode.hpp>
#include <mapnik/config_error.hpp>
// boost
#include <boost/variant.hpp>
// stl
Expand All @@ -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
Expand Down Expand Up @@ -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>
{

Expand Down Expand Up @@ -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_);
Expand Down
6 changes: 5 additions & 1 deletion plugins/input/postgis/postgisfs.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit 37eeb87

Please sign in to comment.