[core] add polyfill for codecvt for STLs that don't have it yet

This commit is contained in:
Konstantin Käfer
2018-06-21 14:44:00 +02:00
parent 536652ca20
commit 30e570aae7
6 changed files with 58 additions and 14 deletions

View File

@@ -142,6 +142,8 @@ else()
message(STATUS "Can't find ccache — consider installing ccache to improve recompilation performance")
endif()
include(cmake/codecvt.cmake)
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/platform/${MBGL_PLATFORM}/config.cmake)
message(ERROR "Can't find config.cmake file for platform ${MBGL_PLATFORM}")
endif()

19
cmake/codecvt.cmake Normal file
View File

@@ -0,0 +1,19 @@
add_library(codecvt INTERFACE)
# Determine if the STL has codecvt
file(WRITE "${CMAKE_BINARY_DIR}/features/codecvt/main.cpp" "#include <codecvt>\nint main() {}")
try_compile(STL_SUPPORTS_CODECVT
"${CMAKE_BINARY_DIR}/features/codecvt"
SOURCES "${CMAKE_BINARY_DIR}/features/codecvt/main.cpp"
CMAKE_FLAGS "-DCMAKE_MACOSX_BUNDLE:STRING=YES" "-DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED:STRING=NO"
COMPILE_DEFINITIONS "-std=c++14" # CXX_STANDARD wasn't added to try_compile until CMake 3.8
OUTPUT_VARIABLE CODECVT_TEST_OUTPUT
)
if (NOT STL_SUPPORTS_CODECVT)
if ($ENV{V})
message("codecvt support not detected: ${CODECVT_TEST_OUTPUT}")
endif()
target_include_directories(codecvt INTERFACE platform/default/codecvt)
target_add_mason_package(codecvt INTERFACE boost)
endif()

View File

@@ -7,6 +7,8 @@ target_include_directories(mbgl-core
PRIVATE src
)
target_link_libraries(mbgl-core PRIVATE codecvt)
target_add_mason_package(mbgl-core PUBLIC geometry)
target_add_mason_package(mbgl-core PUBLIC variant)
target_add_mason_package(mbgl-core PRIVATE unique_resource)

View File

@@ -71,6 +71,7 @@ macro(mbgl_filesource)
target_add_mason_package(mbgl-filesource PUBLIC jni.hpp)
target_link_libraries(mbgl-filesource
PRIVATE codecvt
PUBLIC sqlite
PUBLIC -llog
PUBLIC -landroid
@@ -86,6 +87,7 @@ add_library(mapbox-gl SHARED
)
target_link_libraries(mapbox-gl
PRIVATE codecvt
PRIVATE mbgl-core
PRIVATE mbgl-filesource
)
@@ -106,6 +108,7 @@ macro(mbgl_platform_test)
)
target_link_libraries(mbgl-test
PRIVATE codecvt
PRIVATE mbgl-core
PRIVATE mbgl-filesource
)

View File

@@ -0,0 +1,30 @@
#pragma once
// This is a minimal polyfill that'll only work exactly for how we use codecvt
#include <string>
#include <boost/locale/encoding_utf.hpp>
namespace std {
template <typename Codecvt, typename Elem = wchar_t>
class wstring_convert {
public:
static_assert(std::is_same<Elem, typename Codecvt::Elem>::value, "type mismatch");
inline std::basic_string<Elem> from_bytes(const string& str) {
return boost::locale::conv::utf_to_utf<Elem>(str);
}
inline string to_bytes(const std::basic_string<Elem>& str) {
return boost::locale::conv::utf_to_utf<char>(str);
}
};
template <typename E>
class codecvt_utf8_utf16 {
public:
using Elem = E;
};
} // namespace std

View File

@@ -1,25 +1,13 @@
#include <mbgl/util/utf.hpp>
#include <memory>
#include <locale>
// GCC 4.9 compatibility
#if !defined(__GNUC__) || __GNUC__ >= 5
#include <codecvt>
#else
#include <boost/locale/encoding_utf.hpp>
#endif
namespace mbgl {
namespace util {
std::u16string utf8_to_utf16::convert(std::string const& utf8) {
#if !defined(__GNUC__) || __GNUC__ >= 5
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
return converter.from_bytes(utf8);
#else
return boost::locale::conv::utf_to_utf<char16_t>(utf8.c_str(), utf8.c_str() + utf8.size());
#endif
std::u16string utf8_to_utf16::convert(const std::string& utf8) {
return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().from_bytes(utf8);
}
} // namespace util