From 7c58bf9fcb77a2306561ceb52e212b93873a693f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 7 Dec 2012 14:06:13 -0800 Subject: [PATCH] replace boost::trim with faster custom trim - closes #1633 --- include/mapnik/util/trim.hpp | 76 +++++++++++++++++++ plugins/input/csv/csv_datasource.cpp | 17 +++-- plugins/input/postgis/postgis_featureset.cpp | 5 +- src/box2d.cpp | 11 ++- src/libxml2_loader.cpp | 18 +---- src/load_map.cpp | 5 +- src/projection.cpp | 9 +-- src/rapidxml_loader.cpp | 7 +- .../data/broken_maps/in_valid_whitespace.xml | 4 + 9 files changed, 109 insertions(+), 43 deletions(-) create mode 100644 include/mapnik/util/trim.hpp create mode 100644 tests/data/broken_maps/in_valid_whitespace.xml diff --git a/include/mapnik/util/trim.hpp b/include/mapnik/util/trim.hpp new file mode 100644 index 000000000..938956fca --- /dev/null +++ b/include/mapnik/util/trim.hpp @@ -0,0 +1,76 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2012 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_TRIM_HPP +#define MAPNIK_TRIM_HPP + +// boost +//#include + +// stl +#include +#include + +namespace mapnik { namespace util { + +/* + faster trim (than boost::trim) + that intentionally does not respect + std::locale to avoid overhead in cases + where the locale is not critical +*/ + +static inline bool not_whitespace(int ch) +{ + if (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') return false; + return true; +} + +// trim from start +static inline std::string & ltrim(std::string & s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), not_whitespace)); + return s; +} + +// trim from end +static inline std::string & rtrim(std::string & s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), not_whitespace).base(), s.end()); + return s; +} + +// trim from both ends +static inline void trim(std::string & s) +{ + ltrim(rtrim(s)); +} + +static inline std::string trim_copy(std::string s) +{ + return ltrim(rtrim(s)); +} + + +}} // end of namespace mapnik + +#endif // MAPNIK_TRIM_HPP diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 2723488de..042c19448 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -41,6 +41,7 @@ #include #include #include +#include // stl #include @@ -68,7 +69,7 @@ csv_datasource::csv_datasource(parameters const& params, bool bind) separator_(*params_.get("separator", "")), quote_(*params_.get("quote", "")), headers_(), - manual_headers_(boost::trim_copy(*params_.get("headers", ""))), + manual_headers_(mapnik::util::trim_copy(*params_.get("headers", ""))), strict_(*params_.get("strict", false)), quiet_(*params_.get("quiet", false)), filesize_max_(*params_.get("filesize_max", 20.0)), // MB @@ -196,7 +197,7 @@ void csv_datasource::parse_csv(T & stream, // if user has not passed a separator manually // then attempt to detect by reading first line - std::string sep = boost::trim_copy(separator); + std::string sep = mapnik::util::trim_copy(separator); if (sep.empty()) { // default to ',' @@ -240,10 +241,10 @@ void csv_datasource::parse_csv(T & stream, typedef boost::escaped_list_separator escape_type; - std::string esc = boost::trim_copy(escape); + std::string esc = mapnik::util::trim_copy(escape); if (esc.empty()) esc = "\\"; - std::string quo = boost::trim_copy(quote); + std::string quo = mapnik::util::trim_copy(quote); if (quo.empty()) quo = "\""; MAPNIK_LOG_DEBUG(csv) << "csv_datasource: csv grammar: sep: '" << sep @@ -281,7 +282,7 @@ void csv_datasource::parse_csv(T & stream, unsigned idx(0); for (; beg != tok.end(); ++beg) { - std::string val = boost::trim_copy(*beg); + std::string val = mapnik::util::trim_copy(*beg); std::string lower_val = boost::algorithm::to_lower_copy(val); if (lower_val == "wkt" || (lower_val.find("geom") != std::string::npos)) @@ -324,7 +325,7 @@ void csv_datasource::parse_csv(T & stream, Tokenizer::iterator beg = tok.begin(); std::string val; if (beg != tok.end()) - val = boost::trim_copy(*beg); + val = mapnik::util::trim_copy(*beg); // skip blank lines if (val.empty()) @@ -338,7 +339,7 @@ void csv_datasource::parse_csv(T & stream, for (; beg != tok.end(); ++beg) { ++idx; - val = boost::trim_copy(*beg); + val = mapnik::util::trim_copy(*beg); if (val.empty()) { if (strict_) @@ -522,7 +523,7 @@ void csv_datasource::parse_csv(T & stream, } else { - value = boost::trim_copy(*beg); + value = mapnik::util::trim_copy(*beg); ++beg; } diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 44e62a0b8..25d516bc8 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -32,9 +32,9 @@ #include #include #include +#include // boost -#include #include // stl @@ -182,8 +182,7 @@ feature_ptr postgis_featureset::next() case 1042: //bpchar { - std::string str(buf); - boost::trim(str); + std::string str = mapnik::util::trim_copy(buf); feature->put(name, tr_->transcode(str.c_str())); break; } diff --git a/src/box2d.cpp b/src/box2d.cpp index 384809cc2..7a64a10e5 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -22,13 +22,13 @@ // mapnik #include +#include // stl #include // boost #include -#include #include // agg @@ -359,14 +359,17 @@ bool box2d::from_string(std::string const& s) for (boost::tokenizer >::iterator beg = tok.begin(); beg != tok.end(); ++beg) { - std::string item(*beg); - boost::trim(item); + std::string item = mapnik::util::trim_copy(*beg); // note: we intentionally do not use mapnik::util::conversions::string2double // here to ensure that shapeindex can statically compile mapnik::box2d without // needing to link to libmapnik std::string::const_iterator str_beg = item.begin(); std::string::const_iterator str_end = item.end(); - bool r = boost::spirit::qi::phrase_parse(str_beg,str_end,boost::spirit::qi::double_,boost::spirit::ascii::space,d[i]); + bool r = boost::spirit::qi::phrase_parse(str_beg, + str_end, + boost::spirit::qi::double_, + boost::spirit::ascii::space, + d[i]); if (!(r && (str_beg == str_end))) { break; diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index e0f034a98..90f6e5cc3 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -23,15 +23,14 @@ #ifdef HAVE_LIBXML2 // mapnik -#include #include #include #include +#include // boost #include #include -#include // libxml #include @@ -39,8 +38,6 @@ #include #include -using namespace std; - #define DEFAULT_OPTIONS (XML_PARSE_NOERROR | XML_PARSE_NOENT | XML_PARSE_NOBLANKS | XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA) namespace mapnik @@ -75,7 +72,7 @@ public: boost::filesystem::path path(filename); if (!boost::filesystem::exists(path)) { - throw config_error(string("Could not load map file: File does not exist"), 0, filename); + throw config_error(std::string("Could not load map file: File does not exist"), 0, filename); } xmlDocPtr doc = xmlCtxtReadFile(ctx_, filename.c_str(), encoding_, options_); @@ -92,13 +89,6 @@ public: throw config_error(msg, error->line, error->file); } } - - /* - if ( ! ctx->valid ) - { - MAPNIK_LOG_WARN(libxml2_loader) << "libxml2_loader: Failed to validate DTD."; - } - */ load(doc, node); } @@ -114,7 +104,7 @@ public: { boost::filesystem::path path(base_path); if (!boost::filesystem::exists(path)) { - throw config_error(string("Could not locate base_path '") + + throw config_error(std::string("Could not locate base_path '") + base_path + "': file or directory does not exist"); } } @@ -186,7 +176,7 @@ private: case XML_TEXT_NODE: { std::string trimmed((const char*)cur_node->content); - boost::algorithm::trim(trimmed); + mapnik::util::trim(trimmed); if (trimmed.empty()) break; //Don't add empty text nodes node.add_child(trimmed, cur_node->line, true); } diff --git a/src/load_map.cpp b/src/load_map.cpp index 89aa84d39..4d4e1b978 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -48,12 +48,12 @@ #include #include #include +#include #include // boost #include #include -#include #include #include #include @@ -255,8 +255,7 @@ void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& bas for (boost::tokenizer >::iterator beg = tokens.begin(); beg != tokens.end(); ++beg) { - std::string item(*beg); - boost::trim(item); + std::string item = mapnik::util::trim_copy(*beg); if (!mapnik::util::string2int(item,n[i])) { throw config_error(std::string("Invalid version string encountered: '") diff --git a/src/projection.cpp b/src/projection.cpp index 1776a22db..900b5addd 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -23,9 +23,7 @@ // mapnik #include #include - -// boost -#include +#include // proj4 #include @@ -151,10 +149,7 @@ void projection::init() std::string projection::expanded() const { if (proj_) { - std::string def(pj_get_def( proj_, 0 )); - //boost::algorithm::ireplace_first(def,params_,""); - boost::trim(def); - return def; + return mapnik::util::trim_copy(pj_get_def( proj_, 0 )); } return std::string(""); } diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp index 6a32e318f..4c0898bee 100644 --- a/src/rapidxml_loader.cpp +++ b/src/rapidxml_loader.cpp @@ -31,16 +31,15 @@ #include #include #include +#include // boost #include -#include // stl #include #include -using namespace std; namespace rapidxml = boost::property_tree::detail::rapidxml; namespace mapnik { @@ -108,7 +107,7 @@ public: // { // boost::filesystem::path path(base_path); // if (!boost::filesystem::exists(path)) { -// throw config_error(string("Could not locate base_path '") + +// throw config_error(std::string("Could not locate base_path '") + // base_path + "': file or directory does not exist"); // } // } @@ -145,7 +144,7 @@ private: case rapidxml::node_cdata: { std::string trimmed(cur_node->value()); - boost::trim(trimmed); + mapnik::util::trim(trimmed); if (trimmed.empty()) break; //Don't add empty text nodes node.add_child(trimmed, 0, true); } diff --git a/tests/data/broken_maps/in_valid_whitespace.xml b/tests/data/broken_maps/in_valid_whitespace.xml new file mode 100644 index 000000000..6ce5452b6 --- /dev/null +++ b/tests/data/broken_maps/in_valid_whitespace.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file