implement inline (in-memory string) support for GeoJSON plugin - refs #2058

This commit is contained in:
Dane Springmeyer 2014-07-28 16:16:10 -07:00
parent ba1127ea57
commit 7f0029eb0b
3 changed files with 59 additions and 17 deletions

View file

@ -101,33 +101,55 @@ geojson_datasource::geojson_datasource(parameters const& params)
type_(datasource::Vector),
desc_(geojson_datasource::name(),
*params.get<std::string>("encoding","utf-8")),
file_(*params.get<std::string>("file","")),
filename_(),
inline_string_(),
extent_(),
features_(),
tree_(16,1)
{
if (file_.empty()) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter");
boost::optional<std::string> base = params.get<std::string>("base");
if (base)
boost::optional<std::string> inline_string = params.get<std::string>("inline");
if (inline_string)
{
file_ = *base + "/" + file_;
inline_string_ = *inline_string;
}
else
{
boost::optional<std::string> file = params.get<std::string>("file");
if (!file) throw mapnik::datasource_exception("GeoJSON Plugin: missing <file> parameter");
using base_iterator_type = std::istreambuf_iterator<char>;
boost::optional<std::string> base = params.get<std::string>("base");
if (base)
filename_ = *base + "/" + *file;
else
filename_ = *file;
}
if (!inline_string_.empty())
{
std::istringstream in(inline_string_);
parse_geojson(in);
}
else
{
#if defined (_WINDOWS)
std::ifstream is(mapnik::utf8_to_utf16(file_),std::ios_base::in | std::ios_base::binary);
std::ifstream in(mapnik::utf8_to_utf16(filename_),std::ios_base::in | std::ios_base::binary);
#else
std::ifstream is(file_.c_str(),std::ios_base::in | std::ios_base::binary);
std::ifstream in(filename_.c_str(),std::ios_base::in | std::ios_base::binary);
#endif
if (!is.is_open())
{
throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + file_ + "'");
if (!in.is_open())
{
throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'");
}
parse_geojson(in);
in.close();
}
}
template <typename T>
void geojson_datasource::parse_geojson(T & stream)
{
using base_iterator_type = std::istreambuf_iterator<char>;
boost::spirit::multi_pass<base_iterator_type> begin =
boost::spirit::make_default_multi_pass(base_iterator_type(is));
boost::spirit::make_default_multi_pass(base_iterator_type(stream));
boost::spirit::multi_pass<base_iterator_type> end =
boost::spirit::make_default_multi_pass(base_iterator_type());
@ -139,7 +161,8 @@ geojson_datasource::geojson_datasource(parameters const& params)
bool result = boost::spirit::qi::phrase_parse(begin, end, fc_grammar, space, features_);
if (!result)
{
throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + file_ + "'");
if (!inline_string_.empty()) throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file from in-memory string");
else throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file '" + filename_ + "'");
}
std::size_t count=0;

View file

@ -65,15 +65,18 @@ public:
mapnik::box2d<double> envelope() const;
mapnik::layer_descriptor get_descriptor() const;
boost::optional<mapnik::datasource::geometry_t> get_geometry_type() const;
template <typename T>
void parse_geojson(T & stream);
private:
mapnik::datasource::datasource_t type_;
std::map<std::string, mapnik::parameters> statistics_;
mapnik::layer_descriptor desc_;
std::string file_;
std::string filename_;
std::string inline_string_;
mapnik::box2d<double> extent_;
std::vector<mapnik::feature_ptr> features_;
spatial_index_type tree_;
};
#endif // FILE_DATASOURCE_HPP
#endif // GEOJSON_DATASOURCE_HPP

View file

@ -51,6 +51,22 @@ if 'geojson' in mapnik.DatasourceCache.plugin_names():
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
def test_geojson_from_in_memory_string():
ds = mapnik.Datasource(type='geojson',inline='{"type":"LineString","coordinates":[[0,0],[10,10]]}')
f = ds.all_features()[0]
desc = ds.describe()
eq_(desc['geometry_type'],mapnik.DataGeometryType.Point)
eq_(f['name'], u'Test')
eq_(f['int'], 1)
eq_(f['description'], u'Test: \u005C')
eq_(f['spaces'], u'this has spaces')
eq_(f['double'], 1.1)
eq_(f['boolean'], True)
eq_(f['NOM_FR'], u'Qu\xe9bec')
eq_(f['NOM_FR'], u'Québec')
# @raises(RuntimeError)
def test_that_nonexistant_query_field_throws(**kwargs):
ds = mapnik.Datasource(type='geojson',file='../data/json/escaped.geojson')