diff options
Diffstat (limited to 'src/boost/libs/locale')
124 files changed, 20671 insertions, 0 deletions
diff --git a/src/boost/libs/locale/CMakeLists.txt b/src/boost/libs/locale/CMakeLists.txt new file mode 100644 index 000000000..73af8451d --- /dev/null +++ b/src/boost/libs/locale/CMakeLists.txt @@ -0,0 +1,181 @@ +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(boost_locale VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_locale + src/encoding/codepage.cpp + src/shared/date_time.cpp + src/shared/format.cpp + src/shared/formatting.cpp + src/shared/generator.cpp + src/shared/ids.cpp + src/shared/localization_backend.cpp + src/shared/message.cpp + src/shared/mo_lambda.cpp + src/util/codecvt_converter.cpp + src/util/default_locale.cpp + src/util/info.cpp + src/util/locale_data.cpp +) + +add_library(Boost::locale ALIAS boost_locale) + +target_include_directories(boost_locale PUBLIC include) + +target_link_libraries(boost_locale + PUBLIC + Boost::assert + Boost::config + Boost::function + Boost::iterator + Boost::smart_ptr + Boost::static_assert + Boost::type_traits + PRIVATE + Boost::thread + Boost::unordered +) + +target_compile_definitions(boost_locale + PUBLIC BOOST_LOCALE_NO_LIB + # Source files already define BOOST_LOCALE_SOURCE + # PRIVATE BOOST_LOCALE_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(boost_locale PUBLIC BOOST_LOCALE_DYN_LINK) +else() + target_compile_definitions(boost_locale PUBLIC BOOST_LOCALE_STATIC_LINK) +endif() + +# Build Options + +find_package(Iconv QUIET) # requires CMake 3.11 +find_package(ICU COMPONENTS data i18n uc QUIET) + +set(_default_posix OFF) + +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin") + set(_default_posix ON) +endif() + +option(BOOST_LOCALE_ENABLE_ICONV "Boost.Locale: enable iconv backend" ${ICONV_FOUND}) +option(BOOST_LOCALE_ENABLE_ICU "Boost.Locale: enable ICU backend" ${ICU_FOUND}) +option(BOOST_LOCALE_ENABLE_POSIX "Boost.Locale: enable POSIX backend" ${_default_posix}) +option(BOOST_LOCALE_ENABLE_STD "Boost.Locale: enable std::locale backend" ON) +option(BOOST_LOCALE_ENABLE_WINAPI "Boost.Locale: enable Windows API backend" ${WIN32}) + +unset(_default_posix) + +if(BOOST_LOCALE_ENABLE_ICONV) + + find_package(Iconv REQUIRED) + + target_compile_definitions(boost_locale PRIVATE BOOST_LOCALE_WITH_ICONV=1) + target_link_libraries(boost_locale PRIVATE Iconv::Iconv) + +endif() + +if(BOOST_LOCALE_ENABLE_ICU) + + find_package(ICU COMPONENTS data i18n uc REQUIRED) + + target_compile_definitions(boost_locale PRIVATE BOOST_LOCALE_WITH_ICU=1) + target_link_libraries(boost_locale PRIVATE ICU::data ICU::i18n ICU::uc) + + target_sources(boost_locale PRIVATE + src/icu/boundary.cpp + src/icu/codecvt.cpp + src/icu/collator.cpp + src/icu/conversion.cpp + src/icu/date_time.cpp + src/icu/formatter.cpp + src/icu/icu_backend.cpp + src/icu/numeric.cpp + src/icu/time_zone.cpp + ) + +endif() + +if(BOOST_LOCALE_ENABLE_STD) + + target_sources(boost_locale PRIVATE + src/std/codecvt.cpp + src/std/collate.cpp + src/std/converter.cpp + src/std/numeric.cpp + src/std/std_backend.cpp + ) + +else() + + target_compile_definitions(boost_locale PRIVATE BOOST_LOCALE_NO_STD_BACKEND=1) + +endif() + +if(BOOST_LOCALE_ENABLE_WINAPI) + + target_sources(boost_locale PRIVATE + src/win32/collate.cpp + src/win32/converter.cpp + src/win32/numeric.cpp + src/win32/win_backend.cpp + ) + +else() + + target_compile_definitions(boost_locale PRIVATE BOOST_LOCALE_NO_WINAPI_BACKEND=1) + +endif() + +if(BOOST_LOCALE_ENABLE_WINAPI OR (BOOST_LOCALE_ENABLE_STD AND WIN32)) + + target_sources(boost_locale PRIVATE + src/win32/lcid.cpp + ) + +endif() + +if(BOOST_LOCALE_ENABLE_POSIX) + + target_sources(boost_locale PRIVATE + src/posix/collate.cpp + src/posix/converter.cpp + src/posix/numeric.cpp + src/posix/codecvt.cpp + src/posix/posix_backend.cpp + ) + +else() + + target_compile_definitions(boost_locale PRIVATE BOOST_LOCALE_NO_POSIX_BACKEND=1) + +endif() + +if(BOOST_LOCALE_ENABLE_WINAPI OR BOOST_LOCALE_ENABLE_STD OR BOOST_LOCALE_ENABLE_POSIX) + + target_sources(boost_locale PRIVATE + src/util/gregorian.cpp + ) + +endif() + +message(STATUS "Boost.Locale: " + "iconv ${BOOST_LOCALE_ENABLE_ICONV}, " + "ICU ${BOOST_LOCALE_ENABLE_ICU}, " + "POSIX ${BOOST_LOCALE_ENABLE_POSIX}, " + "std ${BOOST_LOCALE_ENABLE_STD}, " + "winapi ${BOOST_LOCALE_ENABLE_WINAPI}" +) + +# Testing + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() diff --git a/src/boost/libs/locale/build/Jamfile.v2 b/src/boost/libs/locale/build/Jamfile.v2 new file mode 100644 index 000000000..578e722ee --- /dev/null +++ b/src/boost/libs/locale/build/Jamfile.v2 @@ -0,0 +1,445 @@ +# copyright John Maddock 2003, Artyom Beilis 2010 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + + + +project /boost/locale + : source-location ../src + ; + +import configure ; +import os ; +import toolset ; +import project ; +import feature ; +# Features + +feature.feature boost.locale.iconv : on off : optional propagated ; +feature.feature boost.locale.icu : on off : optional propagated ; +feature.feature boost.locale.posix : on off : optional propagated ; +feature.feature boost.locale.std : on off : optional propagated ; +feature.feature boost.locale.winapi : on off : optional propagated ; + +# Configuration of libraries + +## iconv + +obj has_iconv_libc_obj : ../build/has_iconv.cpp ; +exe has_iconv : has_iconv_libc_obj ; +explicit has_iconv ; + +ICONV_PATH = [ modules.peek : ICONV_PATH ] ; + +lib iconv + : + : <search>$(ICONV_PATH)/lib <link>shared <runtime-link>shared + : + : <include>$(ICONV_PATH)/include + ; + +explicit iconv ; + +obj has_iconv_libc_ext : ../build/has_iconv.cpp iconv ; +exe has_external_iconv : has_iconv_libc_ext iconv ; +explicit has_external_iconv ; + +exe accepts_shared_option : ../build/option.cpp + : <cxxflags>-shared-libstdc++ + <cxxflags>-shared-libgcc + <linkflags>-shared-libstdc++ + <linkflags>-shared-libgcc + ; + +# Xlocale +obj has_xlocale_obj : ../build/has_xlocale.cpp ; +exe has_xlocale : has_xlocale_obj ; +explicit has_xlocale ; + +#end xlocale + + +ICU_PATH = [ modules.peek : ICU_PATH ] ; +ICU_LINK = [ modules.peek : ICU_LINK ] ; + +if $(ICU_LINK) +{ + ICU_OPTS = <include>$(ICU_PATH)/include <linkflags>$(ICU_LINK) <dll-path>$(ICU_PATH)/bin <runtime-link>shared ; + ICU64_OPTS = <include>$(ICU_PATH)/include <linkflags>$(ICU_LINK) <dll-path>$(ICU_PATH)/bin64 <runtime-link>shared ; +} +else +{ + searched-lib icuuc : : <name>icuuc + <search>$(ICU_PATH)/lib + <link>shared + <runtime-link>shared ; + + searched-lib icuuc : : <toolset>msvc + <variant>debug + <name>icuucd + <search>$(ICU_PATH)/lib + <link>shared + <runtime-link>shared ; + + searched-lib icuuc : : <name>this_is_an_invalid_library_name ; + + searched-lib icudt : : <search>$(ICU_PATH)/lib + <name>icudata + <link>shared + <runtime-link>shared ; + + searched-lib icudt : : <search>$(ICU_PATH)/lib + <name>icudt + <toolset>msvc + <link>shared + <runtime-link>shared ; + + searched-lib icudt : : <name>this_is_an_invalid_library_name ; + + searched-lib icuin : : <search>$(ICU_PATH)/lib + <name>icui18n + <link>shared + <runtime-link>shared ; + + searched-lib icuin : : <toolset>msvc + <variant>debug + <name>icuind + <search>$(ICU_PATH)/lib + <link>shared + <runtime-link>shared ; + + searched-lib icuin : : <toolset>msvc + <variant>release + <name>icuin + <search>$(ICU_PATH)/lib + <link>shared + <runtime-link>shared ; + + searched-lib icuin : : <name>this_is_an_invalid_library_name ; + + explicit icuuc icudt icuin ; + + ICU_OPTS = <include>$(ICU_PATH)/include + <library>icuuc/<link>shared/<runtime-link>shared + <library>icudt/<link>shared/<runtime-link>shared + <library>icuin/<link>shared/<runtime-link>shared + <dll-path>$(ICU_PATH)/bin + <runtime-link>shared ; + + + + searched-lib icuuc_64 : : <name>icuuc + <search>$(ICU_PATH)/lib64 + <link>shared + <runtime-link>shared ; + + searched-lib icuuc_64 : : <toolset>msvc + <variant>debug + <name>icuucd + <search>$(ICU_PATH)/lib64 + <link>shared + <runtime-link>shared ; + + searched-lib icuuc_64 : : <name>this_is_an_invalid_library_name ; + + searched-lib icudt_64 : : <search>$(ICU_PATH)/lib64 + <name>icudata + <link>shared + <runtime-link>shared ; + + searched-lib icudt_64 : : <search>$(ICU_PATH)/lib64 + <name>icudt + <toolset>msvc + <link>shared + <runtime-link>shared ; + + searched-lib icudt_64 : : <name>this_is_an_invalid_library_name ; + + searched-lib icuin_64 : : <search>$(ICU_PATH)/lib64 + <name>icui18n + <link>shared + <runtime-link>shared ; + + searched-lib icuin_64 : : <toolset>msvc + <variant>debug + <name>icuind + <search>$(ICU_PATH)/lib64 + <link>shared + <runtime-link>shared ; + + searched-lib icuin_64 : : <toolset>msvc + <variant>release + <name>icuin + <search>$(ICU_PATH)/lib64 + <link>shared + <runtime-link>shared ; + + searched-lib icuin_64 : : <name>this_is_an_invalid_library_name ; + + explicit icuuc_64 icudt_64 icuin_64 ; + + ICU64_OPTS = <include>$(ICU_PATH)/include + <library>icuuc_64/<link>shared/<runtime-link>shared + <library>icudt_64/<link>shared/<runtime-link>shared + <library>icuin_64/<link>shared/<runtime-link>shared + <dll-path>$(ICU_PATH)/bin64 + <runtime-link>shared ; + + +} + +obj has_icu_obj : ../build/has_icu_test.cpp : $(ICU_OPTS) ; +obj has_icu64_obj : ../build/has_icu_test.cpp : $(ICU64_OPTS) ; + +exe has_icu : has_icu_obj : $(ICU_OPTS) ; +exe has_icu64 : has_icu64_obj : $(ICU64_OPTS) ; + +explicit has_icu has_icu64 ; + + +# This function is called whenever the 'boost_locale' metatarget +# below is generated and figures what external components we have, +# what user wants, and what sources have to be compiled in the end. +rule configure-full ( properties * : flags-only ) +{ + + local result ; + local flags-result ; + + local found-iconv ; + + if <boost.locale.iconv>on in $(properties) + || ! <boost.locale.iconv> in $(properties:G) + && ! <target-os>solaris in $(properties) + { + # See if iconv is bundled with standard library. + if [ configure.builds has_iconv : $(properties) : "iconv (libc)" ] + { + found-iconv = true ; + } + else + { + if [ configure.builds has_external_iconv : $(properties) : "iconv (separate)" ] + { + found-iconv = true ; + result += <library>iconv ; + } + } + } + if $(found-iconv) + { + flags-result += <define>BOOST_LOCALE_WITH_ICONV=1 ; + } + + local found-icu ; + + if ! <boost.locale.icu>off in $(properties) + { + if [ configure.builds has_icu : $(properties) : "icu" ] + { + found-icu = true ; + flags-result += <define>BOOST_LOCALE_WITH_ICU=1 $(ICU_OPTS) ; + } + else if [ configure.builds has_icu64 : $(properties) : "icu (lib64)" ] + { + found-icu = true ; + flags-result += <define>BOOST_LOCALE_WITH_ICU=1 $(ICU64_OPTS) ; + } + + if $(found-icu) + { + ICU_SOURCES = + boundary + codecvt + collator + conversion + date_time + formatter + icu_backend + numeric + time_zone + ; + + result += <source>icu/$(ICU_SOURCES).cpp + <library>../../thread/build//boost_thread + ; + } + + } + + if ! $(found-iconv) && ! $(found-icu) && ! <target-os>windows in $(properties) && ! <target-os>cygwin in $(properties) + { + ECHO "- Boost.Locale needs either iconv or ICU library to be built." ; + result += <build>no ; + } + + if ! <boost.locale.std> in $(properties:G) + { + if <toolset>sun in $(properties) + { + properties += <boost.locale.std>off ; + } + else + { + properties += <boost.locale.std>on ; + } + } + + if <boost.locale.std>off in $(properties) + { + flags-result += <define>BOOST_LOCALE_NO_STD_BACKEND=1 ; + } + else + { + STD_SOURCES = + codecvt + collate + converter + numeric + std_backend + ; + result += <source>std/$(STD_SOURCES).cpp ; + } + + if ! <boost.locale.winapi> in $(properties:G) + { + if <target-os>windows in $(properties) + || <target-os>cygwin in $(properties) + { + properties += <boost.locale.winapi>on ; + } + else + { + properties += <boost.locale.winapi>off ; + } + } + if <target-os>windows in $(properties) + && <toolset>gcc in $(properties) + && <link>shared in $(properties) + && [ configure.builds accepts_shared_option : $(properties) : "g++ -shared-* supported" ] + { + flags-result += <cxxflags>-shared-libstdc++ + <cxxflags>-shared-libgcc + <linkflags>-shared-libstdc++ + <linkflags>-shared-libgcc + ; + } + + if <boost.locale.winapi>off in $(properties) + { + flags-result += <define>BOOST_LOCALE_NO_WINAPI_BACKEND=1 ; + } + else + { + WINAPI_SOURCES = + collate + converter + numeric + win_backend + ; + result += <source>win32/$(WINAPI_SOURCES).cpp ; + } + + if ( ! <boost.locale.winapi>off in $(properties) || ! <boost.locale.std>off in $(properties) ) + && ( <target-os>windows in $(properties) || <target-os>cygwin in $(properties) ) + { + result += <source>win32/lcid.cpp ; + } + + if ! <boost.locale.posix> in $(properties:G) + { + if <target-os>linux in $(properties) + || <target-os>darwin in $(properties) + || ( <target-os>freebsd in $(properties) && [ configure.builds has_xlocale : $(properties) : "xlocale supported" ] ) + { + properties += <boost.locale.posix>on ; + } + else + { + properties += <boost.locale.posix>off ; + } + } + + if <boost.locale.posix>off in $(properties) + { + flags-result += <define>BOOST_LOCALE_NO_POSIX_BACKEND=1 ; + } + else + { + POSIX_SOURCES = + collate + converter + numeric + codecvt + posix_backend + ; + result += <source>posix/$(POSIX_SOURCES).cpp ; + } + + if <boost.locale.posix>on in $(properties) || <boost.locale.std>on in $(properties) || <boost.locale.winapi>on in $(properties) + { + result += <source>util/gregorian.cpp ; + } + + result += <library>../../system/build//boost_system ; + + + if "$(flags-only)" = "flags" + { + return $(flags-result) ; + } + else { + result += $(flags-result) ; + return $(result) ; + } +} + +rule configure ( properties * ) +{ + local result = [ configure-full $(properties) : "all" ] ; + return $(result) ; + +} + +rule configure-flags ( properties * ) +{ + local result ; + result = [ configure-full $(properties) : "flags" ] ; + return $(result) ; + +} + + +alias build_options : : : : <conditional>@configure ; +alias build_flags : : : : <conditional>@configure-flags ; + +lib boost_locale + : + encoding/codepage.cpp + shared/date_time.cpp + shared/format.cpp + shared/formatting.cpp + shared/generator.cpp + shared/ids.cpp + shared/localization_backend.cpp + shared/message.cpp + shared/mo_lambda.cpp + util/codecvt_converter.cpp + util/default_locale.cpp + util/info.cpp + util/locale_data.cpp + : + # Don't link explicitly, not required + <define>BOOST_THREAD_NO_LIB=1 + <link>shared:<define>BOOST_LOCALE_DYN_LINK=1 + <threading>multi + # Meanwhile remove this + <conditional>@configure + ; + +boost-install boost_locale ; + + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/build/has_iconv.cpp b/src/boost/libs/locale/build/has_iconv.cpp new file mode 100644 index 000000000..7b500580f --- /dev/null +++ b/src/boost/libs/locale/build/has_iconv.cpp @@ -0,0 +1,14 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <iconv.h> + +int main() +{ + iconv_t d = iconv_open(0,0); + (void)(d); +} diff --git a/src/boost/libs/locale/build/has_icu_test.cpp b/src/boost/libs/locale/build/has_icu_test.cpp new file mode 100644 index 000000000..9419b3019 --- /dev/null +++ b/src/boost/libs/locale/build/has_icu_test.cpp @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2010 + * John Maddock + * + * Use, modification and distribution are subject to the + * Boost Software License, Version 1.0. (See accompanying file + * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ + +#include <unicode/uversion.h> +#include <unicode/locid.h> +#include <unicode/utypes.h> +#include <unicode/uchar.h> +#include <unicode/coll.h> + +#if defined(_MSC_VER) && !defined(_DLL) +#error "Mixing ICU with a static runtime doesn't work" +#endif + +int main() +{ + icu::Locale loc; + UErrorCode err = U_ZERO_ERROR; + UChar32 c = ::u_charFromName(U_UNICODE_CHAR_NAME, "GREEK SMALL LETTER ALPHA", &err); + return err; +} + diff --git a/src/boost/libs/locale/build/has_xlocale.cpp b/src/boost/libs/locale/build/has_xlocale.cpp new file mode 100644 index 000000000..4d788e2b7 --- /dev/null +++ b/src/boost/libs/locale/build/has_xlocale.cpp @@ -0,0 +1,12 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <xlocale.h> +int main() +{ + newlocale(LC_ALL_MASK,"",0); +} diff --git a/src/boost/libs/locale/build/option.cpp b/src/boost/libs/locale/build/option.cpp new file mode 100644 index 000000000..d321a959d --- /dev/null +++ b/src/boost/libs/locale/build/option.cpp @@ -0,0 +1,10 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +int main() +{ +} diff --git a/src/boost/libs/locale/examples/boundary.cpp b/src/boost/libs/locale/examples/boundary.cpp new file mode 100644 index 000000000..7c643f938 --- /dev/null +++ b/src/boost/libs/locale/examples/boundary.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale.hpp> +#include <iostream> +#include <cassert> +#include <ctime> + +int main() +{ + using namespace boost::locale; + using namespace std; + + generator gen; + // Make system default locale global + std::locale loc = gen(""); + locale::global(loc); + cout.imbue(loc); + + + string text="Hello World! あにま! Linux2.6 and Windows7 is word and number. שָלוֹם עוֹלָם!"; + + cout<<text<<endl; + + boundary::ssegment_index index(boundary::word,text.begin(),text.end()); + boundary::ssegment_index::iterator p,e; + + for(p=index.begin(),e=index.end();p!=e;++p) { + cout<<"Part ["<<*p<<"] has "; + if(p->rule() & boundary::word_number) + cout<<"number(s) "; + if(p->rule() & boundary::word_letter) + cout<<"letter(s) "; + if(p->rule() & boundary::word_kana) + cout<<"kana character(s) "; + if(p->rule() & boundary::word_ideo) + cout<<"ideographic character(s) "; + if(p->rule() & boundary::word_none) + cout<<"no word characters"; + cout<<endl; + } + + index.map(boundary::character,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + cout<<"|" <<*p ; + } + cout<<"|\n\n"; + + index.map(boundary::line,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + cout<<"|" <<*p ; + } + cout<<"|\n\n"; + + index.map(boundary::sentence,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + cout<<"|" <<*p ; + } + cout<<"|\n\n"; + +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/examples/calendar.cpp b/src/boost/libs/locale/examples/calendar.cpp new file mode 100644 index 000000000..d905511a7 --- /dev/null +++ b/src/boost/libs/locale/examples/calendar.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale.hpp> +#include <iostream> +#include <iomanip> +#include <ctime> + +int main() +{ + using namespace boost::locale; + + generator gen; + std::locale::global(gen("")); + std::cout.imbue(std::locale()); + // Setup environment + + boost::locale::date_time now; + + date_time start=now; + + // Set the first day of the first month of this year + start.set(period::month(),now.minimum(period::month())); + start.set(period::day(),start.minimum(period::day())); + + int current_year = period::year(now); + + + // Display current year + std::cout << format("{1,ftime='%Y'}") % now << std::endl; + + // + // Run forward untill current year is the date + // + for(now=start; period::year(now) == current_year;) { + + // Print heading of month + if(calendar().is_gregorian()) + std::cout << format("{1,ftime='%B'}") % now <<std::endl; + else + std::cout << format("{1,ftime='%B'} ({1,ftime='%Y-%m-%d',locale=en} - {2,locale=en,ftime='%Y-%m-%d'})") + % now + % date_time(now,now.maximum(period::day())*period::day()) << std::endl; + + int first = calendar().first_day_of_week(); + + // Print weeks days + for(int i=0;i<7;i++) { + date_time tmp(now,period::day_of_week() * (first + i)); + std::cout << format("{1,w=8,ftime='%a'} ") % tmp; + } + std::cout << std::endl; + + int current_month = now / period::month(); + int skip = now / period::day_of_week_local() - 1; + for(int i=0;i<skip*9;i++) + std::cout << ' '; + for(;now / period::month() == current_month ;now += period::day()) { + std::cout << format("{1,w=8,ftime='%e'} ") % now; + if(now / period::day_of_week_local() == 7) + std::cout << std::endl; + } + std::cout << std::endl; + } + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/examples/collate.cpp b/src/boost/libs/locale/examples/collate.cpp new file mode 100644 index 000000000..9e14e43ab --- /dev/null +++ b/src/boost/libs/locale/examples/collate.cpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <iostream> +#include <string> +#include <set> + +#include <boost/locale.hpp> + +using namespace std; +using namespace boost::locale; + +int main() +{ + generator gen; + std::locale::global(gen("")); + /// Set global locale to requested + + /// Create a set that includes all strings sorted according to ABC order + /// std::locale can be used as object for comparison + typedef std::set<std::string,std::locale> set_type; + set_type all_strings; + + /// Read all strings into the set + while(!cin.eof()) { + std::string tmp; + getline(cin,tmp); + all_strings.insert(tmp); + } + /// Print them out + for(set_type::iterator p=all_strings.begin();p!=all_strings.end();++p) { + cout<<*p<<endl; + } + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/examples/conversions.cpp b/src/boost/libs/locale/examples/conversions.cpp new file mode 100644 index 000000000..74037f235 --- /dev/null +++ b/src/boost/libs/locale/examples/conversions.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale.hpp> +#include <boost/algorithm/string/case_conv.hpp> +#include <iostream> + +#include <ctime> + + + +int main() +{ + using namespace boost::locale; + using namespace std; + // Create system default locale + generator gen; + locale loc=gen(""); + locale::global(loc); + cout.imbue(loc); + + + cout<<"Correct case conversion can't be done by simple, character by character conversion"<<endl; + cout<<"because case conversion is context sensitive and not 1-to-1 conversion"<<endl; + cout<<"For example:"<<endl; + cout<<" German grüßen correctly converted to "<<to_upper("grüßen")<<", instead of incorrect " + <<boost::to_upper_copy(std::string("grüßen"))<<endl; + cout<<" where ß is replaced with SS"<<endl; + cout<<" Greek ὈΔΥΣΣΕΎΣ is correctly converted to "<<to_lower("ὈΔΥΣΣΕΎΣ")<<", instead of incorrect " + <<boost::to_lower_copy(std::string("ὈΔΥΣΣΕΎΣ"))<<endl; + cout<<" where Σ is converted to σ or to ς, according to position in the word"<<endl; + cout<<"Such type of conversion just can't be done using std::toupper that work on character base, also std::toupper is "<<endl; + cout<<"not even applicable when working with variable character length like in UTF-8 or UTF-16 limiting the correct "<<endl; + cout<<"behavior to unicode subset BMP or ASCII only"<<endl; + +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/examples/hello.cpp b/src/boost/libs/locale/examples/hello.cpp new file mode 100644 index 000000000..e1a2d93b9 --- /dev/null +++ b/src/boost/libs/locale/examples/hello.cpp @@ -0,0 +1,41 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale.hpp> +#include <iostream> + +#include <ctime> + +int main() +{ + using namespace boost::locale; + using namespace std; + generator gen; + locale loc=gen(""); + // Create system default locale + + locale::global(loc); + // Make it system global + + cout.imbue(loc); + // Set as default locale for output + + cout <<format("Today {1,date} at {1,time} we had run our first localization example") % time(0) + <<endl; + + cout<<"This is how we show numbers in this locale "<<as::number << 103.34 <<endl; + cout<<"This is how we show currency in this locale "<<as::currency << 103.34 <<endl; + cout<<"This is typical date in the locale "<<as::date << std::time(0) <<endl; + cout<<"This is typical time in the locale "<<as::time << std::time(0) <<endl; + cout<<"This is upper case "<<to_upper("Hello World!")<<endl; + cout<<"This is lower case "<<to_lower("Hello World!")<<endl; + cout<<"This is title case "<<to_title("Hello World!")<<endl; + cout<<"This is fold case "<<fold_case("Hello World!")<<endl; + +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/examples/wboundary.cpp b/src/boost/libs/locale/examples/wboundary.cpp new file mode 100644 index 000000000..a14325faa --- /dev/null +++ b/src/boost/libs/locale/examples/wboundary.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +// +// ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +// +// BIG FAT WARNING FOR Microsoft Visual Studio Users +// +// YOU NEED TO CONVERT THIS SOURCE FILE ENCODING TO UTF-8 WITH BOM ENCODING. +// +// Unfortunately MSVC understands that the source code is encoded as +// UTF-8 only if you add useless BOM in the beginning. +// +// So, before you compile "wide" examples with MSVC, please convert them to text +// files with BOM. There are two very simple ways to do it: +// +// 1. Open file with Notepad and save it from there. It would convert +// it to file with BOM. +// 2. In Visual Studio go File->Advances Save Options... and select +// Unicode (UTF-8 with signature) Codepage 65001 +// +// Note: once converted to UTF-8 with BOM, this source code would not +// compile with other compilers, because no-one uses BOM with UTF-8 today +// because it is absolutely meaningless in context of UTF-8. +// +// ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +// +#include <boost/locale.hpp> +#include <iostream> +#include <cassert> +#include <ctime> + +int main() +{ + using namespace boost::locale; + using namespace std; + + // Create system default locale + generator gen; + locale loc=gen(""); + locale::global(loc); + wcout.imbue(loc); + + // This is needed to prevent C library to + // convert strings to narrow + // instead of C++ on some platforms + std::ios_base::sync_with_stdio(false); + + + wstring text=L"Hello World! あにま! Linux2.6 and Windows7 is word and number. שָלוֹם עוֹלָם!"; + + wcout<<text<<endl; + + boundary::wssegment_index index(boundary::word,text.begin(),text.end()); + boundary::wssegment_index::iterator p,e; + + for(p=index.begin(),e=index.end();p!=e;++p) { + wcout<<L"Part ["<<*p<<L"] has "; + if(p->rule() & boundary::word_number) + wcout<<L"number(s) "; + if(p->rule() & boundary::word_letter) + wcout<<L"letter(s) "; + if(p->rule() & boundary::word_kana) + wcout<<L"kana character(s) "; + if(p->rule() & boundary::word_ideo) + wcout<<L"ideographic character(s) "; + if(p->rule() & boundary::word_none) + wcout<<L"no word characters"; + wcout<<endl; + } + + index.map(boundary::character,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + wcout<<L"|" <<*p ; + } + wcout<<L"|\n\n"; + + index.map(boundary::line,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + wcout<<L"|" <<*p ; + } + wcout<<L"|\n\n"; + + index.map(boundary::sentence,text.begin(),text.end()); + + for(p=index.begin(),e=index.end();p!=e;++p) { + wcout<<L"|" <<*p ; + } + wcout<<"|\n\n"; + +} + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii + diff --git a/src/boost/libs/locale/examples/wconversions.cpp b/src/boost/libs/locale/examples/wconversions.cpp new file mode 100644 index 000000000..d26a2a477 --- /dev/null +++ b/src/boost/libs/locale/examples/wconversions.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +// +// ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +// +// BIG FAT WARNING FOR Microsoft Visual Studio Users +// +// YOU NEED TO CONVERT THIS SOURCE FILE ENCODING TO UTF-8 WITH BOM ENCODING. +// +// Unfortunately MSVC understands that the source code is encoded as +// UTF-8 only if you add useless BOM in the beginning. +// +// So, before you compile "wide" examples with MSVC, please convert them to text +// files with BOM. There are two very simple ways to do it: +// +// 1. Open file with Notepad and save it from there. It would convert +// it to file with BOM. +// 2. In Visual Studio go File->Advances Save Options... and select +// Unicode (UTF-8 with signature) Codepage 65001 +// +// Note: once converted to UTF-8 with BOM, this source code would not +// compile with other compilers, because no-one uses BOM with UTF-8 today +// because it is absolutely meaningless in context of UTF-8. +// +// ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! +// +#include <boost/locale.hpp> +#include <boost/algorithm/string/case_conv.hpp> +#include <iostream> + +#include <ctime> + + +int main() +{ + using namespace boost::locale; + using namespace std; + // Create system default locale + generator gen; + locale loc=gen(""); + locale::global(loc); + wcout.imbue(loc); + + // This is needed to prevent C library to + // convert strings to narrow + // instead of C++ on some platforms + std::ios_base::sync_with_stdio(false); + + + wcout<<L"Correct case conversion can't be done by simple, character by character conversion"<<endl; + wcout<<L"because case conversion is context sensitive and not 1-to-1 conversion"<<endl; + wcout<<L"For example:"<<endl; + wcout<<L" German grüßen correctly converted to "<<to_upper(L"grüßen")<<L", instead of incorrect " + <<boost::to_upper_copy(std::wstring(L"grüßen"))<<endl; + wcout<<L" where ß is replaced with SS"<<endl; + wcout<<L" Greek ὈΔΥΣΣΕΎΣ is correctly converted to "<<to_lower(L"ὈΔΥΣΣΕΎΣ")<<L", instead of incorrect " + <<boost::to_lower_copy(std::wstring(L"ὈΔΥΣΣΕΎΣ"))<<endl; + wcout<<L" where Σ is converted to σ or to ς, according to position in the word"<<endl; + wcout<<L"Such type of conversion just can't be done using std::toupper that work on character base, also std::toupper is "<<endl; + wcout<<L"not fully applicable when working with variable character length like in UTF-8 or UTF-16 limiting the correct "<<endl; + wcout<<L"behavoir to BMP or ASCII only"<<endl; + +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/examples/whello.cpp b/src/boost/libs/locale/examples/whello.cpp new file mode 100644 index 000000000..a224eaf42 --- /dev/null +++ b/src/boost/libs/locale/examples/whello.cpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale.hpp> +#include <iostream> + +#include <ctime> + +int main() +{ + using namespace boost::locale; + using namespace std; + + // Create system default locale + generator gen; + locale loc=gen(""); + locale::global(loc); + wcout.imbue(loc); + + // This is needed to prevent C library to + // convert strings to narrow + // instead of C++ on some platforms + std::ios_base::sync_with_stdio(false); + + + wcout <<wformat(L"Today {1,date} at {1,time} we had run our first localization example") % time(0) + <<endl; + + wcout<<L"This is how we show numbers in this locale "<<as::number << 103.34 <<endl; + wcout<<L"This is how we show currency in this locale "<<as::currency << 103.34 <<endl; + wcout<<L"This is typical date in the locale "<<as::date << std::time(0) <<endl; + wcout<<L"This is typical time in the locale "<<as::time << std::time(0) <<endl; + wcout<<L"This is upper case "<<to_upper(L"Hello World!")<<endl; + wcout<<L"This is lower case "<<to_lower(L"Hello World!")<<endl; + wcout<<L"This is title case "<<to_title(L"Hello World!")<<endl; + wcout<<L"This is fold case "<<fold_case(L"Hello World!")<<endl; + +} + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/index.html b/src/boost/libs/locale/index.html new file mode 100644 index 000000000..80b010d58 --- /dev/null +++ b/src/boost/libs/locale/index.html @@ -0,0 +1,16 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> +<head> + <title>Boost.Locale Documentation</title> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> + <meta http-equiv="refresh" content="0; URL=doc/html/index.html" /> +</head> + +<body> + Automatic redirection failed, please go to <a href= + "doc/html/index.html">doc/html/index.html</a> +</body> +</html> +<!-- Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) Distributed under the Boost Software License, Version 1.0 --> diff --git a/src/boost/libs/locale/meta/libraries.json b/src/boost/libs/locale/meta/libraries.json new file mode 100644 index 000000000..2364222ea --- /dev/null +++ b/src/boost/libs/locale/meta/libraries.json @@ -0,0 +1,14 @@ +{ + "key": "locale", + "name": "Locale", + "authors": [ + "Artyom Beilis" + ], + "description": "Provide localization and Unicode handling tools for C++.", + "category": [ + "String" + ], + "maintainers": [ + "Artyom Beilis <artyomtnk -at- yahoo.com>" + ] +} diff --git a/src/boost/libs/locale/performance/perf_collate.cpp b/src/boost/libs/locale/performance/perf_collate.cpp new file mode 100644 index 000000000..c0721d8cd --- /dev/null +++ b/src/boost/libs/locale/performance/perf_collate.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <iostream> +#include <string> +#include <set> + +#include <boost/locale.hpp> + +using namespace std; +using namespace boost::locale; + +int main(int argc,char **argv) +{ + if(argc!=2) { + std::cerr << "Usage backend locale" << std::endl; + return 1; + } + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select(argv[1]); + generator gen(mgr); + std::locale::global(gen(argv[2])); + /// Set global locale to requested + + /// Create a set that includes all strings sorted according to ABC order + /// std::locale can be used as object for comparison + std::vector<std::string> all; + typedef std::set<std::string,std::locale> set_type; + set_type all_strings; + + /// Read all strings into the set + while(!cin.eof()) { + std::string tmp; + getline(cin,tmp); + all.push_back(tmp); + } + for(int i=0;i<10000;i++) { + std::vector<std::string> tmp = all; + std::sort(tmp.begin(),tmp.end(),std::locale()); + if(i==0) { + for(unsigned j=0;j<tmp.size();j++) + std::cout << tmp[j] << std::endl; + } + } + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/performance/perf_convert.cpp b/src/boost/libs/locale/performance/perf_convert.cpp new file mode 100644 index 000000000..6d69be65f --- /dev/null +++ b/src/boost/libs/locale/performance/perf_convert.cpp @@ -0,0 +1,56 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <iostream> +#include <string> +#include <set> + +#include <boost/locale.hpp> + +using namespace std; +using namespace boost::locale; + +int main(int argc,char **argv) +{ + if(argc!=2) { + std::cerr << "Usage backend locale" << std::endl; + return 1; + } + /// Set global locale to requested + + /// Create a set that includes all strings sorted according to ABC order + /// std::locale can be used as object for comparison + std::vector<std::string> all; + typedef std::set<std::string,std::locale> set_type; + set_type all_strings; + + /// Read all strings into the set + while(!cin.eof()) { + std::string tmp; + getline(cin,tmp); + all.push_back(tmp); + } + + { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select(argv[1]); + generator gen(mgr); + std::locale::global(gen(argv[2])); + for(int i=0;i<10000;i++) { + for(unsigned j=0;j<all.size();j++) { + boost::locale::to_upper(all[j]); + boost::locale::to_lower(all[j]); + if(i==0) { + std::cout << boost::locale::to_upper(all[j]) << std::endl; + std::cout << boost::locale::to_lower(all[j]) << std::endl; + } + } + } + } + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/performance/perf_format.cpp b/src/boost/libs/locale/performance/perf_format.cpp new file mode 100644 index 000000000..417e1ba3e --- /dev/null +++ b/src/boost/libs/locale/performance/perf_format.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <iostream> +#include <string> +#include <set> +#include <ctime> +#include <boost/locale.hpp> + +using namespace std; +using namespace boost::locale; + +int main(int argc,char **argv) +{ + if(argc!=2) { + std::cerr << "Usage backend locale" << std::endl; + return 1; + } + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select(argv[1]); + generator gen(mgr); + std::locale::global(gen(argv[2])); + /// Set global locale to requested + + for(int i=0;i<100000;i++) { + std::ostringstream ss; + for(int j=0;j<5;j++) { + ss << boost::locale::as::datetime << std::time(0) <<" "<< boost::locale::as::number << 13456.345 <<"\n"; + } + if(i==0) + std::cout << ss.str() << std::endl; + } + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/encoding/codepage.cpp b/src/boost/libs/locale/src/encoding/codepage.cpp new file mode 100644 index 000000000..c19e36b8c --- /dev/null +++ b/src/boost/libs/locale/src/encoding/codepage.cpp @@ -0,0 +1,201 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/config.hpp> + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +#define BOOST_LOCALE_WITH_WCONV +#endif + +#ifdef BOOST_LOCALE_WITH_ICONV +#include "iconv_codepage.ipp" +#endif +#ifdef BOOST_LOCALE_WITH_ICU +#include "uconv_codepage.ipp" +#endif +#ifdef BOOST_LOCALE_WITH_WCONV +#include "wconv_codepage.ipp" +#endif + +#include <boost/locale/encoding.hpp> +#include <boost/locale/hold_ptr.hpp> + +#include <string> +#include <cstring> +#include <memory> + +namespace boost { + namespace locale { + namespace conv { + namespace impl { + + std::string convert_between(char const *begin, + char const *end, + char const *to_charset, + char const *from_charset, + method_type how) + { + hold_ptr<converter_between> cvt; + #ifdef BOOST_LOCALE_WITH_ICONV + cvt.reset(new iconv_between()); + if(cvt->open(to_charset,from_charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_ICU + cvt.reset(new uconv_between()); + if(cvt->open(to_charset,from_charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_WCONV + cvt.reset(new wconv_between()); + if(cvt->open(to_charset,from_charset,how)) + return cvt->convert(begin,end); + #endif + throw invalid_charset_error(std::string(to_charset) + " or " + from_charset); + } + + template<typename CharType> + std::basic_string<CharType> convert_to( + char const *begin, + char const *end, + char const *charset, + method_type how) + { + hold_ptr<converter_to_utf<CharType> > cvt; + #ifdef BOOST_LOCALE_WITH_ICONV + cvt.reset(new iconv_to_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_ICU + cvt.reset(new uconv_to_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_WCONV + cvt.reset(new wconv_to_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + throw invalid_charset_error(charset); + } + + template<typename CharType> + std::string convert_from( + CharType const *begin, + CharType const *end, + char const *charset, + method_type how) + { + hold_ptr<converter_from_utf<CharType> > cvt; + #ifdef BOOST_LOCALE_WITH_ICONV + cvt.reset(new iconv_from_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_ICU + cvt.reset(new uconv_from_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + #ifdef BOOST_LOCALE_WITH_WCONV + cvt.reset(new wconv_from_utf<CharType>()); + if(cvt->open(charset,how)) + return cvt->convert(begin,end); + #endif + throw invalid_charset_error(charset); + } + + std::string normalize_encoding(char const *ccharset) + { + std::string charset; + charset.reserve(std::strlen(ccharset)); + while(*ccharset!=0) { + char c=*ccharset++; + if('0' <= c && c<= '9') + charset+=c; + else if('a' <=c && c <='z') + charset+=c; + else if('A' <=c && c <='Z') + charset+=char(c-'A'+'a'); + } + return charset; + } + + + } // impl + + using namespace impl; + + std::string between(char const *begin,char const *end, + std::string const &to_charset,std::string const &from_charset,method_type how) + { + return convert_between(begin,end,to_charset.c_str(),from_charset.c_str(),how); + } + + template<> + std::basic_string<char> to_utf(char const *begin,char const *end,std::string const &charset,method_type how) + { + return convert_to<char>(begin,end,charset.c_str(),how); + } + + template<> + std::string from_utf(char const *begin,char const *end,std::string const &charset,method_type how) + { + return convert_from<char>(begin,end,charset.c_str(),how); + } + + template<> + std::basic_string<wchar_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how) + { + return convert_to<wchar_t>(begin,end,charset.c_str(),how); + } + + template<> + std::string from_utf(wchar_t const *begin,wchar_t const *end,std::string const &charset,method_type how) + { + return convert_from<wchar_t>(begin,end,charset.c_str(),how); + } + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + template<> + std::basic_string<char16_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how) + { + return convert_to<char16_t>(begin,end,charset.c_str(),how); + } + + template<> + std::string from_utf(char16_t const *begin,char16_t const *end,std::string const &charset,method_type how) + { + return convert_from<char16_t>(begin,end,charset.c_str(),how); + } + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + template<> + std::basic_string<char32_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how) + { + return convert_to<char32_t>(begin,end,charset.c_str(),how); + } + + template<> + std::string from_utf(char32_t const *begin,char32_t const *end,std::string const &charset,method_type how) + { + return convert_from<char32_t>(begin,end,charset.c_str(),how); + } + #endif + + + } + } +} + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/encoding/conv.hpp b/src/boost/libs/locale/src/encoding/conv.hpp new file mode 100644 index 000000000..5453aeded --- /dev/null +++ b/src/boost/libs/locale/src/encoding/conv.hpp @@ -0,0 +1,118 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_CONV_IMPL_HPP +#define BOOST_LOCALE_CONV_IMPL_HPP + +#include <boost/locale/config.hpp> +#include <boost/locale/encoding.hpp> +namespace boost { + namespace locale { + namespace conv { + namespace impl { + + template<typename CharType> + char const *utf_name() + { + union { + char first; + uint16_t u16; + uint32_t u32; + } v; + + if(sizeof(CharType) == 1) { + return "UTF-8"; + } + else if(sizeof(CharType) == 2) { + v.u16 = 1; + if(v.first == 1) { + return "UTF-16LE"; + } + else { + return "UTF-16BE"; + } + } + else if(sizeof(CharType) == 4) { + v.u32 = 1; + if(v.first == 1) { + return "UTF-32LE"; + } + else { + return "UTF-32BE"; + } + + } + else { + return "Unknown Character Encoding"; + } + } + + std::string normalize_encoding(char const *encoding); + + inline int compare_encodings(char const *l,char const *r) + { + return normalize_encoding(l).compare(normalize_encoding(r)); + } + + #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + int encoding_to_windows_codepage(char const *ccharset); + #endif + + class converter_between { + public: + typedef char char_type; + + typedef std::string string_type; + + virtual bool open(char const *to_charset,char const *from_charset,method_type how) = 0; + + virtual std::string convert(char const *begin,char const *end) = 0; + + virtual ~converter_between() + { + } + }; + + template<typename CharType> + class converter_from_utf { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + virtual bool open(char const *charset,method_type how) = 0; + + virtual std::string convert(CharType const *begin,CharType const *end) = 0; + + virtual ~converter_from_utf() + { + } + }; + + template<typename CharType> + class converter_to_utf { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + virtual bool open(char const *charset,method_type how) = 0; + + virtual string_type convert(char const *begin,char const *end) = 0; + + virtual ~converter_to_utf() + { + } + }; + } + } + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +#endif diff --git a/src/boost/libs/locale/src/encoding/iconv_codepage.ipp b/src/boost/libs/locale/src/encoding/iconv_codepage.ipp new file mode 100644 index 000000000..276c60b6b --- /dev/null +++ b/src/boost/libs/locale/src/encoding/iconv_codepage.ipp @@ -0,0 +1,214 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP +#define BOOST_LOCALE_IMPL_ICONV_CODEPAGE_HPP + +#include <boost/locale/encoding.hpp> +#include "../util/iconv.hpp" +#include <errno.h> +#include "conv.hpp" +#include <assert.h> +#include <vector> + +namespace boost { +namespace locale { +namespace conv { +namespace impl { + +class iconverter_base { +public: + + iconverter_base() : + cvt_((iconv_t)(-1)) + { + } + + ~iconverter_base() + { + close(); + } + + size_t conv(char const **inbufc,size_t *inchar_left, + char **outbuf,size_t *outchar_left) + { + char **inbuf = const_cast<char **>(inbufc); + return call_iconv(cvt_,inbuf,inchar_left,outbuf,outchar_left); + } + + bool do_open(char const *to,char const *from,method_type how) + { + close(); + cvt_ = iconv_open(to,from); + how_ = how; + return cvt_ != (iconv_t)(-1); + } + + template<typename OutChar,typename InChar> + std::basic_string<OutChar> real_convert(InChar const *ubegin,InChar const *uend) + { + std::basic_string<OutChar> sresult; + + sresult.reserve(uend - ubegin); + + OutChar result[64]; + + char *out_start = reinterpret_cast<char *>(&result[0]); + char const *begin = reinterpret_cast<char const *>(ubegin); + char const *end = reinterpret_cast<char const *>(uend); + + enum { normal , unshifting , done } state = normal; + + while(state!=done) { + + size_t in_left = end - begin; + size_t out_left = sizeof(result); + + char *out_ptr = out_start; + size_t res = 0; + if(in_left == 0) + state = unshifting; + + if(state == normal) + res = conv(&begin,&in_left,&out_ptr,&out_left); + else + res = conv(0,0,&out_ptr,&out_left); + + int err = errno; + + size_t output_count = (out_ptr - out_start) / sizeof(OutChar); + + if(res!=0 && res!=(size_t)(-1)) { + if(how_ == stop) { + throw conversion_error(); + } + } + + sresult.append(&result[0],output_count); + + if(res == (size_t)(-1)) { + if(err == EILSEQ || err == EINVAL) { + if(how_ == stop) { + throw conversion_error(); + } + + if(begin != end) { + begin+=sizeof(InChar); + if(begin >= end) + break; + } + else { + break; + } + } + else if (err==E2BIG) { + continue; + } + else { + // We should never get there + // but if we do + if(how_ == stop) + throw conversion_error(); + else + break; + } + } + if(state == unshifting) + state = done; + } + return sresult; + } + + +private: + + void close() + { + if(cvt_!=(iconv_t)(-1)) { + iconv_close(cvt_); + cvt_ = (iconv_t)(-1); + } + } + + iconv_t cvt_; + + method_type how_; + +}; + +template<typename CharType> +class iconv_from_utf : public converter_from_utf<CharType> +{ +public: + + typedef CharType char_type; + + virtual bool open(char const *charset,method_type how) + { + return self_.do_open(charset,utf_name<CharType>(),how); + } + + virtual std::string convert(char_type const *ubegin,char_type const *uend) + { + return self_.template real_convert<char,char_type>(ubegin,uend); + } + virtual ~iconv_from_utf() {} +private: + iconverter_base self_; +}; + +class iconv_between: public converter_between +{ +public: + virtual bool open(char const *to_charset,char const *from_charset,method_type how) + { + return self_.do_open(to_charset,from_charset,how); + } + virtual std::string convert(char const *begin,char const *end) + { + return self_.real_convert<char,char>(begin,end); + } + virtual ~iconv_between() {} +private: + iconverter_base self_; + +}; + +template<typename CharType> +class iconv_to_utf : public converter_to_utf<CharType> +{ +public: + + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + virtual bool open(char const *charset,method_type how) + { + return self_.do_open(utf_name<CharType>(),charset,how); + } + + virtual string_type convert(char const *begin,char const *end) + { + return self_.template real_convert<char_type,char>(begin,end); + } + virtual ~iconv_to_utf() {} +private: + iconverter_base self_; +}; + + + +} // impl +} // conv +} // locale +} // boost + + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/encoding/uconv_codepage.ipp b/src/boost/libs/locale/src/encoding/uconv_codepage.ipp new file mode 100644 index 000000000..51e7301bb --- /dev/null +++ b/src/boost/libs/locale/src/encoding/uconv_codepage.ipp @@ -0,0 +1,164 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_UCONV_CODEPAGE_HPP +#define BOOST_LOCALE_IMPL_UCONV_CODEPAGE_HPP +#include <boost/locale/encoding.hpp> +#include "conv.hpp" +#include "../icu/icu_util.hpp" +#include "../icu/uconv.hpp" +#include <unicode/ucnv.h> +#include <unicode/ucnv_err.h> +#include <vector> +#include <memory> + +#include <boost/locale/hold_ptr.hpp> + +namespace boost { +namespace locale { +namespace conv { +namespace impl { + template<typename CharType> + class uconv_to_utf : public converter_to_utf<CharType> { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + virtual bool open(char const *charset,method_type how) + { + close(); + try { + cvt_from_.reset(new from_type(charset,how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + cvt_to_.reset(new to_type("UTF-8",how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + } + catch(std::exception const &/*e*/) { + close(); + return false; + } + return true; + } + void close() + { + cvt_from_.reset(); + cvt_to_.reset(); + } + + virtual string_type convert(char const *begin,char const *end) + { + try { + return cvt_to_->std(cvt_from_->icu_checked(begin,end)); + } + catch(std::exception const &/*e*/) { + throw conversion_error(); + } + } + + private: + + typedef impl_icu::icu_std_converter<char> from_type; + typedef impl_icu::icu_std_converter<CharType> to_type; + + hold_ptr<from_type> cvt_from_; + hold_ptr<to_type> cvt_to_; + + }; + + + template<typename CharType> + class uconv_from_utf : public converter_from_utf<CharType> { + public: + typedef CharType char_type; + virtual bool open(char const *charset,method_type how) + { + close(); + try { + cvt_from_.reset(new from_type("UTF-8",how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + cvt_to_.reset(new to_type(charset,how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + } + catch(std::exception const &/*e*/) { + close(); + return false; + } + return true; + } + void close() + { + cvt_from_.reset(); + cvt_to_.reset(); + } + + virtual std::string convert(CharType const *begin,CharType const *end) + { + try { + return cvt_to_->std(cvt_from_->icu_checked(begin,end)); + } + catch(std::exception const &/*e*/) { + throw conversion_error(); + } + } + + private: + + typedef impl_icu::icu_std_converter<CharType> from_type; + typedef impl_icu::icu_std_converter<char> to_type; + + hold_ptr<from_type> cvt_from_; + hold_ptr<to_type> cvt_to_; + + }; + + class uconv_between : public converter_between { + public: + virtual bool open(char const *to_charset,char const *from_charset,method_type how) + { + close(); + try { + cvt_from_.reset(new from_type(from_charset,how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + cvt_to_.reset(new to_type(to_charset,how == skip ? impl_icu::cvt_skip : impl_icu::cvt_stop)); + } + catch(std::exception const &/*e*/) { + close(); + return false; + } + return true; + } + void close() + { + cvt_from_.reset(); + cvt_to_.reset(); + } + + virtual std::string convert(char const *begin,char const *end) + { + try { + return cvt_to_->std(cvt_from_->icu(begin,end)); + } + catch(std::exception const &/*e*/) { + throw conversion_error(); + } + } + + private: + + typedef impl_icu::icu_std_converter<char> from_type; + typedef impl_icu::icu_std_converter<char> to_type; + + hold_ptr<from_type> cvt_from_; + hold_ptr<to_type> cvt_to_; + + }; + + +} // impl +} // conv +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +#endif diff --git a/src/boost/libs/locale/src/encoding/wconv_codepage.ipp b/src/boost/libs/locale/src/encoding/wconv_codepage.ipp new file mode 100644 index 000000000..4ab9ece08 --- /dev/null +++ b/src/boost/libs/locale/src/encoding/wconv_codepage.ipp @@ -0,0 +1,539 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_IMPL_WCONV_CODEPAGE_HPP +#define BOOST_LOCALE_IMPL_WCONV_CODEPAGE_HPP + + +#include <boost/locale/encoding.hpp> +#include <algorithm> +#include <cstring> +#include <string> +#include "conv.hpp" + +#ifndef NOMINMAX +# define NOMINMAX +#endif +#include <windows.h> +#include <vector> + + +namespace boost { +namespace locale { +namespace conv { +namespace impl { + + struct windows_encoding { + char const *name; + unsigned codepage; + unsigned was_tested; + }; + + bool operator<(windows_encoding const &l,windows_encoding const &r) + { + return strcmp(l.name,r.name) < 0; + } + + windows_encoding all_windows_encodings[] = { + { "big5", 950, 0 }, + { "cp1250", 1250, 0 }, + { "cp1251", 1251, 0 }, + { "cp1252", 1252, 0 }, + { "cp1253", 1253, 0 }, + { "cp1254", 1254, 0 }, + { "cp1255", 1255, 0 }, + { "cp1256", 1256, 0 }, + { "cp1257", 1257, 0 }, + { "cp874", 874, 0 }, + { "cp932", 932, 0 }, + { "cp936", 936, 0 }, + { "eucjp", 20932, 0 }, + { "euckr", 51949, 0 }, + { "gb18030", 54936, 0 }, + { "gb2312", 20936, 0 }, + { "gbk", 936, 0 }, + { "iso2022jp", 50220, 0 }, + { "iso2022kr", 50225, 0 }, + { "iso88591", 28591, 0 }, + { "iso885913", 28603, 0 }, + { "iso885915", 28605, 0 }, + { "iso88592", 28592, 0 }, + { "iso88593", 28593, 0 }, + { "iso88594", 28594, 0 }, + { "iso88595", 28595, 0 }, + { "iso88596", 28596, 0 }, + { "iso88597", 28597, 0 }, + { "iso88598", 28598, 0 }, + { "iso88599", 28599, 0 }, + { "koi8r", 20866, 0 }, + { "koi8u", 21866, 0 }, + { "ms936", 936, 0 }, + { "shiftjis", 932, 0 }, + { "sjis", 932, 0 }, + { "usascii", 20127, 0 }, + { "utf8", 65001, 0 }, + { "windows1250", 1250, 0 }, + { "windows1251", 1251, 0 }, + { "windows1252", 1252, 0 }, + { "windows1253", 1253, 0 }, + { "windows1254", 1254, 0 }, + { "windows1255", 1255, 0 }, + { "windows1256", 1256, 0 }, + { "windows1257", 1257, 0 }, + { "windows874", 874, 0 }, + { "windows932", 932, 0 }, + { "windows936", 936, 0 }, + }; + + size_t remove_substitutions(std::vector<char> &v) + { + if(std::find(v.begin(),v.end(),0) == v.end()) { + return v.size(); + } + std::vector<char> v2; + v2.reserve(v.size()); + for(unsigned i=0;i<v.size();i++) { + if(v[i]!=0) + v2.push_back(v[i]); + } + v.swap(v2); + return v.size(); + } + + void multibyte_to_wide_one_by_one(int codepage,char const *begin,char const *end,std::vector<wchar_t> &buf) + { + buf.reserve(end-begin); + while(begin!=end) { + wchar_t wide_buf[4]; + int n = 0; + int len = IsDBCSLeadByteEx(codepage,*begin) ? 2 : 1; + if(len == 2 && begin+1==end) + return; + n = MultiByteToWideChar(codepage,MB_ERR_INVALID_CHARS,begin,len,wide_buf,4); + for(int i=0;i<n;i++) + buf.push_back(wide_buf[i]); + begin+=len; + } + } + + + void multibyte_to_wide(int codepage,char const *begin,char const *end,bool do_skip,std::vector<wchar_t> &buf) + { + if(begin==end) + return; + int n = MultiByteToWideChar(codepage,MB_ERR_INVALID_CHARS,begin,end-begin,0,0); + if(n == 0) { + if(do_skip) { + multibyte_to_wide_one_by_one(codepage,begin,end,buf); + return; + } + throw conversion_error(); + } + + buf.resize(n,0); + if(MultiByteToWideChar(codepage,MB_ERR_INVALID_CHARS,begin,end-begin,&buf.front(),buf.size())==0) + throw conversion_error(); + } + + void wide_to_multibyte_non_zero(int codepage,wchar_t const *begin,wchar_t const *end,bool do_skip,std::vector<char> &buf) + { + if(begin==end) + return; + BOOL substitute = FALSE; + BOOL *substitute_ptr = codepage == 65001 || codepage == 65000 ? 0 : &substitute; + char subst_char = 0; + char *subst_char_ptr = codepage == 65001 || codepage == 65000 ? 0 : &subst_char; + + int n = WideCharToMultiByte(codepage,0,begin,end-begin,0,0,subst_char_ptr,substitute_ptr); + buf.resize(n); + + if(WideCharToMultiByte(codepage,0,begin,end-begin,&buf[0],n,subst_char_ptr,substitute_ptr)==0) + throw conversion_error(); + if(substitute) { + if(do_skip) + remove_substitutions(buf); + else + throw conversion_error(); + } + } + + void wide_to_multibyte(int codepage,wchar_t const *begin,wchar_t const *end,bool do_skip,std::vector<char> &buf) + { + if(begin==end) + return; + buf.reserve(end-begin); + wchar_t const *e = std::find(begin,end,L'\0'); + wchar_t const *b = begin; + for(;;) { + std::vector<char> tmp; + wide_to_multibyte_non_zero(codepage,b,e,do_skip,tmp); + size_t osize = buf.size(); + buf.resize(osize+tmp.size()); + std::copy(tmp.begin(),tmp.end(),buf.begin()+osize); + if(e!=end) { + buf.push_back('\0'); + b=e+1; + e=std::find(b,end,L'0'); + } + else + break; + } + } + + + int encoding_to_windows_codepage(char const *ccharset) + { + std::string charset = normalize_encoding(ccharset); + windows_encoding ref; + ref.name = charset.c_str(); + size_t n = sizeof(all_windows_encodings)/sizeof(all_windows_encodings[0]); + windows_encoding *begin = all_windows_encodings; + windows_encoding *end = all_windows_encodings + n; + windows_encoding *ptr = std::lower_bound(begin,end,ref); + if(ptr!=end && strcmp(ptr->name,charset.c_str())==0) { + if(ptr->was_tested) { + return ptr->codepage; + } + else if(IsValidCodePage(ptr->codepage)) { + // the thread safety is not an issue, maximum + // it would be checked more then once + ptr->was_tested=1; + return ptr->codepage; + } + else { + return -1; + } + } + return -1; + + } + + template<typename CharType> + bool validate_utf16(CharType const *str,unsigned len) + { + CharType const *begin = str; + CharType const *end = str+len; + while(begin!=end) { + utf::code_point c = utf::utf_traits<CharType,2>::template decode<CharType const *>(begin,end); + if(c==utf::illegal || c==utf::incomplete) + return false; + } + return true; + } + + template<typename CharType,typename OutChar> + void clean_invalid_utf16(CharType const *str,unsigned len,std::vector<OutChar> &out) + { + out.reserve(len); + for(unsigned i=0;i<len;i++) { + uint16_t c = static_cast<uint16_t>(str[i]); + + if(0xD800 <= c && c<= 0xDBFF) { + i++; + if(i>=len) + return; + uint16_t c2=static_cast<uint16_t>(str[i]); + if(0xDC00 <= c2 && c2 <= 0xDFFF) { + out.push_back(static_cast<OutChar>(c)); + out.push_back(static_cast<OutChar>(c2)); + } + } + else if(0xDC00 <= c && c <=0xDFFF) + continue; + else + out.push_back(static_cast<OutChar>(c)); + } + } + + + class wconv_between : public converter_between { + public: + wconv_between() : + how_(skip), + to_code_page_ (-1), + from_code_page_ ( -1) + { + } + bool open(char const *to_charset,char const *from_charset,method_type how) + { + how_ = how; + to_code_page_ = encoding_to_windows_codepage(to_charset); + from_code_page_ = encoding_to_windows_codepage(from_charset); + if(to_code_page_ == -1 || from_code_page_ == -1) + return false; + return true; + } + virtual std::string convert(char const *begin,char const *end) + { + if(to_code_page_ == 65001 && from_code_page_ == 65001) + return utf_to_utf<char>(begin,end,how_); + + std::string res; + + std::vector<wchar_t> tmp; // buffer for mb2w + std::wstring tmps; // buffer for utf_to_utf + wchar_t const *wbegin=0; + wchar_t const *wend=0; + + if(from_code_page_ == 65001) { + tmps = utf_to_utf<wchar_t>(begin,end,how_); + if(tmps.empty()) + return res; + wbegin = tmps.c_str(); + wend = wbegin + tmps.size(); + } + else { + multibyte_to_wide(from_code_page_,begin,end,how_ == skip,tmp); + if(tmp.empty()) + return res; + wbegin = &tmp[0]; + wend = wbegin + tmp.size(); + } + + if(to_code_page_ == 65001) { + return utf_to_utf<char>(wbegin,wend,how_); + } + + std::vector<char> ctmp; + wide_to_multibyte(to_code_page_,wbegin,wend,how_ == skip,ctmp); + if(ctmp.empty()) + return res; + res.assign(&ctmp.front(),ctmp.size()); + return res; + } + private: + method_type how_; + int to_code_page_; + int from_code_page_; + }; + + template<typename CharType,int size = sizeof(CharType) > + class wconv_to_utf; + + template<typename CharType,int size = sizeof(CharType) > + class wconv_from_utf; + + template<> + class wconv_to_utf<char,1> : public converter_to_utf<char> , public wconv_between { + public: + virtual bool open(char const *cs,method_type how) + { + return wconv_between::open("UTF-8",cs,how); + } + virtual std::string convert(char const *begin,char const *end) + { + return wconv_between::convert(begin,end); + } + }; + + template<> + class wconv_from_utf<char,1> : public converter_from_utf<char> , public wconv_between { + public: + virtual bool open(char const *cs,method_type how) + { + return wconv_between::open(cs,"UTF-8",how); + } + virtual std::string convert(char const *begin,char const *end) + { + return wconv_between::convert(begin,end); + } + }; + + template<typename CharType> + class wconv_to_utf<CharType,2> : public converter_to_utf<CharType> { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + wconv_to_utf() : + how_(skip), + code_page_(-1) + { + } + + virtual bool open(char const *charset,method_type how) + { + how_ = how; + code_page_ = encoding_to_windows_codepage(charset); + return code_page_ != -1; + } + + virtual string_type convert(char const *begin,char const *end) + { + if(code_page_ == 65001) { + return utf_to_utf<char_type>(begin,end,how_); + } + std::vector<wchar_t> tmp; + multibyte_to_wide(code_page_,begin,end,how_ == skip,tmp); + string_type res; + if(!tmp.empty()) + res.assign(reinterpret_cast<char_type *>(&tmp.front()),tmp.size()); + return res; + } + + private: + method_type how_; + int code_page_; + }; + + template<typename CharType> + class wconv_from_utf<CharType,2> : public converter_from_utf<CharType> { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + wconv_from_utf() : + how_(skip), + code_page_(-1) + { + } + + virtual bool open(char const *charset,method_type how) + { + how_ = how; + code_page_ = encoding_to_windows_codepage(charset); + return code_page_ != -1; + } + + virtual std::string convert(CharType const *begin,CharType const *end) + { + if(code_page_ == 65001) { + return utf_to_utf<char>(begin,end,how_); + } + wchar_t const *wbegin = 0; + wchar_t const *wend = 0; + std::vector<wchar_t> buffer; // if needed + if(begin==end) + return std::string(); + if(validate_utf16(begin,end-begin)) { + wbegin = reinterpret_cast<wchar_t const *>(begin); + wend = reinterpret_cast<wchar_t const *>(end); + } + else { + if(how_ == stop) { + throw conversion_error(); + } + else { + clean_invalid_utf16(begin,end-begin,buffer); + if(!buffer.empty()) { + wbegin = &buffer[0]; + wend = wbegin + buffer.size(); + } + } + } + std::string res; + if(wbegin==wend) + return res; + std::vector<char> ctmp; + wide_to_multibyte(code_page_,wbegin,wend,how_ == skip,ctmp); + if(ctmp.empty()) + return res; + res.assign(&ctmp.front(),ctmp.size()); + return res; + } + + private: + method_type how_; + int code_page_; + }; + + + + template<typename CharType> + class wconv_to_utf<CharType,4> : public converter_to_utf<CharType> { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + wconv_to_utf() : + how_(skip), + code_page_(-1) + { + } + + virtual bool open(char const *charset,method_type how) + { + how_ = how; + code_page_ = encoding_to_windows_codepage(charset); + return code_page_ != -1; + } + + virtual string_type convert(char const *begin,char const *end) + { + if(code_page_ == 65001) { + return utf_to_utf<char_type>(begin,end,how_); + } + std::vector<wchar_t> buf; + multibyte_to_wide(code_page_,begin,end,how_ == skip,buf); + + if(buf.empty()) + return string_type(); + + return utf_to_utf<CharType>(&buf[0],&buf[0]+buf.size(),how_); + } + private: + method_type how_; + int code_page_; + }; + + template<typename CharType> + class wconv_from_utf<CharType,4> : public converter_from_utf<CharType> { + public: + typedef CharType char_type; + + typedef std::basic_string<char_type> string_type; + + wconv_from_utf() : + how_(skip), + code_page_(-1) + { + } + + virtual bool open(char const *charset,method_type how) + { + how_ = how; + code_page_ = encoding_to_windows_codepage(charset); + return code_page_ != -1; + } + + virtual std::string convert(CharType const *begin,CharType const *end) + { + if(code_page_ == 65001) { + return utf_to_utf<char>(begin,end,how_); + } + std::wstring tmp = utf_to_utf<wchar_t>(begin,end,how_); + + std::vector<char> ctmp; + wide_to_multibyte(code_page_,tmp.c_str(),tmp.c_str()+tmp.size(),how_ == skip,ctmp); + std::string res; + if(ctmp.empty()) + return res; + res.assign(&ctmp.front(),ctmp.size()); + return res; + + } + + private: + method_type how_; + int code_page_; + }; + + + + + +} // impl +} // conv +} // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/all_generator.hpp b/src/boost/libs/locale/src/icu/all_generator.hpp new file mode 100644 index 000000000..ca8f26d63 --- /dev/null +++ b/src/boost/libs/locale/src/icu/all_generator.hpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_ALL_GENERATOR_HPP +#define BOOST_LOCALE_IMPL_ALL_GENERATOR_HPP + +#include <boost/locale/generator.hpp> + +namespace boost { + namespace locale { + namespace impl_icu { + struct cdata; + std::locale create_convert(std::locale const &,cdata const &,character_facet_type); // ok + std::locale create_collate(std::locale const &,cdata const &,character_facet_type); // ok + std::locale create_formatting(std::locale const &,cdata const &,character_facet_type); // ok + std::locale create_parsing(std::locale const &,cdata const &,character_facet_type); // ok + std::locale create_codecvt(std::locale const &,std::string const &encoding,character_facet_type); // ok + std::locale create_boundary(std::locale const &,cdata const &,character_facet_type); // ok + std::locale create_calendar(std::locale const &,cdata const &); // ok + + } + } +} + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/boundary.cpp b/src/boost/libs/locale/src/icu/boundary.cpp new file mode 100644 index 000000000..8d2651042 --- /dev/null +++ b/src/boost/libs/locale/src/icu/boundary.cpp @@ -0,0 +1,231 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/boundary.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/hold_ptr.hpp> +#include <unicode/uversion.h> +#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 306 +#include <unicode/utext.h> +#endif +#include <unicode/brkiter.h> +#include <unicode/rbbi.h> + +#include "cdata.hpp" +#include "all_generator.hpp" +#include "icu_util.hpp" +#include "uconv.hpp" + +namespace boost { +namespace locale { +namespace boundary { +namespace impl_icu { + +using namespace boost::locale::impl_icu; + +index_type map_direct(boundary_type t,icu::BreakIterator *it,int reserve) +{ + index_type indx; + indx.reserve(reserve); +#if U_ICU_VERSION_MAJOR_NUM >= 52 + icu::BreakIterator *rbbi=it; +#else + icu::RuleBasedBreakIterator *rbbi=dynamic_cast<icu::RuleBasedBreakIterator *>(it); +#endif + + indx.push_back(break_info()); + it->first(); + int pos=0; + while((pos=it->next())!=icu::BreakIterator::DONE) { + indx.push_back(break_info(pos)); + /// Character does not have any specific break types + if(t!=character && rbbi) { + // + // There is a collapse for MSVC: int32_t defined by both boost::cstdint and icu... + // So need to pick one ;( + // + std::vector< ::int32_t> buffer; + ::int32_t membuf[8]={0}; // try not to use memory allocation if possible + ::int32_t *buf=membuf; + + UErrorCode err=U_ZERO_ERROR; + int n = rbbi->getRuleStatusVec(buf,8,err); + + if(err == U_BUFFER_OVERFLOW_ERROR) { + buf=&buffer.front(); + buffer.resize(n,0); + n = rbbi->getRuleStatusVec(buf,buffer.size(),err); + } + + check_and_throw_icu_error(err); + + for(int i=0;i<n;i++) { + switch(t) { + case word: + if(UBRK_WORD_NONE<=buf[i] && buf[i]<UBRK_WORD_NONE_LIMIT) + indx.back().rule |= word_none; + else if(UBRK_WORD_NUMBER<=buf[i] && buf[i]<UBRK_WORD_NUMBER_LIMIT) + indx.back().rule |= word_number; + else if(UBRK_WORD_LETTER<=buf[i] && buf[i]<UBRK_WORD_LETTER_LIMIT) + indx.back().rule |= word_letter; + else if(UBRK_WORD_KANA<=buf[i] && buf[i]<UBRK_WORD_KANA_LIMIT) + indx.back().rule |= word_kana; + else if(UBRK_WORD_IDEO<=buf[i] && buf[i]<UBRK_WORD_IDEO_LIMIT) + indx.back().rule |= word_ideo; + break; + + case line: + if(UBRK_LINE_SOFT<=buf[i] && buf[i]<UBRK_LINE_SOFT_LIMIT) + indx.back().rule |= line_soft; + else if(UBRK_LINE_HARD<=buf[i] && buf[i]<UBRK_LINE_HARD_LIMIT) + indx.back().rule |= line_hard; + break; + + case sentence: + if(UBRK_SENTENCE_TERM<=buf[i] && buf[i]<UBRK_SENTENCE_TERM_LIMIT) + indx.back().rule |= sentence_term; + else if(UBRK_SENTENCE_SEP<=buf[i] && buf[i]<UBRK_SENTENCE_SEP_LIMIT) + indx.back().rule |= sentence_sep; + break; + default: + ; + } + } + } + else { + indx.back().rule |=character_any; // Baisc mark... for character + } + } + return indx; +} + +icu::BreakIterator *get_iterator(boundary_type t,icu::Locale const &loc) +{ + UErrorCode err=U_ZERO_ERROR; + hold_ptr<icu::BreakIterator> bi; + switch(t) { + case character: + bi.reset(icu::BreakIterator::createCharacterInstance(loc,err)); + break; + case word: + bi.reset(icu::BreakIterator::createWordInstance(loc,err)); + break; + case sentence: + bi.reset(icu::BreakIterator::createSentenceInstance(loc,err)); + break; + case line: + bi.reset(icu::BreakIterator::createLineInstance(loc,err)); + break; + default: + throw std::runtime_error("Invalid iteration type"); + } + check_and_throw_icu_error(err); + if(!bi.get()) + throw std::runtime_error("Failed to create break iterator"); + return bi.release(); +} + + +template<typename CharType> +index_type do_map(boundary_type t,CharType const *begin,CharType const *end,icu::Locale const &loc,std::string const &encoding) +{ + index_type indx; + hold_ptr<icu::BreakIterator> bi(get_iterator(t,loc)); + +#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 306 + UErrorCode err=U_ZERO_ERROR; + if(sizeof(CharType) == 2 || (sizeof(CharType)==1 && encoding=="UTF-8")) + { + UText *ut=0; + try { + if(sizeof(CharType)==1) + ut=utext_openUTF8(0,reinterpret_cast<char const *>(begin),end-begin,&err); + else // sizeof(CharType)==2 + ut=utext_openUChars(0,reinterpret_cast<UChar const *>(begin),end-begin,&err); + + check_and_throw_icu_error(err); + err=U_ZERO_ERROR; + if(!ut) throw std::runtime_error("Failed to create UText"); + bi->setText(ut,err); + check_and_throw_icu_error(err); + index_type res=map_direct(t,bi.get(),end-begin); + indx.swap(res); + } + catch(...) { + if(ut) + utext_close(ut); + throw; + } + if(ut) utext_close(ut); + } + else +#endif + { + icu_std_converter<CharType> cvt(encoding); + icu::UnicodeString str=cvt.icu(begin,end); + bi->setText(str); + index_type indirect = map_direct(t,bi.get(),str.length()); + indx=indirect; + for(size_t i=1;i<indirect.size();i++) { + size_t offset_inderect=indirect[i-1].offset; + size_t diff = indirect[i].offset - offset_inderect; + size_t offset_direct=indx[i-1].offset; + indx[i].offset=offset_direct + cvt.cut(str,begin,end,diff,offset_inderect,offset_direct); + } + } + return indx; +} // do_map + +template<typename CharType> +class boundary_indexing_impl : public boundary_indexing<CharType> { +public: + boundary_indexing_impl(cdata const &data) : + locale_(data.locale), + encoding_(data.encoding) + { + } + index_type map(boundary_type t,CharType const *begin,CharType const *end) const + { + return do_map<CharType>(t,begin,end,locale_,encoding_); + } +private: + icu::Locale locale_; + std::string encoding_; +}; + + + +} // impl_icu +} // boundary + +namespace impl_icu { + std::locale create_boundary(std::locale const &in,cdata const &cd,character_facet_type type) + { + using namespace boost::locale::boundary::impl_icu; + switch(type) { + case char_facet: + return std::locale(in,new boundary_indexing_impl<char>(cd)); + case wchar_t_facet: + return std::locale(in,new boundary_indexing_impl<wchar_t>(cd)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(in,new boundary_indexing_impl<char16_t>(cd)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(in,new boundary_indexing_impl<char32_t>(cd)); + #endif + default: + return in; + } + } +} // impl_icu + +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/cdata.hpp b/src/boost/libs/locale/src/icu/cdata.hpp new file mode 100644 index 000000000..2bffeab4c --- /dev/null +++ b/src/boost/libs/locale/src/icu/cdata.hpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_ICU_CDATA_HPP +#define BOOST_LOCALE_ICU_CDATA_HPP + +#include <unicode/locid.h> +#include <string> + +namespace boost { + namespace locale { + namespace impl_icu { + struct cdata { + icu::Locale locale; + std::string encoding; + bool utf8; + }; + } + } +} + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/codecvt.cpp b/src/boost/libs/locale/src/icu/codecvt.cpp new file mode 100644 index 000000000..2cecdb7dd --- /dev/null +++ b/src/boost/libs/locale/src/icu/codecvt.cpp @@ -0,0 +1,159 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/encoding.hpp> +#include <boost/locale/encoding_errors.hpp> +#include "../encoding/conv.hpp" +#include "all_generator.hpp" +#include "uconv.hpp" +#include <unicode/ucnv.h> +#include <unicode/ucnv_err.h> +#include <boost/locale/util.hpp> +#include <boost/locale/hold_ptr.hpp> +#include "codecvt.hpp" + +#ifdef BOOST_MSVC +# pragma warning(disable : 4244) // loose data +#endif + +#include "icu_util.hpp" +#include <vector> +namespace boost { +namespace locale { +namespace impl_icu { + class uconv_converter : public util::base_converter { + public: + + uconv_converter(std::string const &encoding) : + encoding_(encoding) + { + UErrorCode err=U_ZERO_ERROR; + + // No need to check err each time, this + // is how ICU works. + cvt_ = ucnv_open(encoding.c_str(),&err); + ucnv_setFromUCallBack(cvt_,UCNV_FROM_U_CALLBACK_STOP,0,0,0,&err); + ucnv_setToUCallBack(cvt_,UCNV_TO_U_CALLBACK_STOP,0,0,0,&err); + + if(!cvt_ || U_FAILURE(err)) { + if(cvt_) + ucnv_close(cvt_); + throw conv::invalid_charset_error(encoding); + } + + max_len_ = ucnv_getMaxCharSize(cvt_); + } + + virtual ~uconv_converter() + { + ucnv_close(cvt_); + } + + virtual bool is_thread_safe() const + { + return false; + } + + virtual uconv_converter *clone() const + { + return new uconv_converter(encoding_); + } + + uint32_t to_unicode(char const *&begin,char const *end) + { + UErrorCode err=U_ZERO_ERROR; + char const *tmp = begin; + UChar32 c=ucnv_getNextUChar(cvt_,&tmp,end,&err); + ucnv_reset(cvt_); + if(err == U_TRUNCATED_CHAR_FOUND) { + return incomplete; + } + if(U_FAILURE(err)) { + return illegal; + } + + begin = tmp; + return c; + } + + uint32_t from_unicode(uint32_t u,char *begin,char const *end) + { + UChar code_point[2]={0}; + int len; + if(u<=0xFFFF) { + if(0xD800 <=u && u<= 0xDFFF) // No surragates + return illegal; + code_point[0]=u; + len=1; + } + else { + u-=0x10000; + code_point[0]=0xD800 | (u>>10); + code_point[1]=0xDC00 | (u & 0x3FF); + len=2; + } + UErrorCode err=U_ZERO_ERROR; + int olen = ucnv_fromUChars(cvt_,begin,end-begin,code_point,len,&err); + ucnv_reset(cvt_); + if(err == U_BUFFER_OVERFLOW_ERROR) + return incomplete; + if(U_FAILURE(err)) + return illegal; + return olen; + } + + virtual int max_len() const + { + return max_len_; + } + + private: + std::string encoding_; + UConverter *cvt_; + int max_len_; + }; + + util::base_converter *create_uconv_converter(std::string const &encoding) + { + hold_ptr<util::base_converter> cvt; + try { + cvt.reset(new uconv_converter(encoding)); + } + catch(std::exception const &/*e*/) + { + // no encoding so we return empty pointer + } + return cvt.release(); + } + + std::locale create_codecvt(std::locale const &in,std::string const &encoding,character_facet_type type) + { + if(conv::impl::normalize_encoding(encoding.c_str())=="utf8") + return util::create_utf8_codecvt(in,type); + + try { + return util::create_simple_codecvt(in,encoding,type); + } + catch(boost::locale::conv::invalid_charset_error const &) { + hold_ptr<util::base_converter> cvt; + try { + cvt.reset(create_uconv_converter(encoding)); + } + catch(std::exception const &/*e*/) + { + cvt.reset(new util::base_converter()); + } + return util::create_codecvt_from_pointer(in,cvt.release(),type); + } + } + +} // impl_icu +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/codecvt.hpp b/src/boost/libs/locale/src/icu/codecvt.hpp new file mode 100644 index 000000000..1e3987901 --- /dev/null +++ b/src/boost/libs/locale/src/icu/codecvt.hpp @@ -0,0 +1,24 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_ICU_CODECVT_HPP +#define BOOST_LOCALE_IMPL_ICU_CODECVT_HPP +#include <boost/locale/config.hpp> +#include <boost/locale/util.hpp> +#include <memory> +namespace boost { +namespace locale { +namespace impl_icu { + BOOST_LOCALE_DECL + util::base_converter *create_uconv_converter(std::string const &encoding); + +} // impl_icu +} // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/collator.cpp b/src/boost/libs/locale/src/icu/collator.cpp new file mode 100644 index 000000000..7f1ea6ae5 --- /dev/null +++ b/src/boost/libs/locale/src/icu/collator.cpp @@ -0,0 +1,201 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/collator.hpp> +#include <boost/locale/generator.hpp> +#include <boost/thread.hpp> +#include <vector> +#include <limits> + +#include "cdata.hpp" +#include "all_generator.hpp" +#include "uconv.hpp" +#include "../shared/mo_hash.hpp" + +#include <unicode/coll.h> +#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402 +# include <unicode/stringpiece.h> +#endif + +namespace boost { + namespace locale { + namespace impl_icu { + template<typename CharType> + class collate_impl : public collator<CharType> + { + public: + typedef typename collator<CharType>::level_type level_type; + level_type limit(level_type level) const + { + if(level < 0) + level=collator_base::primary; + else if(level >= level_count) + level = static_cast<level_type>(level_count - 1); + return level; + } + + #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402 + int do_utf8_compare( level_type level, + char const *b1,char const *e1, + char const *b2,char const *e2, + UErrorCode &status) const + { + icu::StringPiece left (b1,e1-b1); + icu::StringPiece right(b2,e2-b2); + return get_collator(level)->compareUTF8(left,right,status); + + } + #endif + + int do_ustring_compare( level_type level, + CharType const *b1,CharType const *e1, + CharType const *b2,CharType const *e2, + UErrorCode &status) const + { + icu::UnicodeString left=cvt_.icu(b1,e1); + icu::UnicodeString right=cvt_.icu(b2,e2); + return get_collator(level)->compare(left,right,status); + } + + int do_real_compare(level_type level, + CharType const *b1,CharType const *e1, + CharType const *b2,CharType const *e2, + UErrorCode &status) const + { + return do_ustring_compare(level,b1,e1,b2,e2,status); + } + + virtual int do_compare( level_type level, + CharType const *b1,CharType const *e1, + CharType const *b2,CharType const *e2) const + { + UErrorCode status=U_ZERO_ERROR; + + int res = do_real_compare(level,b1,e1,b2,e2,status); + + if(U_FAILURE(status)) + throw std::runtime_error(std::string("Collation failed:") + u_errorName(status)); + if(res < 0) + return -1; + else if(res > 0) + return 1; + return 0; + } + + std::vector<uint8_t> do_basic_transform(level_type level,CharType const *b,CharType const *e) const + { + icu::UnicodeString str=cvt_.icu(b,e); + std::vector<uint8_t> tmp; + tmp.resize(str.length()); + icu::Collator *collate = get_collator(level); + int len = collate->getSortKey(str,&tmp[0],tmp.size()); + if(len > int(tmp.size())) { + tmp.resize(len); + collate->getSortKey(str,&tmp[0],tmp.size()); + } + else + tmp.resize(len); + return tmp; + } + std::basic_string<CharType> do_transform(level_type level,CharType const *b,CharType const *e) const + { + std::vector<uint8_t> tmp = do_basic_transform(level,b,e); + return std::basic_string<CharType>(tmp.begin(),tmp.end()); + } + + long do_hash(level_type level,CharType const *b,CharType const *e) const + { + std::vector<uint8_t> tmp = do_basic_transform(level,b,e); + tmp.push_back(0); + return gnu_gettext::pj_winberger_hash_function(reinterpret_cast<char *>(&tmp.front())); + } + + collate_impl(cdata const &d) : + cvt_(d.encoding), + locale_(d.locale), + is_utf8_(d.utf8) + { + + } + icu::Collator *get_collator(level_type ilevel) const + { + int l = limit(ilevel); + static const icu::Collator::ECollationStrength levels[level_count] = + { + icu::Collator::PRIMARY, + icu::Collator::SECONDARY, + icu::Collator::TERTIARY, + icu::Collator::QUATERNARY, + icu::Collator::IDENTICAL + }; + + icu::Collator *col = collates_[l].get(); + if(col) + return col; + + UErrorCode status=U_ZERO_ERROR; + + collates_[l].reset(icu::Collator::createInstance(locale_,status)); + + if(U_FAILURE(status)) + throw std::runtime_error(std::string("Creation of collate failed:") + u_errorName(status)); + + collates_[l]->setStrength(levels[l]); + return collates_[l].get(); + } + + private: + static const int level_count = 5; + icu_std_converter<CharType> cvt_; + icu::Locale locale_; + mutable boost::thread_specific_ptr<icu::Collator> collates_[level_count]; + bool is_utf8_; + }; + + + #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402 + template<> + int collate_impl<char>::do_real_compare( + level_type level, + char const *b1,char const *e1, + char const *b2,char const *e2, + UErrorCode &status) const + { + if(is_utf8_) + return do_utf8_compare(level,b1,e1,b2,e2,status); + else + return do_ustring_compare(level,b1,e1,b2,e2,status); + } + #endif + + std::locale create_collate(std::locale const &in,cdata const &cd,character_facet_type type) + { + switch(type) { + case char_facet: + return std::locale(in,new collate_impl<char>(cd)); + case wchar_t_facet: + return std::locale(in,new collate_impl<wchar_t>(cd)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(in,new collate_impl<char16_t>(cd)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(in,new collate_impl<char32_t>(cd)); + #endif + default: + return in; + } + } + + } /// impl_icu + + } // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/conversion.cpp b/src/boost/libs/locale/src/icu/conversion.cpp new file mode 100644 index 000000000..193d64714 --- /dev/null +++ b/src/boost/libs/locale/src/icu/conversion.cpp @@ -0,0 +1,212 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/conversion.hpp> +#include "all_generator.hpp" +#include <unicode/normlzr.h> +#include <unicode/ustring.h> +#include <unicode/locid.h> +#include <unicode/uversion.h> +#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 308 +#include <unicode/ucasemap.h> +#define WITH_CASE_MAPS +#endif + + +#include "cdata.hpp" +#include "uconv.hpp" + +#include <vector> + +namespace boost { +namespace locale { +namespace impl_icu { + + + namespace { + void normalize_string(icu::UnicodeString &str,int flags) + { + UErrorCode code=U_ZERO_ERROR; + UNormalizationMode mode=UNORM_DEFAULT; + switch(flags) { + case norm_nfd: + mode=UNORM_NFD; + break; + case norm_nfc: + mode=UNORM_NFC; + break; + case norm_nfkd: + mode=UNORM_NFKD; + break; + case norm_nfkc: + mode=UNORM_NFKC; + break; + } + icu::UnicodeString tmp; + icu::Normalizer::normalize(str,mode,0,tmp,code); + + check_and_throw_icu_error(code); + + str=tmp; + } + } + + + template<typename CharType> + class converter_impl : public converter<CharType> { + public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + converter_impl(cdata const &d) : + locale_(d.locale), + encoding_(d.encoding) + { + } + + virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int flags = 0) const + { + icu_std_converter<char_type> cvt(encoding_); + icu::UnicodeString str=cvt.icu(begin,end); + switch(how) { + case converter_base::normalization: + normalize_string(str,flags); + break; + case converter_base::upper_case: + str.toUpper(locale_); + break; + case converter_base::lower_case: + str.toLower(locale_); + break; + case converter_base::title_case: + str.toTitle(0,locale_); + break; + case converter_base::case_folding: + str.foldCase(); + break; + default: + ; + } + return cvt.std(str); + } + + private: + icu::Locale locale_; + std::string encoding_; + }; // converter_impl + + #ifdef WITH_CASE_MAPS + class raii_casemap { + raii_casemap(raii_casemap const &); + void operator = (raii_casemap const&); + public: + raii_casemap(std::string const &locale_id) : + map_(0) + { + UErrorCode err=U_ZERO_ERROR; + map_ = ucasemap_open(locale_id.c_str(),0,&err); + check_and_throw_icu_error(err); + if(!map_) + throw std::runtime_error("Failed to create UCaseMap"); + } + template<typename Conv> + std::string convert(Conv func,char const *begin,char const *end) const + { + std::vector<char> buf((end-begin)*11/10+1); + UErrorCode err=U_ZERO_ERROR; + int size = func(map_,&buf.front(),buf.size(),begin,end-begin,&err); + if(err == U_BUFFER_OVERFLOW_ERROR) { + err = U_ZERO_ERROR; + buf.resize(size+1); + size = func(map_,&buf.front(),buf.size(),begin,end-begin,&err); + } + check_and_throw_icu_error(err); + return std::string(&buf.front(),size); + } + ~raii_casemap() + { + ucasemap_close(map_); + } + private: + UCaseMap *map_; + }; + + class utf8_converter_impl : public converter<char> { + public: + + utf8_converter_impl(cdata const &d) : + locale_id_(d.locale.getName()), + map_(locale_id_) + { + } + + virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int flags = 0) const + { + + if(how == converter_base::normalization) { + icu_std_converter<char> cvt("UTF-8"); + icu::UnicodeString str=cvt.icu(begin,end); + normalize_string(str,flags); + return cvt.std(str); + } + + switch(how) + { + case converter_base::upper_case: + return map_.convert(ucasemap_utf8ToUpper,begin,end); + case converter_base::lower_case: + return map_.convert(ucasemap_utf8ToLower,begin,end); + case converter_base::title_case: + { + // Non-const method, so need to create a separate map + raii_casemap map(locale_id_); + return map.convert(ucasemap_utf8ToTitle,begin,end); + } + case converter_base::case_folding: + return map_.convert(ucasemap_utf8FoldCase,begin,end); + default: + return std::string(begin,end-begin); + } + } + private: + std::string locale_id_; + raii_casemap map_; + }; // converter_impl + +#endif // WITH_CASE_MAPS + + std::locale create_convert(std::locale const &in,cdata const &cd,character_facet_type type) + { + switch(type) { + case char_facet: + #ifdef WITH_CASE_MAPS + if(cd.utf8) + return std::locale(in,new utf8_converter_impl(cd)); + #endif + return std::locale(in,new converter_impl<char>(cd)); + case wchar_t_facet: + return std::locale(in,new converter_impl<wchar_t>(cd)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(in,new converter_impl<char16_t>(cd)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(in,new converter_impl<char32_t>(cd)); + #endif + default: + return in; + } + } + + +} // impl_icu +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/date_time.cpp b/src/boost/libs/locale/src/icu/date_time.cpp new file mode 100644 index 000000000..1c872c37e --- /dev/null +++ b/src/boost/libs/locale/src/icu/date_time.cpp @@ -0,0 +1,292 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/date_time_facet.hpp> +#include <boost/locale/date_time.hpp> +#include <boost/locale/formatting.hpp> +#include <boost/locale/hold_ptr.hpp> +#include "all_generator.hpp" + +#include <boost/thread.hpp> +#include <unicode/calendar.h> +#include <unicode/gregocal.h> +#include <unicode/utypes.h> + +#include <memory> +#include <math.h> + +#include "cdata.hpp" +#include "uconv.hpp" +#include "time_zone.hpp" + +#include <iostream> + + +namespace boost { +namespace locale { +namespace impl_icu { + + static void check_and_throw_dt(UErrorCode &e) + { + if(U_FAILURE(e)) { + throw date_time_error(u_errorName(e)); + } + } + using period::marks::period_mark; + + static UCalendarDateFields to_icu(period::marks::period_mark f) + { + using namespace period::marks; + + switch(f) { + case era: return UCAL_ERA; + case year: return UCAL_YEAR; + case extended_year: return UCAL_EXTENDED_YEAR; + case month: return UCAL_MONTH; + case day: return UCAL_DATE; + case day_of_year: return UCAL_DAY_OF_YEAR; + case day_of_week: return UCAL_DAY_OF_WEEK; + case day_of_week_in_month: return UCAL_DAY_OF_WEEK_IN_MONTH; + case day_of_week_local: return UCAL_DOW_LOCAL; + case hour: return UCAL_HOUR_OF_DAY; + case hour_12: return UCAL_HOUR; + case am_pm: return UCAL_AM_PM; + case minute: return UCAL_MINUTE; + case second: return UCAL_SECOND; + case week_of_year: return UCAL_WEEK_OF_YEAR; + case week_of_month: return UCAL_WEEK_OF_MONTH; + default: + throw std::invalid_argument("Invalid date_time period type"); + } + } + + + class calendar_impl : public abstract_calendar { + public: + + calendar_impl(cdata const &dat) + { + UErrorCode err=U_ZERO_ERROR; + calendar_.reset(icu::Calendar::createInstance(dat.locale,err)); + check_and_throw_dt(err); + #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM < 402 + // workaround old/invalid data, it should be 4 in general + calendar_->setMinimalDaysInFirstWeek(4); + #endif + encoding_ = dat.encoding; + } + calendar_impl(calendar_impl const &other) + { + calendar_.reset(other.calendar_->clone()); + encoding_ = other.encoding_; + } + + calendar_impl *clone() const + { + return new calendar_impl(*this); + } + + void set_value(period::marks::period_mark p,int value) + { + calendar_->set(to_icu(p),int32_t(value)); + } + + int get_value(period::marks::period_mark p,value_type type) const + { + UErrorCode err=U_ZERO_ERROR; + int v=0; + if(p==period::marks::first_day_of_week) { + guard l(lock_); + v=calendar_->getFirstDayOfWeek(err); + } + else { + UCalendarDateFields uper=to_icu(p); + guard l(lock_); + switch(type) { + case absolute_minimum: + v=calendar_->getMinimum(uper); + break; + case actual_minimum: + v=calendar_->getActualMinimum(uper,err); + break; + case greatest_minimum: + v=calendar_->getGreatestMinimum(uper); + break; + case current: + v=calendar_->get(uper,err); + break; + case least_maximum: + v=calendar_->getLeastMaximum(uper); + break; + case actual_maximum: + v=calendar_->getActualMaximum(uper,err); + break; + case absolute_maximum: + v=calendar_->getMaximum(uper); + break; + } + } + check_and_throw_dt(err); + return v; + } + + virtual void set_time(posix_time const &p) + { + double utime = p.seconds * 1000.0 + p.nanoseconds / 1000000.0; + UErrorCode code=U_ZERO_ERROR; + calendar_->setTime(utime,code); + check_and_throw_dt(code); + } + virtual void normalize() + { + // Can't call complete() explicitly (protected) + // calling get wich calls complete + UErrorCode code=U_ZERO_ERROR; + calendar_->get(UCAL_YEAR,code); + check_and_throw_dt(code); + } + virtual posix_time get_time() const + { + + UErrorCode code=U_ZERO_ERROR; + double rtime = 0; + { + guard l(lock_); + rtime = calendar_->getTime(code); + } + check_and_throw_dt(code); + rtime/=1000.0; + double secs = floor(rtime); + posix_time res; + res.seconds = static_cast<int64_t>(secs); + res.nanoseconds = static_cast<uint32_t>((rtime - secs) / 1e9); + if(res.nanoseconds > 999999999) + res.nanoseconds = 999999999; + return res; + } + virtual void set_option(calendar_option_type opt,int /*v*/) + { + switch(opt) { + case is_gregorian: + throw date_time_error("is_gregorian is not settable options for calendar"); + case is_dst: + throw date_time_error("is_dst is not settable options for calendar"); + default: + ; + } + } + virtual int get_option(calendar_option_type opt) const + { + switch(opt) { + case is_gregorian: + return dynamic_cast<icu::GregorianCalendar const *>(calendar_.get())!=0; + case is_dst: + { + guard l(lock_); + UErrorCode err = U_ZERO_ERROR; + bool res = ( calendar_->inDaylightTime(err) != 0 ); + check_and_throw_dt(err); + return res; + } + default: + return 0; + } + } + virtual void adjust_value(period::marks::period_mark p,update_type u,int difference) + { + UErrorCode err=U_ZERO_ERROR; + switch(u) { + case move: + calendar_->add(to_icu(p),difference,err); + break; + case roll: + calendar_->roll(to_icu(p),difference,err); + break; + } + check_and_throw_dt(err); + } + virtual int difference(abstract_calendar const *other_ptr,period::marks::period_mark p) const + { + UErrorCode err=U_ZERO_ERROR; + double other_time = 0; + // + // fieldDifference has side effect of moving calendar (WTF?) + // So we clone it for performing this operation + // + hold_ptr<icu::Calendar> self(calendar_->clone()); + + calendar_impl const *other_cal=dynamic_cast<calendar_impl const *>(other_ptr); + if(other_cal){ + guard l(other_cal->lock_); + other_time = other_cal->calendar_->getTime(err); + check_and_throw_dt(err); + } + else { + posix_time p = other_ptr->get_time(); + other_time = p.seconds * 1000.0 + p.nanoseconds / 1000000.0; + } + + int diff = self->fieldDifference(other_time,to_icu(p),err); + + check_and_throw_dt(err); + return diff; + } + virtual void set_timezone(std::string const &tz) + { + calendar_->adoptTimeZone(get_time_zone(tz)); + } + virtual std::string get_timezone() const + { + icu::UnicodeString tz; + calendar_->getTimeZone().getID(tz); + icu_std_converter<char> cvt(encoding_); + return cvt.std(tz); + } + virtual bool same(abstract_calendar const *other) const + { + calendar_impl const *oc=dynamic_cast<calendar_impl const *>(other); + if(!oc) + return false; + return calendar_->isEquivalentTo(*oc->calendar_)!=0; + } + + private: + typedef boost::unique_lock<boost::mutex> guard; + mutable boost::mutex lock_; + std::string encoding_; + hold_ptr<icu::Calendar> calendar_; + }; + + class icu_calendar_facet : public calendar_facet { + public: + icu_calendar_facet(cdata const &d,size_t refs = 0) : + calendar_facet(refs), + data_(d) + { + } + virtual abstract_calendar *create_calendar() const + { + return new calendar_impl(data_); + } + private: + cdata data_; + }; + + std::locale create_calendar(std::locale const &in,cdata const &d) + { + return std::locale(in,new icu_calendar_facet(d)); + } + +} // impl_icu +} // locale +} // boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/icu/formatter.cpp b/src/boost/libs/locale/src/icu/formatter.cpp new file mode 100644 index 000000000..2af18eee9 --- /dev/null +++ b/src/boost/libs/locale/src/icu/formatter.cpp @@ -0,0 +1,618 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/formatting.hpp> +#include "formatter.hpp" +#include <boost/locale/info.hpp> +#include "uconv.hpp" + + +#include <unicode/numfmt.h> +#include <unicode/rbnf.h> +#include <unicode/datefmt.h> +#include <unicode/smpdtfmt.h> +#include <unicode/decimfmt.h> + +#include <limits> + +#include <iostream> + +#include "predefined_formatters.hpp" +#include "time_zone.hpp" + +#ifdef BOOST_MSVC +# pragma warning(disable : 4244) // lose data +#endif + + +namespace boost { +namespace locale { + namespace impl_icu { + + + std::locale::id icu_formatters_cache::id; + + namespace { + struct init { init() { std::has_facet<icu_formatters_cache>(std::locale::classic()); } } instance; + } + + + template<typename CharType> + class number_format : public formatter<CharType> { + public: + typedef CharType char_type; + typedef std::basic_string<CharType> string_type; + + virtual string_type format(double value,size_t &code_points) const + { + icu::UnicodeString tmp; + icu_fmt_->format(value,tmp); + code_points=tmp.countChar32(); + return cvt_.std(tmp); + } + virtual string_type format(int64_t value,size_t &code_points) const + { + icu::UnicodeString tmp; + icu_fmt_->format(static_cast< ::int64_t>(value),tmp); + code_points=tmp.countChar32(); + return cvt_.std(tmp); + } + + virtual string_type format(int32_t value,size_t &code_points) const + { + icu::UnicodeString tmp; + #ifdef __SUNPRO_CC + icu_fmt_->format(static_cast<int>(value),tmp); + #else + icu_fmt_->format(::int32_t(value),tmp); + #endif + code_points=tmp.countChar32(); + return cvt_.std(tmp); + } + + virtual size_t parse(string_type const &str,double &value) const + { + return do_parse(str,value); + } + + virtual size_t parse(string_type const &str,int64_t &value) const + { + return do_parse(str,value); + } + virtual size_t parse(string_type const &str,int32_t &value) const + { + return do_parse(str,value); + } + + number_format(icu::NumberFormat *fmt,std::string codepage) : + cvt_(codepage), + icu_fmt_(fmt) + { + } + + private: + + bool get_value(double &v,icu::Formattable &fmt) const + { + UErrorCode err=U_ZERO_ERROR; + v=fmt.getDouble(err); + if(U_FAILURE(err)) + return false; + return true; + } + + bool get_value(int64_t &v,icu::Formattable &fmt) const + { + UErrorCode err=U_ZERO_ERROR; + v=fmt.getInt64(err); + if(U_FAILURE(err)) + return false; + return true; + } + + bool get_value(int32_t &v,icu::Formattable &fmt) const + { + UErrorCode err=U_ZERO_ERROR; + v=fmt.getLong(err); + if(U_FAILURE(err)) + return false; + return true; + } + + template<typename ValueType> + size_t do_parse(string_type const &str,ValueType &v) const + { + icu::Formattable val; + icu::ParsePosition pp; + icu::UnicodeString tmp = cvt_.icu(str.data(),str.data()+str.size()); + + icu_fmt_->parse(tmp,val,pp); + + ValueType tmp_v; + + if(pp.getIndex() == 0 || !get_value(tmp_v,val)) + return 0; + size_t cut = cvt_.cut(tmp,str.data(),str.data()+str.size(),pp.getIndex()); + if(cut==0) + return 0; + v=tmp_v; + return cut; + } + + icu_std_converter<CharType> cvt_; + icu::NumberFormat *icu_fmt_; + }; + + + template<typename CharType> + class date_format : public formatter<CharType> { + public: + typedef CharType char_type; + typedef std::basic_string<CharType> string_type; + + virtual string_type format(double value,size_t &code_points) const + { + return do_format(value,code_points); + } + virtual string_type format(int64_t value,size_t &code_points) const + { + return do_format(value,code_points); + } + + virtual string_type format(int32_t value,size_t &code_points) const + { + return do_format(value,code_points); + } + + virtual size_t parse(string_type const &str,double &value) const + { + return do_parse(str,value); + } + virtual size_t parse(string_type const &str,int64_t &value) const + { + return do_parse(str,value); + } + virtual size_t parse(string_type const &str,int32_t &value) const + { + return do_parse(str,value); + } + + date_format(icu::DateFormat *fmt,bool transfer_owneship,std::string codepage) : + cvt_(codepage) + { + if(transfer_owneship) { + aicu_fmt_.reset(fmt); + icu_fmt_ = aicu_fmt_.get(); + } + else { + icu_fmt_ = fmt; + } + } + + private: + + template<typename ValueType> + size_t do_parse(string_type const &str,ValueType &value) const + { + icu::ParsePosition pp; + icu::UnicodeString tmp = cvt_.icu(str.data(),str.data() + str.size()); + + UDate udate = icu_fmt_->parse(tmp,pp); + if(pp.getIndex() == 0) + return 0; + double date = udate / 1000.0; + typedef std::numeric_limits<ValueType> limits_type; + if(date > limits_type::max() || date < limits_type::min()) + return 0; + size_t cut = cvt_.cut(tmp,str.data(),str.data()+str.size(),pp.getIndex()); + if(cut==0) + return 0; + value=static_cast<ValueType>(date); + return cut; + + } + + string_type do_format(double value,size_t &codepoints) const + { + UDate date = value * 1000.0; /// UDate is time_t in miliseconds + icu::UnicodeString tmp; + icu_fmt_->format(date,tmp); + codepoints=tmp.countChar32(); + return cvt_.std(tmp); + } + + icu_std_converter<CharType> cvt_; + hold_ptr<icu::DateFormat> aicu_fmt_; + icu::DateFormat *icu_fmt_; + }; + + icu::UnicodeString strftime_to_icu_full(icu::DateFormat *dfin,char const *alt) + { + hold_ptr<icu::DateFormat> df(dfin); + icu::SimpleDateFormat *sdf=dynamic_cast<icu::SimpleDateFormat *>(df.get()); + icu::UnicodeString tmp; + if(sdf) { + sdf->toPattern(tmp); + } + else { + tmp=alt; + } + return tmp; + + } + + icu::UnicodeString strftime_to_icu_symbol(char c,icu::Locale const &locale,icu_formatters_cache const *cache=0) + { + switch(c) { + case 'a': // Abbr Weekday + return "EE"; + case 'A': // Full Weekday + return "EEEE"; + case 'b': // Abbr Month + return "MMM"; + case 'B': // Full Month + return "MMMM"; + case 'c': // DateTile Full + { + if(cache) + return cache->date_time_format_[1][1]; + return strftime_to_icu_full( + icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull,icu::DateFormat::kFull,locale), + "yyyy-MM-dd HH:mm:ss" + ); + } + // not supported by ICU ;( + // case 'C': // Century -> 1980 -> 19 + // retur + case 'd': // Day of Month [01,31] + return "dd"; + case 'D': // %m/%d/%y + return "MM/dd/yy"; + case 'e': // Day of Month [1,31] + return "d"; + case 'h': // == b + return "MMM"; + case 'H': // 24 clock hour 00,23 + return "HH"; + case 'I': // 12 clock hour 01,12 + return "hh"; + case 'j': // day of year 001,366 + return "D"; + case 'm': // month as [01,12] + return "MM"; + case 'M': // minute [00,59] + return "mm"; + case 'n': // \n + return "\n"; + case 'p': // am-pm + return "a"; + case 'r': // time with AM/PM %I:%M:%S %p + return "hh:mm:ss a"; + case 'R': // %H:%M + return "HH:mm"; + case 'S': // second [00,61] + return "ss"; + case 't': // \t + return "\t"; + case 'T': // %H:%M:%S + return "HH:mm:ss"; +/* case 'u': // weekday 1,7 1=Monday + case 'U': // week number of year [00,53] Sunday first + case 'V': // week number of year [01,53] Moday first + case 'w': // weekday 0,7 0=Sunday + case 'W': // week number of year [00,53] Moday first, */ + case 'x': // Date + { + if(cache) + return cache->date_format_[1]; + return strftime_to_icu_full( + icu::DateFormat::createDateInstance(icu::DateFormat::kMedium,locale), + "yyyy-MM-dd" + ); + } + case 'X': // Time + { + if(cache) + return cache->time_format_[1]; + return strftime_to_icu_full( + icu::DateFormat::createTimeInstance(icu::DateFormat::kMedium,locale), + "HH:mm:ss" + ); + } + case 'y': // Year [00-99] + return "yy"; + case 'Y': // Year 1998 + return "yyyy"; + case 'Z': // timezone + return "vvvv"; + case '%': // % + return "%"; + default: + return ""; + } + } + + icu::UnicodeString strftime_to_icu(icu::UnicodeString const &ftime,icu::Locale const &locale) + { + unsigned len=ftime.length(); + icu::UnicodeString result; + bool escaped=false; + for(unsigned i=0;i<len;i++) { + UChar c=ftime[i]; + if(c=='%') { + i++; + c=ftime[i]; + if(c=='E' || c=='O') { + i++; + c=ftime[i]; + } + if(escaped) { + result+="'"; + escaped=false; + } + result+=strftime_to_icu_symbol(c,locale); + } + else if(c=='\'') { + result+="''"; + } + else { + if(!escaped) { + result+="'"; + escaped=true; + } + result+=c; + } + } + if(escaped) + result+="'"; + return result; + } + + template<typename CharType> + formatter<CharType> *generate_formatter( + std::ios_base &ios, + icu::Locale const &locale, + std::string const &encoding) + { + using namespace boost::locale::flags; + + hold_ptr<formatter<CharType> > fmt; + ios_info &info=ios_info::get(ios); + uint64_t disp = info.display_flags(); + + icu_formatters_cache const &cache = std::use_facet<icu_formatters_cache>(ios.getloc()); + + + if(disp == posix) + return fmt.release(); + + UErrorCode err=U_ZERO_ERROR; + + switch(disp) { + case number: + { + std::ios_base::fmtflags how = (ios.flags() & std::ios_base::floatfield); + icu::NumberFormat *nf = 0; + + if(how == std::ios_base::scientific) + nf = cache.number_format(icu_formatters_cache::fmt_sci); + else + nf = cache.number_format(icu_formatters_cache::fmt_number); + + nf->setMaximumFractionDigits(ios.precision()); + if(how == std::ios_base::scientific || how == std::ios_base::fixed ) { + nf->setMinimumFractionDigits(ios.precision()); + } + else { + nf->setMinimumFractionDigits(0); + } + fmt.reset(new number_format<CharType>(nf,encoding)); + } + break; + case currency: + { + icu::NumberFormat *nf; + + uint64_t curr = info.currency_flags(); + + if(curr == currency_default || curr == currency_national) + nf = cache.number_format(icu_formatters_cache::fmt_curr_nat); + else + nf = cache.number_format(icu_formatters_cache::fmt_curr_iso); + + fmt.reset(new number_format<CharType>(nf,encoding)); + } + break; + case percent: + { + icu::NumberFormat *nf = cache.number_format(icu_formatters_cache::fmt_per); + nf->setMaximumFractionDigits(ios.precision()); + std::ios_base::fmtflags how = (ios.flags() & std::ios_base::floatfield); + if(how == std::ios_base::scientific || how == std::ios_base::fixed ) { + nf->setMinimumFractionDigits(ios.precision()); + } + else { + nf->setMinimumFractionDigits(0); + } + fmt.reset(new number_format<CharType>(nf,encoding)); + + } + break; + case spellout: + fmt.reset(new number_format<CharType>(cache.number_format(icu_formatters_cache::fmt_spell),encoding)); + break; + case ordinal: + fmt.reset(new number_format<CharType>(cache.number_format(icu_formatters_cache::fmt_ord),encoding)); + break; + case date: + case time: + case datetime: + case strftime: + { + using namespace flags; + hold_ptr<icu::DateFormat> adf; + icu::DateFormat *df = 0; + icu::SimpleDateFormat *sdf = cache.date_formatter(); + // try to use cached first + if(sdf) { + int tmf=info.time_flags(); + switch(tmf) { + case time_short: + tmf=0; + break; + case time_long: + tmf=2; + break; + case time_full: + tmf=3; + break; + case time_default: + case time_medium: + default: + tmf=1; + } + int dtf=info.date_flags(); + switch(dtf) { + case date_short: + dtf=0; + break; + case date_long: + dtf=2; + break; + case date_full: + dtf=3; + break; + case date_default: + case date_medium: + default: + dtf=1; + } + + icu::UnicodeString pattern; + switch(disp) { + case date: + pattern = cache.date_format_[dtf]; + break; + case time: + pattern = cache.time_format_[tmf]; + break; + case datetime: + pattern = cache.date_time_format_[dtf][tmf]; + break; + case strftime: + { + if( !cache.date_format_[1].isEmpty() + && !cache.time_format_[1].isEmpty() + && !cache.date_time_format_[1][1].isEmpty()) + { + icu_std_converter<CharType> cvt_(encoding); + std::basic_string<CharType> const &f=info.date_time_pattern<CharType>(); + pattern = strftime_to_icu(cvt_.icu(f.c_str(),f.c_str()+f.size()),locale); + } + } + break; + } + if(!pattern.isEmpty()) { + sdf->applyPattern(pattern); + df = sdf; + sdf = 0; + } + sdf = 0; + } + + if(!df) { + icu::DateFormat::EStyle dstyle = icu::DateFormat::kDefault; + icu::DateFormat::EStyle tstyle = icu::DateFormat::kDefault; + + switch(info.time_flags()) { + case time_short: tstyle=icu::DateFormat::kShort; break; + case time_medium: tstyle=icu::DateFormat::kMedium; break; + case time_long: tstyle=icu::DateFormat::kLong; break; + case time_full: tstyle=icu::DateFormat::kFull; break; + } + switch(info.date_flags()) { + case date_short: dstyle=icu::DateFormat::kShort; break; + case date_medium: dstyle=icu::DateFormat::kMedium; break; + case date_long: dstyle=icu::DateFormat::kLong; break; + case date_full: dstyle=icu::DateFormat::kFull; break; + } + + if(disp==date) + adf.reset(icu::DateFormat::createDateInstance(dstyle,locale)); + else if(disp==time) + adf.reset(icu::DateFormat::createTimeInstance(tstyle,locale)); + else if(disp==datetime) + adf.reset(icu::DateFormat::createDateTimeInstance(dstyle,tstyle,locale)); + else {// strftime + icu_std_converter<CharType> cvt_(encoding); + std::basic_string<CharType> const &f=info.date_time_pattern<CharType>(); + icu::UnicodeString fmt = strftime_to_icu(cvt_.icu(f.data(),f.data()+f.size()),locale); + adf.reset(new icu::SimpleDateFormat(fmt,locale,err)); + } + if(U_FAILURE(err)) + return fmt.release(); + df = adf.get(); + } + + df->adoptTimeZone(get_time_zone(info.time_zone())); + + // Depending if we own formatter or not + if(adf.get()) + fmt.reset(new date_format<CharType>(adf.release(),true,encoding)); + else + fmt.reset(new date_format<CharType>(df,false,encoding)); + } + break; + } + + return fmt.release(); + } + + + + template<> + formatter<char> *formatter<char>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e) + { + return generate_formatter<char>(ios,l,e); + } + + template<> + formatter<wchar_t> *formatter<wchar_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e) + { + return generate_formatter<wchar_t>(ios,l,e); + } + + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + template<> + formatter<char16_t> *formatter<char16_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e) + { + return generate_formatter<char16_t>(ios,l,e); + } + + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + template<> + formatter<char32_t> *formatter<char32_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e) + { + return generate_formatter<char32_t>(ios,l,e); + } + + #endif + +} // impl_icu + +} // locale +} // boost + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + + diff --git a/src/boost/libs/locale/src/icu/formatter.hpp b/src/boost/libs/locale/src/icu/formatter.hpp new file mode 100644 index 000000000..30414dc56 --- /dev/null +++ b/src/boost/libs/locale/src/icu/formatter.hpp @@ -0,0 +1,132 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_FORMATTER_HPP_INCLUDED +#define BOOST_LOCALE_FORMATTER_HPP_INCLUDED + +#include <string> +#include <memory> +#include <boost/cstdint.hpp> +#include <boost/locale/config.hpp> +#include <unicode/locid.h> + +namespace boost { +namespace locale { +namespace impl_icu { + + /// + /// \brief Special base polymorphic class that is used as a character type independent base for all formatter classes + /// + + class base_formatter { + public: + virtual ~base_formatter() + { + } + }; + + /// + /// \brief A class that is used for formatting numbers, currency and dates/times + /// + template<typename CharType> + class formatter : public base_formatter { + public: + typedef CharType char_type; + typedef std::basic_string<CharType> string_type; + + /// + /// Format the value and return the number of Unicode code points + /// + virtual string_type format(double value,size_t &code_points) const = 0; + /// + /// Format the value and return the number of Unicode code points + /// + virtual string_type format(int64_t value,size_t &code_points) const = 0; + /// + /// Format the value and return the number of Unicode code points + /// + virtual string_type format(int32_t value,size_t &code_points) const = 0; + + /// + /// Parse the string and return the number of used characters. If it returns 0 + /// then parsing failed. + /// + virtual size_t parse(string_type const &str,double &value) const = 0; + /// + /// Parse the string and return the number of used characters. If it returns 0 + /// then parsing failed. + /// + virtual size_t parse(string_type const &str,int64_t &value) const = 0; + /// + /// Parse the string and return the number of used characters. If it returns 0 + /// then parsing failed. + /// + virtual size_t parse(string_type const &str,int32_t &value) const = 0; + + /// + /// Get formatter for the current state of ios_base -- flags and locale, + /// NULL may be returned if an invalid combination of flags is provided or this type + /// of formatting is not supported by locale. See: create + /// + /// Note: formatter is cached. If \a ios is not changed (no flags or locale changed) + /// the formatter would remain the same. Otherwise it would be rebuild and cached + /// for future use. It is useful for saving time for generation + /// of multiple values with same locale. + /// + /// For example, this code: + /// + /// \code + /// std::cout << as::spellout; + /// for(int i=1;i<=10;i++) + /// std::cout << i <<std::endl; + /// \endcode + /// + /// Would create a new spelling formatter only once. + /// + static formatter *create(std::ios_base &ios,icu::Locale const &l,std::string const &enc); + + virtual ~formatter() + { + } + }; // class formatter + + /// + /// Specialization for real implementation + /// + template<> + formatter<char> *formatter<char>::create(std::ios_base &ios,icu::Locale const &l,std::string const &enc); + + /// + /// Specialization for real implementation + /// + template<> + formatter<wchar_t> *formatter<wchar_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + /// + /// Specialization for real implementation + /// + template<> + formatter<char16_t> *formatter<char16_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e); + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + /// + /// Specialization for real implementation + /// + template<> + formatter<char32_t> *formatter<char32_t>::create(std::ios_base &ios,icu::Locale const &l,std::string const &e); + #endif + +} // namespace impl_icu +} // namespace locale +} // namespace boost + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/icu_backend.cpp b/src/boost/libs/locale/src/icu/icu_backend.cpp new file mode 100644 index 000000000..e3a5d4f58 --- /dev/null +++ b/src/boost/libs/locale/src/icu/icu_backend.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include <boost/locale/util.hpp> +#include "all_generator.hpp" +#include "cdata.hpp" +#include "icu_backend.hpp" +#include "../util/locale_data.hpp" +#include <algorithm> +#include <iterator> + +#include <unicode/ucnv.h> + +namespace boost { +namespace locale { +namespace impl_icu { + class icu_localization_backend : public localization_backend { + public: + icu_localization_backend() : + invalid_(true), + use_ansi_encoding_(false) + { + } + icu_localization_backend(icu_localization_backend const &other) : + localization_backend(), + paths_(other.paths_), + domains_(other.domains_), + locale_id_(other.locale_id_), + invalid_(true), + use_ansi_encoding_(other.use_ansi_encoding_) + { + } + virtual icu_localization_backend *clone() const + { + return new icu_localization_backend(*this); + } + + void set_option(std::string const &name,std::string const &value) + { + invalid_ = true; + if(name=="locale") + locale_id_ = value; + else if(name=="message_path") + paths_.push_back(value); + else if(name=="message_application") + domains_.push_back(value); + else if(name=="use_ansi_encoding") + use_ansi_encoding_ = value == "true"; + + } + void clear_options() + { + invalid_ = true; + use_ansi_encoding_ = false; + locale_id_.clear(); + paths_.clear(); + domains_.clear(); + } + + void prepare_data() + { + if(!invalid_) + return; + invalid_ = false; + real_id_ = locale_id_; + if(real_id_.empty()) { + bool utf8 = ! use_ansi_encoding_; + real_id_ = util::get_system_locale(utf8); + } + + util::locale_data d; + d.parse(real_id_); + + data_.locale = icu::Locale::createCanonical(real_id_.c_str()); + data_.encoding = d.encoding; + data_.utf8 = d.utf8; + language_ = d.language; + country_ = d.country; + variant_ = d.variant; + } + + virtual std::locale install(std::locale const &base, + locale_category_type category, + character_facet_type type = nochar_facet) + { + prepare_data(); + + switch(category) { + case convert_facet: + return create_convert(base,data_,type); + case collation_facet: + return create_collate(base,data_,type); + case formatting_facet: + return create_formatting(base,data_,type); + case parsing_facet: + return create_parsing(base,data_,type); + case codepage_facet: + return create_codecvt(base,data_.encoding,type); + case message_facet: + { + gnu_gettext::messages_info minf; + minf.language = language_; + minf.country = country_; + minf.variant = variant_; + minf.encoding = data_.encoding; + std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); + minf.paths = paths_; + switch(type) { + case char_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); + case wchar_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf)); + #endif + default: + return base; + } + } + case boundary_facet: + return create_boundary(base,data_,type); + case calendar_facet: + return create_calendar(base,data_); + case information_facet: + return util::create_info(base,real_id_); + default: + return base; + } + } + + private: + + std::vector<std::string> paths_; + std::vector<std::string> domains_; + std::string locale_id_; + + cdata data_; + std::string language_; + std::string country_; + std::string variant_; + std::string real_id_; + bool invalid_; + bool use_ansi_encoding_; + }; + + localization_backend *create_localization_backend() + { + return new icu_localization_backend(); + } + +} // impl icu +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/icu_backend.hpp b/src/boost/libs/locale/src/icu/icu_backend.hpp new file mode 100644 index 000000000..d43cb2db2 --- /dev/null +++ b/src/boost/libs/locale/src/icu/icu_backend.hpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_ICU_LOCALIZATION_BACKEND_HPP +#define BOOST_LOCALE_IMPL_ICU_LOCALIZATION_BACKEND_HPP +namespace boost { + namespace locale { + class localization_backend; + namespace impl_icu { + localization_backend *create_localization_backend(); + } // impl_icu + } // locale +} // boost +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/icu/icu_util.hpp b/src/boost/libs/locale/src/icu/icu_util.hpp new file mode 100644 index 000000000..4330bda6b --- /dev/null +++ b/src/boost/libs/locale/src/icu/icu_util.hpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_SRC_ICU_UTIL_HPP +#define BOOST_SRC_ICU_UTIL_HPP +#include <unicode/utypes.h> +#include <stdexcept> + +namespace boost { +namespace locale { +namespace impl_icu { + + inline void throw_icu_error(UErrorCode err) + { + throw std::runtime_error(u_errorName(err)); + } + + inline void check_and_throw_icu_error(UErrorCode err) + { + if(U_FAILURE(err)) + throw_icu_error(err); + } +} // impl +} // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/numeric.cpp b/src/boost/libs/locale/src/icu/numeric.cpp new file mode 100644 index 000000000..debecfb89 --- /dev/null +++ b/src/boost/libs/locale/src/icu/numeric.cpp @@ -0,0 +1,426 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <limits> +#include "formatter.hpp" +#include <boost/locale/formatting.hpp> +#include <boost/locale/hold_ptr.hpp> +#include "all_generator.hpp" +#include "cdata.hpp" +#include <algorithm> +#include "predefined_formatters.hpp" + +namespace boost { +namespace locale { +namespace impl_icu { + +namespace details { + template<typename V,int n=std::numeric_limits<V>::digits,bool integer=std::numeric_limits<V>::is_integer> + struct cast_traits; + + template<typename v> + struct cast_traits<v,7,true> { + typedef int32_t cast_type; + }; + template<typename v> + struct cast_traits<v,8,true> { + typedef int32_t cast_type; + }; + + template<typename v> + struct cast_traits<v,15,true> { + typedef int32_t cast_type; + }; + template<typename v> + struct cast_traits<v,16,true> { + typedef int32_t cast_type; + }; + template<typename v> + struct cast_traits<v,31,true> { + typedef int32_t cast_type; + }; + template<typename v> + struct cast_traits<v,32,true> { + typedef int64_t cast_type; + }; + template<typename v> + struct cast_traits<v,63,true> { + typedef int64_t cast_type; + }; + template<typename v> + struct cast_traits<v,64,true> { + typedef int64_t cast_type; + }; + template<typename V,int u> + struct cast_traits<V,u,false> { + typedef double cast_type; + }; + + // ICU does not support uint64_t values so fallback + // to POSIX formatting + template< typename V, + bool Sig=std::numeric_limits<V>::is_signed, + bool Int=std::numeric_limits<V>::is_integer, + bool Big=(sizeof(V) >= 8) + > + struct use_parent_traits + { + static bool use(V /*v*/) { return false; } + }; + template<typename V> + struct use_parent_traits<V,false,true,true> + { + static bool use(V v) { return static_cast<int64_t>(v) < 0; } + }; + +} + + + +class num_base { +protected: + + template<typename ValueType> + static bool use_parent(std::ios_base &ios,ValueType v) + { + uint64_t flg = ios_info::get(ios).display_flags(); + if(flg == flags::posix) + return true; + if(details::use_parent_traits<ValueType>::use(v)) + return true; + + if(!std::numeric_limits<ValueType>::is_integer) + return false; + + if(flg == flags::number && (ios.flags() & std::ios_base::basefield) != std::ios_base::dec) { + return true; + } + return false; + } +}; + + +template<typename CharType> +class num_format : public std::num_put<CharType>, protected num_base +{ +public: + typedef typename std::num_put<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + typedef formatter<CharType> formatter_type; + typedef hold_ptr<formatter_type> formatter_ptr; + + num_format(cdata const &d,size_t refs = 0) : + std::num_put<CharType>(refs), + loc_(d.locale), + enc_(d.encoding) + { + } +protected: + + + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, double val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long double val) const + { + return do_real_put(out,ios,fill,val); + } + + #ifndef BOOST_NO_LONG_LONG + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long long val) const + { + return do_real_put(out,ios,fill,val); + } + #endif + + +private: + + + + template<typename ValueType> + iter_type do_real_put (iter_type out, std::ios_base &ios, char_type fill, ValueType val) const + { + if(use_parent<ValueType>(ios,val)) + return std::num_put<char_type>::do_put(out,ios,fill,val); + + formatter_ptr formatter(formatter_type::create(ios,loc_,enc_)); + + if(formatter.get() == 0) + return std::num_put<char_type>::do_put(out,ios,fill,val); + + size_t code_points; + typedef typename details::cast_traits<ValueType>::cast_type cast_type; + string_type const &str = formatter->format(static_cast<cast_type>(val),code_points); + std::streamsize on_left=0,on_right = 0,points = code_points; + if(points < ios.width()) { + std::streamsize n = ios.width() - points; + + std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield; + + // + // We do not really know internal point, so we assume that it does not + // exist. So according to the standard field should be right aligned + // + if(flags != std::ios_base::left) + on_left = n; + on_right = n - on_left; + } + while(on_left > 0) { + *out++ = fill; + on_left--; + } + std::copy(str.begin(),str.end(),out); + while(on_right > 0) { + *out++ = fill; + on_right--; + } + ios.width(0); + return out; + + } + + icu::Locale loc_; + std::string enc_; + +}; /// num_format + + +template<typename CharType> +class num_parse : public std::num_get<CharType>, protected num_base +{ +public: + num_parse(cdata const &d,size_t refs = 0) : + std::num_get<CharType>(refs), + loc_(d.locale), + enc_(d.encoding) + { + } +protected: + typedef typename std::num_get<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + typedef formatter<CharType> formatter_type; + typedef hold_ptr<formatter_type> formatter_ptr; + typedef std::basic_istream<CharType> stream_type; + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned short &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned int &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,float &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,double &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long double &val) const + { + return do_real_get(in,end,ios,err,val); + } + + #ifndef BOOST_NO_LONG_LONG + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + #endif + +private: + + + // + // This is not really an efficient solution, but it works + // + template<typename ValueType> + iter_type do_real_get(iter_type in,iter_type end,std::ios_base &ios,std::ios_base::iostate &err,ValueType &val) const + { + stream_type *stream_ptr = dynamic_cast<stream_type *>(&ios); + if(!stream_ptr || use_parent<ValueType>(ios,0)) { + return std::num_get<CharType>::do_get(in,end,ios,err,val); + } + + formatter_ptr formatter(formatter_type::create(ios,loc_,enc_)); + if(formatter.get()==0) { + return std::num_get<CharType>::do_get(in,end,ios,err,val); + } + + typedef typename details::cast_traits<ValueType>::cast_type cast_type; + string_type tmp; + tmp.reserve(64); + + CharType c; + while(in!=end && (((c=*in)<=32 && (c>0)) || c==127)) // Assuming that ASCII is a subset + ++in; + + while(tmp.size() < 4096 && in!=end && *in!='\n') { + tmp += *in++; + } + + cast_type value; + size_t parsed_chars; + + if((parsed_chars = formatter->parse(tmp,value))==0 || !valid<ValueType>(value)) { + err |= std::ios_base::failbit; + } + else { + val=static_cast<ValueType>(value); + } + + for(size_t n=tmp.size();n>parsed_chars;n--) { + stream_ptr->putback(tmp[n-1]); + } + + in = iter_type(*stream_ptr); + + if(in==end) + err |=std::ios_base::eofbit; + return in; + } + + template<typename ValueType,typename CastedType> + bool valid(CastedType v) const + { + typedef std::numeric_limits<ValueType> value_limits; + typedef std::numeric_limits<CastedType> casted_limits; + if(v < 0 && value_limits::is_signed == false) + return false; + + static const CastedType max_val = value_limits::max(); + + if(sizeof(CastedType) > sizeof(ValueType) && v > max_val) + return false; + + if(value_limits::is_integer == casted_limits::is_integer) { + return true; + } + if(value_limits::is_integer) { // and casted is not + if(static_cast<CastedType>(static_cast<ValueType>(v))!=v) + return false; + } + return true; + } + + icu::Locale loc_; + std::string enc_; + +}; + + +template<typename CharType> +std::locale install_formatting_facets(std::locale const &in,cdata const &cd) +{ + std::locale tmp=std::locale(in,new num_format<CharType>(cd)); + if(!std::has_facet<icu_formatters_cache>(in)) { + tmp=std::locale(tmp,new icu_formatters_cache(cd.locale)); + } + return tmp; +} + +template<typename CharType> +std::locale install_parsing_facets(std::locale const &in,cdata const &cd) +{ + std::locale tmp=std::locale(in,new num_parse<CharType>(cd)); + if(!std::has_facet<icu_formatters_cache>(in)) { + tmp=std::locale(tmp,new icu_formatters_cache(cd.locale)); + } + return tmp; +} + +std::locale create_formatting(std::locale const &in,cdata const &cd,character_facet_type type) +{ + switch(type) { + case char_facet: + return install_formatting_facets<char>(in,cd); + case wchar_t_facet: + return install_formatting_facets<wchar_t>(in,cd); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return install_formatting_facets<char16_t>(in,cd); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return install_formatting_facets<char32_t>(in,cd); + #endif + default: + return in; + } +} + +std::locale create_parsing(std::locale const &in,cdata const &cd,character_facet_type type) +{ + switch(type) { + case char_facet: + return install_parsing_facets<char>(in,cd); + case wchar_t_facet: + return install_parsing_facets<wchar_t>(in,cd); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return install_parsing_facets<char16_t>(in,cd); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return install_parsing_facets<char32_t>(in,cd); + #endif + default: + return in; + } +} + + +} // impl_icu + +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/predefined_formatters.hpp b/src/boost/libs/locale/src/icu/predefined_formatters.hpp new file mode 100644 index 000000000..906dfe83e --- /dev/null +++ b/src/boost/libs/locale/src/icu/predefined_formatters.hpp @@ -0,0 +1,187 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED +#define BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED + +#include <string> +#include <memory> +#include <boost/cstdint.hpp> +#include <boost/thread.hpp> +#include <boost/locale/config.hpp> +#include <boost/locale/hold_ptr.hpp> + +#include <unicode/locid.h> +#include <unicode/numfmt.h> +#include <unicode/rbnf.h> +#include <unicode/datefmt.h> +#include <unicode/smpdtfmt.h> +#include <unicode/decimfmt.h> + +namespace boost { +namespace locale { + namespace impl_icu { + + class icu_formatters_cache : public std::locale::facet { + public: + + static std::locale::id id; + + icu_formatters_cache(icu::Locale const &locale) : + locale_(locale) + { + + static const icu::DateFormat::EStyle styles[4] = { + icu::DateFormat::kShort, + icu::DateFormat::kMedium, + icu::DateFormat::kLong, + icu::DateFormat::kFull + }; + + + for(int i=0;i<4;i++) { + hold_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateInstance(styles[i],locale)); + icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get()); + if(sfmt) { + sfmt->toPattern(date_format_[i]); + } + } + + for(int i=0;i<4;i++) { + hold_ptr<icu::DateFormat> fmt(icu::DateFormat::createTimeInstance(styles[i],locale)); + icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get()); + if(sfmt) { + sfmt->toPattern(time_format_[i]); + } + } + + for(int i=0;i<4;i++) { + for(int j=0;j<4;j++) { + hold_ptr<icu::DateFormat> fmt( + icu::DateFormat::createDateTimeInstance(styles[i],styles[j],locale)); + icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get()); + if(sfmt) { + sfmt->toPattern(date_time_format_[i][j]); + } + } + } + + + } + + typedef enum { + fmt_number, + fmt_sci, + fmt_curr_nat, + fmt_curr_iso, + fmt_per, + fmt_spell, + fmt_ord, + fmt_count + } fmt_type; + + icu::NumberFormat *number_format(fmt_type type) const + { + icu::NumberFormat *ptr = number_format_[type].get(); + if(ptr) + return ptr; + UErrorCode err=U_ZERO_ERROR; + hold_ptr<icu::NumberFormat> ap; + + switch(type) { + case fmt_number: + ap.reset(icu::NumberFormat::createInstance(locale_,err)); + break; + case fmt_sci: + ap.reset(icu::NumberFormat::createScientificInstance(locale_,err)); + break; + #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402 + #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 408 + case fmt_curr_nat: + ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY,err)); + break; + case fmt_curr_iso: + ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY_ISO,err)); + break; + #else + case fmt_curr_nat: + ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kCurrencyStyle,err)); + break; + case fmt_curr_iso: + ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kIsoCurrencyStyle,err)); + break; + #endif + #else + case fmt_curr_nat: + case fmt_curr_iso: + ap.reset(icu::NumberFormat::createCurrencyInstance(locale_,err)); + break; + #endif + case fmt_per: + ap.reset(icu::NumberFormat::createPercentInstance(locale_,err)); + break; + case fmt_spell: + ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT,locale_,err)); + break; + case fmt_ord: + ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL,locale_,err)); + break; + default: + throw std::runtime_error("locale::internal error should not get there"); + } + + test(err); + ptr = ap.get(); + number_format_[type].reset(ap.release()); + return ptr; + } + + void test(UErrorCode err) const + { + if(U_FAILURE(err)) + throw std::runtime_error("Failed to create a formatter"); + } + + icu::UnicodeString date_format_[4]; + icu::UnicodeString time_format_[4]; + icu::UnicodeString date_time_format_[4][4]; + + icu::SimpleDateFormat *date_formatter() const + { + icu::SimpleDateFormat *p=date_formatter_.get(); + if(p) + return p; + + hold_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateTimeInstance( + icu::DateFormat::kMedium, + icu::DateFormat::kMedium, + locale_)); + + if(dynamic_cast<icu::SimpleDateFormat *>(fmt.get())) { + p = static_cast<icu::SimpleDateFormat *>(fmt.release()); + date_formatter_.reset(p); + } + return p; + } + + private: + + mutable boost::thread_specific_ptr<icu::NumberFormat> number_format_[fmt_count]; + mutable boost::thread_specific_ptr<icu::SimpleDateFormat> date_formatter_; + icu::Locale locale_; + }; + + + + } // namespace impl_icu +} // namespace locale +} // namespace boost + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/time_zone.cpp b/src/boost/libs/locale/src/icu/time_zone.cpp new file mode 100644 index 000000000..8276231f9 --- /dev/null +++ b/src/boost/libs/locale/src/icu/time_zone.cpp @@ -0,0 +1,239 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include "time_zone.hpp" + +// +// Bug - when ICU tries to find a file that is equivalent to /etc/localtime it finds /usr/share/zoneinfo/localtime +// that is just a symbolic link to /etc/localtime. +// +// It started in 4.0 and was fixed in version 4.6, also the fix was backported to the 4.4 branch so it should be +// available from 4.4.3... So we test if the workaround is required +// +// It is also relevant only for Linux, BSD and Apple (as I see in ICU code) +// + +#if U_ICU_VERSION_MAJOR_NUM == 4 && (U_ICU_VERSION_MINOR_NUM * 100 + U_ICU_VERSION_PATCHLEVEL_NUM) <= 402 +# if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__) +# define BOOST_LOCALE_WORKAROUND_ICU_BUG +# endif +#endif + +#ifdef BOOST_LOCALE_WORKAROUND_ICU_BUG +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fstream> +#include <pthread.h> +#include <string.h> +#include <memory> +#endif + +#include <boost/locale/hold_ptr.hpp> + +namespace boost { + namespace locale { + namespace impl_icu { + + #ifndef BOOST_LOCALE_WORKAROUND_ICU_BUG + + // This is normal behavior + + icu::TimeZone *get_time_zone(std::string const &time_zone) + { + + if(time_zone.empty()) { + return icu::TimeZone::createDefault(); + } + else { + return icu::TimeZone::createTimeZone(time_zone.c_str()); + } + } + + #else + + // + // This is a workaround for an ICU timezone detection bug. + // It is \b very ICU specific and should not be used + // in general. It is also designed to work only on + // specific patforms: Linux, BSD and Apple, where this bug may actually + // occur + // + namespace { + + // Under BSD, Linux and Mac OS X dirent has normal size + // so no issues with readdir_r + + class directory { + public: + directory(char const *name) : d(0),read_result(0) + { + d=opendir(name); + if(!d) + return; + } + ~directory() + { + if(d) + closedir(d); + } + bool is_open() + { + return d; + } + char const *next() + { + if(d && readdir_r(d,&de,&read_result)==0 && read_result!=0) + return de.d_name; + return 0; + } + private: + DIR *d; + struct dirent de; + struct dirent *read_result; + }; + + bool files_equal(std::string const &left,std::string const &right) + { + char l[256],r[256]; + std::ifstream ls(left.c_str()); + if(!ls) + return false; + std::ifstream rs(right.c_str()); + if(!rs) + return false; + do { + ls.read(l,sizeof(l)); + rs.read(r,sizeof(r)); + size_t n; + if((n=ls.gcount())!=size_t(rs.gcount())) + return false; + if(memcmp(l,r,n)!=0) + return false; + }while(!ls.eof() || !rs.eof()); + if(bool(ls.eof())!=bool(rs.eof())) + return false; + return true; + } + + std::string find_file_in(std::string const &ref,size_t size,std::string const &dir) + { + directory d(dir.c_str()); + if(!d.is_open()) + return std::string(); + + char const *name=0; + while((name=d.next())!=0) { + std::string file_name = name; + if( file_name == "." + || file_name ==".." + || file_name=="posixrules" + || file_name=="localtime") + { + continue; + } + struct stat st; + std::string path = dir+"/"+file_name; + if(stat(path.c_str(),&st)==0) { + if(S_ISDIR(st.st_mode)) { + std::string res = find_file_in(ref,size,path); + if(!res.empty()) + return file_name + "/" + res; + } + else { + if(size_t(st.st_size) == size && files_equal(path,ref)) { + return file_name; + } + } + } + } + return std::string(); + } + + // This actually emulates ICU's search + // algorithm... just it ignores localtime + std::string detect_correct_time_zone() + { + + char const *tz_dir = "/usr/share/zoneinfo"; + char const *tz_file = "/etc/localtime"; + + struct stat st; + if(::stat(tz_file,&st)!=0) + return std::string(); + size_t size = st.st_size; + std::string r = find_file_in(tz_file,size,tz_dir); + if(r.empty()) + return r; + if(r.compare(0,6,"posix/")==0 || r.compare(0,6,"right/",6)==0) + return r.substr(6); + return r; + } + + + // + // Using pthread as: + // - This bug is relevant for only Linux, BSD, Mac OS X and + // pthreads are native threading API + // - The dependency on boost.thread may be removed when using + // more recent ICU versions (so TLS would not be needed) + // + // This the dependency on Boost.Thread is eliminated + // + + pthread_once_t init_tz = PTHREAD_ONCE_INIT; + std::string default_time_zone_name; + + extern "C" { + static void init_tz_proc() + { + try { + default_time_zone_name = detect_correct_time_zone(); + } + catch(...){} + } + } + + std::string get_time_zone_name() + { + pthread_once(&init_tz,init_tz_proc); + return default_time_zone_name; + } + + + } // namespace + + icu::TimeZone *get_time_zone(std::string const &time_zone) + { + + if(!time_zone.empty()) { + return icu::TimeZone::createTimeZone(time_zone.c_str()); + } + hold_ptr<icu::TimeZone> tz(icu::TimeZone::createDefault()); + icu::UnicodeString id; + tz->getID(id); + // Check if there is a bug? + if(id != icu::UnicodeString("localtime")) + return tz.release(); + // Now let's deal with the bug and run the fixed + // search loop as that of ICU + std::string real_id = get_time_zone_name(); + if(real_id.empty()) { + // if we failed fallback to ICU's time zone + return tz.release(); + } + return icu::TimeZone::createTimeZone(real_id.c_str()); + } + #endif // bug workaround + + } + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/time_zone.hpp b/src/boost/libs/locale/src/icu/time_zone.hpp new file mode 100644 index 000000000..3fbeb83f4 --- /dev/null +++ b/src/boost/libs/locale/src/icu/time_zone.hpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_ICU_GET_TIME_ZONE_HPP +#define BOOST_LOCALE_IMPL_ICU_GET_TIME_ZONE_HPP + +#include <unicode/calendar.h> +#include <string> + +namespace boost { + namespace locale { + namespace impl_icu { + + // Provides a workaround for an ICU default timezone bug and also + // handles time_zone string correctly - if empty returns default + // otherwise returns the instance created with time_zone + icu::TimeZone *get_time_zone(std::string const &time_zone); + } + } +} +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/icu/uconv.hpp b/src/boost/libs/locale/src/icu/uconv.hpp new file mode 100644 index 000000000..f9eb2d1bd --- /dev/null +++ b/src/boost/libs/locale/src/icu/uconv.hpp @@ -0,0 +1,316 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_SRC_LOCALE_ICU_UCONV_HPP +#define BOOST_SRC_LOCALE_ICU_UCONV_HPP +#include <unicode/unistr.h> +#include <unicode/ucnv.h> +#include <unicode/ustring.h> +#include <unicode/utf.h> +#include <unicode/utf16.h> + +#include <boost/locale/encoding.hpp> + +#include <string> +#include <memory> +#include "icu_util.hpp" + +namespace boost { +namespace locale { +namespace impl_icu { + + typedef enum { + cvt_skip, + cvt_stop + } cpcvt_type; + + + template<typename CharType,int char_size = sizeof(CharType) > + class icu_std_converter { + public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + icu_std_converter(std::string charset,cpcvt_type cv=cvt_skip); + icu::UnicodeString icu(char_type const *begin,char_type const *end) const; + string_type std(icu::UnicodeString const &str) const; + size_t cut(icu::UnicodeString const &str,char_type const *begin,char_type const *end,size_t n,size_t from_u=0,size_t from_c=0) const; + }; + + template<typename CharType> + class icu_std_converter<CharType,1> { + public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + + icu::UnicodeString icu_checked(char_type const *vb,char_type const *ve) const + { + return icu(vb,ve); // Already done + } + icu::UnicodeString icu(char_type const *vb,char_type const *ve) const + { + char const *begin=reinterpret_cast<char const *>(vb); + char const *end=reinterpret_cast<char const *>(ve); + uconv cvt(charset_,cvt_type_); + UErrorCode err=U_ZERO_ERROR; + icu::UnicodeString tmp(begin,end-begin,cvt.cvt(),err); + check_and_throw_icu_error(err); + return tmp; + } + + string_type std(icu::UnicodeString const &str) const + { + uconv cvt(charset_,cvt_type_); + return cvt.go(str.getBuffer(),str.length(),max_len_); + } + + icu_std_converter(std::string charset,cpcvt_type cvt_type = cvt_skip) : + charset_(charset), + cvt_type_(cvt_type) + { + uconv cvt(charset_,cvt_type); + max_len_=cvt.max_char_size(); + } + + size_t cut(icu::UnicodeString const &str,char_type const *begin,char_type const *end, + size_t n,size_t from_u=0,size_t from_char=0) const + { + size_t code_points = str.countChar32(from_u,n); + uconv cvt(charset_,cvt_type_); + return cvt.cut(code_points,begin+from_char,end); + } + + struct uconv { + uconv(uconv const &other); + void operator=(uconv const &other); + public: + uconv(std::string const &charset,cpcvt_type cvt_type=cvt_skip) + { + UErrorCode err=U_ZERO_ERROR; + cvt_ = ucnv_open(charset.c_str(),&err); + if(!cvt_ || U_FAILURE(err)) { + if(cvt_) + ucnv_close(cvt_); + throw conv::invalid_charset_error(charset); + } + + try { + if(cvt_type==cvt_skip) { + ucnv_setFromUCallBack(cvt_,UCNV_FROM_U_CALLBACK_SKIP,0,0,0,&err); + check_and_throw_icu_error(err); + + err=U_ZERO_ERROR; + ucnv_setToUCallBack(cvt_,UCNV_TO_U_CALLBACK_SKIP,0,0,0,&err); + check_and_throw_icu_error(err); + } + else { + ucnv_setFromUCallBack(cvt_,UCNV_FROM_U_CALLBACK_STOP,0,0,0,&err); + check_and_throw_icu_error(err); + + err=U_ZERO_ERROR; + ucnv_setToUCallBack(cvt_,UCNV_TO_U_CALLBACK_STOP,0,0,0,&err); + check_and_throw_icu_error(err); + } + } + catch(...) { ucnv_close(cvt_) ; throw; } + } + + int max_char_size() + { + return ucnv_getMaxCharSize(cvt_); + } + + string_type go(UChar const *buf,int length,int max_size) + { + string_type res; + res.resize(UCNV_GET_MAX_BYTES_FOR_STRING(length,max_size)); + char *ptr=reinterpret_cast<char *>(&res[0]); + UErrorCode err=U_ZERO_ERROR; + int n = ucnv_fromUChars(cvt_,ptr,res.size(),buf,length,&err); + check_and_throw_icu_error(err); + res.resize(n); + return res; + } + + size_t cut(size_t n,char_type const *begin,char_type const *end) + { + char_type const *saved = begin; + while(n > 0 && begin < end) { + UErrorCode err=U_ZERO_ERROR; + ucnv_getNextUChar(cvt_,&begin,end,&err); + if(U_FAILURE(err)) + return 0; + n--; + } + return begin - saved; + } + + UConverter *cvt() { return cvt_; } + + ~uconv() + { + ucnv_close(cvt_); + } + + private: + UConverter *cvt_; + }; + + private: + int max_len_; + std::string charset_; + cpcvt_type cvt_type_; + }; + + template<typename CharType> + class icu_std_converter<CharType,2> { + public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + + icu::UnicodeString icu_checked(char_type const *begin,char_type const *end) const + { + icu::UnicodeString tmp(end-begin,0,0); // make inital capacity + while(begin!=end) { + UChar cl = *begin++; + if(U16_IS_SINGLE(cl)) + tmp.append(static_cast<UChar32>(cl)); + else if(U16_IS_LEAD(cl)) { + if(begin==end) { + throw_if_needed(); + } + else { + UChar ct=*begin++; + if(!U16_IS_TRAIL(ct)) + throw_if_needed(); + else { + UChar32 c=U16_GET_SUPPLEMENTARY(cl,ct); + tmp.append(c); + } + } + } + else + throw_if_needed(); + } + return tmp; + } + void throw_if_needed() const + { + if(mode_ == cvt_stop) + throw conv::conversion_error(); + } + icu::UnicodeString icu(char_type const *vb,char_type const *ve) const + { + UChar const *begin=reinterpret_cast<UChar const *>(vb); + UChar const *end=reinterpret_cast<UChar const *>(ve); + icu::UnicodeString tmp(begin,end-begin); + return tmp; + + } + + string_type std(icu::UnicodeString const &str) const + { + char_type const *ptr=reinterpret_cast<char_type const *>(str.getBuffer()); + return string_type(ptr,str.length()); + } + size_t cut(icu::UnicodeString const &/*str*/,char_type const * /*begin*/,char_type const * /*end*/,size_t n, + size_t /*from_u*/=0,size_t /*from_c*/=0) const + { + return n; + } + + icu_std_converter(std::string /*charset*/,cpcvt_type mode=cvt_skip) : + mode_(mode) + { + } + private: + cpcvt_type mode_; + + }; + + template<typename CharType> + class icu_std_converter<CharType,4> { + public: + + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + icu::UnicodeString icu_checked(char_type const *begin,char_type const *end) const + { + icu::UnicodeString tmp(end-begin,0,0); // make inital capacity + while(begin!=end) { + UChar32 c = static_cast<UChar32>(*begin++); + if(U_IS_UNICODE_CHAR(c)) + tmp.append(c); + else + throw_if_needed(); + } + return tmp; + } + void throw_if_needed() const + { + if(mode_ == cvt_stop) + throw conv::conversion_error(); + } + + icu::UnicodeString icu(char_type const *begin,char_type const *end) const + { + icu::UnicodeString tmp(end-begin,0,0); // make inital capacity + while(begin!=end) { + UChar32 c=static_cast<UChar32>(*begin++); + tmp.append(c); + } + return tmp; + + } + + string_type std(icu::UnicodeString const &str) const + { + string_type tmp; + tmp.resize(str.length()); + UChar32 *ptr=reinterpret_cast<UChar32 *>(&tmp[0]); + + #ifdef __SUNPRO_CC + int len=0; + #else + ::int32_t len=0; + #endif + + UErrorCode code=U_ZERO_ERROR; + u_strToUTF32(ptr,tmp.size(),&len,str.getBuffer(),str.length(),&code); + + check_and_throw_icu_error(code); + + tmp.resize(len); + + return tmp; + } + + size_t cut(icu::UnicodeString const &str,char_type const * /*begin*/,char_type const * /*end*/,size_t n, + size_t from_u=0,size_t /*from_c*/=0) const + { + return str.countChar32(from_u,n); + } + + icu_std_converter(std::string /*charset*/,cpcvt_type mode=cvt_skip) : + mode_(mode) + { + } + private: + cpcvt_type mode_; + + }; +} /// impl_icu +} // locale +} // boost + +#endif + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/all_generator.hpp b/src/boost/libs/locale/src/posix/all_generator.hpp new file mode 100644 index 000000000..8a80e79d0 --- /dev/null +++ b/src/boost/libs/locale/src/posix/all_generator.hpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_POSIX_ALL_GENERATOR_HPP +#define BOOST_LOCALE_IMPL_POSIX_ALL_GENERATOR_HPP + +#include <boost/locale/generator.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <locale.h> + +#ifdef __APPLE__ +#include <xlocale.h> +#endif + +namespace boost { + namespace locale { + namespace impl_posix { + + std::locale create_convert( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type); + + std::locale create_collate( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type); + + std::locale create_formatting( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type); + + std::locale create_parsing( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type); + std::locale create_codecvt( std::locale const &in, + std::string const &encoding, + character_facet_type type); + + } + } +} + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/codecvt.cpp b/src/boost/libs/locale/src/posix/codecvt.cpp new file mode 100644 index 000000000..897888a9c --- /dev/null +++ b/src/boost/libs/locale/src/posix/codecvt.cpp @@ -0,0 +1,252 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/encoding.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/locale/hold_ptr.hpp> +#include "../encoding/conv.hpp" +#include <boost/locale/util.hpp> +#include "all_generator.hpp" + +#include <errno.h> +#include <algorithm> +#include <stdexcept> +#include <vector> +#include "codecvt.hpp" + +#ifdef BOOST_LOCALE_WITH_ICONV +#include "../util/iconv.hpp" +#endif + +namespace boost { +namespace locale { +namespace impl_posix { + +#ifdef BOOST_LOCALE_WITH_ICONV + class mb2_iconv_converter : public util::base_converter { + public: + + mb2_iconv_converter(std::string const &encoding) : + encoding_(encoding), + to_utf_((iconv_t)(-1)), + from_utf_((iconv_t)(-1)) + { + iconv_t d = (iconv_t)(-1); + std::vector<uint32_t> first_byte_table; + try { + d = iconv_open(utf32_encoding(),encoding.c_str()); + if(d == (iconv_t)(-1)) { + throw std::runtime_error("Unsupported encoding" + encoding); + } + for(unsigned c=0;c<256;c++) { + char ibuf[2] = { char(c) , 0 }; + char *in = ibuf; + size_t insize =2; + uint32_t obuf[2] = {illegal,illegal}; + char *out = reinterpret_cast<char *>(obuf); + size_t outsize = 8; + // Basic sigle codepoint conversion + call_iconv(d,&in,&insize,&out,&outsize); + if(insize == 0 && outsize == 0 && obuf[1] == 0) { + first_byte_table.push_back(obuf[0]); + continue; + } + + // Test if this is illegal first byte or incomplete + in = ibuf; + insize = 1; + out = reinterpret_cast<char *>(obuf); + outsize = 8; + call_iconv(d,0,0,0,0); + size_t res = call_iconv(d,&in,&insize,&out,&outsize); + + // Now if this single byte starts a sequence we add incomplete + // to know to ask that we need two bytes, othewise it may only be + // illegal + + uint32_t point; + if(res == (size_t)(-1) && errno == EINVAL) + point = incomplete; + else + point = illegal; + first_byte_table.push_back(point); + + } + } + catch(...) { + if(d!=(iconv_t)(-1)) + iconv_close(d); + throw; + } + iconv_close(d); + first_byte_table_.reset(new std::vector<uint32_t>()); + first_byte_table_->swap(first_byte_table); + } + + mb2_iconv_converter(mb2_iconv_converter const &other) : + first_byte_table_(other.first_byte_table_), + encoding_(other.encoding_), + to_utf_((iconv_t)(-1)), + from_utf_((iconv_t)(-1)) + { + } + + virtual ~mb2_iconv_converter() + { + if(to_utf_ != (iconv_t)(-1)) + iconv_close(to_utf_); + if(from_utf_ != (iconv_t)(-1)) + iconv_close(from_utf_); + + } + + virtual bool is_thread_safe() const + { + return false; + } + + virtual mb2_iconv_converter *clone() const + { + return new mb2_iconv_converter(*this); + } + + uint32_t to_unicode(char const *&begin,char const *end) + { + if(begin == end) + return incomplete; + + unsigned char seq0 = *begin; + uint32_t index = (*first_byte_table_)[seq0]; + if(index == illegal) + return illegal; + if(index != incomplete) { + begin++; + return index; + } + else if(begin+1 == end) + return incomplete; + + open(to_utf_,utf32_encoding(),encoding_.c_str()); + + // maybe illegal or may be double byte + + char inseq[3] = { static_cast<char>(seq0) , begin[1], 0}; + char *inbuf = inseq; + size_t insize = 3; + uint32_t result[2] = { illegal, illegal }; + size_t outsize = 8; + char *outbuf = reinterpret_cast<char*>(result); + call_iconv(to_utf_,&inbuf,&insize,&outbuf,&outsize); + if(outsize == 0 && insize == 0 && result[1]==0 ) { + begin+=2; + return result[0]; + } + return illegal; + } + + uint32_t from_unicode(uint32_t cp,char *begin,char const *end) + { + if(cp == 0) { + if(begin!=end) { + *begin = 0; + return 1; + } + else { + return incomplete; + } + } + + open(from_utf_,encoding_.c_str(),utf32_encoding()); + + uint32_t codepoints[2] = {cp,0}; + char *inbuf = reinterpret_cast<char *>(codepoints); + size_t insize = sizeof(codepoints); + char outseq[3] = {0}; + char *outbuf = outseq; + size_t outsize = 3; + + call_iconv(from_utf_,&inbuf,&insize,&outbuf,&outsize); + + if(insize != 0 || outsize > 1) + return illegal; + size_t len = 2 - outsize ; + size_t reminder = end - begin; + if(reminder < len) + return incomplete; + for(unsigned i=0;i<len;i++) + *begin++ = outseq[i]; + return len; + } + + void open(iconv_t &d,char const *to,char const *from) + { + if(d!=(iconv_t)(-1)) + return; + d=iconv_open(to,from); + } + + static char const *utf32_encoding() + { + union { char one; uint32_t value; } test; + test.value = 1; + if(test.one == 1) + return "UTF-32LE"; + else + return "UTF-32BE"; + } + + virtual int max_len() const + { + return 2; + } + + private: + boost::shared_ptr<std::vector<uint32_t> > first_byte_table_; + std::string encoding_; + iconv_t to_utf_; + iconv_t from_utf_; + }; + + util::base_converter *create_iconv_converter(std::string const &encoding) + { + hold_ptr<util::base_converter> cvt; + try { + cvt.reset(new mb2_iconv_converter(encoding)); + } + catch(std::exception const &e) { + // Nothing to do, just retrun empty cvt + } + return cvt.release(); + } + +#else // no iconv + util::base_converter *create_iconv_converter(std::string const &/*encoding*/) + { + return 0; + } +#endif + + std::locale create_codecvt(std::locale const &in,std::string const &encoding,character_facet_type type) + { + if(conv::impl::normalize_encoding(encoding.c_str())=="utf8") + return util::create_utf8_codecvt(in,type); + + try { + return util::create_simple_codecvt(in,encoding,type); + } + catch(conv::invalid_charset_error const &) { + util::base_converter *cvt = create_iconv_converter(encoding); + return util::create_codecvt_from_pointer(in,cvt,type); + } + } + +} // impl_posix +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/codecvt.hpp b/src/boost/libs/locale/src/posix/codecvt.hpp new file mode 100644 index 000000000..976c07e32 --- /dev/null +++ b/src/boost/libs/locale/src/posix/codecvt.hpp @@ -0,0 +1,28 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_POSIX_CODECVT_HPP +#define BOOST_LOCALE_IMPL_POSIX_CODECVT_HPP +#include <boost/locale/config.hpp> +#include <boost/locale/util.hpp> + +#include <memory> +#include <string> + +namespace boost { +namespace locale { +namespace impl_posix { + BOOST_LOCALE_DECL + util::base_converter *create_iconv_converter(std::string const &encoding); + +} // impl_posix +} // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/posix/collate.cpp b/src/boost/libs/locale/src/posix/collate.cpp new file mode 100644 index 000000000..859bb9cf6 --- /dev/null +++ b/src/boost/libs/locale/src/posix/collate.cpp @@ -0,0 +1,124 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#if defined(__FreeBSD__) +#include <xlocale.h> +#endif +#include <locale> +#include <locale.h> +#include <string.h> +#include <wchar.h> +#include <string> +#include <stdexcept> +#include <ios> +#include <vector> +#include <boost/locale/generator.hpp> +#include "../shared/mo_hash.hpp" + +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_posix { + +template<typename CharType> +struct coll_traits; + +template<> +struct coll_traits<char> { + static size_t xfrm(char *out,char const *in,size_t n,locale_t l) + { + return strxfrm_l(out,in,n,l); + } + static size_t coll(char const *left,char const *right,locale_t l) + { + return strcoll_l(left,right,l); + } +}; + +template<> +struct coll_traits<wchar_t> { + static size_t xfrm(wchar_t *out,wchar_t const *in,size_t n,locale_t l) + { + return wcsxfrm_l(out,in,n,l); + } + static size_t coll(wchar_t const *left,wchar_t const *right,locale_t l) + { + return wcscoll_l(left,right,l); + } +}; + +template<typename CharType> +class collator : public std::collate<CharType> { +public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + collator(boost::shared_ptr<locale_t> l,size_t refs = 0) : + std::collate<CharType>(refs), + lc_(l) + { + } + virtual ~collator() + { + } + virtual int do_compare(char_type const *lb,char_type const *le,char_type const *rb,char_type const *re) const + { + string_type left(lb,le-lb); + string_type right(rb,re-rb); + int res = coll_traits<char_type>::coll(left.c_str(),right.c_str(),*lc_); + if(res < 0) + return -1; + if(res > 0) + return 1; + return 0; + } + virtual long do_hash(char_type const *b,char_type const *e) const + { + string_type s(do_transform(b,e)); + char const *begin = reinterpret_cast<char const *>(s.c_str()); + char const *end = begin + s.size() * sizeof(char_type); + return gnu_gettext::pj_winberger_hash_function(begin,end); + } + virtual string_type do_transform(char_type const *b,char_type const *e) const + { + string_type s(b,e-b); + std::vector<char_type> buf((e-b)*2+1); + size_t n = coll_traits<char_type>::xfrm(&buf.front(),s.c_str(),buf.size(),*lc_); + if(n>buf.size()) { + buf.resize(n); + coll_traits<char_type>::xfrm(&buf.front(),s.c_str(),n,*lc_); + } + return string_type(&buf.front(),n); + } +private: + boost::shared_ptr<locale_t> lc_; +}; + + +std::locale create_collate( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return std::locale(in,new collator<char>(lc)); + case wchar_t_facet: + return std::locale(in,new collator<wchar_t>(lc)); + default: + return in; + } +} + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/converter.cpp b/src/boost/libs/locale/src/posix/converter.cpp new file mode 100644 index 000000000..bf8bc566d --- /dev/null +++ b/src/boost/libs/locale/src/posix/converter.cpp @@ -0,0 +1,165 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE + +#if defined(__FreeBSD__) +#include <xlocale.h> +#endif +#include <locale> +#include <stdexcept> +#include <boost/locale/generator.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string.h> +#include <wctype.h> +#include <ctype.h> +#include <langinfo.h> +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_posix { + +template<typename CharType> +struct case_traits; + +template<> +struct case_traits<char> { + static char lower(char c,locale_t lc) + { + return tolower_l(c,lc); + } + static char upper(char c,locale_t lc) + { + return toupper_l(c,lc); + } +}; + +template<> +struct case_traits<wchar_t> { + static wchar_t lower(wchar_t c,locale_t lc) + { + return towlower_l(c,lc); + } + static wchar_t upper(wchar_t c,locale_t lc) + { + return towupper_l(c,lc); + } +}; + + +template<typename CharType> +class std_converter : public converter<CharType> +{ +public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + typedef std::ctype<char_type> ctype_type; + std_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) : + converter<CharType>(refs), + lc_(lc) + { + } + virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int /*flags*/ = 0) const + { + switch(how) { + case converter_base::upper_case: + { + string_type res; + res.reserve(end-begin); + while(begin!=end) { + res+=case_traits<char_type>::upper(*begin++,*lc_); + } + return res; + } + case converter_base::lower_case: + case converter_base::case_folding: + { + string_type res; + res.reserve(end-begin); + while(begin!=end) { + res+=case_traits<char_type>::lower(*begin++,*lc_); + } + return res; + } + default: + return string_type(begin,end-begin); + } + } +private: + boost::shared_ptr<locale_t> lc_; +}; + +class utf8_converter : public converter<char> { +public: + utf8_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) : + converter<char>(refs), + lc_(lc) + { + } + virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int /*flags*/ = 0) const + { + switch(how) { + case upper_case: + { + std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8"); + std::wstring wres; + wres.reserve(tmp.size()); + for(unsigned i=0;i<tmp.size();i++) + wres+=towupper_l(tmp[i],*lc_); + return conv::from_utf<wchar_t>(wres,"UTF-8"); + } + + case lower_case: + case case_folding: + { + std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8"); + std::wstring wres; + wres.reserve(tmp.size()); + for(unsigned i=0;i<tmp.size();i++) + wres+=towlower_l(tmp[i],*lc_); + return conv::from_utf<wchar_t>(wres,"UTF-8"); + } + default: + return std::string(begin,end-begin); + } + } +private: + boost::shared_ptr<locale_t> lc_; +}; + +std::locale create_convert( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + { + std::string encoding = nl_langinfo_l(CODESET,*lc); + for(unsigned i=0;i<encoding.size();i++) + if('A'<=encoding[i] && encoding[i]<='Z') + encoding[i]=encoding[i]-'A'+'a'; + if(encoding=="utf-8" || encoding=="utf8" || encoding=="utf_8") { + return std::locale(in,new utf8_converter(lc)); + } + return std::locale(in,new std_converter<char>(lc)); + } + case wchar_t_facet: + return std::locale(in,new std_converter<wchar_t>(lc)); + default: + return in; + } +} + + +} // namespace impl_std +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/numeric.cpp b/src/boost/libs/locale/src/posix/numeric.cpp new file mode 100644 index 000000000..2bef81e2e --- /dev/null +++ b/src/boost/libs/locale/src/posix/numeric.cpp @@ -0,0 +1,514 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#if defined(__FreeBSD__) +#include <xlocale.h> +#endif +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/formatting.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/shared_ptr.hpp> +#include <sstream> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <wctype.h> +#include <ctype.h> +#include <langinfo.h> +#include <monetary.h> +#include <errno.h> +#include "../util/numeric.hpp" +#include "all_generator.hpp" + + +#if defined(__linux) || defined(__APPLE__) +#define BOOST_LOCALE_HAVE_WCSFTIME_L +#endif + +namespace boost { +namespace locale { +namespace impl_posix { + +template<typename CharType> +class num_format : public util::base_num_format<CharType> +{ +public: + typedef typename std::num_put<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + + num_format(boost::shared_ptr<locale_t> lc,size_t refs = 0) : + util::base_num_format<CharType>(refs), + lc_(lc) + { + } +protected: + + virtual iter_type do_format_currency(bool intl,iter_type out,std::ios_base &/*ios*/,char_type /*fill*/,long double val) const + { + char buf[4]={}; + char const *format = intl ? "%i" : "%n"; + errno=0; + ssize_t n = strfmon_l(buf,sizeof(buf),*lc_,format,static_cast<double>(val)); + if(n >= 0) + return write_it(out,buf,n); + + for(std::vector<char> tmp(sizeof(buf)*2);tmp.size() <= 4098;tmp.resize(tmp.size()*2)) { + n = strfmon_l(&tmp.front(),tmp.size(),*lc_,format,static_cast<double>(val)); + if(n >= 0) + return write_it(out,&tmp.front(),n); + } + return out; + } + + std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out,char const *ptr,size_t n) const + { + for(size_t i=0;i<n;i++) + *out++ = *ptr++; + return out; + } + + std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out,char const *ptr,size_t n) const + { + std::wstring tmp = conv::to_utf<wchar_t>(ptr,ptr+n,nl_langinfo_l(CODESET,*lc_)); + for(size_t i=0;i<tmp.size();i++) + *out++ = tmp[i]; + return out; + } +private: + + boost::shared_ptr<locale_t> lc_; + +}; /// num_format + + +template<typename CharType> +struct ftime_traits; + +template<> +struct ftime_traits<char> { + static std::string ftime(char const *format,const struct tm *t,locale_t lc) + { + char buf[16]; + size_t n=strftime_l(buf,sizeof(buf),format,t,lc); + if(n == 0) { + // should be big enough + // + // Note standard specifies that in case of the error + // the function returns 0, however 0 may be actually + // valid output value of for example empty format or an + // output of %p in some locales + // + // Thus we try to guess that 1024 would be enough. + std::vector<char> v(1024); + n = strftime_l(&v.front(),1024,format,t,lc); + return std::string(&v.front(),n); + } + return std::string(buf,n); + } +}; + +template<> +struct ftime_traits<wchar_t> { + static std::wstring ftime(wchar_t const *format,const struct tm *t,locale_t lc) + { + #ifdef HAVE_WCSFTIME_L + wchar_t buf[16]; + size_t n=wcsftime_l(buf,sizeof(buf)/sizeof(buf[0]),format,t,lc); + if(n == 0) { + // should be big enough + // + // Note standard specifies that in case of the error + // the function returns 0, however 0 may be actually + // valid output value of for example empty format or an + // output of %p in some locales + // + // Thus we try to guess that 1024 would be enough. + std::vector<wchar_t> v(1024); + n = wcsftime_l(&v.front(),1024,format,t,lc); + } + return std::wstring(&v.front(),n); + #else + std::string enc = nl_langinfo_l(CODESET,lc); + std::string nformat = conv::from_utf<wchar_t>(format,enc); + std::string nres = ftime_traits<char>::ftime(nformat.c_str(),t,lc); + return conv::to_utf<wchar_t>(nres,enc); + #endif + } +}; + + +template<typename CharType> +class time_put_posix : public std::time_put<CharType> { +public: + time_put_posix(boost::shared_ptr<locale_t> lc, size_t refs = 0) : + std::time_put<CharType>(refs), + lc_(lc) + { + } + virtual ~time_put_posix() + { + } + typedef typename std::time_put<CharType>::iter_type iter_type; + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + virtual iter_type do_put(iter_type out,std::ios_base &/*ios*/,CharType /*fill*/,std::tm const *tm,char format,char modifier) const + { + char_type fmt[4] = { '%' , modifier != 0 ? modifier : format , modifier == 0 ? '\0' : format }; + string_type res = ftime_traits<char_type>::ftime(fmt,tm,*lc_); + for(unsigned i=0;i<res.size();i++) + *out++ = res[i]; + return out; + } + +private: + boost::shared_ptr<locale_t> lc_; +}; + + +template<typename CharType> +class ctype_posix; + +template<> +class ctype_posix<char> : public std::ctype<char> { +public: + + ctype_posix(boost::shared_ptr<locale_t> lc) + { + lc_ = lc; + } + + bool do_is(mask m,char c) const + { + if((m & space) && isspace_l(c,*lc_)) + return true; + if((m & print) && isprint_l(c,*lc_)) + return true; + if((m & cntrl) && iscntrl_l(c,*lc_)) + return true; + if((m & upper) && isupper_l(c,*lc_)) + return true; + if((m & lower) && islower_l(c,*lc_)) + return true; + if((m & alpha) && isalpha_l(c,*lc_)) + return true; + if((m & digit) && isdigit_l(c,*lc_)) + return true; + if((m & xdigit) && isxdigit_l(c,*lc_)) + return true; + if((m & punct) && ispunct_l(c,*lc_)) + return true; + return false; + } + char const *do_is(char const *begin,char const *end,mask *m) const + { + while(begin!=end) { + char c= *begin++; + int r=0; + if(isspace_l(c,*lc_)) + r|=space; + if(isprint_l(c,*lc_)) + r|=cntrl; + if(iscntrl_l(c,*lc_)) + r|=space; + if(isupper_l(c,*lc_)) + r|=upper; + if(islower_l(c,*lc_)) + r|=lower; + if(isalpha_l(c,*lc_)) + r|=alpha; + if(isdigit_l(c,*lc_)) + r|=digit; + if(isxdigit_l(c,*lc_)) + r|=xdigit; + if(ispunct_l(c,*lc_)) + r|=punct; + // r actually should be mask, but some standard + // libraries (like STLPort) + // do not define operator | properly so using int+cast + *m++ = static_cast<mask>(r); + } + return begin; + } + char const *do_scan_is(mask m,char const *begin,char const *end) const + { + while(begin!=end) + if(do_is(m,*begin)) + return begin; + return begin; + } + char const *do_scan_not(mask m,char const *begin,char const *end) const + { + while(begin!=end) + if(!do_is(m,*begin)) + return begin; + return begin; + } + char toupper(char c) const + { + return toupper_l(c,*lc_); + } + char const *toupper(char *begin,char const *end) const + { + for(;begin!=end;begin++) + *begin = toupper_l(*begin,*lc_); + return begin; + } + char tolower(char c) const + { + return tolower_l(c,*lc_); + } + char const *tolower(char *begin,char const *end) const + { + for(;begin!=end;begin++) + *begin = tolower_l(*begin,*lc_); + return begin; + } +private: + boost::shared_ptr<locale_t> lc_; +}; + +template<> +class ctype_posix<wchar_t> : public std::ctype<wchar_t> { +public: + ctype_posix(boost::shared_ptr<locale_t> lc) + { + lc_ = lc; + } + + bool do_is(mask m,wchar_t c) const + { + if((m & space) && iswspace_l(c,*lc_)) + return true; + if((m & print) && iswprint_l(c,*lc_)) + return true; + if((m & cntrl) && iswcntrl_l(c,*lc_)) + return true; + if((m & upper) && iswupper_l(c,*lc_)) + return true; + if((m & lower) && iswlower_l(c,*lc_)) + return true; + if((m & alpha) && iswalpha_l(c,*lc_)) + return true; + if((m & digit) && iswdigit_l(c,*lc_)) + return true; + if((m & xdigit) && iswxdigit_l(c,*lc_)) + return true; + if((m & punct) && iswpunct_l(c,*lc_)) + return true; + return false; + } + wchar_t const *do_is(wchar_t const *begin,wchar_t const *end,mask *m) const + { + while(begin!=end) { + wchar_t c= *begin++; + int r=0; + if(iswspace_l(c,*lc_)) + r|=space; + if(iswprint_l(c,*lc_)) + r|=cntrl; + if(iswcntrl_l(c,*lc_)) + r|=space; + if(iswupper_l(c,*lc_)) + r|=upper; + if(iswlower_l(c,*lc_)) + r|=lower; + if(iswalpha_l(c,*lc_)) + r|=alpha; + if(iswdigit_l(c,*lc_)) + r|=digit; + if(iswxdigit_l(c,*lc_)) + r|=xdigit; + if(iswpunct_l(c,*lc_)) + r|=punct; + // r actually should be mask, but some standard + // libraries (like STLPort) + // do not define operator | properly so using int+cast + *m++ = static_cast<mask>(r); + } + return begin; + } + wchar_t const *do_scan_is(mask m,wchar_t const *begin,wchar_t const *end) const + { + while(begin!=end) + if(do_is(m,*begin)) + return begin; + return begin; + } + wchar_t const *do_scan_not(mask m,wchar_t const *begin,wchar_t const *end) const + { + while(begin!=end) + if(!do_is(m,*begin)) + return begin; + return begin; + } + wchar_t toupper(wchar_t c) const + { + return towupper_l(c,*lc_); + } + wchar_t const *toupper(wchar_t *begin,wchar_t const *end) const + { + for(;begin!=end;begin++) + *begin = towupper_l(*begin,*lc_); + return begin; + } + wchar_t tolower(wchar_t c) const + { + return tolower_l(c,*lc_); + } + wchar_t const *tolower(wchar_t *begin,wchar_t const *end) const + { + for(;begin!=end;begin++) + *begin = tolower_l(*begin,*lc_); + return begin; + } +private: + boost::shared_ptr<locale_t> lc_; +}; + + + + +struct basic_numpunct { + std::string grouping; + std::string thousands_sep; + std::string decimal_point; + basic_numpunct() : + decimal_point(".") + { + } + basic_numpunct(locale_t lc) + { + #if defined(__APPLE__) || defined(__FreeBSD__) + lconv *cv = localeconv_l(lc); + grouping = cv->grouping; + thousands_sep = cv->thousands_sep; + decimal_point = cv->decimal_point; + #else + thousands_sep = nl_langinfo_l(THOUSEP,lc); + decimal_point = nl_langinfo_l(RADIXCHAR,lc); + #ifdef GROUPING + grouping = nl_langinfo_l(GROUPING,lc); + #endif + #endif + } +}; + +template<typename CharType> +class num_punct_posix : public std::numpunct<CharType> { +public: + typedef std::basic_string<CharType> string_type; + num_punct_posix(locale_t lc,size_t refs = 0) : + std::numpunct<CharType>(refs) + { + basic_numpunct np(lc); + to_str(np.thousands_sep,thousands_sep_,lc); + to_str(np.decimal_point,decimal_point_,lc); + grouping_ = np.grouping; + if(thousands_sep_.size() > 1) + grouping_ = std::string(); + if(decimal_point_.size() > 1) + decimal_point_ = CharType('.'); + } + void to_str(std::string &s1,std::string &s2,locale_t /*lc*/) + { + s2.swap(s1); + } + void to_str(std::string &s1,std::wstring &s2,locale_t lc) + { + s2=conv::to_utf<wchar_t>(s1,nl_langinfo_l(CODESET,lc)); + } + virtual CharType do_decimal_point() const + { + return *decimal_point_.c_str(); + } + virtual CharType do_thousands_sep() const + { + return *thousands_sep_.c_str(); + } + virtual std::string do_grouping() const + { + return grouping_; + } + virtual string_type do_truename() const + { + static const char t[]="true"; + return string_type(t,t+sizeof(t)-1); + } + virtual string_type do_falsename() const + { + static const char t[]="false"; + return string_type(t,t+sizeof(t)-1); + } +private: + string_type decimal_point_; + string_type thousands_sep_; + std::string grouping_; +}; + +template<typename CharType> +std::locale create_formatting_impl(std::locale const &in,boost::shared_ptr<locale_t> lc) +{ + std::locale tmp = std::locale(in,new num_punct_posix<CharType>(*lc)); + tmp = std::locale(tmp,new ctype_posix<CharType>(lc)); + tmp = std::locale(tmp,new time_put_posix<CharType>(lc)); + tmp = std::locale(tmp,new num_format<CharType>(lc)); + return tmp; +} + +template<typename CharType> +std::locale create_parsing_impl(std::locale const &in,boost::shared_ptr<locale_t> lc) +{ + std::locale tmp = std::locale(in,new num_punct_posix<CharType>(*lc)); + tmp = std::locale(tmp,new ctype_posix<CharType>(lc)); + tmp = std::locale(tmp,new util::base_num_parse<CharType>()); + return tmp; +} + + +std::locale create_formatting( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return create_formatting_impl<char>(in,lc); + case wchar_t_facet: + return create_formatting_impl<wchar_t>(in,lc); + default: + return in; + } +} + +std::locale create_parsing( std::locale const &in, + boost::shared_ptr<locale_t> lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return create_parsing_impl<char>(in,lc); + case wchar_t_facet: + return create_parsing_impl<wchar_t>(in,lc); + default: + return in; + } +} + + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/posix_backend.cpp b/src/boost/libs/locale/src/posix/posix_backend.cpp new file mode 100644 index 000000000..2ab121df9 --- /dev/null +++ b/src/boost/libs/locale/src/posix/posix_backend.cpp @@ -0,0 +1,184 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#if defined(__FreeBSD__) +#include <xlocale.h> +#endif +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include <boost/locale/info.hpp> +#include "all_generator.hpp" +#include "posix_backend.hpp" + +#include "../util/locale_data.hpp" +#include "../util/gregorian.hpp" +#include <boost/locale/util.hpp> +#include <algorithm> +#include <iterator> + +#include <langinfo.h> + +namespace boost { +namespace locale { +namespace impl_posix { + + class posix_localization_backend : public localization_backend { + public: + posix_localization_backend() : + invalid_(true) + { + } + posix_localization_backend(posix_localization_backend const &other) : + localization_backend(), + paths_(other.paths_), + domains_(other.domains_), + locale_id_(other.locale_id_), + invalid_(true) + { + } + virtual posix_localization_backend *clone() const + { + return new posix_localization_backend(*this); + } + + void set_option(std::string const &name,std::string const &value) + { + invalid_ = true; + if(name=="locale") + locale_id_ = value; + else if(name=="message_path") + paths_.push_back(value); + else if(name=="message_application") + domains_.push_back(value); + + } + void clear_options() + { + invalid_ = true; + locale_id_.clear(); + paths_.clear(); + domains_.clear(); + } + + static void free_locale_by_ptr(locale_t *lc) + { + freelocale(*lc); + delete lc; + } + + void prepare_data() + { + if(!invalid_) + return; + invalid_ = false; + lc_.reset(); + real_id_ = locale_id_; + if(real_id_.empty()) + real_id_ = util::get_system_locale(); + + locale_t tmp = newlocale(LC_ALL_MASK,real_id_.c_str(),0); + + if(!tmp) { + tmp=newlocale(LC_ALL_MASK,"C",0); + } + if(!tmp) { + throw std::runtime_error("newlocale failed"); + } + + locale_t *tmp_p = 0; + + try { + tmp_p = new locale_t(); + } + catch(...) { + freelocale(tmp); + throw; + } + + *tmp_p = tmp; + lc_ = boost::shared_ptr<locale_t>(tmp_p,free_locale_by_ptr); + } + + virtual std::locale install(std::locale const &base, + locale_category_type category, + character_facet_type type = nochar_facet) + { + prepare_data(); + + switch(category) { + case convert_facet: + return create_convert(base,lc_,type); + case collation_facet: + return create_collate(base,lc_,type); + case formatting_facet: + return create_formatting(base,lc_,type); + case parsing_facet: + return create_parsing(base,lc_,type); + case codepage_facet: + return create_codecvt(base,nl_langinfo_l(CODESET,*lc_),type); + case calendar_facet: + { + util::locale_data inf; + inf.parse(real_id_); + return util::install_gregorian_calendar(base,inf.country); + } + case message_facet: + { + gnu_gettext::messages_info minf; + util::locale_data inf; + inf.parse(real_id_); + minf.language = inf.language; + minf.country = inf.country; + minf.variant = inf.variant; + minf.encoding = inf.encoding; + std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); + minf.paths = paths_; + switch(type) { + case char_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); + case wchar_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf)); + #endif + default: + return base; + } + } + case information_facet: + return util::create_info(base,real_id_); + default: + return base; + } + } + + private: + + std::vector<std::string> paths_; + std::vector<std::string> domains_; + std::string locale_id_; + std::string real_id_; + + bool invalid_; + boost::shared_ptr<locale_t> lc_; + }; + + localization_backend *create_localization_backend() + { + return new posix_localization_backend(); + } + +} // impl posix +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/posix/posix_backend.hpp b/src/boost/libs/locale/src/posix/posix_backend.hpp new file mode 100644 index 000000000..586a33abd --- /dev/null +++ b/src/boost/libs/locale/src/posix/posix_backend.hpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_POSIX_LOCALIZATION_BACKEND_HPP +#define BOOST_LOCALE_IMPL_POSIX_LOCALIZATION_BACKEND_HPP +namespace boost { + namespace locale { + class localization_backend; + namespace impl_posix { + localization_backend *create_localization_backend(); + } // impl_std + } // locale +} // boost +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/date_time.cpp b/src/boost/libs/locale/src/shared/date_time.cpp new file mode 100644 index 000000000..4f68b7d8f --- /dev/null +++ b/src/boost/libs/locale/src/shared/date_time.cpp @@ -0,0 +1,469 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/date_time.hpp> +#include <boost/locale/formatting.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <math.h> + +namespace boost { +namespace locale { + +using namespace period; + +///////////////////////// +// Calendar +//////////////////////// + +calendar::calendar(std::locale const &l,std::string const &zone) : + locale_(l), + tz_(zone), + impl_(std::use_facet<calendar_facet>(l).create_calendar()) +{ + impl_->set_timezone(tz_); +} + +calendar::calendar(std::string const &zone) : + tz_(zone), + impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) +{ + impl_->set_timezone(tz_); +} + + +calendar::calendar(std::locale const &l) : + locale_(l), + tz_(time_zone::global()), + impl_(std::use_facet<calendar_facet>(l).create_calendar()) +{ + impl_->set_timezone(tz_); +} + +calendar::calendar(std::ios_base &ios) : + locale_(ios.getloc()), + tz_(ios_info::get(ios).time_zone()), + impl_(std::use_facet<calendar_facet>(locale_).create_calendar()) +{ + impl_->set_timezone(tz_); + +} + +calendar::calendar() : + tz_(time_zone::global()), + impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) +{ + impl_->set_timezone(tz_); +} + +calendar::~calendar() +{ +} + +calendar::calendar(calendar const &other) : + locale_(other.locale_), + tz_(other.tz_), + impl_(other.impl_->clone()) +{ +} + +calendar const &calendar::operator = (calendar const &other) +{ + if(this !=&other) { + impl_.reset(other.impl_->clone()); + locale_ = other.locale_; + tz_ = other.tz_; + } + return *this; +} + + +bool calendar::is_gregorian() const +{ + return impl_->get_option(abstract_calendar::is_gregorian)!=0; +} + +std::string calendar::get_time_zone() const +{ + return tz_; +} + +std::locale calendar::get_locale() const +{ + return locale_; +} + +int calendar::minimum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::absolute_minimum); +} + +int calendar::greatest_minimum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::greatest_minimum); +} + +int calendar::maximum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::absolute_maximum); +} + +int calendar::least_maximum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::least_maximum); +} + +int calendar::first_day_of_week() const +{ + return impl_->get_value(period::marks::first_day_of_week,abstract_calendar::current); +} + +bool calendar::operator==(calendar const &other) const +{ + return impl_->same(other.impl_.get()); +} + +bool calendar::operator!=(calendar const &other) const +{ + return !(*this==other); +} + +////////////////////////////////// +// date_time +///////////////// + +date_time::date_time() : + impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) +{ + impl_->set_timezone(time_zone::global()); +} + +date_time::date_time(date_time const &other) +{ + impl_.reset(other.impl_->clone()); +} + +date_time::date_time(date_time const &other,date_time_period_set const &s) +{ + impl_.reset(other.impl_->clone()); + for(unsigned i=0;i<s.size();i++) { + impl_->set_value(s[i].type.mark(),s[i].value); + } + impl_->normalize(); +} + +date_time const &date_time::operator = (date_time const &other) +{ + if(this != &other) { + date_time tmp(other); + swap(tmp); + } + return *this; +} + +date_time::~date_time() +{ +} + +date_time::date_time(double t) : + impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) +{ + impl_->set_timezone(time_zone::global()); + time(t); +} + +date_time::date_time(double t,calendar const &cal) : + impl_(cal.impl_->clone()) +{ + time(t); +} + +date_time::date_time(calendar const &cal) : + impl_(cal.impl_->clone()) +{ +} + + + +date_time::date_time(date_time_period_set const &s) : + impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar()) +{ + impl_->set_timezone(time_zone::global()); + for(unsigned i=0;i<s.size();i++) { + impl_->set_value(s[i].type.mark(),s[i].value); + } + impl_->normalize(); +} +date_time::date_time(date_time_period_set const &s,calendar const &cal) : + impl_(cal.impl_->clone()) +{ + for(unsigned i=0;i<s.size();i++) { + impl_->set_value(s[i].type.mark(),s[i].value); + } + impl_->normalize(); +} + +date_time const &date_time::operator=(date_time_period_set const &s) +{ + for(unsigned i=0;i<s.size();i++) + impl_->set_value(s[i].type.mark(),s[i].value); + impl_->normalize(); + return *this; +} + +void date_time::set(period_type f,int v) +{ + impl_->set_value(f.mark(),v); + impl_->normalize(); +} + +int date_time::get(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::current); +} + +date_time date_time::operator+(date_time_period const &v) const +{ + date_time tmp(*this); + tmp+=v; + return tmp; +} + +date_time date_time::operator-(date_time_period const &v) const +{ + date_time tmp(*this); + tmp-=v; + return tmp; +} + +date_time date_time::operator<<(date_time_period const &v) const +{ + date_time tmp(*this); + tmp<<=v; + return tmp; +} + +date_time date_time::operator>>(date_time_period const &v) const +{ + date_time tmp(*this); + tmp>>=v; + return tmp; +} + +date_time const &date_time::operator+=(date_time_period const &v) +{ + impl_->adjust_value(v.type.mark(),abstract_calendar::move,v.value); + return *this; +} + +date_time const &date_time::operator-=(date_time_period const &v) +{ + impl_->adjust_value(v.type.mark(),abstract_calendar::move,-v.value); + return *this; +} + +date_time const &date_time::operator<<=(date_time_period const &v) +{ + impl_->adjust_value(v.type.mark(),abstract_calendar::roll,v.value); + return *this; +} + +date_time const &date_time::operator>>=(date_time_period const &v) +{ + impl_->adjust_value(v.type.mark(),abstract_calendar::roll,-v.value); + return *this; +} + + +date_time date_time::operator+(date_time_period_set const &v) const +{ + date_time tmp(*this); + tmp+=v; + return tmp; +} + +date_time date_time::operator-(date_time_period_set const &v) const +{ + date_time tmp(*this); + tmp-=v; + return tmp; +} + +date_time date_time::operator<<(date_time_period_set const &v) const +{ + date_time tmp(*this); + tmp<<=v; + return tmp; +} + +date_time date_time::operator>>(date_time_period_set const &v) const +{ + date_time tmp(*this); + tmp>>=v; + return tmp; +} + +date_time const &date_time::operator+=(date_time_period_set const &v) +{ + for(unsigned i=0;i<v.size();i++) { + *this+=v[i]; + } + return *this; +} + +date_time const &date_time::operator-=(date_time_period_set const &v) +{ + for(unsigned i=0;i<v.size();i++) { + *this-=v[i]; + } + return *this; +} + +date_time const &date_time::operator<<=(date_time_period_set const &v) +{ + for(unsigned i=0;i<v.size();i++) { + *this<<=v[i]; + } + return *this; +} + +date_time const &date_time::operator>>=(date_time_period_set const &v) +{ + for(unsigned i=0;i<v.size();i++) { + *this>>=v[i]; + } + return *this; +} + +double date_time::time() const +{ + posix_time ptime = impl_->get_time(); + return double(ptime.seconds)+1e-9*ptime.nanoseconds; +} + +void date_time::time(double v) +{ + double dseconds = floor(v); + int64_t seconds = static_cast<int64_t>(dseconds); + double fract = v - dseconds; + int nano = static_cast<int>(fract * 1e9); + if(nano < 0) + nano = 0; + else if(nano >999999999) + nano = 999999999; + posix_time ptime; + ptime.seconds = seconds; + ptime.nanoseconds = nano; + impl_->set_time(ptime); +} + +namespace { + int compare(posix_time const &left,posix_time const &right) + { + if(left.seconds < right.seconds) + return -1; + if(left.seconds > right.seconds) + return 1; + if(left.nanoseconds < right.nanoseconds) + return -1; + if(left.nanoseconds > right.nanoseconds) + return 1; + return 0; + } +} + +bool date_time::operator==(date_time const &other) const +{ + return compare(impl_->get_time(),other.impl_->get_time()) == 0; +} + +bool date_time::operator!=(date_time const &other) const +{ + return !(*this==other); +} + +bool date_time::operator<(date_time const &other) const +{ + return compare(impl_->get_time(),other.impl_->get_time()) < 0; +} + +bool date_time::operator>=(date_time const &other) const +{ + return !(*this<other); +} + +bool date_time::operator>(date_time const &other) const +{ + return compare(impl_->get_time(),other.impl_->get_time()) > 0; +} + +bool date_time::operator<=(date_time const &other) const +{ + return !(*this>other); +} + +void date_time::swap(date_time &other) +{ + impl_.swap(other.impl_); +} + +int date_time::difference(date_time const &other,period_type f) const +{ + return impl_->difference(other.impl_.get(),f.mark()); +} + +int date_time::maximum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::actual_maximum); +} + +int date_time::minimum(period_type f) const +{ + return impl_->get_value(f.mark(),abstract_calendar::actual_minimum); +} + +bool date_time::is_in_daylight_saving_time() const +{ + return impl_->get_option(abstract_calendar::is_dst)!=0; +} + +namespace time_zone { + boost::mutex &tz_mutex() + { + static boost::mutex m; + return m; + } + std::string &tz_id() + { + static std::string id; + return id; + } + std::string global() + { + boost::unique_lock<boost::mutex> lock(tz_mutex()); + std::string id = tz_id(); + return id; + } + std::string global(std::string const &new_id) + { + boost::unique_lock<boost::mutex> lock(tz_mutex()); + std::string id = tz_id(); + tz_id() = new_id; + return id; + } +} + + + +} // locale +} // boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/format.cpp b/src/boost/libs/locale/src/shared/format.cpp new file mode 100644 index 000000000..839ee5222 --- /dev/null +++ b/src/boost/libs/locale/src/shared/format.cpp @@ -0,0 +1,188 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/format.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <limits> +#include <stdlib.h> + +#include <iostream> + +namespace boost { + namespace locale { + namespace details { + struct format_parser::data { + unsigned position; + std::streamsize precision; + std::ios_base::fmtflags flags; + ios_info info; + std::locale saved_locale; + bool restore_locale; + void *cookie; + void (*imbuer)(void *,std::locale const &); + }; + + format_parser::format_parser(std::ios_base &ios,void *cookie,void (*imbuer)(void *,std::locale const &)) : + ios_(ios), + d(new data) + { + d->position=std::numeric_limits<unsigned>::max(); + d->precision=ios.precision(); + d->flags = ios.flags(); + d->info=ios_info::get(ios); + d->saved_locale = ios.getloc(); + d->restore_locale=false; + d->cookie = cookie; + d->imbuer = imbuer; + } + + void format_parser::imbue(std::locale const &l) + { + d->imbuer(d->cookie,l); + } + + format_parser::~format_parser() + { + } + + void format_parser::restore() + { + ios_info::get(ios_) = d->info; + ios_.width(0); + ios_.flags(d->flags); + if(d->restore_locale) + imbue(d->saved_locale); + } + + unsigned format_parser::get_position() + { + return d->position; + } + + void format_parser::set_one_flag(std::string const &key,std::string const &value) + { + if(key.empty()) + return; + unsigned i; + for(i=0;i<key.size();i++) { + if(key[i] < '0' || '9'< key[i]) + break; + } + if(i==key.size()) { + d->position=atoi(key.c_str()) - 1; + return; + } + + if(key=="num" || key=="number") { + as::number(ios_); + + if(value=="hex") + ios_.setf(std::ios_base::hex,std::ios_base::basefield); + else if(value=="oct") + ios_.setf(std::ios_base::oct,std::ios_base::basefield); + else if(value=="sci" || value=="scientific") + ios_.setf(std::ios_base::scientific,std::ios_base::floatfield); + else if(value=="fix" || value=="fixed") + ios_.setf(std::ios_base::fixed,std::ios_base::floatfield); + } + else if(key=="cur" || key=="currency") { + as::currency(ios_); + if(value=="iso") + as::currency_iso(ios_); + else if(value=="nat" || value=="national") + as::currency_national(ios_); + } + else if(key=="per" || key=="percent") { + as::percent(ios_); + } + else if(key=="date") { + as::date(ios_); + if(value=="s" || value=="short") + as::date_short(ios_); + else if(value=="m" || value=="medium") + as::date_medium(ios_); + else if(value=="l" || value=="long") + as::date_long(ios_); + else if(value=="f" || value=="full") + as::date_full(ios_); + } + else if(key=="time") { + as::time(ios_); + if(value=="s" || value=="short") + as::time_short(ios_); + else if(value=="m" || value=="medium") + as::time_medium(ios_); + else if(value=="l" || value=="long") + as::time_long(ios_); + else if(value=="f" || value=="full") + as::time_full(ios_); + } + else if(key=="dt" || key=="datetime") { + as::datetime(ios_); + if(value=="s" || value=="short") { + as::date_short(ios_); + as::time_short(ios_); + } + else if(value=="m" || value=="medium") { + as::date_medium(ios_); + as::time_medium(ios_); + } + else if(value=="l" || value=="long") { + as::date_long(ios_); + as::time_long(ios_); + } + else if(value=="f" || value=="full") { + as::date_full(ios_); + as::time_full(ios_); + } + } + else if(key=="spell" || key=="spellout") { + as::spellout(ios_); + } + else if(key=="ord" || key=="ordinal") { + as::ordinal(ios_); + } + else if(key=="left" || key=="<") + ios_.setf(std::ios_base::left,std::ios_base::adjustfield); + else if(key=="right" || key==">") + ios_.setf(std::ios_base::right,std::ios_base::adjustfield); + else if(key=="gmt") + as::gmt(ios_); + else if(key=="local") + as::local_time(ios_); + else if(key=="timezone" || key=="tz") + ios_info::get(ios_).time_zone(value); + else if(key=="w" || key=="width") + ios_.width(atoi(value.c_str())); + else if(key=="p" || key=="precision") + ios_.precision(atoi(value.c_str())); + else if(key=="locale") { + if(!d->restore_locale) { + d->saved_locale=ios_.getloc(); + d->restore_locale=true; + } + + std::string encoding=std::use_facet<info>(d->saved_locale).encoding(); + generator gen; + gen.categories(formatting_facet); + + std::locale new_loc; + if(value.find('.')==std::string::npos) + new_loc = gen(value + "." + encoding); + else + new_loc = gen(value); + + imbue(new_loc); + } + + } + } + } +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/shared/formatting.cpp b/src/boost/libs/locale/src/shared/formatting.cpp new file mode 100644 index 000000000..70c16c908 --- /dev/null +++ b/src/boost/libs/locale/src/shared/formatting.cpp @@ -0,0 +1,180 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/formatting.hpp> +#include <boost/locale/date_time.hpp> +#include <typeinfo> +#include <algorithm> +#include "ios_prop.hpp" + +namespace boost { + namespace locale { + + ios_info::string_set::string_set() : + type(0), + size(0), + ptr(0) + { + } + ios_info::string_set::~string_set() + { + delete [] ptr; + } + ios_info::string_set::string_set(string_set const &other) + { + if(other.ptr!=0) { + ptr=new char[other.size]; + size=other.size; + type=other.type; + memcpy(ptr,other.ptr,size); + } + else { + ptr=0; + size=0; + type=0; + } + } + + void ios_info::string_set::swap(string_set &other) + { + std::swap(type,other.type); + std::swap(size,other.size); + std::swap(ptr,other.ptr); + } + + ios_info::string_set const &ios_info::string_set::operator=(string_set const &other) + { + if(this!=&other) { + string_set tmp(other); + swap(tmp); + } + return *this; + } + + struct ios_info::data {}; + + ios_info::ios_info() : + flags_(0), + domain_id_(0), + d(0) + { + time_zone_ = time_zone::global(); + } + ios_info::~ios_info() + { + } + + ios_info::ios_info(ios_info const &other) + { + flags_ = other.flags_; + domain_id_ = other.domain_id_; + time_zone_ = other.time_zone_; + datetime_ = other.datetime_; + } + + + ios_info const &ios_info::operator=(ios_info const &other) + { + if(this!=&other) { + flags_ = other.flags_; + domain_id_ = other.domain_id_; + time_zone_ = other.time_zone_; + datetime_ = other.datetime_; + } + return *this; + } + + void ios_info::display_flags(uint64_t f) + { + flags_ = (flags_ & ~uint64_t(flags::display_flags_mask)) | f; + } + void ios_info::currency_flags(uint64_t f) + { + flags_ = (flags_ & ~uint64_t(flags::currency_flags_mask)) | f; + } + void ios_info::date_flags(uint64_t f) + { + flags_ = (flags_ & ~uint64_t(flags::date_flags_mask)) | f; + } + void ios_info::time_flags(uint64_t f) + { + flags_ = (flags_ & ~uint64_t(flags::time_flags_mask)) | f; + } + + void ios_info::domain_id(int id) + { + domain_id_ = id; + } + + void ios_info::time_zone(std::string const &tz) + { + time_zone_ = tz; + } + + uint64_t ios_info::display_flags() const + { + return flags_ & flags::display_flags_mask; + } + + uint64_t ios_info::currency_flags() const + { + return flags_ & flags::currency_flags_mask; + } + + uint64_t ios_info::date_flags() const + { + return flags_ & flags::date_flags_mask; + } + + uint64_t ios_info::time_flags() const + { + return flags_ & flags::time_flags_mask; + } + + int ios_info::domain_id() const + { + return domain_id_; + } + + std::string ios_info::time_zone() const + { + return time_zone_; + } + + ios_info::string_set const &ios_info::date_time_pattern_set() const + { + return datetime_; + } + + + ios_info::string_set &ios_info::date_time_pattern_set() + { + return datetime_; + } + + ios_info &ios_info::get(std::ios_base &ios) + { + return impl::ios_prop<ios_info>::get(ios); + } + + void ios_info::on_imbue() + { + } + + namespace { + struct initializer { + initializer() { + impl::ios_prop<ios_info>::global_init(); + } + } initializer_instance; + } // namespace + + } // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/shared/generator.cpp b/src/boost/libs/locale/src/shared/generator.cpp new file mode 100644 index 000000000..a93ecb273 --- /dev/null +++ b/src/boost/libs/locale/src/shared/generator.cpp @@ -0,0 +1,192 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/locale/localization_backend.hpp> +#include <map> +#include <vector> +#include <algorithm> +#include <boost/shared_ptr.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> + +namespace boost { + namespace locale { + struct generator::data { + data(localization_backend_manager const &mgr) : + cats(all_categories), + chars(all_characters), + caching_enabled(false), + use_ansi_encoding(false), + backend_manager(mgr) + { + } + + typedef std::map<std::string,std::locale> cached_type; + mutable cached_type cached; + mutable boost::mutex cached_lock; + + locale_category_type cats; + character_facet_type chars; + + bool caching_enabled; + bool use_ansi_encoding; + + std::vector<std::string> paths; + std::vector<std::string> domains; + + std::map<std::string,std::vector<std::string> > options; + + localization_backend_manager backend_manager; + + }; + + generator::generator(localization_backend_manager const &mgr) : + d(new generator::data(mgr)) + { + } + generator::generator() : + d(new generator::data(localization_backend_manager::global())) + { + } + generator::~generator() + { + } + + locale_category_type generator::categories() const + { + return d->cats; + } + void generator::categories(locale_category_type t) + { + d->cats=t; + } + + void generator::characters(character_facet_type t) + { + d->chars=t; + } + + character_facet_type generator::characters() const + { + return d->chars; + } + + void generator::add_messages_domain(std::string const &domain) + { + if(std::find(d->domains.begin(),d->domains.end(),domain) == d->domains.end()) + d->domains.push_back(domain); + } + + void generator::set_default_messages_domain(std::string const &domain) + { + std::vector<std::string>::iterator p; + if((p=std::find(d->domains.begin(),d->domains.end(),domain)) != d->domains.end()) { + d->domains.erase(p); + } + d->domains.insert(d->domains.begin(),domain); + } + + void generator::clear_domains() + { + d->domains.clear(); + } + void generator::add_messages_path(std::string const &path) + { + d->paths.push_back(path); + } + void generator::clear_paths() + { + d->paths.clear(); + } + void generator::clear_cache() + { + d->cached.clear(); + } + + std::locale generator::generate(std::string const &id) const + { + std::locale base=std::locale::classic(); + + return generate(base,id); + } + + std::locale generator::generate(std::locale const &base,std::string const &id) const + { + if(d->caching_enabled) { + boost::unique_lock<boost::mutex> guard(d->cached_lock); + data::cached_type::const_iterator p = d->cached.find(id); + if(p!=d->cached.end()) { + return p->second; + } + } + shared_ptr<localization_backend> backend(d->backend_manager.create()); + set_all_options(backend,id); + + std::locale result = base; + locale_category_type facets = d->cats; + character_facet_type chars = d->chars; + + for(locale_category_type facet = per_character_facet_first; facet <= per_character_facet_last && facet!=0; facet <<=1) { + if(!(facets & facet)) + continue; + for(character_facet_type ch = character_first_facet ; ch<=character_last_facet;ch <<=1) { + if(!(ch & chars)) + continue; + result = backend->install(result,facet,ch); + } + } + for(locale_category_type facet = non_character_facet_first; facet <= non_character_facet_last && facet!=0; facet <<=1) { + if(!(facets & facet)) + continue; + result = backend->install(result,facet); + } + if(d->caching_enabled) { + boost::unique_lock<boost::mutex> guard(d->cached_lock); + data::cached_type::const_iterator p = d->cached.find(id); + if(p==d->cached.end()) { + d->cached[id] = result; + } + } + return result; + } + + bool generator::use_ansi_encoding() const + { + return d->use_ansi_encoding; + } + + void generator::use_ansi_encoding(bool v) + { + d->use_ansi_encoding = v; + } + + bool generator::locale_cache_enabled() const + { + return d->caching_enabled; + } + void generator::locale_cache_enabled(bool enabled) + { + d->caching_enabled = enabled; + } + + void generator::set_all_options(shared_ptr<localization_backend> backend,std::string const &id) const + { + backend->set_option("locale",id); + if(d->use_ansi_encoding) + backend->set_option("use_ansi_encoding","true"); + for(size_t i=0;i<d->domains.size();i++) + backend->set_option("message_application",d->domains[i]); + for(size_t i=0;i<d->paths.size();i++) + backend->set_option("message_path",d->paths[i]); + } + + } // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/shared/ids.cpp b/src/boost/libs/locale/src/shared/ids.cpp new file mode 100644 index 000000000..952fa85a5 --- /dev/null +++ b/src/boost/libs/locale/src/shared/ids.cpp @@ -0,0 +1,88 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/boundary.hpp> +#include <boost/locale/collator.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/date_time_facet.hpp> +#include <boost/locale/message.hpp> +#include <boost/locale/info.hpp> + +namespace boost { + namespace locale { + + std::locale::id info::id; + std::locale::id calendar_facet::id; + + std::locale::id converter<char>::id; + std::locale::id base_message_format<char>::id; + + std::locale::id converter<wchar_t>::id; + std::locale::id base_message_format<wchar_t>::id; + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + + std::locale::id converter<char16_t>::id; + std::locale::id base_message_format<char16_t>::id; + + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + + std::locale::id converter<char32_t>::id; + std::locale::id base_message_format<char32_t>::id; + + #endif + + namespace boundary { + + std::locale::id boundary_indexing<char>::id; + + std::locale::id boundary_indexing<wchar_t>::id; + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::locale::id boundary_indexing<char16_t>::id; + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::locale::id boundary_indexing<char32_t>::id; + #endif + } + + namespace { + struct install_all { + install_all() + { + std::locale l = std::locale::classic(); + install_by<char>(); + install_by<wchar_t>(); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + install_by<char16_t>(); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + install_by<char32_t>(); + #endif + + std::has_facet<info>(l); + std::has_facet<calendar_facet>(l); + } + template<typename Char> + void install_by() + { + std::locale l = std::locale::classic(); + std::has_facet<boundary::boundary_indexing<Char> >(l); + std::has_facet<converter<Char> >(l); + std::has_facet<base_message_format<Char> >(l); + } + } installer; + } + + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/shared/ios_prop.hpp b/src/boost/libs/locale/src/shared/ios_prop.hpp new file mode 100644 index 000000000..0a820e126 --- /dev/null +++ b/src/boost/libs/locale/src/shared/ios_prop.hpp @@ -0,0 +1,109 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_SRC_LOCALE_IOS_PROP_HPP +#define BOOST_SRC_LOCALE_IOS_PROP_HPP +#include <ios> + +namespace boost { + namespace locale { + namespace impl { + + template<typename Property> + class ios_prop { + public: + static void set(Property const &prop,std::ios_base &ios) + { + int id=get_id(); + if(ios.pword(id)==0) { + ios.pword(id) = new Property(prop); + ios.register_callback(callback,id); + } + else if(ios.pword(id)==invalid) { + ios.pword(id) = new Property(prop); + } + else { + *static_cast<Property *>(ios.pword(id))=prop; + } + } + + static Property &get(std::ios_base &ios) + { + int id=get_id(); + if(!has(ios)) + set(Property(),ios); + return *static_cast<Property *>(ios.pword(id)); + } + + static bool has(std::ios_base &ios) + { + int id=get_id(); + if(ios.pword(id)==0 || ios.pword(id)==invalid) + return false; + return true; + } + + static void unset(std::ios_base &ios) + { + if(has(ios)) { + int id=get_id(); + Property *p=static_cast<Property *>(ios.pword(id)); + delete p; + ios.pword(id)=invalid; + } + } + static void global_init() + { + get_id(); + } + private: + static void * const invalid; + + static void callback(std::ios_base::event ev,std::ios_base &ios,int id) + { + switch(ev) { + case std::ios_base::erase_event: + if(!has(ios)) + break; + delete reinterpret_cast<Property *>(ios.pword(id)); + break; + case std::ios_base::copyfmt_event: + if(ios.pword(id)==invalid || ios.pword(id)==0) + break; + ios.pword(id)=new Property(*reinterpret_cast<Property *>(ios.pword(id))); + break; + case std::ios_base::imbue_event: + if(ios.pword(id)==invalid || ios.pword(id)==0) + break; + reinterpret_cast<Property *>(ios.pword(id))->on_imbue(); + break; + + default: ; + } + } + static int get_id() + { + static int id = std::ios_base::xalloc(); + return id; + } + }; + + template<typename Property> + void * const ios_prop<Property>::invalid = (void *)(-1); + + + + } + } +} + + + +#endif + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/localization_backend.cpp b/src/boost/libs/locale/src/shared/localization_backend.cpp new file mode 100644 index 000000000..0a9b7a281 --- /dev/null +++ b/src/boost/libs/locale/src/shared/localization_backend.cpp @@ -0,0 +1,285 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/localization_backend.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/locale/hold_ptr.hpp> +#include <vector> + +#ifdef BOOST_LOCALE_WITH_ICU +#include "../icu/icu_backend.hpp" +#endif + +#ifndef BOOST_LOCALE_NO_POSIX_BACKEND +#include "../posix/posix_backend.hpp" +#endif + +#ifndef BOOST_LOCALE_NO_STD_BACKEND +#include "../std/std_backend.hpp" +#endif + +#ifndef BOOST_LOCALE_NO_WINAPI_BACKEND +#include "../win32/win_backend.hpp" +#endif + +namespace boost { + namespace locale { + class localization_backend_manager::impl { + void operator = (impl const &); + public: + impl(impl const &other) : + default_backends_(other.default_backends_) + { + for(all_backends_type::const_iterator p=other.all_backends_.begin();p!=other.all_backends_.end();++p) { + all_backends_type::value_type v; + v.first=p->first; + v.second.reset(p->second->clone()); + all_backends_.push_back(v); + } + } + impl() : + default_backends_(32,-1) + { + } + + localization_backend *create() const + { + std::vector<boost::shared_ptr<localization_backend> > backends; + for(unsigned i=0;i<all_backends_.size();i++) + backends.push_back(all_backends_[i].second); + return new actual_backend(backends,default_backends_); + } + void adopt_backend(std::string const &name,localization_backend *backend_ptr) + { + boost::shared_ptr<localization_backend> sptr(backend_ptr); + if(all_backends_.empty()) { + all_backends_.push_back(std::make_pair(name,sptr)); + for(unsigned i=0;i<default_backends_.size();i++) + default_backends_[i]=0; + } + else { + for(unsigned i=0;i<all_backends_.size();i++) + if(all_backends_[i].first == name) + return; + all_backends_.push_back(std::make_pair(name,sptr)); + } + } + + void select(std::string const &backend_name,locale_category_type category = all_categories) + { + unsigned id; + for(id=0;id<all_backends_.size();id++) { + if(all_backends_[id].first == backend_name) + break; + } + if(id==all_backends_.size()) + return; + for(unsigned flag = 1,i=0;i<default_backends_.size();flag <<=1,i++) { + if(category & flag) { + default_backends_[i]=id; + } + } + } + + void remove_all_backends() + { + all_backends_.clear(); + for(unsigned i=0;i<default_backends_.size();i++) { + default_backends_[i]=-1; + } + } + std::vector<std::string> get_all_backends() const + { + std::vector<std::string> res; + all_backends_type::const_iterator p; + for(p=all_backends_.begin();p!=all_backends_.end();++p) { + res.push_back(p->first); + } + return res; + } + + private: + class actual_backend : public localization_backend { + public: + actual_backend(std::vector<boost::shared_ptr<localization_backend> > const &backends,std::vector<int> const &index): + index_(index) + { + backends_.resize(backends.size()); + for(unsigned i=0;i<backends.size();i++) { + backends_[i].reset(backends[i]->clone()); + } + } + virtual actual_backend *clone() const + { + return new actual_backend(backends_,index_); + } + virtual void set_option(std::string const &name,std::string const &value) + { + for(unsigned i=0;i<backends_.size();i++) + backends_[i]->set_option(name,value); + } + virtual void clear_options() + { + for(unsigned i=0;i<backends_.size();i++) + backends_[i]->clear_options(); + } + virtual std::locale install(std::locale const &l,locale_category_type category,character_facet_type type = nochar_facet) + { + int id; + unsigned v; + for(v=1,id=0;v!=0;v<<=1,id++) { + if(category == v) + break; + } + if(v==0) + return l; + if(unsigned(id) >= index_.size()) + return l; + if(index_[id]==-1) + return l; + return backends_[index_[id]]->install(l,category,type); + } + private: + std::vector<boost::shared_ptr<localization_backend> > backends_; + std::vector<int> index_; + }; + + typedef std::vector<std::pair<std::string,boost::shared_ptr<localization_backend> > > all_backends_type; + all_backends_type all_backends_; + std::vector<int> default_backends_; + }; + + + + localization_backend_manager::localization_backend_manager() : + pimpl_(new impl()) + { + } + + localization_backend_manager::~localization_backend_manager() + { + } + + localization_backend_manager::localization_backend_manager(localization_backend_manager const &other) : + pimpl_(new impl(*other.pimpl_)) + { + } + + localization_backend_manager const &localization_backend_manager::operator = (localization_backend_manager const &other) + { + if(this!=&other) { + pimpl_.reset(new impl(*other.pimpl_)); + } + return *this; + } + + + #if !defined(BOOST_LOCALE_HIDE_AUTO_PTR) && !defined(BOOST_NO_AUTO_PTR) + std::auto_ptr<localization_backend> localization_backend_manager::get() const + { + std::auto_ptr<localization_backend> r(pimpl_->create()); + return r; + } + void localization_backend_manager::add_backend(std::string const &name,std::auto_ptr<localization_backend> backend) + { + pimpl_->adopt_backend(name,backend.release()); + } + #endif + #ifndef BOOST_NO_CXX11_SMART_PTR + std::unique_ptr<localization_backend> localization_backend_manager::get_unique_ptr() const + { + std::unique_ptr<localization_backend> r(pimpl_->create()); + return r; + } + void localization_backend_manager::add_backend(std::string const &name,std::unique_ptr<localization_backend> backend) + { + pimpl_->adopt_backend(name,backend.release()); + } + #endif + localization_backend *localization_backend_manager::create() const + { + return pimpl_->create(); + } + void localization_backend_manager::adopt_backend(std::string const &name,localization_backend *backend) + { + pimpl_->adopt_backend(name,backend); + } + + + void localization_backend_manager::remove_all_backends() + { + pimpl_->remove_all_backends(); + } + std::vector<std::string> localization_backend_manager::get_all_backends() const + { + return pimpl_->get_all_backends(); + } + void localization_backend_manager::select(std::string const &backend_name,locale_category_type category) + { + pimpl_->select(backend_name,category); + } + + namespace { + // prevent initialization order fiasco + boost::mutex &localization_backend_manager_mutex() + { + static boost::mutex the_mutex; + return the_mutex; + } + // prevent initialization order fiasco + localization_backend_manager &localization_backend_manager_global() + { + static localization_backend_manager the_manager; + return the_manager; + } + + struct init { + init() { + localization_backend_manager mgr; + #ifdef BOOST_LOCALE_WITH_ICU + mgr.adopt_backend("icu",impl_icu::create_localization_backend()); + #endif + + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + mgr.adopt_backend("posix",impl_posix::create_localization_backend()); + #endif + + #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND + mgr.adopt_backend("winapi",impl_win::create_localization_backend()); + #endif + + #ifndef BOOST_LOCALE_NO_STD_BACKEND + mgr.adopt_backend("std",impl_std::create_localization_backend()); + #endif + + localization_backend_manager::global(mgr); + } + } do_init; + } + + localization_backend_manager localization_backend_manager::global() + { + boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex()); + localization_backend_manager mgr = localization_backend_manager_global(); + return mgr; + } + localization_backend_manager localization_backend_manager::global(localization_backend_manager const &in) + { + boost::unique_lock<boost::mutex> lock(localization_backend_manager_mutex()); + localization_backend_manager mgr = localization_backend_manager_global(); + localization_backend_manager_global() = in; + return mgr; + } + + + + } // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/shared/message.cpp b/src/boost/libs/locale/src/shared/message.cpp new file mode 100644 index 000000000..e25d26fd8 --- /dev/null +++ b/src/boost/libs/locale/src/shared/message.cpp @@ -0,0 +1,784 @@ +// +// Copyright (c) 2009-2015 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#define BOOST_DETAIL_NO_CONTAINER_FWD +#include <boost/config.hpp> +#include <boost/version.hpp> +#include <boost/locale/message.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/locale/hold_ptr.hpp> +#include <boost/locale/encoding.hpp> +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif + + +#if BOOST_VERSION >= 103600 +#define BOOST_LOCALE_UNORDERED_CATALOG +#endif + +#ifdef BOOST_LOCALE_UNORDERED_CATALOG +#include <boost/unordered_map.hpp> +#else +#include <map> +#endif + +#include <iostream> + + +#include "mo_hash.hpp" +#include "mo_lambda.hpp" + +#include <stdio.h> + +#include <string.h> + +namespace boost { + namespace locale { + namespace gnu_gettext { + + class c_file { + c_file(c_file const &); + void operator=(c_file const &); + public: + + FILE *file; + + c_file() : + file(0) + { + } + ~c_file() + { + close(); + } + + void close() + { + if(file) { + fclose(file); + file=0; + } + } + + #if defined(BOOST_WINDOWS) + + bool open(std::string const &file_name,std::string const &encoding) + { + close(); + + // + // Under windows we have to use "_wfopen" to get + // access to path's with Unicode in them + // + // As not all standard C++ libraries support nonstandard std::istream::open(wchar_t const *) + // we would use old and good stdio and _wfopen CRTL functions + // + + std::wstring wfile_name = conv::to_utf<wchar_t>(file_name,encoding); + file = _wfopen(wfile_name.c_str(),L"rb"); + + return file!=0; + } + + #else // POSIX systems do not have all this Wide API crap, as native codepages are UTF-8 + + // We do not use encoding as we use native file name encoding + + bool open(std::string const &file_name,std::string const &/* encoding */) + { + close(); + + file = fopen(file_name.c_str(),"rb"); + + return file!=0; + } + + #endif + + }; + + class mo_file { + public: + typedef std::pair<char const *,char const *> pair_type; + + mo_file(std::vector<char> &file) : + native_byteorder_(true), + size_(0) + { + load_file(file); + init(); + } + + mo_file(FILE *file) : + native_byteorder_(true), + size_(0) + { + load_file(file); + init(); + } + + pair_type find(char const *context_in,char const *key_in) const + { + pair_type null_pair((char const *)0,(char const *)0); + if(hash_size_==0) + return null_pair; + uint32_t hkey = 0; + if(context_in == 0) + hkey = pj_winberger_hash_function(key_in); + else { + pj_winberger_hash::state_type st = pj_winberger_hash::initial_state; + st = pj_winberger_hash::update_state(st,context_in); + st = pj_winberger_hash::update_state(st,'\4'); // EOT + st = pj_winberger_hash::update_state(st,key_in); + hkey = st; + } + uint32_t incr = 1 + hkey % (hash_size_-2); + hkey %= hash_size_; + uint32_t orig=hkey; + + + do { + uint32_t idx = get(hash_offset_ + 4*hkey); + /// Not found + if(idx == 0) + return null_pair; + /// If equal values return translation + if(key_equals(key(idx-1),context_in,key_in)) + return value(idx-1); + /// Rehash + hkey=(hkey + incr) % hash_size_; + } while(hkey!=orig); + return null_pair; + } + + static bool key_equals(char const *real_key,char const *cntx,char const *key) + { + if(cntx == 0) + return strcmp(real_key,key) == 0; + else { + size_t real_len = strlen(real_key); + size_t cntx_len = strlen(cntx); + size_t key_len = strlen(key); + if(cntx_len + 1 + key_len != real_len) + return false; + return + memcmp(real_key,cntx,cntx_len) == 0 + && real_key[cntx_len] == '\4' + && memcmp(real_key + cntx_len + 1 ,key,key_len) == 0; + } + } + + char const *key(int id) const + { + uint32_t off = get(keys_offset_ + id*8 + 4); + return data_ + off; + } + + pair_type value(int id) const + { + uint32_t len = get(translations_offset_ + id*8); + uint32_t off = get(translations_offset_ + id*8 + 4); + if(off >= file_size_ || off + len >= file_size_) + throw std::runtime_error("Bad mo-file format"); + return pair_type(&data_[off],&data_[off]+len); + } + + bool has_hash() const + { + return hash_size_ != 0; + } + + size_t size() const + { + return size_; + } + + bool empty() + { + return size_ == 0; + } + + private: + void init() + { + // Read all format sizes + size_=get(8); + keys_offset_=get(12); + translations_offset_=get(16); + hash_size_=get(20); + hash_offset_=get(24); + } + + void load_file(std::vector<char> &data) + { + vdata_.swap(data); + file_size_ = vdata_.size(); + data_ = &vdata_[0]; + if(file_size_ < 4 ) + throw std::runtime_error("invalid 'mo' file format - the file is too short"); + uint32_t magic=0; + memcpy(&magic,data_,4); + if(magic == 0x950412de) + native_byteorder_ = true; + else if(magic == 0xde120495) + native_byteorder_ = false; + else + throw std::runtime_error("Invalid file format - invalid magic number"); + } + + void load_file(FILE *file) + { + uint32_t magic=0; + // if the size is wrong magic would be wrong + // ok to ingnore fread result + size_t four_bytes = fread(&magic,4,1,file); + (void)four_bytes; // shut GCC + + if(magic == 0x950412de) + native_byteorder_ = true; + else if(magic == 0xde120495) + native_byteorder_ = false; + else + throw std::runtime_error("Invalid file format"); + + fseek(file,0,SEEK_END); + long len=ftell(file); + if(len < 0) { + throw std::runtime_error("Wrong file object"); + } + fseek(file,0,SEEK_SET); + vdata_.resize(len+1,0); // +1 to make sure the vector is not empty + if(fread(&vdata_.front(),1,len,file)!=unsigned(len)) + throw std::runtime_error("Failed to read file"); + data_ = &vdata_[0]; + file_size_ = len; + } + + uint32_t get(unsigned offset) const + { + uint32_t tmp; + if(offset > file_size_ - 4) { + throw std::runtime_error("Bad mo-file format"); + } + memcpy(&tmp,data_ + offset,4); + convert(tmp); + return tmp; + } + + void convert(uint32_t &v) const + { + if(native_byteorder_) + return; + v = ((v & 0xFF) << 24) + | ((v & 0xFF00) << 8) + | ((v & 0xFF0000) >> 8) + | ((v & 0xFF000000) >> 24); + } + + uint32_t keys_offset_; + uint32_t translations_offset_; + uint32_t hash_size_; + uint32_t hash_offset_; + + char const *data_; + size_t file_size_; + std::vector<char> vdata_; + bool native_byteorder_; + size_t size_; + }; + + template<typename CharType> + struct mo_file_use_traits { + static const bool in_use = false; + typedef CharType char_type; + typedef std::pair<char_type const *,char_type const *> pair_type; + static pair_type use(mo_file const &/*mo*/,char_type const * /*context*/,char_type const * /*key*/) + { + return pair_type((char_type const *)(0),(char_type const *)(0)); + } + }; + + template<> + struct mo_file_use_traits<char> { + static const bool in_use = true; + typedef char char_type; + typedef std::pair<char_type const *,char_type const *> pair_type; + static pair_type use(mo_file const &mo,char const *context,char const *key) + { + return mo.find(context,key); + } + }; + + template<typename CharType> + class converter { + public: + converter(std::string /*out_enc*/,std::string in_enc) : + in_(in_enc) + { + } + + std::basic_string<CharType> operator()(char const *begin,char const *end) + { + return conv::to_utf<CharType>(begin,end,in_,conv::stop); + } + + private: + std::string in_; + }; + + template<> + class converter<char> { + public: + converter(std::string out_enc,std::string in_enc) : + out_(out_enc), + in_(in_enc) + { + } + + std::string operator()(char const *begin,char const *end) + { + return conv::between(begin,end,out_,in_,conv::stop); + } + + private: + std::string out_,in_; + }; + + template<typename CharType> + struct message_key { + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + + message_key(string_type const &c = string_type()) : + c_context_(0), + c_key_(0) + { + size_t pos = c.find(char_type(4)); + if(pos == string_type::npos) { + key_ = c; + } + else { + context_ = c.substr(0,pos); + key_ = c.substr(pos+1); + } + } + message_key(char_type const *c,char_type const *k) : + c_key_(k) + { + static const char_type empty = 0; + if(c!=0) + c_context_ = c; + else + c_context_ = ∅ + } + bool operator < (message_key const &other) const + { + int cc = compare(context(),other.context()); + if(cc != 0) + return cc < 0; + return compare(key(),other.key()) < 0; + } + bool operator==(message_key const &other) const + { + return compare(context(),other.context()) == 0 + && compare(key(),other.key())==0; + } + bool operator!=(message_key const &other) const + { + return !(*this==other); + } + char_type const *context() const + { + if(c_context_) + return c_context_; + return context_.c_str(); + } + char_type const *key() const + { + if(c_key_) + return c_key_; + return key_.c_str(); + } + private: + static int compare(char_type const *l,char_type const *r) + { + typedef std::char_traits<char_type> traits_type; + for(;;) { + char_type cl = *l++; + char_type cr = *r++; + if(cl == 0 && cr == 0) + return 0; + if(traits_type::lt(cl,cr)) + return -1; + if(traits_type::lt(cr,cl)) + return 1; + } + } + string_type context_; + string_type key_; + char_type const *c_context_; + char_type const *c_key_; + }; + + template<typename CharType> + struct hash_function { + size_t operator()(message_key<CharType> const &msg) const + { + pj_winberger_hash::state_type state = pj_winberger_hash::initial_state; + CharType const *p = msg.context(); + if(*p != 0) { + CharType const *e = p; + while(*e) + e++; + state = pj_winberger_hash::update_state(state, + reinterpret_cast<char const *>(p), + reinterpret_cast<char const *>(e)); + state = pj_winberger_hash::update_state(state,'\4'); + } + p = msg.key(); + CharType const *e = p; + while(*e) + e++; + state = pj_winberger_hash::update_state(state, + reinterpret_cast<char const *>(p), + reinterpret_cast<char const *>(e)); + return state; + } + }; + + + // By default for wide types the conversion is not requiredyy + template<typename CharType> + CharType const *runtime_conversion(CharType const *msg, + std::basic_string<CharType> &/*buffer*/, + bool /*do_conversion*/, + std::string const &/*locale_encoding*/, + std::string const &/*key_encoding*/) + { + return msg; + } + + // But still need to specialize for char + template<> + char const *runtime_conversion( char const *msg, + std::string &buffer, + bool do_conversion, + std::string const &locale_encoding, + std::string const &key_encoding) + { + if(!do_conversion) + return msg; + if(details::is_us_ascii_string(msg)) + return msg; + std::string tmp = conv::between(msg,locale_encoding,key_encoding,conv::skip); + buffer.swap(tmp); + return buffer.c_str(); + } + + template<typename CharType> + class mo_message : public message_format<CharType> { + + typedef CharType char_type; + typedef std::basic_string<CharType> string_type; + typedef message_key<CharType> key_type; + #ifdef BOOST_LOCALE_UNORDERED_CATALOG + typedef boost::unordered_map<key_type,string_type,hash_function<CharType> > catalog_type; + #else + typedef std::map<key_type,string_type> catalog_type; + #endif + typedef std::vector<catalog_type> catalogs_set_type; + typedef std::map<std::string,int> domains_map_type; + public: + + typedef std::pair<CharType const *,CharType const *> pair_type; + + virtual char_type const *get(int domain_id,char_type const *context,char_type const *id) const + { + return get_string(domain_id,context,id).first; + } + + virtual char_type const *get(int domain_id,char_type const *context,char_type const *single_id,int n) const + { + pair_type ptr = get_string(domain_id,context,single_id); + if(!ptr.first) + return 0; + int form=0; + if(plural_forms_.at(domain_id)) + form = (*plural_forms_[domain_id])(n); + else + form = n == 1 ? 0 : 1; // Fallback to english plural form + + CharType const *p=ptr.first; + for(int i=0;p < ptr.second && i<form;i++) { + p=std::find(p,ptr.second,0); + if(p==ptr.second) + return 0; + ++p; + } + if(p>=ptr.second) + return 0; + return p; + } + + virtual int domain(std::string const &domain) const + { + domains_map_type::const_iterator p=domains_.find(domain); + if(p==domains_.end()) + return -1; + return p->second; + } + + mo_message(messages_info const &inf) + { + std::string language = inf.language; + std::string variant = inf.variant; + std::string country = inf.country; + std::string encoding = inf.encoding; + std::string lc_cat = inf.locale_category; + std::vector<messages_info::domain> const &domains = inf.domains; + std::vector<std::string> const &search_paths = inf.paths; + + // + // List of fallbacks: en_US@euro, en@euro, en_US, en. + // + std::vector<std::string> paths; + + + if(!variant.empty() && !country.empty()) + paths.push_back(language + "_" + country + "@" + variant); + + if(!variant.empty()) + paths.push_back(language + "@" + variant); + + if(!country.empty()) + paths.push_back(language + "_" + country); + + paths.push_back(language); + + catalogs_.resize(domains.size()); + mo_catalogs_.resize(domains.size()); + plural_forms_.resize(domains.size()); + + + for(unsigned id=0;id<domains.size();id++) { + std::string domain=domains[id].name; + std::string key_encoding = domains[id].encoding; + domains_[domain]=id; + + + bool found=false; + for(unsigned j=0;!found && j<paths.size();j++) { + for(unsigned i=0;!found && i<search_paths.size();i++) { + std::string full_path = search_paths[i]+"/"+paths[j]+"/" + lc_cat + "/"+domain+".mo"; + found = load_file(full_path,encoding,key_encoding,id,inf.callback); + } + } + } + } + + char_type const *convert(char_type const *msg,string_type &buffer) const + { + return runtime_conversion<char_type>(msg,buffer,key_conversion_required_,locale_encoding_,key_encoding_); + } + + virtual ~mo_message() + { + } + + private: + int compare_encodings(std::string const &left,std::string const &right) + { + return convert_encoding_name(left).compare(convert_encoding_name(right)); + } + + std::string convert_encoding_name(std::string const &in) + { + std::string result; + for(unsigned i=0;i<in.size();i++) { + char c=in[i]; + if('A' <= c && c<='Z') + c=c-'A' + 'a'; + else if(('a' <= c && c<='z') || ('0' <= c && c<='9')) + ; + else + continue; + result+=c; + } + return result; + } + + + bool load_file( std::string const &file_name, + std::string const &locale_encoding, + std::string const &key_encoding, + int id, + messages_info::callback_type const &callback) + { + locale_encoding_ = locale_encoding; + key_encoding_ = key_encoding; + + key_conversion_required_ = sizeof(CharType) == 1 + && compare_encodings(locale_encoding,key_encoding)!=0; + + boost::shared_ptr<mo_file> mo; + + if(callback) { + std::vector<char> vfile = callback(file_name,locale_encoding); + if(vfile.empty()) + return false; + mo.reset(new mo_file(vfile)); + } + else { + c_file the_file; + the_file.open(file_name,locale_encoding); + if(!the_file.file) + return false; + mo.reset(new mo_file(the_file.file)); + } + + std::string plural = extract(mo->value(0).first,"plural=","\r\n;"); + + std::string mo_encoding = extract(mo->value(0).first,"charset="," \r\n;"); + + if(mo_encoding.empty()) + throw std::runtime_error("Invalid mo-format, encoding is not specified"); + + if(!plural.empty()) { + plural_forms_[id] = lambda::compile(plural.c_str());; + } + + if( mo_useable_directly(mo_encoding,*mo) ) + { + mo_catalogs_[id]=mo; + } + else { + converter<CharType> cvt_value(locale_encoding,mo_encoding); + converter<CharType> cvt_key(key_encoding,mo_encoding); + for(unsigned i=0;i<mo->size();i++) { + char const *ckey = mo->key(i); + string_type skey = cvt_key(ckey,ckey+strlen(ckey)); + key_type key(skey); + + mo_file::pair_type tmp = mo->value(i); + string_type value = cvt_value(tmp.first,tmp.second); + catalogs_[id][key].swap(value); + } + } + return true; + + } + + // Check if the mo file as-is is useful + // 1. It is char and not wide character + // 2. The locale encoding and mo encoding is same + // 3. The source strings encoding and mo encoding is same or all + // mo key strings are US-ASCII + bool mo_useable_directly( std::string const &mo_encoding, + mo_file const &mo) + { + if(sizeof(CharType) != 1) + return false; + if(!mo.has_hash()) + return false; + if(compare_encodings(mo_encoding,locale_encoding_)!=0) + return false; + if(compare_encodings(mo_encoding,key_encoding_)==0) { + return true; + } + for(unsigned i=0;i<mo.size();i++) { + if(!details::is_us_ascii_string(mo.key(i))) { + return false; + } + } + return true; + } + + + + static std::string extract(std::string const &meta,std::string const &key,char const *separator) + { + size_t pos=meta.find(key); + if(pos == std::string::npos) + return ""; + pos+=key.size(); /// size of charset= + size_t end_pos = meta.find_first_of(separator,pos); + return meta.substr(pos,end_pos - pos); + } + + + + + pair_type get_string(int domain_id,char_type const *context,char_type const *in_id) const + { + pair_type null_pair((CharType const *)0,(CharType const *)0); + if(domain_id < 0 || size_t(domain_id) >= catalogs_.size()) + return null_pair; + if(mo_file_use_traits<char_type>::in_use && mo_catalogs_[domain_id]) { + return mo_file_use_traits<char_type>::use(*mo_catalogs_[domain_id],context,in_id); + } + else { + key_type key(context,in_id); + catalog_type const &cat = catalogs_[domain_id]; + typename catalog_type::const_iterator p = cat.find(key); + if(p==cat.end()) { + return null_pair; + } + return pair_type(p->second.data(),p->second.data()+p->second.size()); + } + } + + catalogs_set_type catalogs_; + std::vector<boost::shared_ptr<mo_file> > mo_catalogs_; + std::vector<boost::shared_ptr<lambda::plural> > plural_forms_; + domains_map_type domains_; + + std::string locale_encoding_; + std::string key_encoding_; + bool key_conversion_required_; + }; + + template<> + message_format<char> *create_messages_facet(messages_info const &info) + { + return new mo_message<char>(info); + } + + template<> + message_format<wchar_t> *create_messages_facet(messages_info const &info) + { + return new mo_message<wchar_t>(info); + } + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + + template<> + message_format<char16_t> *create_messages_facet(messages_info const &info) + { + return new mo_message<char16_t>(info); + } + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + + template<> + message_format<char32_t> *create_messages_facet(messages_info const &info) + { + return new mo_message<char32_t>(info); + } + #endif + + + } /// gnu_gettext + + } // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/mo_hash.hpp b/src/boost/libs/locale/src/shared/mo_hash.hpp new file mode 100644 index 000000000..d8c8f69c3 --- /dev/null +++ b/src/boost/libs/locale/src/shared/mo_hash.hpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/cstdint.hpp> + +namespace boost { + namespace locale { + namespace gnu_gettext { + + struct pj_winberger_hash { + + typedef uint32_t state_type; + + static const state_type initial_state = 0; + + static state_type update_state(state_type value,char c) + { + value = (value << 4) + static_cast<unsigned char>(c); + uint32_t high = (value & 0xF0000000U); + if(high!=0) + value = (value ^ (high >> 24)) ^ high; + return value; + } + static state_type update_state(state_type value,char const *ptr) + { + while(*ptr) + value = update_state(value,*ptr++); + return value; + } + static state_type update_state(state_type value,char const *begin,char const *end) + { + while(begin!=end) + value = update_state(value,*begin++); + return value; + } + }; + + inline pj_winberger_hash::state_type pj_winberger_hash_function(char const *ptr) + { + pj_winberger_hash::state_type state = pj_winberger_hash::initial_state; + state = pj_winberger_hash::update_state(state,ptr); + return state; + } + + inline pj_winberger_hash::state_type pj_winberger_hash_function(char const *begin,char const *end) + { + pj_winberger_hash::state_type state = pj_winberger_hash::initial_state; + state = pj_winberger_hash::update_state(state,begin,end); + return state; + } + } + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/mo_lambda.cpp b/src/boost/libs/locale/src/shared/mo_lambda.cpp new file mode 100644 index 000000000..ab4bb0d8e --- /dev/null +++ b/src/boost/libs/locale/src/shared/mo_lambda.cpp @@ -0,0 +1,411 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include "mo_lambda.hpp" +#include <string.h> +#include <stdlib.h> + +namespace boost { +namespace locale { +namespace gnu_gettext { +namespace lambda { + +namespace { // anon + struct identity : public plural { + virtual int operator()(int n) const + { + return n; + }; + virtual identity *clone() const + { + return new identity(); + } + }; + + struct unary : public plural + { + unary(plural_ptr ptr) : + op1(ptr) + { + } + protected: + plural_ptr op1; + }; + + + struct binary : public plural + { + binary(plural_ptr p1,plural_ptr p2) : + op1(p1), + op2(p2) + { + } + protected: + plural_ptr op1,op2; + }; + + struct number : public plural + { + number(int v) : + val(v) + { + } + virtual int operator()(int /*n*/) const + { + return val; + } + virtual number *clone() const + { + return new number(val); + } + + private: + int val; + }; + + #define UNOP(name,oper) \ + struct name: public unary { \ + name(plural_ptr op) : unary(op) \ + { \ + }; \ + virtual int operator()(int n) const \ + { \ + return oper (*op1)(n); \ + } \ + virtual name *clone() const \ + { \ + plural_ptr op1_copy(op1->clone()); \ + return new name(op1_copy); \ + } \ + }; + + #define BINOP(name,oper) \ + struct name : public binary \ + { \ + name(plural_ptr p1,plural_ptr p2) : \ + binary(p1,p2) \ + { \ + } \ + \ + virtual int operator()(int n) const \ + { \ + return (*op1)(n) oper (*op2)(n); \ + } \ + virtual name *clone() const \ + { \ + plural_ptr op1_copy(op1->clone()); \ + plural_ptr op2_copy(op2->clone()); \ + return new name(op1_copy,op2_copy); \ + } \ + }; + + #define BINOPD(name,oper) \ + struct name : public binary { \ + name(plural_ptr p1,plural_ptr p2) : \ + binary(p1,p2) \ + { \ + } \ + virtual int operator()(int n) const \ + { \ + int v1=(*op1)(n); \ + int v2=(*op2)(n); \ + return v2==0 ? 0 : v1 oper v2; \ + } \ + virtual name *clone() const \ + { \ + plural_ptr op1_copy(op1->clone()); \ + plural_ptr op2_copy(op2->clone()); \ + return new name(op1_copy,op2_copy); \ + } \ + }; + + enum { END = 0 , SHL = 256, SHR, GTE,LTE, EQ, NEQ, AND, OR, NUM, VARIABLE }; + + UNOP(l_not,!) + UNOP(minus,-) + UNOP(bin_not,~) + + BINOP(mul,*) + BINOPD(div,/) + BINOPD(mod,%) + static int level10[]={3,'*','/','%'}; + + BINOP(add,+) + BINOP(sub,-) + static int level9[]={2,'+','-'}; + + BINOP(shl,<<) + BINOP(shr,>>) + static int level8[]={2,SHL,SHR}; + + BINOP(gt,>) + BINOP(lt,<) + BINOP(gte,>=) + BINOP(lte,<=) + static int level7[]={4,'<','>',GTE,LTE}; + + BINOP(eq,==) + BINOP(neq,!=) + static int level6[]={2,EQ,NEQ}; + + BINOP(bin_and,&) + static int level5[]={1,'&'}; + + BINOP(bin_xor,^) + static int level4[]={1,'^'}; + + BINOP(bin_or,|) + static int level3[]={1,'|'}; + + BINOP(l_and,&&) + static int level2[]={1,AND}; + + BINOP(l_or,||) + static int level1[]={1,OR}; + + struct conditional : public plural { + conditional(plural_ptr p1,plural_ptr p2,plural_ptr p3) : + op1(p1), + op2(p2), + op3(p3) + { + } + virtual int operator()(int n) const + { + return (*op1)(n) ? (*op2)(n) : (*op3)(n); + } + virtual conditional *clone() const + { + plural_ptr op1_copy(op1->clone()); + plural_ptr op2_copy(op2->clone()); + plural_ptr op3_copy(op3->clone()); + return new conditional(op1_copy,op2_copy,op3_copy); + } + private: + plural_ptr op1,op2,op3; + }; + + + plural_ptr bin_factory(int value,plural_ptr left,plural_ptr right) + { + + switch(value) { + case '/': return plural_ptr(new div(left,right)); + case '*': return plural_ptr(new mul(left,right)); + case '%': return plural_ptr(new mod(left,right)); + case '+': return plural_ptr(new add(left,right)); + case '-': return plural_ptr(new sub(left,right)); + case SHL: return plural_ptr(new shl(left,right)); + case SHR: return plural_ptr(new shr(left,right)); + case '>': return plural_ptr(new gt(left,right)); + case '<': return plural_ptr(new lt(left,right)); + case GTE: return plural_ptr(new gte(left,right)); + case LTE: return plural_ptr(new lte(left,right)); + case EQ: return plural_ptr(new eq(left,right)); + case NEQ: return plural_ptr(new neq(left,right)); + case '&': return plural_ptr(new bin_and(left,right)); + case '^': return plural_ptr(new bin_xor(left,right)); + case '|': return plural_ptr(new bin_or (left,right)); + case AND: return plural_ptr(new l_and(left,right)); + case OR: return plural_ptr(new l_or(left,right)); + default: + return plural_ptr(); + } + } + + static inline bool is_in(int v,int *p) + { + int len=*p; + p++; + while(len && *p!=v) { p++;len--; } + return len!=0; + } + + + class tokenizer { + public: + tokenizer(char const *s) { text=s; pos=0; step(); }; + int get(int *val=NULL){ + int iv=int_value; + int res=next_tocken; + step(); + if(val && res==NUM){ + *val=iv; + } + return res; + }; + int next(int *val=NULL) { + if(val && next_tocken==NUM) { + *val=int_value; + return NUM; + } + return next_tocken; + } + private: + char const *text; + int pos; + int next_tocken; + int int_value; + bool is_blank(char c) + { + return c==' ' || c=='\r' || c=='\n' || c=='\t'; + } + bool isdigit(char c) + { + return '0'<=c && c<='9'; + } + void step() + { + while(text[pos] && is_blank(text[pos])) pos++; + char const *ptr=text+pos; + char *tmp_ptr; + if(strncmp(ptr,"<<",2)==0) { pos+=2; next_tocken=SHL; } + else if(strncmp(ptr,">>",2)==0) { pos+=2; next_tocken=SHR; } + else if(strncmp(ptr,"&&",2)==0) { pos+=2; next_tocken=AND; } + else if(strncmp(ptr,"||",2)==0) { pos+=2; next_tocken=OR; } + else if(strncmp(ptr,"<=",2)==0) { pos+=2; next_tocken=LTE; } + else if(strncmp(ptr,">=",2)==0) { pos+=2; next_tocken=GTE; } + else if(strncmp(ptr,"==",2)==0) { pos+=2; next_tocken=EQ; } + else if(strncmp(ptr,"!=",2)==0) { pos+=2; next_tocken=NEQ; } + else if(*ptr=='n') { pos++; next_tocken=VARIABLE; } + else if(isdigit(*ptr)) { int_value=strtol(text+pos,&tmp_ptr,0); pos=tmp_ptr-text; next_tocken=NUM; } + else if(*ptr=='\0') { next_tocken=0; } + else { next_tocken=*ptr; pos++; } + } + }; + + + #define BINARY_EXPR(expr,hexpr,list) \ + plural_ptr expr() \ + { \ + plural_ptr op1,op2; \ + if((op1=hexpr()).get()==0) \ + return plural_ptr(); \ + while(is_in(t.next(),list)) { \ + int o=t.get(); \ + if((op2=hexpr()).get()==0) \ + return plural_ptr(); \ + op1=bin_factory(o,op1,op2); \ + } \ + return op1; \ + } + + class parser { + public: + + parser(tokenizer &tin) : t(tin) {}; + + plural_ptr compile() + { + plural_ptr res=cond_expr(); + if(res.get() && t.next()!=END) { + return plural_ptr(); + }; + return res; + } + + private: + + plural_ptr value_expr() + { + plural_ptr op; + if(t.next()=='(') { + t.get(); + if((op=cond_expr()).get()==0) + return plural_ptr(); + if(t.get()!=')') + return plural_ptr(); + return op; + } + else if(t.next()==NUM) { + int value; + t.get(&value); + return plural_ptr(new number(value)); + } + else if(t.next()==VARIABLE) { + t.get(); + return plural_ptr(new identity()); + } + return plural_ptr(); + }; + + plural_ptr un_expr() + { + plural_ptr op1; + static int level_unary[]={3,'-','!','~'}; + if(is_in(t.next(),level_unary)) { + int op=t.get(); + if((op1=un_expr()).get()==0) + return plural_ptr(); + switch(op) { + case '-': + return plural_ptr(new minus(op1)); + case '!': + return plural_ptr(new l_not(op1)); + case '~': + return plural_ptr(new bin_not(op1)); + default: + return plural_ptr(); + } + } + else { + return value_expr(); + } + }; + + BINARY_EXPR(l10,un_expr,level10); + BINARY_EXPR(l9,l10,level9); + BINARY_EXPR(l8,l9,level8); + BINARY_EXPR(l7,l8,level7); + BINARY_EXPR(l6,l7,level6); + BINARY_EXPR(l5,l6,level5); + BINARY_EXPR(l4,l5,level4); + BINARY_EXPR(l3,l4,level3); + BINARY_EXPR(l2,l3,level2); + BINARY_EXPR(l1,l2,level1); + + plural_ptr cond_expr() + { + plural_ptr cond,case1,case2; + if((cond=l1()).get()==0) + return plural_ptr(); + if(t.next()=='?') { + t.get(); + if((case1=cond_expr()).get()==0) + return plural_ptr(); + if(t.get()!=':') + return plural_ptr(); + if((case2=cond_expr()).get()==0) + return plural_ptr(); + } + else { + return cond; + } + return plural_ptr(new conditional(cond,case1,case2)); + } + + tokenizer &t; + + }; + +} // namespace anon + +plural_ptr compile(char const *str) +{ + tokenizer t(str); + parser p(t); + return p.compile(); +} + + +} // lambda +} // gnu_gettext +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/shared/mo_lambda.hpp b/src/boost/libs/locale/src/shared/mo_lambda.hpp new file mode 100644 index 000000000..c14afd077 --- /dev/null +++ b/src/boost/libs/locale/src/shared/mo_lambda.hpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_SRC_LOCALE_MO_LAMBDA_HPP_INCLUDED +#define BOOST_SRC_LOCALE_MO_LAMBDA_HPP_INCLUDED + +#include <boost/shared_ptr.hpp> + +namespace boost { + namespace locale { + namespace gnu_gettext { + namespace lambda { + + struct plural { + + virtual int operator()(int n) const = 0; + virtual plural *clone() const = 0; + virtual ~plural() + { + } + }; + + typedef boost::shared_ptr<plural> plural_ptr; + + plural_ptr compile(char const *c_expression); + + } // lambda + } // gnu_gettext + } // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/std/all_generator.hpp b/src/boost/libs/locale/src/std/all_generator.hpp new file mode 100644 index 000000000..d79525b71 --- /dev/null +++ b/src/boost/libs/locale/src/std/all_generator.hpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_STD_ALL_GENERATOR_HPP +#define BOOST_LOCALE_IMPL_STD_ALL_GENERATOR_HPP + +#include <boost/locale/generator.hpp> +#include <vector> + +namespace boost { + namespace locale { + namespace impl_std { + typedef enum { + utf8_none, + utf8_native, + utf8_native_with_wide, + utf8_from_wide + } utf8_support; + + std::locale create_convert( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf = utf8_none); + + std::locale create_collate( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf = utf8_none); + + std::locale create_formatting( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf = utf8_none); + + std::locale create_parsing( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf = utf8_none); + + std::locale create_codecvt( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf = utf8_none); + + } + } +} + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/codecvt.cpp b/src/boost/libs/locale/src/std/codecvt.cpp new file mode 100644 index 000000000..9b62d2f4f --- /dev/null +++ b/src/boost/libs/locale/src/std/codecvt.cpp @@ -0,0 +1,55 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <boost/cstdint.hpp> +#include <boost/locale/util.hpp> +#include "all_generator.hpp" +#include <vector> +namespace boost { +namespace locale { +namespace impl_std { + template<typename CharType> + std::locale codecvt_bychar( std::locale const &in, + std::string const &locale_name) + { + return std::locale(in,new std::codecvt_byname<CharType,char,std::mbstate_t>(locale_name.c_str())); + } + + + std::locale create_codecvt( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf) + { + if(utf == utf8_from_wide) { + return util::create_utf8_codecvt(in,type); + } + switch(type) { + case char_facet: + return codecvt_bychar<char>(in,locale_name); + case wchar_t_facet: + return codecvt_bychar<wchar_t>(in,locale_name); + #if defined(BOOST_LOCALE_ENABLE_CHAR16_T) && !defined(BOOST_NO_CHAR16_T_CODECVT) + case char16_t_facet: + return codecvt_bychar<char16_t>(in,locale_name); + #endif + #if defined(BOOST_LOCALE_ENABLE_CHAR32_T) && !defined(BOOST_NO_CHAR32_T_CODECVT) + case char32_t_facet: + return codecvt_bychar<char32_t>(in,locale_name); + #endif + default: + return in; + } + } + +} // impl_std +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/collate.cpp b/src/boost/libs/locale/src/std/collate.cpp new file mode 100644 index 000000000..8b7127ad7 --- /dev/null +++ b/src/boost/libs/locale/src/std/collate.cpp @@ -0,0 +1,113 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/encoding.hpp> +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_std { + +class utf8_collator_from_wide : public std::collate<char> { +public: + typedef std::collate<wchar_t> wfacet; + utf8_collator_from_wide(std::locale const &base,size_t refs = 0) : + std::collate<char>(refs), + base_(base) + { + } + virtual int do_compare(char const *lb,char const *le,char const *rb,char const *re) const + { + std::wstring l=conv::to_utf<wchar_t>(lb,le,"UTF-8"); + std::wstring r=conv::to_utf<wchar_t>(rb,re,"UTF-8"); + return std::use_facet<wfacet>(base_).compare( l.c_str(),l.c_str()+l.size(), + r.c_str(),r.c_str()+r.size()); + } + virtual long do_hash(char const *b,char const *e) const + { + std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8"); + return std::use_facet<wfacet>(base_).hash(tmp.c_str(),tmp.c_str()+tmp.size()); + } + virtual std::string do_transform(char const *b,char const *e) const + { + std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8"); + std::wstring wkey = + std::use_facet<wfacet>(base_).transform(tmp.c_str(),tmp.c_str()+tmp.size()); + std::string key; + if(sizeof(wchar_t)==2) + key.reserve(wkey.size()*2); + else + key.reserve(wkey.size()*3); + for(unsigned i=0;i<wkey.size();i++) { + if(sizeof(wchar_t)==2) { + uint16_t tv = static_cast<uint16_t>(wkey[i]); + key += char(tv >> 8); + key += char(tv & 0xFF); + } + else { // 4 + uint32_t tv = static_cast<uint32_t>(wkey[i]); + // 21 bit + key += char((tv >> 16) & 0xFF); + key += char((tv >> 8) & 0xFF); + key += char(tv & 0xFF); + } + } + return key; + } +private: + std::locale base_; +}; + +std::locale create_collate( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf) +{ + switch(type) { + case char_facet: + { + if(utf == utf8_from_wide) { + std::locale base= + std::locale(std::locale::classic(), + new std::collate_byname<wchar_t>(locale_name.c_str())); + return std::locale(in,new utf8_collator_from_wide(base)); + } + else + { + return std::locale(in,new std::collate_byname<char>(locale_name.c_str())); + } + } + + case wchar_t_facet: + return std::locale(in,new std::collate_byname<wchar_t>(locale_name.c_str())); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(in,new std::collate_byname<char16_t>(locale_name.c_str())); + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(in,new std::collate_byname<char32_t>(locale_name.c_str())); + #endif + default: + return in; + } +} + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/converter.cpp b/src/boost/libs/locale/src/std/converter.cpp new file mode 100644 index 000000000..e4f925ade --- /dev/null +++ b/src/boost/libs/locale/src/std/converter.cpp @@ -0,0 +1,148 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE + +#include <boost/config.hpp> +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif + +#include <locale> +#include <stdexcept> +#include <boost/locale/generator.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/encoding.hpp> +#include <vector> + + + +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_std { + + +template<typename CharType> +class std_converter : public converter<CharType> +{ +public: + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + typedef std::ctype<char_type> ctype_type; + std_converter(std::locale const &base,size_t refs = 0) : + converter<CharType>(refs), + base_(base) + { + } + virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int /*flags*/ = 0) const + { + switch(how) { + case converter_base::upper_case: + case converter_base::lower_case: + case converter_base::case_folding: + { + ctype_type const &ct=std::use_facet<ctype_type>(base_); + size_t len = end - begin; + std::vector<char_type> res(len+1,0); + char_type *lbegin = &res[0]; + std::copy(begin,end,lbegin); + if(how == converter_base::upper_case) + ct.toupper(lbegin,lbegin+len); + else + ct.tolower(lbegin,lbegin+len); + return string_type(lbegin,len); + } + default: + return string_type(begin,end-begin); + } + } +private: + std::locale base_; +}; + +class utf8_converter : public converter<char> { +public: + typedef std::ctype<char> ctype_type; + typedef std::ctype<wchar_t> wctype_type; + utf8_converter(std::locale const &base,size_t refs = 0) : + converter<char>(refs), + base_(base) + { + } + virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int /*flags*/ = 0) const + { + switch(how) { + case upper_case: + case lower_case: + case case_folding: + { + std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8"); + wctype_type const &ct=std::use_facet<wctype_type>(base_); + size_t len = tmp.size(); + std::vector<wchar_t> res(len+1,0); + wchar_t *lbegin = &res[0]; + std::copy(tmp.c_str(),tmp.c_str()+len,lbegin); + if(how == upper_case) + ct.toupper(lbegin,lbegin+len); + else + ct.tolower(lbegin,lbegin+len); + return conv::from_utf<wchar_t>(lbegin,lbegin+len,"UTF-8"); + } + default: + return std::string(begin,end-begin); + } + } +private: + std::locale base_; +}; + +std::locale create_convert( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf) +{ + switch(type) { + case char_facet: + { + if(utf == utf8_native_with_wide || utf == utf8_from_wide) { + std::locale base(std::locale::classic(),new std::ctype_byname<wchar_t>(locale_name.c_str())); + return std::locale(in,new utf8_converter(base)); + } + std::locale base(std::locale::classic(),new std::ctype_byname<char>(locale_name.c_str())); + return std::locale(in,new std_converter<char>(base)); + } + case wchar_t_facet: + { + std::locale base(std::locale::classic(),new std::ctype_byname<wchar_t>(locale_name.c_str())); + return std::locale(in,new std_converter<wchar_t>(base)); + } + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + { + std::locale base(std::locale::classic(),new std::ctype_byname<char16_t>(locale_name.c_str())); + return std::locale(in,new std_converter<char16_t>(base)); + } + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + { + std::locale base(std::locale::classic(),new std::ctype_byname<char32_t>(locale_name.c_str())); + return std::locale(in,new std_converter<char32_t>(base)); + } + #endif + default: + return in; + } +} + + +} // namespace impl_std +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/numeric.cpp b/src/boost/libs/locale/src/std/numeric.cpp new file mode 100644 index 000000000..cbb0d9de3 --- /dev/null +++ b/src/boost/libs/locale/src/std/numeric.cpp @@ -0,0 +1,456 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/formatting.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <sstream> +#include <stdlib.h> + +#include "../util/numeric.hpp" +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_std { + +template<typename CharType> +class time_put_from_base : public std::time_put<CharType> { +public: + time_put_from_base(std::locale const &base, size_t refs = 0) : + std::time_put<CharType>(refs), + base_(base) + { + } + typedef typename std::time_put<CharType>::iter_type iter_type; + + virtual iter_type do_put(iter_type out,std::ios_base &/*ios*/,CharType fill,std::tm const *tm,char format,char modifier) const + { + std::basic_stringstream<CharType> ss; + ss.imbue(base_); + return std::use_facet<std::time_put<CharType> >(base_).put(out,ss,fill,tm,format,modifier); + } +private: + std::locale base_; +}; + +class utf8_time_put_from_wide : public std::time_put<char> { +public: + utf8_time_put_from_wide(std::locale const &base, size_t refs = 0) : + std::time_put<char>(refs), + base_(base) + { + } + virtual iter_type do_put(iter_type out,std::ios_base &/*ios*/,char fill,std::tm const *tm,char format,char modifier = 0) const + { + std::basic_ostringstream<wchar_t> wtmps; + wtmps.imbue(base_); + std::use_facet<std::time_put<wchar_t> >(base_).put(wtmps,wtmps,wchar_t(fill),tm,wchar_t(format),wchar_t(modifier)); + std::wstring wtmp=wtmps.str(); + std::string const tmp = conv::from_utf<wchar_t>(wtmp,"UTF-8"); + for(unsigned i=0;i<tmp.size();i++) { + *out++ = tmp[i]; + } + return out; + } +private: + std::locale base_; +}; + +class utf8_numpunct_from_wide : public std::numpunct<char> { +public: + utf8_numpunct_from_wide(std::locale const &base,size_t refs = 0) : std::numpunct<char>(refs) + { + typedef std::numpunct<wchar_t> wfacet_type; + wfacet_type const &wfacet = std::use_facet<wfacet_type>(base); + + truename_ = conv::from_utf<wchar_t>(wfacet.truename(),"UTF-8"); + falsename_ = conv::from_utf<wchar_t>(wfacet.falsename(),"UTF-8"); + + wchar_t tmp_decimal_point = wfacet.decimal_point(); + wchar_t tmp_thousands_sep = wfacet.thousands_sep(); + std::string tmp_grouping = wfacet.grouping(); + + if( 32 <= tmp_thousands_sep && tmp_thousands_sep <=126 && + 32 <= tmp_decimal_point && tmp_decimal_point <=126) + { + thousands_sep_ = static_cast<char>(tmp_thousands_sep); + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } + else if(32 <= tmp_decimal_point && tmp_decimal_point <=126 && tmp_thousands_sep == 0xA0) { + // workaround common bug - substitute NBSP with ordinary space + thousands_sep_ = ' '; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } + else if(32 <= tmp_decimal_point && tmp_decimal_point <=126) + { + thousands_sep_=','; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_=std::string(); + } + else { + thousands_sep_ = ','; + decimal_point_ = '.'; + grouping_=std::string(); + } + } + + virtual char do_decimal_point() const + { + return decimal_point_; + } + virtual char do_thousands_sep() const + { + return thousands_sep_; + } + virtual std::string do_grouping() const + { + return grouping_; + } + virtual std::string do_truename() const + { + return truename_; + } + virtual std::string do_falsename() const + { + return falsename_; + } +private: + std::string truename_; + std::string falsename_; + char thousands_sep_; + char decimal_point_; + std::string grouping_; + +}; + +template<bool Intl> +class utf8_moneypunct_from_wide : public std::moneypunct<char,Intl> { +public: + utf8_moneypunct_from_wide(std::locale const &base,size_t refs = 0) : std::moneypunct<char,Intl>(refs) + { + typedef std::moneypunct<wchar_t,Intl> wfacet_type; + wfacet_type const &wfacet = std::use_facet<wfacet_type>(base); + + curr_symbol_ = conv::from_utf<wchar_t>(wfacet.curr_symbol(),"UTF-8"); + positive_sign_ = conv::from_utf<wchar_t>(wfacet.positive_sign(),"UTF-8"); + negative_sign_ = conv::from_utf<wchar_t>(wfacet.negative_sign(),"UTF-8"); + frac_digits_ = wfacet.frac_digits(); + pos_format_ = wfacet.pos_format(); + neg_format_ = wfacet.neg_format(); + + wchar_t tmp_decimal_point = wfacet.decimal_point(); + wchar_t tmp_thousands_sep = wfacet.thousands_sep(); + std::string tmp_grouping = wfacet.grouping(); + if( 32 <= tmp_thousands_sep && tmp_thousands_sep <=126 && + 32 <= tmp_decimal_point && tmp_decimal_point <=126) + { + thousands_sep_ = static_cast<char>(tmp_thousands_sep); + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } + else if(32 <= tmp_decimal_point && tmp_decimal_point <=126 && tmp_thousands_sep == 0xA0) { + // workaround common bug - substitute NBSP with ordinary space + thousands_sep_ = ' '; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } + else if(32 <= tmp_decimal_point && tmp_decimal_point <=126) + { + thousands_sep_=','; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_=std::string(); + } + else { + thousands_sep_ = ','; + decimal_point_ = '.'; + grouping_=std::string(); + } + } + + virtual char do_decimal_point() const + { + return decimal_point_; + } + + virtual char do_thousands_sep() const + { + return thousands_sep_; + } + + virtual std::string do_grouping() const + { + return grouping_; + } + + virtual std::string do_curr_symbol() const + { + return curr_symbol_; + } + virtual std::string do_positive_sign () const + { + return positive_sign_; + } + virtual std::string do_negative_sign() const + { + return negative_sign_; + } + + virtual int do_frac_digits() const + { + return frac_digits_; + } + + virtual std::money_base::pattern do_pos_format() const + { + return pos_format_; + } + + virtual std::money_base::pattern do_neg_format() const + { + return neg_format_; + } + +private: + char thousands_sep_; + char decimal_point_; + std::string grouping_; + std::string curr_symbol_; + std::string positive_sign_; + std::string negative_sign_; + int frac_digits_; + std::money_base::pattern pos_format_,neg_format_; + +}; + +class utf8_numpunct : public std::numpunct_byname<char> { +public: + typedef std::numpunct_byname<char> base_type; + utf8_numpunct(char const *name,size_t refs = 0) : + std::numpunct_byname<char>(name,refs) + { + } + virtual char do_thousands_sep() const + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127) + if(bs == 0xA0) + return ' '; + else + return 0; + else + return bs; + } + virtual std::string do_grouping() const + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127 && bs != 0xA0) + return std::string(); + return base_type::do_grouping(); + } +}; + +template<bool Intl> +class utf8_moneypunct : public std::moneypunct_byname<char,Intl> { +public: + typedef std::moneypunct_byname<char,Intl> base_type; + utf8_moneypunct(char const *name,size_t refs = 0) : + std::moneypunct_byname<char,Intl>(name,refs) + { + } + virtual char do_thousands_sep() const + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127) + if(bs == 0xA0) + return ' '; + else + return 0; + else + return bs; + } + virtual std::string do_grouping() const + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127 && bs != 0xA0) + return std::string(); + return base_type::do_grouping(); + } +}; + + +template<typename CharType> +std::locale create_basic_parsing(std::locale const &in,std::string const &locale_name) +{ + std::locale tmp = std::locale(in,new std::numpunct_byname<CharType>(locale_name.c_str())); + tmp = std::locale(tmp,new std::moneypunct_byname<CharType,true>(locale_name.c_str())); + tmp = std::locale(tmp,new std::moneypunct_byname<CharType,false>(locale_name.c_str())); + tmp = std::locale(tmp,new std::ctype_byname<CharType>(locale_name.c_str())); + return tmp; +} + +template<typename CharType> +std::locale create_basic_formatting(std::locale const &in,std::string const &locale_name) +{ + std::locale tmp = create_basic_parsing<CharType>(in,locale_name); + std::locale base(locale_name.c_str()); + tmp = std::locale(tmp,new time_put_from_base<CharType>(base)); + return tmp; +} + + +std::locale create_formatting( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf) +{ + switch(type) { + case char_facet: + { + if(utf == utf8_from_wide ) { + std::locale base = std::locale(locale_name.c_str()); + + std::locale tmp = std::locale(in,new utf8_time_put_from_wide(base)); + tmp = std::locale(tmp,new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp,new util::base_num_format<char>()); + } + else if(utf == utf8_native) { + std::locale base = std::locale(locale_name.c_str()); + + std::locale tmp = std::locale(in,new time_put_from_base<char>(base)); + tmp = std::locale(tmp,new utf8_numpunct(locale_name.c_str())); + tmp = std::locale(tmp,new utf8_moneypunct<true>(locale_name.c_str())); + tmp = std::locale(tmp,new utf8_moneypunct<false>(locale_name.c_str())); + return std::locale(tmp,new util::base_num_format<char>()); + } + else if(utf == utf8_native_with_wide) { + std::locale base = std::locale(locale_name.c_str()); + + std::locale tmp = std::locale(in,new time_put_from_base<char>(base)); + tmp = std::locale(tmp,new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp,new util::base_num_format<char>()); + } + else + { + std::locale tmp = create_basic_formatting<char>(in,locale_name); + tmp = std::locale(tmp,new util::base_num_format<char>()); + return tmp; + } + } + case wchar_t_facet: + { + std::locale tmp = create_basic_formatting<wchar_t>(in,locale_name); + tmp = std::locale(tmp,new util::base_num_format<wchar_t>()); + return tmp; + } + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + { + std::locale tmp = create_basic_formatting<char16_t>(in,locale_name); + tmp = std::locale(tmp,new util::base_num_format<char16_t>()); + return tmp; + } + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + { + std::locale tmp = create_basic_formatting<char32_t>(in,locale_name); + tmp = std::locale(tmp,new util::base_num_format<char32_t>()); + return tmp; + } + #endif + default: + return in; + } +} + +std::locale create_parsing( std::locale const &in, + std::string const &locale_name, + character_facet_type type, + utf8_support utf) +{ + switch(type) { + case char_facet: + { + if(utf == utf8_from_wide ) { + std::locale base = std::locale::classic(); + + base = std::locale(base,new std::numpunct_byname<wchar_t>(locale_name.c_str())); + base = std::locale(base,new std::moneypunct_byname<wchar_t,true>(locale_name.c_str())); + base = std::locale(base,new std::moneypunct_byname<wchar_t,false>(locale_name.c_str())); + + std::locale tmp = std::locale(in,new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp,new util::base_num_parse<char>()); + } + else if(utf == utf8_native) { + std::locale tmp = std::locale(in,new utf8_numpunct(locale_name.c_str())); + tmp = std::locale(tmp,new utf8_moneypunct<true>(locale_name.c_str())); + tmp = std::locale(tmp,new utf8_moneypunct<false>(locale_name.c_str())); + return std::locale(tmp,new util::base_num_parse<char>()); + } + else if(utf == utf8_native_with_wide) { + std::locale base = std::locale(locale_name.c_str()); + + std::locale tmp = std::locale(in,new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp,new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp,new util::base_num_parse<char>()); + } + else + { + std::locale tmp = create_basic_parsing<char>(in,locale_name); + tmp = std::locale(in,new util::base_num_parse<char>()); + return tmp; + } + } + case wchar_t_facet: + { + std::locale tmp = create_basic_parsing<wchar_t>(in,locale_name); + tmp = std::locale(in,new util::base_num_parse<wchar_t>()); + return tmp; + } + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + { + std::locale tmp = create_basic_parsing<char16_t>(in,locale_name); + tmp = std::locale(in,new util::base_num_parse<char16_t>()); + return tmp; + } + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + { + std::locale tmp = create_basic_parsing<char32_t>(in,locale_name); + tmp = std::locale(in,new util::base_num_parse<char32_t>()); + return tmp; + } + #endif + default: + return in; + } +} + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/std_backend.cpp b/src/boost/libs/locale/src/std/std_backend.cpp new file mode 100644 index 000000000..f9afcb417 --- /dev/null +++ b/src/boost/libs/locale/src/std/std_backend.cpp @@ -0,0 +1,234 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include "all_generator.hpp" +#include "../util/locale_data.hpp" +#include "../util/gregorian.hpp" +#include <boost/locale/util.hpp> +#include <algorithm> +#include <iterator> + +#if defined(BOOST_WINDOWS) +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include <windows.h> +# include "../encoding/conv.hpp" +# include "../win32/lcid.hpp" +#endif + +#include "std_backend.hpp" + +namespace boost { +namespace locale { +namespace impl_std { + + class std_localization_backend : public localization_backend { + public: + std_localization_backend() : + invalid_(true), + use_ansi_encoding_(false) + { + } + std_localization_backend(std_localization_backend const &other) : + localization_backend(), + paths_(other.paths_), + domains_(other.domains_), + locale_id_(other.locale_id_), + invalid_(true), + use_ansi_encoding_(other.use_ansi_encoding_) + { + } + virtual std_localization_backend *clone() const + { + return new std_localization_backend(*this); + } + + void set_option(std::string const &name,std::string const &value) + { + invalid_ = true; + if(name=="locale") + locale_id_ = value; + else if(name=="message_path") + paths_.push_back(value); + else if(name=="message_application") + domains_.push_back(value); + else if(name=="use_ansi_encoding") + use_ansi_encoding_ = value == "true"; + + } + void clear_options() + { + invalid_ = true; + use_ansi_encoding_ = false; + locale_id_.clear(); + paths_.clear(); + domains_.clear(); + } + + void prepare_data() + { + if(!invalid_) + return; + invalid_ = false; + std::string lid=locale_id_; + if(lid.empty()) { + bool use_utf8 = ! use_ansi_encoding_; + lid = util::get_system_locale(use_utf8); + } + in_use_id_ = lid; + data_.parse(lid); + name_ = "C"; + utf_mode_ = utf8_none; + + #if defined(BOOST_WINDOWS) + std::pair<std::string,int> wl_inf = to_windows_name(lid); + std::string win_name = wl_inf.first; + int win_codepage = wl_inf.second; + #endif + + if(!data_.utf8) { + if(loadable(lid)) { + name_ = lid; + utf_mode_ = utf8_none; + } + #if defined(BOOST_WINDOWS) + else if(loadable(win_name) + && win_codepage == conv::impl::encoding_to_windows_codepage(data_.encoding.c_str())) + { + name_ = win_name; + utf_mode_ = utf8_none; + } + #endif + } + else { + if(loadable(lid)) { + name_ = lid; + utf_mode_ = utf8_native_with_wide; + } + #if defined(BOOST_WINDOWS) + else if(loadable(win_name)) { + name_ = win_name; + utf_mode_ = utf8_from_wide; + } + #endif + } + } + + #if defined(BOOST_WINDOWS) + std::pair<std::string,int> to_windows_name(std::string const &l) + { + std::pair<std::string,int> res("C",0); + unsigned lcid = impl_win::locale_to_lcid(l); + char win_lang[256] = {0}; + char win_country[256] = {0}; + char win_codepage[10] = {0}; + if(GetLocaleInfoA(lcid,LOCALE_SENGLANGUAGE,win_lang,sizeof(win_lang))==0) + return res; + std::string lc_name = win_lang; + if(GetLocaleInfoA(lcid,LOCALE_SENGCOUNTRY,win_country,sizeof(win_country))!=0) { + lc_name += "_"; + lc_name += win_country; + } + + res.first = lc_name; + + if(GetLocaleInfoA(lcid,LOCALE_IDEFAULTANSICODEPAGE,win_codepage,sizeof(win_codepage))!=0) + res.second = atoi(win_codepage); + return res; + } + #endif + + bool loadable(std::string name) + { + try { + std::locale l(name.c_str()); + return true; + } + catch(std::exception const &/*e*/) { + return false; + } + } + + virtual std::locale install(std::locale const &base, + locale_category_type category, + character_facet_type type = nochar_facet) + { + prepare_data(); + + switch(category) { + case convert_facet: + return create_convert(base,name_,type,utf_mode_); + case collation_facet: + return create_collate(base,name_,type,utf_mode_); + case formatting_facet: + return create_formatting(base,name_,type,utf_mode_); + case parsing_facet: + return create_parsing(base,name_,type,utf_mode_); + case codepage_facet: + return create_codecvt(base,name_,type,utf_mode_); + case calendar_facet: + return util::install_gregorian_calendar(base,data_.country); + case message_facet: + { + gnu_gettext::messages_info minf; + minf.language = data_.language; + minf.country = data_.country; + minf.variant = data_.variant; + minf.encoding = data_.encoding; + std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); + minf.paths = paths_; + switch(type) { + case char_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); + case wchar_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char16_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char16_t>(minf)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char32_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char32_t>(minf)); + #endif + default: + return base; + } + } + case information_facet: + return util::create_info(base,in_use_id_); + default: + return base; + } + } + + private: + + std::vector<std::string> paths_; + std::vector<std::string> domains_; + std::string locale_id_; + + util::locale_data data_; + std::string name_; + std::string in_use_id_; + utf8_support utf_mode_; + bool invalid_; + bool use_ansi_encoding_; + }; + + localization_backend *create_localization_backend() + { + return new std_localization_backend(); + } + +} // impl icu +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/std/std_backend.hpp b/src/boost/libs/locale/src/std/std_backend.hpp new file mode 100644 index 000000000..0caf779c6 --- /dev/null +++ b/src/boost/libs/locale/src/std/std_backend.hpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_STD_LOCALIZATION_BACKEND_HPP +#define BOOST_LOCALE_IMPL_STD_LOCALIZATION_BACKEND_HPP +namespace boost { + namespace locale { + class localization_backend; + namespace impl_std { + localization_backend *create_localization_backend(); + } // impl_std + } // locale +} // boost +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/util/codecvt_converter.cpp b/src/boost/libs/locale/src/util/codecvt_converter.cpp new file mode 100644 index 000000000..1adb6b41d --- /dev/null +++ b/src/boost/libs/locale/src/util/codecvt_converter.cpp @@ -0,0 +1,458 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/locale/utf8_codecvt.hpp> + +#include "../encoding/conv.hpp" + +#include <boost/locale/util.hpp> + +#ifdef BOOST_MSVC +# pragma warning(disable : 4244 4996) // loose data +#endif + +#include <cstddef> +#include <string.h> +#include <vector> +#include <algorithm> + +//#define DEBUG_CODECVT + +#ifdef DEBUG_CODECVT +#include <iostream> +#endif + +namespace boost { +namespace locale { +namespace util { + + class utf8_converter : public base_converter { + public: + virtual int max_len() const + { + return 4; + } + + virtual utf8_converter *clone() const + { + return new utf8_converter(); + } + + bool is_thread_safe() const + { + return true; + } + + virtual uint32_t to_unicode(char const *&begin,char const *end) + { + char const *p=begin; + + utf::code_point c = utf::utf_traits<char>::decode(p,end); + + if(c==utf::illegal) + return illegal; + + if(c==utf::incomplete) + return incomplete; + + begin = p; + return c; + } + + virtual uint32_t from_unicode(uint32_t u,char *begin,char const *end) + { + if(!utf::is_valid_codepoint(u)) + return illegal; + int width = utf::utf_traits<char>::width(u); + std::ptrdiff_t d=end-begin; + if(d < width) + return incomplete; + utf::utf_traits<char>::encode(u,begin); + return width; + } + }; // utf8_converter + + class simple_converter_impl { + public: + + static const int hash_table_size = 1024; + + simple_converter_impl(std::string const &encoding) + { + for(unsigned i=0;i<128;i++) + to_unicode_tbl_[i]=i; + for(unsigned i=128;i<256;i++) { + char buf[2] = { char(i) , 0 }; + uint32_t uchar=utf::illegal; + try { + std::wstring const tmp = conv::to_utf<wchar_t>(buf,buf+1,encoding,conv::stop); + if(tmp.size() == 1) { + uchar = tmp[0]; + } + else { + uchar = utf::illegal; + } + } + catch(conv::conversion_error const &/*e*/) { + uchar = utf::illegal; + } + to_unicode_tbl_[i]=uchar; + } + for(int i=0;i<hash_table_size;i++) + from_unicode_tbl_[i]=0; + for(unsigned i=1;i<256;i++) { + if(to_unicode_tbl_[i]!=utf::illegal) { + unsigned pos = to_unicode_tbl_[i] % hash_table_size; + while(from_unicode_tbl_[pos]!=0) + pos = (pos + 1) % hash_table_size; + from_unicode_tbl_[pos] = i; + } + } + } + + uint32_t to_unicode(char const *&begin,char const *end) const + { + if(begin==end) + return utf::incomplete; + unsigned char c = *begin++; + return to_unicode_tbl_[c]; + } + uint32_t from_unicode(uint32_t u,char *begin,char const *end) const + { + if(begin==end) + return utf::incomplete; + if(u==0) { + *begin = 0; + return 1; + } + unsigned pos = u % hash_table_size; + unsigned char c; + while((c=from_unicode_tbl_[pos])!=0 && to_unicode_tbl_[c]!=u) + pos = (pos + 1) % hash_table_size; + if(c==0) + return utf::illegal; + *begin = c; + return 1; + } + private: + uint32_t to_unicode_tbl_[256]; + unsigned char from_unicode_tbl_[hash_table_size]; + }; + + class simple_converter : public base_converter { + public: + + virtual ~simple_converter() + { + } + + simple_converter(std::string const &encoding) : + cvt_(encoding) + { + } + + virtual int max_len() const + { + return 1; + } + + virtual bool is_thread_safe() const + { + return true; + } + virtual base_converter *clone() const + { + return new simple_converter(*this); + } + + virtual uint32_t to_unicode(char const *&begin,char const *end) + { + return cvt_.to_unicode(begin,end); + } + virtual uint32_t from_unicode(uint32_t u,char *begin,char const *end) + { + return cvt_.from_unicode(u,begin,end); + } + private: + simple_converter_impl cvt_; + }; + + template<typename CharType> + class simple_codecvt : public generic_codecvt<CharType,simple_codecvt<CharType> > + { + public: + + simple_codecvt(std::string const &encoding,size_t refs = 0) : + generic_codecvt<CharType,simple_codecvt<CharType> >(refs), + cvt_(encoding) + { + } + + struct state_type {}; + static state_type initial_state(generic_codecvt_base::initial_convertion_state /* unused */) + { + return state_type(); + } + static int max_encoding_length() + { + return 1; + } + + utf::code_point to_unicode(state_type &,char const *&begin,char const *end) const + { + return cvt_.to_unicode(begin,end); + } + + utf::code_point from_unicode(state_type &,utf::code_point u,char *begin,char const *end) const + { + return cvt_.from_unicode(u,begin,end); + } + private: + simple_converter_impl cvt_; + + }; + + namespace { + char const *simple_encoding_table[] = { + "cp1250", + "cp1251", + "cp1252", + "cp1253", + "cp1254", + "cp1255", + "cp1256", + "cp1257", + "iso88591", + "iso885913", + "iso885915", + "iso88592", + "iso88593", + "iso88594", + "iso88595", + "iso88596", + "iso88597", + "iso88598", + "iso88599", + "koi8r", + "koi8u", + "usascii", + "windows1250", + "windows1251", + "windows1252", + "windows1253", + "windows1254", + "windows1255", + "windows1256", + "windows1257" + }; + + bool compare_strings(char const *l,char const *r) + { + return strcmp(l,r) < 0; + } + } + + bool check_is_simple_encoding(std::string const &encoding) + { + std::string norm = conv::impl::normalize_encoding(encoding.c_str()); + return std::binary_search<char const **>( simple_encoding_table, + simple_encoding_table + sizeof(simple_encoding_table)/sizeof(char const *), + norm.c_str(), + compare_strings); + return 0; + } + + #if !defined(BOOST_LOCALE_HIDE_AUTO_PTR) && !defined(BOOST_NO_AUTO_PTR) + std::auto_ptr<base_converter> create_utf8_converter() + { + std::auto_ptr<base_converter> res(create_utf8_converter_new_ptr()); + return res; + } + std::auto_ptr<base_converter> create_simple_converter(std::string const &encoding) + { + std::auto_ptr<base_converter> res(create_simple_converter_new_ptr(encoding)); + return res; + } + std::locale create_codecvt(std::locale const &in,std::auto_ptr<base_converter> cvt,character_facet_type type) + { + return create_codecvt_from_pointer(in,cvt.release(),type); + } + #endif + #ifndef BOOST_NO_CXX11_SMART_PTR + std::unique_ptr<base_converter> create_utf8_converter_unique_ptr() + { + std::unique_ptr<base_converter> res(create_utf8_converter_new_ptr()); + return res; + } + std::unique_ptr<base_converter> create_simple_converter_unique_ptr(std::string const &encoding) + { + std::unique_ptr<base_converter> res(create_simple_converter_new_ptr(encoding)); + return res; + } + std::locale create_codecvt(std::locale const &in,std::unique_ptr<base_converter> cvt,character_facet_type type) + { + return create_codecvt_from_pointer(in,cvt.release(),type); + } + #endif + + base_converter *create_simple_converter_new_ptr(std::string const &encoding) + { + if(check_is_simple_encoding(encoding)) + return new simple_converter(encoding); + return 0; + } + + base_converter *create_utf8_converter_new_ptr() + { + return new utf8_converter(); + } + + template<typename CharType> + class code_converter : public generic_codecvt<CharType,code_converter<CharType> > + { + public: + #ifndef BOOST_NO_CXX11_SMART_PTR + typedef std::unique_ptr<base_converter> base_converter_ptr; + #define PTR_TRANS(x) std::move((x)) + #else + typedef std::auto_ptr<base_converter> base_converter_ptr; + #define PTR_TRANS(x) (x) + #endif + typedef base_converter_ptr state_type; + + code_converter(base_converter_ptr cvt,size_t refs = 0) : + generic_codecvt<CharType,code_converter<CharType> >(refs), + cvt_(PTR_TRANS(cvt)) + { + max_len_ = cvt_->max_len(); + thread_safe_ = cvt_->is_thread_safe(); + } + + + int max_encoding_length() const + { + return max_len_; + } + + base_converter_ptr initial_state(generic_codecvt_base::initial_convertion_state /* unused */) const + { + base_converter_ptr r; + if(!thread_safe_) + r.reset(cvt_->clone()); + return r; + } + + utf::code_point to_unicode(base_converter_ptr &ptr,char const *&begin,char const *end) const + { + if(thread_safe_) + return cvt_->to_unicode(begin,end); + else + return ptr->to_unicode(begin,end); + } + + utf::code_point from_unicode(base_converter_ptr &ptr,utf::code_point u,char *begin,char const *end) const + { + if(thread_safe_) + return cvt_->from_unicode(u,begin,end); + else + return ptr->from_unicode(u,begin,end); + } + + private: + base_converter_ptr cvt_; + int max_len_; + bool thread_safe_; + }; + + + std::locale create_codecvt_from_pointer(std::locale const &in,base_converter *pcvt,character_facet_type type) + { + code_converter<char>::base_converter_ptr cvt(pcvt); + if(!cvt.get()) + cvt.reset(new base_converter()); + switch(type) { + case char_facet: + return std::locale(in,new code_converter<char>(PTR_TRANS(cvt))); + case wchar_t_facet: + return std::locale(in,new code_converter<wchar_t>(PTR_TRANS(cvt))); + #if defined(BOOST_LOCALE_ENABLE_CHAR16_T) && !defined(BOOST_NO_CHAR16_T_CODECVT) + case char16_t_facet: + return std::locale(in,new code_converter<char16_t>(PTR_TRANS(cvt))); + #endif + #if defined(BOOST_LOCALE_ENABLE_CHAR32_T) && !defined(BOOST_NO_CHAR32_T_CODECVT) + case char32_t_facet: + return std::locale(in,new code_converter<char32_t>(PTR_TRANS(cvt))); + #endif + default: + return in; + } + } + + + /// + /// Install utf8 codecvt to UTF-16 or UTF-32 into locale \a in and return + /// new locale that is based on \a in and uses new facet. + /// + std::locale create_utf8_codecvt(std::locale const &in,character_facet_type type) + { + switch(type) { + case char_facet: + return std::locale(in,new utf8_codecvt<char>()); + case wchar_t_facet: + return std::locale(in,new utf8_codecvt<wchar_t>()); + #if defined(BOOST_LOCALE_ENABLE_CHAR16_T) && !defined(BOOST_NO_CHAR16_T_CODECVT) + case char16_t_facet: + return std::locale(in,new utf8_codecvt<char16_t>()); + #endif + #if defined(BOOST_LOCALE_ENABLE_CHAR32_T) && !defined(BOOST_NO_CHAR32_T_CODECVT) + case char32_t_facet: + return std::locale(in,new utf8_codecvt<char32_t>()); + #endif + default: + return in; + } + } + + /// + /// This function installs codecvt that can be used for conversion between single byte + /// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points, + /// + /// Throws invalid_charset_error if the chacater set is not supported or isn't single byte character + /// set + std::locale create_simple_codecvt(std::locale const &in,std::string const &encoding,character_facet_type type) + { + if(!check_is_simple_encoding(encoding)) + throw boost::locale::conv::invalid_charset_error("Invalid simple encoding " + encoding); + + switch(type) { + case char_facet: + return std::locale(in,new simple_codecvt<char>(encoding)); + case wchar_t_facet: + return std::locale(in,new simple_codecvt<wchar_t>(encoding)); + #if defined(BOOST_LOCALE_ENABLE_CHAR16_T) && !defined(BOOST_NO_CHAR16_T_CODECVT) + case char16_t_facet: + return std::locale(in,new simple_codecvt<char16_t>(encoding)); + #endif + #if defined(BOOST_LOCALE_ENABLE_CHAR32_T) && !defined(BOOST_NO_CHAR32_T_CODECVT) + case char32_t_facet: + return std::locale(in,new simple_codecvt<char32_t>(encoding)); + #endif + default: + return in; + } + } + + + +} // util +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/default_locale.cpp b/src/boost/libs/locale/src/util/default_locale.cpp new file mode 100644 index 000000000..b0aab03c7 --- /dev/null +++ b/src/boost/libs/locale/src/util/default_locale.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#define BOOST_LOCALE_SOURCE +#include <boost/locale/util.hpp> +#include <boost/config.hpp> +#include <stdlib.h> + +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include <windows.h> +#define BOOST_LOCALE_USE_WIN32_API +#endif + +namespace boost { + namespace locale { + namespace util { + std::string get_system_locale(bool use_utf8) + { + char const *lang = 0; + if(!lang || !*lang) + lang = getenv("LC_CTYPE"); + if(!lang || !*lang) + lang = getenv("LC_ALL"); + if(!lang || !*lang) + lang = getenv("LANG"); + #ifndef BOOST_LOCALE_USE_WIN32_API + (void)use_utf8; // not relevant for non-windows + if(!lang || !*lang) + lang = "C"; + return lang; + #else + if(lang && *lang) { + return lang; + } + char buf[10]; + if(GetLocaleInfoA(LOCALE_USER_DEFAULT,LOCALE_SISO639LANGNAME,buf,sizeof(buf))==0) + return "C"; + std::string lc_name = buf; + if(GetLocaleInfoA(LOCALE_USER_DEFAULT,LOCALE_SISO3166CTRYNAME,buf,sizeof(buf))!=0) { + lc_name += "_"; + lc_name += buf; + } + if(!use_utf8) { + if(GetLocaleInfoA(LOCALE_USER_DEFAULT,LOCALE_IDEFAULTANSICODEPAGE,buf,sizeof(buf))!=0) { + if(atoi(buf)==0) + lc_name+=".UTF-8"; + else { + lc_name +=".windows-"; + lc_name +=buf; + } + } + else { + lc_name += "UTF-8"; + } + } + else { + lc_name += ".UTF-8"; + } + return lc_name; + + #endif + } + } // impl + } // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/util/gregorian.cpp b/src/boost/libs/locale/src/util/gregorian.cpp new file mode 100644 index 000000000..49e45c3a5 --- /dev/null +++ b/src/boost/libs/locale/src/util/gregorian.cpp @@ -0,0 +1,852 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/config.hpp> +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/date_time_facet.hpp> +#include <boost/locale/date_time.hpp> +#include <boost/locale/hold_ptr.hpp> +#include <stdlib.h> +#include <ctime> +#include <memory> +#include <algorithm> +#include <limits> + +#include "timezone.hpp" +#include "gregorian.hpp" + +namespace boost { +namespace locale { +namespace util { + namespace { + + int is_leap(int year) + { + if(year % 400 == 0) + return 1; + if(year % 100 == 0) + return 0; + if(year % 4 == 0) + return 1; + return 0; + } + + int days_in_month(int year,int month) + { + static const int tbl[2][12] = { + { 31,28,31,30,31,30,31,31,30,31,30,31 }, + { 31,29,31,30,31,30,31,31,30,31,30,31 } + }; + return tbl[is_leap(year)][month - 1]; + } + + inline int days_from_0(int year) + { + year--; + return 365 * year + (year / 400) - (year/100) + (year / 4); + } + + int days_from_1970(int year) + { + static const int days_from_0_to_1970 = days_from_0(1970); + return days_from_0(year) - days_from_0_to_1970; + } + + int days_from_1jan(int year,int month,int day) + { + static const int days[2][12] = { + { 0,31,59,90,120,151,181,212,243,273,304,334 }, + { 0,31,60,91,121,152,182,213,244,274,305,335 } + }; + return days[is_leap(year)][month-1] + day - 1; + } + + std::time_t internal_timegm(std::tm const *t) + { + int year = t->tm_year + 1900; + int month = t->tm_mon; + if(month > 11) { + year += month/12; + month %= 12; + } + else if(month < 0) { + int years_diff = (-month + 11)/12; + year -= years_diff; + month+=12 * years_diff; + } + month++; + int day = t->tm_mday; + int day_of_year = days_from_1jan(year,month,day); + int days_since_epoch = days_from_1970(year) + day_of_year; + + std::time_t seconds_in_day = 3600 * 24; + std::time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec; + + return result; + } + + } // anon + + + + + namespace { + + // Locale dependent data + + bool comparator(char const *left,char const *right) + { + return strcmp(left,right) < 0; + } + + // + // Ref: CLDR 1.9 common/supplemental/supplementalData.xml + // + // monday - default + // fri - MV + // sat - AE AF BH DJ DZ EG ER ET IQ IR JO KE KW LY MA OM QA SA SD SO SY TN YE + // sun - AR AS AZ BW CA CN FO GE GL GU HK IL IN JM JP KG KR LA MH MN MO MP MT NZ PH PK SG TH TT TW UM US UZ VI ZW + // + + int first_day_of_week(char const *terr) { + static char const * const sat[] = { + "AE","AF","BH","DJ","DZ","EG","ER","ET","IQ","IR", + "JO","KE","KW","LY","MA","OM","QA","SA","SD","SO", + "SY","TN","YE" + }; + static char const * const sunday[] = { + "AR","AS","AZ","BW","CA","CN","FO","GE","GL","GU", + "HK","IL","IN","JM","JP","KG","KR","LA","MH","MN", + "MO","MP","MT","NZ","PH","PK","SG","TH","TT","TW", + "UM","US","UZ","VI","ZW" + }; + if(strcmp(terr,"MV") == 0) + return 5; // fri + if(std::binary_search<char const * const *>(sat,sat+sizeof(sat)/(sizeof(sat[0])),terr,comparator)) + return 6; // sat + if(std::binary_search<char const * const *>(sunday,sunday+sizeof(sunday)/(sizeof(sunday[0])),terr,comparator)) + return 0; // sun + // default + return 1; // mon + } + } + + class gregorian_calendar : public abstract_calendar { + public: + + gregorian_calendar(std::string const &terr) + { + first_day_of_week_ = first_day_of_week(terr.c_str()); + time_ = std::time(0); + is_local_ = true; + tzoff_ = 0; + from_time(time_); + } + + /// + /// Make a polymorphic copy of the calendar + /// + virtual gregorian_calendar *clone() const + { + return new gregorian_calendar(*this); + } + + /// + /// Set specific \a value for period \a p, note not all values are settable. + /// + virtual void set_value(period::marks::period_mark p,int value) + { + using namespace period::marks; + switch(p) { + case era: ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] + return; + case year: ///< Year, it is calendar specific + case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. + tm_updated_.tm_year = value - 1900; + break; + case month: + tm_updated_.tm_mon = value; + break; + case day: + tm_updated_.tm_mday = value; + break; + case hour: ///< 24 clock hour [0..23] + tm_updated_.tm_hour = value; + break; + case hour_12: ///< 12 clock hour [0..11] + tm_updated_.tm_hour = tm_updated_.tm_hour / 12 * 12 + value; + break; + case am_pm: ///< am or pm marker, [0..1] + tm_updated_.tm_hour = 12 * value + tm_updated_.tm_hour % 12; + break; + case minute: ///< minute [0..59] + tm_updated_.tm_min = value; + break; + case second: + tm_updated_.tm_sec = value; + break; + case day_of_year: + normalize(); + tm_updated_.tm_mday += (value - (tm_updated_.tm_yday + 1)); + break; + case day_of_week: ///< Day of week, starting from Sunday, [1..7] + if(value < 1) // make sure it is positive + value += (-value / 7) * 7 + 7; + // convert to local DOW + value = (value - 1 - first_day_of_week_ + 14) % 7 + 1; + // fall throght + case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] + normalize(); + tm_updated_.tm_mday += (value - 1) - (tm_updated_.tm_wday - first_day_of_week_ + 7) % 7; + break; + case day_of_week_in_month: ///< Original number of the day of the week in month. (1st sunday, 2nd sunday etc) + case week_of_year: ///< The week number in the year, 4 is the minimal number of days to be in month + case week_of_month: ///< The week number withing current month + { + normalize(); + int current_week = get_value(p,current); + int diff = 7 * (value - current_week); + tm_updated_.tm_mday += diff; + } + break; + case period::marks::first_day_of_week: ///< For example Sunday in US, Monday in France + default: + return; + } + normalized_ = false; + } + + void normalize() + { + if(!normalized_) { + std::tm val = tm_updated_; + val.tm_isdst = -1; + val.tm_wday = -1; // indecator of error + std::time_t point = -1; + if(is_local_) { + point = std::mktime(&val); + if(point == static_cast<std::time_t>(-1)){ + #ifndef BOOST_WINDOWS + // windows does not handle negative time_t, under other plaforms + // it may be actually valid value in 1969-12-31 23:59:59 + // so we check that a filed was updated - does not happen in case of error + if(val.tm_wday == -1) + #endif + { + throw date_time_error("boost::locale::gregorian_calendar: invalid time"); + } + } + } + else { + point = internal_timegm(&val); + #ifdef BOOST_WINDOWS + // Windows uses TLS, thread safe + std::tm *revert_point = 0; + if(point < 0 || (revert_point = gmtime(&point)) == 0) + throw date_time_error("boost::locale::gregorian_calendar time is out of range"); + val = *revert_point; + #else + if(!gmtime_r(&point,&val)) + throw date_time_error("boost::locale::gregorian_calendar invalid time"); + #endif + + } + + time_ = point - tzoff_; + tm_ = val; + tm_updated_ = val; + normalized_ = true; + } + } + + int get_week_number(int day,int wday) const + { + /// + /// This is the number of days that are considered withing + /// period such that the week belongs there + /// + static const int days_in_full_week = 4; + + + // Alaways use local week start + int current_dow = (wday - first_day_of_week_ + 7) % 7; + // Calculate local week day of Jan 1st. + int first_week_day = (current_dow + 700 - day) % 7; + // adding something big devidable by 7 + + int start_of_period_in_weeks; + if(first_week_day < days_in_full_week) { + start_of_period_in_weeks = - first_week_day; + } + else { + start_of_period_in_weeks = 7 - first_week_day; + } + int week_number_in_days = day - start_of_period_in_weeks; + if(week_number_in_days < 0) + return -1; + return week_number_in_days / 7 + 1; + } + + /// + /// Get specific value for period \a p according to a value_type \a v + /// + virtual int get_value(period::marks::period_mark p,value_type v) const + { + using namespace period::marks; + switch(p) { + case era: + return 1; + case year: + case extended_year: + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + #ifdef BOOST_WINDOWS + return 1970; // Unix epoch windows can't handle negative time_t + #else + if(sizeof(std::time_t) == 4) + return 1901; // minimal year with 32 bit time_t + else + return 1; + #endif + case absolute_maximum: + case least_maximum: + case actual_maximum: + if(sizeof(std::time_t) == 4) + return 2038; // Y2K38 - maximal with 32 bit time_t + else + return std::numeric_limits<int>::max(); + case current: + return tm_.tm_year + 1900; + }; + break; + case month: + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 11; + case current: + return tm_.tm_mon; + }; + break; + case day: + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + return 31; + case least_maximum: + return 28; + case actual_maximum: + return days_in_month(tm_.tm_year + 1900,tm_.tm_mon + 1); + case current: + return tm_.tm_mday; + }; + break; + case day_of_year: ///< The number of day in year, starting from 1 + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + return 366; + case least_maximum: + return 365; + case actual_maximum: + return is_leap(tm_.tm_year + 1900) ? 366 : 365; + case current: + return tm_.tm_yday + 1; + } + break; + case day_of_week: ///< Day of week, starting from Sunday, [1..7] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 7; + case current: + return tm_.tm_wday + 1; + } + break; + case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 7; + case current: + return (tm_.tm_wday - first_day_of_week_ + 7) % 7 + 1; + } + break; + case hour: ///< 24 clock hour [0..23] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 23; + case current: + return tm_.tm_hour; + } + break; + case hour_12: ///< 12 clock hour [0..11] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 11; + case current: + return tm_.tm_hour % 12; + } + break; + case am_pm: ///< am or pm marker, [0..1] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 1; + case current: + return tm_.tm_hour >= 12 ? 1 : 0; + } + break; + case minute: ///< minute [0..59] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 59; + case current: + return tm_.tm_min; + } + break; + case second: ///< second [0..59] + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 0; + case absolute_maximum: + case least_maximum: + case actual_maximum: + return 59; + case current: + return tm_.tm_sec; + } + break; + case period::marks::first_day_of_week: ///< For example Sunday in US, Monday in France + return first_day_of_week_ + 1; + + case week_of_year: ///< The week number in the year + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + return 53; + case least_maximum: + return 52; + case actual_maximum: + { + int year = tm_.tm_year + 1900; + int end_of_year_days = (is_leap(year) ? 366 : 365) - 1; + int dow_of_end_of_year = (end_of_year_days - tm_.tm_yday + tm_.tm_wday) % 7; + return get_week_number(end_of_year_days,dow_of_end_of_year); + } + case current: + { + int val = get_week_number(tm_.tm_yday,tm_.tm_wday); + if(val < 0) + return 53; + return val; + } + } + case week_of_month: ///< The week number withing current month + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + return 5; + case least_maximum: + return 4; + case actual_maximum: + { + int end_of_month_days = days_in_month(tm_.tm_year + 1900,tm_.tm_mon + 1); + int dow_of_end_of_month = (end_of_month_days - tm_.tm_mday + tm_.tm_wday) % 7; + return get_week_number(end_of_month_days,dow_of_end_of_month); + } + case current: + { + int val = get_week_number(tm_.tm_mday,tm_.tm_wday); + if(val < 0) + return 5; + return val; + } + } + + case day_of_week_in_month: ///< Original number of the day of the week in month. + switch(v) { + case absolute_minimum: + case greatest_minimum: + case actual_minimum: + return 1; + case absolute_maximum: + return 5; + case least_maximum: + return 4; + case actual_maximum: + if(tm_.tm_mon == 1 && !is_leap(tm_.tm_year + 1900)) { + // only in february in non leap year is 28 days, the rest + // conver more then 4 weeks + return 4; + } + return 5; + case current: + return (tm_.tm_mday - 1) / 7 + 1; + default: + ; + } + default: + ; + } + return 0; + + } + + /// + /// Set current time point + /// + virtual void set_time(posix_time const &p) + { + from_time(static_cast<std::time_t>(p.seconds)); + } + virtual posix_time get_time() const + { + posix_time pt = { time_, 0}; + return pt; + } + + /// + /// Set option for calendar, for future use + /// + virtual void set_option(calendar_option_type opt,int /*v*/) + { + switch(opt) { + case is_gregorian: + throw date_time_error("is_gregorian is not settable options for calendar"); + case is_dst: + throw date_time_error("is_dst is not settable options for calendar"); + default: + ; + } + } + /// + /// Get option for calendar, currently only check if it is Gregorian calendar + /// + virtual int get_option(calendar_option_type opt) const + { + switch(opt) { + case is_gregorian: + return 1; + case is_dst: + return tm_.tm_isdst == 1; + default: + return 0; + }; + } + + /// + /// Adjust period's \a p value by \a difference items using a update_type \a u. + /// Note: not all values are adjustable + /// + virtual void adjust_value(period::marks::period_mark p,update_type u,int difference) + { + switch(u) { + case move: + { + using namespace period::marks; + switch(p) { + case year: ///< Year, it is calendar specific + case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. + tm_updated_.tm_year +=difference; + break; + case month: + tm_updated_.tm_mon +=difference; + break; + case day: + case day_of_year: + case day_of_week: ///< Day of week, starting from Sunday, [1..7] + case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] + tm_updated_.tm_mday +=difference; + break; + case hour: ///< 24 clock hour [0..23] + case hour_12: ///< 12 clock hour [0..11] + tm_updated_.tm_hour += difference; + break; + case am_pm: ///< am or pm marker, [0..1] + tm_updated_.tm_hour += 12 * difference; + break; + case minute: ///< minute [0..59] + tm_updated_.tm_min += difference; + break; + case second: + tm_updated_.tm_sec += difference; + break; + case week_of_year: ///< The week number in the year + case week_of_month: ///< The week number withing current month + case day_of_week_in_month: ///< Original number of the day of the week in month. + tm_updated_.tm_mday +=difference * 7; + break; + default: + ; // Not all values are adjustable + } + normalized_ = false; + normalize(); + } + break; + case roll: + { // roll + int cur_min = get_value(p,actual_minimum); + int cur_max = get_value(p,actual_maximum); + int max_diff = cur_max - cur_min + 1; + if(max_diff > 0) { + int value = get_value(p,current); + int addon = 0; + if(difference < 0) + addon = ((-difference/max_diff) + 1) * max_diff; + value = (value - cur_min + difference + addon) % max_diff + cur_min; + set_value(p,value); + normalize(); + } + } + default: + ; + } + } + + int get_diff(period::marks::period_mark p,int diff,gregorian_calendar const *other) const + { + if(diff == 0) + return 0; + hold_ptr<gregorian_calendar> self(clone()); + self->adjust_value(p,move,diff); + if(diff > 0){ + if(self->time_ > other->time_) + return diff - 1; + else + return diff; + } + else { + if(self->time_ < other->time_) + return diff + 1; + else + return diff; + } + } + + /// + /// Calculate the difference between this calendar and \a other in \a p units + /// + virtual int difference(abstract_calendar const *other_cal,period::marks::period_mark p) const + { + hold_ptr<gregorian_calendar> keeper; + gregorian_calendar const *other = dynamic_cast<gregorian_calendar const *>(other_cal); + if(!other) { + keeper.reset(clone()); + keeper->set_time(other_cal->get_time()); + other = keeper.get(); + } + + int factor = 1; // for weeks vs days handling + + using namespace period::marks; + switch(p) { + case era: + return 0; + case year: + case extended_year: + { + int diff = other->tm_.tm_year - tm_.tm_year; + return get_diff(period::marks::year,diff,other); + } + case month: + { + int diff = 12 * (other->tm_.tm_year - tm_.tm_year) + + other->tm_.tm_mon - tm_.tm_mon; + return get_diff(period::marks::month,diff,other); + } + case day_of_week_in_month: + case week_of_month: + case week_of_year: + factor = 7; + // fall + case day: + case day_of_year: + case day_of_week: + case day_of_week_local: + { + int diff = other->tm_.tm_yday - tm_.tm_yday; + if(other->tm_.tm_year != tm_.tm_year) { + diff += days_from_0(other->tm_.tm_year + 1900) - + days_from_0(tm_.tm_year + 1900); + } + return get_diff(period::marks::day,diff,other) / factor; + } + case am_pm: + return static_cast<int>( (other->time_ - time_) / (3600*12) ); + case hour: + case hour_12: + return static_cast<int>( (other->time_ - time_) / 3600 ); + case minute: + return static_cast<int>( (other->time_ - time_) / 60 ); + case second: + return static_cast<int>( other->time_ - time_ ); + default: + return 0; + }; + } + + /// + /// Set time zone, empty - use system + /// + virtual void set_timezone(std::string const &tz) + { + if(tz.empty()) { + is_local_ = true; + tzoff_ = 0; + } + else { + is_local_ = false; + tzoff_ = parse_tz(tz); + } + from_time(time_); + time_zone_name_ = tz; + } + virtual std::string get_timezone() const + { + return time_zone_name_; + } + + virtual bool same(abstract_calendar const *other) const + { + gregorian_calendar const *gcal = dynamic_cast<gregorian_calendar const *>(other); + if(!gcal) + return false; + return + gcal->tzoff_ == tzoff_ + && gcal->is_local_ == is_local_ + && gcal->first_day_of_week_ == first_day_of_week_; + } + + virtual ~gregorian_calendar() + { + } + + private: + + void from_time(std::time_t point) + { + std::time_t real_point = point + tzoff_; + std::tm *t = 0; + #ifdef BOOST_WINDOWS + // Windows uses TLS, thread safe + t = is_local_ ? localtime(&real_point) : gmtime(&real_point); + #else + std::tm tmp_tm; + t = is_local_ ? localtime_r(&real_point,&tmp_tm) : gmtime_r(&real_point,&tmp_tm); + #endif + if(!t) { + throw date_time_error("boost::locale::gregorian_calendar: invalid time point"); + } + tm_ = *t; + tm_updated_ = *t; + normalized_ = true; + time_ = point; + } + int first_day_of_week_; + std::time_t time_; + std::tm tm_; + std::tm tm_updated_; + bool normalized_; + bool is_local_; + int tzoff_; + std::string time_zone_name_; + + }; + + abstract_calendar *create_gregorian_calendar(std::string const &terr) + { + return new gregorian_calendar(terr); + } + + class gregorian_facet : public calendar_facet { + public: + gregorian_facet(std::string const &terr,size_t refs = 0) : + calendar_facet(refs), + terr_(terr) + { + } + virtual abstract_calendar *create_calendar() const + { + return create_gregorian_calendar(terr_); + } + private: + std::string terr_; + }; + + std::locale install_gregorian_calendar(std::locale const &in,std::string const &terr) + { + return std::locale(in,new gregorian_facet(terr)); + } + + +} // util +} // locale +} //boost + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/gregorian.hpp b/src/boost/libs/locale/src/util/gregorian.hpp new file mode 100644 index 000000000..dc8c5d591 --- /dev/null +++ b/src/boost/libs/locale/src/util/gregorian.hpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_SRC_UTIL_GREGORIAN_HPP +#define BOOST_LOCALE_SRC_UTIL_GREGORIAN_HPP + +#include <locale> + +namespace boost { +namespace locale { +namespace util { + + std::locale install_gregorian_calendar(std::locale const &in,std::string const &terr); + +} // util +} // locale +} //boost + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/iconv.hpp b/src/boost/libs/locale/src/util/iconv.hpp new file mode 100644 index 000000000..3dc69fbc6 --- /dev/null +++ b/src/boost/libs/locale/src/util/iconv.hpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_ICONV_FIXER_HPP +#define BOOST_LOCALE_ICONV_FIXER_HPP + +#include <iconv.h> + +namespace boost { + namespace locale { +#if defined(__ICONV_F_HIDE_INVALID) && defined(__FreeBSD__) + extern "C" { + typedef size_t (*const_iconv_ptr_type)(iconv_t d,char const **in,size_t *insize,char **out,size_t *outsize,uint32_t,size_t *); + typedef size_t (*nonconst_iconv_ptr_type)(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize,uint32_t,size_t *); + } + inline size_t do_iconv(const_iconv_ptr_type ptr,iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + char const **rin = const_cast<char const **>(in); + return ptr(d,rin,insize,out,outsize,__ICONV_F_HIDE_INVALID,0); + } + inline size_t do_iconv(nonconst_iconv_ptr_type ptr,iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + return ptr(d,in,insize,out,outsize,__ICONV_F_HIDE_INVALID,0); + } + inline size_t call_iconv(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + char const **rin = const_cast<char const **>(in); + return do_iconv(__iconv, d, in,insize,out,outsize); + } +#else + extern "C" { + typedef size_t (*gnu_iconv_ptr_type)(iconv_t d,char const **in,size_t *insize,char **out,size_t *outsize); + typedef size_t (*posix_iconv_ptr_type)(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize); + } + inline size_t do_iconv(gnu_iconv_ptr_type ptr,iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + char const **rin = const_cast<char const **>(in); + return ptr(d,rin,insize,out,outsize); + } + inline size_t do_iconv(posix_iconv_ptr_type ptr,iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + return ptr(d,in,insize,out,outsize); + } + inline size_t call_iconv(iconv_t d,char **in,size_t *insize,char **out,size_t *outsize) + { + return do_iconv( iconv, d, in,insize,out,outsize); + } +#endif + + } // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/info.cpp b/src/boost/libs/locale/src/util/info.cpp new file mode 100644 index 000000000..67266354e --- /dev/null +++ b/src/boost/libs/locale/src/util/info.cpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <boost/locale/util.hpp> +#include <sstream> +#include <stdlib.h> + +#include "locale_data.hpp" + +namespace boost { +namespace locale { +namespace util { + class simple_info : public info { + public: + simple_info(std::string const &name,size_t refs = 0) : + info(refs), + name_(name) + { + d.parse(name); + } + virtual std::string get_string_property(string_propery v) const + { + switch(v) { + case language_property: + return d.language; + case country_property: + return d.country; + case variant_property: + return d.variant; + case encoding_property: + return d.encoding; + case name_property: + return name_; + default: + return ""; + }; + } + + virtual int get_integer_property(integer_property v) const + { + switch(v) { + case utf8_property: + return d.utf8; + default: + return 0; + } + } + private: + locale_data d; + std::string name_; + }; + + std::locale create_info(std::locale const &in,std::string const &name) + { + return std::locale(in,new simple_info(name)); + } + + +} // util +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/locale_data.cpp b/src/boost/libs/locale/src/util/locale_data.cpp new file mode 100644 index 000000000..a0070d535 --- /dev/null +++ b/src/boost/libs/locale/src/util/locale_data.cpp @@ -0,0 +1,113 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include "locale_data.hpp" +#include "../encoding/conv.hpp" +#include <string> + +namespace boost { +namespace locale { +namespace util { + void locale_data::parse(std::string const &locale_name) + { + language = "C"; + country.clear(); + variant.clear(); + encoding = "us-ascii"; + utf8=false; + parse_from_lang(locale_name); + } + + void locale_data::parse_from_lang(std::string const &locale_name) + { + size_t end = locale_name.find_first_of("-_@."); + std::string tmp = locale_name.substr(0,end); + if(tmp.empty()) + return; + for(unsigned i=0;i<tmp.size();i++) { + if('A' <= tmp[i] && tmp[i]<='Z') + tmp[i]=tmp[i]-'A'+'a'; + else if(tmp[i] < 'a' || 'z' < tmp[i]) + return; + } + language = tmp; + if(end >= locale_name.size()) + return; + + if(locale_name[end] == '-' || locale_name[end]=='_') { + parse_from_country(locale_name.substr(end+1)); + } + else if(locale_name[end] == '.') { + parse_from_encoding(locale_name.substr(end+1)); + } + else if(locale_name[end] == '@') { + parse_from_variant(locale_name.substr(end+1)); + } + } + + void locale_data::parse_from_country(std::string const &locale_name) + { + size_t end = locale_name.find_first_of("@."); + std::string tmp = locale_name.substr(0,end); + if(tmp.empty()) + return; + for(unsigned i=0;i<tmp.size();i++) { + if('a' <= tmp[i] && tmp[i]<='z') + tmp[i]=tmp[i]-'a'+'A'; + else if(tmp[i] < 'A' || 'Z' < tmp[i]) + return; + } + + country = tmp; + + if(end >= locale_name.size()) + return; + else if(locale_name[end] == '.') { + parse_from_encoding(locale_name.substr(end+1)); + } + else if(locale_name[end] == '@') { + parse_from_variant(locale_name.substr(end+1)); + } + } + + void locale_data::parse_from_encoding(std::string const &locale_name) + { + size_t end = locale_name.find_first_of("@"); + std::string tmp = locale_name.substr(0,end); + if(tmp.empty()) + return; + for(unsigned i=0;i<tmp.size();i++) { + if('A' <= tmp[i] && tmp[i]<='Z') + tmp[i]=tmp[i]-'A'+'a'; + } + encoding = tmp; + + utf8 = conv::impl::normalize_encoding(encoding.c_str()) == "utf8"; + + if(end >= locale_name.size()) + return; + + if(locale_name[end] == '@') { + parse_from_variant(locale_name.substr(end+1)); + } + } + + void locale_data::parse_from_variant(std::string const &locale_name) + { + variant = locale_name; + for(unsigned i=0;i<variant.size();i++) { + if('A' <= variant[i] && variant[i]<='Z') + variant[i]=variant[i]-'A'+'a'; + } + } + +} // util +} // locale +} // boost + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/locale_data.hpp b/src/boost/libs/locale/src/util/locale_data.hpp new file mode 100644 index 000000000..5b929f148 --- /dev/null +++ b/src/boost/libs/locale/src/util/locale_data.hpp @@ -0,0 +1,47 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_UTIL_LOCALE_DATA_HPP +#define BOOST_LOCALE_IMPL_UTIL_LOCALE_DATA_HPP + +#include <string> + +namespace boost { + namespace locale { + namespace util { + + class locale_data { + public: + locale_data() : + language("C"), + encoding("us-ascii"), + utf8(false) + { + } + + std::string language; + std::string country; + std::string variant; + std::string encoding; + bool utf8; + + void parse(std::string const &locale_name); + + private: + + void parse_from_lang(std::string const &locale_name); + void parse_from_country(std::string const &locale_name); + void parse_from_encoding(std::string const &locale_name); + void parse_from_variant(std::string const &locale_name); + }; + + } // util + } // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/numeric.hpp b/src/boost/libs/locale/src/util/numeric.hpp new file mode 100644 index 000000000..892427dfc --- /dev/null +++ b/src/boost/libs/locale/src/util/numeric.hpp @@ -0,0 +1,393 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP +#define BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/formatting.hpp> +#include <boost/locale/info.hpp> +#include <sstream> +#include <vector> +#include <ctime> +#include <stdlib.h> + +#include "timezone.hpp" + +// This is internal header so disable crappy "unsecure functions" for all +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif + + +namespace boost { +namespace locale { +namespace util { + +template<typename CharType> +struct formatting_size_traits { + static size_t size(std::basic_string<CharType> const &s,std::locale const &/*l*/) + { + return s.size(); + } +}; + +template<> +struct formatting_size_traits<char> { + static size_t size(std::string const &s,std::locale const &l) + { + if(!std::has_facet<info>(l)) + return s.size(); + if(!std::use_facet<info>(l).utf8()) + return s.size(); + // count code points, poor man's text size + size_t res = 0; + for(size_t i=0;i<s.size();i++) { + unsigned char c = s[i]; + if(c <= 127) + res ++; + else if ((c & 0xC0) == 0xC0) { // first UTF-8 byte + res ++; + } + } + return res; + } +}; + + + +template<typename CharType> +class base_num_format : public std::num_put<CharType> +{ +public: + typedef typename std::num_put<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + + base_num_format(size_t refs = 0) : + std::num_put<CharType>(refs) + { + } +protected: + + + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, double val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long double val) const + { + return do_real_put(out,ios,fill,val); + } + + #ifndef BOOST_NO_LONG_LONG + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, long long val) const + { + return do_real_put(out,ios,fill,val); + } + virtual iter_type do_put (iter_type out, std::ios_base &ios, char_type fill, unsigned long long val) const + { + return do_real_put(out,ios,fill,val); + } + #endif + + +private: + + + + template<typename ValueType> + iter_type do_real_put (iter_type out, std::ios_base &ios, char_type fill, ValueType val) const + { + typedef std::num_put<char_type> super; + + ios_info &info=ios_info::get(ios); + + switch(info.display_flags()) { + case flags::posix: + { + typedef std::basic_ostringstream<char_type> sstream_type; + sstream_type ss; + ss.imbue(std::locale::classic()); + ss.flags(ios.flags()); + ss.precision(ios.precision()); + ss.width(ios.width()); + iter_type ret_ptr = super::do_put(out,ss,fill,val); + ios.width(0); + return ret_ptr; + } + case flags::date: + return format_time(out,ios,fill,static_cast<std::time_t>(val),'x'); + case flags::time: + return format_time(out,ios,fill,static_cast<std::time_t>(val),'X'); + case flags::datetime: + return format_time(out,ios,fill,static_cast<std::time_t>(val),'c'); + case flags::strftime: + return format_time(out,ios,fill,static_cast<std::time_t>(val),info.date_time_pattern<char_type>()); + case flags::currency: + { + bool nat = info.currency_flags()==flags::currency_default + || info.currency_flags() == flags::currency_national; + bool intl = !nat; + return do_format_currency(intl,out,ios,fill,static_cast<long double>(val)); + } + + case flags::number: + case flags::percent: + case flags::spellout: + case flags::ordinal: + default: + return super::do_put(out,ios,fill,val); + } + } + + virtual iter_type do_format_currency(bool intl,iter_type out,std::ios_base &ios,char_type fill,long double val) const + { + if(intl) + return format_currency<true>(out,ios,fill,val); + else + return format_currency<false>(out,ios,fill,val); + } + + template<bool intl> + iter_type format_currency(iter_type out,std::ios_base &ios,char_type fill,long double val) const + { + std::locale loc = ios.getloc(); + int digits = std::use_facet<std::moneypunct<char_type,intl> >(loc).frac_digits(); + while(digits > 0) { + val*=10; + digits --; + } + std::ios_base::fmtflags f=ios.flags(); + ios.flags(f | std::ios_base::showbase); + out = std::use_facet<std::money_put<char_type> >(loc).put(out,intl,ios,fill,val); + ios.flags(f); + return out; + } + + iter_type format_time(iter_type out,std::ios_base &ios,char_type fill,std::time_t time,char c) const + { + string_type fmt; + fmt+=char_type('%'); + fmt+=char_type(c); + return format_time(out,ios,fill,time,fmt); + } + + iter_type format_time(iter_type out,std::ios_base &ios,char_type fill,std::time_t time,string_type const &format) const + { + std::string tz = ios_info::get(ios).time_zone(); + std::tm tm; + #if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__) + std::vector<char> tmp_buf(tz.c_str(),tz.c_str()+tz.size()+1); + #endif + if(tz.empty()) { + #ifdef BOOST_WINDOWS + /// Windows uses TLS + tm = *localtime(&time); + #else + localtime_r(&time,&tm); + #endif + } + else { + int gmtoff = parse_tz(tz); + time+=gmtoff; + #ifdef BOOST_WINDOWS + /// Windows uses TLS + tm = *gmtime(&time); + #else + gmtime_r(&time,&tm); + #endif + + #if defined(__linux) || defined(__FreeBSD__) || defined(__APPLE__) + // These have extra fields to specify timezone + if(gmtoff!=0) { + // bsd and apple want tm_zone be non-const + tm.tm_zone=&tmp_buf.front(); + tm.tm_gmtoff = gmtoff; + } + #endif + } + std::basic_ostringstream<char_type> tmp_out; + std::use_facet<std::time_put<char_type> >(ios.getloc()).put(tmp_out,tmp_out,fill,&tm,format.c_str(),format.c_str()+format.size()); + string_type str = tmp_out.str(); + std::streamsize on_left=0,on_right = 0; + std::streamsize points = + formatting_size_traits<char_type>::size(str,ios.getloc()); + if(points < ios.width()) { + std::streamsize n = ios.width() - points; + + std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield; + + // + // we do not really know internal point, so we assume that it does not + // exist. so according to the standard field should be right aligned + // + if(flags != std::ios_base::left) + on_left = n; + on_right = n - on_left; + } + while(on_left > 0) { + *out++ = fill; + on_left--; + } + std::copy(str.begin(),str.end(),out); + while(on_right > 0) { + *out++ = fill; + on_right--; + } + ios.width(0); + return out; + } + +}; /// num_format + + +template<typename CharType> +class base_num_parse : public std::num_get<CharType> +{ +public: + base_num_parse(size_t refs = 0) : + std::num_get<CharType>(refs) + { + } +protected: + typedef typename std::num_get<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned short &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned int &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,float &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get(iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,double &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long double &val) const + { + return do_real_get(in,end,ios,err,val); + } + + #ifndef BOOST_NO_LONG_LONG + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,long long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + virtual iter_type do_get (iter_type in, iter_type end, std::ios_base &ios,std::ios_base::iostate &err,unsigned long long &val) const + { + return do_real_get(in,end,ios,err,val); + } + + #endif + +private: + + template<typename ValueType> + iter_type do_real_get(iter_type in,iter_type end,std::ios_base &ios,std::ios_base::iostate &err,ValueType &val) const + { + typedef std::num_get<char_type> super; + + ios_info &info=ios_info::get(ios); + + switch(info.display_flags()) { + case flags::posix: + { + std::stringstream ss; + ss.imbue(std::locale::classic()); + ss.flags(ios.flags()); + ss.precision(ios.precision()); + return super::do_get(in,end,ss,err,val); + } + case flags::currency: + { + long double ret_val = 0; + if(info.currency_flags()==flags::currency_default || info.currency_flags() == flags::currency_national) + in = parse_currency<false>(in,end,ios,err,ret_val); + else + in = parse_currency<true>(in,end,ios,err,ret_val); + if(!(err & std::ios_base::failbit)) + val = static_cast<ValueType>(ret_val); + return in; + } + + // date-time parsing is not supported + // due to buggy standard + case flags::date: + case flags::time: + case flags::datetime: + case flags::strftime: + + case flags::number: + case flags::percent: + case flags::spellout: + case flags::ordinal: + default: + return super::do_get(in,end,ios,err,val); + } + } + + template<bool intl> + iter_type parse_currency(iter_type in,iter_type end,std::ios_base &ios,std::ios_base::iostate &err,long double &val) const + { + std::locale loc = ios.getloc(); + int digits = std::use_facet<std::moneypunct<char_type,intl> >(loc).frac_digits(); + long double rval; + in = std::use_facet<std::money_get<char_type> >(loc).get(in,end,intl,ios,err,rval); + if(!(err & std::ios::failbit)) { + while(digits > 0) { + rval/=10; + digits --; + } + val = rval; + } + return in; + } + + +}; + +} // util +} // locale +} //boost + + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/util/timezone.hpp b/src/boost/libs/locale/src/util/timezone.hpp new file mode 100644 index 000000000..07a8c8ca2 --- /dev/null +++ b/src/boost/libs/locale/src/util/timezone.hpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP +#define BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP +#include <string> +#include <stdlib.h> +#include <string.h> +namespace boost { +namespace locale { +namespace util { + inline int parse_tz(std::string const &tz) + { + int gmtoff = 0; + std::string ltz; + for(unsigned i=0;i<tz.size();i++) { + if('a' <= tz[i] && tz[i] <= 'z') + ltz += tz[i]-'a' + 'A'; + else if(tz[i]==' ') + ; + else + ltz+=tz[i]; + } + if(ltz.compare(0,3,"GMT")!=0 && ltz.compare(0,3,"UTC")!=0) + return 0; + if(ltz.size()<=3) + return 0; + char const *begin = ltz.c_str()+3; + char *end=0; + int hours = strtol(begin,&end,10); + if(end != begin) { + gmtoff+=hours * 3600; + } + if(*end==':') { + begin=end+1; + int minutes = strtol(begin,&end,10); + if(end!=begin) + gmtoff+=minutes * 60; + } + return gmtoff; + } + +} // util +} // locale +} //boost + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/all_generator.hpp b/src/boost/libs/locale/src/win32/all_generator.hpp new file mode 100644 index 000000000..083d05627 --- /dev/null +++ b/src/boost/libs/locale/src/win32/all_generator.hpp @@ -0,0 +1,45 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_WIN32_ALL_GENERATOR_HPP +#define BOOST_LOCALE_IMPL_WIN32_ALL_GENERATOR_HPP + +#include <boost/locale/generator.hpp> +#include <vector> +#include <locale.h> + +namespace boost { + namespace locale { + namespace impl_win { + + class winlocale; + + std::locale create_convert( std::locale const &in, + winlocale const &lc, + character_facet_type type); + + std::locale create_collate( std::locale const &in, + winlocale const &lc, + character_facet_type type); + + std::locale create_formatting( std::locale const &in, + winlocale const &lc, + character_facet_type type); + + std::locale create_parsing( std::locale const &in, + winlocale const &lc, + character_facet_type type); + + std::locale create_codecvt( std::locale const &in, + character_facet_type type); + + } + } +} + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/api.hpp b/src/boost/libs/locale/src/win32/api.hpp new file mode 100644 index 000000000..a41fbde5e --- /dev/null +++ b/src/boost/libs/locale/src/win32/api.hpp @@ -0,0 +1,357 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_WIN32_API_HPP +#define BOOST_LOCALE_IMPL_WIN32_API_HPP + +#include <string> +#include <vector> +#include <sstream> +#include <iomanip> +#include <limits> +#include <ctime> + +#include "lcid.hpp" + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef UNICODE +#define UNICODE +#endif +#include <windows.h> + +#include <boost/locale/conversion.hpp> +#include <boost/locale/collator.hpp> + +#define BOOST_LOCALE_WINDOWS_2000_API + +#if defined(_WIN32_NT) && _WIN32_NT >= 0x600 && !defined(BOOST_LOCALE_WINDOWS_2000_API) +#define BOOST_LOCALE_WINDOWS_VISTA_API +#else +#define BOOST_LOCALE_WINDOWS_2000_API +#endif + +namespace boost { +namespace locale { +namespace impl_win { + + struct numeric_info { + std::wstring thousands_sep; + std::wstring decimal_point; + std::string grouping; + }; + + inline DWORD collation_level_to_flag(collator_base::level_type level) + { + DWORD flags; + switch(level) { + case collator_base::primary: + flags = NORM_IGNORESYMBOLS | NORM_IGNORECASE | NORM_IGNORENONSPACE; + break; + case collator_base::secondary: + flags = NORM_IGNORESYMBOLS | NORM_IGNORECASE; + break; + case collator_base::tertiary: + flags = NORM_IGNORESYMBOLS; + break; + default: + flags = 0; + } + return flags; + } + + + + #ifdef BOOST_LOCALE_WINDOWS_2000_API + + class winlocale{ + public: + winlocale() : + lcid(0) + { + } + + winlocale(std::string const &name) + { + lcid = locale_to_lcid(name); + } + + unsigned lcid; + + bool is_c() const + { + return lcid == 0; + } + }; + + + //////////////////////////////////////////////////////////////////////// + /// + /// Number Format + /// + //////////////////////////////////////////////////////////////////////// + + inline numeric_info wcsnumformat_l(winlocale const &l) + { + numeric_info res; + res.decimal_point = L'.'; + unsigned lcid = l.lcid; + + if(lcid == 0) + return res; + + // limits according to MSDN + static const int th_size = 4; + static const int de_size = 4; + static const int gr_size = 10; + + wchar_t th[th_size]={0}; + wchar_t de[de_size]={0}; + wchar_t gr[gr_size]={0}; + + if( GetLocaleInfoW(lcid,LOCALE_STHOUSAND,th,th_size)==0 + || GetLocaleInfoW(lcid,LOCALE_SDECIMAL ,de,de_size)==0 + || GetLocaleInfoW(lcid,LOCALE_SGROUPING,gr,gr_size)==0) + { + return res; + } + res.decimal_point = de; + res.thousands_sep = th; + bool inf_group = false; + for(unsigned i=0;gr[i];i++) { + if(gr[i]==L';') + continue; + if(L'1'<= gr[i] && gr[i]<=L'9') { + res.grouping += char(gr[i]-L'0'); + } + else if(gr[i]==L'0') + inf_group = true; + } + if(!inf_group) { + if(std::numeric_limits<char>::is_signed) { + res.grouping+=std::numeric_limits<char>::min(); + } + else { + res.grouping+=std::numeric_limits<char>::max(); + } + } + return res; + } + + inline std::wstring win_map_string_l(unsigned flags,wchar_t const *begin,wchar_t const *end,winlocale const &l) + { + std::wstring res; + int len = LCMapStringW(l.lcid,flags,begin,end-begin,0,0); + if(len == 0) + return res; + std::vector<wchar_t> buf(len+1); + int l2 = LCMapStringW(l.lcid,flags,begin,end-begin,&buf.front(),buf.size()); + res.assign(&buf.front(),l2); + return res; + } + + //////////////////////////////////////////////////////////////////////// + /// + /// Collation + /// + //////////////////////////////////////////////////////////////////////// + + + inline int wcscoll_l( collator_base::level_type level, + wchar_t const *lb,wchar_t const *le, + wchar_t const *rb,wchar_t const *re, + winlocale const &l) + { + return CompareStringW(l.lcid,collation_level_to_flag(level),lb,le-lb,rb,re-rb) - 2; + } + + + //////////////////////////////////////////////////////////////////////// + /// + /// Money Format + /// + //////////////////////////////////////////////////////////////////////// + + inline std::wstring wcsfmon_l(double value,winlocale const &l) + { + std::wostringstream ss; + ss.imbue(std::locale::classic()); + + ss << std::setprecision(std::numeric_limits<double>::digits10+1) << value; + std::wstring sval = ss.str(); + int len = GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,0,0); + std::vector<wchar_t> buf(len+1); + GetCurrencyFormatW(l.lcid,0,sval.c_str(),0,&buf.front(),len); + return &buf.front(); + } + + //////////////////////////////////////////////////////////////////////// + /// + /// Time Format + /// + //////////////////////////////////////////////////////////////////////// + + + inline std::wstring wcs_format_date_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l) + { + int len = GetDateFormatW(l.lcid,0,tm,format,0,0); + std::vector<wchar_t> buf(len+1); + GetDateFormatW(l.lcid,0,tm,format,&buf.front(),len); + return &buf.front(); + } + + inline std::wstring wcs_format_time_l(wchar_t const *format,SYSTEMTIME const *tm,winlocale const &l) + { + int len = GetTimeFormatW(l.lcid,0,tm,format,0,0); + std::vector<wchar_t> buf(len+1); + GetTimeFormatW(l.lcid,0,tm,format,&buf.front(),len); + return &buf.front(); + } + + inline std::wstring wcsfold(wchar_t const *begin,wchar_t const *end) + { + winlocale l; + l.lcid = 0x0409; // en-US + return win_map_string_l(LCMAP_LOWERCASE,begin,end,l); + } + + inline std::wstring wcsnormalize(norm_type norm,wchar_t const *begin,wchar_t const *end) + { + // We use FoldString, under Vista it actually does normalization; + // under XP and below it does something similar, half job, better then nothing + unsigned flags = 0; + switch(norm) { + case norm_nfd: + flags = MAP_COMPOSITE; + break; + case norm_nfc: + flags = MAP_PRECOMPOSED; + break; + case norm_nfkd: + flags = MAP_FOLDCZONE; + break; + case norm_nfkc: + flags = MAP_FOLDCZONE | MAP_COMPOSITE; + break; + default: + flags = MAP_PRECOMPOSED; + } + + int len = FoldStringW(flags,begin,end-begin,0,0); + if(len == 0) + return std::wstring(); + std::vector<wchar_t> v(len+1); + len = FoldStringW(flags,begin,end-begin,&v.front(),len+1); + return std::wstring(&v.front(),len); + } + + + #endif + + inline std::wstring wcsxfrm_l(collator_base::level_type level,wchar_t const *begin,wchar_t const *end,winlocale const &l) + { + int flag = LCMAP_SORTKEY | collation_level_to_flag(level); + + return win_map_string_l(flag,begin,end,l); + } + + inline std::wstring towupper_l(wchar_t const *begin,wchar_t const *end,winlocale const &l) + { + return win_map_string_l(LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING,begin,end,l); + } + + inline std::wstring towlower_l(wchar_t const *begin,wchar_t const *end,winlocale const &l) + { + return win_map_string_l(LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING,begin,end,l); + } + + inline std::wstring wcsftime_l(char c,std::tm const *tm,winlocale const &l) + { + SYSTEMTIME wtm=SYSTEMTIME(); + wtm.wYear = tm->tm_year + 1900; + wtm.wMonth = tm->tm_mon+1; + wtm.wDayOfWeek = tm->tm_wday; + wtm.wDay = tm->tm_mday; + wtm.wHour = tm->tm_hour; + wtm.wMinute = tm->tm_min; + wtm.wSecond = tm->tm_sec; + switch(c) { + case 'a': // Abbr Weekday + return wcs_format_date_l(L"ddd",&wtm,l); + case 'A': // Full Weekday + return wcs_format_date_l(L"dddd",&wtm,l); + case 'b': // Abbr Month + return wcs_format_date_l(L"MMM",&wtm,l); + case 'B': // Full Month + return wcs_format_date_l(L"MMMM",&wtm,l); + case 'c': // DateTile Full + return wcs_format_date_l(0,&wtm,l) + L" " + wcs_format_time_l(0,&wtm,l); + // not supported by WIN ;( + // case 'C': // Century -> 1980 -> 19 + // retur + case 'd': // Day of Month [01,31] + return wcs_format_date_l(L"dd",&wtm,l); + case 'D': // %m/%d/%y + return wcs_format_date_l(L"MM/dd/yy",&wtm,l); + case 'e': // Day of Month [1,31] + return wcs_format_date_l(L"d",&wtm,l); + case 'h': // == b + return wcs_format_date_l(L"MMM",&wtm,l); + case 'H': // 24 clock hour 00,23 + return wcs_format_time_l(L"HH",&wtm,l); + case 'I': // 12 clock hour 01,12 + return wcs_format_time_l(L"hh",&wtm,l); + /* + case 'j': // day of year 001,366 + return "D";*/ + case 'm': // month as [01,12] + return wcs_format_date_l(L"MM",&wtm,l); + case 'M': // minute [00,59] + return wcs_format_time_l(L"mm",&wtm,l); + case 'n': // \n + return L"\n"; + case 'p': // am-pm + return wcs_format_time_l(L"tt",&wtm,l); + case 'r': // time with AM/PM %I:%M:%S %p + return wcs_format_time_l(L"hh:mm:ss tt",&wtm,l); + case 'R': // %H:%M + return wcs_format_time_l(L"HH:mm",&wtm,l); + case 'S': // second [00,61] + return wcs_format_time_l(L"ss",&wtm,l); + case 't': // \t + return L"\t"; + case 'T': // %H:%M:%S + return wcs_format_time_l(L"HH:mm:ss",&wtm,l); +/* case 'u': // weekday 1,7 1=Monday + case 'U': // week number of year [00,53] Sunday first + case 'V': // week number of year [01,53] Moday first + case 'w': // weekday 0,7 0=Sunday + case 'W': // week number of year [00,53] Moday first, */ + case 'x': // Date + return wcs_format_date_l(0,&wtm,l); + case 'X': // Time + return wcs_format_time_l(0,&wtm,l); + case 'y': // Year [00-99] + return wcs_format_date_l(L"yy",&wtm,l); + case 'Y': // Year 1998 + return wcs_format_date_l(L"yyyy",&wtm,l); + case '%': // % + return L"%"; + default: + return L""; + } + } + + + +} // win +} // locale +} // boost +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/src/win32/collate.cpp b/src/boost/libs/locale/src/win32/collate.cpp new file mode 100644 index 000000000..40e8c3d21 --- /dev/null +++ b/src/boost/libs/locale/src/win32/collate.cpp @@ -0,0 +1,127 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/encoding.hpp> +#include <boost/locale/generator.hpp> +#include "api.hpp" +#include "../shared/mo_hash.hpp" + +namespace boost { +namespace locale { +namespace impl_win { + +class utf8_collator : public collator<char> { +public: + utf8_collator(winlocale lc,size_t refs = 0) : + collator<char>(refs), + lc_(lc) + { + } + virtual int do_compare(collator_base::level_type level,char const *lb,char const *le,char const *rb,char const *re) const + { + std::wstring l=conv::to_utf<wchar_t>(lb,le,"UTF-8"); + std::wstring r=conv::to_utf<wchar_t>(rb,re,"UTF-8"); + return wcscoll_l(level,l.c_str(),l.c_str()+l.size(),r.c_str(),r.c_str()+r.size(),lc_); + } + virtual long do_hash(collator_base::level_type level,char const *b,char const *e) const + { + std::string key = do_transform(level,b,e); + return gnu_gettext::pj_winberger_hash_function(key.c_str(),key.c_str() + key.size()); + } + virtual std::string do_transform(collator_base::level_type level,char const *b,char const *e) const + { + std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8"); + std::wstring wkey = wcsxfrm_l(level,tmp.c_str(),tmp.c_str()+tmp.size(),lc_); + std::string key; + if(sizeof(wchar_t)==2) + key.reserve(wkey.size()*2); + else + key.reserve(wkey.size()*3); + for(unsigned i=0;i<wkey.size();i++) { + if(sizeof(wchar_t)==2) { + uint16_t tv = static_cast<uint16_t>(wkey[i]); + key += char(tv >> 8); + key += char(tv & 0xFF); + } + else { // 4 + uint32_t tv = static_cast<uint32_t>(wkey[i]); + // 21 bit + key += char((tv >> 16) & 0xFF); + key += char((tv >> 8) & 0xFF); + key += char(tv & 0xFF); + } + } + return key; + } +private: + winlocale lc_; +}; + + +class utf16_collator : public collator<wchar_t> { +public: + typedef std::collate<wchar_t> wfacet; + utf16_collator(winlocale lc,size_t refs = 0) : + collator<wchar_t>(refs), + lc_(lc) + { + } + virtual int do_compare(collator_base::level_type level,wchar_t const *lb,wchar_t const *le,wchar_t const *rb,wchar_t const *re) const + { + return wcscoll_l(level,lb,le,rb,re,lc_); + } + virtual long do_hash(collator_base::level_type level,wchar_t const *b,wchar_t const *e) const + { + std::wstring key = do_transform(level,b,e); + char const *begin = reinterpret_cast<char const *>(key.c_str()); + char const *end = begin + key.size()*sizeof(wchar_t); + return gnu_gettext::pj_winberger_hash_function(begin,end); + } + virtual std::wstring do_transform(collator_base::level_type level,wchar_t const *b,wchar_t const *e) const + { + return wcsxfrm_l(level,b,e,lc_); + } +private: + winlocale lc_; +}; + + +std::locale create_collate( std::locale const &in, + winlocale const &lc, + character_facet_type type) +{ + if(lc.is_c()) { + switch(type) { + case char_facet: + return std::locale(in,new std::collate_byname<char>("C")); + case wchar_t_facet: + return std::locale(in,new std::collate_byname<wchar_t>("C")); + } + } + else { + switch(type) { + case char_facet: + return std::locale(in,new utf8_collator(lc)); + case wchar_t_facet: + return std::locale(in,new utf16_collator(lc)); + } + } + return in; +} + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/converter.cpp b/src/boost/libs/locale/src/win32/converter.cpp new file mode 100644 index 000000000..fffb0c7b8 --- /dev/null +++ b/src/boost/libs/locale/src/win32/converter.cpp @@ -0,0 +1,106 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE + +#include <locale> +#include <stdexcept> +#include <boost/locale/generator.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/encoding.hpp> +#include <vector> +#include <string.h> +#include "api.hpp" +#include "all_generator.hpp" + +namespace boost { +namespace locale { +namespace impl_win { + +class utf16_converter : public converter<wchar_t> +{ +public: + utf16_converter(winlocale const &lc,size_t refs = 0) : + converter<wchar_t>(refs), + lc_(lc) + { + } + virtual std::wstring convert(converter_base::conversion_type how,wchar_t const *begin,wchar_t const *end,int flags = 0) const + { + switch(how) { + case converter_base::upper_case: + return towupper_l(begin,end,lc_); + case converter_base::lower_case: + return towlower_l(begin,end,lc_); + case converter_base::case_folding: + return wcsfold(begin,end); + case converter_base::normalization: + return wcsnormalize(static_cast<norm_type>(flags),begin,end); + default: + return std::wstring(begin,end-begin); + } + } +private: + winlocale lc_; +}; + +class utf8_converter : public converter<char> { +public: + utf8_converter(winlocale const &lc,size_t refs = 0) : + converter<char>(refs), + lc_(lc) + { + } + virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int flags = 0) const + { + std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8"); + wchar_t const *wb=tmp.c_str(); + wchar_t const *we=wb+tmp.size(); + + std::wstring res; + + switch(how) { + case upper_case: + res = towupper_l(wb,we,lc_); + break; + case lower_case: + res = towlower_l(wb,we,lc_); + break; + case case_folding: + res = wcsfold(wb,we); + break; + case normalization: + res = wcsnormalize(static_cast<norm_type>(flags),wb,we); + break; + default: + res = tmp; // make gcc happy + } + return conv::from_utf(res,"UTF-8"); + } +private: + winlocale lc_; +}; + +std::locale create_convert( std::locale const &in, + winlocale const &lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return std::locale(in,new utf8_converter(lc)); + case wchar_t_facet: + return std::locale(in,new utf16_converter(lc)); + default: + return in; + } +} + + +} // namespace impl_win32 +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/lcid.cpp b/src/boost/libs/locale/src/win32/lcid.cpp new file mode 100644 index 000000000..67542e6c6 --- /dev/null +++ b/src/boost/libs/locale/src/win32/lcid.cpp @@ -0,0 +1,127 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include "lcid.hpp" +#include <string.h> +#include <string> +#include <sstream> +#include <map> + +#include "../util/locale_data.hpp" + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include <windows.h> + +#include <boost/thread/mutex.hpp> + +namespace boost { +namespace locale { +namespace impl_win { + +typedef std::map<std::string,unsigned> table_type; + +static table_type * volatile table = 0; + +boost::mutex &lcid_table_mutex() +{ + static boost::mutex m; + return m; +} + +table_type &real_lcid_table() +{ + static table_type table; + return table; +} + +BOOL CALLBACK proc(char *s) +{ + table_type &tbl = real_lcid_table(); + try { + std::istringstream ss; + ss.str(s); + ss >> std::hex; + + unsigned lcid ; + ss >>lcid; + if(ss.fail() || !ss.eof()) { + return FALSE; + } + + char iso_639_lang[16]; + char iso_3166_country[16]; + if(GetLocaleInfoA(lcid,LOCALE_SISO639LANGNAME,iso_639_lang,sizeof(iso_639_lang))==0) + return FALSE; + std::string lc_name = iso_639_lang; + if(GetLocaleInfoA(lcid,LOCALE_SISO3166CTRYNAME,iso_3166_country,sizeof(iso_3166_country))!=0) { + lc_name += "_"; + lc_name += iso_3166_country; + } + table_type::iterator p = tbl.find(lc_name); + if(p!=tbl.end()) { + if(p->second > lcid) + p->second = lcid; + } + else { + tbl[lc_name]=lcid; + } + } + catch(...) { + tbl.clear(); + return FALSE; + } + return TRUE; +} + + +table_type const &get_ready_lcid_table() +{ + if(table) + return *table; + else { + boost::unique_lock<boost::mutex> lock(lcid_table_mutex()); + if(table) + return *table; + EnumSystemLocalesA(proc,LCID_INSTALLED); + table = &real_lcid_table(); + return *table; + } +} + +unsigned locale_to_lcid(std::string const &locale_name) +{ + if(locale_name.empty()) { + return LOCALE_USER_DEFAULT; + } + boost::locale::util::locale_data d; + d.parse(locale_name); + std::string id = d.language; + + if(!d.country.empty()) { + id+="_"+d.country; + } + if(!d.variant.empty()) { + id+="@" + d.variant; + } + + table_type const &tbl = get_ready_lcid_table(); + table_type::const_iterator p = tbl.find(id); + + unsigned lcid = 0; + if(p!=tbl.end()) + lcid = p->second; + return lcid; +} + + +} // impl_win +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/lcid.hpp b/src/boost/libs/locale/src/win32/lcid.hpp new file mode 100644 index 000000000..ed988394e --- /dev/null +++ b/src/boost/libs/locale/src/win32/lcid.hpp @@ -0,0 +1,25 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_WIN32_LCID_HPP +#define BOOST_LOCALE_IMPL_WIN32_LCID_HPP + +#include <string> +#include <boost/locale/config.hpp> + +namespace boost { + namespace locale { + namespace impl_win { + + BOOST_LOCALE_DECL unsigned locale_to_lcid(std::string const &locale_name); + + } // impl_win + } // locale +} // boost + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/numeric.cpp b/src/boost/libs/locale/src/win32/numeric.cpp new file mode 100644 index 000000000..00bc94fd6 --- /dev/null +++ b/src/boost/libs/locale/src/win32/numeric.cpp @@ -0,0 +1,245 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <locale> +#include <string> +#include <ios> +#include <boost/locale/formatting.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/shared_ptr.hpp> +#include <sstream> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <wctype.h> +#include <ctype.h> + +#include "all_generator.hpp" +#include "api.hpp" +#include "../util/numeric.hpp" + +namespace boost { +namespace locale { +namespace impl_win { + namespace { + + std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out,std::wstring const &s) + { + for(size_t i=0;i<s.size();i++) + *out++ = s[i]; + return out; + } + + std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out,std::wstring const &s) + { + std::string tmp = conv::from_utf(s,"UTF-8"); + for(size_t i=0;i<tmp.size();i++) + *out++ = tmp[i]; + return out; + } + } + + +template<typename CharType> +class num_format : public util::base_num_format<CharType> +{ +public: + typedef typename std::num_put<CharType>::iter_type iter_type; + typedef std::basic_string<CharType> string_type; + typedef CharType char_type; + + num_format(winlocale const &lc,size_t refs = 0) : + util::base_num_format<CharType>(refs), + lc_(lc) + { + } +private: + + virtual + iter_type do_format_currency(bool /*intl*/,iter_type out,std::ios_base &ios,char_type fill,long double val) const + { + if(lc_.is_c()) { + std::locale loc = ios.getloc(); + int digits = std::use_facet<std::moneypunct<char_type> >(loc).frac_digits(); + while(digits > 0) { + val*=10; + digits --; + } + std::ios_base::fmtflags f=ios.flags(); + ios.flags(f | std::ios_base::showbase); + out = std::use_facet<std::money_put<char_type> >(loc).put(out,false,ios,fill,val); + ios.flags(f); + return out; + } + else { + std::wstring cur = wcsfmon_l(val,lc_); + return write_it(out,cur); + } + } + +private: + winlocale lc_; + +}; /// num_format + +template<typename CharType> +class time_put_win : public std::time_put<CharType> { +public: + time_put_win(winlocale const &lc, size_t refs = 0) : + std::time_put<CharType>(refs), + lc_(lc) + { + } + virtual ~time_put_win() + { + } + typedef typename std::time_put<CharType>::iter_type iter_type; + typedef CharType char_type; + typedef std::basic_string<char_type> string_type; + + virtual iter_type do_put( iter_type out, + std::ios_base &/*ios*/, + CharType /*fill*/, + std::tm const *tm, + char format, + char /*modifier*/) const + { + return write_it(out,wcsftime_l(format,tm,lc_)); + } + +private: + winlocale lc_; +}; + + +template<typename CharType> +class num_punct_win : public std::numpunct<CharType> { +public: + typedef std::basic_string<CharType> string_type; + num_punct_win(winlocale const &lc,size_t refs = 0) : + std::numpunct<CharType>(refs) + { + numeric_info np = wcsnumformat_l(lc) ; + if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0") + np.thousands_sep=L" "; + + to_str(np.thousands_sep,thousands_sep_); + to_str(np.decimal_point,decimal_point_); + grouping_ = np.grouping; + if(thousands_sep_.size() > 1) + grouping_ = std::string(); + if(decimal_point_.size() > 1) + decimal_point_ = CharType('.'); + } + + void to_str(std::wstring &s1,std::wstring &s2) + { + s2.swap(s1); + } + + void to_str(std::wstring &s1,std::string &s2) + { + s2=conv::from_utf(s1,"UTF-8"); + } + virtual CharType do_decimal_point() const + { + return *decimal_point_.c_str(); + } + virtual CharType do_thousands_sep() const + { + return *thousands_sep_.c_str(); + } + virtual std::string do_grouping() const + { + return grouping_; + } + virtual string_type do_truename() const + { + static const char t[]="true"; + return string_type(t,t+sizeof(t)-1); + } + virtual string_type do_falsename() const + { + static const char t[]="false"; + return string_type(t,t+sizeof(t)-1); + } +private: + string_type decimal_point_; + string_type thousands_sep_; + std::string grouping_; +}; + +template<typename CharType> +std::locale create_formatting_impl(std::locale const &in,winlocale const &lc) +{ + if(lc.is_c()) { + std::locale tmp(in,new std::numpunct_byname<CharType>("C")); + tmp=std::locale(tmp,new std::time_put_byname<CharType>("C")); + tmp = std::locale(tmp,new num_format<CharType>(lc)); + return tmp; + } + else { + std::locale tmp(in,new num_punct_win<CharType>(lc)); + tmp = std::locale(tmp,new time_put_win<CharType>(lc)); + tmp = std::locale(tmp,new num_format<CharType>(lc)); + return tmp; + } +} + +template<typename CharType> +std::locale create_parsing_impl(std::locale const &in,winlocale const &lc) +{ + std::numpunct<CharType> *np = 0; + if(lc.is_c()) + np = new std::numpunct_byname<CharType>("C"); + else + np = new num_punct_win<CharType>(lc); + std::locale tmp(in,np); + tmp = std::locale(tmp,new util::base_num_parse<CharType>()); + return tmp; +} + + +std::locale create_formatting( std::locale const &in, + winlocale const &lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return create_formatting_impl<char>(in,lc); + case wchar_t_facet: + return create_formatting_impl<wchar_t>(in,lc); + default: + return in; + } +} + +std::locale create_parsing( std::locale const &in, + winlocale const &lc, + character_facet_type type) +{ + switch(type) { + case char_facet: + return create_parsing_impl<char>(in,lc); + case wchar_t_facet: + return create_parsing_impl<wchar_t>(in,lc); + default: + return in; + } +} + + + +} // impl_std +} // locale +} //boost + + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/win_backend.cpp b/src/boost/libs/locale/src/win32/win_backend.cpp new file mode 100644 index 000000000..cd9ec8375 --- /dev/null +++ b/src/boost/libs/locale/src/win32/win_backend.cpp @@ -0,0 +1,153 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#define BOOST_LOCALE_SOURCE +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include <boost/locale/info.hpp> +#include "all_generator.hpp" +#include "win_backend.hpp" +#include <boost/locale/util.hpp> +#include "../util/gregorian.hpp" +#include "../util/locale_data.hpp" +#include "api.hpp" +#include <algorithm> +#include <iterator> + +namespace boost { +namespace locale { +namespace impl_win { + + class winapi_localization_backend : public localization_backend { + public: + winapi_localization_backend() : + invalid_(true) + { + } + winapi_localization_backend(winapi_localization_backend const &other) : + localization_backend(), + paths_(other.paths_), + domains_(other.domains_), + locale_id_(other.locale_id_), + invalid_(true) + { + } + virtual winapi_localization_backend *clone() const + { + return new winapi_localization_backend(*this); + } + + void set_option(std::string const &name,std::string const &value) + { + invalid_ = true; + if(name=="locale") + locale_id_ = value; + else if(name=="message_path") + paths_.push_back(value); + else if(name=="message_application") + domains_.push_back(value); + + } + void clear_options() + { + invalid_ = true; + locale_id_.clear(); + paths_.clear(); + domains_.clear(); + } + + void prepare_data() + { + if(!invalid_) + return; + invalid_ = false; + if(locale_id_.empty()) { + real_id_ = util::get_system_locale(true); // always UTF-8 + lc_ = winlocale(real_id_); + } + else { + lc_=winlocale(locale_id_); + real_id_ = locale_id_; + } + util::locale_data d; + d.parse(real_id_); + if(!d.utf8) { + lc_ = winlocale(); + // Make it C as non-UTF8 locales are not supported + } + } + + virtual std::locale install(std::locale const &base, + locale_category_type category, + character_facet_type type = nochar_facet) + { + prepare_data(); + + switch(category) { + case convert_facet: + return create_convert(base,lc_,type); + case collation_facet: + return create_collate(base,lc_,type); + case formatting_facet: + return create_formatting(base,lc_,type); + case parsing_facet: + return create_parsing(base,lc_,type); + case calendar_facet: + { + util::locale_data inf; + inf.parse(real_id_); + return util::install_gregorian_calendar(base,inf.country); + } + case message_facet: + { + gnu_gettext::messages_info minf; + std::locale tmp=util::create_info(std::locale::classic(),real_id_); + boost::locale::info const &inf=std::use_facet<boost::locale::info>(tmp); + minf.language = inf.language(); + minf.country = inf.country(); + minf.variant = inf.variant(); + minf.encoding = inf.encoding(); + std::copy(domains_.begin(),domains_.end(),std::back_inserter<gnu_gettext::messages_info::domains_type>(minf.domains)); + minf.paths = paths_; + switch(type) { + case char_facet: + return std::locale(base,gnu_gettext::create_messages_facet<char>(minf)); + case wchar_t_facet: + return std::locale(base,gnu_gettext::create_messages_facet<wchar_t>(minf)); + default: + return base; + } + } + case information_facet: + return util::create_info(base,real_id_); + case codepage_facet: + return util::create_utf8_codecvt(base,type); + default: + return base; + } + } + + private: + + std::vector<std::string> paths_; + std::vector<std::string> domains_; + std::string locale_id_; + std::string real_id_; + + bool invalid_; + winlocale lc_; + }; + + localization_backend *create_localization_backend() + { + return new winapi_localization_backend(); + } + +} // impl win +} // locale +} // boost +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/src/win32/win_backend.hpp b/src/boost/libs/locale/src/win32/win_backend.hpp new file mode 100644 index 000000000..82f5401f6 --- /dev/null +++ b/src/boost/libs/locale/src/win32/win_backend.hpp @@ -0,0 +1,20 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_IMPL_WIN32_LOCALIZATION_BACKEND_HPP +#define BOOST_LOCALE_IMPL_WIN32_LOCALIZATION_BACKEND_HPP +namespace boost { + namespace locale { + class localization_backend; + namespace impl_win { + localization_backend *create_localization_backend(); + } // impl_win + } // locale +} // boost +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/test/Jamfile.v2 b/src/boost/libs/locale/test/Jamfile.v2 new file mode 100644 index 000000000..db66db2c8 --- /dev/null +++ b/src/boost/libs/locale/test/Jamfile.v2 @@ -0,0 +1,56 @@ +# +# Copyright 2011 Artyom Beilis +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt. + + +project + : requirements + <library>/boost/locale//boost_locale + <use>../build//build_flags + # Make sure we get all defines we need + # Otherwise we would have problem knowing + # what backends are actually in use + <link>shared + <define>BOOST_LOCALE_DYN_LINK=1 + ; + +# Shared boost.locale tests + +test-suite "boost_locale_test" + : + # Configuration Information + [ run test_config.cpp : : : <test-info>always_show_run_output ] + # Shared + [ run test_utf.cpp ] + [ run test_date_time.cpp ] + [ run test_ios_prop.cpp ] + [ run test_codecvt.cpp ] + [ run test_codepage_converter.cpp ] + [ run test_codepage.cpp ] + [ run test_message.cpp : $(BOOST_ROOT)/libs/locale/test ] + [ run test_generator.cpp ] + # icu + [ run test_collate.cpp ] + [ run test_convert.cpp ] + [ run test_boundary.cpp ] + [ run test_formatting.cpp : : : <optimization>off ] + [ run test_icu_vs_os_timezone.cpp ] + # winapi + [ run test_winapi_collate.cpp ] + [ run test_winapi_convert.cpp ] + [ run test_winapi_formatting.cpp ] + # posix + [ run test_posix_collate.cpp ] + [ run test_posix_convert.cpp ] + [ run test_posix_formatting.cpp ] + # std + [ run test_std_collate.cpp ] + [ run test_std_convert.cpp ] + [ run test_std_formatting.cpp ] + ; + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/test/generate_catalogs.sh b/src/boost/libs/locale/test/generate_catalogs.sh new file mode 100755 index 000000000..c3a0bb06f --- /dev/null +++ b/src/boost/libs/locale/test/generate_catalogs.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +# +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + +msgfmt --endianness=big he/LC_MESSAGES/simple.po -o he/LC_MESSAGES/simple.mo +msgfmt he/LC_MESSAGES/default.po -o he/LC_MESSAGES/default.mo +msgfmt he/LC_MESSAGES/fall.po -o he/LC_MESSAGES/fall.mo +msgfmt he_IL/LC_MESSAGES/full.po -o he_IL/LC_MESSAGES/full.mo + diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/default.mo b/src/boost/libs/locale/test/he/LC_MESSAGES/default.mo Binary files differnew file mode 100644 index 000000000..de43713c4 --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/default.mo diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/default.po b/src/boost/libs/locale/test/he/LC_MESSAGES/default.po new file mode 100644 index 000000000..f79dfbd43 --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/default.po @@ -0,0 +1,35 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural= (n==1 ? 0 : (n==2 ? 1 : (n>10 ? 3 : 2))) ;\n" + +msgid "בדיקה" +msgstr "test" + +msgid "hello" +msgstr "שלום" + +msgid "#hello" +msgstr "#שלום" + +msgctxt "context" +msgid "hello" +msgstr "שלום בהקשר אחר" + +msgid "x day" +msgid_plural "x days" +msgstr[0] "יום x" +msgstr[1] "יומיים" +msgstr[2] "x ימים" +msgstr[3] "x יום" + +msgctxt "context" +msgid "x day" +msgid_plural "בהקשר x days" +msgstr[0] "בהקשר יום x" +msgstr[1] "בהקשר יומיים" +msgstr[2] "בהקשר x ימים" +msgstr[3] "בהקשר x יום" + diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/fall.mo b/src/boost/libs/locale/test/he/LC_MESSAGES/fall.mo Binary files differnew file mode 100644 index 000000000..ebc9a9ca2 --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/fall.mo diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/fall.po b/src/boost/libs/locale/test/he/LC_MESSAGES/fall.po new file mode 100644 index 000000000..5d3b6d28a --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/fall.po @@ -0,0 +1,10 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "test" +msgstr "he" + + diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/simple.mo b/src/boost/libs/locale/test/he/LC_MESSAGES/simple.mo Binary files differnew file mode 100644 index 000000000..54549c182 --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/simple.mo diff --git a/src/boost/libs/locale/test/he/LC_MESSAGES/simple.po b/src/boost/libs/locale/test/he/LC_MESSAGES/simple.po new file mode 100644 index 000000000..9120b7fbb --- /dev/null +++ b/src/boost/libs/locale/test/he/LC_MESSAGES/simple.po @@ -0,0 +1,23 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n!=1;\n" + +msgid "hello" +msgstr "היי" + +msgid "#hello" +msgstr "#היי" + +msgctxt "context" +msgid "hello" +msgstr "היי בהקשר אחר" + + +#: test_message.cpp:47 +msgid "test" +msgid_plural "tests" +msgstr[0] "" +msgstr[1] "" diff --git a/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.mo b/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.mo Binary files differnew file mode 100644 index 000000000..844f9d8d1 --- /dev/null +++ b/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.mo diff --git a/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.po b/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.po new file mode 100644 index 000000000..32dbdeaaf --- /dev/null +++ b/src/boost/libs/locale/test/he_IL/LC_MESSAGES/full.po @@ -0,0 +1,10 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "test" +msgstr "he_IL" + + diff --git a/src/boost/libs/locale/test/test_boundary.cpp b/src/boost/libs/locale/test/test_boundary.cpp new file mode 100644 index 000000000..56b62f243 --- /dev/null +++ b/src/boost/libs/locale/test/test_boundary.cpp @@ -0,0 +1,537 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_WITH_ICU +#include <iostream> +int main() +{ + std::cout << "ICU is not build... Skipping" << std::endl; +} +#else + +#define BOOST_LOCALE_ERROR_LIMIT 100000 + +#include <boost/locale/boundary.hpp> +#include <boost/locale/generator.hpp> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <list> +#include <unicode/uversion.h> + +// Debugging code + +template<typename Char> +void print_str(std::basic_string<Char> const &/*s*/) +{ +} + +template<> +void print_str<char>(std::basic_string<char> const &s) +{ + std::cout << "[" << s <<"]" << std::endl; +} + + +namespace lb = boost::locale::boundary; + +template<typename Char,typename Iterator> +void test_word_container(Iterator begin,Iterator end, + std::vector<int> const &ipos, + std::vector<int> const &imasks, + std::vector<std::basic_string<Char> > const &ichunks, + std::locale l, + lb::boundary_type bt=lb::word + ) +{ + for(int sm=(bt == lb::word ? 31 : 3 ) ;sm>=0;sm--) { + unsigned mask = + ((sm & 1 ) != 0) * 0xF + + ((sm & 2 ) != 0) * 0xF0 + + ((sm & 4 ) != 0) * 0xF00 + + ((sm & 8 ) != 0) * 0xF000 + + ((sm & 16) != 0) * 0xF0000; + + std::vector<int> masks,pos; + std::vector<unsigned> bmasks; + std::basic_string<Char> empty_chunk; + + std::vector<std::basic_string<Char> > chunks; + std::vector<std::basic_string<Char> > fchunks; + std::vector<Iterator> iters; + iters.push_back(begin); + bmasks.push_back(0); + + for(unsigned i=0;i<imasks.size();i++) { + if(imasks[i] & mask) { + masks.push_back(imasks[i]); + chunks.push_back(ichunks[i]); + fchunks.push_back(empty_chunk + ichunks[i]); + empty_chunk.clear(); + pos.push_back(ipos[i]); + } + else { + empty_chunk+=ichunks[i]; + } + + if((imasks[i] & mask) || i==imasks.size()-1){ + Iterator ptr=begin; + std::advance(ptr,ipos[i]); + iters.push_back(ptr); + bmasks.push_back(imasks[i]); + } + } + + // + // segment iterator tests + // + { + lb::segment_index<Iterator> map(bt,begin,end,l); + typedef typename lb::segment_index<Iterator>::iterator iter_type; + + map.rule(mask); + + { + unsigned i=0; + iter_type p; + map.full_select(false); + for(p=map.begin();p!=map.end();++p,i++) { + TEST(p->str()==chunks[i]); + TEST(p->rule() == unsigned(masks[i])); + } + + TEST(chunks.size() == i); + for(;;) { + if(p==map.begin()) { + TEST(i==0); + break; + } + else { + --p; + TEST(p->str()==chunks[--i]); + TEST(p->rule() == unsigned(masks[i])); + } + } + for(i=0,p=map.end();i<chunks.size();i++){ + --p; + unsigned index = chunks.size() - i - 1; + TEST(p->str()==chunks[index]); + TEST(p->rule() == unsigned(masks[index])); + } + TEST(p==map.begin()); + } + + { + unsigned i=0; + iter_type p; + map.full_select(true); + for(p=map.begin();p!=map.end();++p,i++) { + TEST(p->str()==fchunks[i]); + TEST(p->rule() == unsigned(masks[i])); + } + + TEST(chunks.size() == i); + + for(;;) { + if(p==map.begin()) { + TEST(i==0); + break; + } + else { + --p; + if(p->str()!=fchunks[i-1]) { + print_str(p->str()); + print_str(fchunks[i-1]); + } + TEST(p->str()==fchunks[--i]); + TEST(p->rule() == unsigned(masks[i])); + } + } + + for(i=0,p=map.end();i<chunks.size();i++){ + --p; + unsigned index = chunks.size() - i - 1; + TEST(p->str()==fchunks[index]); + TEST(p->rule() == unsigned(masks[index])); + } + TEST(p==map.begin()); + } + + { + iter_type p; + unsigned chunk_ptr=0; + unsigned i=0; + map.full_select(false); + for(Iterator optr=begin;optr!=end;optr++,i++) { + p=map.find(optr); + if(chunk_ptr < pos.size() && i>=unsigned(pos[chunk_ptr])){ + chunk_ptr++; + } + if(chunk_ptr>=pos.size()) { + TEST(p==map.end()); + } + else { + TEST(p->str()==chunks[chunk_ptr]); + TEST(p->rule()==unsigned(masks[chunk_ptr])); + } + } + } + { + iter_type p; + unsigned chunk_ptr=0; + unsigned i=0; + map.full_select(true); + for(Iterator optr=begin;optr!=end;optr++,i++) { + p=map.find(optr); + if(chunk_ptr < pos.size() && i>=unsigned(pos[chunk_ptr])){ + chunk_ptr++; + } + if(chunk_ptr>=pos.size()) { + TEST(p==map.end()); + } + else { + TEST(p->str()==fchunks[chunk_ptr]); + TEST(p->rule()==unsigned(masks[chunk_ptr])); + } + } + } + + } // segment iterator tests + + { // break iterator tests + lb::boundary_point_index<Iterator> map(bt,begin,end,l); + typedef typename lb::boundary_point_index<Iterator>::iterator iter_type; + + map.rule(mask); + + unsigned i=0; + iter_type p; + for(p=map.begin();p!=map.end();++p,i++) { + TEST(p->iterator()==iters[i]); + TEST(p->rule()==bmasks[i]); + } + + TEST(iters.size() == i); + + do { + --p; + --i; + TEST(p->iterator()==iters.at(i)); + } while(p!=map.begin()); + TEST(i==0); + + unsigned iters_ptr=0; + for(Iterator optr=begin;optr!=end;optr++) { + p=map.find(optr); + TEST(p->iterator()==iters[iters_ptr]); + if(iters.at(iters_ptr)==optr) + iters_ptr++; + } + + } // break iterator tests + + { // copy test + typedef lb::segment_index<Iterator> ti_type; + typedef lb::boundary_point_index<Iterator> bi_type; + { // segment to bound + ti_type ti(bt,begin,end,l); + ti.rule(mask); + { + bi_type bi(ti); + bi.rule(mask); + unsigned i=0; + typename bi_type::iterator p; + for(p=bi.begin();p!=bi.end();++p,i++) { + TEST(p->iterator()==iters[i]); + TEST(p->rule()==bmasks[i]); + } + } + { + bi_type bi; + bi.rule(mask); + bi = ti; + unsigned i=0; + typename bi_type::iterator p; + for(p=bi.begin();p!=bi.end();++p,i++) { + TEST(p->iterator()==iters[i]); + TEST(p->rule()==bmasks[i]); + } + } + // boundary_point to bound + bi_type bi_2(bt,begin,end,l); + bi_2.rule(mask); + { + bi_type bi(bi_2); + unsigned i=0; + typename bi_type::iterator p; + for(p=bi.begin();p!=bi.end();++p,i++) { + TEST(p->iterator()==iters[i]); + TEST(p->rule()==bmasks[i]); + } + } + { + bi_type bi; + bi = bi_2; + unsigned i=0; + typename bi_type::iterator p; + for(p=bi.begin();p!=bi.end();++p,i++) { + TEST(p->iterator()==iters[i]); + TEST(p->rule()==bmasks[i]); + } + } + } + { // boundary_point to segment + bi_type bi(bt,begin,end,l); + { + ti_type ti(bi); + ti.rule(mask); + unsigned i=0; + typename ti_type::iterator p; + for(p=ti.begin();p!=ti.end();++p,i++) { + TEST(p->str()==chunks[i]); + TEST(p->rule()==unsigned(masks[i])); + } + } + { + ti_type ti; + ti.rule(mask); + ti = (bi); + unsigned i=0; + typename ti_type::iterator p; + for(p=ti.begin();p!=ti.end();++p,i++) { + TEST(p->str()==chunks[i]); + TEST(p->rule()==unsigned(masks[i])); + } + } + ti_type ti_2(bt,begin,end,l); + ti_2.rule(mask); + { + ti_type ti(ti_2); + unsigned i=0; + typename ti_type::iterator p; + for(p=ti.begin();p!=ti.end();++p,i++) { + TEST(p->str()==chunks[i]); + TEST(p->rule()==unsigned(masks[i])); + } + } + { + ti_type ti; + ti = (ti_2); + unsigned i=0; + typename ti_type::iterator p; + for(p=ti.begin();p!=ti.end();++p,i++) { + TEST(p->str()==chunks[i]); + TEST(p->rule()==unsigned(masks[i])); + } + } + } + } + } // for mask + +} + +template<typename Char> +void run_word(std::string *original,int *none,int *num,int *word,int *kana,int *ideo,std::locale l,lb::boundary_type b=lb::word) +{ + std::vector<int> pos; + std::vector<std::basic_string<Char> > chunks; + std::vector<int> masks; + std::basic_string<Char> test_string; + for(int i=0;!original[i].empty();i++) { + chunks.push_back(to_correct_string<Char>(original[i],l)); + test_string+=chunks.back(); + pos.push_back(test_string.size()); + masks.push_back( + ( none ? none[i]*15 : 0) + | ( num ? ((num[i]*15) << 4) : 0) + | ( word ? ((word[i]*15) << 8) : 0) + | ( kana ? ((kana[i]*15) << 12) : 0) + | ( ideo ? ((ideo[i]*15) << 16) : 0) + ); + } + + std::list<Char> lst(test_string.begin(),test_string.end()); + test_word_container<Char>(lst.begin(),lst.end(),pos,masks,chunks,l,b); + test_word_container<Char>(test_string.begin(),test_string.end(),pos,masks,chunks,l,b); +} + +std::string character[]={"שָ","ל","וֹ","ם","!",""}; +int nones[]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + +std::string sentence1[]={"To be\n","or not\n","to be?\n"," That is the question. ","Or maybe not",""}; +int sentence1a[]={ 0, 0, 1, 1, 0, 0}; +int sentence1b[]={ 1, 1, 0, 0, 1, 0}; + +std::string line1[]={"To ","be\n","or ","not\n","to ","be",""}; +int line1a[]={ 1, 0, 1 , 0, 1, 1 , 0 }; +int line1b[]={ 0, 1, 0 , 1, 0, 0 , 0 }; + + +void test_boundaries(std::string *all,int *first,int *second,lb::boundary_type t) +{ + boost::locale::generator g; + std::cout << " char UTF-8" << std::endl; + run_word<char>(all,first,second,0,0,0,g("he_IL.UTF-8"),t); + std::cout << " char CP1255" << std::endl; + run_word<char>(all,first,second,0,0,0,g("he_IL.cp1255"),t); + std::cout << " wchar_t"<<std::endl; + run_word<wchar_t>(all,first,second,0,0,0,g("he_IL.UTF-8"),t); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << " char16_t"<<std::endl; + run_word<char16_t>(all,first,second,0,0,0,g("he_IL.UTF-8"),t); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << " char32_t"<<std::endl; + run_word<char32_t>(all,first,second,0,0,0,g("he_IL.UTF-8"),t); + #endif + +} + +void word_boundary() +{ + boost::locale::generator g; + //std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","ひらがな","ヒラガナ",""}; + //std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","ひん","アヒル",""}; + std::string all1[]={"10"," ","Hello"," ","Windows7"," ","平仮名","アヒル",""}; + int none1[]={ 0, 1, 0, 1, 0, 1, 0, 0, 0}; + int num1[]={ 1, 0, 0, 0, 1, 0, 0 , 0 , 0}; + int word1[]={ 0, 0, 1, 0, 1, 0, 0 , 0 , 0}; +#if U_ICU_VERSION_MAJOR_NUM >= 50 + int kana1[]={ 0, 0, 0, 0, 0, 0, 0, 0 , 0}; + int ideo1[]={ 0, 0, 0, 0, 0, 0, 1, 1 , 1}; +#else + int kana1[]={ 0, 0, 0, 0, 0, 0, 0, 1 , 1}; + int ideo1[]={ 0, 0, 0, 0, 0, 0, 1, 0 , 0}; +#endif + + + int zero[25]={0}; + std::string all2[]={""}; + + std::string all3[]={" "," ","Hello",",","World","!"," ",""}; + int none3[]={ 1, 1, 0, 1, 0, 1, 1, 0}; + int word3[]={ 0, 0, 1, 0, 1, 0, 0, 0}; + + std::cout << " char UTF-8" << std::endl; + run_word<char>(all1,none1,num1,word1,kana1,ideo1,g("ja_JP.UTF-8")); + run_word<char>(all2,zero,zero,zero,zero,zero,g("en_US.UTF-8")); + run_word<char>(all3,none3,zero,word3,zero,zero,g("en_US.UTF-8")); + + std::cout << " char Shift-JIS" << std::endl; + run_word<char>(all1,none1,num1,word1,kana1,ideo1,g("ja_JP.Shift-JIS")); + run_word<char>(all2,zero,zero,zero,zero,zero,g("ja_JP.Shift-JIS")); + run_word<char>(all3,none3,zero,word3,zero,zero,g("ja_JP.Shift-JIS")); + + std::cout << " wchar_t"<<std::endl; + run_word<wchar_t>(all1,none1,num1,word1,kana1,ideo1,g("ja_JP.UTF-8")); + run_word<wchar_t>(all2,zero,zero,zero,zero,zero,g("en_US.UTF-8")); + run_word<wchar_t>(all3,none3,zero,word3,zero,zero,g("en_US.UTF-8")); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << " char16_t"<<std::endl; + run_word<char16_t>(all1,none1,num1,word1,kana1,ideo1,g("ja_JP.UTF-8")); + run_word<char16_t>(all2,zero,zero,zero,zero,zero,g("en_US.UTF-8")); + run_word<char16_t>(all3,none3,zero,word3,zero,zero,g("en_US.UTF-8")); + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << " char32_t"<<std::endl; + run_word<char32_t>(all1,none1,num1,word1,kana1,ideo1,g("ja_JP.UTF-8")); + run_word<char32_t>(all2,zero,zero,zero,zero,zero,g("en_US.UTF-8")); + run_word<char32_t>(all3,none3,zero,word3,zero,zero,g("en_US.UTF-8")); + #endif +} +void test_op_one_side(std::string const &sl,std::string const &sr,int val) +{ + boost::locale::boundary::ssegment l(sl.begin(),sl.end(),0),r(sr.begin(),sr.end(),0); + + // segment + TEST( (l==r) == (val==0)); + TEST( (l!=r) == (val!=0)); + TEST( (l<=r) == (val<=0)); + TEST( (l< r) == (val<0)); + TEST( (l>=r) == (val>=0)); + TEST( (l> r) == (val>0)); + + // C string + TEST( (l==sr.c_str()) == (val==0)); + TEST( (l!=sr.c_str()) == (val!=0)); + TEST( (l<=sr.c_str()) == (val<=0)); + TEST( (l< sr.c_str()) == (val<0)); + TEST( (l>=sr.c_str()) == (val>=0)); + TEST( (l> sr.c_str()) == (val>0)); + + TEST( (sl.c_str()==r) == (val==0)); + TEST( (sl.c_str()!=r) == (val!=0)); + TEST( (sl.c_str()<=r) == (val<=0)); + TEST( (sl.c_str()< r) == (val<0)); + TEST( (sl.c_str()>=r) == (val>=0)); + TEST( (sl.c_str()> r) == (val>0)); + + + // C++ string + TEST( (l==sr) == (val==0)); + TEST( (l!=sr) == (val!=0)); + TEST( (l<=sr) == (val<=0)); + TEST( (l< sr) == (val<0)); + TEST( (l>=sr) == (val>=0)); + TEST( (l> sr) == (val>0)); + + TEST( (sl==r) == (val==0)); + TEST( (sl!=r) == (val!=0)); + TEST( (sl<=r) == (val<=0)); + TEST( (sl< r) == (val<0)); + TEST( (sl>=r) == (val>=0)); + TEST( (sl> r) == (val>0)); + // self check + TEST( (sl==sr) == (val==0)); + TEST( (sl!=sr) == (val!=0)); + TEST( (sl<=sr) == (val<=0)); + TEST( (sl< sr) == (val<0)); + TEST( (sl>=sr) == (val>=0)); + TEST( (sl> sr) == (val>0)); + +} + +void test_op(std::string const &sl,std::string const &sr,int val) +{ + test_op_one_side(sl,sr,val); + test_op_one_side(sr,sl,-val); +} +void segment_operator() +{ + test_op("","a",-1); + test_op("","",0); + test_op("aa","aaa",-1); + test_op("aa","ab",-1); +} + +int main() +{ + try { + std::cout << "Testing segment operators" << std::endl; + segment_operator(); + std::cout << "Testing word boundary" << std::endl; + word_boundary(); + std::cout << "Testing character boundary" << std::endl; + test_boundaries(character,nones,0,lb::character); + std::cout << "Testing sentence boundary" << std::endl; + test_boundaries(sentence1,sentence1a,sentence1b,lb::sentence); + std::cout << "Testing line boundary" << std::endl; + test_boundaries(line1,line1a,line1b,lb::line); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); +} + +#endif // NOICU +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_codecvt.cpp b/src/boost/libs/locale/test/test_codecvt.cpp new file mode 100644 index 000000000..026a5aeaa --- /dev/null +++ b/src/boost/libs/locale/test/test_codecvt.cpp @@ -0,0 +1,283 @@ +// +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include <boost/locale/utf8_codecvt.hpp> +#include <locale> +#include <iostream> +#include <iomanip> +#include <string.h> +#include <wchar.h> +#include <memory.h> +#define BOOST_LOCALE_ERROR_LIMIT -1 +#include "test_locale.hpp" + +static char const *utf8_name = "\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt"; +static wchar_t const *wide_name = L"\U0001D49E-\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042.txt"; + +char const *res(std::codecvt_base::result r) +{ + switch(r){ + case std::codecvt_base::ok: return "ok"; + case std::codecvt_base::partial: return "partial"; + case std::codecvt_base::error: return "error"; + case std::codecvt_base::noconv: return "noconv"; + default: + return "error"; + } +} + +typedef std::codecvt<wchar_t,char,std::mbstate_t> cvt_type; + +void test_codecvt_in_n_m(cvt_type const &cvt,int n,int m) +{ + wchar_t const *wptr = wide_name; + int wlen = wcslen(wide_name); + int u8len = strlen(utf8_name); + char const *from = utf8_name; + char const *end = from; + char const *real_end = utf8_name + u8len; + char const *from_next = from; + std::mbstate_t mb=std::mbstate_t(); + while(from_next < real_end) { + if(from == end) { + end = from + n; + if(end > real_end) + end = real_end; + } + + wchar_t buf[128]; + wchar_t *to = buf; + wchar_t *to_end = to + m; + wchar_t *to_next = to; + + + std::mbstate_t mb2 = mb; + std::codecvt_base::result r = cvt.in(mb,from,end,from_next,to,to_end,to_next); + //std::cout << "In from_size=" << (end-from) << " from move=" << (from_next - from) << " to move= " << to_next - to << " state = " << res(r) << std::endl; + + int count = cvt.length(mb2,from,end,to_end - to); + #ifndef BOOST_LOCALE_DO_LENGTH_MBSTATE_CONST + TEST(memcmp(&mb,&mb2,sizeof(mb))==0); + if(count != from_next - from) { + std::cout << count << " " << from_next - from << std::endl; + } + TEST(count == from_next - from); + #else + TEST(count == to_next - to); + #endif + + + if(r == cvt_type::partial) { + end+=n; + if(end > real_end) + end = real_end; + } + else + TEST(r == cvt_type::ok); + while(to!=to_next) { + TEST(*wptr == *to); + wptr++; + to++; + } + to=to_next; + from = from_next; + } + TEST(wptr == wide_name + wlen); + TEST(from == real_end); + +} + +void test_codecvt_out_n_m(cvt_type const &cvt,int n,int m) +{ + char const *nptr = utf8_name; + int wlen = wcslen(wide_name); + int u8len = strlen(utf8_name); + + std::mbstate_t mb=std::mbstate_t(); + + wchar_t const *from_next = wide_name; + wchar_t const *real_from_end = wide_name + wlen; + + char buf[256]; + char *to = buf; + char *to_next = to; + char *to_end = to + n; + char *real_to_end = buf + sizeof(buf); + + while(from_next < real_from_end) { + wchar_t const *from = from_next; + wchar_t const *from_end = from + m; + if(from_end > real_from_end) + from_end = real_from_end; + if(to_end == to) { + to_end = to+n; + } + + std::codecvt_base::result r = cvt.out(mb,from,from_end,from_next,to,to_end,to_next); + //std::cout << "In from_size=" << (end-from) << " from move=" << (from_next - from) << " to move= " << to_next - to << " state = " << res(r) << std::endl; + if(r == cvt_type::partial) { + TEST(to_end - to_next < cvt.max_length()); + to_end += n; + if(to_end > real_to_end) + to_end = real_to_end; + } + else { + TEST(r == cvt_type::ok); + } + + while(to!=to_next) { + TEST(*nptr == *to); + nptr++; + to++; + } + from = from_next; + } + TEST(nptr == utf8_name + u8len); + TEST(from_next == real_from_end); + TEST(cvt.unshift(mb,to,to+n,to_next)==cvt_type::ok); + TEST(to_next == to); + +} + + +void test_codecvt_conv() +{ + std::cout << "Conversions " << std::endl; + std::locale l(std::locale::classic(),new boost::locale::utf8_codecvt<wchar_t>()); + + cvt_type const &cvt = std::use_facet<cvt_type>(l); + + TEST(cvt.max_length()==4); + + for(int i=1;i<=(int)strlen(utf8_name)+1;i++) { + for(int j=1;j<=(int)wcslen(wide_name)+1;j++) { + try { + test_codecvt_in_n_m(cvt,i,j); + test_codecvt_out_n_m(cvt,i,j); + } + catch(...) { + std::cerr << "Wlen=" <<j << " Nlen=" << i << std::endl; + throw; + } + } + } +} + +void test_codecvt_err() +{ + std::cout << "Errors " << std::endl; + std::locale l(std::locale::classic(),new boost::locale::utf8_codecvt<wchar_t>()); + + cvt_type const &cvt = std::use_facet<cvt_type>(l); + + std::cout << "- UTF-8" << std::endl; + { + + wchar_t buf[2]; + wchar_t *to=buf; + wchar_t *to_end = buf+2; + wchar_t *to_next = to; + char const *err_utf="1\xFF\xFF"; + { + std::mbstate_t mb=std::mbstate_t(); + char const *from=err_utf; + char const *from_end = from + strlen(from); + char const *from_next = from; + to_next = to; + TEST(cvt.in(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::error); + TEST(from_next == from+1); + TEST(to_next == to + 1); + TEST(*to == '1'); + } + err_utf++; + { + std::mbstate_t mb=std::mbstate_t(); + char const *from=err_utf; + char const *from_end = from + strlen(from); + char const *from_next = from; + TEST(cvt.in(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::error); + TEST(from_next == from); + TEST(to_next == to); + } + } + + std::cout << "- UTF-16/32" << std::endl; + { + + char buf[32]; + char *to=buf; + char *to_end = buf+32; + char *to_next = to; + wchar_t err_buf[3] = { '1' , 0xDC9E }; // second surrogate not works both for UTF-16 and 32 + wchar_t const *err_utf = err_buf; + { + std::mbstate_t mb=std::mbstate_t(); + wchar_t const *from=err_utf; + wchar_t const *from_end = from + wcslen(from); + wchar_t const *from_next = from; + TEST(cvt.out(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::error); + TEST(from_next == from+1); + TEST(to_next == to + 1); + TEST(*to == '1'); + } + err_utf++; + { + std::mbstate_t mb=std::mbstate_t(); + wchar_t const *from=err_utf; + wchar_t const *from_end = from + wcslen(from); + wchar_t const *from_next = from; + to_next = to; + TEST(cvt.out(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::error); + TEST(from_next == from); + TEST(to_next == to); + } + } + +} + + +void test_char_char() +{ + std::cout << "Char-char specialization"<<std::endl; + std::locale l(std::locale::classic(),new boost::locale::utf8_codecvt<char>()); + std::codecvt<char,char,std::mbstate_t> const &cvt=std::use_facet<std::codecvt<char,char,std::mbstate_t> >(l); + std::mbstate_t mb=std::mbstate_t(); + char const *from = "a"; + char const *from_end = from+1; + char const *from_next = from; + char buf[2]; + char *to = buf; + char *to_end = buf+1; + char *to_next = to; + TEST(cvt.always_noconv()==true); + TEST(cvt.in(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::noconv); + TEST(from_next == from); + TEST(to_next == to); + TEST(cvt.out(mb,from,from_end,from_next,to,to_end,to_next)==cvt_type::noconv); + TEST(from_next == from); + TEST(to_next == to); + TEST(cvt.encoding()==1); + TEST(cvt.max_length()==1); +} + +int main() +{ + try { + test_codecvt_conv(); + test_codecvt_err(); + test_char_char(); + + } + catch(std::exception const &e) { + std::cerr << "Failed : " << e.what() << std::endl; + return 1; + } + std::cout << "Ok" << std::endl; + return 0; +} +/// +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/test/test_codepage.cpp b/src/boost/libs/locale/test/test_codepage.cpp new file mode 100644 index 000000000..389c811eb --- /dev/null +++ b/src/boost/libs/locale/test/test_codepage.cpp @@ -0,0 +1,517 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/locale/encoding.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/info.hpp> +#include <boost/locale/config.hpp> +#include <fstream> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" + + +#ifndef BOOST_LOCALE_NO_POSIX_BACKEND +# ifdef __APPLE__ +# include <xlocale.h> +# endif +# include <locale.h> +#endif + +#if !defined(BOOST_LOCALE_WITH_ICU) && !defined(BOOST_LOCALE_WITH_ICONV) && (defined(BOOST_WINDOWS) || defined(__CYGWIN__)) +#ifndef NOMINMAX +# define NOMINMAX +#endif +#include <windows.h> +#endif + + +bool test_iso; +bool test_iso_8859_8 = true; +bool test_utf; +bool test_sjis; + +std::string he_il_8bit; +std::string en_us_8bit; +std::string ja_jp_shiftjis; + + +template<typename Char> +std::basic_string<Char> read_file(std::basic_istream<Char> &in) +{ + std::basic_string<Char> res; + Char c; + while(in.get(c)) + res+=c; + return res; +} + + +template<typename Char> +void test_ok(std::string file,std::locale const &l,std::basic_string<Char> cmp=std::basic_string<Char>()) +{ + if(cmp.empty()) + cmp=to<Char>(file); + std::ofstream test("testi.txt"); + test << file; + test.close(); + typedef std::basic_fstream<Char> stream_type; + + stream_type f1("testi.txt",stream_type::in); + f1.imbue(l); + TEST(read_file<Char>(f1) == cmp); + f1.close(); + + stream_type f2("testo.txt",stream_type::out); + f2.imbue(l); + f2 << cmp; + f2.close(); + + std::ifstream testo("testo.txt"); + TEST(read_file<char>(testo) == file); +} + +template<typename Char> +void test_rfail(std::string file,std::locale const &l,int pos) +{ + std::ofstream test("testi.txt"); + test << file; + test.close(); + typedef std::basic_fstream<Char> stream_type; + + stream_type f1("testi.txt",stream_type::in); + f1.imbue(l); + Char c; + for(int i=0;i<pos;i++) { + f1.get(c); + if(f1.fail()) { // failed before as detected errors at forward; + return; + } + TEST(f1); + } + // if the pos above suceed, at this point + // it MUST fail + TEST(f1.get(c).fail()); +} + +template<typename Char> +void test_wfail(std::string file,std::locale const &l,int pos) +{ + typedef std::basic_fstream<Char> stream_type; + stream_type f1("testo.txt",stream_type::out); + f1.imbue(l); + std::basic_string<Char> out=to<Char>(file); + int i; + for(i=0;i<pos;i++) { + f1 << out.at(i); + f1<<std::flush; + TEST(f1.good()); + } + f1 << out.at(i); + TEST(f1.fail() || (f1<<std::flush).fail()); +} + + +template<typename Char> +void test_for_char() +{ + boost::locale::generator g; + if(test_utf) { + std::cout << " UTF-8" << std::endl; + test_ok<Char>("grüße\nn i",g("en_US.UTF-8")); + test_rfail<Char>("abc\xFF\xFF",g("en_US.UTF-8"),3); + std::cout << " Testing codepoints above 0xFFFF" << std::endl; + std::cout << " Single U+2008A" << std::endl; + test_ok<Char>("\xf0\xa0\x82\x8a",g("en_US.UTF-8")); // U+2008A + std::cout << " Single U+2008A withing text" << std::endl; + test_ok<Char>("abc\"\xf0\xa0\x82\x8a\"",g("en_US.UTF-8")); // U+2008A + std::string one = "\xf0\xa0\x82\x8a"; + std::string res; + for(unsigned i=0;i<1000;i++) + res+=one; + std::cout << " U+2008A x 1000" << std::endl; + test_ok<Char>(res.c_str(),g("en_US.UTF-8")); // U+2008A + } + else { + std::cout << " UTF-8 Not supported " << std::endl; + } + + if(test_iso) { + if(test_iso_8859_8) { + std::cout << " ISO8859-8" << std::endl; + test_ok<Char>("hello \xf9\xec\xe5\xed",g(he_il_8bit),to<Char>("hello שלום")); + } + std::cout << " ISO8859-1" << std::endl; + test_ok<Char>(to<char>("grüße\nn i"),g(en_us_8bit),to<Char>("grüße\nn i")); + test_wfail<Char>("grüßen שלום",g(en_us_8bit),7); + } + + if(test_sjis) { + std::cout << " Shift-JIS" << std::endl; + test_ok<Char>("\x93\xfa\x96\x7b",g(ja_jp_shiftjis), + boost::locale::conv::to_utf<Char>("\xe6\x97\xa5\xe6\x9c\xac","UTF-8")); // Japan + } +} +void test_wide_io() +{ + std::cout << " wchar_t" << std::endl; + test_for_char<wchar_t>(); + + #if defined BOOST_LOCALE_ENABLE_CHAR16_T && !defined(BOOST_NO_CHAR16_T_CODECVT) + std::cout << " char16_t" << std::endl; + test_for_char<char16_t>(); + #endif + #if defined BOOST_LOCALE_ENABLE_CHAR32_T && !defined(BOOST_NO_CHAR32_T_CODECVT) + std::cout << " char32_t" << std::endl; + test_for_char<char32_t>(); + #endif +} + +template<typename Char> +void test_pos(std::string source,std::basic_string<Char> target,std::string encoding) +{ + using namespace boost::locale::conv; + boost::locale::generator g; + std::locale l= encoding == "ISO8859-8" ? g("he_IL."+encoding) : g("en_US."+encoding); + TEST(to_utf<Char>(source,encoding)==target); + TEST(to_utf<Char>(source.c_str(),encoding)==target); + TEST(to_utf<Char>(source.c_str(),source.c_str()+source.size(),encoding)==target); + + TEST(to_utf<Char>(source,l)==target); + TEST(to_utf<Char>(source.c_str(),l)==target); + TEST(to_utf<Char>(source.c_str(),source.c_str()+source.size(),l)==target); + + TEST(from_utf<Char>(target,encoding)==source); + TEST(from_utf<Char>(target.c_str(),encoding)==source); + TEST(from_utf<Char>(target.c_str(),target.c_str()+target.size(),encoding)==source); + + TEST(from_utf<Char>(target,l)==source); + TEST(from_utf<Char>(target.c_str(),l)==source); + TEST(from_utf<Char>(target.c_str(),target.c_str()+target.size(),l)==source); +} + +#define TESTF(X) TEST_THROWS(X,boost::locale::conv::conversion_error) + +template<typename Char> +void test_to_neg(std::string source,std::basic_string<Char> target,std::string encoding) +{ + using namespace boost::locale::conv; + boost::locale::generator g; + std::locale l=g("en_US."+encoding); + + TEST(to_utf<Char>(source,encoding)==target); + TEST(to_utf<Char>(source.c_str(),encoding)==target); + TEST(to_utf<Char>(source.c_str(),source.c_str()+source.size(),encoding)==target); + TEST(to_utf<Char>(source,l)==target); + TEST(to_utf<Char>(source.c_str(),l)==target); + TEST(to_utf<Char>(source.c_str(),source.c_str()+source.size(),l)==target); + + TESTF(to_utf<Char>(source,encoding,stop)); + TESTF(to_utf<Char>(source.c_str(),encoding,stop)); + TESTF(to_utf<Char>(source.c_str(),source.c_str()+source.size(),encoding,stop)); + TESTF(to_utf<Char>(source,l,stop)); + TESTF(to_utf<Char>(source.c_str(),l,stop)); + TESTF(to_utf<Char>(source.c_str(),source.c_str()+source.size(),l,stop)); +} + +template<typename Char> +void test_from_neg(std::basic_string<Char> source,std::string target,std::string encoding) +{ + using namespace boost::locale::conv; + boost::locale::generator g; + std::locale l=g("en_US."+encoding); + + TEST(from_utf<Char>(source,encoding)==target); + TEST(from_utf<Char>(source.c_str(),encoding)==target); + TEST(from_utf<Char>(source.c_str(),source.c_str()+source.size(),encoding)==target); + TEST(from_utf<Char>(source,l)==target); + TEST(from_utf<Char>(source.c_str(),l)==target); + TEST(from_utf<Char>(source.c_str(),source.c_str()+source.size(),l)==target); + + TESTF(from_utf<Char>(source,encoding,stop)); + TESTF(from_utf<Char>(source.c_str(),encoding,stop)); + TESTF(from_utf<Char>(source.c_str(),source.c_str()+source.size(),encoding,stop)); + TESTF(from_utf<Char>(source,l,stop)); + TESTF(from_utf<Char>(source.c_str(),l,stop)); + TESTF(from_utf<Char>(source.c_str(),source.c_str()+source.size(),l,stop)); +} + +template<typename Char> +std::basic_string<Char> utf(char const *s) +{ + return to<Char>(s); +} + +template<> +std::basic_string<char> utf(char const *s) +{ + return s; +} + +template<typename Char> +void test_with_0() +{ + std::string a("abc\0\0 yz\0",3+2+3+1); + TEST(boost::locale::conv::from_utf<Char>(boost::locale::conv::to_utf<Char>(a,"UTF-8"),"UTF-8") == a); + TEST(boost::locale::conv::from_utf<Char>(boost::locale::conv::to_utf<Char>(a,"ISO8859-1"),"ISO8859-1") == a); +} + +template<typename Char,int n=sizeof(Char)> +struct utfutf; + +template<> +struct utfutf<char,1> { + static char const *ok() {return "grüßen";} + static char const *bad() { return "gr\xFF" "üßen"; } + // split into 2 to make SunCC happy +}; + +template<> +struct utfutf<wchar_t,2> { + static wchar_t const *ok(){ return L"\x67\x72\xfc\xdf\x65\x6e"; } + static wchar_t const *bad() { + static wchar_t buf[256] = L"\x67\x72\xFF\xfc\xFE\xFD\xdf\x65\x6e"; + buf[2]=0xDC01; // second surrogate must not be + buf[4]=0xD801; // First + buf[5]=0xD801; // Must be surrogate trail + return buf; + } +}; +template<> +struct utfutf<wchar_t,4> { + static wchar_t const *ok(){ return L"\x67\x72\xfc\xdf\x65\x6e"; } + static wchar_t const *bad() { + static wchar_t buf[256] = L"\x67\x72\xFF\xfc\xdf\x65\x6e"; + buf[2]=static_cast<wchar_t>(0x1000000); // > 10FFFF + return buf; + } +}; + + +template<typename CharOut,typename CharIn> +void test_combinations() +{ + using boost::locale::conv::utf_to_utf; + typedef utfutf<CharOut> out; + typedef utfutf<CharIn> in; + TEST( (utf_to_utf<CharOut,CharIn>(in::ok())==out::ok()) ); + TESTF( (utf_to_utf<CharOut,CharIn>(in::bad(),boost::locale::conv::stop)) ); + TEST( (utf_to_utf<CharOut,CharIn>(in::bad())==out::ok()) ); +} + +void test_all_combinations() +{ + std::cout << "Testing utf_to_utf" << std::endl; + std::cout <<" char<-char"<<std::endl; + test_combinations<char,char>(); + std::cout <<" char<-wchar"<<std::endl; + test_combinations<char,wchar_t>(); + std::cout <<" wchar<-char"<<std::endl; + test_combinations<wchar_t,char>(); + std::cout <<" wchar<-wchar"<<std::endl; + test_combinations<wchar_t,wchar_t>(); +} + +template<typename Char> +void test_to() +{ + test_pos<Char>(to<char>("grüßen"),utf<Char>("grüßen"),"ISO8859-1"); + if(test_iso_8859_8) + test_pos<Char>("\xf9\xec\xe5\xed",utf<Char>("שלום"),"ISO8859-8"); + test_pos<Char>("grüßen",utf<Char>("grüßen"),"UTF-8"); + test_pos<Char>("abc\"\xf0\xa0\x82\x8a\"",utf<Char>("abc\"\xf0\xa0\x82\x8a\""),"UTF-8"); + + test_to_neg<Char>("g\xFFrüßen",utf<Char>("grüßen"),"UTF-8"); + test_from_neg<Char>(utf<Char>("hello שלום"),"hello ","ISO8859-1"); + + test_with_0<Char>(); +} + + +void test_skip(char const *enc,char const *utf,char const *name,char const *opt=0) +{ + if(opt!=0) { + if(boost::locale::conv::to_utf<char>(enc,name) == opt) { + test_skip(enc,opt,name); + return; + } + } + TEST(boost::locale::conv::to_utf<char>(enc,name) == utf); + TEST(boost::locale::conv::to_utf<wchar_t>(enc,name) == boost::locale::conv::utf_to_utf<wchar_t>(utf)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + TEST(boost::locale::conv::to_utf<char16_t>(enc,name) == boost::locale::conv::utf_to_utf<char16_t>(utf)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + TEST(boost::locale::conv::to_utf<char32_t>(enc,name) == boost::locale::conv::utf_to_utf<char32_t>(utf)); + #endif +} + +void test_simple_conversions() +{ + namespace blc=boost::locale::conv; + std::cout << "- Testing correct invalid bytes skipping" << std::endl; + try { + std::cout << "-- ISO-8859-8" << std::endl; + test_skip("test \xE0\xE1\xFB-","test \xd7\x90\xd7\x91-","ISO-8859-8"); + test_skip("\xFB","","ISO-8859-8"); + test_skip("test \xE0\xE1\xFB","test \xd7\x90\xd7\x91","ISO-8859-8"); + test_skip("\xFB-","-","ISO-8859-8"); + } + catch(blc::invalid_charset_error const &) { + std::cout <<"--- not supported" << std::endl; + } + try { + std::cout << "-- cp932" << std::endl; + test_skip("test\xE0\xA0 \x83\xF8-","test\xe7\x87\xbf -","cp932","test\xe7\x87\xbf "); + test_skip("\x83\xF8","","cp932"); + test_skip("test\xE0\xA0 \x83\xF8","test\xe7\x87\xbf ","cp932"); + test_skip("\x83\xF8-","-","cp932",""); + } + catch(blc::invalid_charset_error const &) { + std::cout <<"--- not supported" << std::endl; + } +} + + +int main() +{ + try { + std::vector<std::string> def; + #ifdef BOOST_LOCALE_WITH_ICU + def.push_back("icu"); + #endif + #ifndef BOOST_LOCALE_NO_STD_BACKEND + def.push_back("std"); + #endif + #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND + def.push_back("winapi"); + #endif + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + def.push_back("posix"); + #endif + + #if !defined(BOOST_LOCALE_WITH_ICU) && !defined(BOOST_LOCALE_WITH_ICONV) && (defined(BOOST_WINDOWS) || defined(__CYGWIN__)) + test_iso_8859_8 = IsValidCodePage(28598)!=0; + #endif + + test_simple_conversions(); + + + for(int type = 0; type < int(def.size()); type ++ ) { + boost::locale::localization_backend_manager tmp_backend = boost::locale::localization_backend_manager::global(); + tmp_backend.select(def[type]); + boost::locale::localization_backend_manager::global(tmp_backend); + + std::string bname = def[type]; + + if(bname=="std") { + en_us_8bit = get_std_name("en_US.ISO8859-1"); + he_il_8bit = get_std_name("he_IL.ISO8859-8"); + ja_jp_shiftjis = get_std_name("ja_JP.SJIS"); + if(!ja_jp_shiftjis.empty() && !test_std_supports_SJIS_codecvt(ja_jp_shiftjis)) + { + std::cout << "Warning: detected unproper support of " << ja_jp_shiftjis << " locale, disableling it" << std::endl; + ja_jp_shiftjis = ""; + } + } + else { + en_us_8bit = "en_US.ISO8859-1"; + he_il_8bit = "he_IL.ISO8859-8"; + ja_jp_shiftjis = "ja_JP.SJIS"; + } + + std::cout << "Testing for backend " << def[type] << std::endl; + + test_iso = true; + if(bname=="std" && (he_il_8bit.empty() || en_us_8bit.empty())) { + std::cout << "no iso locales availible, passing" << std::endl; + test_iso = false; + } + test_sjis = true; + if(bname=="std" && ja_jp_shiftjis.empty()) { + test_sjis = false; + } + if(bname=="winapi") { + test_iso = false; + test_sjis = false; + } + test_utf = true; + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + if(bname=="posix") { + { + locale_t l = newlocale(LC_ALL_MASK,he_il_8bit.c_str(),0); + if(!l) + test_iso = false; + else + freelocale(l); + } + { + locale_t l = newlocale(LC_ALL_MASK,en_us_8bit.c_str(),0); + if(!l) + test_iso = false; + else + freelocale(l); + } + { + locale_t l = newlocale(LC_ALL_MASK,"en_US.UTF-8",0); + if(!l) + test_utf = false; + else + freelocale(l); + } + #ifdef BOOST_LOCALE_WITH_ICONV + { + locale_t l = newlocale(LC_ALL_MASK,ja_jp_shiftjis.c_str(),0); + if(!l) + test_sjis = false; + else + freelocale(l); + } + #else + test_sjis = false; + #endif + } + #endif + + if(def[type]=="std" && (get_std_name("en_US.UTF-8").empty() || get_std_name("he_IL.UTF-8").empty())) + { + test_utf = false; + } + + std::cout << "Testing wide I/O" << std::endl; + test_wide_io(); + std::cout << "Testing charset to/from UTF conversion functions" << std::endl; + std::cout << " char" << std::endl; + test_to<char>(); + std::cout << " wchar_t" << std::endl; + test_to<wchar_t>(); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(bname == "icu" || bname == "std") { + std::cout << " char16_t" << std::endl; + test_to<char16_t>(); + } + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(bname == "icu" || bname == "std") { + std::cout << " char32_t" << std::endl; + test_to<char32_t>(); + } + #endif + + test_all_combinations(); + } + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_codepage_converter.cpp b/src/boost/libs/locale/test/test_codepage_converter.cpp new file mode 100644 index 000000000..a246b2923 --- /dev/null +++ b/src/boost/libs/locale/test/test_codepage_converter.cpp @@ -0,0 +1,323 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <boost/locale/util.hpp> +#ifdef BOOST_LOCALE_WITH_ICU +#include "../src/icu/codecvt.hpp" +#endif +#if defined(BOOST_LOCALE_WITH_ICONV) && !defined(BOOST_LOCALE_NO_POSIX_BACKEND) +#include "../src/posix/codecvt.hpp" +#endif + +#include <string.h> + +char *make2(unsigned v) +{ + static unsigned char buf[3] = {0}; + buf[0] = 0xC0 | (v >> 6); + buf[1] = 0x80 | (v & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +char *make3(unsigned v) +{ + static unsigned char buf[4] = {0}; + buf[0] = 0xE0 | ((v >> 12) ) ; + buf[1] = 0x80 | ((v >> 6) & 0x3F ); + buf[2] = 0x80 | ((v >> 0) & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +char *make4(unsigned v) +{ + static unsigned char buf[5] = {0}; + buf[0] = 0xF0 | ((v >> 18) ) ; + buf[1] = 0x80 | ((v >> 12) & 0x3F ); + buf[2] = 0x80 | ((v >> 6) & 0x3F ); + buf[3] = 0x80 | ((v >> 0) & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +static const unsigned illegal=0xFFFFFFFF; +static const unsigned incomplete=0xFFFFFFFE; + + +bool test_to(boost::locale::util::base_converter &cvt,char const *s,unsigned codepoint) +{ + size_t len = strlen(s); + char const *end = s + len; + return cvt.to_unicode(s,end) == codepoint; +} + +bool test_from(boost::locale::util::base_converter &cvt,unsigned codepoint,char const *str) +{ + char buf[32]; + unsigned res = cvt.from_unicode(codepoint,buf,buf+sizeof(buf)); + if(res == boost::locale::util::base_converter::illegal) { + return str == 0; + } + else { + return str!=0 && strlen(str) == res && memcmp(str,buf,res) == 0; + } +} + +bool test_incomplete(boost::locale::util::base_converter &cvt,unsigned codepoint,int len) +{ + char buf[32]; + unsigned res = cvt.from_unicode(codepoint,buf,buf+len); + return res == incomplete; +} + + + +#define TEST_TO(str,codepoint) TEST(test_to(*cvt,str,codepoint)) +#define TEST_FROM(str,codepoint) TEST(test_from(*cvt,codepoint,str)) +#define TEST_INC(codepoint,len) TEST(test_incomplete(*cvt,codepoint,len)) + +void test_shiftjis(boost::locale::util::base_converter* pcvt) +{ + boost::locale::hold_ptr<boost::locale::util::base_converter> cvt(pcvt); + + std::cout << "- Correct" << std::endl; + TEST_TO("a",'a'); + TEST_TO("X",'X'); + TEST_TO("\xCB",0xFF8b); // half width katakana Hi ヒ + TEST_TO("\x83\x71",0x30d2); // Full width katakana Hi ヒ + TEST_TO("\x82\xd0",0x3072); // Full width hiragana Hi ひ + + TEST_FROM("a",'a'); + TEST_FROM("X",'X'); + TEST_FROM("\xCB",0xFF8b); // half width katakana Hi ヒ + TEST_FROM("\x83\x71",0x30d2); // Full width katakana Hi ヒ + TEST_FROM("\x82\xd0",0x3072); // Full width hiragana Hi ひ + + std::cout << "- Illegal/incomplete" << std::endl; + + TEST_TO("\xa0",illegal); + TEST_TO("\x82",incomplete); + TEST_TO("\x83\xf0",illegal); + + TEST_INC(0x30d2,1); // Full width katakana Hi ヒ + TEST_INC(0x3072,1); // Full width hiragana Hi ひ + + TEST_FROM(0,0x5e9); // Hebrew ש not in ShiftJIS +} + + +int main() +{ + try { + using namespace boost::locale::util; + + #ifndef BOOST_NO_CXX11_SMART_PTR + std::unique_ptr<base_converter> cvt; + #else + std::auto_ptr<base_converter> cvt; + #endif + + std::cout << "Test UTF-8" << std::endl; + std::cout << "- From UTF-8" << std::endl; + + + #ifndef BOOST_NO_CXX11_SMART_PTR + cvt = std::move(create_utf8_converter_unique_ptr()); + #else + cvt = create_utf8_converter(); + #endif + + TEST(cvt.get()); + TEST(cvt->is_thread_safe()); + TEST(cvt->max_len() == 4); + + std::cout << "-- Correct" << std::endl; + + TEST_TO("\x7f",0x7f); + TEST_TO("\xC2\x80",0x80); + TEST_TO("\xdf\xBF",0x7FF); + TEST_TO("\xe0\xa0\x80",0x800); + TEST_TO("\xef\xbf\xbf",0xFFFF); + TEST_TO("\xf0\x90\x80\x80",0x10000); + TEST_TO("\xf4\x8f\xbf\xbf",0x10FFFF); + + std::cout << "-- Too big" << std::endl; + TEST_TO("\xf4\x9f\x80\x80",illegal); // 11 0000 + TEST_TO("\xfb\xbf\xbf\xbf",illegal); // 3FF FFFF + TEST_TO("\xf8\x90\x80\x80\x80",illegal); // 400 0000 + TEST_TO("\xfd\xbf\xbf\xbf\xbf\xbf",illegal); // 7fff ffff + + std::cout << "-- Invalid trail" << std::endl; + TEST_TO("\xC2\x7F",illegal); + TEST_TO("\xdf\x7F",illegal); + TEST_TO("\xe0\x7F\x80",illegal); + TEST_TO("\xef\xbf\x7F",illegal); + TEST_TO("\xe0\x7F\x80",illegal); + TEST_TO("\xef\xbf\x7F",illegal); + TEST_TO("\xf0\x7F\x80\x80",illegal); + TEST_TO("\xf4\x7f\xbf\xbf",illegal); + TEST_TO("\xf0\x90\x7F\x80",illegal); + TEST_TO("\xf4\x8f\x7F\xbf",illegal); + TEST_TO("\xf0\x90\x80\x7F",illegal); + TEST_TO("\xf4\x8f\xbf\x7F",illegal); + + std::cout << "-- Invalid length" << std::endl; + + /// Test that this actually works + TEST_TO(make2(0x80),0x80); + TEST_TO(make2(0x7ff),0x7ff); + + TEST_TO(make3(0x800),0x800); + TEST_TO(make3(0xffff),0xffff); + + TEST_TO(make4(0x10000),0x10000); + TEST_TO(make4(0x10ffff),0x10ffff); + + TEST_TO(make4(0x110000),illegal); + TEST_TO(make4(0x1fffff),illegal); + + TEST_TO(make2(0),illegal); + TEST_TO(make3(0),illegal); + TEST_TO(make4(0),illegal); + TEST_TO(make2(0x7f),illegal); + TEST_TO(make3(0x7f),illegal); + TEST_TO(make4(0x7f),illegal); + + TEST_TO(make3(0x80),illegal); + TEST_TO(make4(0x80),illegal); + TEST_TO(make3(0x7ff),illegal); + TEST_TO(make4(0x7ff),illegal); + + TEST_TO(make4(0x8000),illegal); + TEST_TO(make4(0xffff),illegal); + + std::cout << "-- Invalid surrogate" << std::endl; + + TEST_TO(make3(0xD800),illegal); + TEST_TO(make3(0xDBFF),illegal); + TEST_TO(make3(0xDC00),illegal); + TEST_TO(make3(0xDFFF),illegal); + + TEST_TO(make4(0xD800),illegal); + TEST_TO(make4(0xDBFF),illegal); + TEST_TO(make4(0xDC00),illegal); + TEST_TO(make4(0xDFFF),illegal); + + std::cout <<"-- Incomplete" << std::endl; + + TEST_TO("\x80",illegal); + TEST_TO("\xC2",incomplete); + + TEST_TO("\xdf",incomplete); + + TEST_TO("\xe0",incomplete); + TEST_TO("\xe0\xa0",incomplete); + + TEST_TO("\xef\xbf",incomplete); + TEST_TO("\xef",incomplete); + + TEST_TO("\xf0\x90\x80",incomplete); + TEST_TO("\xf0\x90",incomplete); + TEST_TO("\xf0",incomplete); + + TEST_TO("\xf4\x8f\xbf",incomplete); + TEST_TO("\xf4\x8f",incomplete); + TEST_TO("\xf4",incomplete); + + std::cout << "- To UTF-8" << std::endl; + + std::cout << "-- Test correct" << std::endl; + + TEST_FROM("\x7f",0x7f); + TEST_FROM("\xC2\x80",0x80); + TEST_FROM("\xdf\xBF",0x7FF); + TEST_INC(0x7FF,1); + TEST_FROM("\xe0\xa0\x80",0x800); + TEST_INC(0x800,2); + TEST_INC(0x800,1); + TEST_FROM("\xef\xbf\xbf",0xFFFF); + TEST_INC(0x10000,3); + TEST_INC(0x10000,2); + TEST_INC(0x10000,1); + TEST_FROM("\xf0\x90\x80\x80",0x10000); + TEST_FROM("\xf4\x8f\xbf\xbf",0x10FFFF); + + std::cout << "-- Test no surrogate " << std::endl; + + TEST_FROM(0,0xD800); + TEST_FROM(0,0xDBFF); + TEST_FROM(0,0xDC00); + TEST_FROM(0,0xDFFF); + + std::cout << "-- Test invalid " << std::endl; + + TEST_FROM(0,0x110000); + TEST_FROM(0,0x1FFFFF); + + + std::cout << "Test windows-1255" << std::endl; + + #ifndef BOOST_NO_CXX11_SMART_PTR + cvt = std::move(create_simple_converter_unique_ptr("windows-1255")); + #else + cvt = create_simple_converter("windows-1255"); + #endif + + TEST(cvt.get()); + TEST(cvt->is_thread_safe()); + TEST(cvt->max_len() == 1); + + std::cout << "- From 1255" << std::endl; + + TEST_TO("\xa4",0x20aa); + TEST_TO("\xe0",0x05d0); + TEST_TO("\xc4",0x5b4); + TEST_TO("\xfb",illegal); + TEST_TO("\xdd",illegal); + TEST_TO("\xff",illegal); + TEST_TO("\xfe",0x200f); + + std::cout << "- To 1255" << std::endl; + + TEST_FROM("\xa4",0x20aa); + TEST_FROM("\xe0",0x05d0); + TEST_FROM("\xc4",0x5b4); + TEST_FROM("\xfe",0x200f); + + TEST_FROM(0,0xe4); + TEST_FROM(0,0xd0); + + #ifdef BOOST_LOCALE_WITH_ICU + std::cout << "Testing Shift-JIS using ICU/uconv" << std::endl; + + cvt.reset(boost::locale::impl_icu::create_uconv_converter("Shift-JIS")); + TEST(cvt.get()); + test_shiftjis(cvt.release()); + #endif + + #if defined(BOOST_LOCALE_WITH_ICONV) && !defined(BOOST_LOCALE_NO_POSIX_BACKEND) + std::cout << "Testing Shift-JIS using POSIX/iconv" << std::endl; + + cvt.reset(boost::locale::impl_posix::create_iconv_converter("Shift-JIS")); + if(cvt.get()) { + test_shiftjis(cvt.release()); + } + else { + std::cout<< "- Shift-JIS is not supported!" << std::endl; + } + #endif + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_collate.cpp b/src/boost/libs/locale/test/test_collate.cpp new file mode 100644 index 000000000..60f63abe9 --- /dev/null +++ b/src/boost/libs/locale/test/test_collate.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_WITH_ICU +#include <iostream> +int main() +{ + std::cout << "ICU is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/collator.hpp> +#include <boost/locale/generator.hpp> +#include <iomanip> +#include "test_locale.hpp" + + +template<typename Char> +void test_comp(std::locale l,std::basic_string<Char> left,std::basic_string<Char> right,int ilevel,int expected) +{ + typedef std::basic_string<Char> string_type; + boost::locale::collator_base::level_type level = static_cast<boost::locale::collator_base::level_type>(ilevel); + TEST(boost::locale::comparator<Char>(l,level)(left,right) == (expected < 0)); + if(ilevel==4) { + std::collate<Char> const &coll=std::use_facet<std::collate<Char> >(l); + string_type lt=coll.transform(left.c_str(),left.c_str()+left.size()); + string_type rt=coll.transform(right.c_str(),right.c_str()+right.size()); + if(expected < 0) + TEST(lt<rt); + else if(expected == 0) { + TEST(lt==rt); + } + else + TEST(lt > rt); + long lh=coll.hash(left.c_str(),left.c_str()+left.size()); + long rh=coll.hash(right.c_str(),right.c_str()+right.size()); + if(expected == 0) + TEST(lh==rh); + else + TEST(lh!=rh); + } + boost::locale::collator<Char> const &coll=std::use_facet<boost::locale::collator<Char> >(l); + string_type lt=coll.transform(level,left.c_str(),left.c_str()+left.size()); + TEST(lt==coll.transform(level,left)); + string_type rt=coll.transform(level,right.c_str(),right.c_str()+right.size()); + TEST(rt==coll.transform(level,right)); + if(expected < 0) + TEST(lt<rt); + else if(expected == 0) + TEST(lt==rt); + else + TEST(lt > rt); + long lh=coll.hash(level,left.c_str(),left.c_str()+left.size()); + TEST(lh==coll.hash(level,left)); + long rh=coll.hash(level,right.c_str(),right.c_str()+right.size()); + TEST(rh==coll.hash(level,right)); + if(expected == 0) + TEST(lh==rh); + else + TEST(lh!=rh); + +} + +#define TEST_COMP(c,_l,_r) test_comp<c>(l,_l,_r,level,expected) + + +void compare(std::string left,std::string right,int level,int expected) +{ + boost::locale::generator gen; + std::locale l=gen("en_US.UTF-8"); + if(level == 4) + TEST(l(left,right) == (expected < 0)); + TEST_COMP(char,left,right); + TEST_COMP(wchar_t,to<wchar_t>(left),to<wchar_t>(right)); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + TEST_COMP(char16_t,to<char16_t>(left),to<char16_t>(right)); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + TEST_COMP(char32_t,to<char32_t>(left),to<char32_t>(right)); + #endif + l=gen("en_US.ISO8859-1"); + if(level == 4) + TEST(l(to<char>(left),to<char>(right)) == (expected < 0)); + TEST_COMP(char,to<char>(left),to<char>(right)); +} + + +void test_collate() +{ + int + primary = 0, + secondary = 1, + tertiary = 2, + quaternary = 3, + identical = 4; + int le = -1,gt = 1,eq = 0; + + + compare("a","A",primary,eq); + compare("a","A",secondary,eq); + compare("A","a",tertiary,gt); + compare("a","A",tertiary,le); + compare("a","A",quaternary,le); + compare("A","a",quaternary,gt); + compare("a","A",identical,le); + compare("A","a",identical,gt); + compare("a","ä",primary,eq); // a , ä + compare("a","ä",secondary,le); // a , ä + compare("ä","a",secondary,gt); // a , ä + compare("a","ä",quaternary,le); // a , ä + compare("ä","a",quaternary,gt); // a , ä + compare("a","ä",identical,le); // a , ä + compare("ä","a",identical,gt); // a , ä +} + + + + +int main() +{ + try { + test_collate(); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // NOICU +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_config.cpp b/src/boost/libs/locale/test/test_config.cpp new file mode 100644 index 000000000..2205a8659 --- /dev/null +++ b/src/boost/libs/locale/test/test_config.cpp @@ -0,0 +1,133 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <iostream> +#include <iomanip> +#include <stdlib.h> +#include <locale.h> +#include <locale> +#include <time.h> +#include <stdexcept> + +#include <boost/locale.hpp> +#ifdef BOOST_LOCALE_WITH_ICU +#include <unicode/uversion.h> +#endif + +#include "test_locale_tools.hpp" + + +char const *env(char const *s) +{ + char const *r=getenv(s); + if(r) + return r; + return ""; +} + +void check_locale(char const **names) +{ + std::cout << " " << std::setw(32) << "locale" << std::setw(4) << "C" << std::setw(4) << "C++" << std::endl; + while(*names) { + char const *name = *names; + std::cout << " " << std::setw(32) << name << std::setw(4); + if(setlocale(LC_ALL,name)!=0) + std::cout << "Yes"; + else + std::cout << "No"; + std::cout << std::setw(4); + try { + std::locale l(name); + std::cout << "Yes"; + } + catch(std::exception const &) { + std::cout << "No"; + } + std::cout << std::endl; + names++; + } +} + +int main() +{ + std::cout << "- Backends: "; + #ifdef BOOST_LOCALE_WITH_ICU + std::cout << "icu:" << U_ICU_VERSION << " "; + #endif + #ifndef BOOST_LOCALE_NO_STD_BACKEND + std::cout << "std "; + #endif + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + std::cout << "posix "; + #endif + #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND + std::cout << "winapi"; + #endif + std::cout << std::endl; + #ifdef BOOST_LOCALE_WITH_ICONV + std::cout << "- With iconv" << std::endl; + #else + std::cout << "- Without iconv" << std::endl; + #endif + std::cout << "- Environment " << std::endl; + std::cout << " LANG="<< env("LANG") << std::endl; + std::cout << " LC_ALL="<< env("LC_ALL") << std::endl; + std::cout << " LC_CTYPE="<< env("LC_CTYPE") << std::endl; + std::cout << " TZ="<< env("TZ") << std::endl; + + char const *clocale=setlocale(LC_ALL,""); + if(!clocale) + clocale= "undetected"; + std::cout <<"- C locale: " << clocale << std::endl; + + try { + std::locale loc(""); + std::cout << "- C++ locale: " << loc.name() << std::endl; + } + catch(std::exception const &) { + std::cout << "- C++ locale: is not supported" << std::endl; + } + + char const *locales_to_check[] = { + "en_US.UTF-8", "en_US.ISO8859-1", "English_United States.1252", + "he_IL.UTF-8", "he_IL.ISO8859-8", "Hebrew_Israel.1255", + "ru_RU.UTF-8", "Russian_Russia.1251", + "tr_TR.UTF-8", "Turkish_Turkey.1254", + "ja_JP.UTF-8", "ja_JP.SJIS", "Japanese_Japan.932", + 0 + }; + std::cout << "- Testing locales availability on the operation system:" << std::endl; + check_locale(locales_to_check); + std::cout << "--- Testing Japanese_Japan.932 is working: " << test_std_supports_SJIS_codecvt("Japanese_Japan.932") << std::endl; + + std::cout << "- Testing timezone and time " << std::endl; + { + setlocale(LC_ALL,"C"); + time_t now = time(0); + char buf[1024]; + strftime(buf,sizeof(buf),"%%c=%c; %%Z=%Z; %%z=%z",localtime(&now)); + std::cout << " Local Time :" << buf << std::endl; + strftime(buf,sizeof(buf),"%%c=%c; %%Z=%Z; %%z=%z",gmtime(&now)); + std::cout << " Universal Time:" << buf << std::endl; + } + std::cout << "- Boost.Locale's locale: "; + try { + boost::locale::generator gen; + std::locale l = gen(""); + std::cout << std::use_facet<boost::locale::info>(l).name() << std::endl; + } + catch(std::exception const &) { + std::cout << " undetected" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_convert.cpp b/src/boost/libs/locale/test/test_convert.cpp new file mode 100644 index 000000000..36f6e572b --- /dev/null +++ b/src/boost/libs/locale/test/test_convert.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_WITH_ICU +#include <iostream> +int main() +{ + std::cout << "ICU is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/conversion.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" + + +template<typename Char> +void test_normc(std::basic_string<Char> orig,std::basic_string<Char> normal,boost::locale::norm_type type) +{ + std::locale l = boost::locale::generator().generate("en_US.UTF-8"); + TEST(normalize(orig,type,l)==normal); + TEST(normalize(orig.c_str(),type,l)==normal); + TEST(normalize(orig.c_str(),orig.c_str()+orig.size(),type,l)==normal); +} + +void test_norm(std::string orig,std::string normal,boost::locale::norm_type type) +{ + test_normc<char>(orig,normal,type); + test_normc<wchar_t>(to<wchar_t>(orig),to<wchar_t>(normal),type); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + test_normc<char16_t>(to<char16_t>(orig),to<char16_t>(normal),type); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + test_normc<char32_t>(to<char32_t>(orig),to<char32_t>(normal),type); + #endif +} + +#define TEST_A(Chr,how,source,dest) \ + do { \ + boost::locale::info const &inf=std::use_facet<boost::locale::info>(std::locale()); \ + std::cout <<"Testing " #how " for " #Chr ", lang="<<inf.language(); \ + if(std::string("char")==#Chr) std::cout <<" charset="<< inf.encoding(); \ + std::cout << std::endl; \ + std::basic_string<Chr> source_s=(source),dest_s=(dest); \ + TEST(boost::locale::how(source_s)==dest_s); \ + TEST(boost::locale::how(source_s.c_str())==dest_s); \ + TEST(boost::locale::how(source_s.c_str(),source_s.c_str()+source_s.size())==dest_s);\ + }while(0) + +#define TEST_ALL_CASES \ + do { \ + eight_bit=true; \ + std::locale::global(gen("en_US.UTF-8")); \ + TEST_V(to_upper,"grüßen i","GRÜSSEN I"); \ + TEST_V(to_lower,"Façade","façade"); \ + TEST_V(to_title,"façadE world","Façade World"); \ + TEST_V(fold_case,"Hello World","hello world"); \ + std::locale::global(gen("tr_TR.UTF-8")); \ + eight_bit=false; \ + TEST_V(to_upper,"i","İ"); \ + TEST_V(to_lower,"İ","i"); \ + }while(0) + + +int main() +{ + try { + { + using namespace boost::locale; + std::cout << "Testing Unicode normalization" << std::endl; + test_norm("\xEF\xAC\x81","\xEF\xAC\x81",norm_nfd); /// ligature fi + test_norm("\xEF\xAC\x81","\xEF\xAC\x81",norm_nfc); + test_norm("\xEF\xAC\x81","fi",norm_nfkd); + test_norm("\xEF\xAC\x81","fi",norm_nfkc); + test_norm("ä","ä",norm_nfd); // ä to a and accent + test_norm("ä","ä",norm_nfc); + } + + boost::locale::generator gen; + bool eight_bit=true; + + #define TEST_V(how,source_s,dest_s) \ + do { \ + TEST_A(char,how,source_s,dest_s); \ + if(eight_bit) { \ + std::locale tmp=std::locale(); \ + std::locale::global(gen("en_US.ISO8859-1")); \ + TEST_A(char,how,to<char>(source_s),to<char>(dest_s)); \ + std::locale::global(tmp); \ + } \ + }while(0) + + TEST_ALL_CASES; + #undef TEST_V + + #define TEST_V(how,source_s,dest_s) TEST_A(wchar_t,how,to<wchar_t>(source_s),to<wchar_t>(dest_s)) + TEST_ALL_CASES; + #undef TEST_V + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + #define TEST_V(how,source_s,dest_s) TEST_A(char16_t,how,to<char16_t>(source_s),to<char16_t>(dest_s)) + TEST_ALL_CASES; + #undef TEST_V + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + #define TEST_V(how,source_s,dest_s) TEST_A(char32_t,how,to<char32_t>(source_s),to<char32_t>(dest_s)) + TEST_ALL_CASES; + #undef TEST_V + #endif + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} +#endif // NO ICU +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_date_time.cpp b/src/boost/libs/locale/test/test_date_time.cpp new file mode 100644 index 000000000..91af52870 --- /dev/null +++ b/src/boost/libs/locale/test/test_date_time.cpp @@ -0,0 +1,302 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/locale/date_time.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/formatting.hpp> +#include <boost/locale/localization_backend.hpp> +#include <iomanip> +#include "test_locale.hpp" + +#ifdef BOOST_LOCALE_WITH_ICU +#include <unicode/uversion.h> +#define BOOST_ICU_VER (U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM) +#else +#define BOOST_ICU_VER 406 +#endif + +#ifdef BOOST_MSVC +# pragma warning(disable : 4244) // loose data +#endif + +#define RESET() do { time_point = base_time_point; ss.str(""); } while(0) +#define TESTR(X) do { TEST(X); RESET(); } while(0) +//#define TESTEQSR(t,X) do { ss << (t); TESTR(ss.str() == X); } while(0) +#define TESTEQSR(t,X) do { ss << (t); if(ss.str()!=X) { std::cerr <<"[" << ss.str() <<"]!=[" <<X<<"]" << std::endl; } TESTR(ss.str() == X); } while(0) + +int main() +{ + try { + using namespace boost::locale; + using namespace boost::locale::period; + std::string def[] = { + #ifdef BOOST_LOCALE_WITH_ICU + "icu" , + #endif + #ifndef BOOST_LOCALE_NO_STD_BACKEND + "std" , + #endif + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + "posix", + #endif + #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND + "winapi", + #endif + }; + for(int type = 0 ; type < int(sizeof(def)/sizeof(def[0])) ; type ++ ) { + boost::locale::localization_backend_manager tmp_backend = boost::locale::localization_backend_manager::global(); + tmp_backend.select(def[type]); + boost::locale::localization_backend_manager::global(tmp_backend); + std::cout << "Testing for backend: " << def[type] << std::endl; + std::string backend_name = def[type]; + { + + boost::locale::generator g; + + std::locale loc=g("en_US.UTF-8"); + + std::locale::global(loc); + + std::string tz("GMT"); + time_zone::global(tz); + calendar cal(loc,tz); + + TEST(calendar() == cal); + TEST(calendar(loc) == cal); + TEST(calendar(tz) == cal); + TEST(calendar(loc,"GMT+01:00") != cal); + TEST(calendar(g("ru_RU.UTF-8")) != cal); + + TEST(cal.minimum(month())==0); + TEST(cal.maximum(month())==11); + TEST(cal.minimum(day())==1); + TEST(cal.greatest_minimum(day())==1); + TEST(cal.least_maximum(day())==28); + TEST(cal.maximum(day())==31); + + TEST(calendar(g("ar_EG.UTF-8")).first_day_of_week() == 7); + TEST(calendar(g("he_IL.UTF-8")).first_day_of_week() == 1); + TEST(calendar(g("ru_RU.UTF-8")).first_day_of_week() == 2); + + std::ostringstream ss; + ss.imbue(loc); + ss<<boost::locale::as::time_zone(tz); + + date_time time_point; + + time_point=year(1970) + february() + day(5); + + ss << as::ftime("%Y-%m-%d")<< time_point; + + TEST(ss.str() == "1970-02-05"); + time_point = 3 * hour_12() + 1 * am_pm() + 33 * minute() + 13 * second(); + ss.str(""); + ss << as::ftime("%Y-%m-%d %H:%M:%S") << time_point; + TEST( ss.str() == "1970-02-05 15:33:13"); ss.str(""); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:05 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + date_time base_time_point=date_time(a_datetime); + + RESET(); + + time_point += hour(); + TESTEQSR(time_point,"1970-02-05 16:33:13"); + + TEST(time_point.minimum(day())==1); + TEST(time_point.maximum(day())==28); + + time_point += year() * 2 + 1 *month(); + TESTEQSR(time_point,"1972-03-05 15:33:13"); + + time_point -= minute(); + TESTEQSR( time_point, "1970-02-05 15:32:13"); + + time_point <<= minute() * 30; + TESTEQSR( time_point, "1970-02-05 15:03:13"); + + time_point >>= minute(40); + TESTEQSR( time_point, "1970-02-05 15:53:13"); + + TEST((time_point + month()) / month() == 2); + TEST(month(time_point + month(1)) == 2); + TEST(time_point / month() == 1); + TEST((time_point - month()) / month()== 0); + TEST(time_point / month() == 1); + TEST((time_point << month()) / month()== 2); + TEST(time_point / month()== 1); + TEST((time_point >> month()) / month()== 0); + TEST(time_point / month()== 1); + + + + TEST( (time_point + 2 * hour() - time_point) / minute() == 120); + TEST( (time_point + month()- time_point) / day() == 28); + TEST( (time_point + 2* month()- (time_point+month())) / day() == 31); + TEST( day(time_point + 2* month()- (time_point+month())) == 31); + + TESTEQSR( time_point + hour(), "1970-02-05 16:33:13"); + TESTEQSR( time_point - hour(2), "1970-02-05 13:33:13"); + TESTEQSR( time_point >> minute(), "1970-02-05 15:32:13"); + TESTEQSR( time_point << second(), "1970-02-05 15:33:14"); + + TEST(time_point == time_point); + TEST(!(time_point != time_point)); + TEST(time_point.get(hour()) == 15); + TEST(time_point/hour() == 15); + TEST(time_point+year() != time_point); + TEST(time_point - minute() <= time_point); + TEST(time_point <= time_point); + TEST(time_point + minute() >= time_point); + TEST(time_point >= time_point); + + TEST(time_point < time_point + second()); + TEST(!(time_point < time_point - second())); + TEST(time_point > time_point - second()); + TEST(!(time_point > time_point + second())); + + TEST(time_point.get(day()) == 5); + TEST(time_point.get(year()) == 1970); + + TEST(time_point.get(era()) == 1); + TEST(time_point.get(year()) == 1970); + TEST(time_point.get(extended_year()) == 1970); + if(backend_name == "icu") { + time_point=extended_year(-3); + TEST(time_point.get(era()) == 0); + TEST(time_point.get(year()) == 4); + } + RESET(); + TEST(time_point.get(month()) == 1); + TEST(time_point.get(day()) == 5); + TEST(time_point.get(day_of_year()) == 36); + TEST(time_point.get(day_of_week()) == 5); + TEST(time_point.get(day_of_week_in_month())==1); + time_point=date_time(a_datetime,calendar(g("ru_RU.UTF-8"))); + TEST(time_point.get(day_of_week_local()) == 4); + time_point = year(2026) + january() + day(1); + TEST(time_point.get(day_of_week()) == 5); + TEST(time_point.get(week_of_year()) == 1); + TEST(time_point.get(week_of_month()) == 1); + time_point = day_of_week() * 1; + TEST(time_point.get(day()) == 4); + TEST(time_point.get(week_of_year()) == 1); + TEST(time_point.get(week_of_month()) == 1); + time_point += day() * 1; + TEST(time_point.get(week_of_year()) == 2); + TEST(time_point.get(week_of_month()) == 2); + time_point = february() + day() * 2; + + + TEST(time_point.get(week_of_year()) == 6); + + if(backend_name!="icu" || BOOST_ICU_VER<408 || BOOST_ICU_VER > 6000) { + TEST(time_point.get(week_of_month()) == 1); + } + else { + // cldr changes + TEST(time_point.get(week_of_month()) == 2); + } + + time_point = year(2010) + january() + day() * 3; + + if(backend_name!="icu" || BOOST_ICU_VER<408 || BOOST_ICU_VER > 6000) { + TEST(time_point.get(week_of_year()) == 53); + } + else { + TEST(time_point.get(week_of_year()) == 1); + } + + time_point = year()*2010 + january() + day() * 4; + + if(backend_name!="icu" || BOOST_ICU_VER<408 || BOOST_ICU_VER > 6000) { + TEST(time_point.get(week_of_year()) == 1); + } + else { + TEST(time_point.get(week_of_year()) == 2); + } + time_point = year()*2010 + january() + day() * 10; + + if(backend_name!="icu" || BOOST_ICU_VER<408 || BOOST_ICU_VER > 6000) { + TEST(time_point.get(week_of_year()) == 1); + } + else { + TEST(time_point.get(week_of_year()) == 2); + } + + time_point = year()*2010 + january() + day() * 11; + if(backend_name!="icu" || BOOST_ICU_VER<408 || BOOST_ICU_VER > 6000) { + TEST(time_point.get(week_of_year()) == 2); + } + else { + TEST(time_point.get(week_of_year()) == 3); + } + RESET(); + TEST(time_point.get(hour()) == 15); + TEST(date_time(a_datetime,calendar("GMT+01:00")).get(hour()) ==16); + TEST(time_point.get(hour_12()) == 3); + TEST(time_point.get(am_pm()) == 1); + TEST(time_point.get(minute()) == 33); + TEST(time_point.get(second()) == 13); + TEST(date_time(year()* 1984 + february() + day()).get(week_of_year())==5); + TEST(time_point.get(week_of_month()) == 1); + RESET(); + + // Make sure we don't get year() < 1970 so the test would + // work on windows where mktime supports positive time_t + // only + time_point = year() * 2010; + + TEST((time_point + year() *1 - hour() * 1 - time_point) / year() == 0); + TEST((time_point + year() *1 - time_point) / year() == 1); + TEST((time_point + year() *1 + hour() * 1 - time_point) / year() == 1); + TEST((time_point - year() *1 + hour() * 1 - time_point) / year() == 0); + TEST((time_point - year() *1 - time_point) / year() == -1); + TEST((time_point - year() *1 - hour() * 1 - time_point) / year() == -1); + + RESET(); + + time_point.time(24*3600 * 2); + + time_point = year() * 2011; + time_point = march(); + time_point = day() * 29; + + date_time tmp_save = time_point; + + time_point = year() * 2011; + time_point = february(); + time_point = day() * 5; + + TEST(time_point.get(year()) == 2011); + TEST(time_point.get(month()) == 2); // march + TEST(time_point.get(day()) == 5); + + time_point = tmp_save; + + time_point = year() * 2011 + february() + day() * 5; + TEST(time_point.get(year()) == 2011); + TEST(time_point.get(month()) == 1); // february + TEST(time_point.get(day()) == 5); + + } // test + } // for loop + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_formatting.cpp b/src/boost/libs/locale/test/test_formatting.cpp new file mode 100644 index 000000000..4a337f26c --- /dev/null +++ b/src/boost/libs/locale/test/test_formatting.cpp @@ -0,0 +1,576 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_LOCALE_WITH_ICU +#include <iostream> +int main() +{ + std::cout << "ICU is not build... Skipping" << std::endl; +} +#else + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +// Disable this "security crap" +#endif + +#include <boost/locale/formatting.hpp> +#include <boost/locale/format.hpp> +#include <boost/locale/date_time.hpp> +#include <boost/locale/generator.hpp> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <sstream> +#include <iostream> +#include <iomanip> +#include <limits> + +#include <unicode/uversion.h> + +using namespace boost::locale; + +//#define TEST_DEBUG +#ifdef BOOST_MSVC +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifdef TEST_DEBUG +#undef BOOST_LOCALE_ENABLE_CHAR16_T +#undef BOOST_LOCALE_ENABLE_CHAR32_T +template<typename T> +void print_diff(T const &,T const &,int) +{ +} +template<> +void print_diff(std::string const &l,std::string const &r,int line) +{ + if(l!=r) { + std::cerr << "----[" << l <<"]!=\n----["<<r<<"] in " << line << std::endl; + } +} + +#define TESTEQ(x,y) do { print_diff((x),(y),__LINE__); TEST((x)==(y)); } while(0) +#else +#define TESTEQ(x,y) TEST((x)==(y)) +#endif + +#define TEST_FMT(manip,value,expected) \ +do{ \ + std::basic_ostringstream<CharType> ss; \ + ss.imbue(loc); \ + ss << manip << value; \ + TESTEQ(ss.str(),to_correct_string<CharType>(expected,loc)); \ +}while(0) + +#ifndef _LIBCPP_VERSION +static bool parsing_fails() +{ + return true; +} +#else +static bool parsing_fails() +{ + static bool checked=false; + static bool fails; + if(!checked) { + try { + std::istringstream ss("x"); + ss.exceptions(std::ios_base::failbit); + int x; + ss>>x; + fails =false; + } + catch(std::ios_base::failure const &) { + fails=true; + } + catch(...) { + fails=false; + } + checked=true; + if(!fails) { + std::cerr << "!!! Warning: libc++ library does not throw an exception on failbit !!!" << std::endl; + } + } + return fails; +} +#endif + + +#define TEST_NOPAR(manip,actual,type) \ +do{ \ + type v; \ + std::basic_string<CharType> act= \ + to_correct_string<CharType>(actual,loc); \ + { \ + std::basic_istringstream<CharType> ss; \ + ss.imbue(loc); \ + ss.str(act); \ + ss >> manip >> v ; \ + TEST(ss.fail()); \ + } \ + if(parsing_fails()){ \ + std::basic_istringstream<CharType> ss; \ + ss.imbue(loc); \ + ss.str(act); \ + ss.exceptions(std::ios_base::failbit); \ + ss >> manip; \ + TEST_THROWS(ss >> v,std::ios_base::failure); \ + } \ +}while(0) + +#define TEST_PAR(manip,type,actual,expected) \ +do{ \ + type v; \ + {std::basic_istringstream<CharType> ss; \ + ss.imbue(loc); \ + ss.str(to_correct_string<CharType>(actual,loc)); \ + ss >> manip >> v >> std::ws; \ + TESTEQ(v,expected); \ + TEST(ss.eof()); }\ + {std::basic_istringstream<CharType> ss; \ + ss.imbue(loc); \ + ss.str(to_correct_string<CharType>(std::string(actual)+"@",loc)); \ + CharType tmp_c; \ + ss >> manip >> v >> std::skipws >> tmp_c; \ + TESTEQ(v,expected); \ + TEST(tmp_c=='@'); } \ +}while(0) + +#define TEST_FP1(manip,value_in,str,type,value_out) \ +do { \ + TEST_FMT(manip,value_in,str); \ + TEST_PAR(manip,type,str,value_out); \ +}while(0) + +#define TEST_FP2(m1,m2,value_in,str,type,value_out) \ +do { \ + TEST_FMT(m1<<m2,value_in,str); \ + TEST_PAR(m1>>m2,type,str,value_out); \ +}while(0) + +#define TEST_FP3(m1,m2,m3,value_in,str,type,value_out) \ +do { \ + TEST_FMT(m1<<m2<<m3,value_in,str); \ + TEST_PAR(m1>>m2>>m3,type,str,value_out); \ +}while(0) + +#define TEST_FP4(m1,m2,m3,m4,value_in,str,type,value_out) \ +do { \ + TEST_FMT(m1<<m2<<m3<<m4,value_in,str); \ + TEST_PAR(m1>>m2>>m3>>m4,type,str,value_out); \ +}while(0) + + +#define FORMAT(f,v,exp) \ + do{\ + std::basic_ostringstream<CharType> ss; \ + ss.imbue(loc); \ + std::basic_string<CharType> fmt = to_correct_string<CharType>(f,loc); \ + ss << boost::locale::basic_format<CharType>(fmt) % v; \ + TESTEQ(ss.str(),to_correct_string<CharType>(exp,loc)); \ + ss.str(to_correct_string<CharType>("",loc)); \ + ss << boost::locale::basic_format<CharType>(boost::locale::translate(fmt.c_str())) % v; \ + /*ss << boost::locale::basic_format<CharType>(fmt) % v; */ \ + TESTEQ(ss.str(),to_correct_string<CharType>(exp,loc)); \ + TESTEQ( (boost::locale::basic_format<CharType>(fmt) % v).str(loc),to_correct_string<CharType>(exp,loc)); \ + } while(0) + + +#define TEST_MIN_MAX_FMT(type,minval,maxval) \ + do { \ + TEST_FMT(as::number,std::numeric_limits<type>::min(),minval); \ + TEST_FMT(as::number,std::numeric_limits<type>::max(),maxval); \ + }while(0) + +#define TEST_MIN_MAX_PAR(type,minval,maxval) \ + do {\ + TEST_PAR(as::number,type,minval,std::numeric_limits<type>::min()); \ + TEST_PAR(as::number,type,maxval,std::numeric_limits<type>::max()); \ + }while(0) + +#define TEST_MIN_MAX(type,minval,maxval) \ + do { \ + TEST_MIN_MAX_FMT(type,minval,maxval); \ + TEST_MIN_MAX_PAR(type,minval,maxval); \ + }while(0) + + +#define BOOST_ICU_VER (U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM) +#define BOOST_ICU_EXACT_VER (U_ICU_VERSION_MAJOR_NUM*10000 + U_ICU_VERSION_MINOR_NUM * 100 + U_ICU_VERSION_PATCHLEVEL_NUM) + +bool short_parsing_fails() +{ + static bool fails = false; + static bool get_result = false; + if(get_result) + return fails; + std::stringstream ss("65000"); + ss.imbue(std::locale::classic()); + short v=0; + ss >> v; + fails = ss.fail(); + get_result = true; + return fails; +} + +template<typename CharType> +void test_manip(std::string e_charset="UTF-8") +{ + boost::locale::generator g; + std::locale loc=g("en_US."+e_charset); + + TEST_FP1(as::posix,1200.1,"1200.1",double,1200.1); + TEST_FP1(as::number,1200.1,"1,200.1",double,1200.1); + TEST_FMT(as::number<<std::setfill(CharType('_'))<<std::setw(6),1534,"_1,534"); + TEST_FMT(as::number<<std::left<<std::setfill(CharType('_'))<<std::setw(6),1534,"1,534_"); + + // Ranges + if(sizeof(short) == 2) { + TEST_MIN_MAX(short,"-32,768","32,767"); + TEST_MIN_MAX(unsigned short,"0","65,535"); + TEST_NOPAR(as::number,"-1",unsigned short); + if(short_parsing_fails()) { + TEST_NOPAR(as::number,"65,535",short); + } + } + if(sizeof(int)==4) { + TEST_MIN_MAX(int,"-2,147,483,648","2,147,483,647"); + TEST_MIN_MAX(unsigned int,"0","4,294,967,295"); + TEST_NOPAR(as::number,"-1",unsigned int); + TEST_NOPAR(as::number,"4,294,967,295",int); + } + if(sizeof(long)==4) { + TEST_MIN_MAX(long,"-2,147,483,648","2,147,483,647"); + TEST_MIN_MAX(unsigned long,"0","4,294,967,295"); + TEST_NOPAR(as::number,"-1",unsigned long); + TEST_NOPAR(as::number,"4,294,967,295",long); + } + if(sizeof(long)==8) { + TEST_MIN_MAX(long,"-9,223,372,036,854,775,808","9,223,372,036,854,775,807"); + TEST_MIN_MAX_FMT(unsigned long,"0","18446744073709551615"); // Unsupported range by icu - ensure fallback + TEST_NOPAR(as::number,"-1",unsigned long); + } + #ifndef BOOST_NO_LONG_LONG + if(sizeof(long long)==8) { + TEST_MIN_MAX(long long,"-9,223,372,036,854,775,808","9,223,372,036,854,775,807"); + // we can't really parse this as ICU does not support this range, only format + TEST_MIN_MAX_FMT(unsigned long long,"0","18446744073709551615"); // Unsupported range by icu - ensure fallback + TEST_FMT(as::number,9223372036854775807ULL,"9,223,372,036,854,775,807"); + TEST_FMT(as::number,9223372036854775808ULL,"9223372036854775808"); // Unsupported range by icu - ensure fallback + TEST_NOPAR(as::number,"-1",unsigned long long); + } + #endif + + + + TEST_FP3(as::number,std::left,std::setw(3),15,"15 ",int,15); + TEST_FP3(as::number,std::right,std::setw(3),15," 15",int,15); + TEST_FP3(as::number,std::setprecision(3),std::fixed,13.1,"13.100",double,13.1); + #if BOOST_ICU_VER < 5601 + // bug #13276 + TEST_FP3(as::number,std::setprecision(3),std::scientific,13.1,"1.310E1",double,13.1); + #endif + + TEST_NOPAR(as::number,"",int); + TEST_NOPAR(as::number,"--3",int); + TEST_NOPAR(as::number,"y",int); + + TEST_FP1(as::percent,0.1,"10%",double,0.1); + TEST_FP3(as::percent,std::fixed,std::setprecision(1),0.10,"10.0%",double,0.1); + + TEST_NOPAR(as::percent,"1",double); + + TEST_FP1(as::currency,1345,"$1,345.00",int,1345); + TEST_FP1(as::currency,1345.34,"$1,345.34",double,1345.34); + + TEST_NOPAR(as::currency,"$",double); + + + #if BOOST_ICU_VER >= 402 + TEST_FP2(as::currency,as::currency_national,1345,"$1,345.00",int,1345); + TEST_FP2(as::currency,as::currency_national,1345.34,"$1,345.34",double,1345.34); + TEST_FP2(as::currency,as::currency_iso,1345,"USD1,345.00",int,1345); + TEST_FP2(as::currency,as::currency_iso,1345.34,"USD1,345.34",double,1345.34); + #endif + TEST_FP1(as::spellout,10,"ten",int,10); + #if 402 <= BOOST_ICU_VER && BOOST_ICU_VER < 408 + if(e_charset=="UTF-8") { + TEST_FMT(as::ordinal,1,"1\xcb\xa2\xe1\xb5\x97"); // 1st with st as ligatures + } + #else + TEST_FMT(as::ordinal,1,"1st"); + #endif + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:05 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + TEST_FP2(as::date, as::gmt,a_datetime,"Feb 5, 1970",time_t,a_date); + TEST_FP3(as::date,as::date_short ,as::gmt,a_datetime,"2/5/70",time_t,a_date); + TEST_FP3(as::date,as::date_medium,as::gmt,a_datetime,"Feb 5, 1970",time_t,a_date); + TEST_FP3(as::date,as::date_long ,as::gmt,a_datetime,"February 5, 1970",time_t,a_date); + TEST_FP3(as::date,as::date_full ,as::gmt,a_datetime,"Thursday, February 5, 1970",time_t,a_date); + + TEST_NOPAR(as::date>>as::date_short,"aa/bb/cc",double); + +#if BOOST_ICU_VER >= 5901 +#define GMT_FULL "Greenwich Mean Time" +#else +#define GMT_FULL "GMT" +#endif + + TEST_FP2(as::time, as::gmt,a_datetime,"3:33:13 PM",time_t,a_time+a_timesec); + TEST_FP3(as::time,as::time_short ,as::gmt,a_datetime,"3:33 PM",time_t,a_time); + TEST_FP3(as::time,as::time_medium,as::gmt,a_datetime,"3:33:13 PM",time_t,a_time+a_timesec); + #if BOOST_ICU_VER >= 408 + TEST_FP3(as::time,as::time_long ,as::gmt,a_datetime,"3:33:13 PM GMT",time_t,a_time+a_timesec); + #if BOOST_ICU_EXACT_VER != 40800 + // know bug #8675 + TEST_FP3(as::time,as::time_full ,as::gmt,a_datetime,"3:33:13 PM " GMT_FULL,time_t,a_time+a_timesec); + #endif + #else + TEST_FP3(as::time,as::time_long ,as::gmt,a_datetime,"3:33:13 PM GMT+00:00",time_t,a_time+a_timesec); + TEST_FP3(as::time,as::time_full ,as::gmt,a_datetime,"3:33:13 PM GMT+00:00",time_t,a_time+a_timesec); + #endif + + TEST_NOPAR(as::time,"AM",double); + + TEST_FP2(as::time, as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); + TEST_FP3(as::time,as::time_short ,as::time_zone("GMT+01:00"),a_datetime,"4:33 PM",time_t,a_time); + TEST_FP3(as::time,as::time_medium,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); + +#if U_ICU_VERSION_MAJOR_NUM >= 52 +#define GMT_P100 "GMT+1" +#else +#define GMT_P100 "GMT+01:00" +#endif + + +#if U_ICU_VERSION_MAJOR_NUM >= 50 +#define PERIOD "," +#define ICUAT " at" +#else +#define PERIOD "" +#define ICUAT "" +#endif + + TEST_FP3(as::time,as::time_long ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM " GMT_P100,time_t,a_time+a_timesec); + #if BOOST_ICU_VER == 308 && defined(__CYGWIN__) + // Known faliture ICU issue + #else + TEST_FP3(as::time,as::time_full ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM GMT+01:00",time_t,a_time+a_timesec); + #endif + + TEST_FP2(as::datetime, as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); + TEST_FP4(as::datetime,as::date_short ,as::time_short ,as::gmt,a_datetime,"2/5/70" PERIOD " 3:33 PM",time_t,a_date+a_time); + TEST_FP4(as::datetime,as::date_medium,as::time_medium,as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); + #if BOOST_ICU_VER >= 408 + TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" ICUAT " 3:33:13 PM GMT",time_t,a_datetime); + #if BOOST_ICU_EXACT_VER != 40800 + // know bug #8675 + TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" ICUAT " 3:33:13 PM " GMT_FULL,time_t,a_datetime); + #endif + #else + TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); + TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); + #endif + + time_t now=time(0); + time_t lnow = now + 3600 * 4; + char local_time_str[256]; + std::string format="%H:%M:%S"; + std::basic_string<CharType> format_string(format.begin(),format.end()); + strftime(local_time_str,sizeof(local_time_str),format.c_str(),gmtime(&lnow)); + TEST_FMT(as::ftime(format_string),now,local_time_str); + TEST_FMT(as::ftime(format_string)<<as::gmt<<as::local_time,now,local_time_str); + + std::string marks = + "aAbB" + "cdeh" + "HIjm" + "Mnpr" + "RStT" + "xXyY" + "Z%"; + + std::string result[]= { + "Thu","Thursday","Feb","February", // aAbB + #if BOOST_ICU_VER >= 408 + "Thursday, February 5, 1970" ICUAT " 3:33:13 PM " GMT_FULL, // c + #else + "Thursday, February 5, 1970 3:33:13 PM GMT+00:00", // c + #endif + "05","5","Feb", // deh + "15","03","36","02", // HIjm + "33","\n","PM", "03:33:13 PM",// Mnpr + "15:33","13","\t","15:33:13", // RStT + "Feb 5, 1970","3:33:13 PM","70","1970", // xXyY + #if BOOST_ICU_VER >= 408 + GMT_FULL // Z + #else + "GMT+00:00" // Z + #endif + ,"%" }; // % + + for(unsigned i=0;i<marks.size();i++) { + format_string.clear(); + format_string+=static_cast<CharType>('%'); + format_string+=static_cast<CharType>(marks[i]); + TEST_FMT(as::ftime(format_string)<<as::gmt,a_datetime,result[i]); + } + + std::string sample_f[]={ + "Now is %A, %H o'clo''ck ' or not ' ", + "'test %H'", + "%H'", + "'%H'" + }; + std::string expected_f[] = { + "Now is Thursday, 15 o'clo''ck ' or not ' ", + "'test 15'", + "15'", + "'15'" + }; + + for(unsigned i=0;i<sizeof(sample_f)/sizeof(sample_f[0]);i++) { + format_string.assign(sample_f[i].begin(),sample_f[i].end()); + TEST_FMT(as::ftime(format_string)<<as::gmt,a_datetime,expected_f[i]); + } + +} + +template<typename CharType> +void test_format(std::string charset="UTF-8") +{ + boost::locale::generator g; + std::locale loc=g("en_US."+charset); + + FORMAT("{3} {1} {2}", 1 % 2 % 3,"3 1 2"); + FORMAT("{1} {2}", "hello" % 2,"hello 2"); + FORMAT("{1}",1200.1,"1200.1"); + FORMAT("Test {1,num}",1200.1,"Test 1,200.1"); + FORMAT("{{}} {1,number}",1200.1,"{} 1,200.1"); + #if BOOST_ICU_VER < 5601 + // bug #13276 + FORMAT("{1,num=sci,p=3}",13.1,"1.310E1"); + FORMAT("{1,num=scientific,p=3}",13.1,"1.310E1"); + #endif + FORMAT("{1,num=fix,p=3}",13.1,"13.100"); + FORMAT("{1,num=fixed,p=3}",13.1,"13.100"); + FORMAT("{1,<,w=3,num}",-1,"-1 "); + FORMAT("{1,>,w=3,num}",1," 1"); + FORMAT("{per,1}",0.1,"10%"); + FORMAT("{percent,1}",0.1,"10%"); + FORMAT("{1,cur}",1234,"$1,234.00"); + FORMAT("{1,currency}",1234,"$1,234.00"); + if(charset=="UTF-8") { + if(U_ICU_VERSION_MAJOR_NUM >=4) + FORMAT("{1,cur,locale=de_DE}",10,"10,00\xC2\xA0€"); + else + FORMAT("{1,cur,locale=de_DE}",10,"10,00 €"); + } + #if BOOST_ICU_VER >= 402 + FORMAT("{1,cur=nat}",1234,"$1,234.00"); + FORMAT("{1,cur=national}",1234,"$1,234.00"); + FORMAT("{1,cur=iso}",1234,"USD1,234.00"); + #endif + FORMAT("{1,spell}",10,"ten"); + FORMAT("{1,spellout}",10,"ten"); + #if 402 <= BOOST_ICU_VER && BOOST_ICU_VER < 408 + if(charset=="UTF-8") { + FORMAT("{1,ord}",1,"1\xcb\xa2\xe1\xb5\x97"); + FORMAT("{1,ordinal}",1,"1\xcb\xa2\xe1\xb5\x97"); + } + #else + FORMAT("{1,ord}",1,"1st"); + FORMAT("{1,ordinal}",1,"1st"); + #endif + + time_t now=time(0); + time_t lnow = now + 3600 * 4; + char local_time_str[256]; + std::string format="'%H:%M:%S'"; + std::basic_string<CharType> format_string(format.begin(),format.end()); + strftime(local_time_str,sizeof(local_time_str),format.c_str(),gmtime(&lnow)); + + FORMAT("{1,ftime='''%H:%M:%S'''}",now,local_time_str); + FORMAT("{1,local,ftime='''%H:%M:%S'''}",now,local_time_str); + FORMAT("{1,ftime='''%H:%M:%S'''}",now,local_time_str); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:05 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + FORMAT("{1,date,gmt};{1,time,gmt};{1,datetime,gmt};{1,dt,gmt}",a_datetime, + "Feb 5, 1970;3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM"); + #if BOOST_ICU_VER >= 408 + FORMAT("{1,time=short,gmt};{1,time=medium,gmt};{1,time=long,gmt};{1,date=full,gmt}",a_datetime, + "3:33 PM;3:33:13 PM;3:33:13 PM GMT;Thursday, February 5, 1970"); + FORMAT("{1,time=s,gmt};{1,time=m,gmt};{1,time=l,gmt};{1,date=f,gmt}",a_datetime, + "3:33 PM;3:33:13 PM;3:33:13 PM GMT;Thursday, February 5, 1970"); + #else + FORMAT("{1,time=short,gmt};{1,time=medium,gmt};{1,time=long,gmt};{1,date=full,gmt}",a_datetime, + "3:33 PM;3:33:13 PM;3:33:13 PM GMT+00:00;Thursday, February 5, 1970"); + FORMAT("{1,time=s,gmt};{1,time=m,gmt};{1,time=l,gmt};{1,date=f,gmt}",a_datetime, + "3:33 PM;3:33:13 PM;3:33:13 PM GMT+00:00;Thursday, February 5, 1970"); + #endif + FORMAT("{1,time=s,tz=GMT+01:00}",a_datetime,"4:33 PM"); + FORMAT("{1,time=s,timezone=GMT+01:00}",a_datetime,"4:33 PM"); + + FORMAT("{1,gmt,ftime='%H'''}",a_datetime,"15'"); + FORMAT("{1,gmt,ftime='''%H'}",a_datetime,"'15"); + FORMAT("{1,gmt,ftime='%H o''clock'}",a_datetime,"15 o'clock"); + + // Test not a year of the week + a_datetime=1388491200; // 2013-12-31 12:00 - check we don't use week of year + + FORMAT("{1,gmt,ftime='%Y'}",a_datetime,"2013"); + FORMAT("{1,gmt,ftime='%y'}",a_datetime,"13"); + FORMAT("{1,gmt,ftime='%D'}",a_datetime,"12/31/13"); +} + + +int main() +{ + try { + boost::locale::time_zone::global("GMT+4:00"); + std::cout << "Testing char, UTF-8" << std::endl; + test_manip<char>(); + test_format<char>(); + std::cout << "Testing char, ISO8859-1" << std::endl; + test_manip<char>("ISO8859-1"); + test_format<char>("ISO8859-1"); + + std::cout << "Testing wchar_t" << std::endl; + test_manip<wchar_t>(); + test_format<wchar_t>(); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "Testing char16_t" << std::endl; + test_manip<char16_t>(); + test_format<char16_t>(); + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "Testing char32_t" << std::endl; + test_manip<char32_t>(); + test_format<char32_t>(); + #endif + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // NOICU +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_generator.cpp b/src/boost/libs/locale/test/test_generator.cpp new file mode 100644 index 000000000..dde161005 --- /dev/null +++ b/src/boost/libs/locale/test/test_generator.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <boost/locale/message.hpp> +#include <iomanip> +#include "test_locale.hpp" + + +bool has_message(std::locale const &l) +{ + return std::has_facet<boost::locale::message_format<char> >(l); +} + +struct test_facet : public std::locale::facet { + test_facet() : std::locale::facet(0) {} + static std::locale::id id; +}; + +std::locale::id test_facet::id; + + +int main() +{ + try { + boost::locale::generator g; + std::locale l=g("en_US.UTF-8"); + TEST(has_message(l)); + + g.categories(g.categories() ^ boost::locale::message_facet); + g.locale_cache_enabled(true); + g("en_US.UTF-8"); + g.categories(g.categories() | boost::locale::message_facet); + l=g("en_US.UTF-8"); + TEST(!has_message(l)); + g.clear_cache(); + g.locale_cache_enabled(false); + l=g("en_US.UTF-8"); + TEST(has_message(l)); + g.characters(g.characters() ^ boost::locale::char_facet); + l=g("en_US.UTF-8"); + TEST(!has_message(l)); + g.characters(g.characters() | boost::locale::char_facet); + l=g("en_US.UTF-8"); + TEST(has_message(l)); + + l=g("en_US.ISO8859-1"); + TEST(std::use_facet<boost::locale::info>(l).language()=="en"); + TEST(std::use_facet<boost::locale::info>(l).country()=="US"); + TEST(!std::use_facet<boost::locale::info>(l).utf8()); + TEST(std::use_facet<boost::locale::info>(l).encoding()=="iso8859-1"); + + l=g("en_US.UTF-8"); + TEST(std::use_facet<boost::locale::info>(l).language()=="en"); + TEST(std::use_facet<boost::locale::info>(l).country()=="US"); + TEST(std::use_facet<boost::locale::info>(l).utf8()); + + l=g("en_US.ISO8859-1"); + TEST(std::use_facet<boost::locale::info>(l).language()=="en"); + TEST(std::use_facet<boost::locale::info>(l).country()=="US"); + TEST(!std::use_facet<boost::locale::info>(l).utf8()); + TEST(std::use_facet<boost::locale::info>(l).encoding()=="iso8859-1"); + + l=g("en_US.ISO8859-1"); + TEST(std::use_facet<boost::locale::info>(l).language()=="en"); + TEST(std::use_facet<boost::locale::info>(l).country()=="US"); + TEST(!std::use_facet<boost::locale::info>(l).utf8()); + TEST(std::use_facet<boost::locale::info>(l).encoding()=="iso8859-1"); + + std::locale l_wt(std::locale::classic(),new test_facet); + + TEST(std::has_facet<test_facet>(g.generate(l_wt,"en_US.UTF-8"))); + TEST(std::has_facet<test_facet>(g.generate(l_wt,"en_US.ISO8859-1"))); + TEST(!std::has_facet<test_facet>(g("en_US.UTF-8"))); + TEST(!std::has_facet<test_facet>(g("en_US.ISO8859-1"))); + + g.locale_cache_enabled(true); + g.generate(l_wt,"en_US.UTF-8"); + g.generate(l_wt,"en_US.ISO8859-1"); + TEST(std::has_facet<test_facet>(g("en_US.UTF-8"))); + TEST(std::has_facet<test_facet>(g("en_US.ISO8859-1"))); + TEST(std::use_facet<boost::locale::info>(g("en_US.UTF-8")).utf8()); + TEST(!std::use_facet<boost::locale::info>(g("en_US.ISO8859-1")).utf8()); + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_icu_vs_os_timezone.cpp b/src/boost/libs/locale/test/test_icu_vs_os_timezone.cpp new file mode 100644 index 000000000..fa1fd94dc --- /dev/null +++ b/src/boost/libs/locale/test/test_icu_vs_os_timezone.cpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_WITH_ICU +#include <iostream> +int main() +{ + std::cout << "ICU is not build... Skipping" << std::endl; +} +#else + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +// Disable this "security crap" +#endif + +#include <boost/locale/formatting.hpp> +#include <boost/locale/format.hpp> +#include <boost/locale/generator.hpp> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <sstream> +#include <iostream> +#include <iomanip> + +#include <time.h> + +int main() +{ + try { + + time_t now=time(0); + boost::locale::generator gen; + std::locale::global(gen("en_US.UTF-8")); + + for(int i=0;i<366;i++) { + time_t point = now + i * 24 * 3600; + std::stringstream ss; + ss << boost::locale::format("{1,ftime='%H %M %S'}") % point; + int icu_hour = 0,icu_min = 0,icu_sec = 0; + ss >> icu_hour >> icu_min >> icu_sec; + std::tm *tm=localtime(&point); + TEST(icu_hour == tm->tm_hour); + TEST(icu_min == tm->tm_min); + TEST(icu_sec == tm->tm_sec); + + } + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // NO ICU + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_ios_prop.cpp b/src/boost/libs/locale/test/test_ios_prop.cpp new file mode 100644 index 000000000..e94f7991d --- /dev/null +++ b/src/boost/libs/locale/test/test_ios_prop.cpp @@ -0,0 +1,84 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include "test_locale.hpp" +#include "../src/shared/ios_prop.hpp" +#include <sstream> +#include <locale> + +int counter=0; +int imbued=0; +struct propery { + propery(int xx=-1) : x(xx) { counter ++; } + propery(propery const &other) { counter++; x=other.x; } + propery const &operator=(propery const &other) { + x=other.x; + return *this; + }; + int x; + void on_imbue() {imbued++; } + ~propery() { counter--; } +}; +typedef boost::locale::impl::ios_prop<propery> prop_type; + +struct init { + init() { prop_type::global_init(); } +}; + +int main() +{ + try { + { + std::stringstream ss; + TEST(!prop_type::has(ss)); + TEST(prop_type::get(ss).x==-1); + TEST(prop_type::has(ss)); + TEST(counter==1); + } + TEST(counter==0); + { + std::stringstream ss; + prop_type::set(propery(1),ss); + TEST(counter==1); + TEST(prop_type::get(ss).x==1); + } + TEST(counter==0); + { + std::stringstream ss; + prop_type::set(propery(1),ss); + TEST(counter==1); + TEST(prop_type::get(ss).x==1); + } + TEST(counter==0); + { + std::stringstream ss,ss2; + prop_type::set(propery(2),ss); + ss2.copyfmt(ss); + TEST(prop_type::get(ss).x==2); + TEST(prop_type::has(ss2)); + TEST(prop_type::has(ss)); + TEST(prop_type::get(ss2).x==2); + prop_type::get(ss2).x=3; + TEST(prop_type::get(ss2).x==3); + TEST(prop_type::get(ss).x==2); + TEST(counter==2); + TEST(imbued==0); + ss2.imbue(std::locale::classic()); + TEST(imbued==1); + } + TEST(counter==0); + }catch(std::exception const &e) { + std::cerr << "Fail:" << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + return 0; +} +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_locale.hpp b/src/boost/libs/locale/test/test_locale.hpp new file mode 100644 index 000000000..f3b182450 --- /dev/null +++ b/src/boost/libs/locale/test/test_locale.hpp @@ -0,0 +1,118 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCALE_TEST_H +#define BOOST_LOCALE_TEST_H +#include <stdexcept> +#include <sstream> +#include <iostream> +#include <iomanip> +#include <cstdlib> +#include <string> + +int error_counter=0; +int test_counter=0; + +#ifndef BOOST_LOCALE_ERROR_LIMIT +#define BOOST_LOCALE_ERROR_LIMIT 20 +#endif + + +#define THROW_IF_TOO_BIG(X) \ +do { \ + if((X) > BOOST_LOCALE_ERROR_LIMIT) \ + throw std::runtime_error("Error limits reached, stopping unit test"); \ +}while(0) + +#define TEST(X) \ + do { \ + test_counter++; \ + if(X) break; \ + std::cerr << "Error in line:"<<__LINE__ << " "#X << std::endl; \ + THROW_IF_TOO_BIG(error_counter++); \ + }while(0) +#endif + +#define TEST_THROWS(X,E) \ + do { \ + test_counter++; \ + try { X; } catch(E const &/*e*/ ) {break;} catch(...){} \ + std::cerr << "Error in line:"<<__LINE__ << " "#X << std::endl; \ + THROW_IF_TOO_BIG(error_counter++); \ + }while(0) + +#define FINALIZE() \ + do { \ + int passed=test_counter - error_counter; \ + std::cout << std::endl; \ + std::cout << "Passed "<<passed<<" tests" << std::endl; \ + if(error_counter >0 ) { \ + std::cout << "Failed "<<error_counter<<" tests"<<std::endl; \ + } \ + std::cout <<" "<< std::fixed << std::setprecision(1) \ + << std::setw(5) << 100.0 * passed / test_counter << \ + "% of tests completed sucsessefully" << std::endl; \ + return error_counter == 0 ? EXIT_SUCCESS : EXIT_FAILURE ; \ + }while(0) + + +inline unsigned utf8_next(std::string const &s,unsigned &pos) +{ + unsigned c=(unsigned char)s[pos++]; + if( (unsigned char)(c - 0xc0) >= 0x35) + return c; + unsigned l; + if(c < 192) + l = 0; + else if(c < 224) + l = 1; + else if(c < 240) + l = 2; + else + l = 3; + + c&=(1<<(6-l))-1; + + switch(l) { + case 3: + c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); + case 2: + c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); + case 1: + c = (c << 6) | (((unsigned char)s[pos++]) & 0x3F); + } + return c; +} + +template<typename Char> +std::basic_string<Char> to(std::string const &utf8) +{ + std::basic_string<Char> out; + unsigned i=0; + while(i<utf8.size()) { + unsigned point; + unsigned prev=i; + point = utf8_next(utf8,i); + if(sizeof(Char)==1 && point > 255) { + std::ostringstream ss; + ss << "Can't convert codepoint U" << std::hex << point <<"(" <<std::string(utf8.begin()+prev,utf8.begin()+i)<<") to Latin1"; + throw std::runtime_error(ss.str()); + } + else if(sizeof(Char)==2 && point >0xFFFF) { // Deal with surragates + point-=0x10000; + out+=static_cast<Char>(0xD800 | (point>>10)); + out+=static_cast<Char>(0xDC00 | (point & 0x3FF)); + continue; + } + out+=static_cast<Char>(point); + } + return out; +} + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/test/test_locale_tools.hpp b/src/boost/libs/locale/test/test_locale_tools.hpp new file mode 100644 index 000000000..daaa107c7 --- /dev/null +++ b/src/boost/libs/locale/test/test_locale_tools.hpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCLAE_TEST_LOCALE_TOOLS_HPP +#define BOOST_LOCLAE_TEST_LOCALE_TOOLS_HPP + +#include <boost/locale/encoding.hpp> + +#include <fstream> +#include <stdlib.h> +#include <stdio.h> + +template<typename Char> +std::basic_string<Char> to_correct_string(std::string const &e,std::locale /*l*/) +{ + return boost::locale::conv::to_utf<Char>(e,"UTF-8"); +} + + +template<> +inline std::string to_correct_string(std::string const &e,std::locale l) +{ + return boost::locale::conv::from_utf(e,l); +} + +bool has_std_locale(std::string const &name) +{ + try { + std::locale tmp(name.c_str()); + return true; + } + catch(...) { + return false; + } +} + +inline bool test_std_supports_SJIS_codecvt(std::string const &locale_name) +{ + bool res = true; + { + // Japan in Shift JIS/cp932 + char const *japan_932 = "\x93\xfa\x96\x7b"; + std::ofstream f("test-siftjis.txt"); + f<<japan_932; + f.close(); + } + try { + std::wfstream test; + test.imbue(std::locale(locale_name.c_str())); + test.open("test-siftjis.txt"); + // Japan in Unicode + std::wstring cmp = L"\u65e5\u672c"; + std::wstring ref; + test >> ref; + res = ref == cmp; + } + catch(std::exception const &) + { + res = false; + } + remove("test-siftjis.txt"); + return res; +} + +std::string get_std_name(std::string const &name,std::string *real_name = 0) +{ + if(has_std_locale(name)) { + if(real_name) + *real_name = name; + return name; + } + + #ifdef BOOST_WINDOWS + bool utf8=name.find("UTF-8")!=std::string::npos; + + if(name=="en_US.UTF-8" || name == "en_US.ISO8859-1") { + if(has_std_locale("English_United States.1252")) { + if(real_name) + *real_name = "English_United States.1252"; + return utf8 ? name : "en_US.windows-1252"; + } + return ""; + } + else if(name=="he_IL.UTF-8" || name == "he_IL.ISO8859-8") { + if(has_std_locale("Hebrew_Israel.1255")) { + if(real_name) + *real_name = "Hebrew_Israel.1255"; + return utf8 ? name : "he_IL.windows-1255"; + return name; + } + } + else if(name=="ru_RU.UTF-8") { + if(has_std_locale("Russian_Russia.1251")) { + if(real_name) + *real_name = "Russian_Russia.1251"; + return name; + } + } + else if(name == "tr_TR.UTF-8") { + if(has_std_locale("Turkish_Turkey.1254")) { + if(real_name) + *real_name = "Turkish_Turkey.1254"; + return name; + } + } + if(name == "ja_JP.SJIS") { + if(has_std_locale("Japanese_Japan.932")) { + if(real_name) + *real_name = "Japanese_Japan.932"; + return name; + } + return ""; + } + #endif + return ""; +} + + + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/boost/libs/locale/test/test_message.cpp b/src/boost/libs/locale/test/test_message.cpp new file mode 100644 index 000000000..2c0d365f3 --- /dev/null +++ b/src/boost/libs/locale/test/test_message.cpp @@ -0,0 +1,535 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include <boost/locale/generator.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/message.hpp> +#include <boost/locale/gnu_gettext.hpp> +#include <boost/locale/encoding.hpp> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <fstream> + +namespace bl = boost::locale; + +std::string backend; + +bool file_loader_is_actually_called = false; + +struct file_loader { + std::vector<char> operator()(std::string const &name,std::string const &/*encoding*/) const + { + std::vector<char> buffer; + std::ifstream f(name.c_str(),std::ifstream::binary); + if(!f) + return buffer; + f.seekg(0,std::ifstream::end); + size_t len = f.tellg(); + if(len == 0) + return buffer; + f.seekg(0); + buffer.resize(len,'\0'); + f.read(&buffer[0],len); + file_loader_is_actually_called = true; + return buffer; + } +}; + + +std::string same_s(std::string s) +{ + return s; +} + +std::wstring same_w(std::wstring s) +{ + return s; +} + +#ifdef BOOST_LOCALE_ENABLE_CHAR16_T +std::u16string same_u16(std::u16string s) +{ + return s; +} +#endif + +#ifdef BOOST_LOCALE_ENABLE_CHAR32_T +std::u32string same_u32(std::u32string s) +{ + return s; +} +#endif + +template<typename Char> +void strings_equal(std::string n_c,std::string n_s,std::string n_p,int n,std::string iexpected,std::locale const &l,std::string domain) +{ + typedef std::basic_string<Char> string_type; + string_type expected=to_correct_string<Char>(iexpected,l); + + string_type c = to<Char>(n_c.c_str()); + string_type s = to<Char>(n_s.c_str()); + string_type p = to<Char>(n_p.c_str()); + + if(domain=="default") { + TEST(bl::translate(c,s,p,n).str(l)==expected); + Char const *c_c_str = c.c_str(),*s_c_str=s.c_str(), *p_c_str=p.c_str(); // workaround gcc-3.4 bug + TEST(bl::translate(c_c_str,s_c_str,p_c_str,n).str(l)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + string_type tmp=bl::translate(c,s,p,n); + TEST(tmp==expected); + tmp=bl::translate(c,s,p,n).str(); + TEST(tmp==expected); + std::locale::global(tmp_locale); + + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::translate(c,s,p,n); + TEST(ss.str()==expected); + } + TEST( bl::translate(c,s,p,n).str(l,domain)==expected ); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + TEST(bl::translate(c,s,p,n).str(domain)==expected); + std::locale::global(tmp_locale); + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(c,s,p,n); + TEST(ss.str()==expected); + } + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(c.c_str(),s.c_str(),p.c_str(),n); + TEST(ss.str()==expected); + } +} + + + + +template<typename Char> +void strings_equal(std::string n_s,std::string n_p,int n,std::string iexpected,std::locale const &l,std::string domain) +{ + typedef std::basic_string<Char> string_type; + string_type expected=to_correct_string<Char>(iexpected,l); + string_type s = to<Char>(n_s.c_str()); + string_type p = to<Char>(n_p.c_str()); + if(domain=="default") { + TEST(bl::translate(s,p,n).str(l)==expected); + Char const *s_c_str=s.c_str(), *p_c_str=p.c_str(); // workaround gcc-3.4 bug + TEST(bl::translate(s_c_str,p_c_str,n).str(l)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + string_type tmp=bl::translate(s,p,n); + TEST(tmp==expected); + tmp=bl::translate(s,p,n).str(); + TEST(tmp==expected); + std::locale::global(tmp_locale); + + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::translate(s,p,n); + TEST(ss.str()==expected); + } + TEST(bl::translate(s,p,n).str(l,domain)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + TEST(bl::translate(s,p,n).str(domain)==expected); + std::locale::global(tmp_locale); + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(s,p,n); + TEST(ss.str()==expected); + } + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(s.c_str(),p.c_str(),n); + TEST(ss.str()==expected); + } +} + + +template<typename Char> +void strings_equal(std::string n_c,std::string n_original,std::string iexpected,std::locale const &l,std::string domain) +{ + typedef std::basic_string<Char> string_type; + string_type expected=to_correct_string<Char>(iexpected,l); + string_type original = to<Char>(n_original.c_str()); + string_type c = to<Char>(n_c.c_str()); + if(domain=="default") { + TEST(bl::translate(c,original).str(l)==expected); + Char const *original_c_str=original.c_str(); // workaround gcc-3.4 bug + Char const *context_c_str = c.c_str(); + TEST(bl::translate(context_c_str,original_c_str).str(l)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + string_type tmp=bl::translate(c,original); + TEST(tmp==expected); + tmp=bl::translate(c,original).str(); + TEST(tmp==expected); + std::locale::global(tmp_locale); + + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::translate(c,original); + TEST(ss.str()==expected); + } + TEST(bl::translate(c,original).str(l,domain)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + TEST(bl::translate(c,original).str(domain)==expected); + std::locale::global(tmp_locale); + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(c,original); + TEST(ss.str()==expected); + } + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(c.c_str(),original.c_str()); + TEST(ss.str()==expected); + } +} + + + + +template<typename Char> +void strings_equal(std::string n_original,std::string iexpected,std::locale const &l,std::string domain) +{ + typedef std::basic_string<Char> string_type; + string_type expected=to_correct_string<Char>(iexpected,l); + string_type original = to<Char>(n_original.c_str()); + if(domain=="default") { + TEST(bl::translate(original).str(l)==expected); + Char const *original_c_str=original.c_str(); // workaround gcc-3.4 bug + TEST(bl::translate(original_c_str).str(l)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + string_type tmp=bl::translate(original); + TEST(tmp==expected); + tmp=bl::translate(original).str(); + TEST(tmp==expected); + std::locale::global(tmp_locale); + + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::translate(original); + TEST(ss.str()==expected); + } + TEST(bl::translate(original).str(l,domain)==expected); + std::locale tmp_locale=std::locale(); + std::locale::global(l); + TEST(bl::translate(original).str(domain)==expected); + std::locale::global(tmp_locale); + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(original); + TEST(ss.str()==expected); + } + { + std::basic_ostringstream<Char> ss; + ss.imbue(l); + ss << bl::as::domain(domain) << bl::translate(original.c_str()); + TEST(ss.str()==expected); + } +} + +void test_cntranslate(std::string c,std::string s,std::string p,int n,std::string expected,std::locale const &l,std::string domain) +{ + strings_equal<char>(c,s,p,n,expected,l,domain); + strings_equal<wchar_t>(c,s,p,n,expected,l,domain); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(backend=="icu" || backend=="std") + strings_equal<char16_t>(c,s,p,n,expected,l,domain); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(backend=="icu" || backend=="std") + strings_equal<char32_t>(c,s,p,n,expected,l,domain); + #endif +} + + +void test_ntranslate(std::string s,std::string p,int n,std::string expected,std::locale const &l,std::string domain) +{ + strings_equal<char>(s,p,n,expected,l,domain); + strings_equal<wchar_t>(s,p,n,expected,l,domain); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(backend=="icu" || backend=="std") + strings_equal<char16_t>(s,p,n,expected,l,domain); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(backend=="icu" || backend=="std") + strings_equal<char32_t>(s,p,n,expected,l,domain); + #endif +} + +void test_ctranslate(std::string c,std::string original,std::string expected,std::locale const &l,std::string domain) +{ + strings_equal<char>(c,original,expected,l,domain); + strings_equal<wchar_t>(c,original,expected,l,domain); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(backend=="icu" || backend=="std") + strings_equal<char16_t>(c,original,expected,l,domain); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(backend=="icu" || backend=="std") + strings_equal<char32_t>(c,original,expected,l,domain); + #endif +} + + + +void test_translate(std::string original,std::string expected,std::locale const &l,std::string domain) +{ + strings_equal<char>(original,expected,l,domain); + strings_equal<wchar_t>(original,expected,l,domain); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(backend=="icu" || backend=="std") + strings_equal<char16_t>(original,expected,l,domain); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(backend=="icu" || backend=="std") + strings_equal<char32_t>(original,expected,l,domain); + #endif +} + +bool iso_8859_8_not_supported = false; + + +int main(int argc,char **argv) +{ + try { + std::string def[] = { + #ifdef BOOST_LOCALE_WITH_ICU + "icu" , + #endif + #ifndef BOOST_LOCALE_NO_STD_BACKEND + "std" , + #endif + #ifndef BOOST_LOCALE_NO_POSIX_BACKEND + "posix", + #endif + #ifndef BOOST_LOCALE_NO_WINAPI_BACKEND + "winapi", + #endif + }; + for(int type = 0 ; type < int(sizeof(def)/sizeof(def[0])) ; type ++ ) { + boost::locale::localization_backend_manager tmp_backend = boost::locale::localization_backend_manager::global(); + tmp_backend.select(def[type]); + boost::locale::localization_backend_manager::global(tmp_backend); + + backend = def[type]; + + std::cout << "Testing for backend --------- " << def[type] << std::endl; + + boost::locale::generator g; + g.add_messages_domain("simple"); + g.add_messages_domain("full"); + g.add_messages_domain("fall"); + if(argc==2) + g.add_messages_path(argv[1]); + else + g.add_messages_path("./"); + g.set_default_messages_domain("default"); + + + std::string locales[] = { "he_IL.UTF-8", "he_IL.ISO8859-8" }; + + for(unsigned i=0;i<sizeof(locales)/sizeof(locales[0]);i++){ + std::locale l; + + if(i==1) { + try { + l = g(locales[i]); + } + catch(boost::locale::conv::invalid_charset_error const &e) { + std::cout << "Looks like ISO-8859-8 is not supported! skipping" << std::endl; + iso_8859_8_not_supported = true; + continue; + } + } + else { + l = g(locales[i]); + } + + std::cout << " Testing "<<locales[i]<<std::endl; + std::cout << " single forms" << std::endl; + + test_translate("hello","שלום",l,"default"); + test_translate("hello","היי",l,"simple"); + test_translate("hello","hello",l,"undefined"); + test_translate("untranslated","untranslated",l,"default"); + // Check removal of old "context" information + test_translate("#untranslated","#untranslated",l,"default"); + test_translate("##untranslated","##untranslated",l,"default"); + test_ctranslate("context","hello","שלום בהקשר אחר",l,"default"); + test_translate("#hello","#שלום",l,"default"); + + std::cout << " plural forms" << std::endl; + + { + test_ntranslate("x day","x days",0,"x ימים",l,"default"); + test_ntranslate("x day","x days",1,"יום x",l,"default"); + test_ntranslate("x day","x days",2,"יומיים",l,"default"); + test_ntranslate("x day","x days",3,"x ימים",l,"default"); + test_ntranslate("x day","x days",20,"x יום",l,"default"); + + test_ntranslate("x day","x days",0,"x days",l,"undefined"); + test_ntranslate("x day","x days",1,"x day",l,"undefined"); + test_ntranslate("x day","x days",2,"x days",l,"undefined"); + test_ntranslate("x day","x days",20,"x days",l,"undefined"); + } + std::cout << " plural forms with context" << std::endl; + { + std::string inp = "context"; + std::string out = "בהקשר "; + + test_cntranslate(inp,"x day","x days",0,out+"x ימים",l,"default"); + test_cntranslate(inp,"x day","x days",1,out+"יום x",l,"default"); + test_cntranslate(inp,"x day","x days",2,out+"יומיים",l,"default"); + test_cntranslate(inp,"x day","x days",3,out+"x ימים",l,"default"); + test_cntranslate(inp,"x day","x days",20,out+"x יום",l,"default"); + + test_cntranslate(inp,"x day","x days",0,"x days",l,"undefined"); + test_cntranslate(inp,"x day","x days",1,"x day",l,"undefined"); + test_cntranslate(inp,"x day","x days",2,"x days",l,"undefined"); + test_cntranslate(inp,"x day","x days",20,"x days",l,"undefined"); + } + } + std::cout << " Testing fallbacks" <<std::endl; + test_translate("test","he_IL",g("he_IL.UTF-8"),"full"); + test_translate("test","he",g("he_IL.UTF-8"),"fall"); + + std::cout << " Testing automatic conversions " << std::endl; + std::locale::global(g("he_IL.UTF-8")); + + + TEST(same_s(bl::translate("hello"))=="שלום"); + TEST(same_w(bl::translate(to<wchar_t>("hello")))==to<wchar_t>("שלום")); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + if(backend=="icu" || backend=="std") + TEST(same_u16(bl::translate(to<char16_t>("hello")))==to<char16_t>("שלום")); + #endif + + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + if(backend=="icu" || backend=="std") + TEST(same_u32(bl::translate(to<char32_t>("hello")))==to<char32_t>("שלום")); + #endif + + } + + std::cout << "Testing custom file system support" << std::endl; + { + boost::locale::gnu_gettext::messages_info info; + info.language = "he"; + info.country = "IL"; + info.encoding="UTF-8"; + if(argc==2) + info.paths.push_back(argv[1]); + else + info.paths.push_back("./"); + + info.domains.push_back(bl::gnu_gettext::messages_info::domain("default")); + info.callback = file_loader(); + + std::locale l(std::locale::classic(),boost::locale::gnu_gettext::create_messages_facet<char>(info)); + TEST(file_loader_is_actually_called); + TEST(bl::translate("hello").str(l)=="שלום"); + } + if(iso_8859_8_not_supported) + { + std::cout << "ISO 8859-8 not supported so skipping non-US-ASCII keys" << std::endl; + } + else + { + std::cout << "Testing non-US-ASCII keys" << std::endl; + std::cout << " UTF-8 keys" << std::endl; + { + boost::locale::generator g; + g.add_messages_domain("default"); + if(argc==2) + g.add_messages_path(argv[1]); + else + g.add_messages_path("./"); + + std::locale l = g("he_IL.UTF-8"); + + // narrow + TEST(bl::gettext("בדיקה",l)=="test"); + TEST(bl::gettext("לא קיים",l)=="לא קיים"); + + // wide + std::wstring wtest = bl::conv::to_utf<wchar_t>("בדיקה","UTF-8"); + std::wstring wmiss = bl::conv::to_utf<wchar_t>("לא קיים","UTF-8"); + TEST(bl::gettext(wtest.c_str(),l)==L"test"); + TEST(bl::gettext(wmiss.c_str(),l)==wmiss); + + l=g("he_IL.ISO-8859-8"); + + // conversion with substitution + TEST(bl::gettext("test-あにま-בדיקה",l)==bl::conv::from_utf("test--בדיקה","ISO-8859-8")); + } + + std::cout << " `ANSI' keys" << std::endl; + + { + boost::locale::generator g; + g.add_messages_domain("default/ISO-8859-8"); + if(argc==2) + g.add_messages_path(argv[1]); + else + g.add_messages_path("./"); + + std::locale l = g("he_IL.UTF-8"); + + // narrow non-UTF-8 keys + // match + TEST(bl::gettext(bl::conv::from_utf("בדיקה","ISO-8859-8").c_str(),l)=="test"); + // conversion + TEST(bl::gettext(bl::conv::from_utf("לא קיים","ISO-8859-8").c_str(),l)=="לא קיים"); + } + } + // Test compiles + { + bl::gettext(""); + bl::gettext(L""); + bl::dgettext("",""); + bl::dgettext("",L""); + bl::pgettext("",""); + bl::pgettext(L"",L""); + bl::dpgettext("","",""); + bl::dpgettext("",L"",L""); + bl::ngettext("","",1); + bl::ngettext(L"",L"",1); + bl::dngettext("","","",1); + bl::dngettext("",L"",L"",1); + bl::npgettext("","","",1); + bl::npgettext(L"",L"",L"",1); + bl::dnpgettext("","","","",1); + bl::dnpgettext("",L"",L"",L"",1); + } + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_posix_collate.cpp b/src/boost/libs/locale/test/test_posix_collate.cpp new file mode 100644 index 000000000..966302089 --- /dev/null +++ b/src/boost/libs/locale/test/test_posix_collate.cpp @@ -0,0 +1,120 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifdef BOOST_LOCALE_NO_POSIX_BACKEND +#include <iostream> +int main() +{ + std::cout << "POSIX Backend is not build... Skipping" << std::endl; +} +#else +#include <boost/locale/config.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include "test_posix_tools.hpp" +#include <iostream> + +int get_sign(int x) +{ + if(x<0) + return -1; + else if(x==0) + return 0; + return 1; +} + +template<typename CharType> +void test_one(std::locale const &l,std::string ia,std::string ib,int diff) +{ + std::basic_string<CharType> a=to_correct_string<CharType>(ia,l); + std::basic_string<CharType> b=to_correct_string<CharType>(ib,l); + if(diff < 0) { + TEST(l(a,b)); + TEST(!l(b,a)); + } + else if(diff == 0) { + TEST(!l(a,b)); + TEST(!l(b,a)); + } + else { + TEST(!l(a,b)); + TEST(l(b,a)); + } + + std::collate<CharType> const &col = std::use_facet<std::collate<CharType> >(l); + + TEST(diff == col.compare(a.c_str(),a.c_str()+a.size(),b.c_str(),b.c_str()+b.size())); + TEST(diff == get_sign(col.transform(a.c_str(),a.c_str()+a.size()).compare(col.transform(b.c_str(),b.c_str()+b.size())))); + if(diff == 0) { + TEST(col.hash(a.c_str(),a.c_str()+a.size()) == col.hash(b.c_str(),b.c_str()+b.size())); + } +} + +template<typename CharType> +void test_char() +{ + boost::locale::generator gen; + + std::cout << "- Testing at least C" << std::endl; + + std::locale l = gen("en_US.UTF-8"); + + test_one<CharType>(l,"a","b",-1); + test_one<CharType>(l,"a","a",0); + + std::string name; + + + #if !defined(__APPLE__) && !defined(__FreeBSD__) + std::string names[] = { "en_US.UTF-8", "en_US.ISO8859-1" }; + for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) { + if(have_locale(names[i])) { + name = names[i]; + std::cout << "- Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"a","ç",-1); + test_one<CharType>(l,"ç","d",-1); + } + else { + std::cout << "- " << names[i] << " not supported, skipping" << std::endl; + } + } + #else + std::cout << "- Collation is broken on this OS C standard library, skipping" << std::endl; + #endif +} + + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("posix"); + boost::locale::localization_backend_manager::global(mgr); + + std::cout << "Testing char" << std::endl; + test_char<char>(); + std::cout << "Testing wchar_t" << std::endl; + test_char<wchar_t>(); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} +#endif // NO POSIX +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_posix_convert.cpp b/src/boost/libs/locale/test/test_posix_convert.cpp new file mode 100644 index 000000000..76d5c6522 --- /dev/null +++ b/src/boost/libs/locale/test/test_posix_convert.cpp @@ -0,0 +1,122 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifdef BOOST_LOCALE_NO_POSIX_BACKEND +#include <iostream> +int main() +{ + std::cout << "POSIX Backend is not build... Skipping" << std::endl; +} +#else +#include <boost/locale/conversion.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include "test_posix_tools.hpp" +#include <iostream> + +#include <wctype.h> + + +template<typename CharType> +void test_one(std::locale const &l,std::string src,std::string tgtl,std::string tgtu) +{ + TEST(boost::locale::to_upper(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtu,l)); + TEST(boost::locale::to_lower(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); + TEST(boost::locale::fold_case(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); +} + +template<typename CharType> +void test_char() +{ + boost::locale::generator gen; + + std::cout << "- Testing at least C" << std::endl; + + std::locale l = gen("en_US.UTF-8"); + + test_one<CharType>(l,"Hello World i","hello world i","HELLO WORLD I"); + + std::string name = "en_US.UTF-8"; + if(have_locale(name)) { + std::cout << "- Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"Façade","façade","FAÇADE"); + } + else { + std::cout << "- en_US.UTF-8 is not supported, skipping" << std::endl; + } + + name = "en_US.ISO8859-1"; + if(have_locale(name)) { + std::cout << "Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"Hello World","hello world","HELLO WORLD"); + #if defined(__APPLE__) || defined(__FreeBSD__) + if(sizeof(CharType)!=1) + #endif + test_one<CharType>(l,"Façade","façade","FAÇADE"); + } + else { + std::cout << "- en_US.ISO8859-1 is not supported, skipping" << std::endl; + } + + name = "tr_TR.UTF-8"; + if(have_locale(name)) { + std::cout << "Testing " << name << std::endl; + locale_t cl = newlocale(LC_ALL_MASK,name.c_str(),0); + try { + TEST(cl); + if(towupper_l(L'i',cl) == 0x130) { + test_one<CharType>(gen(name),"i","i","İ"); + } + else { + std::cout <<" Turkish locale is not supported well" << std::endl; + } + } + catch(...) { + if(cl) freelocale(cl); + throw; + } + if(cl) freelocale(cl); + + } + else + { + std::cout << "- tr_TR.UTF-8 is not supported, skipping" << std::endl; + } +} + + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("posix"); + boost::locale::localization_backend_manager::global(mgr); + + std::cout << "Testing char" << std::endl; + test_char<char>(); + std::cout << "Testing wchar_t" << std::endl; + test_char<wchar_t>(); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // POSIX +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_posix_formatting.cpp b/src/boost/libs/locale/test/test_posix_formatting.cpp new file mode 100644 index 000000000..55e83cf5d --- /dev/null +++ b/src/boost/libs/locale/test/test_posix_formatting.cpp @@ -0,0 +1,281 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifdef BOOST_LOCALE_NO_POSIX_BACKEND +#include <iostream> +int main() +{ + std::cout << "POSIX Backend is not build... Skipping" << std::endl; +} +#else +#include <boost/locale/formatting.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include "test_posix_tools.hpp" +#include <iostream> + +#include <time.h> +#include <monetary.h> +#include <assert.h> +#include <langinfo.h> + +//#define DEBUG_FMT + +bool equal(std::string const &s1,std::string const &s2,locale_t /*lc*/) +{ + return s1 == s2; +} + +bool equal(std::wstring const &s1,std::string const &s2,locale_t lc) +{ + return s1 == boost::locale::conv::to_utf<wchar_t>(s2,nl_langinfo_l(CODESET,lc)); +} + +template<typename CharType> +std::basic_string<CharType> conv_to_char(char const *p) +{ + std::basic_string<CharType> r; + while(*p) + r+=CharType(*p++); + return r; +} + + +template<typename CharType,typename RefCharType> +void test_by_char(std::locale const &l,locale_t lreal) +{ + typedef std::basic_stringstream<CharType> ss_type; + + using namespace boost::locale; + + { + std::cout << "- Testing as::posix" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + TEST(ss.str()==to_correct_string<CharType>("1045.45",l)); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + #endif + } + + { + std::cout << "- Testing as::number" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << as::number; + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + + if(std::use_facet<boost::locale::info>(l).country()=="US") + TEST(equal(ss.str(),"1,045.45",lreal)); + } + + { + std::cout << "- Testing as::currency national " << std::endl; + + char buf[256]; + strfmon_l(buf,256,lreal,"%n",1043.34); + + ss_type ss; + ss.imbue(l); + + ss << as::currency; + ss << 1043.34; + TEST(ss); + + TEST(equal(ss.str(),buf,lreal)); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(buf,"UTF-8") << "]\n" ; + #endif + + } + + { + std::cout << "- Testing as::currency iso" << std::endl; + char buf[256]; + strfmon_l(buf,256,lreal,"%i",1043.34); + ss_type ss; + ss.imbue(l); + + ss << as::currency << as::currency_iso; + ss << 1043.34; + TEST(ss); + + TEST(equal(ss.str(),buf,lreal)); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(buf,"UTF-8") << "]\n" ; + #endif + } + + + { + std::cout << "- Testing as::date/time" << std::endl; + ss_type ss; + ss.imbue(l); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:05 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + ss << as::time_zone("GMT"); + + ss << as::date << a_datetime << CharType('\n'); + ss << as::time << a_datetime << CharType('\n'); + ss << as::datetime << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+01:00"); + ss << as::ftime(conv_to_char<CharType>("%H")) << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+00:15"); + ss << as::ftime(conv_to_char<CharType>("%M")) << a_datetime << CharType('\n'); + + std::tm tm=*gmtime(&a_datetime); + char buf[256]; + strftime_l(buf,sizeof(buf),"%x\n%X\n%c\n16\n48\n",&tm,lreal); + + TEST(equal(ss.str(),buf,lreal)); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(buf,"UTF-8") << "]\n" ; + #endif + } + +} + +int main() +{ + locale_t lreal = 0; + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("posix"); + boost::locale::localization_backend_manager::global(mgr); + boost::locale::generator gen; + std::string name; + + { + std::cout << "en_US.UTF locale" << std::endl; + name="en_US.UTF-8"; + if(!have_locale(name)) { + std::cout << "en_US.UTF-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name); + lreal=newlocale(LC_ALL_MASK,name.c_str(),0); + assert(lreal); + std::cout << "UTF-8" << std::endl; + + test_by_char<char,char>(l1,lreal); + + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,char>(l1,lreal); + freelocale(lreal); + lreal = 0; + } + } + { + std::cout << "en_US.Latin-1 locale" << std::endl; + std::string name = "en_US.ISO8859-1"; + if(!have_locale(name)) { + std::cout << "en_US.ISO8859-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name); + lreal=newlocale(LC_ALL_MASK,name.c_str(),0); + assert(lreal); + test_by_char<char,char>(l1,lreal); + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,char>(l1,lreal); + freelocale(lreal); + lreal = 0; + } + } + { + std::cout << "he_IL.UTF locale" << std::endl; + name="he_IL.UTF-8"; + if(!have_locale(name)) { + std::cout << name << " not supported" << std::endl; + } + else { + std::locale l1=gen(name); + lreal=newlocale(LC_ALL_MASK,name.c_str(),0); + assert(lreal); + std::cout << "UTF-8" << std::endl; + + test_by_char<char,char>(l1,lreal); + + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,char>(l1,lreal); + freelocale(lreal); + lreal = 0; + } + } + { + std::cout << "he_IL.ISO locale" << std::endl; + std::string name = "he_IL.ISO8859-8"; + if(!have_locale(name)) { + std::cout << name <<" not supported" << std::endl; + } + else { + std::locale l1=gen(name); + lreal=newlocale(LC_ALL_MASK,name.c_str(),0); + assert(lreal); + test_by_char<char,char>(l1,lreal); + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,char>(l1,lreal); + freelocale(lreal); + lreal = 0; + } + } + { + std::cout << "Testing UTF-8 punct issues" << std::endl; + std::string name = "ru_RU.UTF-8"; + if(!have_locale(name)) { + std::cout << "- No russian locale" << std::endl; + } + else { + std::locale l1=gen(name); + std::ostringstream ss; + ss.imbue(l1); + ss << std::setprecision(10) ; + ss << boost::locale::as::number << 12345.45; + std::string v=ss.str(); + TEST(v == "12345,45" || v == "12 345,45" || v=="12.345,45"); + } + } + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + if(lreal) + freelocale(lreal); + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // posix +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_posix_tools.hpp b/src/boost/libs/locale/test/test_posix_tools.hpp new file mode 100644 index 000000000..6be9c589f --- /dev/null +++ b/src/boost/libs/locale/test/test_posix_tools.hpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_LOCLAE_TEST_LOCALE_POSIX_TOOLS_HPP +#define BOOST_LOCLAE_TEST_LOCALE_POSIX_TOOLS_HPP + +#include <locale.h> +#include <string> + +#if defined(__APPLE__) || defined(__FreeBSD__) +#include <xlocale.h> +#endif + +inline bool have_locale(std::string const &name) +{ + locale_t l=newlocale(LC_ALL_MASK,name.c_str(),0); + if(l) { + freelocale(l); + return true; + } + return false; +} + +#endif +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + diff --git a/src/boost/libs/locale/test/test_std_collate.cpp b/src/boost/libs/locale/test/test_std_collate.cpp new file mode 100644 index 000000000..1f01b766a --- /dev/null +++ b/src/boost/libs/locale/test/test_std_collate.cpp @@ -0,0 +1,129 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifdef BOOST_LOCALE_NO_STD_BACKEND +#include <iostream> +int main() +{ + std::cout << "STD Backend is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/config.hpp> +#include <boost/locale/conversion.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <iostream> + +int get_sign(int x) +{ + if(x<0) + return -1; + else if(x==0) + return 0; + return 1; +} + +template<typename CharType> +void test_one(std::locale const &l,std::string ia,std::string ib,int diff) +{ + std::basic_string<CharType> a=to_correct_string<CharType>(ia,l); + std::basic_string<CharType> b=to_correct_string<CharType>(ib,l); + if(diff < 0) { + TEST(l(a,b)); + TEST(!l(b,a)); + } + else if(diff == 0) { + TEST(!l(a,b)); + TEST(!l(b,a)); + } + else { + TEST(!l(a,b)); + TEST(l(b,a)); + } + + std::collate<CharType> const &col = std::use_facet<std::collate<CharType> >(l); + + TEST(diff == col.compare(a.c_str(),a.c_str()+a.size(),b.c_str(),b.c_str()+b.size())); + TEST(diff == get_sign(col.transform(a.c_str(),a.c_str()+a.size()).compare(col.transform(b.c_str(),b.c_str()+b.size())))); + if(diff == 0) { + TEST(col.hash(a.c_str(),a.c_str()+a.size()) == col.hash(b.c_str(),b.c_str()+b.size())); + } +} + +template<typename CharType> +void test_char() +{ + boost::locale::generator gen; + + std::cout << "- Testing at least C" << std::endl; + + std::locale l = gen("en_US.UTF-8"); + + test_one<CharType>(l,"a","b",-1); + test_one<CharType>(l,"a","a",0); + + std::string name; + + #if defined(_LIBCPP_VERSION) && (defined(__APPLE__) || defined(__FreeBSD__)) + std::cout << "- Collation is broken on this OS's standard C++ library, skipping" << std::endl; + #else + std::string names[] = { "en_US.UTF-8", "en_US.ISO8859-1" }; + for(unsigned i=0;i<sizeof(names)/sizeof(names[0]);i++) { + name = get_std_name(names[i]); + if(!name.empty()) { + std::cout << "- Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"a","ç",-1); + test_one<CharType>(l,"ç","d",-1); + } + else { + std::cout << "- " << names[i] << " not supported, skipping" << std::endl; + } + } + #endif +} + + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("std"); + boost::locale::localization_backend_manager::global(mgr); + + std::cout << "Testing char" << std::endl; + test_char<char>(); + std::cout << "Testing wchar_t" << std::endl; + test_char<wchar_t>(); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "Testing char16_t" << std::endl; + test_char<char16_t>(); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "Testing char32_t" << std::endl; + test_char<char32_t>(); + #endif + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // NO STD + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_std_convert.cpp b/src/boost/libs/locale/test/test_std_convert.cpp new file mode 100644 index 000000000..6259e5547 --- /dev/null +++ b/src/boost/libs/locale/test/test_std_convert.cpp @@ -0,0 +1,120 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifdef BOOST_LOCALE_NO_STD_BACKEND +#include <iostream> +int main() +{ + std::cout << "STD Backend is not build... Skipping" << std::endl; +} +#else + + + +#include <boost/locale/conversion.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <iostream> + +template<typename CharType> +void test_one(std::locale const &l,std::string src,std::string tgtl,std::string tgtu) +{ + TEST(boost::locale::to_upper(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtu,l)); + TEST(boost::locale::to_lower(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); + TEST(boost::locale::fold_case(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); +} + +template<typename CharType> +void test_char() +{ + boost::locale::generator gen; + + std::cout << "- Testing at least C" << std::endl; + + std::locale l = gen("en_US.UTF-8"); + + test_one<CharType>(l,"Hello World i","hello world i","HELLO WORLD I"); + + std::string name; + + name = get_std_name("en_US.UTF-8"); + if(!name.empty()) { + std::cout << "- Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"Façade","façade","FAÇADE"); + } + else { + std::cout << "- en_US.UTF-8 is not supported, skipping" << std::endl; + } + + name = get_std_name("en_US.ISO8859-1"); + if(!name.empty()) { + std::cout << "Testing " << name << std::endl; + std::locale l=gen(name); + test_one<CharType>(l,"Hello World","hello world","HELLO WORLD"); + test_one<CharType>(l,"Façade","façade","FAÇADE"); + } + else { + std::cout << "- en_US.ISO8859-1 is not supported, skipping" << std::endl; + } + std::string real_name; + name = get_std_name("tr_TR.UTF-8",&real_name); + if(!name.empty()) { + std::cout << "Testing " << name << std::endl; + if(std::use_facet<std::ctype<wchar_t> >(std::locale(real_name.c_str())).toupper(L'i')!=L'I') { + std::locale l=gen(name); + test_one<CharType>(l,"i","i","İ"); + } + else { + std::cout << "Standard library does not support this locale's case conversion correctly" << std::endl; + } + } + else + { + std::cout << "- tr_TR.UTF-8 is not supported, skipping" << std::endl; + } +} + + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("std"); + boost::locale::localization_backend_manager::global(mgr); + + std::cout << "Testing char" << std::endl; + test_char<char>(); + std::cout << "Testing wchar_t" << std::endl; + test_char<wchar_t>(); + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "Testing char16_t" << std::endl; + test_char<char16_t>(); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "Testing char32_t" << std::endl; + test_char<char32_t>(); + #endif + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // no std +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_std_formatting.cpp b/src/boost/libs/locale/test/test_std_formatting.cpp new file mode 100644 index 000000000..30cb4e1bd --- /dev/null +++ b/src/boost/libs/locale/test/test_std_formatting.cpp @@ -0,0 +1,371 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + + +#ifdef BOOST_LOCALE_NO_STD_BACKEND +#include <iostream> +int main() +{ + std::cout << "STD Backend is not build... Skipping" << std::endl; +} +#else + + +#include <boost/locale/formatting.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <iostream> + +//#define DEBUG_FMT + +#include <boost/config.hpp> +#ifdef BOOST_MSVC +# pragma warning(disable : 4996) +#endif + + +template<typename C1,typename C2> +bool equal(std::basic_string<C1> const &s1,std::basic_string<C2> const &s2) +{ + return boost::locale::conv::from_utf(s1,"UTF-8") == boost::locale::conv::from_utf(s2,"UTF-8"); +} + +template<> +bool equal(std::string const &s1,std::string const &s2) +{ + return s1==s2; +} + +template<typename CharType> +std::basic_string<CharType> conv_to_char(char const *p) +{ + std::basic_string<CharType> r; + while(*p) + r+=CharType(*p++); + return r; +} + + +template<typename CharType,typename RefCharType> +void test_by_char(std::locale const &l,std::locale const &lreal) +{ + typedef std::basic_stringstream<CharType> ss_type; + typedef std::basic_stringstream<RefCharType> ss_ref_type; + + using namespace boost::locale; + + { + std::cout << "- Testing as::posix" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + TEST(ss.str()==to_correct_string<CharType>("1045.45",l)); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + #endif + } + + { + std::cout << "- Testing as::number" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << as::number; + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + + ss_ref_type ss_ref; + ss_ref.imbue(lreal); + + ss_ref << 1045.45; + + TEST(equal(ss.str(),ss_ref.str())); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(ss_ref.str(),"UTF-8") << "]\n" ; + #endif + } + + { + std::cout << "- Testing as::currency national " << std::endl; + + bool bad_parsing = false; + ss_ref_type ss_ref; + ss_ref.imbue(lreal); + ss_ref << std::showbase; + std::use_facet<std::money_put<RefCharType> >(lreal).put(ss_ref,false,ss_ref,RefCharType(' '),104334); + { // workaround MSVC library issues + std::ios_base::iostate err=std::ios_base::iostate(); + typename std::money_get<RefCharType>::iter_type end; + long double tmp; + std::use_facet<std::money_get<RefCharType> >(lreal).get(ss_ref,end,false,ss_ref,err,tmp); + if(err & std::ios_base::failbit) { + std::cout << "-- Looks like standard library does not support parsing well" << std::endl; + bad_parsing=true; + } + } + + ss_type ss; + ss.imbue(l); + + ss << as::currency; + ss << 1043.34; + if(!bad_parsing) { + TEST(ss); + double v1; + ss >> v1; + } + + + TEST(equal(ss.str(),ss_ref.str())); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(ss_ref.str(),"UTF-8") << "]\n" ; + #endif + + } + + { + std::cout << "- Testing as::currency iso" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << as::currency << as::currency_iso; + ss << 1043.34; + TEST(ss); + double v1; + ss >> v1; + TEST(ss); + TEST(v1==1043.34); + + ss_ref_type ss_ref; + ss_ref.imbue(lreal); + ss_ref << std::showbase; + std::use_facet<std::money_put<RefCharType> >(lreal).put(ss_ref,true,ss_ref,RefCharType(' '),104334); + + TEST(equal(ss.str(),ss_ref.str())); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(ss_ref.str(),"UTF-8") << "]\n" ; + #endif + } + + + { + std::cout << "- Testing as::date/time" << std::endl; + ss_type ss; + ss.imbue(l); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:05 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + ss << as::time_zone("GMT"); + + ss << as::date << a_datetime << CharType('\n'); + ss << as::time << a_datetime << CharType('\n'); + ss << as::datetime << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+01:00"); + ss << as::ftime(conv_to_char<CharType>("%H")) << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+00:15"); + ss << as::ftime(conv_to_char<CharType>("%M")) << a_datetime << CharType('\n'); + + ss_ref_type ss_ref; + ss_ref.imbue(lreal); + + std::basic_string<RefCharType> rfmt(conv_to_char<RefCharType>("%x\n%X\n%c\n16\n48\n")); + + std::tm tm=*gmtime(&a_datetime); + + std::use_facet<std::time_put<RefCharType> >(lreal).put(ss_ref,ss_ref,RefCharType(' '),&tm,rfmt.c_str(),rfmt.c_str()+rfmt.size()); + + TEST(equal(ss.str(),ss_ref.str())); + #ifdef DEBUG_FMT + std::cout << "[" << boost::locale::conv::from_utf(ss.str(),"UTF-8") << "]=\n" ; + std::cout << "[" << boost::locale::conv::from_utf(ss_ref.str(),"UTF-8") << "]\n" ; + #endif + } + +} + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("std"); + boost::locale::localization_backend_manager::global(mgr); + boost::locale::generator gen; + + { + std::cout << "en_US.UTF locale" << std::endl; + std::string real_name; + std::string name = get_std_name("en_US.UTF-8",&real_name); + if(name.empty()) { + std::cout << "en_US.UTF-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name),l2(real_name.c_str()); + std::cout << "UTF-8" << std::endl; + if(name==real_name) + test_by_char<char,char>(l1,l2); + else + test_by_char<char,wchar_t>(l1,l2); + + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,wchar_t>(l1,l2); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "char16 UTF-16" << std::endl; + test_by_char<char16_t,char16_t>(l1,l2); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "char32 UTF-32" << std::endl; + test_by_char<char32_t,char32_t>(l1,l2); + #endif + } + } + { + std::cout << "en_US.Latin-1 locale" << std::endl; + std::string real_name; + std::string name = get_std_name("en_US.ISO8859-1",&real_name); + if(name.empty()) { + std::cout << "en_US.ISO8859-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name),l2(real_name.c_str()); + test_by_char<char,char>(l1,l2); + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,wchar_t>(l1,l2); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "char16 UTF-16" << std::endl; + test_by_char<char16_t,char16_t>(l1,l2); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "char32 UTF-32" << std::endl; + test_by_char<char32_t,char32_t>(l1,l2); + #endif + } + } + { + std::cout << "he_IL.UTF locale" << std::endl; + std::string real_name; + std::string name = get_std_name("he_IL.UTF-8",&real_name); + if(name.empty()) { + std::cout << "he_IL.UTF-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name),l2(real_name.c_str()); + std::cout << "UTF-8" << std::endl; + if(name==real_name) + test_by_char<char,char>(l1,l2); + else + test_by_char<char,wchar_t>(l1,l2); + + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,wchar_t>(l1,l2); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "char16 UTF-16" << std::endl; + test_by_char<char16_t,char16_t>(l1,l2); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "char32 UTF-32" << std::endl; + test_by_char<char32_t,char32_t>(l1,l2); + #endif + } + } + { + std::cout << "he_IL.ISO8859-8 locale" << std::endl; + std::string real_name; + std::string name = get_std_name("he_IL.ISO8859-8",&real_name); + if(name.empty()) { + std::cout << "he_IL.ISO8859-8 not supported" << std::endl; + } + else { + std::locale l1=gen(name),l2(real_name.c_str()); + test_by_char<char,char>(l1,l2); + std::cout << "Wide UTF-" << sizeof(wchar_t) * 8 << std::endl; + test_by_char<wchar_t,wchar_t>(l1,l2); + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + std::cout << "char16 UTF-16" << std::endl; + test_by_char<char16_t,char16_t>(l1,l2); + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + std::cout << "char32 UTF-32" << std::endl; + test_by_char<char32_t,char32_t>(l1,l2); + #endif + } + } + { + std::cout << "Testing UTF-8 punct workaround" << std::endl; + std::string real_name; + std::string name = get_std_name("ru_RU.UTF-8",&real_name); + if(name.empty()) { + std::cout << "- No russian locale" << std::endl; + } + else if(name != real_name) { + std::cout << "- Not having UTF-8 locale, no need for workaround" << std::endl; + } + else { + std::locale l1=gen(name),l2(real_name.c_str()); + bool fails = false; + try { + std::ostringstream ss; + ss.imbue(l2); + ss << 12345.45; + boost::locale::conv::from_utf<char>(ss.str(),"windows-1251",boost::locale::conv::stop); + fails = false; + } + catch(...) { + fails = true; + } + + if(!fails) { + std::cout << "- No invalid UTF. No need to check"<<std::endl; + } + else { + std::ostringstream ss; + ss.imbue(l1); + ss << std::setprecision(10) ; + ss << boost::locale::as::number << 12345.45; + TEST(ss.str() == "12 345,45" || ss.str()=="12345,45"); + } + } + } + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // no std + + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_utf.cpp b/src/boost/libs/locale/test/test_utf.cpp new file mode 100644 index 000000000..3476154da --- /dev/null +++ b/src/boost/libs/locale/test/test_utf.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <boost/locale/utf.hpp> + +#include <string.h> + +using namespace boost::locale::utf; + +char *make2(unsigned v) +{ + static unsigned char buf[3] = {0}; + buf[0] = 0xC0 | (v >> 6); + buf[1] = 0x80 | (v & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +char *make3(unsigned v) +{ + static unsigned char buf[4] = {0}; + buf[0] = 0xE0 | ((v >> 12) ) ; + buf[1] = 0x80 | ((v >> 6) & 0x3F ); + buf[2] = 0x80 | ((v >> 0) & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +char *make4(unsigned v) +{ + static unsigned char buf[5] = {0}; + buf[0] = 0xF0 | ((v >> 18) ) ; + buf[1] = 0x80 | ((v >> 12) & 0x3F ); + buf[2] = 0x80 | ((v >> 6) & 0x3F ); + buf[3] = 0x80 | ((v >> 0) & 0x3F ); + return reinterpret_cast<char*>(buf); +} + +boost::uint32_t const *u32_seq(boost::uint32_t a) +{ + static boost::uint32_t buf[2]; + buf[0]=a; + buf[1]=0; + return buf; +} + +boost::uint16_t const *u16_seq(boost::uint16_t a) +{ + static boost::uint16_t buf[2]; + buf[0]=a; + buf[1]=0; + return buf; +} + +boost::uint16_t const *u16_seq(boost::uint16_t a,boost::uint16_t b) +{ + static boost::uint16_t buf[3]; + buf[0]=a; + buf[1]=b; + buf[2]=0; + return buf; +} + +template<typename CharType> +void test_to(CharType const *s,unsigned codepoint) +{ + CharType const *begin = s; + CharType const *end = begin; + + while(*end) + end++; + + typedef utf_traits<CharType> tr; + + TEST(tr::max_width == 4 / sizeof(CharType)); + + TEST(tr::template decode<CharType const *>(begin,end) == codepoint); + + if(codepoint == incomplete || codepoint != illegal) + TEST(end == begin); + + if(codepoint == incomplete) { + TEST(*s== 0 || 0 < tr::trail_length(*s)); + TEST(tr::trail_length(*s) + 1 > end - s); + } + + if(codepoint != incomplete && codepoint != illegal) { + begin=s; + TEST(tr::is_lead(*begin)); + TEST(!tr::is_trail(*begin)); + begin++; + while(begin!=end) { + TEST(tr::is_trail(*begin)); + TEST(!tr::is_lead(*begin)); + begin++; + } + TEST(tr::width(codepoint)==end - s); + TEST(tr::trail_length(*s) == tr::width(codepoint) - 1); + begin = s; + TEST(tr::decode_valid(begin) == codepoint); + TEST(begin == end); + } +} + +template<typename CharType> +void test_from(CharType const *str,unsigned codepoint) +{ + CharType buf[5] = {1,1,1,1,1}; + CharType *p=buf; + p = utf_traits<CharType>::template encode<CharType *>(codepoint,p); + CharType const *end = str; + while(*end) + end++; + TEST(end - str == p-buf ); + TEST(*p); + *p=0; + TEST(memcmp(str,buf,sizeof(CharType) * (end-str))==0); +} + + +int main() +{ + try { + + std::cout << "Test UTF-8" << std::endl; + std::cout << "- From UTF-8" << std::endl; + + + std::cout << "-- Correct" << std::endl; + + test_to("\x7f",0x7f); + test_to("\xc2\x80",0x80); + test_to("\xdf\xbf",0x7ff); + test_to("\xe0\xa0\x80",0x800); + test_to("\xef\xbf\xbf",0xffff); + test_to("\xf0\x90\x80\x80",0x10000); + test_to("\xf4\x8f\xbf\xbf",0x10ffff); + + std::cout << "-- Too big" << std::endl; + test_to("\xf4\x9f\x80\x80",illegal); // 11 0000 + test_to("\xfb\xbf\xbf\xbf",illegal); // 3ff ffff + test_to("\xf8\x90\x80\x80\x80",illegal); // 400 0000 + test_to("\xfd\xbf\xbf\xbf\xbf\xbf",illegal); // 7fff ffff + + std::cout << "-- Invalid length" << std::endl; + + /// test that this actually works + test_to(make2(0x80),0x80); + test_to(make2(0x7ff),0x7ff); + + test_to(make3(0x800),0x800); + test_to(make3(0xffff),0xffff); + + test_to(make4(0x10000),0x10000); + test_to(make4(0x10ffff),0x10ffff); + + test_to(make4(0x110000),illegal); + test_to(make4(0x1fffff),illegal); + + test_to(make2(0),illegal); + test_to(make3(0),illegal); + test_to(make4(0),illegal); + test_to(make2(0x7f),illegal); + test_to(make3(0x7f),illegal); + test_to(make4(0x7f),illegal); + + test_to(make3(0x80),illegal); + test_to(make4(0x80),illegal); + test_to(make3(0x7ff),illegal); + test_to(make4(0x7ff),illegal); + + test_to(make4(0x8000),illegal); + test_to(make4(0xffff),illegal); + + std::cout << "-- Invalid surrogate" << std::endl; + + test_to(make3(0xd800),illegal); + test_to(make3(0xdbff),illegal); + test_to(make3(0xdc00),illegal); + test_to(make3(0xdfff),illegal); + + test_to(make4(0xd800),illegal); + test_to(make4(0xdbff),illegal); + test_to(make4(0xdc00),illegal); + test_to(make4(0xdfff),illegal); + + std::cout <<"-- Incomplete" << std::endl; + + test_to("",incomplete); + + test_to("\x80",illegal); + test_to("\xc2",incomplete); + + test_to("\xdf",incomplete); + + test_to("\xe0",incomplete); + test_to("\xe0\xa0",incomplete); + + test_to("\xef\xbf",incomplete); + test_to("\xef",incomplete); + + test_to("\xf0\x90\x80",incomplete); + test_to("\xf0\x90",incomplete); + test_to("\xf0",incomplete); + + test_to("\xf4\x8f\xbf",incomplete); + test_to("\xf4\x8f",incomplete); + test_to("\xf4",incomplete); + + std::cout << "- To UTF-8" << std::endl; + + std::cout << "-- Test correct" << std::endl; + + test_from("\x7f",0x7f); + test_from("\xc2\x80",0x80); + test_from("\xdf\xbf",0x7ff); + test_from("\xe0\xa0\x80",0x800); + test_from("\xef\xbf\xbf",0xffff); + test_from("\xf0\x90\x80\x80",0x10000); + test_from("\xf4\x8f\xbf\xbf",0x10ffff); + + std::cout << "Test UTF-16" << std::endl; + std::cout << "- From UTF-16" << std::endl; + + + std::cout << "-- Correct" << std::endl; + + test_to(u16_seq(0x10),0x10); + test_to(u16_seq(0xffff),0xffff); + test_to(u16_seq(0xD800,0xDC00),0x10000); + test_to(u16_seq(0xDBFF,0xDFFF),0x10FFFF); + + + std::cout << "-- Invalid surrogate" << std::endl; + + test_to(u16_seq(0xDFFF),illegal); + test_to(u16_seq(0xDC00),illegal); + + std::cout <<"-- Incomplete" << std::endl; + + test_to(u16_seq(0),incomplete); + test_to(u16_seq(0xD800),incomplete); + test_to(u16_seq(0xDBFF),incomplete); + + std::cout << "- To UTF-16" << std::endl; + + std::cout << "-- Test correct" << std::endl; + + test_to(u16_seq(0x10),0x10); + test_to(u16_seq(0xffff),0xffff); + test_to(u16_seq(0xD800,0xDC00),0x10000); + test_to(u16_seq(0xDBFF,0xDFFF),0x10FFFF); + + + std::cout << "Test UTF-32" << std::endl; + std::cout << "- From UTF-32" << std::endl; + + + std::cout << "-- Correct" << std::endl; + + test_to(u32_seq(0x10),0x10); + test_to(u32_seq(0xffff),0xffff); + test_to(u32_seq(0x10000),0x10000); + test_to(u32_seq(0x10ffff),0x10ffff); + + + + std::cout << "-- Invalid surrogate" << std::endl; + + test_to(u32_seq(0xD800),illegal); + test_to(u32_seq(0xDBFF),illegal); + test_to(u32_seq(0xDFFF),illegal); + test_to(u32_seq(0xDC00),illegal); + test_to(u32_seq(0x110000),illegal); + + std::cout <<"-- Incomplete" << std::endl; + + test_to(u32_seq(0),incomplete); + + std::cout << "- To UTF-32" << std::endl; + + std::cout << "-- Test correct" << std::endl; + + test_to(u32_seq(0x10),0x10); + test_to(u32_seq(0xffff),0xffff); + test_to(u32_seq(0x10ffff),0x10ffff); + + + + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_winapi_collate.cpp b/src/boost/libs/locale/test/test_winapi_collate.cpp new file mode 100644 index 000000000..fb12f7cac --- /dev/null +++ b/src/boost/libs/locale/test/test_winapi_collate.cpp @@ -0,0 +1,133 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifdef BOOST_LOCALE_NO_WINAPI_BACKEND +#include <iostream> +int main() +{ + std::cout << "WinAPI Backend is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/collator.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/localization_backend.hpp> +#include <iomanip> +#include "test_locale.hpp" + + +template<typename Char> +void test_comp(std::locale l,std::basic_string<Char> left,std::basic_string<Char> right,int ilevel,int expected) +{ + typedef std::basic_string<Char> string_type; + boost::locale::collator_base::level_type level = static_cast<boost::locale::collator_base::level_type>(ilevel); + TEST(boost::locale::comparator<Char>(l,level)(left,right) == (expected < 0)); + if(ilevel==4) { + std::collate<Char> const &coll=std::use_facet<std::collate<Char> >(l); + string_type lt=coll.transform(left.c_str(),left.c_str()+left.size()); + string_type rt=coll.transform(right.c_str(),right.c_str()+right.size()); + if(expected < 0) + TEST(lt<rt); + else if(expected == 0) { + TEST(lt==rt); + } + else + TEST(lt > rt); + long lh=coll.hash(left.c_str(),left.c_str()+left.size()); + long rh=coll.hash(right.c_str(),right.c_str()+right.size()); + if(expected == 0) + TEST(lh==rh); + else + TEST(lh!=rh); + } + boost::locale::collator<Char> const &coll=std::use_facet<boost::locale::collator<Char> >(l); + string_type lt=coll.transform(level,left.c_str(),left.c_str()+left.size()); + TEST(lt==coll.transform(level,left)); + string_type rt=coll.transform(level,right.c_str(),right.c_str()+right.size()); + TEST(rt==coll.transform(level,right)); + if(expected < 0) + TEST(lt<rt); + else if(expected == 0) + TEST(lt==rt); + else + TEST(lt > rt); + long lh=coll.hash(level,left.c_str(),left.c_str()+left.size()); + TEST(lh==coll.hash(level,left)); + long rh=coll.hash(level,right.c_str(),right.c_str()+right.size()); + TEST(rh==coll.hash(level,right)); + if(expected == 0) + TEST(lh==rh); + else + TEST(lh!=rh); + +} + +#define TEST_COMP(c,_l,_r) test_comp<c>(l,_l,_r,level,expected) + + +void compare(std::string left,std::string right,int level,int expected) +{ + boost::locale::generator gen; + std::locale l=gen("en_US.UTF-8"); + if(level == 4) + TEST(l(left,right) == (expected < 0)); + TEST_COMP(char,left,right); + TEST_COMP(wchar_t,to<wchar_t>(left),to<wchar_t>(right)); +} + + +void test_collate() +{ + int + primary = 0, + secondary = 1, + tertiary = 2, + quaternary = 3, + identical = 4; + int le = -1,gt = 1,eq = 0; + + + compare("a","A",primary,eq); + compare("a","A",secondary,eq); + compare("A","a",tertiary,gt); + compare("a","A",tertiary,le); + compare("a","A",quaternary,le); + compare("A","a",quaternary,gt); + compare("a","A",identical,le); + compare("A","a",identical,gt); + compare("a","ä",primary,eq); // a , ä + compare("a","ä",secondary,le); // a , ä + compare("ä","a",secondary,gt); // a , ä + compare("a","ä",quaternary,le); // a , ä + compare("ä","a",quaternary,gt); // a , ä + compare("a","ä",identical,le); // a , ä + compare("ä","a",identical,gt); // a , ä +} + + + + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("winapi"); + boost::locale::localization_backend_manager::global(mgr); + + test_collate(); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} +#endif // NO WINAPI +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_winapi_convert.cpp b/src/boost/libs/locale/test/test_winapi_convert.cpp new file mode 100644 index 000000000..5f5584b70 --- /dev/null +++ b/src/boost/libs/locale/test/test_winapi_convert.cpp @@ -0,0 +1,108 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +#ifdef BOOST_LOCALE_NO_WINAPI_BACKEND +#include <iostream> +int main() +{ + std::cout << "WinAPI Backend is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/conversion.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include <iostream> + +template<typename CharType> +void test_one(std::locale const &l,std::string src,std::string tgtl,std::string tgtu) +{ + TEST(boost::locale::to_upper(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtu,l)); + TEST(boost::locale::to_lower(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); + TEST(boost::locale::fold_case(to_correct_string<CharType>(src,l),l) == to_correct_string<CharType>(tgtl,l)); +} + +template<typename CharType> +void test_char() +{ + boost::locale::generator gen; + + std::cout << "- Testing at least C" << std::endl; + + + std::locale l = gen("en_US.UTF-8"); + + test_one<CharType>(l,"Hello World i","hello world i","HELLO WORLD I"); + + std::string name = "en_US.UTF-8"; + + std::cout << "- Testing " << name << std::endl; + l=gen(name); + test_one<CharType>(l,"Façade","façade","FAÇADE"); + + + name = "tr_TR.UTF-8"; + std::cout << "Testing " << name << std::endl; + test_one<CharType>(gen(name),"i","i","İ"); + +} + +template<typename Char> +void test_normc(std::basic_string<Char> orig,std::basic_string<Char> normal,boost::locale::norm_type type) +{ + std::locale l = boost::locale::generator().generate("en_US.UTF-8"); + TEST(boost::locale::normalize(orig,type,l)==normal); + TEST(boost::locale::normalize(orig.c_str(),type,l)==normal); + TEST(boost::locale::normalize(orig.c_str(),orig.c_str()+orig.size(),type,l)==normal); +} + + +void test_norm(std::string orig,std::string normal,boost::locale::norm_type type) +{ + test_normc<char>(orig,normal,type); + test_normc<wchar_t>(to<wchar_t>(orig),to<wchar_t>(normal),type); +} + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("winapi"); + boost::locale::localization_backend_manager::global(mgr); + + std::cout << "Testing char" << std::endl; + test_char<char>(); + std::cout << "Testing wchar_t" << std::endl; + test_char<wchar_t>(); + + std::cout << "Testing Unicode normalization" << std::endl; + test_norm("\xEF\xAC\x81","\xEF\xAC\x81",boost::locale::norm_nfd); /// ligature fi + test_norm("\xEF\xAC\x81","\xEF\xAC\x81",boost::locale::norm_nfc); + #if defined(_WIN32_NT) && _WIN32_NT >= 0x600 + test_norm("\xEF\xAC\x81","fi",boost::locale::norm_nfkd); + test_norm("\xEF\xAC\x81","fi",boost::locale::norm_nfkc); + #endif + test_norm("ä","ä",boost::locale::norm_nfd); // ä to a and accent + test_norm("ä","ä",boost::locale::norm_nfc); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // no winapi +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + + +// boostinspect:noascii diff --git a/src/boost/libs/locale/test/test_winapi_formatting.cpp b/src/boost/libs/locale/test/test_winapi_formatting.cpp new file mode 100644 index 000000000..a505b6f3e --- /dev/null +++ b/src/boost/libs/locale/test/test_winapi_formatting.cpp @@ -0,0 +1,267 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#ifdef BOOST_LOCALE_NO_WINAPI_BACKEND +#include <iostream> +int main() +{ + std::cout << "WinAPI Backend is not build... Skipping" << std::endl; +} +#else + +#include <boost/locale/formatting.hpp> +#include <boost/locale/localization_backend.hpp> +#include <boost/locale/generator.hpp> +#include <boost/locale/encoding.hpp> +#include <boost/locale/info.hpp> +#include <iomanip> +#include "test_locale.hpp" +#include "test_locale_tools.hpp" +#include "../src/win32/lcid.hpp" +#include <iostream> + +#include <time.h> +#include <assert.h> + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include <windows.h> + +#define DEBUG_FMT + +bool equal(std::string const &s1,std::wstring const &s2) +{ + bool res = s1 == boost::locale::conv::from_utf(s2,"UTF-8"); + #ifdef DEBUG_FMT + if(!res) + std::cout << "[" << s1 << "]!=["<<boost::locale::conv::from_utf(s2,"UTF-8")<<"]"<<std::endl; + #endif + return res; +} + +bool equal(std::wstring const &s1,std::wstring const &s2) +{ + bool res = s1 == s2; + #ifdef DEBUG_FMT + if(!res) + std::cout << "[" << boost::locale::conv::from_utf(s1,"UTF-8") << "]!=["<<boost::locale::conv::from_utf(s2,"UTF-8")<<"]"<<std::endl; + #endif + return res; +} + + +bool equal(std::string const &s1,std::string const &s2) +{ + bool res = s1 == s2; + #ifdef DEBUG_FMT + if(!res) + std::cout << "[" << s1 << "]!=["<<s2<<"]"<<std::endl; + #endif + return res; +} + +bool equal(std::wstring const &s1,std::string const &s2) +{ + bool res = s1 == boost::locale::conv::to_utf<wchar_t>(s2,"UTF-8"); + #ifdef DEBUG_FMT + if(!res) + std::cout << "[" << boost::locale::conv::from_utf(s1,"UTF-8") << "]!=["<<s2<<"]"<<std::endl; + #endif + return res; + +} + +template<typename CharType> +std::basic_string<CharType> conv_to_char(char const *p) +{ + std::basic_string<CharType> r; + while(*p) + r+=CharType(*p++); + return r; +} + + +template<typename CharType> +void test_by_char(std::locale const &l,std::string name,int lcid) +{ + typedef std::basic_stringstream<CharType> ss_type; + typedef std::basic_string<CharType> string_type; + + using namespace boost::locale; + + { + std::cout << "--- Testing as::posix" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + TEST(equal(ss.str(),"1045.45")); + } + + { + std::cout << "--- Testing as::number" << std::endl; + ss_type ss; + ss.imbue(l); + + ss << as::number; + ss << 1045.45; + TEST(ss); + double n; + ss >> n; + TEST(ss); + TEST(n == 1045.45); + + if(name == "ru_RU.UTF-8") { + if(sizeof(CharType)==1) + TEST(equal(ss.str(),"1 045,45")); // SP + else + TEST(equal(ss.str(),"1\xC2\xA0" "045,45")); // NBSP + } + else + TEST(equal(ss.str(),"1,045.45")); + } + + { + std::cout << "--- Testing as::currency " << std::endl; + + ss_type ss; + ss.imbue(l); + + ss << as::currency; + ss << 1043.34; + TEST(ss); + + wchar_t buf[256]; + GetCurrencyFormatW(lcid,0,L"1043.34",0,buf,256); + + TEST(equal(ss.str(),buf)); + } + + { + std::cout << "--- Testing as::date/time" << std::endl; + ss_type ss; + ss.imbue(l); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:13 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + ss << as::time_zone("GMT"); + + ss << as::date << a_datetime << CharType('\n'); + ss << as::time << a_datetime << CharType('\n'); + ss << as::datetime << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+01:00"); + ss << as::ftime(conv_to_char<CharType>("%H")) << a_datetime << CharType('\n'); + ss << as::time_zone("GMT+00:15"); + ss << as::ftime(conv_to_char<CharType>("%M")) << a_datetime << CharType('\n'); + + wchar_t time_buf[256]; + wchar_t date_buf[256]; + + SYSTEMTIME st= { 1970, 2,5, 5,15,33,13,0 }; + GetTimeFormatW(lcid,0,&st,0,time_buf,256); + GetDateFormatW(lcid,0,&st,0,date_buf,256); + TEST(equal(ss.str(),std::wstring(date_buf)+L"\n" + time_buf +L"\n" + date_buf + L" " + time_buf + L"\n16\n48\n")); + + } + +} + + +void test_date_time(std::locale l) +{ + std::ostringstream ss; + ss.imbue(l); + + ss << boost::locale::as::time_zone("GMT"); + + time_t a_date = 3600*24*(31+4); // Feb 5th + time_t a_time = 3600*15+60*33; // 15:33:13 + time_t a_timesec = 13; + time_t a_datetime = a_date + a_time + a_timesec; + + std::string pat[] = { + "a", "Thu", + "A", "Thursday", + "b", "Feb", + "B", "February", + "d", "05", + "D", "02/05/70", + "e", "5", + "h", "Feb", + "H", "15", + "I", "03", + "m", "02", + "M", "33", + "n", "\n", + "p", "PM", + "r", "03:33:13 PM", + "R", "15:33", + "S", "13", + "t", "\t", + "y", "70", + "Y", "1970", + "%", "%" + }; + + for(unsigned i=0;i<sizeof(pat)/sizeof(pat[0]);i+=2) { + ss.str(""); + ss << boost::locale::as::ftime("%" + pat[i]) << a_datetime; + TEST(equal(ss.str(),pat[i+1])); + } +} + +int main() +{ + try { + boost::locale::localization_backend_manager mgr = boost::locale::localization_backend_manager::global(); + mgr.select("winapi"); + boost::locale::localization_backend_manager::global(mgr); + boost::locale::generator gen; + std::string name; + std::string names[] = { "en_US.UTF-8", "he_IL.UTF-8", "ru_RU.UTF-8" }; + int lcids[] = { 0x0409, 0x040D ,0x0419 }; + + for(unsigned i=0;i<sizeof(names)/sizeof(names[9]);i++) { + name = names[i]; + std::cout << "- " << name << " locale" << std::endl; + if(boost::locale::impl_win::locale_to_lcid(name) == 0) { + std::cout << "-- not supported, skipping" << std::endl; + continue; + } + std::locale l1=gen(name); + std::cout << "-- UTF-8" << std::endl; + test_by_char<char>(l1,name,lcids[i]); + std::cout << "-- UTF-16" << std::endl; + test_by_char<wchar_t>(l1,name,lcids[i]); + } + std::cout << "- Testing strftime" <<std::endl; + test_date_time(gen("en_US.UTF-8")); + } + catch(std::exception const &e) { + std::cerr << "Failed " << e.what() << std::endl; + return EXIT_FAILURE; + } + FINALIZE(); + +} + +#endif // no winapi + +// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 + +// boostinspect:noascii diff --git a/src/boost/libs/locale/tools/cross-compile-gettext.sh b/src/boost/libs/locale/tools/cross-compile-gettext.sh new file mode 100755 index 000000000..ce8491baa --- /dev/null +++ b/src/boost/libs/locale/tools/cross-compile-gettext.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# +# Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +# +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + + +# Small and Fast Cross Compile Script + +rm -r build +cd build + +BUILD_TYPE=i586-mingw32msvc +GETTEXT_VER=0.18.1.1 +ICONV_VER=1.13.1 + +wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$ICONV_VER.tar.gz || exit 1 +wget http://ftp.gnu.org/pub/gnu/gettext/gettext-$GETTEXT_VER.tar.gz || exit 1 + +tar -xzf libiconv-$ICONV_VER.tar.gz || exit 1 +tar -xzf gettext-$GETTEXT_VER.tar.gz || exit 1 + + +mkdir win32 +PACKAGE_DIR=gettext-tools-static-$GETTEXT_VER +mkdir $PACKAGE_DIR + +PREFIX=`pwd`/win32 + +cd libiconv-$ICONV_VER + +./configure --disable-shared --host=$BUILD_TYPE --prefix=$PREFIX || exit 1 +make -j 4 && make install || exit 1 +cp ./COPYING ../$PACKAGE_DIR/COPYING-libiconv.txt + +cd ../gettext-$GETTEXT_VER + +./configure --disable-shared --host=$BUILD_TYPE --prefix=$PREFIX --with-libiconv-prefix=$PREFIX || exit 1 +cd gettext-tools +make -j 4 && make install || exit 1 +cd .. + +cp ./gettext-tools/gnulib-lib/libxml/COPYING ../$PACKAGE_DIR/COPYING-libxml.txt +cp ./COPYING ../$PACKAGE_DIR/COPYING-gettext.txt + +cd .. + +echo http://ftp.gnu.org/pub/gnu/libiconv/libiconv-$ICONV_VER.tar.gz > $PACKAGE_DIR/sources.txt +echo http://ftp.gnu.org/pub/gnu/gettext/gettext-$GETTEXT_VER.tar.gz >> $PACKAGE_DIR/sources.txt + +cp win32/bin/*.exe $PACKAGE_DIR + +unix2dos $PACKAGE_DIR/*.txt + +zip $PACKAGE_DIR.zip $PACKAGE_DIR/* + +mv $PACKAGE_DIR.zip .. |