From f2782d0b67fd97d6e7eceed849d9070b83715cfe Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 24 Feb 2016 17:42:51 -0800 Subject: [PATCH] [csv] move spirit usage to cpp --- include/mapnik/csv/csv_grammar.hpp | 12 +- include/mapnik/csv/csv_types.hpp | 37 +++ plugins/input/csv/build.py | 1 + plugins/input/csv/csv_datasource.cpp | 3 + plugins/input/csv/csv_datasource.hpp | 2 +- plugins/input/csv/csv_featureset.hpp | 1 - plugins/input/csv/csv_getline.hpp | 72 +++++ plugins/input/csv/csv_inline_featureset.hpp | 1 - plugins/input/csv/csv_utils.cpp | 287 ++++++++++++++++++++ plugins/input/csv/csv_utils.hpp | 260 ++---------------- utils/mapnik-index/process_csv_file.cpp | 5 + 11 files changed, 428 insertions(+), 253 deletions(-) create mode 100644 include/mapnik/csv/csv_types.hpp create mode 100644 plugins/input/csv/csv_getline.hpp create mode 100644 plugins/input/csv/csv_utils.cpp diff --git a/include/mapnik/csv/csv_grammar.hpp b/include/mapnik/csv/csv_grammar.hpp index 6edecadfd..97778205d 100644 --- a/include/mapnik/csv/csv_grammar.hpp +++ b/include/mapnik/csv/csv_grammar.hpp @@ -20,20 +20,16 @@ * *****************************************************************************/ -#ifndef MAPNIK_CVS_GRAMMAR_HPP -#define MAPNIK_CVS_GRAMMAR_HPP - -//#define BOOST_SPIRIT_DEBUG +#ifndef MAPNIK_CSV_GRAMMAR_HPP +#define MAPNIK_CSV_GRAMMAR_HPP +#include #include #include namespace mapnik { namespace qi = boost::spirit::qi; -using csv_value = std::string; -using csv_line = std::vector; -using csv_data = std::vector; struct csv_white_space_skipper : qi::primitive_parser { @@ -110,4 +106,4 @@ private: } -#endif // MAPNIK_CVS_GRAMMAR_HPP +#endif // MAPNIK_CSV_GRAMMAR_HPP diff --git a/include/mapnik/csv/csv_types.hpp b/include/mapnik/csv/csv_types.hpp new file mode 100644 index 000000000..5359c3dd6 --- /dev/null +++ b/include/mapnik/csv/csv_types.hpp @@ -0,0 +1,37 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_CSV_TYPES_HPP +#define MAPNIK_CSV_TYPES_HPP + +#include +#include + +namespace mapnik { + +using csv_value = std::string; +using csv_line = std::vector; +using csv_data = std::vector; + +} + +#endif // MAPNIK_CSV_TYPES_HPP diff --git a/plugins/input/csv/build.py b/plugins/input/csv/build.py index edc3ae0ea..91675a1ae 100644 --- a/plugins/input/csv/build.py +++ b/plugins/input/csv/build.py @@ -39,6 +39,7 @@ else: plugin_sources = Split( """ + %(PLUGIN_NAME)s_utils.cpp %(PLUGIN_NAME)s_datasource.cpp %(PLUGIN_NAME)s_featureset.cpp %(PLUGIN_NAME)s_inline_featureset.cpp diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 1c22e054e..a69bfa251 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -37,9 +37,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #if defined(MAPNIK_MEMORY_MAPPED_FILE) diff --git a/plugins/input/csv/csv_datasource.hpp b/plugins/input/csv/csv_datasource.hpp index ac2482f9b..5dfbe330b 100644 --- a/plugins/input/csv/csv_datasource.hpp +++ b/plugins/input/csv/csv_datasource.hpp @@ -32,6 +32,7 @@ #include #include #include +#include "csv_utils.hpp" #pragma GCC diagnostic push #include @@ -42,7 +43,6 @@ // stl #include -#include #include template diff --git a/plugins/input/csv/csv_featureset.hpp b/plugins/input/csv/csv_featureset.hpp index 8fbf77bb8..f29ecc7dc 100644 --- a/plugins/input/csv/csv_featureset.hpp +++ b/plugins/input/csv/csv_featureset.hpp @@ -28,7 +28,6 @@ #include "csv_utils.hpp" #include "csv_datasource.hpp" #include -#include #if defined(MAPNIK_MEMORY_MAPPED_FILE) #pragma GCC diagnostic push diff --git a/plugins/input/csv/csv_getline.hpp b/plugins/input/csv/csv_getline.hpp new file mode 100644 index 000000000..9dfe5de49 --- /dev/null +++ b/plugins/input/csv/csv_getline.hpp @@ -0,0 +1,72 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * 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 + * + *****************************************************************************/ + +#ifndef MAPNIK_CSV_GETLINE_HPP +#define MAPNIK_CSV_GETLINE_HPP + +#include +#include +#include + +namespace csv_utils +{ + +template +std::basic_istream& getline_csv(std::istream& is, std::basic_string& s, CharT delim, CharT quote) +{ + typename std::basic_string::size_type nread = 0; + typename std::basic_istream::sentry sentry(is, true); + if (sentry) + { + std::basic_streambuf* buf = is.rdbuf(); + s.clear(); + bool has_quote = false; + while (nread < s.max_size()) + { + int c1 = buf->sbumpc(); + if (Traits::eq_int_type(c1, Traits::eof())) + { + is.setstate(std::ios_base::eofbit); + break; + } + else + { + ++nread; + CharT c = Traits::to_char_type(c1); + if (Traits::eq(c, quote)) + has_quote = !has_quote; + if (!Traits::eq(c, delim) || has_quote) + s.push_back(c); + else + break;// Character is extracted but not appended. + } + } + } + if (nread == 0 || nread >= s.max_size()) + is.setstate(std::ios_base::failbit); + + return is; +} + +} + +#endif // MAPNIK_CSV_GETLINE_HPP diff --git a/plugins/input/csv/csv_inline_featureset.hpp b/plugins/input/csv/csv_inline_featureset.hpp index 3da9f638a..c72be6e86 100644 --- a/plugins/input/csv/csv_inline_featureset.hpp +++ b/plugins/input/csv/csv_inline_featureset.hpp @@ -28,7 +28,6 @@ #include "csv_utils.hpp" #include "csv_datasource.hpp" #include -#include class csv_inline_featureset : public mapnik::Featureset { diff --git a/plugins/input/csv/csv_utils.cpp b/plugins/input/csv/csv_utils.cpp new file mode 100644 index 000000000..526f17313 --- /dev/null +++ b/plugins/input/csv/csv_utils.cpp @@ -0,0 +1,287 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 Artem Pavlenko + * + * 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 + * + *****************************************************************************/ + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "csv_getline.hpp" +#include "csv_utils.hpp" + +#if defined(MAPNIK_MEMORY_MAPPED_FILE) +#pragma GCC diagnostic push +#include +#include +#pragma GCC diagnostic pop +#endif + + +#include +#include +#include +#include + +namespace csv_utils +{ + +static const mapnik::csv_line_grammar line_g; +static const mapnik::csv_white_space_skipper skipper{}; + +mapnik::csv_line parse_line(char const* start, char const* end, char separator, char quote, std::size_t num_columns) +{ + mapnik::csv_line values; + if (num_columns > 0) values.reserve(num_columns); + if (!boost::spirit::qi::phrase_parse(start, end, (line_g)(separator, quote), skipper, values)) + { + throw mapnik::datasource_exception("Failed to parse CSV line:\n" + std::string(start, end)); + } + return values; +} + +mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote) +{ + auto start = line_str.c_str(); + auto end = start + line_str.length(); + return parse_line(start, end, separator, quote, 0); +} + + +bool is_likely_number(std::string const& value) +{ + return (std::strspn( value.c_str(), "e-.+0123456789" ) == value.size()); +} + +struct ignore_case_equal_pred +{ + bool operator () (unsigned char a, unsigned char b) const + { + return std::tolower(a) == std::tolower(b); + } +}; + +bool ignore_case_equal(std::string const& s0, std::string const& s1) +{ + return std::equal(s0.begin(), s0.end(), + s1.begin(), ignore_case_equal_pred()); +} + +} + + +namespace detail { + +template +std::tuple autodect_csv_flavour(T & stream, std::size_t file_length) +{ + // autodetect newlines/quotes/separators + char newline = '\n'; // default + bool has_newline = false; + bool has_single_quote = false; + char quote = '"'; // default + char separator = ','; // default + // local counters + int num_commas = 0; + int num_tabs = 0; + int num_pipes = 0; + int num_semicolons = 0; + + static std::size_t const max_size = 4000; + std::size_t size = std::min(file_length, max_size); + std::vector buffer; + buffer.resize(size); + stream.read(buffer.data(), size); + for (auto c : buffer) + { + switch (c) + { + case '\r': + newline = '\r'; + has_newline = true; + break; + case '\n': + has_newline = true; + break; + case '\'': + if (!has_single_quote) + { + quote = c; + has_single_quote = true; + } + break; + case ',': + if (!has_newline) ++num_commas; + break; + case '\t': + if (!has_newline) ++num_tabs; + break; + case '|': + if (!has_newline) ++num_pipes; + break; + case ';': + if (!has_newline) ++num_semicolons; + break; + } + } + // detect separator + if (num_tabs > 0 && num_tabs > num_commas) + { + separator = '\t'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; + } + else // pipes/semicolons + { + if (num_pipes > num_commas) + { + separator = '|'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; + } + else if (num_semicolons > num_commas) + { + separator = ';'; + MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; + } + } + + if (has_newline && has_single_quote) + { + std::istringstream ss(std::string(buffer.begin(), buffer.end())); + std::size_t num_columns = 0; + for (std::string line; csv_utils::getline_csv(ss, line, newline, quote); ) + { + if (size < file_length && ss.eof()) + { + // we can't be sure last line + // is not truncated so skip it + break; + } + if (line.size() == 0) continue; // empty lines are not interesting + auto num_quotes = std::count(line.begin(), line.end(), quote); + if (num_quotes % 2 != 0) + { + quote = '"'; + break; + } + auto columns = csv_utils::parse_line(line, separator, quote); + if (num_columns > 0 && num_columns != columns.size()) + { + quote = '"'; + break; + } + num_columns = columns.size(); + } + } + return std::make_tuple(newline, has_newline, separator, quote); +} + +template std::tuple autodect_csv_flavour(std::istringstream & stream, std::size_t file_length); +template std::tuple autodect_csv_flavour(std::ifstream & stream, std::size_t file_length); +template std::tuple autodect_csv_flavour(boost::interprocess::ibufferstream & stream, std::size_t file_length); + +void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) +{ + std::string lower_val(header); + std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); + if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) + { + locator.type = geometry_column_locator::WKT; + locator.index = index; + } + else if (lower_val == "geojson") + { + locator.type = geometry_column_locator::GEOJSON; + locator.index = index; + } + else if (lower_val == "x" || lower_val == "lon" + || lower_val == "lng" || lower_val == "long" + || (lower_val.find("longitude") != std::string::npos)) + { + locator.index = index; + locator.type = geometry_column_locator::LON_LAT; + } + + else if (lower_val == "y" + || lower_val == "lat" + || (lower_val.find("latitude") != std::string::npos)) + { + locator.index2 = index; + locator.type = geometry_column_locator::LON_LAT; + } +} + +bool valid(geometry_column_locator const& locator, std::size_t max_size) +{ + if (locator.type == geometry_column_locator::UNKNOWN) return false; + if (locator.index >= max_size) return false; + if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; + return true; +} + +mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator) +{ + mapnik::geometry::geometry geom; + if (locator.type == geometry_column_locator::WKT) + { + auto wkt_value = row.at(locator.index); + if (mapnik::from_wkt(wkt_value, geom)) + { + // correct orientations .. + mapnik::geometry::correct(geom); + } + else + { + throw mapnik::datasource_exception("Failed to parse WKT: '" + wkt_value + "'"); + } + } + else if (locator.type == geometry_column_locator::GEOJSON) + { + + auto json_value = row.at(locator.index); + if (!mapnik::json::from_geojson(json_value, geom)) + { + throw mapnik::datasource_exception("Failed to parse GeoJSON: '" + json_value + "'"); + } + } + else if (locator.type == geometry_column_locator::LON_LAT) + { + double x, y; + auto long_value = row.at(locator.index); + auto lat_value = row.at(locator.index2); + if (!mapnik::util::string2double(long_value,x)) + { + throw mapnik::datasource_exception("Failed to parse Longitude: '" + long_value + "'"); + } + if (!mapnik::util::string2double(lat_value,y)) + { + throw mapnik::datasource_exception("Failed to parse Latitude: '" + lat_value + "'"); + } + geom = mapnik::geometry::point(x,y); + } + return geom; +} + +}// ns detail diff --git a/plugins/input/csv/csv_utils.hpp b/plugins/input/csv/csv_utils.hpp index 29233df69..f16a22fd0 100644 --- a/plugins/input/csv/csv_utils.hpp +++ b/plugins/input/csv/csv_utils.hpp @@ -24,183 +24,28 @@ #define MAPNIK_CSV_UTILS_DATASOURCE_HPP // mapnik -#include -#include -#include -#include -#include #include -#include +#include #include -#include - -#pragma GCC diagnostic push -#include -#include -#pragma GCC diagnostic pop +#include #include -#include -#include +#include namespace csv_utils { -static const mapnik::csv_line_grammar line_g; -static const mapnik::csv_white_space_skipper skipper{}; +mapnik::csv_line parse_line(char const* start, char const* end, char separator, char quote, std::size_t num_columns); +mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote); -static mapnik::csv_line parse_line(char const* start, char const* end, char separator, char quote, std::size_t num_columns) -{ - mapnik::csv_line values; - if (num_columns > 0) values.reserve(num_columns); - if (!boost::spirit::qi::phrase_parse(start, end, (line_g)(separator, quote), skipper, values)) - { - throw mapnik::datasource_exception("Failed to parse CSV line:\n" + std::string(start, end)); - } - return values; -} +bool is_likely_number(std::string const& value); -static inline mapnik::csv_line parse_line(std::string const& line_str, char separator, char quote) -{ - auto start = line_str.c_str(); - auto end = start + line_str.length(); - return parse_line(start, end, separator, quote, 0); -} - -static inline bool is_likely_number(std::string const& value) -{ - return (std::strspn( value.c_str(), "e-.+0123456789" ) == value.size()); -} - -struct ignore_case_equal_pred -{ - bool operator () (unsigned char a, unsigned char b) const - { - return std::tolower(a) == std::tolower(b); - } -}; - -inline bool ignore_case_equal(std::string const& s0, std::string const& s1) -{ - return std::equal(s0.begin(), s0.end(), - s1.begin(), ignore_case_equal_pred()); -} +bool ignore_case_equal(std::string const& s0, std::string const& s1); } - namespace detail { -template -std::size_t file_length(T & stream) -{ - stream.seekg(0, std::ios::end); - return stream.tellg(); -} - -template -std::tuple autodect_csv_flavour(T & stream, std::size_t file_length) -{ - // autodetect newlines/quotes/separators - char newline = '\n'; // default - bool has_newline = false; - bool has_single_quote = false; - char quote = '"'; // default - char separator = ','; // default - // local counters - int num_commas = 0; - int num_tabs = 0; - int num_pipes = 0; - int num_semicolons = 0; - - static std::size_t const max_size = 4000; - std::size_t size = std::min(file_length, max_size); - std::vector buffer; - buffer.resize(size); - stream.read(buffer.data(), size); - for (auto c : buffer) - { - switch (c) - { - case '\r': - newline = '\r'; - has_newline = true; - break; - case '\n': - has_newline = true; - break; - case '\'': - if (!has_single_quote) - { - quote = c; - has_single_quote = true; - } - break; - case ',': - if (!has_newline) ++num_commas; - break; - case '\t': - if (!has_newline) ++num_tabs; - break; - case '|': - if (!has_newline) ++num_pipes; - break; - case ';': - if (!has_newline) ++num_semicolons; - break; - } - } - // detect separator - if (num_tabs > 0 && num_tabs > num_commas) - { - separator = '\t'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected tab separator"; - } - else // pipes/semicolons - { - if (num_pipes > num_commas) - { - separator = '|'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected '|' separator"; - } - else if (num_semicolons > num_commas) - { - separator = ';'; - MAPNIK_LOG_DEBUG(csv) << "csv_datasource: auto detected ';' separator"; - } - } - - if (has_newline && has_single_quote) - { - std::istringstream ss(std::string(buffer.begin(), buffer.end())); - std::size_t num_columns = 0; - for (std::string line; csv_utils::getline_csv(ss, line, newline, quote); ) - { - if (size < file_length && ss.eof()) - { - // we can't be sure last line - // is not truncated so skip it - break; - } - if (line.size() == 0) continue; // empty lines are not interesting - auto num_quotes = std::count(line.begin(), line.end(), quote); - if (num_quotes % 2 != 0) - { - quote = '"'; - break; - } - auto columns = csv_utils::parse_line(line, separator, quote); - if (num_columns > 0 && num_columns != columns.size()) - { - quote = '"'; - break; - } - num_columns = columns.size(); - } - } - return std::make_tuple(newline, has_newline, separator, quote); -} - struct geometry_column_locator { geometry_column_locator() @@ -211,87 +56,19 @@ struct geometry_column_locator std::size_t index2; }; -static inline void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator) +template +std::size_t file_length(T & stream) { - std::string lower_val(header); - std::transform(lower_val.begin(), lower_val.end(), lower_val.begin(), ::tolower); - if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) - { - locator.type = geometry_column_locator::WKT; - locator.index = index; - } - else if (lower_val == "geojson") - { - locator.type = geometry_column_locator::GEOJSON; - locator.index = index; - } - else if (lower_val == "x" || lower_val == "lon" - || lower_val == "lng" || lower_val == "long" - || (lower_val.find("longitude") != std::string::npos)) - { - locator.index = index; - locator.type = geometry_column_locator::LON_LAT; - } - - else if (lower_val == "y" - || lower_val == "lat" - || (lower_val.find("latitude") != std::string::npos)) - { - locator.index2 = index; - locator.type = geometry_column_locator::LON_LAT; - } + stream.seekg(0, std::ios::end); + return stream.tellg(); } -static inline bool valid(geometry_column_locator const& locator, std::size_t max_size) -{ - if (locator.type == geometry_column_locator::UNKNOWN) return false; - if (locator.index >= max_size) return false; - if (locator.type == geometry_column_locator::LON_LAT && locator.index2 >= max_size) return false; - return true; -} +template +std::tuple autodect_csv_flavour(T & stream, std::size_t file_length); -static inline mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator) -{ - mapnik::geometry::geometry geom; - if (locator.type == geometry_column_locator::WKT) - { - auto wkt_value = row.at(locator.index); - if (mapnik::from_wkt(wkt_value, geom)) - { - // correct orientations .. - mapnik::geometry::correct(geom); - } - else - { - throw mapnik::datasource_exception("Failed to parse WKT: '" + wkt_value + "'"); - } - } - else if (locator.type == geometry_column_locator::GEOJSON) - { - - auto json_value = row.at(locator.index); - if (!mapnik::json::from_geojson(json_value, geom)) - { - throw mapnik::datasource_exception("Failed to parse GeoJSON: '" + json_value + "'"); - } - } - else if (locator.type == geometry_column_locator::LON_LAT) - { - double x, y; - auto long_value = row.at(locator.index); - auto lat_value = row.at(locator.index2); - if (!mapnik::util::string2double(long_value,x)) - { - throw mapnik::datasource_exception("Failed to parse Longitude: '" + long_value + "'"); - } - if (!mapnik::util::string2double(lat_value,y)) - { - throw mapnik::datasource_exception("Failed to parse Latitude: '" + lat_value + "'"); - } - geom = mapnik::geometry::point(x,y); - } - return geom; -} +void locate_geometry_column(std::string const& header, std::size_t index, geometry_column_locator & locator); +bool valid(geometry_column_locator const& locator, std::size_t max_size); +mapnik::geometry::geometry extract_geometry(std::vector const& row, geometry_column_locator const& locator); template void process_properties(Feature & feature, Headers const& headers, Values const& values, Locator const& locator, Transcoder const& tr) @@ -310,8 +87,8 @@ void process_properties(Feature & feature, Headers const& headers, Values const& std::string value = mapnik::util::trim_copy(*val_beg++); int value_length = value.length(); - if (locator.index == i && (locator.type == detail::geometry_column_locator::WKT - || locator.type == detail::geometry_column_locator::GEOJSON) ) continue; + if (locator.index == i && (locator.type == geometry_column_locator::WKT + || locator.type == geometry_column_locator::GEOJSON) ) continue; bool matched = false; @@ -363,7 +140,6 @@ void process_properties(Feature & feature, Headers const& headers, Values const& } } - }// ns detail #endif // MAPNIK_CSV_UTILS_DATASOURCE_HPP diff --git a/utils/mapnik-index/process_csv_file.cpp b/utils/mapnik-index/process_csv_file.cpp index f4b5e964e..8f4345b6d 100644 --- a/utils/mapnik-index/process_csv_file.cpp +++ b/utils/mapnik-index/process_csv_file.cpp @@ -23,12 +23,15 @@ #include "process_csv_file.hpp" #include "../../plugins/input/csv/csv_getline.hpp" #include "../../plugins/input/csv/csv_utils.hpp" +#include "../../plugins/input/csv/csv_utils.cpp" +#include #include #include #if defined(MAPNIK_MEMORY_MAPPED_FILE) #pragma GCC diagnostic push #include +#include #include #include #pragma GCC diagnostic pop @@ -36,6 +39,8 @@ #endif #include +#include +#include namespace mapnik { namespace detail {