make the requirement of boost_regex unicode support optional by detecting if boost_regex was itself built with ICU support

This commit is contained in:
Dane Springmeyer 2011-02-28 20:00:56 +00:00
parent 8305e242c6
commit efb19dea6c
5 changed files with 94 additions and 9 deletions

View file

@ -219,6 +219,7 @@ pretty_dep_names = {
'freetype-config':'freetype-config program | try setting FREETYPE_CONFIG SCons option', 'freetype-config':'freetype-config program | try setting FREETYPE_CONFIG SCons option',
'osm':'more info: http://trac.mapnik.org/wiki/OsmPlugin', 'osm':'more info: http://trac.mapnik.org/wiki/OsmPlugin',
'curl':'libcurl is required for the "osm" plugin - more info: http://trac.mapnik.org/wiki/OsmPlugin', 'curl':'libcurl is required for the "osm" plugin - more info: http://trac.mapnik.org/wiki/OsmPlugin',
'boost_regex_icu':'libboost_regex built with optional ICU unicode support is needed for unicode regex support in mapnik.',
} }
def pretty_dep(dep): def pretty_dep(dep):
@ -787,6 +788,27 @@ int main()
return True return True
return False return False
def boost_regex_has_icu(context):
ret = context.TryRun("""
#include <boost/regex/icu.hpp>
#include <unicode/unistr.h>
int main()
{
UnicodeString ustr;
boost::u32regex pattern = boost::make_u32regex(ustr);
return 0;
}
""", '.cpp')
# hack to avoid printed output
context.Message('Checking if boost_regex was built with ICU unicode support... ')
context.Result(ret[0])
if ret[0]:
return True
return False
conf_tests = { 'prioritize_paths' : prioritize_paths, conf_tests = { 'prioritize_paths' : prioritize_paths,
'CheckPKGConfig' : CheckPKGConfig, 'CheckPKGConfig' : CheckPKGConfig,
'CheckPKG' : CheckPKG, 'CheckPKG' : CheckPKG,
@ -799,7 +821,8 @@ conf_tests = { 'prioritize_paths' : prioritize_paths,
'ogr_enabled' : ogr_enabled, 'ogr_enabled' : ogr_enabled,
'get_pkg_lib' : get_pkg_lib, 'get_pkg_lib' : get_pkg_lib,
'rollback_option' : rollback_option, 'rollback_option' : rollback_option,
'icu_at_least_four_two' : icu_at_least_four_two 'icu_at_least_four_two' : icu_at_least_four_two,
'boost_regex_has_icu' : boost_regex_has_icu,
} }
@ -924,6 +947,7 @@ if not preconfigured:
env.Append(CXXFLAGS = '-DU_HIDE_DRAFT_API') env.Append(CXXFLAGS = '-DU_HIDE_DRAFT_API')
env.Append(CXXFLAGS = '-DUDISABLE_RENAMING') env.Append(CXXFLAGS = '-DUDISABLE_RENAMING')
if os.path.exists(env['ICU_LIB_NAME']): if os.path.exists(env['ICU_LIB_NAME']):
#-sICU_LINK=" -L/usr/lib -licucore
env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','') env['ICU_LIB_NAME'] = os.path.basename(env['ICU_LIB_NAME']).replace('.dylib','').replace('lib','')
LIBSHEADERS = [ LIBSHEADERS = [
@ -1018,6 +1042,14 @@ if not preconfigured:
color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0]) color_print(4,'Could not find optional header or shared library for boost %s' % libinfo[0])
env['SKIPPED_DEPS'].append('boost ' + libinfo[0]) env['SKIPPED_DEPS'].append('boost ' + libinfo[0])
if env['ICU_LIB_NAME'] not in env['MISSING_DEPS']:
# http://lists.boost.org/Archives/boost/2009/03/150076.php
if conf.boost_regex_has_icu():
# TODO - should avoid having this be globally defined...
env.Append(CXXFLAGS = '-DBOOST_REGEX_HAS_ICU')
else:
env['SKIPPED_DEPS'].append('boost_regex_icu')
env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])] env['REQUESTED_PLUGINS'] = [ driver.strip() for driver in Split(env['INPUT_PLUGINS'])]
if len(env['REQUESTED_PLUGINS']): if len(env['REQUESTED_PLUGINS']):

View file

@ -27,7 +27,10 @@
// boost // boost
#include <boost/regex.hpp> #include <boost/regex.hpp>
//#include <boost/regex/config.hpp>
#if defined(BOOST_REGEX_HAS_ICU)
#include <boost/regex/icu.hpp> #include <boost/regex/icu.hpp>
#endif
namespace mapnik namespace mapnik
{ {
@ -76,13 +79,24 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (regex_match_node const& x) const value_type operator() (regex_match_node const& x) const
{ {
value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr); value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_match(v.to_unicode(),x.pattern); return boost::u32regex_match(v.to_unicode(),x.pattern);
#else
return boost::regex_match(v.to_string(),x.pattern);
#endif
} }
value_type operator() (regex_replace_node const& x) const value_type operator() (regex_replace_node const& x) const
{ {
value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr); value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format); return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format);
#else
std::string repl = boost::regex_replace(v.to_string(),x.pattern,x.format);
mapnik::transcoder tr_("utf8");
return tr_.transcode(repl.c_str());
#endif
} }
feature_type const& feature_; feature_type const& feature_;

