fix json_value name clashing + add skeleton feature validation method
This commit is contained in:
parent
2b6f23890b
commit
92d35d1e40
3 changed files with 71 additions and 50 deletions
|
@ -38,40 +38,40 @@
|
|||
namespace mapnik { namespace json {
|
||||
|
||||
namespace x3 = boost::spirit::x3;
|
||||
struct json_value;
|
||||
using json_array = std::vector<json_value>;
|
||||
using json_object_element = std::pair<int, json_value>;
|
||||
using json_object = std::vector<json_object_element>;
|
||||
using json_value_base = mapnik::util::variant<value_null,
|
||||
struct geojson_value;
|
||||
using geojson_array = std::vector<geojson_value>;
|
||||
using geojson_object_element = std::pair<int, geojson_value>;
|
||||
using geojson_object = std::vector<geojson_object_element>;
|
||||
using geojson_value_base = mapnik::util::variant<value_null,
|
||||
value_bool,
|
||||
value_integer,
|
||||
value_double,
|
||||
std::string,
|
||||
mapnik::geometry::geometry_types,
|
||||
positions,
|
||||
json_array,
|
||||
json_object>;
|
||||
struct json_value : json_value_base
|
||||
geojson_array,
|
||||
geojson_object>;
|
||||
struct geojson_value : geojson_value_base
|
||||
{
|
||||
#if __cpp_inheriting_constructors >= 200802
|
||||
|
||||
using json_value_base::json_value_base;
|
||||
using geojson_value_base::geojson_value_base;
|
||||
|
||||
#else
|
||||
|
||||
json_value() = default;
|
||||
geojson_value() = default;
|
||||
|
||||
template <typename T>
|
||||
json_value(T && val)
|
||||
: json_value_base(std::forward<T>(val)) {}
|
||||
geojson_value(T && val)
|
||||
: geojson_value_base(std::forward<T>(val)) {}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace grammar {
|
||||
|
||||
using geojson_grammar_type = x3::rule<class geojson_tag, json_value>;
|
||||
using key_value_type = x3::rule<class key_value_tag, json_object_element>;
|
||||
using geojson_grammar_type = x3::rule<class geojson_tag, geojson_value>;
|
||||
using key_value_type = x3::rule<class key_value_tag, geojson_object_element>;
|
||||
BOOST_SPIRIT_DECLARE(geojson_grammar_type);
|
||||
BOOST_SPIRIT_DECLARE(key_value_type);
|
||||
}
|
||||
|
|
|
@ -91,24 +91,24 @@ struct geometry_type_ : x3::symbols<mapnik::geometry::geometry_types>
|
|||
geojson_grammar_type const value("JSON Value");
|
||||
key_value_type const key_value("JSON key/value");
|
||||
// rules
|
||||
x3::rule<class json_object_tag, json_object> object("JSON Object");
|
||||
x3::rule<class json_array_tag, json_array> array("JSON Array");
|
||||
x3::rule<class json_number_tag, json_value> number("JSON Number");
|
||||
//x3::rule<class key_value_tag, json_object_element> key_value("JSON key/value");
|
||||
x3::rule<class json_object_tag, geojson_object> object("JSON Object");
|
||||
x3::rule<class json_array_tag, geojson_array> array("JSON Array");
|
||||
x3::rule<class json_number_tag, geojson_value> number("JSON Number");
|
||||
//x3::rule<class key_value_tag, geojson_object_element> key_value("JSON key/value");
|
||||
// GeoJSON
|
||||
x3::rule<class geojson_coordinates_tag, json_object_element> coordinates("GeoJSON Coordinates");
|
||||
x3::rule<class geojson_geometry_type_tag, json_object_element> geometry_type("GeoJSON Geometry Type");
|
||||
x3::rule<class geojson_key_value_type_tag, json_object_element> geojson_key_value("GeoJSON Key/Value Type");
|
||||
auto const json_double = x3::real_parser<value_double, x3::strict_real_policies<value_double>>();
|
||||
auto const json_integer = x3::int_parser<value_integer, 10, 1, -1>();
|
||||
x3::rule<class geojson_coordinates_tag, geojson_object_element> coordinates("GeoJSON Coordinates");
|
||||
x3::rule<class geojson_geometry_type_tag, geojson_object_element> geometry_type("GeoJSON Geometry Type");
|
||||
x3::rule<class geojson_key_value_type_tag, geojson_object_element> geojson_key_value("GeoJSON Key/Value Type");
|
||||
auto const geojson_double = x3::real_parser<value_double, x3::strict_real_policies<value_double>>();
|
||||
auto const geojson_integer = x3::int_parser<value_integer, 10, 1, -1>();
|
||||
|
||||
// import unicode string rule
|
||||
namespace { auto const& json_string = mapnik::json::unicode_string_grammar(); }
|
||||
namespace { auto const& geojson_string = mapnik::json::unicode_string_grammar(); }
|
||||
// import positions rule
|
||||
namespace { auto const& positions_rule = mapnik::json::positions_grammar(); }
|
||||
|
||||
// GeoJSON types
|
||||
auto const value_def = object | array | json_string | number
|
||||
auto const value_def = object | array | geojson_string | number
|
||||
;
|
||||
|
||||
auto const coordinates_def = string("\"coordinates\"")[assign_key] > lit(':') > (positions_rule[assign_value] | value[assign_value])
|
||||
|
@ -117,7 +117,7 @@ auto const coordinates_def = string("\"coordinates\"")[assign_key] > lit(':') >
|
|||
auto const geometry_type_def = string("\"type\"")[assign_key] > lit(':') > (geometry_type_sym[assign_value] | value[assign_value])
|
||||
;
|
||||
|
||||
auto const key_value_def = json_string[assign_key] > lit(':') > value[assign_value]
|
||||
auto const key_value_def = geojson_string[assign_key] > lit(':') > value[assign_value]
|
||||
;
|
||||
|
||||
auto const geojson_key_value_def =
|
||||
|
@ -138,8 +138,8 @@ auto const array_def = lit('[')
|
|||
> lit(']')
|
||||
;
|
||||
|
||||
auto const number_def = json_double[assign]
|
||||
| json_integer[assign]
|
||||
auto const number_def = geojson_double[assign]
|
||||
| geojson_integer[assign]
|
||||
| lit("true") [make_true]
|
||||
| lit ("false") [make_false]
|
||||
| lit("null")[make_null]
|
||||
|
|
|
@ -41,28 +41,21 @@
|
|||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
struct feature_validate_callback
|
||||
template <typename Keys>
|
||||
bool validate_geojson_feature(mapnik::json::geojson_value const& value, Keys const& keys)
|
||||
{
|
||||
feature_validate_callback(mapnik::box2d<T> const& box)
|
||||
: box_(box) {}
|
||||
|
||||
void operator() (mapnik::feature_ptr const& f) const
|
||||
if (!value.is<mapnik::json::geojson_object>())
|
||||
{
|
||||
if (box_ != box_)
|
||||
{
|
||||
throw std::runtime_error("Bounding boxes mismatch validation feature");
|
||||
}
|
||||
std::clog << "Expecting an GeoJSON object" << std::endl;
|
||||
return false;
|
||||
}
|
||||
mapnik::box2d<T> const& box_;
|
||||
mapnik::json::geojson_object const& feature = mapnik::util::get<mapnik::json::geojson_object>(value);
|
||||
return true;
|
||||
};
|
||||
|
||||
using box_type = mapnik::box2d<float>;
|
||||
using boxes_type = std::vector<std::pair<box_type, std::pair<std::size_t, std::size_t>>>;
|
||||
using base_iterator_type = char const*;
|
||||
//const mapnik::json::extract_bounding_box_grammar<base_iterator_type, boxes_type> geojson_datasource_static_bbox_grammar;
|
||||
//const mapnik::transcoder tr("utf8");
|
||||
//const mapnik::json::feature_grammar_callback<base_iterator_type, mapnik::feature_impl, feature_validate_callback<float>> fc_grammar(tr);
|
||||
}
|
||||
|
||||
namespace mapnik { namespace json {
|
||||
|
@ -182,14 +175,14 @@ auto const bounding_box = x3::rule<struct bounding_box_rule_tag, std::tuple<boos
|
|||
|
|
||||
coordinates_rule[assign_bbox]
|
||||
|
|
||||
omit[json_string]
|
||||
omit[geojson_string]
|
||||
|
|
||||
omit[char_]))][assign_range];
|
||||
|
||||
|
||||
auto const feature = bounding_box[on_feature_callback];
|
||||
|
||||
auto const key_value_ = omit[json_string] > lit(':') > omit[geojson_value] ;
|
||||
auto const key_value_ = omit[geojson_string] > lit(':') > omit[geojson_value] ;
|
||||
|
||||
auto const features = lit("\"features\"")
|
||||
> lit(':') > lit('[') > -(omit[feature] % lit(',')) > lit(']');
|
||||
|
@ -205,13 +198,13 @@ auto const feature_collection = x3::rule<struct feature_collection_tag> {}
|
|||
namespace {
|
||||
struct collect_features
|
||||
{
|
||||
collect_features(std::vector<mapnik::json::json_value> & values)
|
||||
collect_features(std::vector<mapnik::json::geojson_value> & values)
|
||||
: values_(values) {}
|
||||
void operator() (mapnik::json::json_value && val) const
|
||||
void operator() (mapnik::json::geojson_value && val) const
|
||||
{
|
||||
values_.push_back(std::move(val));
|
||||
}
|
||||
std::vector<mapnik::json::json_value> & values_;
|
||||
std::vector<mapnik::json::geojson_value> & values_;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename Boxes>
|
||||
|
@ -230,7 +223,6 @@ struct extract_positions
|
|||
auto size = std::distance(r.begin(), r.end());
|
||||
boxes_.emplace_back(std::make_pair(bbox,std::make_pair(offset, size)));
|
||||
//boxes_.emplace_back(std::make_tuple(bbox,offset, size));
|
||||
//std::clog << offset << ":" << size << " " << bbox << std::endl;
|
||||
}
|
||||
Iterator start_;
|
||||
Boxes & boxes_;
|
||||
|
@ -308,14 +300,43 @@ std::pair<bool,typename T::value_type::first_type> process_geojson_file_x3(T & b
|
|||
return std::make_pair(false, extent);
|
||||
}
|
||||
|
||||
mapnik::context_ptr ctx = std::make_shared<mapnik::context_type>();
|
||||
//std::size_t start_id = 1;
|
||||
auto feature_grammar = x3::with<mapnik::json::keys_tag>(std::ref(keys))
|
||||
[ mapnik::json::grammar::geojson_value ];
|
||||
for (auto const& item : boxes)
|
||||
{
|
||||
if (item.first.valid())
|
||||
{
|
||||
if (!extent.valid()) extent = item.first;
|
||||
else extent.expand_to_include(item.first);
|
||||
|
||||
if (validate_features)
|
||||
{
|
||||
base_iterator_type feat_itr = start + item.second.first;
|
||||
base_iterator_type feat_end = feat_itr + item.second.second;
|
||||
mapnik::json::geojson_value feature_value;
|
||||
try
|
||||
{
|
||||
bool result = x3::phrase_parse(feat_itr, feat_end, feature_grammar, space_type(), feature_value);
|
||||
if (!result || feat_itr != feat_end)
|
||||
{
|
||||
if (verbose) std::clog << std::string(start + item.second.first, feat_end ) << std::endl;
|
||||
return std::make_pair(false, extent);
|
||||
}
|
||||
}
|
||||
catch (x3::expectation_failure<std::string::const_iterator> const& ex)
|
||||
{
|
||||
if (verbose) std::clog << ex.what() << std::endl;
|
||||
return std::make_pair(false, extent);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return std::make_pair(false, extent);
|
||||
}
|
||||
if (!validate_geojson_feature(feature_value, keys))
|
||||
{
|
||||
return std::make_pair(false, extent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(true, extent);
|
||||
|
|
Loading…
Reference in a new issue