View file

@ -87,7 +87,11 @@ struct regex_match_impl
template <typename T0,typename T1> template <typename T0,typename T1>
expr_node operator() (T0 & node, T1 const& pattern) const expr_node operator() (T0 & node, T1 const& pattern) const
{ {
#if defined(BOOST_REGEX_HAS_ICU)
return regex_match_node(node,tr_.transcode(pattern.c_str())); return regex_match_node(node,tr_.transcode(pattern.c_str()));
#else
return regex_match_node(node,pattern);
#endif
} }
mapnik::transcoder const& tr_; mapnik::transcoder const& tr_;
@ -107,7 +111,11 @@ struct regex_replace_impl
template <typename T0,typename T1,typename T2> template <typename T0,typename T1,typename T2>
expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const expr_node operator() (T0 & node, T1 const& pattern, T2 const& format) const
{ {
#if defined(BOOST_REGEX_HAS_ICU)
return regex_replace_node(node,tr_.transcode(pattern.c_str()),tr_.transcode(format.c_str())); return regex_replace_node(node,tr_.transcode(pattern.c_str()),tr_.transcode(format.c_str()));
#else
return regex_replace_node(node,pattern,format);
#endif
} }
mapnik::transcoder const& tr_; mapnik::transcoder const& tr_;

View file

@ -30,7 +30,9 @@
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#if defined(BOOST_REGEX_HAS_ICU)
#include <boost/regex/icu.hpp> #include <boost/regex/icu.hpp>
#endif
#include <boost/function.hpp> #include <boost/function.hpp>
namespace mapnik namespace mapnik
@ -225,6 +227,7 @@ struct binary_node
expr_node left,right; expr_node left,right;
}; };
#if defined(BOOST_REGEX_HAS_ICU)
struct regex_match_node struct regex_match_node
{ {
regex_match_node (expr_node const& a, UnicodeString const& ustr) regex_match_node (expr_node const& a, UnicodeString const& ustr)
@ -235,6 +238,7 @@ struct regex_match_node
boost::u32regex pattern; boost::u32regex pattern;
}; };
struct regex_replace_node struct regex_replace_node
{ {
regex_replace_node (expr_node const& a, UnicodeString const& ustr, UnicodeString const& f) regex_replace_node (expr_node const& a, UnicodeString const& ustr, UnicodeString const& f)
@ -246,7 +250,30 @@ struct regex_replace_node
boost::u32regex pattern; boost::u32regex pattern;
UnicodeString format; UnicodeString format;
}; };
#else
struct regex_match_node
{
regex_match_node (expr_node const& a, std::string const& str)
: expr(a),
pattern(str) {}
expr_node expr;
boost::regex pattern;
};
struct regex_replace_node
{
regex_replace_node (expr_node const& a, std::string const& str, std::string const& f)
: expr(a),
pattern(str),
format(f) {}
expr_node expr;
boost::regex pattern;
std::string format;
};
#endif
struct function_call struct function_call
{ {

View file

@ -76,34 +76,38 @@ struct expression_string : boost::static_visitor<void>
void operator() (regex_match_node const & x) const void operator() (regex_match_node const & x) const
{ {
// TODO - replace with pre ICU 4.2 compatible fromUTF32()
#if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >=2)
boost::apply_visitor(expression_string(str_),x.expr); boost::apply_visitor(expression_string(str_),x.expr);
str_ +=".match('"; str_ +=".match('";
#if defined(BOOST_REGEX_HAS_ICU)
std::string utf8; std::string utf8;
UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length()); UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
to_utf8(ustr,utf8); to_utf8(ustr,utf8);
str_ += utf8; str_ += utf8;
str_ +="')"; #else
str_ += x.pattern.str();
#endif #endif
str_ +="')";
} }
void operator() (regex_replace_node const & x) const void operator() (regex_replace_node const & x) const
{ {
// TODO - replace with pre ICU 4.2 compatible fromUTF32()
#if (U_ICU_VERSION_MAJOR_NUM >= 4) && (U_ICU_VERSION_MINOR_NUM >=2)
boost::apply_visitor(expression_string(str_),x.expr); boost::apply_visitor(expression_string(str_),x.expr);
str_ +=".replace("; str_ +=".replace(";
str_ += "'";
#if defined(BOOST_REGEX_HAS_ICU)
std::string utf8; std::string utf8;
UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length()); UnicodeString ustr = UnicodeString::fromUTF32( &x.pattern.str()[0] ,x.pattern.str().length());
to_utf8(ustr,utf8); to_utf8(ustr,utf8);
str_ += "'";
str_ += utf8; str_ += utf8;
str_ +="','"; str_ +="','";
to_utf8(x.format ,utf8); to_utf8(x.format ,utf8);
str_ += utf8; str_ += utf8;
str_ +="')"; #else
str_ += x.pattern.str();
str_ +="','";
str_ += x.pattern.str();
#endif #endif
str_ +="')";
} }
private: private: