First Commit
This commit is contained in:
20
externals/boost/libs/atomic/config/Jamfile.v2
vendored
Normal file
20
externals/boost/libs/atomic/config/Jamfile.v2
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright Andrey Semashev 2020.
|
||||
# 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)
|
||||
#
|
||||
|
||||
import atomic-arch-config ;
|
||||
|
||||
lib synchronization ;
|
||||
explicit synchronization ;
|
||||
|
||||
exe has_synchronization_lib : has_synchronization_lib.cpp : <library>synchronization ;
|
||||
explicit has_synchronization_lib ;
|
||||
|
||||
obj has_sse2 : has_sse2.cpp : <conditional>@atomic-arch-config.sse2-flags ;
|
||||
explicit has_sse2 ;
|
||||
|
||||
obj has_sse41 : has_sse41.cpp : <conditional>@atomic-arch-config.sse41-flags ;
|
||||
explicit has_sse41 ;
|
||||
17
externals/boost/libs/atomic/config/has_sse2.cpp
vendored
Normal file
17
externals/boost/libs/atomic/config/has_sse2.cpp
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2020.
|
||||
* 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 <emmintrin.h>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
__m128i mm = _mm_setzero_si128();
|
||||
mm = _mm_cmpeq_epi32(mm, mm);
|
||||
mm = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm), _mm_castsi128_ps(mm), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm = _mm_packs_epi32(mm, mm);
|
||||
return _mm_movemask_epi8(mm);
|
||||
}
|
||||
17
externals/boost/libs/atomic/config/has_sse41.cpp
vendored
Normal file
17
externals/boost/libs/atomic/config/has_sse41.cpp
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright Andrey Semashev 2020.
|
||||
* 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 <smmintrin.h>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
__m128i mm = _mm_setzero_si128();
|
||||
mm = _mm_cmpeq_epi64(mm, mm);
|
||||
mm = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm), _mm_castsi128_ps(mm), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm = _mm_packs_epi32(mm, mm);
|
||||
return _mm_movemask_epi8(mm);
|
||||
}
|
||||
33
externals/boost/libs/atomic/config/has_synchronization_lib.cpp
vendored
Normal file
33
externals/boost/libs/atomic/config/has_synchronization_lib.cpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
|
||||
#define BOOST_USE_WINAPI_VERSION 0x0602
|
||||
|
||||
// Include Boost.Predef first so that windows.h is guaranteed to be not included
|
||||
#include <boost/predef/os/windows.h>
|
||||
#include <boost/predef/os/cygwin.h>
|
||||
#if !BOOST_OS_WINDOWS && !BOOST_OS_CYGWIN
|
||||
#error "This config test is for Windows only"
|
||||
#endif
|
||||
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/predef/platform.h>
|
||||
#if !(BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM))
|
||||
#error "No WaitOnAddress API"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/wait_on_address.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned int n = 0u, compare = 0u;
|
||||
boost::winapi::WaitOnAddress(&n, &compare, sizeof(n), 0);
|
||||
return 0;
|
||||
}
|
||||
82
externals/boost/libs/atomic/src/bit_operation_tools.hpp
vendored
Normal file
82
externals/boost/libs/atomic/src/bit_operation_tools.hpp
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file bit_operation_tools.hpp
|
||||
*
|
||||
* This file contains bit operation tools
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_BIT_OPERATION_TOOLS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_BIT_OPERATION_TOOLS_HPP_INCLUDED_
|
||||
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
|
||||
#if BOOST_ARCH_X86
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
extern "C" unsigned char _BitScanForward(unsigned long* index, unsigned long x);
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! Counts trailing zero bits
|
||||
BOOST_FORCEINLINE unsigned int count_trailing_zeros(unsigned int x)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return __builtin_ctz(x);
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long index;
|
||||
_BitScanForward(&index, x);
|
||||
return static_cast< unsigned int >(index);
|
||||
#else
|
||||
unsigned int index = 0u;
|
||||
if ((x & 0xFFFF) == 0u)
|
||||
{
|
||||
x >>= 16;
|
||||
index += 16u;
|
||||
}
|
||||
if ((x & 0xFF) == 0u)
|
||||
{
|
||||
x >>= 8;
|
||||
index += 8u;
|
||||
}
|
||||
if ((x & 0xF) == 0u)
|
||||
{
|
||||
x >>= 4;
|
||||
index += 4u;
|
||||
}
|
||||
if ((x & 0x3) == 0u)
|
||||
{
|
||||
x >>= 2;
|
||||
index += 2u;
|
||||
}
|
||||
if ((x & 0x1) == 0u)
|
||||
{
|
||||
index += 1u;
|
||||
}
|
||||
return index;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ARCH_X86
|
||||
|
||||
#endif // BOOST_ATOMIC_BIT_OPERATION_TOOLS_HPP_INCLUDED_
|
||||
86
externals/boost/libs/atomic/src/cpuid.hpp
vendored
Normal file
86
externals/boost/libs/atomic/src/cpuid.hpp
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file cpuid.hpp
|
||||
*
|
||||
* This file contains declaration of \c cpuid function
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_CPUID_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_CPUID_HPP_INCLUDED_
|
||||
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
|
||||
#if BOOST_ARCH_X86
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h> // __cpuid
|
||||
#endif
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! The function invokes x86 cpuid instruction
|
||||
inline void cpuid(uint32_t& eax, uint32_t& ebx, uint32_t& ecx, uint32_t& edx)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#if (defined(__i386__) || defined(__VXWORKS__)) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC >= 50100))
|
||||
// Unless the compiler can do it automatically, we have to backup ebx in 32-bit PIC/PIE code because it is reserved by the ABI.
|
||||
// For VxWorks ebx is reserved on 64-bit as well.
|
||||
#if defined(__x86_64__)
|
||||
uint64_t rbx = ebx;
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgq %%rbx, %0\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgq %%rbx, %0\n\t"
|
||||
: "+DS" (rbx), "+a" (eax), "+c" (ecx), "+d" (edx)
|
||||
);
|
||||
ebx = static_cast< uint32_t >(rbx);
|
||||
#else // defined(__x86_64__)
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"xchgl %%ebx, %0\n\t"
|
||||
"cpuid\n\t"
|
||||
"xchgl %%ebx, %0\n\t"
|
||||
: "+DS" (ebx), "+a" (eax), "+c" (ecx), "+d" (edx)
|
||||
);
|
||||
#endif // defined(__x86_64__)
|
||||
#else
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"cpuid\n\t"
|
||||
: "+a" (eax), "+b" (ebx), "+c" (ecx), "+d" (edx)
|
||||
);
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
int regs[4] = {};
|
||||
__cpuid(regs, eax);
|
||||
eax = regs[0];
|
||||
ebx = regs[1];
|
||||
ecx = regs[2];
|
||||
edx = regs[3];
|
||||
#else
|
||||
#error "Boost.Atomic: Unsupported compiler, cpuid instruction cannot be generated"
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ARCH_X86
|
||||
|
||||
#endif // BOOST_ATOMIC_CPUID_HPP_INCLUDED_
|
||||
45
externals/boost/libs/atomic/src/find_address.hpp
vendored
Normal file
45
externals/boost/libs/atomic/src/find_address.hpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file find_address.hpp
|
||||
*
|
||||
* This file contains declaration of \c find_address algorithm
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_FIND_ADDRESS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_FIND_ADDRESS_HPP_INCLUDED_
|
||||
|
||||
#include <cstddef>
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/int_sizes.hpp>
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! \c find_address signature
|
||||
typedef std::size_t (find_address_t)(const volatile void* addr, const volatile void* const* addrs, std::size_t size);
|
||||
|
||||
extern find_address_t find_address_generic;
|
||||
|
||||
#if BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8 || BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 4)
|
||||
extern find_address_t find_address_sse2;
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
extern find_address_t find_address_sse41;
|
||||
#endif // BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
#endif // BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8 || BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 4)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ATOMIC_FIND_ADDRESS_HPP_INCLUDED_
|
||||
289
externals/boost/libs/atomic/src/find_address_sse2.cpp
vendored
Normal file
289
externals/boost/libs/atomic/src/find_address_sse2.cpp
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file find_address_sse2.cpp
|
||||
*
|
||||
* This file contains SSE2 implementation of the \c find_address algorithm
|
||||
*/
|
||||
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
#include <boost/atomic/detail/int_sizes.hpp>
|
||||
|
||||
#if BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8 || BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 4)
|
||||
|
||||
#include <cstddef>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/intptr.hpp>
|
||||
#include "find_address.hpp"
|
||||
#include "x86_vector_tools.hpp"
|
||||
#include "bit_operation_tools.hpp"
|
||||
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
namespace {
|
||||
|
||||
BOOST_FORCEINLINE __m128i mm_pand_si128(__m128i mm1, __m128i mm2)
|
||||
{
|
||||
// As of 2020, gcc, clang and icc prefer to generate andps instead of pand if the surrounding
|
||||
// instructions pertain to FP domain, even if we use the _mm_and_si128 intrinsic. In our
|
||||
// algorithm implementation, the FP instruction happen to be shufps, which is not actually
|
||||
// restricted to FP domain (it is actually implemented in a separate MMX EU in Pentium 4 or
|
||||
// a shuffle EU in INT domain in Core 2; on AMD K8/K10 all SSE instructions are implemented in
|
||||
// FADD, FMUL and FMISC EUs regardless of INT/FP data types, and shufps is implemented in FADD/FMUL).
|
||||
// In other words, there should be no domain bypass penalty between shufps and pand.
|
||||
//
|
||||
// This would usually not pose a problem since andps and pand have the same latency and throughput
|
||||
// on most architectures of that age (before SSE4.1). However, it is possible that a newer architecture
|
||||
// runs the SSE2 code path (e.g. because some weird compiler doesn't support SSE4.1 or because
|
||||
// a hypervisor blocks SSE4.1 detection), and there pand may have a better throughput. For example,
|
||||
// Sandy Bridge can execute 3 pand instructions per cycle, but only one andps. For this reason
|
||||
// we prefer to generate pand and not andps.
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__AVX__)
|
||||
// Generate VEX-coded variant if the code is compiled for AVX and later.
|
||||
__asm__("vpand %1, %0, %0\n\t" : "+x" (mm1) : "x" (mm2));
|
||||
#else
|
||||
__asm__("pand %1, %0\n\t" : "+x" (mm1) : "x" (mm2));
|
||||
#endif
|
||||
#else
|
||||
mm1 = _mm_and_si128(mm1, mm2);
|
||||
#endif
|
||||
return mm1;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif // BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
|
||||
//! SSE2 implementation of the \c find_address algorithm
|
||||
std::size_t find_address_sse2(const volatile void* addr, const volatile void* const* addrs, std::size_t size)
|
||||
{
|
||||
#if BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
|
||||
if (size < 12u)
|
||||
return find_address_generic(addr, addrs, size);
|
||||
|
||||
const __m128i mm_addr = mm_set1_epiptr((uintptr_t)addr);
|
||||
std::size_t pos = 0u;
|
||||
const std::size_t n = (size + 1u) & ~static_cast< std::size_t >(1u);
|
||||
for (std::size_t m = n & ~static_cast< std::size_t >(15u); pos < m; pos += 16u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
__m128i mm3 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
__m128i mm4 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 6u));
|
||||
__m128i mm5 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 8u));
|
||||
__m128i mm6 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 10u));
|
||||
__m128i mm7 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 12u));
|
||||
__m128i mm8 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 14u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi32(mm2, mm_addr);
|
||||
mm3 = _mm_cmpeq_epi32(mm3, mm_addr);
|
||||
mm4 = _mm_cmpeq_epi32(mm4, mm_addr);
|
||||
mm5 = _mm_cmpeq_epi32(mm5, mm_addr);
|
||||
mm6 = _mm_cmpeq_epi32(mm6, mm_addr);
|
||||
mm7 = _mm_cmpeq_epi32(mm7, mm_addr);
|
||||
mm8 = _mm_cmpeq_epi32(mm8, mm_addr);
|
||||
|
||||
__m128i mm_mask1_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask1_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
__m128i mm_mask2_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask2_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
__m128i mm_mask3_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm5), _mm_castsi128_ps(mm6), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask3_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm5), _mm_castsi128_ps(mm6), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
__m128i mm_mask4_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm7), _mm_castsi128_ps(mm8), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask4_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm7), _mm_castsi128_ps(mm8), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
mm_mask1_lo = mm_pand_si128(mm_mask1_lo, mm_mask1_hi);
|
||||
mm_mask2_lo = mm_pand_si128(mm_mask2_lo, mm_mask2_hi);
|
||||
mm_mask3_lo = mm_pand_si128(mm_mask3_lo, mm_mask3_hi);
|
||||
mm_mask4_lo = mm_pand_si128(mm_mask4_lo, mm_mask4_hi);
|
||||
|
||||
mm_mask1_lo = _mm_packs_epi32(mm_mask1_lo, mm_mask2_lo);
|
||||
mm_mask3_lo = _mm_packs_epi32(mm_mask3_lo, mm_mask4_lo);
|
||||
|
||||
mm_mask1_lo = _mm_packs_epi16(mm_mask1_lo, mm_mask3_lo);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm_mask1_lo);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((n - pos) >= 8u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
__m128i mm3 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
__m128i mm4 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 6u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi32(mm2, mm_addr);
|
||||
mm3 = _mm_cmpeq_epi32(mm3, mm_addr);
|
||||
mm4 = _mm_cmpeq_epi32(mm4, mm_addr);
|
||||
|
||||
__m128i mm_mask1_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask1_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
__m128i mm_mask2_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask2_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
mm_mask1_lo = mm_pand_si128(mm_mask1_lo, mm_mask1_hi);
|
||||
mm_mask2_lo = mm_pand_si128(mm_mask2_lo, mm_mask2_hi);
|
||||
|
||||
mm_mask1_lo = _mm_packs_epi32(mm_mask1_lo, mm_mask2_lo);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm_mask1_lo);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask) / 2u;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 8u;
|
||||
}
|
||||
|
||||
if ((n - pos) >= 4u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi32(mm2, mm_addr);
|
||||
|
||||
__m128i mm_mask1_lo = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
__m128i mm_mask1_hi = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(3, 1, 3, 1)));
|
||||
|
||||
mm_mask1_lo = mm_pand_si128(mm_mask1_lo, mm_mask1_hi);
|
||||
|
||||
uint32_t mask = _mm_movemask_ps(_mm_castsi128_ps(mm_mask1_lo));
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 4u;
|
||||
}
|
||||
|
||||
if (pos < n)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
__m128i mm_mask = _mm_shuffle_epi32(mm1, _MM_SHUFFLE(2, 3, 0, 1));
|
||||
mm_mask = mm_pand_si128(mm_mask, mm1);
|
||||
|
||||
uint32_t mask = _mm_movemask_pd(_mm_castsi128_pd(mm_mask));
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 2u;
|
||||
}
|
||||
|
||||
done:
|
||||
return pos;
|
||||
|
||||
#else // BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
|
||||
if (size < 10u)
|
||||
return find_address_generic(addr, addrs, size);
|
||||
|
||||
const __m128i mm_addr = _mm_set1_epi32((uintptr_t)addr);
|
||||
std::size_t pos = 0u;
|
||||
const std::size_t n = (size + 3u) & ~static_cast< std::size_t >(3u);
|
||||
for (std::size_t m = n & ~static_cast< std::size_t >(15u); pos < m; pos += 16u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
__m128i mm3 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 8u));
|
||||
__m128i mm4 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 12u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi32(mm2, mm_addr);
|
||||
mm3 = _mm_cmpeq_epi32(mm3, mm_addr);
|
||||
mm4 = _mm_cmpeq_epi32(mm4, mm_addr);
|
||||
|
||||
mm1 = _mm_packs_epi32(mm1, mm2);
|
||||
mm3 = _mm_packs_epi32(mm3, mm4);
|
||||
|
||||
mm1 = _mm_packs_epi16(mm1, mm3);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm1);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((n - pos) >= 8u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi32(mm2, mm_addr);
|
||||
|
||||
mm1 = _mm_packs_epi32(mm1, mm2);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm1);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask) / 2u;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 8u;
|
||||
}
|
||||
|
||||
if (pos < n)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
|
||||
mm1 = _mm_cmpeq_epi32(mm1, mm_addr);
|
||||
|
||||
uint32_t mask = _mm_movemask_ps(_mm_castsi128_ps(mm1));
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 4u;
|
||||
}
|
||||
|
||||
done:
|
||||
return pos;
|
||||
|
||||
#endif // BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8 || BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 4)
|
||||
154
externals/boost/libs/atomic/src/find_address_sse41.cpp
vendored
Normal file
154
externals/boost/libs/atomic/src/find_address_sse41.cpp
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file find_address_sse41.cpp
|
||||
*
|
||||
* This file contains SSE4.1 implementation of the \c find_address algorithm
|
||||
*/
|
||||
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
#include <boost/atomic/detail/int_sizes.hpp>
|
||||
|
||||
#if BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8)
|
||||
|
||||
#include <cstddef>
|
||||
#include <smmintrin.h>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/intptr.hpp>
|
||||
#include "find_address.hpp"
|
||||
#include "x86_vector_tools.hpp"
|
||||
#include "bit_operation_tools.hpp"
|
||||
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
//! SSE4.1 implementation of the \c find_address algorithm
|
||||
std::size_t find_address_sse41(const volatile void* addr, const volatile void* const* addrs, std::size_t size)
|
||||
{
|
||||
if (size < 12u)
|
||||
return find_address_generic(addr, addrs, size);
|
||||
|
||||
const __m128i mm_addr = mm_set1_epiptr((uintptr_t)addr);
|
||||
std::size_t pos = 0u;
|
||||
const std::size_t n = (size + 1u) & ~static_cast< std::size_t >(1u);
|
||||
for (std::size_t m = n & ~static_cast< std::size_t >(15u); pos < m; pos += 16u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
__m128i mm3 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
__m128i mm4 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 6u));
|
||||
__m128i mm5 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 8u));
|
||||
__m128i mm6 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 10u));
|
||||
__m128i mm7 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 12u));
|
||||
__m128i mm8 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 14u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi64(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi64(mm2, mm_addr);
|
||||
mm3 = _mm_cmpeq_epi64(mm3, mm_addr);
|
||||
mm4 = _mm_cmpeq_epi64(mm4, mm_addr);
|
||||
mm5 = _mm_cmpeq_epi64(mm5, mm_addr);
|
||||
mm6 = _mm_cmpeq_epi64(mm6, mm_addr);
|
||||
mm7 = _mm_cmpeq_epi64(mm7, mm_addr);
|
||||
mm8 = _mm_cmpeq_epi64(mm8, mm_addr);
|
||||
|
||||
mm1 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm5 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm5), _mm_castsi128_ps(mm6), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm7 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm7), _mm_castsi128_ps(mm8), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
|
||||
mm1 = _mm_packs_epi32(mm1, mm3);
|
||||
mm5 = _mm_packs_epi32(mm5, mm7);
|
||||
|
||||
mm1 = _mm_packs_epi16(mm1, mm5);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm1);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ((n - pos) >= 8u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
__m128i mm3 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 4u));
|
||||
__m128i mm4 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 6u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi64(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi64(mm2, mm_addr);
|
||||
mm3 = _mm_cmpeq_epi64(mm3, mm_addr);
|
||||
mm4 = _mm_cmpeq_epi64(mm4, mm_addr);
|
||||
|
||||
mm1 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
mm3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm3), _mm_castsi128_ps(mm4), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
|
||||
mm1 = _mm_packs_epi32(mm1, mm3);
|
||||
|
||||
uint32_t mask = _mm_movemask_epi8(mm1);
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask) / 2u;
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 8u;
|
||||
}
|
||||
|
||||
if ((n - pos) >= 4u)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
__m128i mm2 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos + 2u));
|
||||
|
||||
mm1 = _mm_cmpeq_epi64(mm1, mm_addr);
|
||||
mm2 = _mm_cmpeq_epi64(mm2, mm_addr);
|
||||
|
||||
mm1 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(mm1), _mm_castsi128_ps(mm2), _MM_SHUFFLE(2, 0, 2, 0)));
|
||||
|
||||
uint32_t mask = _mm_movemask_ps(_mm_castsi128_ps(mm1));
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 4u;
|
||||
}
|
||||
|
||||
if (pos < n)
|
||||
{
|
||||
__m128i mm1 = _mm_load_si128(reinterpret_cast< const __m128i* >(addrs + pos));
|
||||
|
||||
mm1 = _mm_cmpeq_epi64(mm1, mm_addr);
|
||||
uint32_t mask = _mm_movemask_pd(_mm_castsi128_pd(mm1));
|
||||
if (mask)
|
||||
{
|
||||
pos += atomics::detail::count_trailing_zeros(mask);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pos += 2u;
|
||||
}
|
||||
|
||||
done:
|
||||
return pos;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8)
|
||||
1414
externals/boost/libs/atomic/src/lock_pool.cpp
vendored
Normal file
1414
externals/boost/libs/atomic/src/lock_pool.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13
externals/boost/libs/atomic/src/lock_pool_init1.ipp
vendored
Normal file
13
externals/boost/libs/atomic/src/lock_pool_init1.ipp
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
|
||||
#if BOOST_PP_ITERATION() > 1
|
||||
,
|
||||
#endif
|
||||
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }
|
||||
79
externals/boost/libs/atomic/src/lock_pool_init256.ipp
vendored
Normal file
79
externals/boost/libs/atomic/src/lock_pool_init256.ipp
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
|
||||
#if BOOST_PP_ITERATION() > 1
|
||||
,
|
||||
#endif
|
||||
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT },
|
||||
{ BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }, { BOOST_ATOMIC_LOCK_STATE_INIT }
|
||||
113
externals/boost/libs/atomic/src/wait_on_address.cpp
vendored
Normal file
113
externals/boost/libs/atomic/src/wait_on_address.cpp
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file wait_on_address.cpp
|
||||
*
|
||||
* This file contains implementation of runtime detection of \c WaitOnAddress and related APIs on Windows.
|
||||
*
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddresssingle
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddressall
|
||||
*/
|
||||
|
||||
// Include boost/winapi/config.hpp first to make sure target Windows version is selected by Boost.WinAPI
|
||||
#include <boost/winapi/config.hpp>
|
||||
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
#include <boost/atomic/detail/link.hpp>
|
||||
#include <boost/atomic/detail/once_flag.hpp>
|
||||
#include <boost/atomic/detail/wait_on_address.hpp>
|
||||
|
||||
#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/memory_order.hpp>
|
||||
#include <boost/winapi/thread.hpp>
|
||||
#include <boost/winapi/get_proc_address.hpp>
|
||||
#include <boost/winapi/dll.hpp>
|
||||
|
||||
#include <boost/atomic/detail/core_operations.hpp>
|
||||
|
||||
#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
BOOST_ATOMIC_DECL wait_on_address_t* wait_on_address = NULL;
|
||||
BOOST_ATOMIC_DECL wake_by_address_t* wake_by_address_single = NULL;
|
||||
BOOST_ATOMIC_DECL wake_by_address_t* wake_by_address_all = NULL;
|
||||
|
||||
#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
BOOST_ATOMIC_DECL once_flag wait_functions_once_flag = { 2u };
|
||||
|
||||
BOOST_ATOMIC_DECL void initialize_wait_functions() BOOST_NOEXCEPT
|
||||
{
|
||||
BOOST_STATIC_ASSERT_MSG(once_flag_operations::is_always_lock_free, "Boost.Atomic unsupported target platform: native atomic operations not implemented for bytes");
|
||||
|
||||
once_flag_operations::storage_type old_val = once_flag_operations::load(wait_functions_once_flag.m_flag, boost::memory_order_acquire);
|
||||
while (true)
|
||||
{
|
||||
if (old_val == 2u)
|
||||
{
|
||||
if (BOOST_UNLIKELY(!once_flag_operations::compare_exchange_strong(wait_functions_once_flag.m_flag, old_val, 1u, boost::memory_order_relaxed, boost::memory_order_relaxed)))
|
||||
continue;
|
||||
|
||||
boost::winapi::HMODULE_ kernel_base = boost::winapi::get_module_handle(L"api-ms-win-core-synch-l1-2-0.dll");
|
||||
if (BOOST_LIKELY(kernel_base != NULL))
|
||||
{
|
||||
wait_on_address_t* woa = (wait_on_address_t*)boost::winapi::get_proc_address(kernel_base, "WaitOnAddress");
|
||||
if (BOOST_LIKELY(woa != NULL))
|
||||
{
|
||||
wake_by_address_t* wbas = (wake_by_address_t*)boost::winapi::get_proc_address(kernel_base, "WakeByAddressSingle");
|
||||
wake_by_address_t* wbaa = (wake_by_address_t*)boost::winapi::get_proc_address(kernel_base, "WakeByAddressAll");
|
||||
|
||||
if (BOOST_LIKELY(wbas != NULL && wbaa != NULL))
|
||||
{
|
||||
wait_on_address = woa;
|
||||
wake_by_address_single = wbas;
|
||||
wake_by_address_all = wbaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
once_flag_operations::store(wait_functions_once_flag.m_flag, 0u, boost::memory_order_release);
|
||||
break;
|
||||
}
|
||||
else if (old_val == 1u)
|
||||
{
|
||||
boost::winapi::SwitchToThread();
|
||||
old_val = once_flag_operations::load(wait_functions_once_flag.m_flag, boost::memory_order_acquire);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
BOOST_ATOMIC_DECL once_flag wait_functions_once_flag = { 0u };
|
||||
|
||||
BOOST_ATOMIC_DECL void initialize_wait_functions() BOOST_NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
52
externals/boost/libs/atomic/src/x86_vector_tools.hpp
vendored
Normal file
52
externals/boost/libs/atomic/src/x86_vector_tools.hpp
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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)
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Semashev
|
||||
*/
|
||||
/*!
|
||||
* \file x86_vector_tools.hpp
|
||||
*
|
||||
* This file contains common tools for x86 vectorization
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_X86_VECTOR_TOOLS_HPP_INCLUDED_
|
||||
#define BOOST_ATOMIC_X86_VECTOR_TOOLS_HPP_INCLUDED_
|
||||
|
||||
#include <boost/predef/architecture/x86.h>
|
||||
#include <boost/atomic/detail/int_sizes.hpp>
|
||||
|
||||
#if BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8)
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/atomic/detail/intptr.hpp>
|
||||
#include <boost/atomic/detail/config.hpp>
|
||||
|
||||
#include <boost/atomic/detail/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace atomics {
|
||||
namespace detail {
|
||||
|
||||
BOOST_FORCEINLINE __m128i mm_set1_epiptr(uintptr_t ptr)
|
||||
{
|
||||
#if !defined(_MSC_VER) || _MSC_FULL_VER >= 190024210
|
||||
return _mm_set1_epi64x(ptr);
|
||||
#else
|
||||
// MSVC up until 14.0 update 3 doesn't provide _mm_set1_epi64x
|
||||
uint32_t lo = static_cast< uint32_t >(ptr), hi = static_cast< uint32_t >(ptr >> 32);
|
||||
return _mm_set_epi32(hi, lo, hi, lo);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace atomics
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/atomic/detail/footer.hpp>
|
||||
|
||||
#endif // BOOST_ARCH_X86 && defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER == 8)
|
||||
|
||||
#endif // BOOST_ATOMIC_X86_VECTOR_TOOLS_HPP_INCLUDED_
|
||||
15
externals/boost/libs/chrono/src/chrono.cpp
vendored
Normal file
15
externals/boost/libs/chrono/src/chrono.cpp
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// chrono.cpp --------------------------------------------------------------//
|
||||
|
||||
// Copyright Beman Dawes 2008
|
||||
// Copyright Vicente J. Botet Escriba 2009-2010
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// define BOOST_CHRONO_SOURCE so that <boost/filesystem/config.hpp> knows
|
||||
// the library is being built (possibly exporting rather than importing code)
|
||||
|
||||
#define BOOST_CHRONO_SOURCE
|
||||
|
||||
#include <boost/chrono/detail/inlined/chrono.hpp>
|
||||
|
||||
18
externals/boost/libs/chrono/src/process_cpu_clocks.cpp
vendored
Normal file
18
externals/boost/libs/chrono/src/process_cpu_clocks.cpp
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// boost process_cpu_clocks.cpp -----------------------------------------------------------//
|
||||
|
||||
// Copyright 2009-2010 Vicente J. Botet Escriba
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// See http://www.boost.org/libs/chrono for documentation.
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// define BOOST_CHRONO_SOURCE so that <boost/chrono/config.hpp> knows
|
||||
// the library is being built (possibly exporting rather than importing code)
|
||||
|
||||
#define BOOST_CHRONO_SOURCE
|
||||
|
||||
#include <boost/chrono/detail/inlined/process_cpu_clocks.hpp>
|
||||
|
||||
19
externals/boost/libs/chrono/src/thread_clock.cpp
vendored
Normal file
19
externals/boost/libs/chrono/src/thread_clock.cpp
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// boost thread_clock.cpp -----------------------------------------------------------//
|
||||
|
||||
// Copyright 2010 Vicente J. Botet Escriba
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
// See http://www.boost.org/libs/chrono for documentation.
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
|
||||
// define BOOST_CHRONO_SOURCE so that <boost/chrono/config.hpp> knows
|
||||
// the library is being built (possibly exporting rather than importing code)
|
||||
|
||||
#define BOOST_CHRONO_SOURCE
|
||||
|
||||
#include <boost/chrono/detail/inlined/thread_clock.hpp>
|
||||
|
||||
1541
externals/boost/libs/config/test/config_info.cpp
vendored
Normal file
1541
externals/boost/libs/config/test/config_info.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
72
externals/boost/libs/date_time/src/date_time.doc
vendored
Normal file
72
externals/boost/libs/date_time/src/date_time.doc
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 2001-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
/*! @mainpage Boost Date-Time Library Reference Documentation
|
||||
*
|
||||
*
|
||||
*@section intro Introduction
|
||||
*
|
||||
* The Boost Date-Time Library (originally the Generic Date-Time Library or GDTL)
|
||||
* is a set of C++ date-time libraries based on the concepts of generic programming.
|
||||
* This is an online reference guide generated from the source code
|
||||
* that provides a handy way to learn about the details of the
|
||||
* library. If you are a user you should start with the
|
||||
* <a href="../user_docs/index.html">User Documentation</a>.
|
||||
*
|
||||
*@section using Using This Documentation
|
||||
*
|
||||
* The online documentation provides extensive information about the details
|
||||
* of the library including:
|
||||
* - <A href="inherits.html">Class hierarchy</A>
|
||||
* - <A href="namespaces.html">Namespace Documentation</A>
|
||||
* - List of <A href="files.html">source files</A>
|
||||
* - Annotated list of classes and structs
|
||||
* <A href="annotated.html">(Compound List)</A>
|
||||
*
|
||||
* For example, suppose you wanted to learn more about the
|
||||
* gregorian::greg_month class.
|
||||
* You could alternatively browse the
|
||||
* - <A href="classboost_1_1gregorian_1_1greg__month.html">Class documentation page</A>
|
||||
* - Include dependencies for greg_month.hpp
|
||||
* - Hyperlinked and colorized source files: <A href="greg__month_8hpp-source.html">[hpp file]</A> <A href="greg__month_8cpp-source.html">[cpp file]</A>
|
||||
*
|
||||
* The main navigation bar at the top provides that access to many
|
||||
* different modes of naviation through the library.
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
//! Overall boost namespace -- library does not put any symbols here
|
||||
namespace boost {
|
||||
|
||||
//! Namespace for basic templates and components used to construct date-time systems
|
||||
/*!
|
||||
This namespace encapsulates various types of templates and classes used
|
||||
to construct coherent date-time systems including date, time, etc. These
|
||||
components should be considered helper components to be utilized in the
|
||||
construction of specific date-time system implementations. See namespace
|
||||
gregorian for one such example.
|
||||
*/
|
||||
namespace date_time {}
|
||||
|
||||
}
|
||||
/*! Namespace for the c++ standard library. Library does not define any symbols in the namespace, but uses some classes from this namespace.
|
||||
*/
|
||||
namespace std {}
|
||||
|
||||
/*!\class std::out_of_range
|
||||
\brief Exception class defined in c++ standard library.
|
||||
A derivative of std::logic_error and std::exception and base class for
|
||||
many exceptions in the library. See also:
|
||||
|
||||
<a href="http://docs.mandragor.org/files/Programming_languages/Cpp/libstdcpp_v3_Source_Documentation/classstd_1_1out__of__range.html">Mandragor docs for libstdcpp_v3 std::out_of_range</a>
|
||||
*/
|
||||
|
||||
|
||||
|
||||
38
externals/boost/libs/date_time/src/gregorian/date_generators.cpp
vendored
Normal file
38
externals/boost/libs/date_time/src/gregorian/date_generators.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BOOST_DATE_TIME_SOURCE
|
||||
#define BOOST_DATE_TIME_SOURCE
|
||||
#endif
|
||||
#include "boost/date_time/date_generators.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace date_time {
|
||||
|
||||
const char* const _nth_as_str[] = {"out of range", "first", "second",
|
||||
"third", "fourth", "fifth"};
|
||||
|
||||
//! Returns nth arg as string. 1 -> "first", 2 -> "second", max is 5.
|
||||
BOOST_DATE_TIME_DECL const char* nth_as_str(int ele)
|
||||
{
|
||||
if(ele >= 1 && ele <= 5) {
|
||||
return _nth_as_str[ele];
|
||||
}
|
||||
else {
|
||||
return _nth_as_str[0];
|
||||
}
|
||||
}
|
||||
|
||||
} } //namespace date_time
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
173
externals/boost/libs/date_time/src/gregorian/greg_month.cpp
vendored
Normal file
173
externals/boost/libs/date_time/src/gregorian/greg_month.cpp
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
/* Copyright (c) 2002-2005 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BOOST_DATE_TIME_SOURCE
|
||||
#define BOOST_DATE_TIME_SOURCE
|
||||
#endif
|
||||
#include "boost/date_time/gregorian/greg_month.hpp"
|
||||
#include "boost/date_time/gregorian/greg_facet.hpp"
|
||||
#include "boost/date_time/date_format_simple.hpp"
|
||||
#include "boost/date_time/compiler_config.hpp"
|
||||
#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS)
|
||||
#include "boost/date_time/gregorian/formatters_limited.hpp"
|
||||
#else
|
||||
#include "boost/date_time/gregorian/formatters.hpp"
|
||||
#endif
|
||||
#include "boost/date_time/date_parsing.hpp"
|
||||
#include "boost/date_time/gregorian/parsers.hpp"
|
||||
|
||||
#include "greg_names.hpp"
|
||||
namespace boost {
|
||||
namespace gregorian {
|
||||
|
||||
/*! Returns a shared pointer to a map of Month strings & numbers.
|
||||
* Strings are both full names and abbreviations.
|
||||
* Ex. ("jan",1), ("february",2), etc...
|
||||
* Note: All characters are lowercase - for case insensitivity
|
||||
*/
|
||||
greg_month::month_map_ptr_type greg_month::get_month_map_ptr()
|
||||
{
|
||||
static month_map_ptr_type month_map_ptr(new greg_month::month_map_type());
|
||||
|
||||
if(month_map_ptr->empty()) {
|
||||
std::string s("");
|
||||
for(unsigned short i = 1; i <= 12; ++i) {
|
||||
greg_month m(static_cast<month_enum>(i));
|
||||
s = m.as_long_string();
|
||||
s = date_time::convert_to_lower(s);
|
||||
month_map_ptr->insert(std::make_pair(s, i));
|
||||
s = m.as_short_string();
|
||||
s = date_time::convert_to_lower(s);
|
||||
month_map_ptr->insert(std::make_pair(s, i));
|
||||
}
|
||||
}
|
||||
return month_map_ptr;
|
||||
}
|
||||
|
||||
|
||||
//! Returns 3 char english string for the month ex: Jan, Feb, Mar, Apr
|
||||
const char*
|
||||
greg_month::as_short_string() const
|
||||
{
|
||||
return short_month_names[value_-1];
|
||||
}
|
||||
|
||||
//! Returns full name of month as string in english ex: January, February
|
||||
const char*
|
||||
greg_month::as_long_string() const
|
||||
{
|
||||
return long_month_names[value_-1];
|
||||
}
|
||||
|
||||
//! Return special_value from string argument
|
||||
/*! Return special_value from string argument. If argument is
|
||||
* not one of the special value names (defined in names.hpp),
|
||||
* return 'not_special' */
|
||||
special_values special_value_from_string(const std::string& s) {
|
||||
short i = date_time::find_match(special_value_names,
|
||||
special_value_names,
|
||||
date_time::NumSpecialValues,
|
||||
s);
|
||||
if(i >= date_time::NumSpecialValues) { // match not found
|
||||
return not_special;
|
||||
}
|
||||
else {
|
||||
return static_cast<special_values>(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
//! Returns 3 wchar_t english string for the month ex: Jan, Feb, Mar, Apr
|
||||
const wchar_t*
|
||||
greg_month::as_short_wstring() const
|
||||
{
|
||||
return w_short_month_names[value_-1];
|
||||
}
|
||||
|
||||
//! Returns full name of month as wchar_t string in english ex: January, February
|
||||
const wchar_t*
|
||||
greg_month::as_long_wstring() const
|
||||
{
|
||||
return w_long_month_names[value_-1];
|
||||
}
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
|
||||
#ifndef BOOST_DATE_TIME_NO_LOCALE
|
||||
/*! creates an all_date_names_put object with the correct set of names.
|
||||
* This function is only called in the event of an exception where
|
||||
* the imbued locale containing the needed facet is for some reason
|
||||
* unreachable.
|
||||
*/
|
||||
BOOST_DATE_TIME_DECL
|
||||
boost::date_time::all_date_names_put<greg_facet_config, char>*
|
||||
create_facet_def(char /*type*/)
|
||||
{
|
||||
typedef
|
||||
boost::date_time::all_date_names_put<greg_facet_config, char> facet_def;
|
||||
|
||||
return new facet_def(short_month_names,
|
||||
long_month_names,
|
||||
special_value_names,
|
||||
short_weekday_names,
|
||||
long_weekday_names);
|
||||
}
|
||||
|
||||
//! generates a locale with the set of gregorian name-strings of type char*
|
||||
BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, char /*type*/){
|
||||
typedef boost::date_time::all_date_names_put<greg_facet_config, char> facet_def;
|
||||
return std::locale(loc, new facet_def(short_month_names,
|
||||
long_month_names,
|
||||
special_value_names,
|
||||
short_weekday_names,
|
||||
long_weekday_names)
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
/*! creates an all_date_names_put object with the correct set of names.
|
||||
* This function is only called in the event of an exception where
|
||||
* the imbued locale containing the needed facet is for some reason
|
||||
* unreachable.
|
||||
*/
|
||||
BOOST_DATE_TIME_DECL
|
||||
boost::date_time::all_date_names_put<greg_facet_config, wchar_t>*
|
||||
create_facet_def(wchar_t /*type*/)
|
||||
{
|
||||
typedef
|
||||
boost::date_time::all_date_names_put<greg_facet_config,wchar_t> facet_def;
|
||||
|
||||
return new facet_def(w_short_month_names,
|
||||
w_long_month_names,
|
||||
w_special_value_names,
|
||||
w_short_weekday_names,
|
||||
w_long_weekday_names);
|
||||
}
|
||||
|
||||
//! generates a locale with the set of gregorian name-strings of type wchar_t*
|
||||
BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, wchar_t /*type*/){
|
||||
typedef boost::date_time::all_date_names_put<greg_facet_config, wchar_t> facet_def;
|
||||
return std::locale(loc, new facet_def(w_short_month_names,
|
||||
w_long_month_names,
|
||||
w_special_value_names,
|
||||
w_short_weekday_names,
|
||||
w_long_weekday_names)
|
||||
);
|
||||
}
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
#endif // BOOST_DATE_TIME_NO_LOCALE
|
||||
|
||||
} } //namespace gregorian
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
43
externals/boost/libs/date_time/src/gregorian/greg_names.hpp
vendored
Normal file
43
externals/boost/libs/date_time/src/gregorian/greg_names.hpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DATE_TIME_SRC_GREG_NAMES_HPP___
|
||||
#define DATE_TIME_SRC_GREG_NAMES_HPP___
|
||||
|
||||
#include "boost/date_time/gregorian/greg_month.hpp"
|
||||
#include "boost/date_time/special_defs.hpp"
|
||||
namespace boost {
|
||||
namespace gregorian {
|
||||
|
||||
|
||||
const char* const short_month_names[NumMonths]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec", "NAM"};
|
||||
const char* const long_month_names[NumMonths]={"January","February","March","April","May","June","July","August","September","October","November","December","NotAMonth"};
|
||||
const char* const special_value_names[date_time::NumSpecialValues]={"not-a-date-time","-infinity","+infinity","min_date_time","max_date_time","not_special"};
|
||||
|
||||
|
||||
const char* const short_weekday_names[]={"Sun", "Mon", "Tue",
|
||||
"Wed", "Thu", "Fri", "Sat"};
|
||||
const char* const long_weekday_names[]= {"Sunday","Monday","Tuesday",
|
||||
"Wednesday", "Thursday",
|
||||
"Friday", "Saturday"};
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
const wchar_t* const w_short_month_names[NumMonths]={L"Jan",L"Feb",L"Mar",L"Apr",L"May",L"Jun",L"Jul",L"Aug",L"Sep",L"Oct",L"Nov",L"Dec",L"NAM"};
|
||||
const wchar_t* const w_long_month_names[NumMonths]={L"January",L"February",L"March",L"April",L"May",L"June",L"July",L"August",L"September",L"October",L"November",L"December",L"NotAMonth"};
|
||||
const wchar_t* const w_special_value_names[date_time::NumSpecialValues]={L"not-a-date-time",L"-infinity",L"+infinity",L"min_date_time",L"max_date_time",L"not_special"};
|
||||
|
||||
const wchar_t* const w_short_weekday_names[]={L"Sun", L"Mon", L"Tue",
|
||||
L"Wed", L"Thu", L"Fri", L"Sat"};
|
||||
const wchar_t* const w_long_weekday_names[]= {L"Sunday",L"Monday",L"Tuesday",
|
||||
L"Wednesday", L"Thursday",
|
||||
L"Friday", L"Saturday"};
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
} } // boost::gregorian
|
||||
#endif // DATE_TIME_SRC_GREG_NAMES_HPP___
|
||||
50
externals/boost/libs/date_time/src/gregorian/greg_weekday.cpp
vendored
Normal file
50
externals/boost/libs/date_time/src/gregorian/greg_weekday.cpp
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland, Bart Garst
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BOOST_DATE_TIME_SOURCE
|
||||
#define BOOST_DATE_TIME_SOURCE
|
||||
#endif
|
||||
#include "boost/date_time/gregorian/greg_weekday.hpp"
|
||||
|
||||
#include "greg_names.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace gregorian {
|
||||
|
||||
//! Return a 3 digit english string of the day of week (eg: Sun)
|
||||
const char*
|
||||
greg_weekday::as_short_string() const
|
||||
{
|
||||
return short_weekday_names[value_];
|
||||
}
|
||||
//! Return a point to a long english string representing day of week
|
||||
const char*
|
||||
greg_weekday::as_long_string() const
|
||||
{
|
||||
return long_weekday_names[value_];
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTRING
|
||||
//! Return a 3 digit english wchar_t string of the day of week (eg: Sun)
|
||||
const wchar_t*
|
||||
greg_weekday::as_short_wstring() const
|
||||
{
|
||||
return w_short_weekday_names[value_];
|
||||
}
|
||||
//! Return a point to a long english wchar_t string representing day of week
|
||||
const wchar_t*
|
||||
greg_weekday::as_long_wstring() const
|
||||
{
|
||||
return w_long_weekday_names[value_];
|
||||
}
|
||||
#endif // BOOST_NO_STD_WSTRING
|
||||
|
||||
} } //namespace gregorian
|
||||
|
||||
62
externals/boost/libs/date_time/src/gregorian/gregorian_types.cpp
vendored
Normal file
62
externals/boost/libs/date_time/src/gregorian/gregorian_types.cpp
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/* Copyright (c) 2002,2003 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup date_basics Date Basics
|
||||
This page summarizes some of the key user types and functions needed
|
||||
to write programs using the gregorian date system. This is not a
|
||||
comprehensive list, but rather some key types to start exploring.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
/** @defgroup date_alg Date Algorithms / Generators
|
||||
Date algorithms or generators are tools for generating other dates or
|
||||
schedules of dates. A generator function starts with some part of a
|
||||
date such as a month and day and is supplied another part to then
|
||||
generate a final date.
|
||||
|
||||
**/
|
||||
|
||||
/** @defgroup date_format Date Formatting
|
||||
The functions on these page are some of the key formatting functions
|
||||
for dates.
|
||||
**/
|
||||
|
||||
|
||||
//File doesn't have a current purpose except to generate docs
|
||||
//and keep it changeable without recompiles
|
||||
/*! @example days_alive.cpp
|
||||
Calculate the number of days you have been living using durations and dates.
|
||||
*/
|
||||
/*! @example days_till_new_year.cpp
|
||||
Calculate the number of days till new years
|
||||
*/
|
||||
/*! @example print_month.cpp
|
||||
Simple utility to print out days of the month with the days of a month. Demontstrates date iteration (date_time::date_itr).
|
||||
*/
|
||||
/*! @example localization.cpp
|
||||
An example showing localized stream-based I/O.
|
||||
*/
|
||||
/*! @example dates_as_strings.cpp
|
||||
Various parsing and output of strings (mostly supported for
|
||||
compilers that do not support localized streams).
|
||||
*/
|
||||
/*! @example period_calc.cpp
|
||||
Calculates if a date is in an 'irregular' collection of periods using
|
||||
period calculation functions.
|
||||
*/
|
||||
/*! @example print_holidays.cpp
|
||||
This is an example of using functors to define a holiday schedule
|
||||
*/
|
||||
/*! @example localization.cpp
|
||||
Demonstrates the use of facets to localize date output for Gregorian dates.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
35
externals/boost/libs/date_time/src/posix_time/posix_time_types.cpp
vendored
Normal file
35
externals/boost/libs/date_time/src/posix_time/posix_time_types.cpp
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/* Copyright (c) 2002-2004 CrystalClear Software, Inc.
|
||||
* Use, modification and distribution is subject to the
|
||||
* Boost Software License, Version 1.0. (See accompanying
|
||||
* file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
* Author: Jeff Garland
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
|
||||
//File doesn't have a current purpose except to generate docs
|
||||
//and keep it changeable without recompiles
|
||||
|
||||
/** @defgroup time_basics Time Basics
|
||||
|
||||
**/
|
||||
|
||||
/** @defgroup time_format Time Formatting
|
||||
|
||||
**/
|
||||
|
||||
|
||||
|
||||
/*! @example local_utc_conversion.cpp
|
||||
Demonstrate utc to local and local to utc calculations including dst.
|
||||
*/
|
||||
/*! @example time_periods.cpp Demonstrate some simple uses of time periods.
|
||||
*/
|
||||
/*! @example print_hours.cpp Demonstrate time iteration, clock retrieval, and simple calculation.
|
||||
*/
|
||||
/*! @example time_math.cpp Various types of calculations with times and time durations.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
349
externals/boost/libs/exception/src/clone_current_exception_non_intrusive.cpp
vendored
Normal file
349
externals/boost/libs/exception/src/clone_current_exception_non_intrusive.cpp
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
//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)
|
||||
|
||||
//This MSVC-specific cpp file implements non-intrusive cloning of exception objects.
|
||||
//Based on an exception_ptr implementation by Anthony Williams.
|
||||
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
#error This file requires exception handling to be enabled.
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/exception/detail/clone_current_exception.hpp>
|
||||
|
||||
#if defined(BOOST_ENABLE_NON_INTRUSIVE_EXCEPTION_PTR) && defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
//Non-intrusive cloning support implemented below, only for MSVC versions mentioned above.
|
||||
//Thanks Anthony Williams!
|
||||
//Thanks to Martin Weiss for implementing 64-bit support!
|
||||
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
unsigned const exception_maximum_parameters=15;
|
||||
unsigned const exception_noncontinuable=1;
|
||||
|
||||
#if _MSC_VER==1310
|
||||
int const exception_info_offset=0x74;
|
||||
#elif ((_MSC_VER==1400 || _MSC_VER==1500) && !defined _M_X64)
|
||||
int const exception_info_offset=0x80;
|
||||
#elif ((_MSC_VER==1400 || _MSC_VER==1500) && defined _M_X64)
|
||||
int const exception_info_offset=0xE0;
|
||||
#else
|
||||
int const exception_info_offset=-1;
|
||||
#endif
|
||||
|
||||
struct
|
||||
exception_record
|
||||
{
|
||||
unsigned long ExceptionCode;
|
||||
unsigned long ExceptionFlags;
|
||||
exception_record * ExceptionRecord;
|
||||
void * ExceptionAddress;
|
||||
unsigned long NumberParameters;
|
||||
ULONG_PTR ExceptionInformation[exception_maximum_parameters];
|
||||
};
|
||||
|
||||
struct
|
||||
exception_pointers
|
||||
{
|
||||
exception_record * ExceptionRecord;
|
||||
void * ContextRecord;
|
||||
};
|
||||
|
||||
unsigned const cpp_exception_code=0xE06D7363;
|
||||
unsigned const cpp_exception_magic_flag=0x19930520;
|
||||
#ifdef _M_X64
|
||||
unsigned const cpp_exception_parameter_count=4;
|
||||
#else
|
||||
unsigned const cpp_exception_parameter_count=3;
|
||||
#endif
|
||||
|
||||
struct
|
||||
dummy_exception_type
|
||||
{
|
||||
};
|
||||
|
||||
typedef int(dummy_exception_type::*normal_copy_constructor_ptr)(void * src);
|
||||
typedef int(dummy_exception_type::*copy_constructor_with_virtual_base_ptr)(void * src,void * dst);
|
||||
typedef void (dummy_exception_type::*destructor_ptr)();
|
||||
|
||||
union
|
||||
cpp_copy_constructor
|
||||
{
|
||||
void * address;
|
||||
normal_copy_constructor_ptr normal_copy_constructor;
|
||||
copy_constructor_with_virtual_base_ptr copy_constructor_with_virtual_base;
|
||||
};
|
||||
|
||||
union
|
||||
cpp_destructor
|
||||
{
|
||||
void * address;
|
||||
destructor_ptr destructor;
|
||||
};
|
||||
|
||||
enum
|
||||
cpp_type_flags
|
||||
{
|
||||
class_is_simple_type=1,
|
||||
class_has_virtual_base=4
|
||||
};
|
||||
|
||||
// ATTENTION: On x86 fields such as type_info and copy_constructor are really pointers
|
||||
// but on 64bit these are 32bit offsets from HINSTANCE. Hints on the 64bit handling from
|
||||
// http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx .
|
||||
struct
|
||||
cpp_type_info
|
||||
{
|
||||
unsigned flags;
|
||||
int type_info;
|
||||
int this_offset;
|
||||
int vbase_descr;
|
||||
int vbase_offset;
|
||||
unsigned long size;
|
||||
int copy_constructor;
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_type_info_table
|
||||
{
|
||||
unsigned count;
|
||||
int info;
|
||||
};
|
||||
|
||||
struct
|
||||
cpp_exception_type
|
||||
{
|
||||
unsigned flags;
|
||||
int destructor;
|
||||
int custom_handler;
|
||||
int type_info_table;
|
||||
};
|
||||
|
||||
struct
|
||||
exception_object_deleter
|
||||
{
|
||||
cpp_exception_type const & et_;
|
||||
size_t image_base_;
|
||||
|
||||
exception_object_deleter( cpp_exception_type const & et, size_t image_base ):
|
||||
et_(et),
|
||||
image_base_(image_base)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
operator()( void * obj )
|
||||
{
|
||||
BOOST_ASSERT(obj!=0);
|
||||
dummy_exception_type* dummy_exception_ptr = static_cast<dummy_exception_type *>(obj);
|
||||
if( et_.destructor )
|
||||
{
|
||||
cpp_destructor destructor;
|
||||
destructor.address = reinterpret_cast<void *>(et_.destructor + image_base_);
|
||||
(dummy_exception_ptr->*(destructor.destructor))();
|
||||
}
|
||||
free(obj);
|
||||
}
|
||||
};
|
||||
|
||||
cpp_type_info const &
|
||||
get_cpp_type_info( cpp_exception_type const & et, size_t image_base )
|
||||
{
|
||||
cpp_type_info_table * const typearray = reinterpret_cast<cpp_type_info_table * const>(et.type_info_table + image_base);
|
||||
cpp_type_info * const ti = reinterpret_cast<cpp_type_info * const>(typearray->info + image_base);
|
||||
BOOST_ASSERT(ti!=0);
|
||||
return *ti;
|
||||
}
|
||||
|
||||
void
|
||||
copy_msvc_exception( void * dst, void * src, cpp_type_info const & ti, size_t image_base )
|
||||
{
|
||||
cpp_copy_constructor copy_constructor;
|
||||
copy_constructor.address = reinterpret_cast<void *>(ti.copy_constructor + image_base);
|
||||
|
||||
if( !(ti.flags & class_is_simple_type) && copy_constructor.normal_copy_constructor )
|
||||
{
|
||||
dummy_exception_type * dummy_exception_ptr = static_cast<dummy_exception_type *>(dst);
|
||||
if( ti.flags & class_has_virtual_base )
|
||||
(dummy_exception_ptr->*(copy_constructor.copy_constructor_with_virtual_base))(src,dst);
|
||||
else
|
||||
(dummy_exception_ptr->*(copy_constructor.normal_copy_constructor))(src);
|
||||
}
|
||||
else
|
||||
memmove(dst,src,ti.size);
|
||||
}
|
||||
|
||||
boost::shared_ptr<void>
|
||||
clone_msvc_exception( void * src, cpp_exception_type const & et, size_t image_base )
|
||||
{
|
||||
BOOST_ASSERT(src!=0);
|
||||
cpp_type_info const & ti=get_cpp_type_info(et,image_base);
|
||||
if( void * dst = malloc(ti.size) )
|
||||
{
|
||||
try
|
||||
{
|
||||
copy_msvc_exception(dst,src,ti,image_base);
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
free(dst);
|
||||
throw;
|
||||
}
|
||||
return boost::shared_ptr<void>(dst,exception_object_deleter(et,image_base));
|
||||
}
|
||||
else
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
class
|
||||
cloned_exception:
|
||||
public boost::exception_detail::clone_base
|
||||
{
|
||||
cloned_exception( cloned_exception const & );
|
||||
cloned_exception & operator=( cloned_exception const & );
|
||||
|
||||
cpp_exception_type const & et_;
|
||||
size_t image_base_;
|
||||
boost::shared_ptr<void> exc_;
|
||||
|
||||
public:
|
||||
cloned_exception( EXCEPTION_RECORD const * record ):
|
||||
et_(*reinterpret_cast<cpp_exception_type const *>(record->ExceptionInformation[2])),
|
||||
image_base_((cpp_exception_parameter_count==4) ? record->ExceptionInformation[3] : 0),
|
||||
exc_(clone_msvc_exception(reinterpret_cast<void *>(record->ExceptionInformation[1]),et_,image_base_))
|
||||
{
|
||||
}
|
||||
|
||||
cloned_exception( void * exc, cpp_exception_type const & et, size_t image_base ):
|
||||
et_(et),
|
||||
image_base_(image_base),
|
||||
exc_(clone_msvc_exception(exc,et_,image_base))
|
||||
{
|
||||
}
|
||||
|
||||
~cloned_exception() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
}
|
||||
|
||||
boost::exception_detail::clone_base const *
|
||||
clone() const
|
||||
{
|
||||
return new cloned_exception(exc_.get(),et_,image_base_);
|
||||
}
|
||||
|
||||
void
|
||||
rethrow() const
|
||||
{
|
||||
cpp_type_info const & ti=get_cpp_type_info(et_,image_base_);
|
||||
void * dst = _alloca(ti.size);
|
||||
copy_msvc_exception(dst,exc_.get(),ti,image_base_);
|
||||
ULONG_PTR args[cpp_exception_parameter_count];
|
||||
args[0]=cpp_exception_magic_flag;
|
||||
args[1]=reinterpret_cast<ULONG_PTR>(dst);
|
||||
args[2]=reinterpret_cast<ULONG_PTR>(&et_);
|
||||
if (cpp_exception_parameter_count==4)
|
||||
args[3]=image_base_;
|
||||
|
||||
RaiseException(cpp_exception_code,EXCEPTION_NONCONTINUABLE,cpp_exception_parameter_count,args);
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
is_cpp_exception( EXCEPTION_RECORD const * record )
|
||||
{
|
||||
return record &&
|
||||
(record->ExceptionCode==cpp_exception_code) &&
|
||||
(record->NumberParameters==cpp_exception_parameter_count) &&
|
||||
(record->ExceptionInformation[0]==cpp_exception_magic_flag);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
exception_cloning_filter( int & result, boost::exception_detail::clone_base const * & ptr, void * info_ )
|
||||
{
|
||||
BOOST_ASSERT(exception_info_offset>=0);
|
||||
BOOST_ASSERT(info_!=0);
|
||||
EXCEPTION_RECORD* record = static_cast<EXCEPTION_POINTERS *>(info_)->ExceptionRecord;
|
||||
if( is_cpp_exception(record) )
|
||||
{
|
||||
if( !record->ExceptionInformation[2] )
|
||||
record = *reinterpret_cast<EXCEPTION_RECORD * *>(reinterpret_cast<char *>(_errno())+exception_info_offset);
|
||||
if( is_cpp_exception(record) && record->ExceptionInformation[2] )
|
||||
try
|
||||
{
|
||||
ptr = new cloned_exception(record);
|
||||
result = boost::exception_detail::clone_current_exception_result::success;
|
||||
}
|
||||
catch(
|
||||
std::bad_alloc & )
|
||||
{
|
||||
result = boost::exception_detail::clone_current_exception_result::bad_alloc;
|
||||
}
|
||||
catch(
|
||||
... )
|
||||
{
|
||||
result = boost::exception_detail::clone_current_exception_result::bad_exception;
|
||||
}
|
||||
}
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
int
|
||||
clone_current_exception_non_intrusive( clone_base const * & cloned )
|
||||
{
|
||||
BOOST_ASSERT(!cloned);
|
||||
int result = clone_current_exception_result::not_supported;
|
||||
if( exception_info_offset>=0 )
|
||||
{
|
||||
clone_base const * ptr=0;
|
||||
__try
|
||||
{
|
||||
throw;
|
||||
}
|
||||
__except(exception_cloning_filter(result,ptr,GetExceptionInformation()))
|
||||
{
|
||||
}
|
||||
if( result==clone_current_exception_result::success )
|
||||
cloned=ptr;
|
||||
}
|
||||
BOOST_ASSERT(result!=clone_current_exception_result::success || cloned);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//On all other compilers, return clone_current_exception_result::not_supported.
|
||||
//On such platforms, only the intrusive enable_current_exception() cloning will work.
|
||||
|
||||
namespace
|
||||
boost
|
||||
{
|
||||
namespace
|
||||
exception_detail
|
||||
{
|
||||
int
|
||||
clone_current_exception_non_intrusive( clone_base const * & )
|
||||
{
|
||||
return clone_current_exception_result::not_supported;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
171
externals/boost/libs/iostreams/src/bzip2.cpp
vendored
Normal file
171
externals/boost/libs/iostreams/src/bzip2.cpp
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
||||
// (C) Copyright 2003-2007 Jonathan Turkanis
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// To configure Boost to work with libbz2, see the
|
||||
// installation instructions here:
|
||||
// http://boost.org/libs/iostreams/doc/index.html?path=7
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/filter/bzip2.hpp>
|
||||
#include "bzlib.h" // Julian Seward's "bzip.h" header.
|
||||
// To configure Boost to work with libbz2, see the
|
||||
// installation instructions here:
|
||||
// http://boost.org/libs/iostreams/doc/index.html?path=7
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
namespace bzip2 {
|
||||
|
||||
// Status codes
|
||||
|
||||
const int ok = BZ_OK;
|
||||
const int run_ok = BZ_RUN_OK;
|
||||
const int flush_ok = BZ_FLUSH_OK;
|
||||
const int finish_ok = BZ_FINISH_OK;
|
||||
const int stream_end = BZ_STREAM_END;
|
||||
const int sequence_error = BZ_SEQUENCE_ERROR;
|
||||
const int param_error = BZ_PARAM_ERROR;
|
||||
const int mem_error = BZ_MEM_ERROR;
|
||||
const int data_error = BZ_DATA_ERROR;
|
||||
const int data_error_magic = BZ_DATA_ERROR_MAGIC;
|
||||
const int io_error = BZ_IO_ERROR;
|
||||
const int unexpected_eof = BZ_UNEXPECTED_EOF;
|
||||
const int outbuff_full = BZ_OUTBUFF_FULL;
|
||||
const int config_error = BZ_CONFIG_ERROR;
|
||||
|
||||
// Action codes
|
||||
|
||||
const int finish = BZ_FINISH;
|
||||
const int run = BZ_RUN;
|
||||
|
||||
} // End namespace bzip2.
|
||||
|
||||
//------------------Implementation of bzip2_error-----------------------------//
|
||||
|
||||
bzip2_error::bzip2_error(int error)
|
||||
: BOOST_IOSTREAMS_FAILURE("bzip2 error"), error_(error)
|
||||
{ }
|
||||
|
||||
void bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case BZ_OK:
|
||||
case BZ_RUN_OK:
|
||||
case BZ_FLUSH_OK:
|
||||
case BZ_FINISH_OK:
|
||||
case BZ_STREAM_END:
|
||||
return;
|
||||
case BZ_MEM_ERROR:
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
default:
|
||||
boost::throw_exception(bzip2_error(error));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------Implementation of bzip2_base------------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
bzip2_base::bzip2_base(const bzip2_params& params)
|
||||
: params_(params), stream_(new bz_stream), ready_(false)
|
||||
{ }
|
||||
|
||||
bzip2_base::~bzip2_base() { delete static_cast<bz_stream*>(stream_); }
|
||||
|
||||
void bzip2_base::before( const char*& src_begin, const char* src_end,
|
||||
char*& dest_begin, char* dest_end )
|
||||
{
|
||||
bz_stream* s = static_cast<bz_stream*>(stream_);
|
||||
s->next_in = const_cast<char*>(src_begin);
|
||||
s->avail_in = static_cast<unsigned>(src_end - src_begin);
|
||||
s->next_out = reinterpret_cast<char*>(dest_begin);
|
||||
s->avail_out= static_cast<unsigned>(dest_end - dest_begin);
|
||||
}
|
||||
|
||||
void bzip2_base::after(const char*& src_begin, char*& dest_begin)
|
||||
{
|
||||
bz_stream* s = static_cast<bz_stream*>(stream_);
|
||||
src_begin = const_cast<char*>(s->next_in);
|
||||
dest_begin = s->next_out;
|
||||
}
|
||||
|
||||
int bzip2_base::check_end(const char* src_begin, const char* dest_begin)
|
||||
{
|
||||
bz_stream* s = static_cast<bz_stream*>(stream_);
|
||||
if( src_begin == s->next_in &&
|
||||
s->avail_in == 0 &&
|
||||
dest_begin == s->next_out) {
|
||||
return bzip2::unexpected_eof;
|
||||
} else {
|
||||
return bzip2::ok;
|
||||
}
|
||||
}
|
||||
|
||||
int bzip2_base::end(bool compress, std::nothrow_t)
|
||||
{
|
||||
if (!ready_) return bzip2::ok;
|
||||
ready_ = false;
|
||||
bz_stream* s = static_cast<bz_stream*>(stream_);
|
||||
return compress ? BZ2_bzCompressEnd(s) : BZ2_bzDecompressEnd(s);
|
||||
}
|
||||
|
||||
void bzip2_base::end(bool compress)
|
||||
{
|
||||
bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
end(compress, std::nothrow)
|
||||
);
|
||||
}
|
||||
|
||||
int bzip2_base::compress(int action)
|
||||
{
|
||||
return BZ2_bzCompress(static_cast<bz_stream*>(stream_), action);
|
||||
}
|
||||
|
||||
int bzip2_base::decompress()
|
||||
{
|
||||
return BZ2_bzDecompress(static_cast<bz_stream*>(stream_));
|
||||
}
|
||||
|
||||
void bzip2_base::do_init
|
||||
( bool compress,
|
||||
bzip2::alloc_func /* alloc */,
|
||||
bzip2::free_func /* free */,
|
||||
void* derived )
|
||||
{
|
||||
bz_stream* s = static_cast<bz_stream*>(stream_);
|
||||
|
||||
// Current interface for customizing memory management
|
||||
// is non-conforming and has been disabled:
|
||||
// s->bzalloc = alloc;
|
||||
// s->bzfree = free;
|
||||
s->bzalloc = 0;
|
||||
s->bzfree = 0;
|
||||
s->opaque = derived;
|
||||
bzip2_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
compress ?
|
||||
BZ2_bzCompressInit( s,
|
||||
params_.block_size,
|
||||
0,
|
||||
params_.work_factor ) :
|
||||
BZ2_bzDecompressInit( s,
|
||||
0,
|
||||
params_.small )
|
||||
);
|
||||
ready_ = true;
|
||||
}
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
621
externals/boost/libs/iostreams/src/file_descriptor.cpp
vendored
Normal file
621
externals/boost/libs/iostreams/src/file_descriptor.cpp
vendored
Normal file
@@ -0,0 +1,621 @@
|
||||
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
||||
// (C) Copyright 2003-2007 Jonathan Turkanis
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdio> // SEEK_SET, etc.
|
||||
#include <boost/config.hpp> // BOOST_JOIN
|
||||
#include <boost/iostreams/detail/error.hpp>
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/detail/config/rtl.hpp> // BOOST_IOSTREAMS_FD_XXX
|
||||
#include <boost/iostreams/detail/config/windows_posix.hpp>
|
||||
#include <boost/iostreams/detail/system_failure.hpp>
|
||||
#include <boost/iostreams/detail/ios.hpp> // openmodes, failure.
|
||||
#include <boost/iostreams/device/file_descriptor.hpp>
|
||||
#include <boost/integer_traits.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
// Must come last.
|
||||
#include <boost/iostreams/detail/config/disable_warnings.hpp>
|
||||
|
||||
// OS-specific headers for low-level i/o.
|
||||
|
||||
#include <fcntl.h> // file opening flags.
|
||||
#include <sys/stat.h> // file access permissions.
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
# include <io.h> // low-level file i/o.
|
||||
# define WINDOWS_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# ifndef INVALID_SET_FILE_POINTER
|
||||
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
# endif
|
||||
#else
|
||||
# include <sys/types.h> // mode_t.
|
||||
# include <unistd.h> // low-level file i/o.
|
||||
#endif
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
//------------------Definition of file_descriptor_impl------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Contains the platform dependant implementation
|
||||
struct file_descriptor_impl {
|
||||
// Note: These need to match file_desciptor_flags
|
||||
enum flags {
|
||||
never_close = 0,
|
||||
close_on_exit = 1,
|
||||
close_on_close = 2,
|
||||
close_always = 3
|
||||
};
|
||||
|
||||
file_descriptor_impl();
|
||||
~file_descriptor_impl();
|
||||
void open(file_handle fd, flags);
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
void open(int fd, flags);
|
||||
#endif
|
||||
void open(const detail::path&, BOOST_IOS::openmode);
|
||||
bool is_open() const;
|
||||
void close();
|
||||
void close_impl(bool close_flag, bool throw_);
|
||||
std::streamsize read(char* s, std::streamsize n);
|
||||
std::streamsize write(const char* s, std::streamsize n);
|
||||
std::streampos seek(stream_offset off, BOOST_IOS::seekdir way);
|
||||
static file_handle invalid_handle();
|
||||
file_handle handle_;
|
||||
int flags_;
|
||||
};
|
||||
|
||||
//------------------Implementation of file_descriptor_impl--------------------//
|
||||
|
||||
file_descriptor_impl::file_descriptor_impl()
|
||||
: handle_(invalid_handle()), flags_(0)
|
||||
{ }
|
||||
|
||||
file_descriptor_impl::~file_descriptor_impl()
|
||||
{
|
||||
close_impl(flags_ & close_on_exit, false);
|
||||
}
|
||||
|
||||
void file_descriptor_impl::open(file_handle fd, flags f)
|
||||
{
|
||||
// Using 'close' to close the existing handle so that it will throw an
|
||||
// exception if it fails.
|
||||
//
|
||||
// Only closing after assigning the new handle, so that the class will
|
||||
// take ownership of the handle regardless of whether close throws.
|
||||
|
||||
file_descriptor_impl tmp;
|
||||
tmp.handle_ = handle_;
|
||||
tmp.flags_ = flags_ & close_on_exit ? close_on_close : never_close;
|
||||
|
||||
handle_ = fd;
|
||||
flags_ = f;
|
||||
|
||||
tmp.close();
|
||||
}
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
void file_descriptor_impl::open(int fd, flags f)
|
||||
{ open(reinterpret_cast<file_handle>(_get_osfhandle(fd)), f); }
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
void file_descriptor_impl::open(const detail::path& p, BOOST_IOS::openmode mode)
|
||||
{
|
||||
close_impl(flags_ & close_on_exit, true);
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
DWORD dwDesiredAccess;
|
||||
DWORD dwCreationDisposition;
|
||||
|
||||
if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) ||
|
||||
((mode & BOOST_IOS::trunc) &&
|
||||
((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) {
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
|
||||
}
|
||||
else if ( mode & BOOST_IOS::in ) {
|
||||
if ( mode & BOOST_IOS::app )
|
||||
{
|
||||
dwCreationDisposition = OPEN_ALWAYS;
|
||||
dwDesiredAccess =
|
||||
GENERIC_READ |
|
||||
FILE_APPEND_DATA |
|
||||
FILE_WRITE_ATTRIBUTES |
|
||||
FILE_WRITE_EA |
|
||||
STANDARD_RIGHTS_WRITE |
|
||||
SYNCHRONIZE;
|
||||
}
|
||||
else if ( mode & BOOST_IOS::trunc )
|
||||
{
|
||||
dwCreationDisposition = CREATE_ALWAYS;
|
||||
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
else if ( mode & BOOST_IOS::out )
|
||||
{
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwCreationDisposition = OPEN_EXISTING;
|
||||
dwDesiredAccess = GENERIC_READ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( mode & BOOST_IOS::app )
|
||||
{
|
||||
dwCreationDisposition = OPEN_ALWAYS;
|
||||
dwDesiredAccess =
|
||||
FILE_APPEND_DATA |
|
||||
FILE_WRITE_ATTRIBUTES |
|
||||
FILE_WRITE_EA |
|
||||
STANDARD_RIGHTS_WRITE |
|
||||
SYNCHRONIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dwCreationDisposition = CREATE_ALWAYS;
|
||||
dwDesiredAccess = GENERIC_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HANDLE handle = p.is_wide() ?
|
||||
::CreateFileW( p.c_wstr(),
|
||||
dwDesiredAccess,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, // lpSecurityAttributes
|
||||
dwCreationDisposition,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL ) : // hTemplateFile
|
||||
::CreateFileA( p.c_str(),
|
||||
dwDesiredAccess,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, // lpSecurityAttributes
|
||||
dwCreationDisposition,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL ); // hTemplateFile
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
handle_ = handle;
|
||||
flags_ = close_always;
|
||||
} else {
|
||||
flags_ = 0;
|
||||
throw_system_failure("failed opening file");
|
||||
}
|
||||
#else // #ifdef BOOST_IOSTREAMS_WINDOWS //------------------------------------//
|
||||
|
||||
// Calculate oflag argument to open.
|
||||
|
||||
int oflag = 0;
|
||||
if ( !(mode & (BOOST_IOS::in | BOOST_IOS::out | BOOST_IOS::app)) ||
|
||||
((mode & BOOST_IOS::trunc) &&
|
||||
((mode & BOOST_IOS::app) || !(mode & BOOST_IOS::out))) ) {
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad open mode"));
|
||||
}
|
||||
else if ( mode & BOOST_IOS::in ) {
|
||||
if ( mode & BOOST_IOS::app )
|
||||
oflag |= O_CREAT | O_APPEND | O_RDWR;
|
||||
else if ( mode & BOOST_IOS::trunc )
|
||||
oflag |= O_CREAT | O_TRUNC | O_RDWR;
|
||||
else if ( mode & BOOST_IOS::out )
|
||||
oflag |= O_RDWR;
|
||||
else
|
||||
oflag |= O_RDONLY;
|
||||
}
|
||||
else {
|
||||
if ( mode & BOOST_IOS::app )
|
||||
oflag |= O_CREAT | O_APPEND | O_WRONLY;
|
||||
else
|
||||
oflag |= O_CREAT | O_TRUNC | O_WRONLY;
|
||||
}
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
oflag |= O_LARGEFILE;
|
||||
#endif
|
||||
|
||||
// Calculate pmode argument to open.
|
||||
|
||||
mode_t pmode = S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IWGRP |
|
||||
S_IROTH | S_IWOTH;
|
||||
|
||||
// Open file.
|
||||
|
||||
int fd = BOOST_IOSTREAMS_FD_OPEN(p.c_str(), oflag, pmode);
|
||||
if (fd == -1) {
|
||||
boost::throw_exception(system_failure("failed opening file"));
|
||||
} else {
|
||||
if ( mode & BOOST_IOS::ate ) {
|
||||
if (BOOST_IOSTREAMS_FD_SEEK(fd, 0, SEEK_END) == -1) {
|
||||
BOOST_IOSTREAMS_FD_CLOSE(fd);
|
||||
boost::throw_exception(system_failure("failed opening file"));
|
||||
}
|
||||
}
|
||||
handle_ = fd;
|
||||
flags_ = close_always;
|
||||
}
|
||||
#endif // #ifndef BOOST_IOSTREAMS_WINDOWS //----------------------------------//
|
||||
}
|
||||
|
||||
bool file_descriptor_impl::is_open() const
|
||||
{ return handle_ != invalid_handle(); }
|
||||
|
||||
void file_descriptor_impl::close()
|
||||
{
|
||||
close_impl((flags_ & close_on_close) != 0, true);
|
||||
}
|
||||
|
||||
void file_descriptor_impl::close_impl(bool close_flag, bool throw_) {
|
||||
if (handle_ != invalid_handle()) {
|
||||
bool success = true;
|
||||
|
||||
if (close_flag) {
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
success = ::CloseHandle(handle_) == 1;
|
||||
#else
|
||||
success = BOOST_IOSTREAMS_FD_CLOSE(handle_) != -1;
|
||||
#endif
|
||||
}
|
||||
// Even if the close fails, we want nothing more to do with the handle
|
||||
handle_ = invalid_handle();
|
||||
flags_ = 0;
|
||||
if (!success && throw_)
|
||||
throw_system_failure("failed closing file");
|
||||
}
|
||||
}
|
||||
|
||||
std::streamsize file_descriptor_impl::read(char* s, std::streamsize n)
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
DWORD result;
|
||||
if (!::ReadFile(handle_, s, static_cast<DWORD>(n), &result, NULL))
|
||||
{
|
||||
// report EOF if the write-side of a pipe has been closed
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
throw_system_failure("failed reading");
|
||||
}
|
||||
return result == 0 ? -1 : static_cast<std::streamsize>(result);
|
||||
#else // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
errno = 0;
|
||||
std::streamsize result = BOOST_IOSTREAMS_FD_READ(handle_, s, n);
|
||||
if (errno != 0)
|
||||
throw_system_failure("failed reading");
|
||||
return result == 0 ? -1 : result;
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
}
|
||||
|
||||
std::streamsize file_descriptor_impl::write(const char* s, std::streamsize n)
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
DWORD ignore;
|
||||
if (!::WriteFile(handle_, s, static_cast<DWORD>(n), &ignore, NULL))
|
||||
throw_system_failure("failed writing");
|
||||
return n;
|
||||
#else // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
int amt = BOOST_IOSTREAMS_FD_WRITE(handle_, s, n);
|
||||
if (amt < n) // Handles blocking fd's only.
|
||||
throw_system_failure("failed writing");
|
||||
return n;
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
}
|
||||
|
||||
std::streampos file_descriptor_impl::seek
|
||||
(stream_offset off, BOOST_IOS::seekdir way)
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
LONG lDistanceToMove = static_cast<LONG>(off & 0xffffffff);
|
||||
LONG lDistanceToMoveHigh = static_cast<LONG>(off >> 32);
|
||||
DWORD dwResultLow =
|
||||
::SetFilePointer( handle_,
|
||||
lDistanceToMove,
|
||||
&lDistanceToMoveHigh,
|
||||
way == BOOST_IOS::beg ?
|
||||
FILE_BEGIN :
|
||||
way == BOOST_IOS::cur ?
|
||||
FILE_CURRENT :
|
||||
FILE_END );
|
||||
if ( dwResultLow == INVALID_SET_FILE_POINTER &&
|
||||
::GetLastError() != NO_ERROR )
|
||||
{
|
||||
boost::throw_exception(system_failure("failed seeking"));
|
||||
} else {
|
||||
return offset_to_position(
|
||||
(stream_offset(lDistanceToMoveHigh) << 32) + dwResultLow
|
||||
);
|
||||
}
|
||||
#else // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
if ( off > integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_max ||
|
||||
off < integer_traits<BOOST_IOSTREAMS_FD_OFFSET>::const_min )
|
||||
{
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("bad offset"));
|
||||
}
|
||||
stream_offset result =
|
||||
BOOST_IOSTREAMS_FD_SEEK(
|
||||
handle_,
|
||||
static_cast<BOOST_IOSTREAMS_FD_OFFSET>(off),
|
||||
( way == BOOST_IOS::beg ?
|
||||
SEEK_SET :
|
||||
way == BOOST_IOS::cur ?
|
||||
SEEK_CUR :
|
||||
SEEK_END )
|
||||
);
|
||||
if (result == -1)
|
||||
boost::throw_exception(system_failure("failed seeking"));
|
||||
return offset_to_position(result);
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
}
|
||||
|
||||
// Returns the value stored in a file_handle variable when no file is open
|
||||
file_handle file_descriptor_impl::invalid_handle()
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
return INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//------------------Implementation of file_descriptor-------------------------//
|
||||
|
||||
file_descriptor::file_descriptor() : pimpl_(new impl_type) { }
|
||||
|
||||
file_descriptor::file_descriptor(handle_type fd, file_descriptor_flags f)
|
||||
: pimpl_(new impl_type)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor::file_descriptor(handle_type fd, bool close_on_exit)
|
||||
: pimpl_(new impl_type)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
file_descriptor::file_descriptor(int fd, file_descriptor_flags f)
|
||||
: pimpl_(new impl_type)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor::file_descriptor(int fd, bool close_on_exit)
|
||||
: pimpl_(new impl_type)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
file_descriptor::file_descriptor( const std::string& path,
|
||||
BOOST_IOS::openmode mode )
|
||||
: pimpl_(new impl_type)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor::file_descriptor( const char* path,
|
||||
BOOST_IOS::openmode mode )
|
||||
: pimpl_(new impl_type)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor::file_descriptor(const file_descriptor& other)
|
||||
: pimpl_(other.pimpl_)
|
||||
{ }
|
||||
|
||||
void file_descriptor::open(handle_type fd, file_descriptor_flags f)
|
||||
{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor::open(handle_type fd, bool close_on_exit)
|
||||
{ pimpl_->open(fd, close_on_exit ?
|
||||
detail::file_descriptor_impl::close_always :
|
||||
detail::file_descriptor_impl::close_on_close); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
void file_descriptor::open(int fd, file_descriptor_flags f)
|
||||
{ pimpl_->open(fd, static_cast<detail::file_descriptor_impl::flags>(f)); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor::open(int fd, bool close_on_exit)
|
||||
{ pimpl_->open(fd, close_on_exit ?
|
||||
detail::file_descriptor_impl::close_always :
|
||||
detail::file_descriptor_impl::close_on_close); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
void file_descriptor::open(const std::string& path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
void file_descriptor::open(const char* path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
bool file_descriptor::is_open() const { return pimpl_->is_open(); }
|
||||
|
||||
void file_descriptor::close() { pimpl_->close(); }
|
||||
|
||||
std::streamsize file_descriptor::read(char_type* s, std::streamsize n)
|
||||
{ return pimpl_->read(s, n); }
|
||||
|
||||
std::streamsize file_descriptor::write(const char_type* s, std::streamsize n)
|
||||
{ return pimpl_->write(s, n); }
|
||||
|
||||
std::streampos file_descriptor::seek(stream_offset off, BOOST_IOS::seekdir way)
|
||||
{ return pimpl_->seek(off, way); }
|
||||
|
||||
detail::file_handle file_descriptor::handle() const { return pimpl_->handle_; }
|
||||
|
||||
void file_descriptor::init() { pimpl_.reset(new impl_type); }
|
||||
|
||||
void file_descriptor::open(
|
||||
const detail::path& path,
|
||||
BOOST_IOS::openmode mode,
|
||||
BOOST_IOS::openmode base )
|
||||
{
|
||||
mode |= base;
|
||||
pimpl_->open(path, mode);
|
||||
}
|
||||
|
||||
//------------------Implementation of file_descriptor_source------------------//
|
||||
|
||||
file_descriptor_source::file_descriptor_source(
|
||||
handle_type fd, file_descriptor_flags f)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor_source::file_descriptor_source(
|
||||
handle_type fd, bool close_on_exit)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
file_descriptor_source::file_descriptor_source(int fd, file_descriptor_flags f)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor_source::file_descriptor_source(int fd, bool close_on_exit)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
file_descriptor_source::file_descriptor_source(
|
||||
const std::string& path, BOOST_IOS::openmode mode)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor_source::file_descriptor_source(
|
||||
const char* path, BOOST_IOS::openmode mode)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor_source::file_descriptor_source(
|
||||
const file_descriptor_source& other)
|
||||
: file_descriptor(static_cast<const file_descriptor&>(other))
|
||||
{ }
|
||||
|
||||
void file_descriptor_source::open(handle_type fd, file_descriptor_flags f)
|
||||
{ file_descriptor::open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor_source::open(handle_type fd, bool close_on_exit)
|
||||
{ file_descriptor::open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
void file_descriptor_source::open(int fd, file_descriptor_flags f)
|
||||
{ file_descriptor::open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor_source::open(int fd, bool close_on_exit)
|
||||
{ file_descriptor::open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
void file_descriptor_source::open(
|
||||
const std::string& path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
void file_descriptor_source::open(
|
||||
const char* path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
void file_descriptor_source::open(
|
||||
const detail::path& path, BOOST_IOS::openmode mode)
|
||||
{
|
||||
if (mode & (BOOST_IOS::out | BOOST_IOS::trunc))
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
|
||||
file_descriptor::open(path, mode, BOOST_IOS::in);
|
||||
}
|
||||
|
||||
//------------------Implementation of file_descriptor_sink--------------------//
|
||||
|
||||
file_descriptor_sink::file_descriptor_sink(
|
||||
handle_type fd, file_descriptor_flags f)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor_sink::file_descriptor_sink(
|
||||
handle_type fd, bool close_on_exit)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
file_descriptor_sink::file_descriptor_sink(int fd, file_descriptor_flags f)
|
||||
{ open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
file_descriptor_sink::file_descriptor_sink(int fd, bool close_on_exit)
|
||||
{ open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
file_descriptor_sink::file_descriptor_sink(
|
||||
const std::string& path, BOOST_IOS::openmode mode)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor_sink::file_descriptor_sink(
|
||||
const char* path, BOOST_IOS::openmode mode)
|
||||
{ open(path, mode); }
|
||||
|
||||
file_descriptor_sink::file_descriptor_sink(const file_descriptor_sink& other)
|
||||
: file_descriptor(static_cast<const file_descriptor&>(other))
|
||||
{ }
|
||||
|
||||
void file_descriptor_sink::open(handle_type fd, file_descriptor_flags f)
|
||||
{ file_descriptor::open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor_sink::open(handle_type fd, bool close_on_exit)
|
||||
{ file_descriptor::open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS //---------------------------------------------//
|
||||
|
||||
void file_descriptor_sink::open(int fd, file_descriptor_flags f)
|
||||
{ file_descriptor::open(fd, f); }
|
||||
|
||||
#if defined(BOOST_IOSTREAMS_USE_DEPRECATED)
|
||||
void file_descriptor_sink::open(int fd, bool close_on_exit)
|
||||
{ file_descriptor::open(fd, close_on_exit); }
|
||||
#endif
|
||||
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS //-----------------------------------//
|
||||
|
||||
void file_descriptor_sink::open(
|
||||
const std::string& path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
void file_descriptor_sink::open(
|
||||
const char* path, BOOST_IOS::openmode mode)
|
||||
{ open(detail::path(path), mode); }
|
||||
|
||||
void file_descriptor_sink::open(
|
||||
const detail::path& path, BOOST_IOS::openmode mode)
|
||||
{
|
||||
if (mode & BOOST_IOS::in)
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid mode"));
|
||||
file_descriptor::open(path, mode, BOOST_IOS::out);
|
||||
}
|
||||
|
||||
#include <boost/iostreams/detail/config/enable_warnings.hpp>
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
174
externals/boost/libs/iostreams/src/gzip.cpp
vendored
Normal file
174
externals/boost/libs/iostreams/src/gzip.cpp
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
||||
// (C) Copyright 2003-2007 Jonathan Turkanis
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// To configure Boost to work with libbz2, see the
|
||||
// installation instructions here:
|
||||
// http://boost.org/libs/iostreams/doc/index.html?path=7
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
//------------------Implementation of gzip_header-----------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
void gzip_header::process(char c)
|
||||
{
|
||||
uint8_t value = static_cast<uint8_t>(c);
|
||||
switch (state_) {
|
||||
case s_id1:
|
||||
if (value != gzip::magic::id1)
|
||||
boost::throw_exception(gzip_error(gzip::bad_header));
|
||||
state_ = s_id2;
|
||||
break;
|
||||
case s_id2:
|
||||
if (value != gzip::magic::id2)
|
||||
boost::throw_exception(gzip_error(gzip::bad_header));
|
||||
state_ = s_cm;
|
||||
break;
|
||||
case s_cm:
|
||||
if (value != gzip::method::deflate)
|
||||
boost::throw_exception(gzip_error(gzip::bad_method));
|
||||
state_ = s_flg;
|
||||
break;
|
||||
case s_flg:
|
||||
flags_ = value;
|
||||
state_ = s_mtime;
|
||||
break;
|
||||
case s_mtime:
|
||||
mtime_ += value << (offset_ * 8);
|
||||
if (offset_ == 3) {
|
||||
state_ = s_xfl;
|
||||
offset_ = 0;
|
||||
} else {
|
||||
++offset_;
|
||||
}
|
||||
break;
|
||||
case s_xfl:
|
||||
state_ = s_os;
|
||||
break;
|
||||
case s_os:
|
||||
os_ = value;
|
||||
if (flags_ & gzip::flags::extra) {
|
||||
state_ = s_xlen;
|
||||
} else if (flags_ & gzip::flags::name) {
|
||||
state_ = s_name;
|
||||
} else if (flags_ & gzip::flags::comment) {
|
||||
state_ = s_comment;
|
||||
} else if (flags_ & gzip::flags::header_crc) {
|
||||
state_ = s_hcrc;
|
||||
} else {
|
||||
state_ = s_done;
|
||||
}
|
||||
break;
|
||||
case s_xlen:
|
||||
xlen_ += value << (offset_ * 8);
|
||||
if (offset_ == 1) {
|
||||
state_ = s_extra;
|
||||
offset_ = 0;
|
||||
} else {
|
||||
++offset_;
|
||||
}
|
||||
break;
|
||||
case s_extra:
|
||||
if (--xlen_ == 0) {
|
||||
if (flags_ & gzip::flags::name) {
|
||||
state_ = s_name;
|
||||
} else if (flags_ & gzip::flags::comment) {
|
||||
state_ = s_comment;
|
||||
} else if (flags_ & gzip::flags::header_crc) {
|
||||
state_ = s_hcrc;
|
||||
} else {
|
||||
state_ = s_done;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case s_name:
|
||||
if (c != 0) {
|
||||
file_name_ += c;
|
||||
} else if (flags_ & gzip::flags::comment) {
|
||||
state_ = s_comment;
|
||||
} else if (flags_ & gzip::flags::header_crc) {
|
||||
state_ = s_hcrc;
|
||||
} else {
|
||||
state_ = s_done;
|
||||
}
|
||||
break;
|
||||
case s_comment:
|
||||
if (c != 0) {
|
||||
comment_ += c;
|
||||
} else if (flags_ & gzip::flags::header_crc) {
|
||||
state_ = s_hcrc;
|
||||
} else {
|
||||
state_ = s_done;
|
||||
}
|
||||
break;
|
||||
case s_hcrc:
|
||||
if (offset_ == 1) {
|
||||
state_ = s_done;
|
||||
offset_ = 0;
|
||||
} else {
|
||||
++offset_;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void gzip_header::reset()
|
||||
{
|
||||
file_name_.clear();
|
||||
comment_.clear();
|
||||
os_ = flags_ = offset_ = xlen_ = 0;
|
||||
mtime_ = 0;
|
||||
state_ = s_id1;
|
||||
}
|
||||
|
||||
//------------------Implementation of gzip_footer-----------------------------//
|
||||
|
||||
void gzip_footer::process(char c)
|
||||
{
|
||||
uint8_t value = static_cast<uint8_t>(c);
|
||||
if (state_ == s_crc) {
|
||||
crc_ += value << (offset_ * 8);
|
||||
if (offset_ == 3) {
|
||||
state_ = s_isize;
|
||||
offset_ = 0;
|
||||
} else {
|
||||
++offset_;
|
||||
}
|
||||
} else if (state_ == s_isize) {
|
||||
isize_ += value << (offset_ * 8);
|
||||
if (offset_ == 3) {
|
||||
state_ = s_done;
|
||||
offset_ = 0;
|
||||
} else {
|
||||
++offset_;
|
||||
}
|
||||
} else {
|
||||
BOOST_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void gzip_footer::reset()
|
||||
{
|
||||
crc_ = isize_ = offset_ = 0;
|
||||
state_ = s_crc;
|
||||
}
|
||||
|
||||
} // End namespace boost::iostreams::detail.
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
171
externals/boost/libs/iostreams/src/lzma.cpp
vendored
Normal file
171
externals/boost/libs/iostreams/src/lzma.cpp
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// (C) Copyright Milan Svoboda 2008.
|
||||
// Originally developed under the fusecompress project.
|
||||
// Based on bzip2.cpp by:
|
||||
// (C) Copyright Jonathan Turkanis 2003.
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <lzma.h>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/filter/lzma.hpp>
|
||||
|
||||
|
||||
#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
|
||||
#if LZMA_VERSION < 50020002
|
||||
#define BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
namespace lzma {
|
||||
|
||||
// Compression levels
|
||||
|
||||
const uint32_t no_compression = 0;
|
||||
const uint32_t best_speed = 1;
|
||||
const uint32_t best_compression = 9;
|
||||
const uint32_t default_compression = 2;
|
||||
|
||||
// Status codes
|
||||
|
||||
const int okay = LZMA_OK;
|
||||
const int stream_end = LZMA_STREAM_END;
|
||||
const int unsupported_check = LZMA_UNSUPPORTED_CHECK;
|
||||
const int mem_error = LZMA_MEM_ERROR;
|
||||
const int options_error = LZMA_OPTIONS_ERROR;
|
||||
const int data_error = LZMA_DATA_ERROR;
|
||||
const int buf_error = LZMA_BUF_ERROR;
|
||||
const int prog_error = LZMA_PROG_ERROR;
|
||||
|
||||
// Flush codes
|
||||
|
||||
const int finish = LZMA_FINISH;
|
||||
const int full_flush = LZMA_FULL_FLUSH;
|
||||
const int sync_flush = LZMA_SYNC_FLUSH;
|
||||
const int run = LZMA_RUN;
|
||||
|
||||
// Code for current OS
|
||||
|
||||
} // End namespace lzma.
|
||||
|
||||
//------------------Implementation of lzma_error------------------------------//
|
||||
|
||||
lzma_error::lzma_error(int error)
|
||||
: BOOST_IOSTREAMS_FAILURE("lzma error"), error_(error)
|
||||
{ }
|
||||
|
||||
void lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case LZMA_OK:
|
||||
case LZMA_STREAM_END:
|
||||
return;
|
||||
case LZMA_MEM_ERROR:
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
default:
|
||||
boost::throw_exception(lzma_error(error));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------Implementation of lzma_base-------------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
lzma_base::lzma_base()
|
||||
: stream_(new lzma_stream), level_(lzma::default_compression), threads_(1)
|
||||
{ }
|
||||
|
||||
lzma_base::~lzma_base() { delete static_cast<lzma_stream*>(stream_); }
|
||||
|
||||
void lzma_base::before( const char*& src_begin, const char* src_end,
|
||||
char*& dest_begin, char* dest_end )
|
||||
{
|
||||
lzma_stream* s = static_cast<lzma_stream*>(stream_);
|
||||
s->next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(src_begin));
|
||||
s->avail_in = static_cast<size_t>(src_end - src_begin);
|
||||
s->next_out = reinterpret_cast<uint8_t*>(dest_begin);
|
||||
s->avail_out= static_cast<size_t>(dest_end - dest_begin);
|
||||
}
|
||||
|
||||
void lzma_base::after(const char*& src_begin, char*& dest_begin, bool)
|
||||
{
|
||||
lzma_stream* s = static_cast<lzma_stream*>(stream_);
|
||||
src_begin = const_cast<const char*>(reinterpret_cast<const char*>(s->next_in));
|
||||
dest_begin = reinterpret_cast<char*>(s->next_out);
|
||||
}
|
||||
|
||||
int lzma_base::deflate(int action)
|
||||
{
|
||||
return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
|
||||
}
|
||||
|
||||
int lzma_base::inflate(int action)
|
||||
{
|
||||
return lzma_code(static_cast<lzma_stream*>(stream_), static_cast<lzma_action>(action));
|
||||
}
|
||||
|
||||
void lzma_base::reset(bool compress, bool realloc)
|
||||
{
|
||||
lzma_stream* s = static_cast<lzma_stream*>(stream_);
|
||||
lzma_end(s);
|
||||
if (realloc)
|
||||
{
|
||||
init_stream(compress);
|
||||
}
|
||||
}
|
||||
|
||||
void lzma_base::do_init
|
||||
( const lzma_params& p, bool compress,
|
||||
lzma::alloc_func, lzma::free_func,
|
||||
void* )
|
||||
{
|
||||
|
||||
level_ = p.level;
|
||||
threads_ = p.threads;
|
||||
|
||||
#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
|
||||
if (threads_ == 0) {
|
||||
threads_ = lzma_cputhreads();
|
||||
}
|
||||
#endif
|
||||
|
||||
init_stream(compress);
|
||||
}
|
||||
|
||||
void lzma_base::init_stream(bool compress)
|
||||
{
|
||||
lzma_stream* s = static_cast<lzma_stream*>(stream_);
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
#ifndef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
|
||||
const lzma_mt opt = { 0, threads_, 0, 1000, level_, NULL, LZMA_CHECK_CRC32 };
|
||||
#endif
|
||||
|
||||
lzma_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
compress ?
|
||||
#ifdef BOOST_IOSTREAMS_LZMA_NO_MULTITHREADED
|
||||
lzma_easy_encoder(s, level_, LZMA_CHECK_CRC32) :
|
||||
#else
|
||||
lzma_stream_encoder_mt(s, &opt) :
|
||||
#endif
|
||||
lzma_stream_decoder(s, 100 * 1024 * 1024, LZMA_CONCATENATED)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
499
externals/boost/libs/iostreams/src/mapped_file.cpp
vendored
Normal file
499
externals/boost/libs/iostreams/src/mapped_file.cpp
vendored
Normal file
@@ -0,0 +1,499 @@
|
||||
// (C) Copyright Craig Henderson 2002 'boost/memmap.hpp' from sandbox
|
||||
// (C) Copyright Jonathan Turkanis 2004.
|
||||
// (C) Copyright Jonathan Graehl 2004.
|
||||
// (C) Copyright Jorge Lodos 2008.
|
||||
// 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_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <boost/iostreams/detail/config/rtl.hpp>
|
||||
#include <boost/iostreams/detail/config/windows_posix.hpp>
|
||||
#include <boost/iostreams/detail/file_handle.hpp>
|
||||
#include <boost/iostreams/detail/system_failure.hpp>
|
||||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/mman.h> // mmap, munmap.
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h> // struct stat.
|
||||
# include <unistd.h> // sysconf.
|
||||
#endif
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Class containing the platform-sepecific implementation
|
||||
// Invariant: The members params_, data_, size_, handle_ (and mapped_handle_
|
||||
// on Windows) either
|
||||
// - all have default values (or INVALID_HANDLE_VALUE for
|
||||
// Windows handles), or
|
||||
// - all have values reflecting a successful mapping.
|
||||
// In the first case, error_ may be true, reflecting a recent unsuccessful
|
||||
// open or close attempt; in the second case, error_ is always false.
|
||||
class mapped_file_impl {
|
||||
public:
|
||||
typedef mapped_file_source::size_type size_type;
|
||||
typedef mapped_file_source::param_type param_type;
|
||||
typedef mapped_file_source::mapmode mapmode;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
size_type, max_length = mapped_file_source::max_length);
|
||||
mapped_file_impl();
|
||||
~mapped_file_impl();
|
||||
void open(param_type p);
|
||||
bool is_open() const { return data_ != 0; }
|
||||
void close();
|
||||
bool error() const { return error_; }
|
||||
mapmode flags() const { return params_.flags; }
|
||||
std::size_t size() const { return static_cast<std::size_t>(size_); }
|
||||
char* data() const { return data_; }
|
||||
void resize(stream_offset new_size);
|
||||
static int alignment();
|
||||
private:
|
||||
void open_file(param_type p);
|
||||
void try_map_file(param_type p);
|
||||
void map_file(param_type& p);
|
||||
bool unmap_file();
|
||||
void clear(bool error);
|
||||
void cleanup_and_throw(const char* msg);
|
||||
param_type params_;
|
||||
char* data_;
|
||||
stream_offset size_;
|
||||
file_handle handle_;
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
file_handle mapped_handle_;
|
||||
#endif
|
||||
bool error_;
|
||||
};
|
||||
|
||||
mapped_file_impl::mapped_file_impl() { clear(false); }
|
||||
|
||||
mapped_file_impl::~mapped_file_impl()
|
||||
{ try { close(); } catch (...) { } }
|
||||
|
||||
void mapped_file_impl::open(param_type p)
|
||||
{
|
||||
if (is_open())
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("file already open"));
|
||||
p.normalize();
|
||||
open_file(p);
|
||||
map_file(p); // May modify p.hint
|
||||
params_ = p;
|
||||
}
|
||||
|
||||
void mapped_file_impl::close()
|
||||
{
|
||||
if (data_ == 0)
|
||||
return;
|
||||
bool error = false;
|
||||
error = !unmap_file() || error;
|
||||
error =
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
!::CloseHandle(handle_)
|
||||
#else
|
||||
::close(handle_) != 0
|
||||
#endif
|
||||
|| error;
|
||||
clear(error);
|
||||
if (error)
|
||||
throw_system_failure("failed closing mapped file");
|
||||
}
|
||||
|
||||
void mapped_file_impl::resize(stream_offset new_size)
|
||||
{
|
||||
if (!is_open())
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("file is closed"));
|
||||
if (flags() & mapped_file::priv)
|
||||
boost::throw_exception(
|
||||
BOOST_IOSTREAMS_FAILURE("can't resize private mapped file")
|
||||
);
|
||||
if (!(flags() & mapped_file::readwrite))
|
||||
boost::throw_exception(
|
||||
BOOST_IOSTREAMS_FAILURE("can't resize readonly mapped file")
|
||||
);
|
||||
if (params_.offset >= new_size)
|
||||
boost::throw_exception(
|
||||
BOOST_IOSTREAMS_FAILURE("can't resize below mapped offset")
|
||||
);
|
||||
if (!unmap_file())
|
||||
cleanup_and_throw("failed unmapping file");
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
stream_offset offset = ::SetFilePointer(handle_, 0, NULL, FILE_CURRENT);
|
||||
if (offset == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
cleanup_and_throw("failed querying file pointer");
|
||||
LONG sizehigh = (new_size >> (sizeof(LONG) * 8));
|
||||
LONG sizelow = (new_size & 0xffffffff);
|
||||
DWORD result = ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
|
||||
if ((result == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
|| !::SetEndOfFile(handle_))
|
||||
cleanup_and_throw("failed resizing mapped file");
|
||||
sizehigh = (offset >> (sizeof(LONG) * 8));
|
||||
sizelow = (offset & 0xffffffff);
|
||||
::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
|
||||
#else
|
||||
if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, new_size) == -1)
|
||||
cleanup_and_throw("failed resizing mapped file");
|
||||
#endif
|
||||
size_ = new_size;
|
||||
param_type p(params_);
|
||||
map_file(p); // May modify p.hint
|
||||
params_ = p;
|
||||
}
|
||||
|
||||
int mapped_file_impl::alignment()
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
SYSTEM_INFO info;
|
||||
::GetSystemInfo(&info);
|
||||
return static_cast<int>(info.dwAllocationGranularity);
|
||||
#else
|
||||
return static_cast<int>(sysconf(_SC_PAGESIZE));
|
||||
#endif
|
||||
}
|
||||
|
||||
void mapped_file_impl::open_file(param_type p)
|
||||
{
|
||||
bool readonly = p.flags != mapped_file::readwrite;
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
|
||||
// Open file
|
||||
DWORD dwDesiredAccess =
|
||||
readonly ?
|
||||
GENERIC_READ :
|
||||
(GENERIC_READ | GENERIC_WRITE);
|
||||
DWORD dwCreationDisposition = (p.new_file_size != 0 && !readonly) ?
|
||||
CREATE_ALWAYS :
|
||||
OPEN_EXISTING;
|
||||
DWORD dwFlagsandAttributes =
|
||||
readonly ?
|
||||
FILE_ATTRIBUTE_READONLY :
|
||||
FILE_ATTRIBUTE_TEMPORARY;
|
||||
handle_ = p.path.is_wide() ?
|
||||
::CreateFileW(
|
||||
p.path.c_wstr(),
|
||||
dwDesiredAccess,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
dwCreationDisposition,
|
||||
dwFlagsandAttributes,
|
||||
NULL ) :
|
||||
::CreateFileA(
|
||||
p.path.c_str(),
|
||||
dwDesiredAccess,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
dwCreationDisposition,
|
||||
dwFlagsandAttributes,
|
||||
NULL );
|
||||
if (handle_ == INVALID_HANDLE_VALUE)
|
||||
cleanup_and_throw("failed opening file");
|
||||
|
||||
// Set file size
|
||||
if (p.new_file_size != 0 && !readonly) {
|
||||
LONG sizehigh = (p.new_file_size >> (sizeof(LONG) * 8));
|
||||
LONG sizelow = (p.new_file_size & 0xffffffff);
|
||||
DWORD result = ::SetFilePointer(handle_, sizelow, &sizehigh, FILE_BEGIN);
|
||||
if ((result == INVALID_SET_FILE_POINTER && ::GetLastError() != NO_ERROR)
|
||||
|| !::SetEndOfFile(handle_))
|
||||
cleanup_and_throw("failed setting file size");
|
||||
}
|
||||
|
||||
// Determine file size. Dynamically locate GetFileSizeEx for compatibility
|
||||
// with old Platform SDK (thanks to Pavel Vozenilik).
|
||||
typedef BOOL (WINAPI *func)(HANDLE, PLARGE_INTEGER);
|
||||
HMODULE hmod = ::GetModuleHandleA("kernel32.dll");
|
||||
func get_size =
|
||||
reinterpret_cast<func>(::GetProcAddress(hmod, "GetFileSizeEx"));
|
||||
if (get_size) {
|
||||
LARGE_INTEGER info;
|
||||
if (get_size(handle_, &info)) {
|
||||
boost::intmax_t size =
|
||||
( (static_cast<boost::intmax_t>(info.HighPart) << 32) |
|
||||
info.LowPart );
|
||||
size_ =
|
||||
static_cast<std::size_t>(
|
||||
p.length != max_length ?
|
||||
std::min<boost::intmax_t>(p.length, size) :
|
||||
size
|
||||
);
|
||||
} else {
|
||||
cleanup_and_throw("failed querying file size");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
DWORD hi;
|
||||
DWORD low;
|
||||
if ( (low = ::GetFileSize(handle_, &hi))
|
||||
!=
|
||||
INVALID_FILE_SIZE )
|
||||
{
|
||||
boost::intmax_t size =
|
||||
(static_cast<boost::intmax_t>(hi) << 32) | low;
|
||||
size_ =
|
||||
static_cast<std::size_t>(
|
||||
p.length != max_length ?
|
||||
std::min<boost::intmax_t>(p.length, size) :
|
||||
size
|
||||
);
|
||||
} else {
|
||||
cleanup_and_throw("failed querying file size");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
|
||||
// Open file
|
||||
int flags = (readonly ? O_RDONLY : O_RDWR);
|
||||
if (p.new_file_size != 0 && !readonly)
|
||||
flags |= (O_CREAT | O_TRUNC);
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
flags |= O_LARGEFILE;
|
||||
#endif
|
||||
errno = 0;
|
||||
if (p.path.is_wide()) { errno = EINVAL; cleanup_and_throw("wide path not supported here"); } // happens on CYGWIN
|
||||
handle_ = ::open(p.path.c_str(), flags, S_IRWXU);
|
||||
if (errno != 0)
|
||||
cleanup_and_throw("failed opening file");
|
||||
|
||||
//--------------Set file size---------------------------------------------//
|
||||
|
||||
if (p.new_file_size != 0 && !readonly)
|
||||
if (BOOST_IOSTREAMS_FD_TRUNCATE(handle_, p.new_file_size) == -1)
|
||||
cleanup_and_throw("failed setting file size");
|
||||
|
||||
//--------------Determine file size---------------------------------------//
|
||||
|
||||
bool success = true;
|
||||
if (p.length != max_length) {
|
||||
size_ = p.length;
|
||||
} else {
|
||||
struct BOOST_IOSTREAMS_FD_STAT info;
|
||||
success = ::BOOST_IOSTREAMS_FD_FSTAT(handle_, &info) != -1;
|
||||
size_ = info.st_size;
|
||||
}
|
||||
if (!success)
|
||||
cleanup_and_throw("failed querying file size");
|
||||
#endif // #ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
}
|
||||
|
||||
void mapped_file_impl::try_map_file(param_type p)
|
||||
{
|
||||
bool priv = p.flags == mapped_file::priv;
|
||||
bool readonly = p.flags == mapped_file::readonly;
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
|
||||
// Create mapping
|
||||
DWORD protect = priv ?
|
||||
PAGE_WRITECOPY :
|
||||
readonly ?
|
||||
PAGE_READONLY :
|
||||
PAGE_READWRITE;
|
||||
mapped_handle_ =
|
||||
::CreateFileMappingA(
|
||||
handle_,
|
||||
NULL,
|
||||
protect,
|
||||
0,
|
||||
0,
|
||||
NULL );
|
||||
if (mapped_handle_ == NULL)
|
||||
cleanup_and_throw("failed create mapping");
|
||||
|
||||
// Access data
|
||||
DWORD access = priv ?
|
||||
FILE_MAP_COPY :
|
||||
readonly ?
|
||||
FILE_MAP_READ :
|
||||
FILE_MAP_WRITE;
|
||||
void* data =
|
||||
::MapViewOfFileEx(
|
||||
mapped_handle_,
|
||||
access,
|
||||
(DWORD) (p.offset >> 32),
|
||||
(DWORD) (p.offset & 0xffffffff),
|
||||
(SIZE_T) (numeric_cast<size_type>(size_) != max_length ? size_ : 0),
|
||||
(LPVOID) p.hint );
|
||||
if (!data)
|
||||
cleanup_and_throw("failed mapping view");
|
||||
#else
|
||||
void* data =
|
||||
::BOOST_IOSTREAMS_FD_MMAP(
|
||||
const_cast<char*>(p.hint),
|
||||
size_,
|
||||
readonly ? PROT_READ : (PROT_READ | PROT_WRITE),
|
||||
priv ? MAP_PRIVATE : MAP_SHARED,
|
||||
handle_,
|
||||
p.offset );
|
||||
if (data == MAP_FAILED)
|
||||
cleanup_and_throw("failed mapping file");
|
||||
#endif
|
||||
data_ = static_cast<char*>(data);
|
||||
}
|
||||
|
||||
void mapped_file_impl::map_file(param_type& p)
|
||||
{
|
||||
try {
|
||||
try_map_file(p);
|
||||
} catch (const std::exception&) {
|
||||
if (p.hint) {
|
||||
p.hint = 0;
|
||||
try_map_file(p);
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool mapped_file_impl::unmap_file()
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
bool error = false;
|
||||
error = !::UnmapViewOfFile(data_) || error;
|
||||
error = !::CloseHandle(mapped_handle_) || error;
|
||||
mapped_handle_ = NULL;
|
||||
return !error;
|
||||
#else
|
||||
return ::munmap(data_, size_) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mapped_file_impl::clear(bool error)
|
||||
{
|
||||
params_ = param_type();
|
||||
data_ = 0;
|
||||
size_ = 0;
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
handle_ = INVALID_HANDLE_VALUE;
|
||||
mapped_handle_ = NULL;
|
||||
#else
|
||||
handle_ = 0;
|
||||
#endif
|
||||
error_ = error;
|
||||
}
|
||||
|
||||
// Called when an error is encountered during the execution of open_file or
|
||||
// map_file
|
||||
void mapped_file_impl::cleanup_and_throw(const char* msg)
|
||||
{
|
||||
#ifdef BOOST_IOSTREAMS_WINDOWS
|
||||
DWORD error = GetLastError();
|
||||
if (mapped_handle_ != NULL)
|
||||
::CloseHandle(mapped_handle_);
|
||||
if (handle_ != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(handle_);
|
||||
SetLastError(error);
|
||||
#else
|
||||
int error = errno;
|
||||
if (handle_ != 0)
|
||||
::close(handle_);
|
||||
errno = error;
|
||||
#endif
|
||||
clear(true);
|
||||
boost::iostreams::detail::throw_system_failure(msg);
|
||||
}
|
||||
|
||||
//------------------Implementation of mapped_file_params_base-----------------//
|
||||
|
||||
void mapped_file_params_base::normalize()
|
||||
{
|
||||
if (mode && flags)
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE(
|
||||
"at most one of 'mode' and 'flags' may be specified"
|
||||
));
|
||||
if (flags) {
|
||||
switch (flags) {
|
||||
case mapped_file::readonly:
|
||||
case mapped_file::readwrite:
|
||||
case mapped_file::priv:
|
||||
break;
|
||||
default:
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid flags"));
|
||||
}
|
||||
} else {
|
||||
flags = (mode & BOOST_IOS::out) ?
|
||||
mapped_file::readwrite :
|
||||
mapped_file::readonly;
|
||||
mode = BOOST_IOS::openmode();
|
||||
}
|
||||
if (offset < 0)
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("invalid offset"));
|
||||
if (new_file_size < 0)
|
||||
boost::throw_exception(
|
||||
BOOST_IOSTREAMS_FAILURE("invalid new file size")
|
||||
);
|
||||
}
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//------------------Implementation of mapped_file_source----------------------//
|
||||
|
||||
mapped_file_source::mapped_file_source()
|
||||
: pimpl_(new impl_type)
|
||||
{ }
|
||||
|
||||
mapped_file_source::mapped_file_source(const mapped_file_source& other)
|
||||
: pimpl_(other.pimpl_)
|
||||
{ }
|
||||
|
||||
bool mapped_file_source::is_open() const
|
||||
{ return pimpl_->is_open(); }
|
||||
|
||||
void mapped_file_source::close() { pimpl_->close(); }
|
||||
|
||||
// safe_bool is explicitly qualified below to please msvc 7.1
|
||||
mapped_file_source::operator mapped_file_source::safe_bool() const
|
||||
{ return pimpl_->error() ? &safe_bool_helper::x : 0; }
|
||||
|
||||
bool mapped_file_source::operator!() const
|
||||
{ return pimpl_->error(); }
|
||||
|
||||
mapped_file_source::mapmode mapped_file_source::flags() const
|
||||
{ return pimpl_->flags(); }
|
||||
|
||||
mapped_file_source::size_type mapped_file_source::size() const
|
||||
{ return pimpl_->size(); }
|
||||
|
||||
const char* mapped_file_source::data() const { return pimpl_->data(); }
|
||||
|
||||
const char* mapped_file_source::begin() const { return data(); }
|
||||
|
||||
const char* mapped_file_source::end() const { return data() + size(); }
|
||||
int mapped_file_source::alignment()
|
||||
{ return detail::mapped_file_impl::alignment(); }
|
||||
|
||||
void mapped_file_source::init() { pimpl_.reset(new impl_type); }
|
||||
|
||||
void mapped_file_source::open_impl(const param_type& p)
|
||||
{ pimpl_->open(p); }
|
||||
|
||||
//------------------Implementation of mapped_file-----------------------------//
|
||||
|
||||
mapped_file::mapped_file(const mapped_file& other)
|
||||
: delegate_(other.delegate_)
|
||||
{ }
|
||||
|
||||
void mapped_file::resize(stream_offset new_size)
|
||||
{ delegate_.pimpl_->resize(new_size); }
|
||||
|
||||
//------------------Implementation of mapped_file_sink------------------------//
|
||||
|
||||
mapped_file_sink::mapped_file_sink(const mapped_file_sink& other)
|
||||
: mapped_file(static_cast<const mapped_file&>(other))
|
||||
{ }
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
188
externals/boost/libs/iostreams/src/zlib.cpp
vendored
Normal file
188
externals/boost/libs/iostreams/src/zlib.cpp
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
||||
// (C) Copyright 2003-2007 Jonathan Turkanis
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// To configure Boost to work with zlib, see the
|
||||
// installation instructions here:
|
||||
// http://boost.org/libs/iostreams/doc/index.html?path=7
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/filter/zlib.hpp>
|
||||
#include "zlib.h" // Jean-loup Gailly's and Mark Adler's "zlib.h" header.
|
||||
// To configure Boost to work with zlib, see the
|
||||
// installation instructions here:
|
||||
// http://boost.org/libs/iostreams/doc/index.html?path=7
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
namespace zlib {
|
||||
|
||||
// Compression levels
|
||||
|
||||
const int no_compression = Z_NO_COMPRESSION;
|
||||
const int best_speed = Z_BEST_SPEED;
|
||||
const int best_compression = Z_BEST_COMPRESSION;
|
||||
const int default_compression = Z_DEFAULT_COMPRESSION;
|
||||
|
||||
// Compression methods
|
||||
|
||||
const int deflated = Z_DEFLATED;
|
||||
|
||||
// Compression strategies
|
||||
|
||||
const int default_strategy = Z_DEFAULT_STRATEGY;
|
||||
const int filtered = Z_FILTERED;
|
||||
const int huffman_only = Z_HUFFMAN_ONLY;
|
||||
|
||||
// Status codes
|
||||
|
||||
const int okay = Z_OK;
|
||||
const int stream_end = Z_STREAM_END;
|
||||
const int stream_error = Z_STREAM_ERROR;
|
||||
const int version_error = Z_VERSION_ERROR;
|
||||
const int data_error = Z_DATA_ERROR;
|
||||
const int mem_error = Z_MEM_ERROR;
|
||||
const int buf_error = Z_BUF_ERROR;
|
||||
|
||||
// Flush codes
|
||||
|
||||
const int finish = Z_FINISH;
|
||||
const int no_flush = Z_NO_FLUSH;
|
||||
const int sync_flush = Z_SYNC_FLUSH;
|
||||
|
||||
// Code for current OS
|
||||
|
||||
//const int os_code = OS_CODE;
|
||||
|
||||
} // End namespace zlib.
|
||||
|
||||
//------------------Implementation of zlib_error------------------------------//
|
||||
|
||||
zlib_error::zlib_error(int error)
|
||||
: BOOST_IOSTREAMS_FAILURE("zlib error"), error_(error)
|
||||
{ }
|
||||
|
||||
void zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case Z_OK:
|
||||
case Z_STREAM_END:
|
||||
//case Z_BUF_ERROR:
|
||||
return;
|
||||
case Z_MEM_ERROR:
|
||||
boost::throw_exception(std::bad_alloc());
|
||||
default:
|
||||
boost::throw_exception(zlib_error(error));
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------Implementation of zlib_base-------------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
zlib_base::zlib_base()
|
||||
: stream_(new z_stream), calculate_crc_(false), crc_(0), crc_imp_(0),
|
||||
total_in_(0), total_out_(0)
|
||||
{ }
|
||||
|
||||
zlib_base::~zlib_base() { delete static_cast<z_stream*>(stream_); }
|
||||
|
||||
void zlib_base::before( const char*& src_begin, const char* src_end,
|
||||
char*& dest_begin, char* dest_end )
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(stream_);
|
||||
s->next_in = reinterpret_cast<zlib::byte*>(const_cast<char*>(src_begin));
|
||||
s->avail_in = static_cast<zlib::uint>(src_end - src_begin);
|
||||
s->next_out = reinterpret_cast<zlib::byte*>(dest_begin);
|
||||
s->avail_out= static_cast<zlib::uint>(dest_end - dest_begin);
|
||||
}
|
||||
|
||||
void zlib_base::after(const char*& src_begin, char*& dest_begin, bool compress)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(stream_);
|
||||
const char* next_in = reinterpret_cast<const char*>(s->next_in);
|
||||
char* next_out = reinterpret_cast<char*>(s->next_out);
|
||||
if (calculate_crc_) {
|
||||
const zlib::byte* buf = compress ?
|
||||
reinterpret_cast<const zlib::byte*>(src_begin) :
|
||||
reinterpret_cast<const zlib::byte*>(
|
||||
const_cast<const char*>(dest_begin)
|
||||
);
|
||||
zlib::uint length = compress ?
|
||||
static_cast<zlib::uint>(next_in - src_begin) :
|
||||
static_cast<zlib::uint>(next_out - dest_begin);
|
||||
crc_ = crc_imp_ = crc32(crc_imp_, buf, length);
|
||||
}
|
||||
total_in_ = s->total_in;
|
||||
total_out_ = s->total_out;
|
||||
src_begin = next_in;
|
||||
dest_begin = next_out;
|
||||
}
|
||||
|
||||
int zlib_base::xdeflate(int flush)
|
||||
{
|
||||
return ::deflate(static_cast<z_stream*>(stream_), flush);
|
||||
}
|
||||
|
||||
int zlib_base::xinflate(int flush)
|
||||
{
|
||||
return ::inflate(static_cast<z_stream*>(stream_), flush);
|
||||
}
|
||||
|
||||
void zlib_base::reset(bool compress, bool realloc)
|
||||
{
|
||||
z_stream* s = static_cast<z_stream*>(stream_);
|
||||
// Undiagnosed bug:
|
||||
// deflateReset(), etc., return Z_DATA_ERROR
|
||||
//zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
realloc ?
|
||||
(compress ? deflateReset(s) : inflateReset(s)) :
|
||||
(compress ? deflateEnd(s) : inflateEnd(s))
|
||||
;
|
||||
//);
|
||||
crc_imp_ = 0;
|
||||
}
|
||||
|
||||
void zlib_base::do_init
|
||||
( const zlib_params& p, bool compress,
|
||||
zlib::xalloc_func /* alloc */, zlib::xfree_func /* free*/,
|
||||
void* derived )
|
||||
{
|
||||
calculate_crc_ = p.calculate_crc;
|
||||
z_stream* s = static_cast<z_stream*>(stream_);
|
||||
|
||||
// Current interface for customizing memory management
|
||||
// is non-conforming and has been disabled:
|
||||
// s->zalloc = alloc;
|
||||
// s->zfree = free;
|
||||
s->zalloc = 0;
|
||||
s->zfree = 0;
|
||||
s->opaque = derived;
|
||||
int window_bits = p.noheader? -p.window_bits : p.window_bits;
|
||||
zlib_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
compress ?
|
||||
deflateInit2( s,
|
||||
p.level,
|
||||
p.method,
|
||||
window_bits,
|
||||
p.mem_level,
|
||||
p.strategy ) :
|
||||
inflateInit2(s, window_bits)
|
||||
);
|
||||
}
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
166
externals/boost/libs/iostreams/src/zstd.cpp
vendored
Normal file
166
externals/boost/libs/iostreams/src/zstd.cpp
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// (C) Copyright Reimar Döffinger 2018.
|
||||
// Based on zstd.cpp by:
|
||||
// (C) Copyright Milan Svoboda 2008.
|
||||
// (C) Copyright Jonathan Turkanis 2003.
|
||||
// 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.)
|
||||
|
||||
// See http://www.boost.org/libs/iostreams for documentation.
|
||||
|
||||
// Define BOOST_IOSTREAMS_SOURCE so that <boost/iostreams/detail/config.hpp>
|
||||
// knows that we are building the library (possibly exporting code), rather
|
||||
// than using it (possibly importing code).
|
||||
#define BOOST_IOSTREAMS_SOURCE
|
||||
|
||||
#include <zstd.h>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/iostreams/detail/config/dyn_link.hpp>
|
||||
#include <boost/iostreams/filter/zstd.hpp>
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
namespace zstd {
|
||||
// Compression levels
|
||||
|
||||
const uint32_t best_speed = 1;
|
||||
const uint32_t best_compression = 19;
|
||||
const uint32_t default_compression = 3;
|
||||
|
||||
// Status codes
|
||||
|
||||
const int okay = 0;
|
||||
const int stream_end = 1;
|
||||
|
||||
// Flush codes
|
||||
|
||||
const int finish = 0;
|
||||
const int flush = 1;
|
||||
const int run = 2;
|
||||
} // End namespace zstd.
|
||||
|
||||
//------------------Implementation of zstd_error------------------------------//
|
||||
|
||||
zstd_error::zstd_error(size_t error)
|
||||
: BOOST_IOSTREAMS_FAILURE(ZSTD_getErrorName(error)), error_(error)
|
||||
{ }
|
||||
|
||||
void zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(size_t error)
|
||||
{
|
||||
if (ZSTD_isError(error))
|
||||
boost::throw_exception(zstd_error(error));
|
||||
}
|
||||
|
||||
//------------------Implementation of zstd_base-------------------------------//
|
||||
|
||||
namespace detail {
|
||||
|
||||
zstd_base::zstd_base()
|
||||
: cstream_(ZSTD_createCStream()), dstream_(ZSTD_createDStream()), in_(new ZSTD_inBuffer), out_(new ZSTD_outBuffer), eof_(0)
|
||||
{ }
|
||||
|
||||
zstd_base::~zstd_base()
|
||||
{
|
||||
ZSTD_freeCStream(static_cast<ZSTD_CStream *>(cstream_));
|
||||
ZSTD_freeDStream(static_cast<ZSTD_DStream *>(dstream_));
|
||||
delete static_cast<ZSTD_inBuffer*>(in_);
|
||||
delete static_cast<ZSTD_outBuffer*>(out_);
|
||||
}
|
||||
|
||||
void zstd_base::before( const char*& src_begin, const char* src_end,
|
||||
char*& dest_begin, char* dest_end )
|
||||
{
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
in->src = src_begin;
|
||||
in->size = static_cast<size_t>(src_end - src_begin);
|
||||
in->pos = 0;
|
||||
out->dst = dest_begin;
|
||||
out->size = static_cast<size_t>(dest_end - dest_begin);
|
||||
out->pos = 0;
|
||||
}
|
||||
|
||||
void zstd_base::after(const char*& src_begin, char*& dest_begin, bool)
|
||||
{
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
src_begin = reinterpret_cast<const char*>(in->src) + in->pos;
|
||||
dest_begin = reinterpret_cast<char*>(out->dst) + out->pos;
|
||||
}
|
||||
|
||||
int zstd_base::deflate(int action)
|
||||
{
|
||||
ZSTD_CStream *s = static_cast<ZSTD_CStream *>(cstream_);
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
// Ignore spurious extra calls.
|
||||
// Note size > 0 will trigger an error in this case.
|
||||
if (eof_ && in->size == 0) return zstd::stream_end;
|
||||
size_t result = ZSTD_compressStream(s, out, in);
|
||||
zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
|
||||
if (action != zstd::run)
|
||||
{
|
||||
result = action == zstd::finish ? ZSTD_endStream(s, out) : ZSTD_flushStream(s, out);
|
||||
zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
|
||||
eof_ = action == zstd::finish && result == 0;
|
||||
return result == 0 ? zstd::stream_end : zstd::okay;
|
||||
}
|
||||
return zstd::okay;
|
||||
}
|
||||
|
||||
int zstd_base::inflate(int action)
|
||||
{
|
||||
ZSTD_DStream *s = static_cast<ZSTD_DStream *>(dstream_);
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
// need loop since iostream code cannot handle short reads
|
||||
do {
|
||||
size_t result = ZSTD_decompressStream(s, out, in);
|
||||
zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(result);
|
||||
} while (in->pos < in->size && out->pos < out->size);
|
||||
return action == zstd::finish && in->size == 0 && out->pos == 0 ? zstd::stream_end : zstd::okay;
|
||||
}
|
||||
|
||||
void zstd_base::reset(bool compress, bool realloc)
|
||||
{
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
if (realloc)
|
||||
{
|
||||
memset(in, 0, sizeof(*in));
|
||||
memset(out, 0, sizeof(*out));
|
||||
eof_ = 0;
|
||||
|
||||
zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
compress ?
|
||||
ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) :
|
||||
ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void zstd_base::do_init
|
||||
( const zstd_params& p, bool compress,
|
||||
zstd::alloc_func, zstd::free_func,
|
||||
void* )
|
||||
{
|
||||
ZSTD_inBuffer *in = static_cast<ZSTD_inBuffer *>(in_);
|
||||
ZSTD_outBuffer *out = static_cast<ZSTD_outBuffer *>(out_);
|
||||
|
||||
memset(in, 0, sizeof(*in));
|
||||
memset(out, 0, sizeof(*out));
|
||||
eof_ = 0;
|
||||
|
||||
level = p.level;
|
||||
zstd_error::check BOOST_PREVENT_MACRO_SUBSTITUTION(
|
||||
compress ?
|
||||
ZSTD_initCStream(static_cast<ZSTD_CStream *>(cstream_), level) :
|
||||
ZSTD_initDStream(static_cast<ZSTD_DStream *>(dstream_))
|
||||
);
|
||||
}
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
163
externals/boost/libs/locale/src/boost/locale/encoding/codepage.cpp
vendored
Normal file
163
externals/boost/libs/locale/src/boost/locale/encoding/codepage.cpp
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
# define BOOST_LOCALE_WITH_WCONV
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_WITH_ICONV
|
||||
# include "boost/locale/encoding/iconv_codepage.ipp"
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_WITH_ICU
|
||||
# include "boost/locale/encoding/uconv_codepage.ipp"
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_WITH_WCONV
|
||||
# include "boost/locale/encoding/wconv_codepage.ipp"
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace conv {
|
||||
namespace impl {
|
||||
|
||||
std::string convert_between(const char* begin,
|
||||
const char* end,
|
||||
const char* to_charset,
|
||||
const char* 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(const char* begin, const char* end, const char* 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(const CharType* begin, const CharType* end, const char* 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);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
using namespace impl;
|
||||
|
||||
std::string between(const char* begin,
|
||||
const char* end,
|
||||
const std::string& to_charset,
|
||||
const std::string& 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(const char* begin, const char* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_to<char>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string from_utf(const char* begin, const char* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_from<char>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::basic_string<wchar_t> to_utf(const char* begin, const char* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_to<wchar_t>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string from_utf(const wchar_t* begin, const wchar_t* end, const std::string& 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(const char* begin, const char* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_to<char16_t>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string from_utf(const char16_t* begin, const char16_t* end, const std::string& 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(const char* begin, const char* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_to<char32_t>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::string from_utf(const char32_t* begin, const char32_t* end, const std::string& charset, method_type how)
|
||||
{
|
||||
return convert_from<char32_t>(begin, end, charset.c_str(), how);
|
||||
}
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::locale::conv
|
||||
73
externals/boost/libs/locale/src/boost/locale/encoding/conv.hpp
vendored
Normal file
73
externals/boost/libs/locale/src/boost/locale/encoding/conv.hpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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>
|
||||
const char* utf_name()
|
||||
{
|
||||
switch(sizeof(CharType)) {
|
||||
case 1: return "UTF-8";
|
||||
case 2: {
|
||||
const int16_t endianMark = 1;
|
||||
const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1;
|
||||
return isLittleEndian ? "UTF-16LE" : "UTF-16BE";
|
||||
}
|
||||
case 4: {
|
||||
const int32_t endianMark = 1;
|
||||
const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1;
|
||||
return isLittleEndian ? "UTF-32LE" : "UTF-32BE";
|
||||
}
|
||||
}
|
||||
return "Unknown Character Encoding";
|
||||
}
|
||||
|
||||
class converter_between {
|
||||
public:
|
||||
typedef char char_type;
|
||||
typedef std::string string_type;
|
||||
|
||||
virtual bool open(const char* to_charset, const char* from_charset, method_type how) = 0;
|
||||
|
||||
virtual std::string convert(const char* begin, const char* end) = 0;
|
||||
|
||||
virtual ~converter_between() = default;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class converter_from_utf {
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
virtual bool open(const char* charset, method_type how) = 0;
|
||||
|
||||
virtual std::string convert(const CharType* begin, const CharType* end) = 0;
|
||||
|
||||
virtual ~converter_from_utf() = default;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class converter_to_utf {
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
virtual bool open(const char* charset, method_type how) = 0;
|
||||
|
||||
virtual string_type convert(const char* begin, const char* end) = 0;
|
||||
|
||||
virtual ~converter_to_utf() = default;
|
||||
};
|
||||
}}}} // namespace boost::locale::conv::impl
|
||||
|
||||
#endif
|
||||
175
externals/boost/libs/locale/src/boost/locale/encoding/iconv_codepage.ipp
vendored
Normal file
175
externals/boost/libs/locale/src/boost/locale/encoding/iconv_codepage.ipp
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/util/iconv.hpp"
|
||||
#include <cerrno>
|
||||
|
||||
namespace boost { namespace locale { namespace conv { namespace impl {
|
||||
|
||||
class iconverter_base {
|
||||
public:
|
||||
iconverter_base() : cvt_((iconv_t)(-1)) {}
|
||||
~iconverter_base() { close(); }
|
||||
|
||||
bool do_open(const char* to, const char* 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(const InChar* ubegin, const InChar* uend)
|
||||
{
|
||||
std::basic_string<OutChar> sresult;
|
||||
|
||||
sresult.reserve(uend - ubegin);
|
||||
|
||||
OutChar result[64];
|
||||
|
||||
char* out_start = reinterpret_cast<char*>(&result[0]);
|
||||
const char* begin = reinterpret_cast<const char*>(ubegin);
|
||||
const char* end = reinterpret_cast<const char*>(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);
|
||||
}
|
||||
}
|
||||
|
||||
size_t conv(const char** inbuf, size_t* inchar_left, char** outbuf, size_t* outchar_left)
|
||||
{
|
||||
return call_iconv(cvt_, inbuf, inchar_left, outbuf, outchar_left);
|
||||
}
|
||||
|
||||
iconv_t cvt_;
|
||||
method_type how_;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class iconv_from_utf : public converter_from_utf<CharType> {
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
return self_.do_open(charset, utf_name<CharType>(), how);
|
||||
}
|
||||
|
||||
std::string convert(const char_type* ubegin, const char_type* uend) override
|
||||
{
|
||||
return self_.template real_convert<char, char_type>(ubegin, uend);
|
||||
}
|
||||
|
||||
private:
|
||||
iconverter_base self_;
|
||||
};
|
||||
|
||||
class iconv_between : public converter_between {
|
||||
public:
|
||||
bool open(const char* to_charset, const char* from_charset, method_type how) override
|
||||
{
|
||||
return self_.do_open(to_charset, from_charset, how);
|
||||
}
|
||||
std::string convert(const char* begin, const char* end) override
|
||||
{
|
||||
return self_.real_convert<char, char>(begin, end);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
return self_.do_open(utf_name<CharType>(), charset, how);
|
||||
}
|
||||
|
||||
string_type convert(const char* begin, const char* end) override
|
||||
{
|
||||
return self_.template real_convert<char_type, char>(begin, end);
|
||||
}
|
||||
|
||||
private:
|
||||
iconverter_base self_;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::locale::conv::impl
|
||||
|
||||
#endif
|
||||
141
externals/boost/libs/locale/src/boost/locale/encoding/uconv_codepage.ipp
vendored
Normal file
141
externals/boost/libs/locale/src/boost/locale/encoding/uconv_codepage.ipp
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 <boost/locale/hold_ptr.hpp>
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include <unicode/ucnv.h>
|
||||
#include <unicode/ucnv_err.h>
|
||||
|
||||
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;
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
close();
|
||||
try {
|
||||
using impl_icu::cpcvt_type;
|
||||
cvt_from_.reset(new from_type(charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
cvt_to_.reset(new to_type("UTF-8", how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
} catch(const std::exception& /*e*/) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void close()
|
||||
{
|
||||
cvt_from_.reset();
|
||||
cvt_to_.reset();
|
||||
}
|
||||
|
||||
string_type convert(const char* begin, const char* end) override
|
||||
{
|
||||
try {
|
||||
return cvt_to_->std(cvt_from_->icu_checked(begin, end));
|
||||
} catch(const std::exception& /*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;
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
close();
|
||||
try {
|
||||
using impl_icu::cpcvt_type;
|
||||
cvt_from_.reset(new from_type("UTF-8", how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
cvt_to_.reset(new to_type(charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
} catch(const std::exception& /*e*/) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void close()
|
||||
{
|
||||
cvt_from_.reset();
|
||||
cvt_to_.reset();
|
||||
}
|
||||
|
||||
std::string convert(const CharType* begin, const CharType* end) override
|
||||
{
|
||||
try {
|
||||
return cvt_to_->std(cvt_from_->icu_checked(begin, end));
|
||||
} catch(const std::exception& /*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:
|
||||
bool open(const char* to_charset, const char* from_charset, method_type how) override
|
||||
{
|
||||
close();
|
||||
try {
|
||||
using impl_icu::cpcvt_type;
|
||||
cvt_from_.reset(new from_type(from_charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
cvt_to_.reset(new to_type(to_charset, how == skip ? cpcvt_type::skip : cpcvt_type::stop));
|
||||
} catch(const std::exception& /*e*/) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void close()
|
||||
{
|
||||
cvt_from_.reset();
|
||||
cvt_to_.reset();
|
||||
}
|
||||
|
||||
std::string convert(const char* begin, const char* end) override
|
||||
{
|
||||
try {
|
||||
return cvt_to_->std(cvt_from_->icu(begin, end));
|
||||
} catch(const std::exception& /*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_;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::locale::conv::impl
|
||||
|
||||
#endif
|
||||
432
externals/boost/libs/locale/src/boost/locale/encoding/wconv_codepage.ipp
vendored
Normal file
432
externals/boost/libs/locale/src/boost/locale/encoding/wconv_codepage.ipp
vendored
Normal file
@@ -0,0 +1,432 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_WCONV_CODEPAGE_HPP
|
||||
#define BOOST_LOCALE_IMPL_WCONV_CODEPAGE_HPP
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
namespace boost { namespace locale { namespace conv { namespace impl {
|
||||
|
||||
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, const char* begin, const char* end, std::vector<wchar_t>& buf)
|
||||
{
|
||||
buf.reserve(end - begin);
|
||||
DWORD flags = MB_ERR_INVALID_CHARS;
|
||||
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, flags, begin, len, wide_buf, 4);
|
||||
if(n == 0 && flags != 0 && GetLastError() == ERROR_INVALID_FLAGS) {
|
||||
flags = 0;
|
||||
n = MultiByteToWideChar(codepage, flags, 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, const char* begin, const char* end, bool do_skip, std::vector<wchar_t>& buf)
|
||||
{
|
||||
if(begin == end)
|
||||
return;
|
||||
const std::ptrdiff_t num_chars = end - begin;
|
||||
if(num_chars > std::numeric_limits<int>::max())
|
||||
throw conversion_error();
|
||||
DWORD flags = MB_ERR_INVALID_CHARS;
|
||||
int n = MultiByteToWideChar(codepage, flags, begin, static_cast<int>(num_chars), 0, 0);
|
||||
if(n == 0 && GetLastError() == ERROR_INVALID_FLAGS) {
|
||||
flags = 0;
|
||||
n = MultiByteToWideChar(codepage, flags, begin, static_cast<int>(num_chars), 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);
|
||||
if(MultiByteToWideChar(codepage, flags, begin, static_cast<int>(num_chars), &buf.front(), n) == 0)
|
||||
throw conversion_error();
|
||||
}
|
||||
|
||||
void wide_to_multibyte_non_zero(int codepage,
|
||||
const wchar_t* begin,
|
||||
const wchar_t* 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;
|
||||
|
||||
const std::ptrdiff_t num_chars = end - begin;
|
||||
if(num_chars > std::numeric_limits<int>::max())
|
||||
throw conversion_error();
|
||||
int n =
|
||||
WideCharToMultiByte(codepage, 0, begin, static_cast<int>(num_chars), 0, 0, subst_char_ptr, substitute_ptr);
|
||||
buf.resize(n);
|
||||
|
||||
if(WideCharToMultiByte(codepage,
|
||||
0,
|
||||
begin,
|
||||
static_cast<int>(num_chars),
|
||||
&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, const wchar_t* begin, const wchar_t* end, bool do_skip, std::vector<char>& buf)
|
||||
{
|
||||
if(begin == end)
|
||||
return;
|
||||
buf.reserve(end - begin);
|
||||
const wchar_t* e = std::find(begin, end, L'\0');
|
||||
const wchar_t* 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;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
bool validate_utf16(const CharType* str, size_t len)
|
||||
{
|
||||
const CharType* begin = str;
|
||||
const CharType* end = str + len;
|
||||
while(begin != end) {
|
||||
utf::code_point c = utf::utf_traits<CharType, 2>::template decode<const CharType*>(begin, end);
|
||||
if(c == utf::illegal || c == utf::incomplete)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename CharType, typename OutChar>
|
||||
void clean_invalid_utf16(const CharType* str, size_t len, std::vector<OutChar>& out)
|
||||
{
|
||||
out.reserve(len);
|
||||
for(size_t 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(const char* to_charset, const char* from_charset, method_type how) override
|
||||
{
|
||||
how_ = how;
|
||||
to_code_page_ = util::encoding_to_windows_codepage(to_charset);
|
||||
from_code_page_ = util::encoding_to_windows_codepage(from_charset);
|
||||
if(to_code_page_ == -1 || from_code_page_ == -1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
std::string convert(const char* begin, const char* end) override
|
||||
{
|
||||
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
|
||||
const wchar_t* wbegin = 0;
|
||||
const wchar_t* 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:
|
||||
bool open(const char* cs, method_type how) override { return cvt.open("UTF-8", cs, how); }
|
||||
std::string convert(const char* begin, const char* end) override { return cvt.convert(begin, end); }
|
||||
|
||||
private:
|
||||
wconv_between cvt;
|
||||
};
|
||||
|
||||
template<>
|
||||
class wconv_from_utf<char, 1> : public converter_from_utf<char> {
|
||||
public:
|
||||
bool open(const char* cs, method_type how) override { return cvt.open(cs, "UTF-8", how); }
|
||||
std::string convert(const char* begin, const char* end) override { return cvt.convert(begin, end); }
|
||||
|
||||
private:
|
||||
wconv_between cvt;
|
||||
};
|
||||
|
||||
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) {}
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
how_ = how;
|
||||
code_page_ = util::encoding_to_windows_codepage(charset);
|
||||
return code_page_ != -1;
|
||||
}
|
||||
|
||||
string_type convert(const char* begin, const char* end) override
|
||||
{
|
||||
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) {}
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
how_ = how;
|
||||
code_page_ = util::encoding_to_windows_codepage(charset);
|
||||
return code_page_ != -1;
|
||||
}
|
||||
|
||||
std::string convert(const CharType* begin, const CharType* end) override
|
||||
{
|
||||
if(code_page_ == 65001) {
|
||||
return utf_to_utf<char>(begin, end, how_);
|
||||
}
|
||||
const wchar_t* wbegin = 0;
|
||||
const wchar_t* wend = 0;
|
||||
std::vector<wchar_t> buffer; // if needed
|
||||
if(begin == end)
|
||||
return std::string();
|
||||
if(validate_utf16(begin, end - begin)) {
|
||||
wbegin = reinterpret_cast<const wchar_t*>(begin);
|
||||
wend = reinterpret_cast<const wchar_t*>(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) {}
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
how_ = how;
|
||||
code_page_ = util::encoding_to_windows_codepage(charset);
|
||||
return code_page_ != -1;
|
||||
}
|
||||
|
||||
string_type convert(const char* begin, const char* end) override
|
||||
{
|
||||
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) {}
|
||||
|
||||
bool open(const char* charset, method_type how) override
|
||||
{
|
||||
how_ = how;
|
||||
code_page_ = util::encoding_to_windows_codepage(charset);
|
||||
return code_page_ != -1;
|
||||
}
|
||||
|
||||
std::string convert(const CharType* begin, const CharType* end) override
|
||||
{
|
||||
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_;
|
||||
};
|
||||
|
||||
}}}} // namespace boost::locale::conv::impl
|
||||
|
||||
// boostinspect:nominmax
|
||||
#endif
|
||||
24
externals/boost/libs/locale/src/boost/locale/icu/all_generator.hpp
vendored
Normal file
24
externals/boost/libs/locale/src/boost/locale/icu/all_generator.hpp
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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(const std::locale&, const cdata&, char_facet_t);
|
||||
std::locale create_collate(const std::locale&, const cdata&, char_facet_t);
|
||||
std::locale create_formatting(const std::locale&, const cdata&, char_facet_t);
|
||||
std::locale create_parsing(const std::locale&, const cdata&, char_facet_t);
|
||||
std::locale create_codecvt(const std::locale&, const std::string& encoding, char_facet_t);
|
||||
std::locale create_boundary(const std::locale&, const cdata&, char_facet_t);
|
||||
std::locale create_calendar(const std::locale&, const cdata&);
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
213
externals/boost/libs/locale/src/boost/locale/icu/boundary.cpp
vendored
Normal file
213
externals/boost/libs/locale/src/boost/locale/icu/boundary.cpp
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/boundary.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include "boost/locale//util/encoding.hpp"
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 306
|
||||
# include <unicode/utext.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <unicode/brkiter.h>
|
||||
#include <unicode/rbbi.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4244) // 'argument' : conversion from 'int'
|
||||
# pragma warning(disable : 4267) // 'argument' : conversion from 'size_t'
|
||||
#endif
|
||||
|
||||
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 = icu_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;
|
||||
case character: BOOST_UNREACHABLE_RETURN(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
indx.back().rule |= character_any; // Baisc mark... for character
|
||||
}
|
||||
}
|
||||
return indx;
|
||||
}
|
||||
|
||||
std::unique_ptr<icu::BreakIterator> get_iterator(boundary_type t, const icu::Locale& loc)
|
||||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
std::unique_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;
|
||||
}
|
||||
check_and_throw_icu_error(err);
|
||||
if(!bi)
|
||||
throw std::runtime_error("Failed to create break iterator");
|
||||
return bi;
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
index_type do_map(boundary_type t,
|
||||
const CharType* begin,
|
||||
const CharType* end,
|
||||
const icu::Locale& loc,
|
||||
const std::string& encoding)
|
||||
{
|
||||
index_type indx;
|
||||
std::unique_ptr<icu::BreakIterator> bi = get_iterator(t, loc);
|
||||
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 306
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
if(sizeof(CharType) == 2 || (sizeof(CharType) == 1 && util::normalize_encoding(encoding) == "utf8")) {
|
||||
UText* ut = 0;
|
||||
try {
|
||||
if(sizeof(CharType) == 1)
|
||||
ut = utext_openUTF8(0, reinterpret_cast<const char*>(begin), end - begin, &err);
|
||||
else // sizeof(CharType)==2
|
||||
ut = utext_openUChars(0, reinterpret_cast<const UChar*>(begin), end - begin, &err);
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
|
||||
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(const cdata& data) : locale_(data.locale), encoding_(data.encoding) {}
|
||||
index_type map(boundary_type t, const CharType* begin, const CharType* end) const
|
||||
{
|
||||
return do_map<CharType>(t, begin, end, locale_, encoding_);
|
||||
}
|
||||
|
||||
private:
|
||||
icu::Locale locale_;
|
||||
std::string encoding_;
|
||||
};
|
||||
|
||||
}} // namespace boundary::impl_icu
|
||||
|
||||
namespace impl_icu {
|
||||
std::locale create_boundary(const std::locale& in, const cdata& cd, char_facet_t type)
|
||||
{
|
||||
using namespace boost::locale::boundary::impl_icu;
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new boundary_indexing_impl<char>(cd));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new boundary_indexing_impl<wchar_t>(cd));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new boundary_indexing_impl<char16_t>(cd));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new boundary_indexing_impl<char32_t>(cd));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
} // namespace impl_icu
|
||||
|
||||
}} // namespace boost::locale
|
||||
22
externals/boost/libs/locale/src/boost/locale/icu/cdata.hpp
vendored
Normal file
22
externals/boost/libs/locale/src/boost/locale/icu/cdata.hpp
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_ICU_CDATA_HPP
|
||||
#define BOOST_LOCALE_ICU_CDATA_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include <string>
|
||||
#include <unicode/locid.h>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
struct cdata {
|
||||
icu::Locale locale;
|
||||
std::string encoding;
|
||||
bool utf8;
|
||||
};
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
129
externals/boost/libs/locale/src/boost/locale/icu/codecvt.cpp
vendored
Normal file
129
externals/boost/libs/locale/src/boost/locale/icu/codecvt.cpp
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/icu/codecvt.hpp"
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/encoding_errors.hpp>
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include <unicode/ucnv.h>
|
||||
#include <unicode/ucnv_err.h>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4244) // loose data
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
class uconv_converter : public util::base_converter {
|
||||
public:
|
||||
uconv_converter(const std::string& 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_);
|
||||
}
|
||||
|
||||
~uconv_converter() { ucnv_close(cvt_); }
|
||||
|
||||
bool is_thread_safe() const override { return false; }
|
||||
|
||||
uconv_converter* clone() const override { return new uconv_converter(encoding_); }
|
||||
|
||||
uint32_t to_unicode(const char*& begin, const char* end) override
|
||||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
const char* 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, const char* end) override
|
||||
{
|
||||
UChar code_point[2] = {0};
|
||||
int len;
|
||||
if(u <= 0xFFFF) {
|
||||
if(0xD800 <= u && u <= 0xDFFF) // No surrogates
|
||||
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;
|
||||
}
|
||||
|
||||
int max_len() const override { return max_len_; }
|
||||
|
||||
private:
|
||||
std::string encoding_;
|
||||
UConverter* cvt_;
|
||||
int max_len_;
|
||||
};
|
||||
|
||||
std::unique_ptr<util::base_converter> create_uconv_converter(const std::string& encoding)
|
||||
{
|
||||
try {
|
||||
return std::unique_ptr<util::base_converter>(new uconv_converter(encoding));
|
||||
} catch(const std::exception& /*e*/) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::locale create_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type)
|
||||
{
|
||||
if(util::normalize_encoding(encoding) == "utf8")
|
||||
return util::create_utf8_codecvt(in, type);
|
||||
|
||||
try {
|
||||
return util::create_simple_codecvt(in, encoding, type);
|
||||
} catch(const boost::locale::conv::invalid_charset_error&) {
|
||||
std::unique_ptr<util::base_converter> cvt;
|
||||
try {
|
||||
cvt = create_uconv_converter(encoding);
|
||||
} catch(const std::exception& /*e*/) {
|
||||
cvt.reset(new util::base_converter());
|
||||
}
|
||||
return util::create_codecvt(in, std::move(cvt), type);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
20
externals/boost/libs/locale/src/boost/locale/icu/codecvt.hpp
vendored
Normal file
20
externals/boost/libs/locale/src/boost/locale/icu/codecvt.hpp
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_ICU_CODECVT_HPP
|
||||
#define BOOST_LOCALE_IMPL_ICU_CODECVT_HPP
|
||||
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
BOOST_LOCALE_DECL
|
||||
std::unique_ptr<util::base_converter> create_uconv_converter(const std::string& encoding);
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
193
externals/boost/libs/locale/src/boost/locale/icu/collator.cpp
vendored
Normal file
193
externals/boost/libs/locale/src/boost/locale/icu/collator.cpp
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/collator.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include "boost/locale/shared/mo_hash.hpp"
|
||||
#include <boost/thread.hpp>
|
||||
#include <limits>
|
||||
#include <unicode/coll.h>
|
||||
#include <vector>
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 402
|
||||
# define BOOST_LOCALE_WITH_STRINGPIECE 1
|
||||
# include <unicode/stringpiece.h>
|
||||
#else
|
||||
# define BOOST_LOCALE_WITH_STRINGPIECE 0
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4244) // 'argument' : conversion from 'int'
|
||||
# pragma warning(disable : 4267) // 'argument' : conversion from 'size_t'
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
template<typename CharType>
|
||||
class collate_impl : public collator<CharType> {
|
||||
public:
|
||||
int level_to_int(collate_level level) const
|
||||
{
|
||||
const auto res = static_cast<int>(level);
|
||||
if(res < 0)
|
||||
return 0;
|
||||
if(res >= level_count)
|
||||
return level_count - 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
#if BOOST_LOCALE_WITH_STRINGPIECE
|
||||
int do_utf8_compare(collate_level level,
|
||||
const char* b1,
|
||||
const char* e1,
|
||||
const char* b2,
|
||||
const char* 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(collate_level level,
|
||||
const CharType* b1,
|
||||
const CharType* e1,
|
||||
const CharType* b2,
|
||||
const CharType* 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(collate_level level,
|
||||
const CharType* b1,
|
||||
const CharType* e1,
|
||||
const CharType* b2,
|
||||
const CharType* e2,
|
||||
UErrorCode& status) const
|
||||
{
|
||||
return do_ustring_compare(level, b1, e1, b2, e2, status);
|
||||
}
|
||||
|
||||
int do_compare(collate_level level,
|
||||
const CharType* b1,
|
||||
const CharType* e1,
|
||||
const CharType* b2,
|
||||
const CharType* e2) const override
|
||||
{
|
||||
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(collate_level level, const CharType* b, const CharType* e) const
|
||||
{
|
||||
icu::UnicodeString str = cvt_.icu(b, e);
|
||||
std::vector<uint8_t> tmp;
|
||||
tmp.resize(str.length() + 1u);
|
||||
icu::Collator* collate = get_collator(level);
|
||||
const 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(collate_level level, const CharType* b, const CharType* e) const override
|
||||
{
|
||||
std::vector<uint8_t> tmp = do_basic_transform(level, b, e);
|
||||
return std::basic_string<CharType>(tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
long do_hash(collate_level level, const CharType* b, const CharType* e) const override
|
||||
{
|
||||
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(const cdata& d) : cvt_(d.encoding), locale_(d.locale), is_utf8_(d.utf8) {}
|
||||
|
||||
icu::Collator* get_collator(collate_level level) const
|
||||
{
|
||||
const int lvl_idx = level_to_int(level);
|
||||
constexpr 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_[lvl_idx].get();
|
||||
if(col)
|
||||
return col;
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
collates_[lvl_idx].reset(icu::Collator::createInstance(locale_, status));
|
||||
|
||||
if(U_FAILURE(status))
|
||||
throw std::runtime_error(std::string("Creation of collate failed:") + u_errorName(status));
|
||||
|
||||
collates_[lvl_idx]->setStrength(levels[lvl_idx]);
|
||||
return collates_[lvl_idx].get();
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int level_count = static_cast<int>(collate_level::identical) + 1;
|
||||
icu_std_converter<CharType> cvt_;
|
||||
icu::Locale locale_;
|
||||
mutable boost::thread_specific_ptr<icu::Collator> collates_[level_count];
|
||||
bool is_utf8_;
|
||||
};
|
||||
|
||||
#if BOOST_LOCALE_WITH_STRINGPIECE
|
||||
template<>
|
||||
int collate_impl<char>::do_real_compare(collate_level level,
|
||||
const char* b1,
|
||||
const char* e1,
|
||||
const char* b2,
|
||||
const char* 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(const std::locale& in, const cdata& cd, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new collate_impl<char>(cd));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new collate_impl<wchar_t>(cd));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new collate_impl<char16_t>(cd));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new collate_impl<char32_t>(cd));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
186
externals/boost/libs/locale/src/boost/locale/icu/conversion.cpp
vendored
Normal file
186
externals/boost/libs/locale/src/boost/locale/icu/conversion.cpp
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/conversion.hpp>
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include <limits>
|
||||
#include <unicode/locid.h>
|
||||
#include <unicode/normlzr.h>
|
||||
#include <unicode/ustring.h>
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 308
|
||||
# include <unicode/ucasemap.h>
|
||||
# define BOOST_LOCALE_WITH_CASEMAP
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<typename CharType>
|
||||
class converter_impl : public converter<CharType> {
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
converter_impl(const cdata& d) : locale_(d.locale), encoding_(d.encoding) {}
|
||||
|
||||
string_type convert(converter_base::conversion_type how,
|
||||
const char_type* begin,
|
||||
const char_type* end,
|
||||
int flags = 0) const override
|
||||
{
|
||||
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;
|
||||
}
|
||||
return cvt.std(str);
|
||||
}
|
||||
|
||||
private:
|
||||
icu::Locale locale_;
|
||||
std::string encoding_;
|
||||
}; // converter_impl
|
||||
|
||||
#ifdef BOOST_LOCALE_WITH_CASEMAP
|
||||
template<typename T>
|
||||
struct get_casemap_size_type;
|
||||
|
||||
template<typename TRes, typename TCaseMap, typename TSize>
|
||||
struct get_casemap_size_type<TRes (*)(TCaseMap*, char*, TSize, const char*, TSize, UErrorCode*)> {
|
||||
using type = TSize;
|
||||
};
|
||||
|
||||
class raii_casemap {
|
||||
public:
|
||||
raii_casemap(const raii_casemap&) = delete;
|
||||
void operator=(const raii_casemap&) = delete;
|
||||
|
||||
raii_casemap(const std::string& 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, const char* begin, const char* end) const
|
||||
{
|
||||
using size_type = typename get_casemap_size_type<Conv>::type;
|
||||
if((end - begin) >= std::numeric_limits<std::ptrdiff_t>::max() / 11)
|
||||
throw std::range_error("String to long to be converted by ICU");
|
||||
const auto max_converted_size = (end - begin) * 11 / 10 + 1;
|
||||
if(max_converted_size >= std::numeric_limits<size_type>::max())
|
||||
throw std::range_error("String to long to be converted by ICU");
|
||||
std::vector<char> buf(max_converted_size);
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
auto size = func(map_,
|
||||
&buf.front(),
|
||||
static_cast<size_type>(buf.size()),
|
||||
begin,
|
||||
static_cast<size_type>(end - begin),
|
||||
&err);
|
||||
if(err == U_BUFFER_OVERFLOW_ERROR) {
|
||||
err = U_ZERO_ERROR;
|
||||
buf.resize(size + 1);
|
||||
size = func(map_,
|
||||
&buf.front(),
|
||||
static_cast<size_type>(buf.size()),
|
||||
begin,
|
||||
static_cast<size_type>(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(const cdata& d) : locale_id_(d.locale.getName()), map_(locale_id_) {}
|
||||
|
||||
std::string
|
||||
convert(converter_base::conversion_type how, const char* begin, const char* end, int flags = 0) const override
|
||||
{
|
||||
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);
|
||||
case 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);
|
||||
}
|
||||
}
|
||||
return std::string(begin, end - begin);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string locale_id_;
|
||||
raii_casemap map_;
|
||||
}; // converter_impl
|
||||
|
||||
#endif // BOOST_LOCALE_WITH_CASEMAP
|
||||
|
||||
std::locale create_convert(const std::locale& in, const cdata& cd, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f:
|
||||
#ifdef BOOST_LOCALE_WITH_CASEMAP
|
||||
if(cd.utf8)
|
||||
return std::locale(in, new utf8_converter_impl(cd));
|
||||
#endif
|
||||
return std::locale(in, new converter_impl<char>(cd));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new converter_impl<wchar_t>(cd));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new converter_impl<char16_t>(cd));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new converter_impl<char32_t>(cd));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
234
externals/boost/libs/locale/src/boost/locale/icu/date_time.cpp
vendored
Normal file
234
externals/boost/libs/locale/src/boost/locale/icu/date_time.cpp
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/date_time.hpp>
|
||||
#include <boost/locale/date_time_facet.hpp>
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/time_zone.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include <boost/thread.hpp>
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
#include <unicode/calendar.h>
|
||||
#include <unicode/gregocal.h>
|
||||
#include <unicode/utypes.h>
|
||||
|
||||
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;
|
||||
case first_day_of_week:
|
||||
case invalid: break;
|
||||
}
|
||||
throw std::invalid_argument("Invalid date_time period type");
|
||||
}
|
||||
|
||||
class calendar_impl : public abstract_calendar {
|
||||
public:
|
||||
calendar_impl(const cdata& dat)
|
||||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
calendar_.reset(icu::Calendar::createInstance(dat.locale, err));
|
||||
check_and_throw_dt(err);
|
||||
#if BOOST_LOCALE_ICU_VERSION < 402
|
||||
// workaround old/invalid data, it should be 4 in general
|
||||
calendar_->setMinimalDaysInFirstWeek(4);
|
||||
#endif
|
||||
encoding_ = dat.encoding;
|
||||
}
|
||||
calendar_impl(const calendar_impl& other)
|
||||
{
|
||||
calendar_.reset(other.calendar_->clone());
|
||||
encoding_ = other.encoding_;
|
||||
}
|
||||
|
||||
calendar_impl* clone() const override
|
||||
{
|
||||
return new calendar_impl(*this);
|
||||
}
|
||||
|
||||
void set_value(period::marks::period_mark p, int value) override
|
||||
{
|
||||
calendar_->set(to_icu(p), int32_t(value));
|
||||
}
|
||||
|
||||
int get_value(period::marks::period_mark p, value_type type) const override
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void set_time(const posix_time& p) override
|
||||
{
|
||||
double utime = p.seconds * 1000.0 + p.nanoseconds / 1000000.0;
|
||||
UErrorCode code = U_ZERO_ERROR;
|
||||
calendar_->setTime(utime, code);
|
||||
check_and_throw_dt(code);
|
||||
}
|
||||
void normalize() override
|
||||
{
|
||||
// Can't call complete() explicitly (protected)
|
||||
// calling get which calls complete
|
||||
UErrorCode code = U_ZERO_ERROR;
|
||||
calendar_->get(UCAL_YEAR, code);
|
||||
check_and_throw_dt(code);
|
||||
}
|
||||
posix_time get_time() const override
|
||||
{
|
||||
const double timeMs = get_time_ms();
|
||||
posix_time res;
|
||||
res.seconds = static_cast<int64_t>(std::floor(timeMs / 1e3));
|
||||
const double remainTimeMs = std::fmod(timeMs, 1e3); // = timeMs - seconds * 1000
|
||||
constexpr uint32_t ns_in_s = static_cast<uint32_t>(1000) * 1000 * 1000;
|
||||
res.nanoseconds = std::min(static_cast<uint32_t>(remainTimeMs * 1e6), ns_in_s - 1u);
|
||||
return res;
|
||||
}
|
||||
double get_time_ms() const override
|
||||
{
|
||||
UErrorCode code = U_ZERO_ERROR;
|
||||
double result;
|
||||
{
|
||||
guard l(lock_);
|
||||
result = calendar_->getTime(code);
|
||||
}
|
||||
check_and_throw_dt(code);
|
||||
return result;
|
||||
}
|
||||
void set_option(calendar_option_type opt, int /*v*/) override
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
int get_option(calendar_option_type opt) const override
|
||||
{
|
||||
switch(opt) {
|
||||
case is_gregorian: return icu_cast<const icu::GregorianCalendar>(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;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void adjust_value(period::marks::period_mark p, update_type u, int difference) override
|
||||
{
|
||||
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);
|
||||
}
|
||||
int difference(const abstract_calendar& other, period::marks::period_mark m) const override
|
||||
{
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
const double other_time_ms = other.get_time_ms();
|
||||
|
||||
// fieldDifference has side effect of moving calendar (WTF?)
|
||||
// So we clone it for performing this operation
|
||||
hold_ptr<icu::Calendar> self(calendar_->clone());
|
||||
|
||||
int diff = self->fieldDifference(other_time_ms, to_icu(m), err);
|
||||
|
||||
check_and_throw_dt(err);
|
||||
return diff;
|
||||
}
|
||||
void set_timezone(const std::string& tz) override
|
||||
{
|
||||
calendar_->adoptTimeZone(get_time_zone(tz));
|
||||
}
|
||||
std::string get_timezone() const override
|
||||
{
|
||||
icu::UnicodeString tz;
|
||||
calendar_->getTimeZone().getID(tz);
|
||||
icu_std_converter<char> cvt(encoding_);
|
||||
return cvt.std(tz);
|
||||
}
|
||||
bool same(const abstract_calendar* other) const override
|
||||
{
|
||||
const calendar_impl* oc = dynamic_cast<const calendar_impl*>(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(const cdata& d, size_t refs = 0) : calendar_facet(refs), data_(d) {}
|
||||
abstract_calendar* create_calendar() const override { return new calendar_impl(data_); }
|
||||
|
||||
private:
|
||||
cdata data_;
|
||||
};
|
||||
|
||||
std::locale create_calendar(const std::locale& in, const cdata& d)
|
||||
{
|
||||
return std::locale(in, new icu_calendar_facet(d));
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
459
externals/boost/libs/locale/src/boost/locale/icu/formatter.cpp
vendored
Normal file
459
externals/boost/libs/locale/src/boost/locale/icu/formatter.cpp
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/icu/formatter.hpp"
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/locale/info.hpp>
|
||||
#include "boost/locale/icu/formatters_cache.hpp"
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include "boost/locale/icu/time_zone.hpp"
|
||||
#include "boost/locale/icu/uconv.hpp"
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <unicode/datefmt.h>
|
||||
#include <unicode/decimfmt.h>
|
||||
#include <unicode/numfmt.h>
|
||||
#include <unicode/rbnf.h>
|
||||
#include <unicode/smpdtfmt.h>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4244) // lose data
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
namespace {
|
||||
// Set the min/max fraction digits for the NumberFormat
|
||||
void set_fraction_digits(icu::NumberFormat& nf, const std::ios_base::fmtflags how, std::streamsize precision)
|
||||
{
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 5601
|
||||
// Since ICU 56.1 the integer part counts to the fraction part
|
||||
if(how == std::ios_base::scientific)
|
||||
precision += nf.getMaximumIntegerDigits();
|
||||
#endif
|
||||
nf.setMaximumFractionDigits(precision);
|
||||
if(how == std::ios_base::scientific || how == std::ios_base::fixed) {
|
||||
nf.setMinimumFractionDigits(precision);
|
||||
} else {
|
||||
nf.setMinimumFractionDigits(0);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<typename CharType>
|
||||
class number_format : public formatter<CharType> {
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef std::basic_string<CharType> string_type;
|
||||
|
||||
number_format(icu::NumberFormat& fmt, std::string codepage) : cvt_(codepage), icu_fmt_(fmt) {}
|
||||
|
||||
string_type format(double value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
string_type format(int64_t value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
string_type format(int32_t value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
size_t parse(const string_type& str, double& value) const override { return do_parse(str, value); }
|
||||
size_t parse(const string_type& str, int64_t& value) const override { return do_parse(str, value); }
|
||||
size_t parse(const string_type& str, int32_t& value) const override { return do_parse(str, value); }
|
||||
|
||||
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>
|
||||
string_type do_format(ValueType value, size_t& code_points) const
|
||||
{
|
||||
icu::UnicodeString tmp;
|
||||
icu_fmt_.format(value, tmp);
|
||||
code_points = tmp.countChar32();
|
||||
return cvt_.std(tmp);
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
size_t do_parse(const string_type& 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;
|
||||
|
||||
string_type format(double value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
string_type format(int64_t value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
|
||||
string_type format(int32_t value, size_t& code_points) const override { return do_format(value, code_points); }
|
||||
|
||||
size_t parse(const string_type& str, double& value) const override { return do_parse(str, value); }
|
||||
size_t parse(const string_type& str, int64_t& value) const override { return do_parse(str, value); }
|
||||
size_t parse(const string_type& str, int32_t& value) const override { return do_parse(str, value); }
|
||||
|
||||
date_format(icu::DateFormat& fmt, const std::string& encoding) : cvt_(encoding), icu_fmt_(fmt) {}
|
||||
date_format(std::unique_ptr<icu::DateFormat> fmt, const std::string& encoding) :
|
||||
cvt_(encoding), icu_fmt_holder_(std::move(fmt)), icu_fmt_(*icu_fmt_holder_)
|
||||
{}
|
||||
|
||||
private:
|
||||
template<typename ValueType>
|
||||
size_t do_parse(const string_type& 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;
|
||||
// Explicit cast to double to avoid warnings changing value (e.g. for INT64_MAX -> double)
|
||||
if(date > static_cast<double>(limits_type::max()) || date < static_cast<double>(limits_type::min()))
|
||||
return 0;
|
||||
size_t cut = cvt_.cut(tmp, str.data(), str.data() + str.size(), pp.getIndex());
|
||||
if(cut == 0)
|
||||
return 0;
|
||||
// Handle the edge case where the double is slightly out of range and hence the cast would be UB
|
||||
// by rounding to the min/max values
|
||||
if(date == static_cast<double>(limits_type::max()))
|
||||
value = limits_type::max();
|
||||
else if(date == static_cast<double>(limits_type::min()))
|
||||
value = limits_type::min();
|
||||
else
|
||||
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 milliseconds
|
||||
icu::UnicodeString tmp;
|
||||
icu_fmt_.format(date, tmp);
|
||||
codepoints = tmp.countChar32();
|
||||
return cvt_.std(tmp);
|
||||
}
|
||||
|
||||
icu_std_converter<CharType> cvt_;
|
||||
std::unique_ptr<icu::DateFormat> icu_fmt_holder_;
|
||||
icu::DateFormat& icu_fmt_;
|
||||
};
|
||||
|
||||
icu::UnicodeString strftime_symbol_to_icu(const char c, const formatters_cache& cache)
|
||||
{
|
||||
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': // DateTime
|
||||
return cache.default_date_time_format();
|
||||
// not supported by ICU ;(
|
||||
// case 'C': // Century -> 1980 -> 19
|
||||
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] Monday first
|
||||
case 'w': // weekday 0,7 0=Sunday
|
||||
case 'W': // week number of year [00,53] Monday first, */
|
||||
case 'x': // Date
|
||||
return cache.default_date_format();
|
||||
case 'X': // Time
|
||||
return cache.default_time_format();
|
||||
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(const icu::UnicodeString& ftime, const formatters_cache& cache)
|
||||
{
|
||||
const 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_symbol_to_icu(c, cache);
|
||||
} else if(c == '\'') {
|
||||
result += "''";
|
||||
} else {
|
||||
if(!escaped) {
|
||||
result += "'";
|
||||
escaped = true;
|
||||
}
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
if(escaped)
|
||||
result += "'";
|
||||
return result;
|
||||
}
|
||||
|
||||
format_len time_flags_to_len(const uint64_t time_flags)
|
||||
{
|
||||
switch(time_flags) {
|
||||
using namespace boost::locale::flags;
|
||||
case time_short: return format_len::Short;
|
||||
case time_medium: return format_len::Medium;
|
||||
case time_long: return format_len::Long;
|
||||
case time_full: return format_len::Full;
|
||||
default: return format_len::Medium;
|
||||
}
|
||||
}
|
||||
format_len date_flags_to_len(const uint64_t date_flags)
|
||||
{
|
||||
switch(date_flags) {
|
||||
using namespace boost::locale::flags;
|
||||
case date_short: return format_len::Short;
|
||||
case date_medium: return format_len::Medium;
|
||||
case date_long: return format_len::Long;
|
||||
case date_full: return format_len::Full;
|
||||
default: return format_len::Medium;
|
||||
}
|
||||
}
|
||||
icu::DateFormat::EStyle time_flags_to_icu_len(const uint64_t time_flags)
|
||||
{
|
||||
switch(time_flags) {
|
||||
using namespace boost::locale::flags;
|
||||
case time_short: return icu::DateFormat::kShort;
|
||||
case time_medium: return icu::DateFormat::kMedium;
|
||||
case time_long: return icu::DateFormat::kLong;
|
||||
case time_full: return icu::DateFormat::kFull;
|
||||
case time_default:
|
||||
default: return icu::DateFormat::kDefault;
|
||||
}
|
||||
}
|
||||
icu::DateFormat::EStyle date_flags_to_icu_len(const uint64_t date_flags)
|
||||
{
|
||||
switch(date_flags) {
|
||||
using namespace boost::locale::flags;
|
||||
case date_short: return icu::DateFormat::kShort;
|
||||
case date_medium: return icu::DateFormat::kMedium;
|
||||
case date_long: return icu::DateFormat::kLong;
|
||||
case date_full: return icu::DateFormat::kFull;
|
||||
case date_default:
|
||||
default: return icu::DateFormat::kDefault;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::unique_ptr<formatter<CharType>>
|
||||
formatter<CharType>::create(std::ios_base& ios, const icu::Locale& locale, const std::string& encoding)
|
||||
{
|
||||
using ptr_type = std::unique_ptr<formatter<CharType>>;
|
||||
|
||||
const ios_info& info = ios_info::get(ios);
|
||||
const formatters_cache& cache = std::use_facet<formatters_cache>(ios.getloc());
|
||||
|
||||
const uint64_t disp = info.display_flags();
|
||||
switch(disp) {
|
||||
using namespace boost::locale::flags;
|
||||
case posix:
|
||||
BOOST_ASSERT_MSG(false, "Shouldn't try to create a posix formatter"); // LCOV_EXCL_LINE
|
||||
break; // LCOV_EXCL_LINE
|
||||
case number: {
|
||||
const std::ios_base::fmtflags how = (ios.flags() & std::ios_base::floatfield);
|
||||
icu::NumberFormat& nf =
|
||||
cache.number_format((how == std::ios_base::scientific) ? num_fmt_type::sci : num_fmt_type::number);
|
||||
set_fraction_digits(nf, how, ios.precision());
|
||||
return ptr_type(new number_format<CharType>(nf, encoding));
|
||||
}
|
||||
case currency: {
|
||||
icu::NumberFormat& nf = cache.number_format(
|
||||
(info.currency_flags() == currency_iso) ? num_fmt_type::curr_iso : num_fmt_type::curr_nat);
|
||||
return ptr_type(new number_format<CharType>(nf, encoding));
|
||||
}
|
||||
case percent: {
|
||||
icu::NumberFormat& nf = cache.number_format(num_fmt_type::percent);
|
||||
set_fraction_digits(nf, ios.flags() & std::ios_base::floatfield, ios.precision());
|
||||
return ptr_type(new number_format<CharType>(nf, encoding));
|
||||
}
|
||||
case spellout:
|
||||
return ptr_type(new number_format<CharType>(cache.number_format(num_fmt_type::spell), encoding));
|
||||
case ordinal:
|
||||
return ptr_type(new number_format<CharType>(cache.number_format(num_fmt_type::ordinal), encoding));
|
||||
case date:
|
||||
case time:
|
||||
case datetime:
|
||||
case strftime: {
|
||||
using namespace flags;
|
||||
std::unique_ptr<icu::DateFormat> new_df;
|
||||
icu::DateFormat* df = 0;
|
||||
// try to use cached first
|
||||
{
|
||||
icu::SimpleDateFormat* sdf = cache.date_formatter();
|
||||
if(sdf) {
|
||||
icu::UnicodeString pattern;
|
||||
switch(disp) {
|
||||
case date: pattern = cache.date_format(date_flags_to_len(info.date_flags())); break;
|
||||
case time: pattern = cache.time_format(time_flags_to_len(info.time_flags())); break;
|
||||
case datetime:
|
||||
pattern = cache.date_time_format(date_flags_to_len(info.date_flags()),
|
||||
time_flags_to_len(info.time_flags()));
|
||||
break;
|
||||
case strftime: {
|
||||
icu_std_converter<CharType> cvt_(encoding);
|
||||
const std::basic_string<CharType>& 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!df) {
|
||||
switch(disp) {
|
||||
case date:
|
||||
new_df.reset(
|
||||
icu::DateFormat::createDateInstance(date_flags_to_icu_len(info.date_flags()), locale));
|
||||
break;
|
||||
case time:
|
||||
new_df.reset(
|
||||
icu::DateFormat::createTimeInstance(time_flags_to_icu_len(info.time_flags()), locale));
|
||||
break;
|
||||
case datetime:
|
||||
new_df.reset(
|
||||
icu::DateFormat::createDateTimeInstance(date_flags_to_icu_len(info.date_flags()),
|
||||
time_flags_to_icu_len(info.time_flags()),
|
||||
locale));
|
||||
break;
|
||||
case strftime: {
|
||||
icu_std_converter<CharType> cvt_(encoding);
|
||||
const std::basic_string<CharType>& f = info.date_time_pattern<CharType>();
|
||||
icu::UnicodeString pattern =
|
||||
strftime_to_icu(cvt_.icu(f.data(), f.data() + f.size()), locale);
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
new_df.reset(new icu::SimpleDateFormat(pattern, locale, err));
|
||||
if(U_FAILURE(err))
|
||||
return nullptr;
|
||||
} break;
|
||||
}
|
||||
df = new_df.get();
|
||||
BOOST_ASSERT_MSG(df, "Failed to create date/time formatter");
|
||||
}
|
||||
|
||||
df->adoptTimeZone(get_time_zone(info.time_zone()));
|
||||
|
||||
// Depending if we own formatter or not
|
||||
if(new_df)
|
||||
return ptr_type(new date_format<CharType>(std::move(new_df), encoding));
|
||||
else
|
||||
return ptr_type(new date_format<CharType>(*df, encoding));
|
||||
} break;
|
||||
}
|
||||
|
||||
return nullptr; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
template class formatter<char>;
|
||||
template class formatter<wchar_t>;
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
template class formatter<char16_t>;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
template class formatter<char32_t>;
|
||||
#endif
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
// boostinspect:nominmax
|
||||
73
externals/boost/libs/locale/src/boost/locale/icu/formatter.hpp
vendored
Normal file
73
externals/boost/libs/locale/src/boost/locale/icu/formatter.hpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_FORMATTER_HPP_INCLUDED
|
||||
#define BOOST_LOCALE_FORMATTER_HPP_INCLUDED
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#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() = default;
|
||||
};
|
||||
|
||||
/// \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(const string_type& 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(const string_type& 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(const string_type& 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.
|
||||
///
|
||||
/// 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 will create a new spelling formatter only once:
|
||||
///
|
||||
/// \code
|
||||
/// std::cout << as::spellout;
|
||||
/// for(int i=1;i<=10;i++)
|
||||
/// std::cout << i << std::endl;
|
||||
/// \endcode
|
||||
///
|
||||
///
|
||||
static std::unique_ptr<formatter>
|
||||
create(std::ios_base& ios, const icu::Locale& locale, const std::string& encoding);
|
||||
}; // class formatter
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
143
externals/boost/libs/locale/src/boost/locale/icu/formatters_cache.cpp
vendored
Normal file
143
externals/boost/libs/locale/src/boost/locale/icu/formatters_cache.cpp
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/icu/formatters_cache.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface...
|
||||
#endif
|
||||
#include <unicode/datefmt.h>
|
||||
#include <unicode/numfmt.h>
|
||||
#include <unicode/rbnf.h>
|
||||
#include <unicode/smpdtfmt.h>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
std::locale::id formatters_cache::id;
|
||||
|
||||
namespace {
|
||||
|
||||
struct init {
|
||||
init() { ignore_unused(std::has_facet<formatters_cache>(std::locale::classic())); }
|
||||
} instance;
|
||||
|
||||
void get_icu_pattern(std::unique_ptr<icu::DateFormat> fmt, icu::UnicodeString& out_str)
|
||||
{
|
||||
icu::SimpleDateFormat* sfmt = icu_cast<icu::SimpleDateFormat>(fmt.get());
|
||||
if(sfmt)
|
||||
sfmt->toPattern(out_str);
|
||||
else
|
||||
out_str.remove(); // LCOV_EXCL_LINE
|
||||
}
|
||||
void get_icu_pattern(icu::DateFormat* fmt, icu::UnicodeString& out_str)
|
||||
{
|
||||
return get_icu_pattern(std::unique_ptr<icu::DateFormat>(fmt), out_str);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
formatters_cache::formatters_cache(const icu::Locale& locale) : locale_(locale)
|
||||
{
|
||||
#define BOOST_LOCALE_ARRAY_SIZE(T) std::extent<typename std::remove_reference<decltype(T)>::type>::value
|
||||
constexpr icu::DateFormat::EStyle styles[]{icu::DateFormat::kShort,
|
||||
icu::DateFormat::kMedium,
|
||||
icu::DateFormat::kLong,
|
||||
icu::DateFormat::kFull};
|
||||
constexpr int num_styles = BOOST_LOCALE_ARRAY_SIZE(styles);
|
||||
|
||||
static_assert(num_styles == BOOST_LOCALE_ARRAY_SIZE(date_format_), "!");
|
||||
for(int i = 0; i < num_styles; i++)
|
||||
get_icu_pattern(icu::DateFormat::createDateInstance(styles[i], locale), date_format_[i]);
|
||||
|
||||
static_assert(num_styles == BOOST_LOCALE_ARRAY_SIZE(time_format_), "!");
|
||||
for(int i = 0; i < num_styles; i++)
|
||||
get_icu_pattern(icu::DateFormat::createTimeInstance(styles[i], locale), time_format_[i]);
|
||||
|
||||
static_assert(num_styles == BOOST_LOCALE_ARRAY_SIZE(date_time_format_), "!");
|
||||
static_assert(num_styles == BOOST_LOCALE_ARRAY_SIZE(date_time_format_[0]), "!");
|
||||
for(int i = 0; i < num_styles; i++) {
|
||||
for(int j = 0; j < num_styles; j++) {
|
||||
get_icu_pattern(icu::DateFormat::createDateTimeInstance(styles[i], styles[j], locale),
|
||||
date_time_format_[i][j]);
|
||||
}
|
||||
}
|
||||
#undef BOOST_LOCALE_ARRAY_SIZE
|
||||
|
||||
const auto get_str_or = [](const icu::UnicodeString& str, const char* default_str) {
|
||||
return str.isEmpty() ? default_str : str;
|
||||
};
|
||||
default_date_format_ = get_str_or(date_format(format_len::Medium), "yyyy-MM-dd");
|
||||
default_time_format_ = get_str_or(time_format(format_len::Medium), "HH:mm:ss");
|
||||
default_date_time_format_ =
|
||||
get_str_or(date_time_format(format_len::Full, format_len::Full), "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
icu::NumberFormat* formatters_cache::create_number_format(num_fmt_type type, UErrorCode& err) const
|
||||
{
|
||||
switch(type) {
|
||||
case num_fmt_type::number: return icu::NumberFormat::createInstance(locale_, err); break;
|
||||
case num_fmt_type::sci: return icu::NumberFormat::createScientificInstance(locale_, err); break;
|
||||
#if BOOST_LOCALE_ICU_VERSION >= 408
|
||||
case num_fmt_type::curr_nat: return icu::NumberFormat::createInstance(locale_, UNUM_CURRENCY, err); break;
|
||||
case num_fmt_type::curr_iso:
|
||||
return icu::NumberFormat::createInstance(locale_, UNUM_CURRENCY_ISO, err);
|
||||
break;
|
||||
#elif BOOST_LOCALE_ICU_VERSION >= 402
|
||||
case num_fmt_type::curr_nat:
|
||||
return icu::NumberFormat::createInstance(locale_, icu::NumberFormat::kCurrencyStyle, err);
|
||||
break;
|
||||
case num_fmt_type::curr_iso:
|
||||
return icu::NumberFormat::createInstance(locale_, icu::NumberFormat::kIsoCurrencyStyle, err);
|
||||
break;
|
||||
#else
|
||||
case num_fmt_type::curr_nat:
|
||||
case num_fmt_type::curr_iso: return icu::NumberFormat::createCurrencyInstance(locale_, err); break;
|
||||
#endif
|
||||
case num_fmt_type::percent: return icu::NumberFormat::createPercentInstance(locale_, err); break;
|
||||
case num_fmt_type::spell: return new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT, locale_, err); break;
|
||||
case num_fmt_type::ordinal: return new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL, locale_, err); break;
|
||||
}
|
||||
throw std::logic_error("locale::internal error should not get there"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
icu::NumberFormat& formatters_cache::number_format(num_fmt_type type) const
|
||||
{
|
||||
icu::NumberFormat* result = number_format_[int(type)].get();
|
||||
if(!result) {
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
std::unique_ptr<icu::NumberFormat> new_ptr(create_number_format(type, err));
|
||||
check_and_throw_icu_error(err, "Failed to create a formatter");
|
||||
result = new_ptr.get();
|
||||
BOOST_ASSERT(result);
|
||||
number_format_[int(type)].reset(new_ptr.release());
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
||||
icu::SimpleDateFormat* formatters_cache::date_formatter() const
|
||||
{
|
||||
icu::SimpleDateFormat* result = date_formatter_.get();
|
||||
if(!result) {
|
||||
std::unique_ptr<icu::DateFormat> fmt(
|
||||
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kMedium, icu::DateFormat::kMedium, locale_));
|
||||
|
||||
result = icu_cast<icu::SimpleDateFormat>(fmt.get());
|
||||
if(result) {
|
||||
fmt.release();
|
||||
date_formatter_.reset(result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
78
externals/boost/libs/locale/src/boost/locale/icu/formatters_cache.hpp
vendored
Normal file
78
externals/boost/libs/locale/src/boost/locale/icu/formatters_cache.hpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED
|
||||
#define BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <locale>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface...
|
||||
#endif
|
||||
#include <unicode/locid.h>
|
||||
#include <unicode/numfmt.h>
|
||||
#include <unicode/smpdtfmt.h>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
enum class format_len {
|
||||
Short,
|
||||
Medium,
|
||||
Long,
|
||||
Full,
|
||||
};
|
||||
|
||||
enum class num_fmt_type { number, sci, curr_nat, curr_iso, percent, spell, ordinal };
|
||||
|
||||
class formatters_cache : public std::locale::facet {
|
||||
public:
|
||||
static std::locale::id id;
|
||||
|
||||
formatters_cache(const icu::Locale& locale);
|
||||
|
||||
icu::NumberFormat& number_format(num_fmt_type type) const;
|
||||
|
||||
const icu::UnicodeString& date_format(format_len f) const { return date_format_[int(f)]; }
|
||||
|
||||
const icu::UnicodeString& time_format(format_len f) const { return time_format_[int(f)]; }
|
||||
|
||||
const icu::UnicodeString& date_time_format(format_len d, format_len t) const
|
||||
{
|
||||
return date_time_format_[int(d)][int(t)];
|
||||
}
|
||||
|
||||
const icu::UnicodeString& default_date_format() const { return default_date_format_; }
|
||||
const icu::UnicodeString& default_time_format() const { return default_time_format_; }
|
||||
const icu::UnicodeString& default_date_time_format() const { return default_date_time_format_; }
|
||||
|
||||
icu::SimpleDateFormat* date_formatter() const;
|
||||
|
||||
private:
|
||||
icu::NumberFormat* create_number_format(num_fmt_type type, UErrorCode& err) const;
|
||||
|
||||
static constexpr auto num_fmt_type_count = static_cast<unsigned>(num_fmt_type::ordinal) + 1;
|
||||
static constexpr auto format_len_count = static_cast<unsigned>(format_len::Full) + 1;
|
||||
|
||||
mutable boost::thread_specific_ptr<icu::NumberFormat> number_format_[num_fmt_type_count];
|
||||
icu::UnicodeString date_format_[format_len_count];
|
||||
icu::UnicodeString time_format_[format_len_count];
|
||||
icu::UnicodeString date_time_format_[format_len_count][format_len_count];
|
||||
icu::UnicodeString default_date_format_, default_time_format_, default_date_time_format_;
|
||||
mutable boost::thread_specific_ptr<icu::SimpleDateFormat> date_formatter_;
|
||||
icu::Locale locale_;
|
||||
};
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
135
externals/boost/libs/locale/src/boost/locale/icu/icu_backend.cpp
vendored
Normal file
135
externals/boost/libs/locale/src/boost/locale/icu/icu_backend.cpp
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/icu/icu_backend.hpp"
|
||||
#include <boost/locale/gnu_gettext.hpp>
|
||||
#include <boost/locale/localization_backend.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <boost/locale/util/locale_data.hpp>
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.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(const icu_localization_backend& other) :
|
||||
localization_backend(), paths_(other.paths_), domains_(other.domains_), locale_id_(other.locale_id_),
|
||||
invalid_(true), use_ansi_encoding_(other.use_ansi_encoding_)
|
||||
{}
|
||||
icu_localization_backend* clone() const override { return new icu_localization_backend(*this); }
|
||||
|
||||
void set_option(const std::string& name, const std::string& value) override
|
||||
{
|
||||
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() override
|
||||
{
|
||||
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.is_utf8();
|
||||
language_ = d.language();
|
||||
country_ = d.country();
|
||||
variant_ = d.variant();
|
||||
}
|
||||
|
||||
std::locale install(const std::locale& base, category_t category, char_facet_t type) override
|
||||
{
|
||||
prepare_data();
|
||||
|
||||
switch(category) {
|
||||
case category_t::convert: return create_convert(base, data_, type);
|
||||
case category_t::collation: return create_collate(base, data_, type);
|
||||
case category_t::formatting: return create_formatting(base, data_, type);
|
||||
case category_t::parsing: return create_parsing(base, data_, type);
|
||||
case category_t::codepage: return create_codecvt(base, data_.encoding, type);
|
||||
case category_t::message: {
|
||||
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_t::nochar: break;
|
||||
case char_facet_t::char_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char>(minf));
|
||||
case char_facet_t::wchar_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<wchar_t>(minf));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char16_t>(minf));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char32_t>(minf));
|
||||
#endif
|
||||
}
|
||||
return base;
|
||||
}
|
||||
case category_t::boundary: return create_boundary(base, data_, type);
|
||||
case category_t::calendar: return create_calendar(base, data_);
|
||||
case category_t::information: return util::create_info(base, real_id_);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
18
externals/boost/libs/locale/src/boost/locale/icu/icu_backend.hpp
vendored
Normal file
18
externals/boost/libs/locale/src/boost/locale/icu/icu_backend.hpp
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_ICU_LOCALIZATION_BACKEND_HPP
|
||||
#define BOOST_LOCALE_IMPL_ICU_LOCALIZATION_BACKEND_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
class localization_backend;
|
||||
namespace impl_icu {
|
||||
localization_backend* create_localization_backend();
|
||||
} // namespace impl_icu
|
||||
}} // namespace boost::locale
|
||||
#endif
|
||||
49
externals/boost/libs/locale/src/boost/locale/icu/icu_util.hpp
vendored
Normal file
49
externals/boost/libs/locale/src/boost/locale/icu/icu_util.hpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2021-2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_SRC_ICU_UTIL_HPP
|
||||
#define BOOST_SRC_ICU_UTIL_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#ifdef BOOST_HAS_STDINT_H
|
||||
# include <stdint.h> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/uversion.h>
|
||||
|
||||
#define BOOST_LOCALE_ICU_VERSION (U_ICU_VERSION_MAJOR_NUM * 100 + U_ICU_VERSION_MINOR_NUM)
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
inline void throw_icu_error(UErrorCode err, std::string desc) // LCOV_EXCL_LINE
|
||||
{
|
||||
if(!desc.empty()) // LCOV_EXCL_LINE
|
||||
desc += ": "; // LCOV_EXCL_LINE
|
||||
throw std::runtime_error(desc + u_errorName(err)); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
inline void check_and_throw_icu_error(UErrorCode err, const char* desc = "")
|
||||
{
|
||||
if(U_FAILURE(err))
|
||||
throw_icu_error(err, desc); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
/// Cast a pointer to an ICU object to a pointer to TargetType
|
||||
/// using RTTI or ICUs "poor man's RTTI" to make it work with e.g. libc++ and hidden visibility
|
||||
template<class TargetType, class SourceType>
|
||||
TargetType* icu_cast(SourceType* p)
|
||||
{
|
||||
TargetType* result = dynamic_cast<TargetType*>(p);
|
||||
if(!result && p && p->getDynamicClassID() == TargetType::getStaticClassID())
|
||||
result = static_cast<TargetType*>(p);
|
||||
return result;
|
||||
}
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
367
externals/boost/libs/locale/src/boost/locale/icu/numeric.cpp
vendored
Normal file
367
externals/boost/libs/locale/src/boost/locale/icu/numeric.cpp
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include "boost/locale/icu/all_generator.hpp"
|
||||
#include "boost/locale/icu/cdata.hpp"
|
||||
#include "boost/locale/icu/formatter.hpp"
|
||||
#include "boost/locale/icu/formatters_cache.hpp"
|
||||
#include <algorithm>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool integer = std::numeric_limits<T>::is_integer>
|
||||
struct icu_format_type;
|
||||
|
||||
template<typename T>
|
||||
struct icu_format_type<T, true> {
|
||||
// ICU supports 32 and 64 bit ints, use the former as long as it fits, else the latter
|
||||
typedef typename std::conditional<std::numeric_limits<T>::digits <= 31, int32_t, int64_t>::type type;
|
||||
};
|
||||
template<typename T>
|
||||
struct icu_format_type<T, false> {
|
||||
// Only float type ICU supports is double
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
// ICU does not support uint64_t values so fall back to the parent/std formatting
|
||||
// if the number is to large to fit into an int64_t
|
||||
template<typename T,
|
||||
bool BigUInt = !std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer
|
||||
&& (sizeof(T) >= sizeof(uint64_t))>
|
||||
struct use_parent_traits {
|
||||
static bool use(T /*v*/) { return false; }
|
||||
};
|
||||
template<typename T>
|
||||
struct use_parent_traits<T, true> {
|
||||
static bool use(T v) { return v > static_cast<T>(std::numeric_limits<int64_t>::max()); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
static bool use_parent(std::ios_base& ios, ValueType v)
|
||||
{
|
||||
const uint64_t flg = ios_info::get(ios).display_flags();
|
||||
if(flg == flags::posix)
|
||||
return true;
|
||||
if(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;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
template<typename CharType>
|
||||
class 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;
|
||||
typedef formatter<CharType> formatter_type;
|
||||
|
||||
num_format(const cdata& d, size_t refs = 0) : std::num_put<CharType>(refs), loc_(d.locale), enc_(d.encoding) {}
|
||||
|
||||
protected:
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, double val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long double val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ValueType>
|
||||
iter_type do_real_put(iter_type out, std::ios_base& ios, char_type fill, ValueType val) const
|
||||
{
|
||||
if(detail::use_parent(ios, val))
|
||||
return std::num_put<char_type>::do_put(out, ios, fill, val);
|
||||
|
||||
const auto formatter = formatter_type::create(ios, loc_, enc_);
|
||||
|
||||
if(!formatter)
|
||||
return std::num_put<char_type>::do_put(out, ios, fill, val);
|
||||
|
||||
size_t code_points;
|
||||
typedef typename detail::icu_format_type<ValueType>::type icu_type;
|
||||
const string_type& str = formatter->format(static_cast<icu_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> {
|
||||
public:
|
||||
num_parse(const cdata& 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 std::basic_istream<CharType> stream_type;
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned short& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned int& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, float& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, double& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
long double& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
long long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned long long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
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 || detail::use_parent(ios, ValueType(0))) {
|
||||
return std::num_get<CharType>::do_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
const auto formatter = formatter_type::create(ios, loc_, enc_);
|
||||
if(!formatter) {
|
||||
return std::num_get<CharType>::do_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
typedef typename detail::icu_format_type<ValueType>::type icu_type;
|
||||
icu_type value;
|
||||
size_t parsed_chars;
|
||||
|
||||
if((parsed_chars = formatter->parse(tmp, value)) == 0 || !is_losless_castable<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;
|
||||
}
|
||||
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
template<typename TargetType, typename SrcType>
|
||||
bool is_losless_castable(SrcType v) const
|
||||
{
|
||||
typedef std::numeric_limits<TargetType> target_limits;
|
||||
typedef std::numeric_limits<SrcType> casted_limits;
|
||||
if(v < 0 && !target_limits::is_signed)
|
||||
return false;
|
||||
|
||||
constexpr TargetType max_val = target_limits::max();
|
||||
|
||||
if(sizeof(SrcType) > sizeof(TargetType) && v > static_cast<SrcType>(max_val))
|
||||
return false;
|
||||
|
||||
if(target_limits::is_integer == casted_limits::is_integer)
|
||||
return true;
|
||||
|
||||
if(target_limits::is_integer) { // and source is not
|
||||
if(static_cast<SrcType>(static_cast<TargetType>(v)) != v)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
|
||||
icu::Locale loc_;
|
||||
std::string enc_;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
std::locale install_formatting_facets(const std::locale& in, const cdata& cd)
|
||||
{
|
||||
std::locale tmp = std::locale(in, new num_format<CharType>(cd));
|
||||
if(!std::has_facet<formatters_cache>(in)) {
|
||||
tmp = std::locale(tmp, new formatters_cache(cd.locale));
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::locale install_parsing_facets(const std::locale& in, const cdata& cd)
|
||||
{
|
||||
std::locale tmp = std::locale(in, new num_parse<CharType>(cd));
|
||||
if(!std::has_facet<formatters_cache>(in)) {
|
||||
tmp = std::locale(tmp, new formatters_cache(cd.locale));
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
std::locale create_formatting(const std::locale& in, const cdata& cd, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return install_formatting_facets<char>(in, cd);
|
||||
case char_facet_t::wchar_f: return install_formatting_facets<wchar_t>(in, cd);
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return install_formatting_facets<char16_t>(in, cd);
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return install_formatting_facets<char32_t>(in, cd);
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
std::locale create_parsing(const std::locale& in, const cdata& cd, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return install_parsing_facets<char>(in, cd);
|
||||
case char_facet_t::wchar_f: return install_parsing_facets<wchar_t>(in, cd);
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return install_parsing_facets<char16_t>(in, cd);
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return install_parsing_facets<char32_t>(in, cd);
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
// boostinspect:nominmax
|
||||
217
externals/boost/libs/locale/src/boost/locale/icu/time_zone.cpp
vendored
Normal file
217
externals/boost/libs/locale/src/boost/locale/icu/time_zone.cpp
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/icu/time_zone.hpp"
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
#include <boost/predef/os.h>
|
||||
|
||||
//
|
||||
// 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 BOOST_LOCALE_ICU_VERSION >= 400 && BOOST_LOCALE_ICU_VERSION <= 406 \
|
||||
&& (BOOST_LOCALE_ICU_VERSION != 404 || U_ICU_VERSION_PATCHLEVEL_NUM >= 3)
|
||||
# if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || defined(__APPLE__)
|
||||
# define BOOST_LOCALE_WORKAROUND_ICU_BUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_WORKAROUND_ICU_BUG
|
||||
# include <cstring>
|
||||
# include <dirent.h>
|
||||
# include <fstream>
|
||||
# include <memory>
|
||||
# include <pthread.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
#ifndef BOOST_LOCALE_WORKAROUND_ICU_BUG
|
||||
|
||||
// This is normal behavior
|
||||
|
||||
icu::TimeZone* get_time_zone(const std::string& time_zone)
|
||||
{
|
||||
if(time_zone.empty()) {
|
||||
return icu::TimeZone::createDefault();
|
||||
} else {
|
||||
icu::TimeZone* icu_tz = icu::TimeZone::createTimeZone(time_zone.c_str());
|
||||
return icu_tz;
|
||||
}
|
||||
}
|
||||
|
||||
#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(const char* name) : d(0), read_result(0)
|
||||
{
|
||||
d = opendir(name);
|
||||
if(!d)
|
||||
return;
|
||||
}
|
||||
~directory()
|
||||
{
|
||||
if(d)
|
||||
closedir(d);
|
||||
}
|
||||
bool is_open() { return d; }
|
||||
const char* 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(const std::string& left, const std::string& 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(const std::string& ref, size_t size, const std::string& dir)
|
||||
{
|
||||
directory d(dir.c_str());
|
||||
if(!d.is_open())
|
||||
return std::string();
|
||||
|
||||
const char* 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()
|
||||
{
|
||||
const char* tz_dir = "/usr/share/zoneinfo";
|
||||
const char* 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(const std::string& 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
|
||||
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
24
externals/boost/libs/locale/src/boost/locale/icu/time_zone.hpp
vendored
Normal file
24
externals/boost/libs/locale/src/boost/locale/icu/time_zone.hpp
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 <boost/locale/config.hpp>
|
||||
#ifdef BOOST_HAS_STDINT_H
|
||||
# include <stdint.h> // Avoid ICU defining e.g. INT8_MIN causing macro redefinition warnings
|
||||
#endif
|
||||
#include <string>
|
||||
#include <unicode/timezone.h>
|
||||
|
||||
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(const std::string& time_zone);
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
#endif
|
||||
306
externals/boost/libs/locale/src/boost/locale/icu/uconv.hpp
vendored
Normal file
306
externals/boost/libs/locale/src/boost/locale/icu/uconv.hpp
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_SRC_LOCALE_ICU_UCONV_HPP
|
||||
#define BOOST_SRC_LOCALE_ICU_UCONV_HPP
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include "boost/locale/icu/icu_util.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unicode/ucnv.h>
|
||||
#include <unicode/unistr.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/utf.h>
|
||||
#include <unicode/utf16.h>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4244) // 'argument' : conversion from 'int'
|
||||
# pragma warning(disable : 4267) // 'argument' : conversion from 'size_t'
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_icu {
|
||||
|
||||
enum class cpcvt_type { skip, stop };
|
||||
|
||||
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 = cpcvt_type::skip);
|
||||
icu::UnicodeString icu(const char_type* begin, const char_type* end) const;
|
||||
string_type std(const icu::UnicodeString& str) const;
|
||||
size_t cut(const icu::UnicodeString& str,
|
||||
const char_type* begin,
|
||||
const char_type* 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(const char_type* vb, const char_type* ve) const
|
||||
{
|
||||
return icu(vb, ve); // Already done
|
||||
}
|
||||
icu::UnicodeString icu(const char_type* vb, const char_type* ve) const
|
||||
{
|
||||
const char* begin = reinterpret_cast<const char*>(vb);
|
||||
const char* end = reinterpret_cast<const char*>(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(const icu::UnicodeString& 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 = cpcvt_type::skip) :
|
||||
charset_(charset), cvt_type_(cvt_type)
|
||||
{
|
||||
uconv cvt(charset_, cvt_type);
|
||||
max_len_ = cvt.max_char_size();
|
||||
}
|
||||
|
||||
size_t cut(const icu::UnicodeString& str,
|
||||
const char_type* begin,
|
||||
const char_type* 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(const uconv& other) = delete;
|
||||
void operator=(const uconv& other) = delete;
|
||||
|
||||
uconv(const std::string& charset, cpcvt_type cvt_type = cpcvt_type::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 == cpcvt_type::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(const UChar* 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, const char_type* begin, const char_type* end)
|
||||
{
|
||||
const char_type* 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(const char_type* begin, const char_type* 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_ == cpcvt_type::stop)
|
||||
throw conv::conversion_error();
|
||||
}
|
||||
icu::UnicodeString icu(const char_type* vb, const char_type* ve) const
|
||||
{
|
||||
const UChar* begin = reinterpret_cast<const UChar*>(vb);
|
||||
const UChar* end = reinterpret_cast<const UChar*>(ve);
|
||||
icu::UnicodeString tmp(begin, end - begin);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string_type std(const icu::UnicodeString& str) const
|
||||
{
|
||||
const char_type* ptr = reinterpret_cast<const char_type*>(str.getBuffer());
|
||||
return string_type(ptr, str.length());
|
||||
}
|
||||
size_t cut(const icu::UnicodeString& /*str*/,
|
||||
const char_type* /*begin*/,
|
||||
const char_type* /*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 = cpcvt_type::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(const char_type* begin, const char_type* 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_ == cpcvt_type::stop)
|
||||
throw conv::conversion_error();
|
||||
}
|
||||
|
||||
icu::UnicodeString icu(const char_type* begin, const char_type* 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(const icu::UnicodeString& str) const
|
||||
{
|
||||
string_type tmp;
|
||||
tmp.resize(str.length());
|
||||
UChar32* ptr = reinterpret_cast<UChar32*>(&tmp[0]);
|
||||
int32_t len = 0;
|
||||
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(const icu::UnicodeString& str,
|
||||
const char_type* /*begin*/,
|
||||
const char_type* /*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 = cpcvt_type::skip) : mode_(mode) {}
|
||||
|
||||
private:
|
||||
cpcvt_type mode_;
|
||||
};
|
||||
}}} // namespace boost::locale::impl_icu
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
32
externals/boost/libs/locale/src/boost/locale/posix/all_generator.hpp
vendored
Normal file
32
externals/boost/libs/locale/src/boost/locale/posix/all_generator.hpp
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 <clocale>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace impl_posix {
|
||||
|
||||
std::locale create_convert(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type);
|
||||
|
||||
std::locale create_collate(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type);
|
||||
|
||||
std::locale create_formatting(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type);
|
||||
|
||||
std::locale create_parsing(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type);
|
||||
std::locale create_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type);
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
|
||||
#endif
|
||||
28
externals/boost/libs/locale/src/boost/locale/posix/codecvt.cpp
vendored
Normal file
28
externals/boost/libs/locale/src/boost/locale/posix/codecvt.cpp
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022-2023 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding_errors.hpp>
|
||||
#include "boost/locale/posix/all_generator.hpp"
|
||||
#include "boost/locale/shared/iconv_codecvt.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_posix {
|
||||
|
||||
std::locale create_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type)
|
||||
{
|
||||
if(util::normalize_encoding(encoding) == "utf8")
|
||||
return util::create_utf8_codecvt(in, type);
|
||||
|
||||
try {
|
||||
return util::create_simple_codecvt(in, encoding, type);
|
||||
} catch(const conv::invalid_charset_error&) {
|
||||
return util::create_codecvt(in, create_iconv_converter(encoding), type);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
98
externals/boost/libs/locale/src/boost/locale/posix/collate.cpp
vendored
Normal file
98
externals/boost/libs/locale/src/boost/locale/posix/collate.cpp
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/generator.hpp>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
#include <clocale>
|
||||
#include <cstring>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "boost/locale/posix/all_generator.hpp"
|
||||
#include "boost/locale/shared/mo_hash.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, const char* in, size_t n, locale_t l) { return strxfrm_l(out, in, n, l); }
|
||||
static size_t coll(const char* left, const char* right, locale_t l) { return strcoll_l(left, right, l); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct coll_traits<wchar_t> {
|
||||
static size_t xfrm(wchar_t* out, const wchar_t* in, size_t n, locale_t l) { return wcsxfrm_l(out, in, n, l); }
|
||||
static size_t coll(const wchar_t* left, const wchar_t* 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(std::shared_ptr<locale_t> l, size_t refs = 0) : std::collate<CharType>(refs), lc_(std::move(l)) {}
|
||||
|
||||
int
|
||||
do_compare(const char_type* lb, const char_type* le, const char_type* rb, const char_type* re) const override
|
||||
{
|
||||
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;
|
||||
}
|
||||
long do_hash(const char_type* b, const char_type* e) const override
|
||||
{
|
||||
string_type s(do_transform(b, e));
|
||||
const char* begin = reinterpret_cast<const char*>(s.c_str());
|
||||
const char* end = begin + s.size() * sizeof(char_type);
|
||||
return gnu_gettext::pj_winberger_hash_function(begin, end);
|
||||
}
|
||||
string_type do_transform(const char_type* b, const char_type* e) const override
|
||||
{
|
||||
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:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
std::locale create_collate(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new collator<char>(std::move(lc)));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new collator<wchar_t>(std::move(lc)));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new collator<char16_t>(std::move(lc)));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new collator<char32_t>(std::move(lc)));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
141
externals/boost/libs/locale/src/boost/locale/posix/converter.cpp
vendored
Normal file
141
externals/boost/libs/locale/src/boost/locale/posix/converter.cpp
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/conversion.hpp>
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <langinfo.h>
|
||||
#include <locale>
|
||||
#include <stdexcept>
|
||||
#include <wctype.h>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#include "boost/locale/posix/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(std::shared_ptr<locale_t> lc, size_t refs = 0) : converter<CharType>(refs), lc_(std::move(lc)) {}
|
||||
string_type convert(converter_base::conversion_type how,
|
||||
const char_type* begin,
|
||||
const char_type* end,
|
||||
int /*flags*/ = 0) const override
|
||||
{
|
||||
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;
|
||||
}
|
||||
case converter_base::normalization:
|
||||
case converter_base::title_case: break;
|
||||
}
|
||||
return string_type(begin, end - begin);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
class utf8_converter : public converter<char> {
|
||||
public:
|
||||
utf8_converter(std::shared_ptr<locale_t> lc, size_t refs = 0) : converter<char>(refs), lc_(std::move(lc)) {}
|
||||
std::string convert(converter_base::conversion_type how,
|
||||
const char* begin,
|
||||
const char* end,
|
||||
int /*flags*/ = 0) const override
|
||||
{
|
||||
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");
|
||||
}
|
||||
case normalization:
|
||||
case title_case: break;
|
||||
}
|
||||
return std::string(begin, end - begin);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
std::locale create_convert(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: {
|
||||
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(std::move(lc)));
|
||||
}
|
||||
return std::locale(in, new std_converter<char>(std::move(lc)));
|
||||
}
|
||||
case char_facet_t::wchar_f: return std::locale(in, new std_converter<wchar_t>(std::move(lc)));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new std_converter<char16_t>(std::move(lc)));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new std_converter<char32_t>(std::move(lc)));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
441
externals/boost/libs/locale/src/boost/locale/posix/numeric.cpp
vendored
Normal file
441
externals/boost/libs/locale/src/boost/locale/posix/numeric.cpp
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/predef/os.h>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <ios>
|
||||
#include <langinfo.h>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
#include <monetary.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wctype.h>
|
||||
|
||||
#include "boost/locale/posix/all_generator.hpp"
|
||||
#include "boost/locale/util/numeric.hpp"
|
||||
|
||||
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(std::shared_ptr<locale_t> lc, size_t refs = 0) :
|
||||
util::base_num_format<CharType>(refs), lc_(std::move(lc))
|
||||
{}
|
||||
|
||||
protected:
|
||||
iter_type do_format_currency(bool intl,
|
||||
iter_type out,
|
||||
std::ios_base& /*ios*/,
|
||||
char_type /*fill*/,
|
||||
long double val) const override
|
||||
{
|
||||
char buf[4] = {};
|
||||
const char* 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, const char* 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, const char* 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:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
|
||||
}; /// num_format
|
||||
|
||||
namespace {
|
||||
std::string do_ftime(const char* 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) {
|
||||
// Note standard specifies that in case of 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.data(), 1024, format, t, lc);
|
||||
return std::string(v.data(), n);
|
||||
}
|
||||
return std::string(buf, n);
|
||||
}
|
||||
template<typename CharType>
|
||||
std::basic_string<CharType> do_ftime(const CharType* format, const struct tm* t, locale_t lc)
|
||||
{
|
||||
const std::string encoding = nl_langinfo_l(CODESET, lc);
|
||||
const std::string nformat = conv::from_utf(format, encoding);
|
||||
const std::string nres = do_ftime(nformat.c_str(), t, lc);
|
||||
return conv::to_utf<CharType>(nres, encoding);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template<typename CharType>
|
||||
class time_put_posix : public std::time_put<CharType> {
|
||||
public:
|
||||
time_put_posix(std::shared_ptr<locale_t> lc, size_t refs = 0) :
|
||||
std::time_put<CharType>(refs), lc_(std::move(lc))
|
||||
{}
|
||||
typedef typename std::time_put<CharType>::iter_type iter_type;
|
||||
typedef CharType char_type;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
iter_type do_put(iter_type out,
|
||||
std::ios_base& /*ios*/,
|
||||
CharType /*fill*/,
|
||||
const std::tm* tm,
|
||||
char format,
|
||||
char modifier) const override
|
||||
{
|
||||
char_type fmt[4] = {'%',
|
||||
static_cast<char_type>(modifier != 0 ? modifier : format),
|
||||
static_cast<char_type>(modifier == 0 ? '\0' : format)};
|
||||
string_type res = do_ftime(fmt, tm, *lc_);
|
||||
for(unsigned i = 0; i < res.size(); i++)
|
||||
*out++ = res[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
class ctype_posix;
|
||||
|
||||
template<>
|
||||
class ctype_posix<char> : public std::ctype<char> {
|
||||
public:
|
||||
ctype_posix(std::shared_ptr<locale_t> lc) : lc_(std::move(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;
|
||||
}
|
||||
const char* do_is(const char* begin, const char* 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;
|
||||
}
|
||||
const char* do_scan_is(mask m, const char* begin, const char* end) const
|
||||
{
|
||||
while(begin != end)
|
||||
if(do_is(m, *begin))
|
||||
return begin;
|
||||
return begin;
|
||||
}
|
||||
const char* do_scan_not(mask m, const char* begin, const char* end) const
|
||||
{
|
||||
while(begin != end)
|
||||
if(!do_is(m, *begin))
|
||||
return begin;
|
||||
return begin;
|
||||
}
|
||||
char toupper(char c) const { return toupper_l(c, *lc_); }
|
||||
const char* toupper(char* begin, const char* end) const
|
||||
{
|
||||
for(; begin != end; begin++)
|
||||
*begin = toupper_l(*begin, *lc_);
|
||||
return begin;
|
||||
}
|
||||
char tolower(char c) const { return tolower_l(c, *lc_); }
|
||||
const char* tolower(char* begin, const char* end) const
|
||||
{
|
||||
for(; begin != end; begin++)
|
||||
*begin = tolower_l(*begin, *lc_);
|
||||
return begin;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
template<>
|
||||
class ctype_posix<wchar_t> : public std::ctype<wchar_t> {
|
||||
public:
|
||||
ctype_posix(std::shared_ptr<locale_t> lc) : lc_(std::move(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;
|
||||
}
|
||||
const wchar_t* do_is(const wchar_t* begin, const wchar_t* 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;
|
||||
}
|
||||
const wchar_t* do_scan_is(mask m, const wchar_t* begin, const wchar_t* end) const
|
||||
{
|
||||
while(begin != end)
|
||||
if(do_is(m, *begin))
|
||||
return begin;
|
||||
return begin;
|
||||
}
|
||||
const wchar_t* do_scan_not(mask m, const wchar_t* begin, const wchar_t* 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_); }
|
||||
const wchar_t* toupper(wchar_t* begin, const wchar_t* 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_); }
|
||||
const wchar_t* tolower(wchar_t* begin, const wchar_t* end) const
|
||||
{
|
||||
for(; begin != end; begin++)
|
||||
*begin = tolower_l(*begin, *lc_);
|
||||
return begin;
|
||||
}
|
||||
|
||||
private:
|
||||
std::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));
|
||||
}
|
||||
CharType do_decimal_point() const override { return *decimal_point_.c_str(); }
|
||||
CharType do_thousands_sep() const override { return *thousands_sep_.c_str(); }
|
||||
std::string do_grouping() const override { return grouping_; }
|
||||
string_type do_truename() const override
|
||||
{
|
||||
static const char t[] = "true";
|
||||
return string_type(t, t + sizeof(t) - 1);
|
||||
}
|
||||
string_type do_falsename() const override
|
||||
{
|
||||
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(const std::locale& in, std::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>(std::move(lc)));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<typename CharType>
|
||||
std::locale create_parsing_impl(const std::locale& in, std::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>(std::move(lc)));
|
||||
tmp = std::locale(tmp, new util::base_num_parse<CharType>());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
std::locale create_formatting(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return create_formatting_impl<char>(in, std::move(lc));
|
||||
case char_facet_t::wchar_f: return create_formatting_impl<wchar_t>(in, std::move(lc));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return create_formatting_impl<char16_t>(in, lc);
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return create_formatting_impl<char32_t>(in, lc);
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
std::locale create_parsing(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return create_parsing_impl<char>(in, std::move(lc));
|
||||
case char_facet_t::wchar_f: return create_parsing_impl<wchar_t>(in, std::move(lc));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return create_parsing_impl<char16_t>(in, lc);
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return create_parsing_impl<char32_t>(in, lc);
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
156
externals/boost/libs/locale/src/boost/locale/posix/posix_backend.cpp
vendored
Normal file
156
externals/boost/libs/locale/src/boost/locale/posix/posix_backend.cpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/posix/posix_backend.hpp"
|
||||
#include <boost/locale/gnu_gettext.hpp>
|
||||
#include <boost/locale/info.hpp>
|
||||
#include <boost/locale/localization_backend.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <boost/locale/util/locale_data.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <langinfo.h>
|
||||
#include <vector>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#include "boost/locale/posix/all_generator.hpp"
|
||||
#include "boost/locale/util/gregorian.hpp"
|
||||
|
||||
namespace boost { namespace locale { namespace impl_posix {
|
||||
|
||||
class posix_localization_backend : public localization_backend {
|
||||
public:
|
||||
posix_localization_backend() : invalid_(true) {}
|
||||
posix_localization_backend(const posix_localization_backend& other) :
|
||||
localization_backend(), paths_(other.paths_), domains_(other.domains_), locale_id_(other.locale_id_),
|
||||
invalid_(true)
|
||||
{}
|
||||
posix_localization_backend* clone() const override { return new posix_localization_backend(*this); }
|
||||
|
||||
void set_option(const std::string& name, const std::string& value) override
|
||||
{
|
||||
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() override
|
||||
{
|
||||
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_ = std::shared_ptr<locale_t>(tmp_p, free_locale_by_ptr);
|
||||
}
|
||||
|
||||
std::locale install(const std::locale& base, category_t category, char_facet_t type) override
|
||||
{
|
||||
prepare_data();
|
||||
|
||||
switch(category) {
|
||||
case category_t::convert: return create_convert(base, lc_, type);
|
||||
case category_t::collation: return create_collate(base, lc_, type);
|
||||
case category_t::formatting: return create_formatting(base, lc_, type);
|
||||
case category_t::parsing: return create_parsing(base, lc_, type);
|
||||
case category_t::codepage: return create_codecvt(base, nl_langinfo_l(CODESET, *lc_), type);
|
||||
case category_t::calendar: {
|
||||
util::locale_data inf;
|
||||
inf.parse(real_id_);
|
||||
return util::install_gregorian_calendar(base, inf.country());
|
||||
}
|
||||
case category_t::message: {
|
||||
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_t::nochar: break;
|
||||
case char_facet_t::char_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char>(minf));
|
||||
case char_facet_t::wchar_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<wchar_t>(minf));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char16_t>(minf));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char32_t>(minf));
|
||||
#endif
|
||||
}
|
||||
return base;
|
||||
}
|
||||
case category_t::information: return util::create_info(base, real_id_);
|
||||
case category_t::boundary: break; // Not implemented
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> paths_;
|
||||
std::vector<std::string> domains_;
|
||||
std::string locale_id_;
|
||||
std::string real_id_;
|
||||
|
||||
bool invalid_;
|
||||
std::shared_ptr<locale_t> lc_;
|
||||
};
|
||||
|
||||
localization_backend* create_localization_backend()
|
||||
{
|
||||
return new posix_localization_backend();
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_posix
|
||||
15
externals/boost/libs/locale/src/boost/locale/posix/posix_backend.hpp
vendored
Normal file
15
externals/boost/libs/locale/src/boost/locale/posix/posix_backend.hpp
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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();
|
||||
} // namespace impl_posix
|
||||
}} // namespace boost::locale
|
||||
#endif
|
||||
424
externals/boost/libs/locale/src/boost/locale/shared/date_time.cpp
vendored
Normal file
424
externals/boost/libs/locale/src/boost/locale/shared/date_time.cpp
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/date_time.hpp>
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
|
||||
using namespace period;
|
||||
|
||||
/////////////////////////
|
||||
// Calendar
|
||||
////////////////////////
|
||||
|
||||
calendar::calendar(const std::locale& l, const std::string& zone) :
|
||||
locale_(l), tz_(zone), impl_(std::use_facet<calendar_facet>(l).create_calendar())
|
||||
{
|
||||
impl_->set_timezone(tz_);
|
||||
}
|
||||
|
||||
calendar::calendar(const std::string& zone) :
|
||||
tz_(zone), impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
|
||||
{
|
||||
impl_->set_timezone(tz_);
|
||||
}
|
||||
|
||||
calendar::calendar(const std::locale& 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() = default;
|
||||
|
||||
calendar::calendar(const calendar& other) : locale_(other.locale_), tz_(other.tz_), impl_(other.impl_->clone()) {}
|
||||
|
||||
calendar& calendar::operator=(const calendar& 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==(const calendar& other) const
|
||||
{
|
||||
return impl_->same(other.impl_.get());
|
||||
}
|
||||
|
||||
bool calendar::operator!=(const calendar& 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(const date_time& other) : impl_(other.impl_->clone()) {}
|
||||
|
||||
date_time::date_time(const date_time& other, const date_time_period_set& 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& date_time::operator=(const date_time& other)
|
||||
{
|
||||
impl_.reset(other.impl_->clone());
|
||||
return *this;
|
||||
}
|
||||
|
||||
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, const calendar& cal) : impl_(cal.impl_->clone())
|
||||
{
|
||||
time(t);
|
||||
}
|
||||
|
||||
date_time::date_time(const calendar& cal) : impl_(cal.impl_->clone()) {}
|
||||
|
||||
date_time::date_time(const date_time_period_set& 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(const date_time_period_set& s, const calendar& 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& date_time::operator=(const date_time_period_set& 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+(const date_time_period& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp += v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator-(const date_time_period& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp -= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator<<(const date_time_period& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp <<= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator>>(const date_time_period& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp >>= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time& date_time::operator+=(const date_time_period& v)
|
||||
{
|
||||
impl_->adjust_value(v.type.mark(), abstract_calendar::move, v.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator-=(const date_time_period& v)
|
||||
{
|
||||
impl_->adjust_value(v.type.mark(), abstract_calendar::move, -v.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator<<=(const date_time_period& v)
|
||||
{
|
||||
impl_->adjust_value(v.type.mark(), abstract_calendar::roll, v.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator>>=(const date_time_period& v)
|
||||
{
|
||||
impl_->adjust_value(v.type.mark(), abstract_calendar::roll, -v.value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time date_time::operator+(const date_time_period_set& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp += v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator-(const date_time_period_set& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp -= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator<<(const date_time_period_set& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp <<= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time date_time::operator>>(const date_time_period_set& v) const
|
||||
{
|
||||
date_time tmp(*this);
|
||||
tmp >>= v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
date_time& date_time::operator+=(const date_time_period_set& v)
|
||||
{
|
||||
for(unsigned i = 0; i < v.size(); i++) {
|
||||
*this += v[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator-=(const date_time_period_set& v)
|
||||
{
|
||||
for(unsigned i = 0; i < v.size(); i++) {
|
||||
*this -= v[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator<<=(const date_time_period_set& v)
|
||||
{
|
||||
for(unsigned i = 0; i < v.size(); i++) {
|
||||
*this <<= v[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
date_time& date_time::operator>>=(const date_time_period_set& v)
|
||||
{
|
||||
for(unsigned i = 0; i < v.size(); i++) {
|
||||
*this >>= v[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
double date_time::time() const
|
||||
{
|
||||
return impl_->get_time_ms() / 1000.;
|
||||
}
|
||||
|
||||
void date_time::time(double v)
|
||||
{
|
||||
double seconds;
|
||||
const double fract_seconds = std::modf(v, &seconds); // v = seconds + fract_seconds
|
||||
posix_time ptime;
|
||||
ptime.seconds = static_cast<int64_t>(seconds);
|
||||
int64_t nano = static_cast<int64_t>(fract_seconds * 1e9);
|
||||
|
||||
constexpr int64_t ns_in_s = static_cast<int64_t>(1000) * 1000 * 1000;
|
||||
if(seconds < 0 && nano != 0) {
|
||||
assert(nano < 0); // Same sign
|
||||
seconds -= 1;
|
||||
nano = ns_in_s + nano;
|
||||
}
|
||||
if(nano < 0)
|
||||
nano = 0;
|
||||
else if(nano >= ns_in_s)
|
||||
nano = ns_in_s - 1;
|
||||
ptime.nanoseconds = static_cast<uint32_t>(nano);
|
||||
impl_->set_time(ptime);
|
||||
}
|
||||
|
||||
namespace {
|
||||
int compare(const posix_time& left, const posix_time& 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;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool date_time::operator==(const date_time& other) const
|
||||
{
|
||||
return compare(impl_->get_time(), other.impl_->get_time()) == 0;
|
||||
}
|
||||
|
||||
bool date_time::operator!=(const date_time& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool date_time::operator<(const date_time& other) const
|
||||
{
|
||||
return compare(impl_->get_time(), other.impl_->get_time()) < 0;
|
||||
}
|
||||
|
||||
bool date_time::operator>=(const date_time& other) const
|
||||
{
|
||||
return !(*this < other);
|
||||
}
|
||||
|
||||
bool date_time::operator>(const date_time& other) const
|
||||
{
|
||||
return compare(impl_->get_time(), other.impl_->get_time()) > 0;
|
||||
}
|
||||
|
||||
bool date_time::operator<=(const date_time& other) const
|
||||
{
|
||||
return !(*this > other);
|
||||
}
|
||||
|
||||
void date_time::swap(date_time& other)
|
||||
{
|
||||
impl_.swap(other.impl_);
|
||||
}
|
||||
|
||||
int date_time::difference(const date_time& 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(const std::string& new_id)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(tz_mutex());
|
||||
std::string id = tz_id();
|
||||
tz_id() = new_id;
|
||||
return id;
|
||||
}
|
||||
} // namespace time_zone
|
||||
|
||||
}} // namespace boost::locale
|
||||
166
externals/boost/libs/locale/src/boost/locale/shared/format.cpp
vendored
Normal file
166
externals/boost/libs/locale/src/boost/locale/shared/format.cpp
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/format.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/locale/info.hpp>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
namespace boost { namespace locale { namespace detail {
|
||||
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*, const std::locale&);
|
||||
};
|
||||
|
||||
format_parser::format_parser(std::ios_base& ios, void* cookie, void (*imbuer)(void*, const std::locale&)) :
|
||||
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(const std::locale& l)
|
||||
{
|
||||
d->imbuer(d->cookie, l);
|
||||
}
|
||||
|
||||
format_parser::~format_parser() = default;
|
||||
|
||||
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(const std::string& key, const std::string& 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(category_t::formatting);
|
||||
|
||||
std::locale new_loc;
|
||||
if(value.find('.') == std::string::npos)
|
||||
new_loc = gen(value + "." + encoding);
|
||||
else
|
||||
new_loc = gen(value);
|
||||
|
||||
imbue(new_loc);
|
||||
}
|
||||
}
|
||||
}}} // namespace boost::locale::detail
|
||||
// boostinspect:nominmax
|
||||
131
externals/boost/libs/locale/src/boost/locale/shared/formatting.cpp
vendored
Normal file
131
externals/boost/libs/locale/src/boost/locale/shared/formatting.cpp
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/date_time.hpp>
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include "boost/locale/shared/ios_prop.hpp"
|
||||
#include <algorithm>
|
||||
#include <typeinfo>
|
||||
|
||||
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(const string_set& 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& ios_info::string_set::operator=(string_set other)
|
||||
{
|
||||
swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ios_info::ios_info() : flags_(0), domain_id_(0), time_zone_(time_zone::global()) {}
|
||||
|
||||
ios_info::~ios_info() = default;
|
||||
|
||||
ios_info::ios_info(const ios_info&) = default;
|
||||
ios_info& ios_info::operator=(const ios_info&) = default;
|
||||
|
||||
void ios_info::display_flags(uint64_t f)
|
||||
{
|
||||
flags_ = (flags_ & ~uint64_t(flags::display_flags_mask)) | f;
|
||||
}
|
||||
uint64_t ios_info::display_flags() const
|
||||
{
|
||||
return flags_ & flags::display_flags_mask;
|
||||
}
|
||||
|
||||
void ios_info::currency_flags(uint64_t f)
|
||||
{
|
||||
flags_ = (flags_ & ~uint64_t(flags::currency_flags_mask)) | f;
|
||||
}
|
||||
uint64_t ios_info::currency_flags() const
|
||||
{
|
||||
return flags_ & flags::currency_flags_mask;
|
||||
}
|
||||
|
||||
void ios_info::date_flags(uint64_t f)
|
||||
{
|
||||
flags_ = (flags_ & ~uint64_t(flags::date_flags_mask)) | f;
|
||||
}
|
||||
uint64_t ios_info::date_flags() const
|
||||
{
|
||||
return flags_ & flags::date_flags_mask;
|
||||
}
|
||||
|
||||
void ios_info::time_flags(uint64_t f)
|
||||
{
|
||||
flags_ = (flags_ & ~uint64_t(flags::time_flags_mask)) | f;
|
||||
}
|
||||
uint64_t ios_info::time_flags() const
|
||||
{
|
||||
return flags_ & flags::time_flags_mask;
|
||||
}
|
||||
|
||||
void ios_info::domain_id(int id)
|
||||
{
|
||||
domain_id_ = id;
|
||||
}
|
||||
int ios_info::domain_id() const
|
||||
{
|
||||
return domain_id_;
|
||||
}
|
||||
|
||||
void ios_info::time_zone(const std::string& tz)
|
||||
{
|
||||
time_zone_ = tz;
|
||||
}
|
||||
std::string ios_info::time_zone() const
|
||||
{
|
||||
return time_zone_;
|
||||
}
|
||||
|
||||
const ios_info::string_set& 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
|
||||
|
||||
}} // namespace boost::locale
|
||||
192
externals/boost/libs/locale/src/boost/locale/shared/generator.cpp
vendored
Normal file
192
externals/boost/libs/locale/src/boost/locale/shared/generator.cpp
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
struct generator::data {
|
||||
data(const localization_backend_manager& 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;
|
||||
|
||||
category_t cats;
|
||||
char_facet_t 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(const localization_backend_manager& mgr) : d(new generator::data(mgr)) {}
|
||||
generator::generator() : d(new generator::data(localization_backend_manager::global())) {}
|
||||
generator::~generator() = default;
|
||||
|
||||
category_t generator::categories() const
|
||||
{
|
||||
return d->cats;
|
||||
}
|
||||
void generator::categories(category_t t)
|
||||
{
|
||||
d->cats = t;
|
||||
}
|
||||
|
||||
void generator::characters(char_facet_t t)
|
||||
{
|
||||
d->chars = t;
|
||||
}
|
||||
|
||||
char_facet_t generator::characters() const
|
||||
{
|
||||
return d->chars;
|
||||
}
|
||||
|
||||
void generator::add_messages_domain(const std::string& 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(const std::string& 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(const std::string& path)
|
||||
{
|
||||
d->paths.push_back(path);
|
||||
}
|
||||
void generator::clear_paths()
|
||||
{
|
||||
d->paths.clear();
|
||||
}
|
||||
void generator::clear_cache()
|
||||
{
|
||||
d->cached.clear();
|
||||
}
|
||||
|
||||
std::locale generator::generate(const std::string& id) const
|
||||
{
|
||||
std::locale base = std::locale::classic();
|
||||
|
||||
return generate(base, id);
|
||||
}
|
||||
|
||||
std::locale generator::generate(const std::locale& base, const std::string& 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;
|
||||
}
|
||||
}
|
||||
hold_ptr<localization_backend> backend(d->backend_manager.create());
|
||||
set_all_options(*backend, id);
|
||||
|
||||
std::locale result = base;
|
||||
category_t facets = d->cats;
|
||||
char_facet_t chars = d->chars;
|
||||
|
||||
for(category_t facet = per_character_facet_first; facet <= per_character_facet_last; ++facet) {
|
||||
if(!(facets & facet))
|
||||
continue;
|
||||
for(char_facet_t ch = character_facet_first; ch <= character_facet_last; ++ch) {
|
||||
if(ch & chars)
|
||||
result = backend->install(result, facet, ch);
|
||||
}
|
||||
}
|
||||
for(category_t facet = non_character_facet_first; facet <= non_character_facet_last; ++facet) {
|
||||
if(facets & facet)
|
||||
result = backend->install(result, facet, char_facet_t::nochar);
|
||||
}
|
||||
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(localization_backend& backend, const std::string& 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]);
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
|
||||
static_assert((char_facet_t::char_f | char_facet_t::wchar_f) & char_facet_t::char_f, "!");
|
||||
static_assert((char_facet_t::char_f | char_facet_t::wchar_f) & char_facet_t::wchar_f, "!");
|
||||
static_assert(!((all_characters ^ char_facet_t::wchar_f) & char_facet_t::wchar_f), "!");
|
||||
|
||||
static_assert((category_t::calendar | category_t::convert) & category_t::calendar, "!");
|
||||
static_assert((category_t::calendar | category_t::convert) & category_t::convert, "!");
|
||||
static_assert(!((all_categories ^ category_t::calendar) & category_t::calendar), "!");
|
||||
|
||||
#ifndef BOOST_NO_CXX14_CONSTEXPR
|
||||
template<typename T>
|
||||
constexpr T inc_enum(T v)
|
||||
{
|
||||
return ++v;
|
||||
}
|
||||
static_assert(inc_enum(char_facet_t::nochar) == char_facet_t::char_f, "!");
|
||||
static_assert(inc_enum(char_facet_t::char_f) == char_facet_t::wchar_f, "!");
|
||||
static_assert(inc_enum(category_t::convert) == category_t::collation, "!");
|
||||
#endif
|
||||
|
||||
}} // namespace boost::locale
|
||||
179
externals/boost/libs/locale/src/boost/locale/shared/iconv_codecvt.cpp
vendored
Normal file
179
externals/boost/libs/locale/src/boost/locale/shared/iconv_codecvt.cpp
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022-2023 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "iconv_codecvt.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#ifdef BOOST_LOCALE_WITH_ICONV
|
||||
# include "boost/locale/util/iconv.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale {
|
||||
|
||||
#ifdef BOOST_LOCALE_WITH_ICONV
|
||||
static const char* utf32_encoding()
|
||||
{
|
||||
union {
|
||||
char one;
|
||||
uint32_t value;
|
||||
} test;
|
||||
test.value = 1;
|
||||
return (test.one == 1) ? "UTF-32LE" : "UTF-32BE";
|
||||
}
|
||||
|
||||
class mb2_iconv_converter : public util::base_converter {
|
||||
public:
|
||||
mb2_iconv_converter(const std::string& encoding) : encoding_(encoding)
|
||||
{
|
||||
iconv_handle d = iconv_open(utf32_encoding(), encoding.c_str());
|
||||
if(!d)
|
||||
throw std::runtime_error("Unsupported encoding" + encoding);
|
||||
|
||||
for(unsigned c = 0; c < first_byte_table_.size(); c++) {
|
||||
const char ibuf[2] = {char(c), 0};
|
||||
size_t insize = sizeof(ibuf);
|
||||
uint32_t obuf[2] = {illegal, illegal};
|
||||
size_t outsize = sizeof(obuf);
|
||||
// Basic single codepoint conversion
|
||||
call_iconv(d, ibuf, &insize, reinterpret_cast<char*>(obuf), &outsize);
|
||||
if(insize == 0 && outsize == 0 && obuf[1] == 0)
|
||||
first_byte_table_[c] = obuf[0];
|
||||
else {
|
||||
// Test if this is illegal first byte or incomplete
|
||||
insize = 1;
|
||||
outsize = sizeof(obuf);
|
||||
call_iconv(d, nullptr, nullptr, nullptr, nullptr);
|
||||
size_t res = call_iconv(d, ibuf, &insize, reinterpret_cast<char*>(obuf), &outsize);
|
||||
|
||||
// Now if this single byte starts a sequence we add incomplete
|
||||
// to know to ask that we need two bytes, otherwise it may only be illegal
|
||||
|
||||
first_byte_table_[c] = (res == size_t(-1) && errno == EINVAL) ? incomplete : illegal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mb2_iconv_converter(const mb2_iconv_converter& other) :
|
||||
first_byte_table_(other.first_byte_table_), encoding_(other.encoding_)
|
||||
{}
|
||||
|
||||
bool is_thread_safe() const override { return false; }
|
||||
|
||||
mb2_iconv_converter* clone() const override { return new mb2_iconv_converter(*this); }
|
||||
|
||||
uint32_t to_unicode(const char*& begin, const char* end) override
|
||||
{
|
||||
if(begin == end)
|
||||
return incomplete;
|
||||
|
||||
const unsigned char seq0 = *begin;
|
||||
|
||||
# if defined(BOOST_GCC_VERSION) && BOOST_GCC_VERSION >= 40600
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wtype-limits"
|
||||
# endif
|
||||
static_assert(std::numeric_limits<unsigned char>::max()
|
||||
< std::tuple_size<decltype(first_byte_table_)>::value,
|
||||
"Wrong table size");
|
||||
# if defined(BOOST_GCC_VERSION) && BOOST_GCC_VERSION >= 40600
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
|
||||
const 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
|
||||
|
||||
const char inseq[3] = {static_cast<char>(seq0), begin[1], 0};
|
||||
size_t insize = sizeof(inseq);
|
||||
uint32_t result[2] = {illegal, illegal};
|
||||
size_t outsize = sizeof(result);
|
||||
call_iconv(to_utf_, inseq, &insize, reinterpret_cast<char*>(result), &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, const char* end) override
|
||||
{
|
||||
if(cp == 0) {
|
||||
if(begin != end) {
|
||||
*begin = 0;
|
||||
return 1;
|
||||
} else {
|
||||
return incomplete;
|
||||
}
|
||||
}
|
||||
|
||||
open(from_utf_, encoding_.c_str(), utf32_encoding());
|
||||
|
||||
const uint32_t inbuf[2] = {cp, 0};
|
||||
size_t insize = sizeof(inbuf);
|
||||
char outseq[3] = {0};
|
||||
size_t outsize = 3;
|
||||
|
||||
call_iconv(from_utf_, reinterpret_cast<const char*>(inbuf), &insize, outseq, &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 static_cast<uint32_t>(len);
|
||||
}
|
||||
|
||||
int max_len() const override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<uint32_t, 256> first_byte_table_;
|
||||
std::string encoding_;
|
||||
iconv_handle to_utf_, from_utf_;
|
||||
|
||||
static void open(iconv_handle& d, const char* to, const char* from)
|
||||
{
|
||||
if(!d)
|
||||
d = iconv_open(to, from);
|
||||
BOOST_ASSERT(d);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<util::base_converter> create_iconv_converter(const std::string& encoding)
|
||||
{
|
||||
try {
|
||||
return std::unique_ptr<util::base_converter>(new mb2_iconv_converter(encoding));
|
||||
} catch(const std::exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#else // no iconv
|
||||
std::unique_ptr<util::base_converter> create_iconv_converter(const std::string& /*encoding*/)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
}} // namespace boost::locale
|
||||
20
externals/boost/libs/locale/src/boost/locale/shared/iconv_codecvt.hpp
vendored
Normal file
20
externals/boost/libs/locale/src/boost/locale/shared/iconv_codecvt.hpp
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_ICONV_CODECVT_HPP
|
||||
#define BOOST_LOCALE_ICONV_CODECVT_HPP
|
||||
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
BOOST_LOCALE_DECL
|
||||
std::unique_ptr<util::base_converter> create_iconv_converter(const std::string& encoding);
|
||||
|
||||
}} // namespace boost::locale
|
||||
|
||||
#endif
|
||||
108
externals/boost/libs/locale/src/boost/locale/shared/ids.cpp
vendored
Normal file
108
externals/boost/libs/locale/src/boost/locale/shared/ids.cpp
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#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/info.hpp>
|
||||
#include <boost/locale/message.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
|
||||
std::locale::id info::id;
|
||||
// Make sure we have the VTable here (Export/Import issues)
|
||||
info::~info() = default;
|
||||
|
||||
std::locale::id calendar_facet::id;
|
||||
calendar_facet::~calendar_facet() = default;
|
||||
|
||||
abstract_calendar::~abstract_calendar() = default;
|
||||
|
||||
std::locale::id converter<char>::id;
|
||||
converter<char>::~converter() = default;
|
||||
std::locale::id base_message_format<char>::id;
|
||||
base_message_format<char>::~base_message_format() = default;
|
||||
|
||||
std::locale::id converter<wchar_t>::id;
|
||||
converter<wchar_t>::~converter() = default;
|
||||
std::locale::id base_message_format<wchar_t>::id;
|
||||
base_message_format<wchar_t>::~base_message_format() = default;
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
|
||||
std::locale::id converter<char16_t>::id;
|
||||
converter<char16_t>::~converter() = default;
|
||||
std::locale::id base_message_format<char16_t>::id;
|
||||
base_message_format<char16_t>::~base_message_format() = default;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
|
||||
std::locale::id converter<char32_t>::id;
|
||||
converter<char32_t>::~converter() = default;
|
||||
std::locale::id base_message_format<char32_t>::id;
|
||||
base_message_format<char32_t>::~base_message_format() = default;
|
||||
|
||||
#endif
|
||||
|
||||
namespace boundary {
|
||||
|
||||
std::locale::id boundary_indexing<char>::id;
|
||||
boundary_indexing<char>::~boundary_indexing() = default;
|
||||
|
||||
std::locale::id boundary_indexing<wchar_t>::id;
|
||||
boundary_indexing<wchar_t>::~boundary_indexing() = default;
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
std::locale::id boundary_indexing<char16_t>::id;
|
||||
boundary_indexing<char16_t>::~boundary_indexing() = default;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
std::locale::id boundary_indexing<char32_t>::id;
|
||||
boundary_indexing<char32_t>::~boundary_indexing() = default;
|
||||
#endif
|
||||
} // namespace boundary
|
||||
|
||||
namespace {
|
||||
// Initialize each facet once to avoid issues where doing so
|
||||
// in a multithreaded environment could cause problems (races)
|
||||
struct init_all {
|
||||
init_all()
|
||||
{
|
||||
const std::locale& l = std::locale::classic();
|
||||
init_by<char>(l);
|
||||
init_by<wchar_t>(l);
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
init_by<char16_t>(l);
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
init_by<char32_t>(l);
|
||||
#endif
|
||||
|
||||
init_facet<info>(l);
|
||||
init_facet<calendar_facet>(l);
|
||||
}
|
||||
template<typename Char>
|
||||
void init_by(const std::locale& l)
|
||||
{
|
||||
init_facet<boundary::boundary_indexing<Char>>(l);
|
||||
init_facet<converter<Char>>(l);
|
||||
init_facet<message_format<Char>>(l);
|
||||
}
|
||||
template<typename Facet>
|
||||
void init_facet(const std::locale& l)
|
||||
{
|
||||
// Use the facet to initialize e.g. their std::locale::id
|
||||
ignore_unused(std::has_facet<Facet>(l));
|
||||
}
|
||||
} facet_initializer;
|
||||
} // namespace
|
||||
|
||||
}} // namespace boost::locale
|
||||
65
externals/boost/libs/locale/src/boost/locale/shared/ios_prop.hpp
vendored
Normal file
65
externals/boost/libs/locale/src/boost/locale/shared/ios_prop.hpp
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_SRC_LOCALE_IOS_PROP_HPP
|
||||
#define BOOST_SRC_LOCALE_IOS_PROP_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <ios>
|
||||
|
||||
namespace boost { namespace locale { namespace impl {
|
||||
|
||||
template<typename Property>
|
||||
class BOOST_SYMBOL_VISIBLE ios_prop {
|
||||
public:
|
||||
static Property& get(std::ios_base& ios)
|
||||
{
|
||||
Property* result = get_impl(ios);
|
||||
return result ? *result : create(ios);
|
||||
}
|
||||
|
||||
static void global_init() { get_id(); }
|
||||
|
||||
private:
|
||||
static Property* get_impl(std::ios_base& ios) { return static_cast<Property*>(ios.pword(get_id())); }
|
||||
|
||||
static Property& create(std::ios_base& ios)
|
||||
{
|
||||
BOOST_ASSERT_MSG(!get_impl(ios), "Called create while the property already exists");
|
||||
const int id = get_id();
|
||||
ios.register_callback(callback, id);
|
||||
Property* value = new Property();
|
||||
ios.pword(id) = value;
|
||||
return *value;
|
||||
}
|
||||
|
||||
static void callback(std::ios_base::event ev, std::ios_base& ios, int id)
|
||||
{
|
||||
Property* prop = get_impl(ios);
|
||||
if(!prop)
|
||||
return;
|
||||
switch(ev) {
|
||||
case std::ios_base::erase_event:
|
||||
delete prop;
|
||||
ios.pword(id) = nullptr;
|
||||
break;
|
||||
case std::ios_base::copyfmt_event: ios.pword(id) = new Property(*prop); break;
|
||||
case std::ios_base::imbue_event: prop->on_imbue(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
static int get_id()
|
||||
{
|
||||
static int id = std::ios_base::xalloc();
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::locale::impl
|
||||
|
||||
#endif
|
||||
249
externals/boost/libs/locale/src/boost/locale/shared/localization_backend.cpp
vendored
Normal file
249
externals/boost/libs/locale/src/boost/locale/shared/localization_backend.cpp
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include <boost/locale/localization_backend.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#ifdef BOOST_LOCALE_WITH_ICU
|
||||
# include "boost/locale/icu/icu_backend.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LOCALE_NO_POSIX_BACKEND
|
||||
# include "boost/locale/posix/posix_backend.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LOCALE_NO_STD_BACKEND
|
||||
# include "boost/locale/std/std_backend.hpp"
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_LOCALE_NO_WINAPI_BACKEND
|
||||
# include "boost/locale/win32/win_backend.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale {
|
||||
localization_backend::~localization_backend() = default;
|
||||
|
||||
class localization_backend_manager::impl {
|
||||
public:
|
||||
impl(const impl& 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) {}
|
||||
|
||||
impl& operator=(const impl&) = delete;
|
||||
|
||||
localization_backend* create() const
|
||||
{
|
||||
std::vector<std::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(const std::string& name, localization_backend* backend_ptr)
|
||||
{
|
||||
std::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(const std::string& backend_name, category_t 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;
|
||||
category_t flag = category_first;
|
||||
for(unsigned i = 0; i < default_backends_.size(); ++flag, ++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(const std::vector<std::shared_ptr<localization_backend>>& backends,
|
||||
const std::vector<int>& index) :
|
||||
index_(index)
|
||||
{
|
||||
backends_.resize(backends.size());
|
||||
for(unsigned i = 0; i < backends.size(); i++) {
|
||||
backends_[i].reset(backends[i]->clone());
|
||||
}
|
||||
}
|
||||
actual_backend* clone() const override { return new actual_backend(backends_, index_); }
|
||||
void set_option(const std::string& name, const std::string& value) override
|
||||
{
|
||||
for(unsigned i = 0; i < backends_.size(); i++)
|
||||
backends_[i]->set_option(name, value);
|
||||
}
|
||||
void clear_options() override
|
||||
{
|
||||
for(unsigned i = 0; i < backends_.size(); i++)
|
||||
backends_[i]->clear_options();
|
||||
}
|
||||
std::locale install(const std::locale& l, category_t category, char_facet_t type) override
|
||||
{
|
||||
unsigned id = 0;
|
||||
for(category_t v = category_first; v != category; ++v, ++id) {
|
||||
if(v == category_last)
|
||||
return l;
|
||||
}
|
||||
if(id >= index_.size() || index_[id] == -1)
|
||||
return l;
|
||||
return backends_[index_[id]]->install(l, category, type);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<localization_backend>> backends_;
|
||||
std::vector<int> index_;
|
||||
};
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::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() = default;
|
||||
|
||||
localization_backend_manager::localization_backend_manager(const localization_backend_manager& other) :
|
||||
pimpl_(new impl(*other.pimpl_))
|
||||
{}
|
||||
|
||||
localization_backend_manager& localization_backend_manager::operator=(const localization_backend_manager& other)
|
||||
{
|
||||
pimpl_.reset(new impl(*other.pimpl_));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<localization_backend> localization_backend_manager::get() const
|
||||
{
|
||||
return std::unique_ptr<localization_backend>(pimpl_->create());
|
||||
}
|
||||
void localization_backend_manager::add_backend(const std::string& name,
|
||||
std::unique_ptr<localization_backend> backend)
|
||||
{
|
||||
pimpl_->adopt_backend(name, backend.release());
|
||||
}
|
||||
|
||||
localization_backend* localization_backend_manager::create() const
|
||||
{
|
||||
return pimpl_->create();
|
||||
}
|
||||
void localization_backend_manager::adopt_backend(const std::string& 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(const std::string& backend_name, category_t 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;
|
||||
} // namespace
|
||||
|
||||
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(const localization_backend_manager& 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;
|
||||
}
|
||||
|
||||
}} // namespace boost::locale
|
||||
678
externals/boost/libs/locale/src/boost/locale/shared/message.cpp
vendored
Normal file
678
externals/boost/libs/locale/src/boost/locale/shared/message.cpp
vendored
Normal file
@@ -0,0 +1,678 @@
|
||||
//
|
||||
// Copyright (c) 2009-2015 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define BOOST_DETAIL_NO_CONTAINER_FWD
|
||||
|
||||
// Need _wfopen which is an extension on MinGW but not on MinGW-w64
|
||||
// So remove the strict-mode define on (only) MinGW before including anything
|
||||
#if defined(__MINGW32__) && defined(__STRICT_ANSI__)
|
||||
# include <_mingw.h>
|
||||
# ifndef __MINGW64_VERSION_MAJOR
|
||||
# undef __STRICT_ANSI__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/gnu_gettext.hpp>
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include <boost/locale/message.hpp>
|
||||
#include "boost/locale/shared/mo_hash.hpp"
|
||||
#include "boost/locale/shared/mo_lambda.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include <boost/version.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace locale { namespace gnu_gettext {
|
||||
|
||||
class c_file {
|
||||
c_file(const c_file&);
|
||||
void operator=(const c_file&);
|
||||
|
||||
public:
|
||||
FILE* file;
|
||||
|
||||
c_file() : file(0) {}
|
||||
~c_file() { close(); }
|
||||
|
||||
void close()
|
||||
{
|
||||
if(file) {
|
||||
fclose(file);
|
||||
file = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
|
||||
bool open(const std::string& file_name, const std::string& 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(const std::string& file_name, const std::string& /* encoding */)
|
||||
{
|
||||
close();
|
||||
|
||||
file = fopen(file_name.c_str(), "rb");
|
||||
|
||||
return file != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
class mo_file {
|
||||
public:
|
||||
typedef std::pair<const char*, const char*> 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(const char* context_in, const char* key_in) const
|
||||
{
|
||||
pair_type null_pair((const char*)0, (const char*)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(const char* real_key, const char* cntx, const char* 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;
|
||||
}
|
||||
}
|
||||
|
||||
const char* 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 ignore 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_;
|
||||
|
||||
const char* data_;
|
||||
size_t file_size_;
|
||||
std::vector<char> vdata_;
|
||||
bool native_byteorder_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
struct mo_file_use_traits {
|
||||
static constexpr bool in_use = false;
|
||||
typedef CharType char_type;
|
||||
typedef std::pair<const char_type*, const char_type*> pair_type;
|
||||
static pair_type use(const mo_file& /*mo*/, const char_type* /*context*/, const char_type* /*key*/)
|
||||
{
|
||||
return pair_type((const char_type*)(0), (const char_type*)(0));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct mo_file_use_traits<char> {
|
||||
static constexpr bool in_use = true;
|
||||
typedef char char_type;
|
||||
typedef std::pair<const char_type*, const char_type*> pair_type;
|
||||
static pair_type use(const mo_file& mo, const char* context, const char* 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()(const char* begin, const char* 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()(const char* begin, const char* 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(const string_type& 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(const char_type* c, const char_type* k) : c_key_(k)
|
||||
{
|
||||
static const char_type empty = 0;
|
||||
if(c != 0)
|
||||
c_context_ = c;
|
||||
else
|
||||
c_context_ = ∅
|
||||
}
|
||||
bool operator<(const message_key& other) const
|
||||
{
|
||||
int cc = compare(context(), other.context());
|
||||
if(cc != 0)
|
||||
return cc < 0;
|
||||
return compare(key(), other.key()) < 0;
|
||||
}
|
||||
bool operator==(const message_key& other) const
|
||||
{
|
||||
return compare(context(), other.context()) == 0 && compare(key(), other.key()) == 0;
|
||||
}
|
||||
bool operator!=(const message_key& other) const { return !(*this == other); }
|
||||
const char_type* context() const
|
||||
{
|
||||
if(c_context_)
|
||||
return c_context_;
|
||||
return context_.c_str();
|
||||
}
|
||||
const char_type* key() const
|
||||
{
|
||||
if(c_key_)
|
||||
return c_key_;
|
||||
return key_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
static int compare(const char_type* l, const char_type* 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_;
|
||||
const char_type* c_context_;
|
||||
const char_type* c_key_;
|
||||
};
|
||||
|
||||
template<typename CharType>
|
||||
struct hash_function {
|
||||
size_t operator()(const message_key<CharType>& msg) const
|
||||
{
|
||||
pj_winberger_hash::state_type state = pj_winberger_hash::initial_state;
|
||||
const CharType* p = msg.context();
|
||||
if(*p != 0) {
|
||||
const CharType* e = util::str_end(p);
|
||||
state = pj_winberger_hash::update_state(state,
|
||||
reinterpret_cast<const char*>(p),
|
||||
reinterpret_cast<const char*>(e));
|
||||
state = pj_winberger_hash::update_state(state, '\4');
|
||||
}
|
||||
p = msg.key();
|
||||
const CharType* e = util::str_end(p);
|
||||
state = pj_winberger_hash::update_state(state,
|
||||
reinterpret_cast<const char*>(p),
|
||||
reinterpret_cast<const char*>(e));
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// By default for wide types the conversion is not required
|
||||
template<typename CharType>
|
||||
const CharType* runtime_conversion(const CharType* msg,
|
||||
std::basic_string<CharType>& /*buffer*/,
|
||||
bool /*do_conversion*/,
|
||||
const std::string& /*locale_encoding*/,
|
||||
const std::string& /*key_encoding*/)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
|
||||
// But still need to specialize for char
|
||||
template<>
|
||||
const char* runtime_conversion(const char* msg,
|
||||
std::string& buffer,
|
||||
bool do_conversion,
|
||||
const std::string& locale_encoding,
|
||||
const std::string& key_encoding)
|
||||
{
|
||||
if(!do_conversion)
|
||||
return msg;
|
||||
if(detail::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;
|
||||
typedef std::unordered_map<key_type, string_type, hash_function<CharType>> catalog_type;
|
||||
typedef std::vector<catalog_type> catalogs_set_type;
|
||||
typedef std::map<std::string, int> domains_map_type;
|
||||
|
||||
public:
|
||||
typedef std::pair<const CharType*, const CharType*> pair_type;
|
||||
|
||||
const char_type* get(int domain_id, const char_type* context, const char_type* in_id) const override
|
||||
{
|
||||
return get_string(domain_id, context, in_id).first;
|
||||
}
|
||||
|
||||
const char_type* get(int domain_id, const char_type* context, const char_type* single_id, int n) const override
|
||||
{
|
||||
pair_type ptr = get_string(domain_id, context, single_id);
|
||||
if(!ptr.first)
|
||||
return nullptr;
|
||||
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
|
||||
|
||||
const CharType* p = ptr.first;
|
||||
for(int i = 0; p < ptr.second && i < form; i++) {
|
||||
p = std::find(p, ptr.second, CharType(0));
|
||||
if(p == ptr.second)
|
||||
return nullptr;
|
||||
++p;
|
||||
}
|
||||
if(p >= ptr.second)
|
||||
return nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
int domain(const std::string& domain) const override
|
||||
{
|
||||
domains_map_type::const_iterator p = domains_.find(domain);
|
||||
if(p == domains_.end())
|
||||
return -1;
|
||||
return p->second;
|
||||
}
|
||||
|
||||
mo_message(const messages_info& inf) : key_conversion_required_(false)
|
||||
{
|
||||
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;
|
||||
const std::vector<messages_info::domain>& domains = inf.domains;
|
||||
const std::vector<std::string>& 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 i = 0; i < domains.size(); i++) {
|
||||
std::string domain = domains[i].name;
|
||||
std::string key_encoding = domains[i].encoding;
|
||||
domains_[domain] = i;
|
||||
|
||||
bool found = false;
|
||||
for(unsigned j = 0; !found && j < paths.size(); j++) {
|
||||
for(unsigned k = 0; !found && k < search_paths.size(); k++) {
|
||||
std::string full_path = search_paths[k] + "/" + paths[j] + "/" + lc_cat + "/" + domain + ".mo";
|
||||
found = load_file(full_path, encoding, key_encoding, i, inf.callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char_type* convert(const char_type* msg, string_type& buffer) const override
|
||||
{
|
||||
return runtime_conversion<char_type>(msg,
|
||||
buffer,
|
||||
key_conversion_required_,
|
||||
locale_encoding_,
|
||||
key_encoding_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool load_file(const std::string& file_name,
|
||||
const std::string& locale_encoding,
|
||||
const std::string& key_encoding,
|
||||
int idx,
|
||||
const messages_info::callback_type& callback)
|
||||
{
|
||||
locale_encoding_ = locale_encoding;
|
||||
key_encoding_ = key_encoding;
|
||||
|
||||
key_conversion_required_ =
|
||||
sizeof(CharType) == 1 && !util::are_encodings_equal(locale_encoding, key_encoding);
|
||||
|
||||
std::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_[idx] = lambda::compile(plural.c_str());
|
||||
|
||||
if(mo_useable_directly(mo_encoding, *mo))
|
||||
mo_catalogs_[idx] = 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++) {
|
||||
const char* 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_[idx][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(const std::string& mo_encoding, const mo_file& mo)
|
||||
{
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
if(sizeof(CharType) != 1)
|
||||
return false;
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
if(!mo.has_hash())
|
||||
return false;
|
||||
if(!util::are_encodings_equal(mo_encoding, locale_encoding_))
|
||||
return false;
|
||||
if(util::are_encodings_equal(mo_encoding, key_encoding_)) {
|
||||
return true;
|
||||
}
|
||||
for(unsigned i = 0; i < mo.size(); i++) {
|
||||
if(!detail::is_us_ascii_string(mo.key(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string extract(const std::string& meta, const std::string& key, const char* 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, const char_type* context, const char_type* in_id) const
|
||||
{
|
||||
pair_type null_pair((const CharType*)0, (const CharType*)0);
|
||||
if(domain_id < 0 || size_t(domain_id) >= catalogs_.size())
|
||||
return null_pair;
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
if(mo_file_use_traits<char_type>::in_use && mo_catalogs_[domain_id]) {
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
return mo_file_use_traits<char_type>::use(*mo_catalogs_[domain_id], context, in_id);
|
||||
} else {
|
||||
key_type key(context, in_id);
|
||||
const catalog_type& 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<std::shared_ptr<mo_file>> mo_catalogs_;
|
||||
std::vector<std::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(const messages_info& info)
|
||||
{
|
||||
return new mo_message<char>(info);
|
||||
}
|
||||
|
||||
template<>
|
||||
message_format<wchar_t>* create_messages_facet(const messages_info& info)
|
||||
{
|
||||
return new mo_message<wchar_t>(info);
|
||||
}
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
|
||||
template<>
|
||||
message_format<char16_t>* create_messages_facet(const messages_info& info)
|
||||
{
|
||||
return new mo_message<char16_t>(info);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
|
||||
template<>
|
||||
message_format<char32_t>* create_messages_facet(const messages_info& info)
|
||||
{
|
||||
return new mo_message<char32_t>(info);
|
||||
}
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::locale::gnu_gettext
|
||||
51
externals/boost/libs/locale/src/boost/locale/shared/mo_hash.hpp
vendored
Normal file
51
externals/boost/libs/locale/src/boost/locale/shared/mo_hash.hpp
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 constexpr 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, const char* ptr)
|
||||
{
|
||||
while(*ptr)
|
||||
value = update_state(value, *ptr++);
|
||||
return value;
|
||||
}
|
||||
static state_type update_state(state_type value, const char* begin, const char* end)
|
||||
{
|
||||
while(begin != end)
|
||||
value = update_state(value, *begin++);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
inline pj_winberger_hash::state_type pj_winberger_hash_function(const char* 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(const char* begin, const char* end)
|
||||
{
|
||||
pj_winberger_hash::state_type state = pj_winberger_hash::initial_state;
|
||||
state = pj_winberger_hash::update_state(state, begin, end);
|
||||
return state;
|
||||
}
|
||||
}}} // namespace boost::locale::gnu_gettext
|
||||
373
externals/boost/libs/locale/src/boost/locale/shared/mo_lambda.cpp
vendored
Normal file
373
externals/boost/libs/locale/src/boost/locale/shared/mo_lambda.cpp
vendored
Normal file
@@ -0,0 +1,373 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/shared/mo_lambda.hpp"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace gnu_gettext { namespace lambda {
|
||||
|
||||
namespace { // anon
|
||||
struct identity : public plural {
|
||||
int operator()(int n) const override { return n; };
|
||||
identity* clone() const override { 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) {}
|
||||
int operator()(int /*n*/) const override { return val; }
|
||||
number* clone() const override { return new number(val); }
|
||||
|
||||
private:
|
||||
int val;
|
||||
};
|
||||
|
||||
#define UNOP(name, oper) \
|
||||
struct name : public unary { \
|
||||
name(plural_ptr op) : unary(op) {} \
|
||||
int operator()(int n) const override { return oper(*op1)(n); } \
|
||||
name* clone() const override \
|
||||
{ \
|
||||
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) {} \
|
||||
\
|
||||
int operator()(int n) const override { return (*op1)(n)oper(*op2)(n); } \
|
||||
name* clone() const override \
|
||||
{ \
|
||||
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) {} \
|
||||
int operator()(int n) const override \
|
||||
{ \
|
||||
int v1 = (*op1)(n); \
|
||||
int v2 = (*op2)(n); \
|
||||
return v2 == 0 ? 0 : v1 oper v2; \
|
||||
} \
|
||||
name* clone() const override \
|
||||
{ \
|
||||
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) {}
|
||||
int operator()(int n) const override { return (*op1)(n) ? (*op2)(n) : (*op3)(n); }
|
||||
conditional* clone() const override
|
||||
{
|
||||
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(const char* 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:
|
||||
const char* text;
|
||||
size_t 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++;
|
||||
const char* 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
|
||||
|
||||
plural_ptr compile(const char* str)
|
||||
{
|
||||
tokenizer t(str);
|
||||
parser p(t);
|
||||
return p.compile();
|
||||
}
|
||||
|
||||
}}}} // namespace boost::locale::gnu_gettext::lambda
|
||||
27
externals/boost/libs/locale/src/boost/locale/shared/mo_lambda.hpp
vendored
Normal file
27
externals/boost/libs/locale/src/boost/locale/shared/mo_lambda.hpp
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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/locale/config.hpp>
|
||||
#include <memory>
|
||||
|
||||
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() = default;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<plural> plural_ptr;
|
||||
|
||||
plural_ptr compile(const char* c_expression);
|
||||
|
||||
}}}} // namespace boost::locale::gnu_gettext::lambda
|
||||
|
||||
#endif
|
||||
44
externals/boost/libs/locale/src/boost/locale/std/all_generator.hpp
vendored
Normal file
44
externals/boost/libs/locale/src/boost/locale/std/all_generator.hpp
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 <locale>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_std {
|
||||
enum class utf8_support { none, native, native_with_wide, from_wide };
|
||||
|
||||
std::locale create_convert(const std::locale& in,
|
||||
const std::string& locale_name,
|
||||
char_facet_t type,
|
||||
utf8_support utf = utf8_support::none);
|
||||
|
||||
std::locale create_collate(const std::locale& in,
|
||||
const std::string& locale_name,
|
||||
char_facet_t type,
|
||||
utf8_support utf = utf8_support::none);
|
||||
|
||||
std::locale create_formatting(const std::locale& in,
|
||||
const std::string& locale_name,
|
||||
char_facet_t type,
|
||||
utf8_support utf = utf8_support::none);
|
||||
|
||||
std::locale create_parsing(const std::locale& in,
|
||||
const std::string& locale_name,
|
||||
char_facet_t type,
|
||||
utf8_support utf = utf8_support::none);
|
||||
|
||||
std::locale create_codecvt(const std::locale& in,
|
||||
const std::string& locale_name,
|
||||
char_facet_t type,
|
||||
utf8_support utf = utf8_support::none);
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
|
||||
#endif
|
||||
38
externals/boost/libs/locale/src/boost/locale/std/codecvt.cpp
vendored
Normal file
38
externals/boost/libs/locale/src/boost/locale/std/codecvt.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/util.hpp>
|
||||
#include "boost/locale/std/all_generator.hpp"
|
||||
#include <locale>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_std {
|
||||
template<typename CharType>
|
||||
std::locale codecvt_bychar(const std::locale& in, const std::string& locale_name)
|
||||
{
|
||||
return std::locale(in, new std::codecvt_byname<CharType, char, std::mbstate_t>(locale_name.c_str()));
|
||||
}
|
||||
|
||||
std::locale
|
||||
create_codecvt(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
|
||||
{
|
||||
if(utf == utf8_support::from_wide)
|
||||
return util::create_utf8_codecvt(in, type);
|
||||
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return codecvt_bychar<char>(in, locale_name);
|
||||
case char_facet_t::wchar_f: return codecvt_bychar<wchar_t>(in, locale_name);
|
||||
#if defined(BOOST_LOCALE_ENABLE_CHAR16_T)
|
||||
case char_facet_t::char16_f: return codecvt_bychar<char16_t>(in, locale_name);
|
||||
#endif
|
||||
#if defined(BOOST_LOCALE_ENABLE_CHAR32_T)
|
||||
case char_facet_t::char32_f: return codecvt_bychar<char32_t>(in, locale_name);
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
92
externals/boost/libs/locale/src/boost/locale/std/collate.cpp
vendored
Normal file
92
externals/boost/libs/locale/src/boost/locale/std/collate.cpp
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include "boost/locale/std/all_generator.hpp"
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
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(const std::locale& base, size_t refs = 0) : std::collate<char>(refs), base_(base) {}
|
||||
int do_compare(const char* lb, const char* le, const char* rb, const char* re) const override
|
||||
{
|
||||
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());
|
||||
}
|
||||
long do_hash(const char* b, const char* e) const override
|
||||
{
|
||||
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());
|
||||
}
|
||||
std::string do_transform(const char* b, const char* e) const override
|
||||
{
|
||||
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;
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
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);
|
||||
}
|
||||
}
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
return key;
|
||||
}
|
||||
|
||||
private:
|
||||
std::locale base_;
|
||||
};
|
||||
|
||||
std::locale
|
||||
create_collate(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: {
|
||||
if(utf == utf8_support::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 char_facet_t::wchar_f: return std::locale(in, new std::collate_byname<wchar_t>(locale_name.c_str()));
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new std::collate_byname<char16_t>(locale_name.c_str()));
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new std::collate_byname<char32_t>(locale_name.c_str()));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
124
externals/boost/libs/locale/src/boost/locale/std/converter.cpp
vendored
Normal file
124
externals/boost/libs/locale/src/boost/locale/std/converter.cpp
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/conversion.hpp>
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <locale>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "boost/locale/std/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(const std::locale& base, size_t refs = 0) : converter<CharType>(refs), base_(base) {}
|
||||
string_type convert(converter_base::conversion_type how,
|
||||
const char_type* begin,
|
||||
const char_type* end,
|
||||
int /*flags*/ = 0) const override
|
||||
{
|
||||
switch(how) {
|
||||
case converter_base::upper_case:
|
||||
case converter_base::lower_case:
|
||||
case converter_base::case_folding: {
|
||||
const ctype_type& 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);
|
||||
}
|
||||
case converter_base::normalization:
|
||||
case converter_base::title_case: break;
|
||||
}
|
||||
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(const std::locale& base, size_t refs = 0) : converter<char>(refs), base_(base) {}
|
||||
std::string convert(converter_base::conversion_type how,
|
||||
const char* begin,
|
||||
const char* end,
|
||||
int /*flags*/ = 0) const override
|
||||
{
|
||||
switch(how) {
|
||||
case upper_case:
|
||||
case lower_case:
|
||||
case case_folding: {
|
||||
std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8");
|
||||
const wctype_type& 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");
|
||||
}
|
||||
case title_case:
|
||||
case normalization: break;
|
||||
}
|
||||
return std::string(begin, end - begin);
|
||||
}
|
||||
|
||||
private:
|
||||
std::locale base_;
|
||||
};
|
||||
|
||||
std::locale
|
||||
create_convert(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: {
|
||||
if(utf == utf8_support::native_with_wide || utf == utf8_support::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 char_facet_t::wchar_f: {
|
||||
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 char_facet_t::char16_f: {
|
||||
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 char_facet_t::char32_f: {
|
||||
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
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
377
externals/boost/libs/locale/src/boost/locale/std/numeric.cpp
vendored
Normal file
377
externals/boost/libs/locale/src/boost/locale/std/numeric.cpp
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <cstdlib>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "boost/locale/std/all_generator.hpp"
|
||||
#include "boost/locale/util/numeric.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(const std::locale& base, size_t refs = 0) : std::time_put<CharType>(refs), base_(base) {}
|
||||
typedef typename std::time_put<CharType>::iter_type iter_type;
|
||||
|
||||
iter_type do_put(iter_type out,
|
||||
std::ios_base& /*ios*/,
|
||||
CharType fill,
|
||||
const std::tm* tm,
|
||||
char format,
|
||||
char modifier) const override
|
||||
{
|
||||
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(const std::locale& base, size_t refs = 0) : std::time_put<char>(refs), base_(base) {}
|
||||
iter_type do_put(iter_type out,
|
||||
std::ios_base& /*ios*/,
|
||||
char fill,
|
||||
const std::tm* tm,
|
||||
char format,
|
||||
char modifier = 0) const override
|
||||
{
|
||||
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(const std::locale& base, size_t refs = 0) : std::numpunct<char>(refs)
|
||||
{
|
||||
typedef std::numpunct<wchar_t> wfacet_type;
|
||||
const wfacet_type& 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();
|
||||
}
|
||||
}
|
||||
|
||||
char do_decimal_point() const override { return decimal_point_; }
|
||||
char do_thousands_sep() const override { return thousands_sep_; }
|
||||
std::string do_grouping() const override { return grouping_; }
|
||||
std::string do_truename() const override { return truename_; }
|
||||
std::string do_falsename() const override { 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(const std::locale& base, size_t refs = 0) : std::moneypunct<char, Intl>(refs)
|
||||
{
|
||||
typedef std::moneypunct<wchar_t, Intl> wfacet_type;
|
||||
const wfacet_type& 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();
|
||||
}
|
||||
}
|
||||
|
||||
char do_decimal_point() const override { return decimal_point_; }
|
||||
|
||||
char do_thousands_sep() const override { return thousands_sep_; }
|
||||
|
||||
std::string do_grouping() const override { return grouping_; }
|
||||
|
||||
std::string do_curr_symbol() const override { return curr_symbol_; }
|
||||
std::string do_positive_sign() const override { return positive_sign_; }
|
||||
std::string do_negative_sign() const override { return negative_sign_; }
|
||||
|
||||
int do_frac_digits() const override { return frac_digits_; }
|
||||
|
||||
std::money_base::pattern do_pos_format() const override { return pos_format_; }
|
||||
|
||||
std::money_base::pattern do_neg_format() const override { 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(const char* name, size_t refs = 0) : std::numpunct_byname<char>(name, refs) {}
|
||||
char do_thousands_sep() const override
|
||||
{
|
||||
unsigned char bs = base_type::do_thousands_sep();
|
||||
if(bs > 127)
|
||||
if(bs == 0xA0)
|
||||
return ' ';
|
||||
else
|
||||
return 0;
|
||||
else
|
||||
return bs;
|
||||
}
|
||||
std::string do_grouping() const override
|
||||
{
|
||||
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(const char* name, size_t refs = 0) : std::moneypunct_byname<char, Intl>(name, refs) {}
|
||||
char do_thousands_sep() const override
|
||||
{
|
||||
unsigned char bs = base_type::do_thousands_sep();
|
||||
if(bs > 127)
|
||||
if(bs == 0xA0)
|
||||
return ' ';
|
||||
else
|
||||
return 0;
|
||||
else
|
||||
return bs;
|
||||
}
|
||||
std::string do_grouping() const override
|
||||
{
|
||||
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(const std::locale& in, const std::string& 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(const std::locale& in, const std::string& 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(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: {
|
||||
switch(utf) {
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::none: break;
|
||||
}
|
||||
std::locale tmp = create_basic_formatting<char>(in, locale_name);
|
||||
tmp = std::locale(tmp, new util::base_num_format<char>());
|
||||
return tmp;
|
||||
}
|
||||
case char_facet_t::wchar_f: {
|
||||
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 char_facet_t::char16_f: {
|
||||
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 char_facet_t::char32_f: {
|
||||
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
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
std::locale
|
||||
create_parsing(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: {
|
||||
switch(utf) {
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::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>());
|
||||
}
|
||||
case utf8_support::none: break;
|
||||
}
|
||||
std::locale tmp = create_basic_parsing<char>(in, locale_name);
|
||||
tmp = std::locale(in, new util::base_num_parse<char>());
|
||||
return tmp;
|
||||
}
|
||||
case char_facet_t::wchar_f: {
|
||||
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 char_facet_t::char16_f: {
|
||||
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 char_facet_t::char32_f: {
|
||||
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
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
208
externals/boost/libs/locale/src/boost/locale/std/std_backend.cpp
vendored
Normal file
208
externals/boost/libs/locale/src/boost/locale/std/std_backend.cpp
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/std/std_backend.hpp"
|
||||
#include <boost/locale/gnu_gettext.hpp>
|
||||
#include <boost/locale/localization_backend.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <boost/locale/util/locale_data.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include "boost/locale/encoding/conv.hpp"
|
||||
# include "boost/locale/util/encoding.hpp"
|
||||
# include "boost/locale/win32/lcid.hpp"
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#include "boost/locale/std/all_generator.hpp"
|
||||
#include "boost/locale/util/gregorian.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(const std_localization_backend& other) :
|
||||
localization_backend(), paths_(other.paths_), domains_(other.domains_), locale_id_(other.locale_id_),
|
||||
invalid_(true), use_ansi_encoding_(other.use_ansi_encoding_)
|
||||
{}
|
||||
std_localization_backend* clone() const override { return new std_localization_backend(*this); }
|
||||
|
||||
void set_option(const std::string& name, const std::string& value) override
|
||||
{
|
||||
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() override
|
||||
{
|
||||
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";
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
const std::pair<std::string, int> wl_inf = to_windows_name(lid);
|
||||
const std::string& win_name = wl_inf.first;
|
||||
const int win_codepage = wl_inf.second;
|
||||
#endif
|
||||
|
||||
if(!data_.is_utf8()) {
|
||||
if(loadable(lid))
|
||||
name_ = lid;
|
||||
#if defined(BOOST_WINDOWS)
|
||||
else if(loadable(win_name) && win_codepage == util::encoding_to_windows_codepage(data_.encoding()))
|
||||
name_ = win_name;
|
||||
#endif
|
||||
utf_mode_ = utf8_support::none;
|
||||
} else {
|
||||
if(loadable(lid)) {
|
||||
name_ = lid;
|
||||
utf_mode_ = utf8_support::native_with_wide;
|
||||
#if defined(BOOST_WINDOWS)
|
||||
// This isn't fully correct:
|
||||
// It will treat the 2-Byte wchar_t as UTF-16 encoded while it may be UCS-2
|
||||
// std::basic_filebuf explicitely disallows using suche multi-byte codecvts
|
||||
// but it works in practice so far, so use it instead of failing for codepoints above U+FFFF
|
||||
utf_mode_ = utf8_support::from_wide;
|
||||
#endif
|
||||
}
|
||||
#if defined(BOOST_WINDOWS)
|
||||
else if(loadable(win_name))
|
||||
{
|
||||
name_ = win_name;
|
||||
utf_mode_ = utf8_support::from_wide;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
utf_mode_ = utf8_support::none;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
std::pair<std::string, int> to_windows_name(const std::string& 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(const std::exception& /*e*/) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::locale install(const std::locale& base, category_t category, char_facet_t type) override
|
||||
{
|
||||
prepare_data();
|
||||
|
||||
switch(category) {
|
||||
case category_t::convert: return create_convert(base, name_, type, utf_mode_);
|
||||
case category_t::collation: return create_collate(base, name_, type, utf_mode_);
|
||||
case category_t::formatting: return create_formatting(base, name_, type, utf_mode_);
|
||||
case category_t::parsing: return create_parsing(base, name_, type, utf_mode_);
|
||||
case category_t::codepage: return create_codecvt(base, name_, type, utf_mode_);
|
||||
case category_t::calendar: return util::install_gregorian_calendar(base, data_.country());
|
||||
case category_t::message: {
|
||||
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_t::nochar: break;
|
||||
case char_facet_t::char_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char>(minf));
|
||||
case char_facet_t::wchar_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<wchar_t>(minf));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char16_t>(minf));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f:
|
||||
return std::locale(base, gnu_gettext::create_messages_facet<char32_t>(minf));
|
||||
#endif
|
||||
}
|
||||
return base;
|
||||
}
|
||||
case category_t::information: return util::create_info(base, in_use_id_);
|
||||
case category_t::boundary: break; // Not implemented
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_std
|
||||
15
externals/boost/libs/locale/src/boost/locale/std/std_backend.hpp
vendored
Normal file
15
externals/boost/libs/locale/src/boost/locale/std/std_backend.hpp
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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();
|
||||
} // namespace impl_std
|
||||
}} // namespace boost::locale
|
||||
#endif
|
||||
325
externals/boost/libs/locale/src/boost/locale/util/codecvt_converter.cpp
vendored
Normal file
325
externals/boost/libs/locale/src/boost/locale/util/codecvt_converter.cpp
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/locale/utf8_codecvt.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(disable : 4244) // loose data
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
|
||||
base_converter::~base_converter() = default;
|
||||
|
||||
class utf8_converter : public base_converter {
|
||||
public:
|
||||
int max_len() const override { return 4; }
|
||||
|
||||
utf8_converter* clone() const override { return new utf8_converter(); }
|
||||
|
||||
bool is_thread_safe() const override { return true; }
|
||||
|
||||
uint32_t to_unicode(const char*& begin, const char* end) override
|
||||
{
|
||||
const char* 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;
|
||||
}
|
||||
|
||||
uint32_t from_unicode(uint32_t u, char* begin, const char* end) override
|
||||
{
|
||||
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 constexpr int hash_table_size = 1024;
|
||||
|
||||
simple_converter_impl(const std::string& 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(const conv::conversion_error& /*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(const char*& begin, const char* 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, const char* 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:
|
||||
simple_converter(const std::string& encoding) : cvt_(encoding) {}
|
||||
|
||||
int max_len() const override { return 1; }
|
||||
|
||||
bool is_thread_safe() const override { return true; }
|
||||
base_converter* clone() const override { return new simple_converter(*this); }
|
||||
|
||||
uint32_t to_unicode(const char*& begin, const char* end) override { return cvt_.to_unicode(begin, end); }
|
||||
uint32_t from_unicode(uint32_t u, char* begin, const char* end) override
|
||||
{
|
||||
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(const std::string& 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&, const char*& begin, const char* end) const
|
||||
{
|
||||
return cvt_.to_unicode(begin, end);
|
||||
}
|
||||
|
||||
utf::code_point from_unicode(state_type&, utf::code_point u, char* begin, const char* end) const
|
||||
{
|
||||
return cvt_.from_unicode(u, begin, end);
|
||||
}
|
||||
|
||||
private:
|
||||
simple_converter_impl cvt_;
|
||||
};
|
||||
|
||||
namespace {
|
||||
const char* 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(const char* l, const char* r)
|
||||
{
|
||||
return strcmp(l, r) < 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool check_is_simple_encoding(const std::string& encoding)
|
||||
{
|
||||
std::string norm = util::normalize_encoding(encoding);
|
||||
return std::binary_search<const char**>(simple_encoding_table,
|
||||
simple_encoding_table
|
||||
+ sizeof(simple_encoding_table) / sizeof(const char*),
|
||||
norm.c_str(),
|
||||
compare_strings);
|
||||
}
|
||||
|
||||
std::unique_ptr<base_converter> create_simple_converter(const std::string& encoding)
|
||||
{
|
||||
return std::unique_ptr<base_converter>(create_simple_converter_new_ptr(encoding));
|
||||
}
|
||||
base_converter* create_simple_converter_new_ptr(const std::string& encoding)
|
||||
{
|
||||
if(check_is_simple_encoding(encoding))
|
||||
return new simple_converter(encoding);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<base_converter> create_utf8_converter()
|
||||
{
|
||||
return std::unique_ptr<base_converter>(create_utf8_converter_new_ptr());
|
||||
}
|
||||
|
||||
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:
|
||||
typedef std::unique_ptr<base_converter> base_converter_ptr;
|
||||
typedef base_converter_ptr state_type;
|
||||
|
||||
code_converter(base_converter_ptr cvt, size_t refs = 0) :
|
||||
generic_codecvt<CharType, code_converter<CharType>>(refs), cvt_(std::move(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, const char*& begin, const char* 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, const char* 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(const std::locale& in, std::unique_ptr<base_converter> cvt, char_facet_t type)
|
||||
{
|
||||
if(!cvt)
|
||||
cvt.reset(new base_converter());
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new code_converter<char>(std::move(cvt)));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new code_converter<wchar_t>(std::move(cvt)));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new code_converter<char16_t>(std::move(cvt)));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new code_converter<char32_t>(std::move(cvt)));
|
||||
#endif
|
||||
}
|
||||
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(const std::locale& in, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new utf8_codecvt<char>());
|
||||
case char_facet_t::wchar_f: return std::locale(in, new utf8_codecvt<wchar_t>());
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new utf8_codecvt<char16_t>());
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new utf8_codecvt<char32_t>());
|
||||
#endif
|
||||
}
|
||||
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 character set is not supported or isn't single byte character
|
||||
/// set
|
||||
std::locale create_simple_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type)
|
||||
{
|
||||
if(!check_is_simple_encoding(encoding))
|
||||
throw boost::locale::conv::invalid_charset_error("Invalid simple encoding " + encoding);
|
||||
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new simple_codecvt<char>(encoding));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new simple_codecvt<wchar_t>(encoding));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new simple_codecvt<char16_t>(encoding));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new simple_codecvt<char32_t>(encoding));
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
66
externals/boost/libs/locale/src/boost/locale/util/default_locale.cpp
vendored
Normal file
66
externals/boost/libs/locale/src/boost/locale/util/default_locale.cpp
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
// Get information about the user default locale and put it into the buffer.
|
||||
// Return true on success
|
||||
template<size_t N>
|
||||
static bool get_user_default_locale_info(LCTYPE lcType, char (&buf)[N])
|
||||
{
|
||||
return GetLocaleInfoA(LOCALE_USER_DEFAULT, lcType, buf, N) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
std::string get_system_locale(bool use_utf8_on_windows)
|
||||
{
|
||||
const char* lang = 0;
|
||||
if(!lang || !*lang)
|
||||
lang = getenv("LC_ALL");
|
||||
if(!lang || !*lang)
|
||||
lang = getenv("LC_CTYPE");
|
||||
if(!lang || !*lang)
|
||||
lang = getenv("LANG");
|
||||
#if !BOOST_LOCALE_USE_WIN32_API
|
||||
(void)use_utf8_on_windows; // not relevant for non-windows
|
||||
if(!lang || !*lang)
|
||||
lang = "C";
|
||||
return lang;
|
||||
#else
|
||||
if(lang && *lang)
|
||||
return lang;
|
||||
|
||||
char buf[10]{};
|
||||
if(!get_user_default_locale_info(LOCALE_SISO639LANGNAME, buf))
|
||||
return "C";
|
||||
std::string lc_name = buf;
|
||||
if(get_user_default_locale_info(LOCALE_SISO3166CTRYNAME, buf)) {
|
||||
lc_name += "_";
|
||||
lc_name += buf;
|
||||
}
|
||||
if(use_utf8_on_windows || !get_user_default_locale_info(LOCALE_IDEFAULTANSICODEPAGE, buf))
|
||||
lc_name += ".UTF-8";
|
||||
else {
|
||||
if(atoi(buf) == 0)
|
||||
lc_name += ".UTF-8";
|
||||
else
|
||||
lc_name.append(".windows-").append(buf);
|
||||
}
|
||||
return lc_name;
|
||||
|
||||
#endif
|
||||
}
|
||||
}}} // namespace boost::locale::util
|
||||
78
externals/boost/libs/locale/src/boost/locale/util/encoding.cpp
vendored
Normal file
78
externals/boost/libs/locale/src/boost/locale/util/encoding.cpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022-2023 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include "boost/locale/util/string.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
# include "boost/locale/util/win_codepages.hpp"
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
static std::string do_normalize_encoding(const char* encoding, const size_t len)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(len);
|
||||
for(char c = *encoding; c != 0; c = *(++encoding)) {
|
||||
if(is_lower_ascii(c) || is_numeric_ascii(c))
|
||||
result += c;
|
||||
else if(is_upper_ascii(c))
|
||||
result += char(c - 'A' + 'a');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string normalize_encoding(const std::string& encoding)
|
||||
{
|
||||
return do_normalize_encoding(encoding.c_str(), encoding.size());
|
||||
}
|
||||
|
||||
std::string normalize_encoding(const char* encoding)
|
||||
{
|
||||
return do_normalize_encoding(encoding, std::strlen(encoding));
|
||||
}
|
||||
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
static int normalized_encoding_to_windows_codepage(const std::string& encoding)
|
||||
{
|
||||
constexpr 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, encoding.c_str());
|
||||
while(ptr != end && ptr->name == encoding) {
|
||||
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
|
||||
++ptr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int encoding_to_windows_codepage(const char* encoding)
|
||||
{
|
||||
return normalized_encoding_to_windows_codepage(normalize_encoding(encoding));
|
||||
}
|
||||
|
||||
int encoding_to_windows_codepage(const std::string& encoding)
|
||||
{
|
||||
return normalized_encoding_to_windows_codepage(normalize_encoding(encoding));
|
||||
}
|
||||
|
||||
#endif
|
||||
}}} // namespace boost::locale::util
|
||||
55
externals/boost/libs/locale/src/boost/locale/util/encoding.hpp
vendored
Normal file
55
externals/boost/libs/locale/src/boost/locale/util/encoding.hpp
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022-2023 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_UTIL_ENCODING_HPP
|
||||
#define BOOST_LOCALE_UTIL_ENCODING_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
|
||||
/// Get the UTF encoding name of the given \a CharType
|
||||
template<typename CharType>
|
||||
const char* utf_name()
|
||||
{
|
||||
constexpr auto CharSize = sizeof(CharType);
|
||||
static_assert(CharSize == 1 || CharSize == 2 || CharSize == 4, "Unknown Character Encoding");
|
||||
switch(CharSize) {
|
||||
case 1: return "UTF-8";
|
||||
case 2: {
|
||||
const int16_t endianMark = 1;
|
||||
const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1;
|
||||
return isLittleEndian ? "UTF-16LE" : "UTF-16BE";
|
||||
}
|
||||
case 4: {
|
||||
const int32_t endianMark = 1;
|
||||
const bool isLittleEndian = reinterpret_cast<const char*>(&endianMark)[0] == 1;
|
||||
return isLittleEndian ? "UTF-32LE" : "UTF-32BE";
|
||||
}
|
||||
}
|
||||
BOOST_UNREACHABLE_RETURN("Unknown UTF");
|
||||
}
|
||||
|
||||
/// Make encoding lowercase and remove all non-alphanumeric characters
|
||||
BOOST_LOCALE_DECL std::string normalize_encoding(const std::string& encoding);
|
||||
BOOST_LOCALE_DECL std::string normalize_encoding(const char* encoding);
|
||||
/// True if the normalized encodings are equal
|
||||
inline bool are_encodings_equal(const std::string& l, const std::string& r)
|
||||
{
|
||||
return normalize_encoding(l) == normalize_encoding(r);
|
||||
}
|
||||
|
||||
#if BOOST_LOCALE_USE_WIN32_API
|
||||
int encoding_to_windows_codepage(const char* encoding);
|
||||
int encoding_to_windows_codepage(const std::string& encoding);
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
#endif
|
||||
716
externals/boost/libs/locale/src/boost/locale/util/gregorian.cpp
vendored
Normal file
716
externals/boost/libs/locale/src/boost/locale/util/gregorian.cpp
vendored
Normal file
@@ -0,0 +1,716 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include "boost/locale/util/gregorian.hpp"
|
||||
#include <boost/locale/date_time.hpp>
|
||||
#include <boost/locale/date_time_facet.hpp>
|
||||
#include <boost/locale/hold_ptr.hpp>
|
||||
#include "boost/locale/util/timezone.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
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)
|
||||
{
|
||||
constexpr 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];
|
||||
}
|
||||
|
||||
constexpr int days_from_0_impl(int year_m1)
|
||||
{
|
||||
return 365 * year_m1 + (year_m1 / 400) - (year_m1 / 100) + (year_m1 / 4);
|
||||
}
|
||||
constexpr int days_from_0(int year)
|
||||
{
|
||||
return days_from_0_impl(year - 1);
|
||||
}
|
||||
|
||||
constexpr int days_from_0_to_1970 = days_from_0(1970);
|
||||
constexpr int days_from_1970(int year)
|
||||
{
|
||||
return days_from_0(year) - days_from_0_to_1970;
|
||||
}
|
||||
|
||||
int days_from_1jan(int year, int month, int day)
|
||||
{
|
||||
constexpr 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(const std::tm* 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;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
// Locale dependent data
|
||||
|
||||
bool comparator(const char* left, const char* 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(const char* terr)
|
||||
{
|
||||
constexpr const char* sat[] = {"AE", "AF", "BH", "DJ", "DZ", "EG", "ER", "ET", "IQ", "IR", "JO", "KE",
|
||||
"KW", "LY", "MA", "OM", "QA", "SA", "SD", "SO", "SY", "TN", "YE"};
|
||||
constexpr const char* 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<const char* const*>(sat, sat + sizeof(sat) / (sizeof(sat[0])), terr, comparator))
|
||||
return 6; // sat
|
||||
if(std::binary_search<const char* const*>(sunday,
|
||||
sunday + sizeof(sunday) / (sizeof(sunday[0])),
|
||||
terr,
|
||||
comparator))
|
||||
return 0; // sun
|
||||
// default
|
||||
return 1; // mon
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class gregorian_calendar : public abstract_calendar {
|
||||
public:
|
||||
gregorian_calendar(const std::string& 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
|
||||
gregorian_calendar* clone() const override { return new gregorian_calendar(*this); }
|
||||
|
||||
/// Set specific \a value for period \a p, note not all values are settable.
|
||||
void set_value(period::marks::period_mark m, int value) override
|
||||
{
|
||||
using namespace period::marks;
|
||||
switch(m) {
|
||||
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;
|
||||
BOOST_FALLTHROUGH;
|
||||
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 within current month
|
||||
{
|
||||
normalize();
|
||||
int current_week = get_value(m, 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
|
||||
case invalid: return;
|
||||
}
|
||||
normalized_ = false;
|
||||
}
|
||||
|
||||
void normalize() override
|
||||
{
|
||||
if(!normalized_) {
|
||||
std::tm val = tm_updated_;
|
||||
val.tm_isdst = -1;
|
||||
val.tm_wday = -1; // indicator 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 within
|
||||
/// period such that the week belongs there
|
||||
constexpr int days_in_full_week = 4;
|
||||
|
||||
// Always 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 dividable 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
|
||||
int get_value(period::marks::period_mark m, value_type v) const override
|
||||
{
|
||||
using namespace period::marks;
|
||||
switch(m) {
|
||||
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:
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
if(sizeof(std::time_t) == 4)
|
||||
return 2038; // Y2K38 - maximal with 32 bit time_t
|
||||
else
|
||||
return std::numeric_limits<int>::max()
|
||||
/ 365; // Reasonably large but we can still get the days without overflowing
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case week_of_month: ///< The week number within 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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
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 february in non leap year is 28 days, the rest
|
||||
// has more then 4 weeks
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
case current: return (tm_.tm_mday - 1) / 7 + 1;
|
||||
}
|
||||
break;
|
||||
case invalid: BOOST_ASSERT_MSG(false, "Shouldn't use 'invalid' value."); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Set current time point
|
||||
void set_time(const posix_time& p) override
|
||||
{
|
||||
from_time(static_cast<std::time_t>(p.seconds));
|
||||
}
|
||||
posix_time get_time() const override
|
||||
{
|
||||
posix_time pt = {time_, 0};
|
||||
return pt;
|
||||
}
|
||||
double get_time_ms() const override
|
||||
{
|
||||
return time_ * 1e3;
|
||||
}
|
||||
|
||||
/// Set option for calendar, for future use
|
||||
void set_option(calendar_option_type opt, int /*v*/) override
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
/// Get option for calendar, currently only check if it is Gregorian calendar
|
||||
int get_option(calendar_option_type opt) const override
|
||||
{
|
||||
switch(opt) {
|
||||
case is_gregorian: return 1;
|
||||
case is_dst: return tm_.tm_isdst == 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Adjust period's \a p value by \a difference items using a update_type \a u.
|
||||
/// Note: not all values are adjustable
|
||||
void adjust_value(period::marks::period_mark m, update_type u, int difference) override
|
||||
{
|
||||
switch(u) {
|
||||
case move: {
|
||||
using namespace period::marks;
|
||||
switch(m) {
|
||||
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 within 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;
|
||||
case era:
|
||||
case period::marks::first_day_of_week:
|
||||
case invalid: break; // Not adjustable and ignored
|
||||
}
|
||||
normalized_ = false;
|
||||
normalize();
|
||||
} break;
|
||||
case roll: {
|
||||
const int cur_min = get_value(m, actual_minimum);
|
||||
const int cur_max = get_value(m, actual_maximum);
|
||||
BOOST_ASSERT(cur_max >= cur_min);
|
||||
const int range = cur_max - cur_min + 1;
|
||||
int value = get_value(m, current) - cur_min;
|
||||
BOOST_ASSERT(value >= 0 && value < range);
|
||||
BOOST_ASSERT_MSG(difference <= std::numeric_limits<int>::max(), "Input is to large");
|
||||
value = (value + difference) % range;
|
||||
// If the sum above was negative the result of the modulo operation "can" be negative too.
|
||||
if(value < 0)
|
||||
value += range;
|
||||
BOOST_ASSERT(value >= 0 && value < range);
|
||||
set_value(m, value + cur_min);
|
||||
normalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_diff(period::marks::period_mark m, int diff, const gregorian_calendar* other) const
|
||||
{
|
||||
if(diff == 0)
|
||||
return 0;
|
||||
hold_ptr<gregorian_calendar> self(clone());
|
||||
self->adjust_value(m, 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
|
||||
int difference(const abstract_calendar& other_cal, period::marks::period_mark m) const override
|
||||
{
|
||||
hold_ptr<gregorian_calendar> keeper;
|
||||
const gregorian_calendar* other = dynamic_cast<const gregorian_calendar*>(&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(m) {
|
||||
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; BOOST_FALLTHROUGH;
|
||||
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_);
|
||||
case invalid:
|
||||
case period::marks::first_day_of_week: break; // Not adjustable
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Set time zone, empty - use system
|
||||
void set_timezone(const std::string& tz) override
|
||||
{
|
||||
if(tz.empty()) {
|
||||
is_local_ = true;
|
||||
tzoff_ = 0;
|
||||
} else {
|
||||
is_local_ = false;
|
||||
tzoff_ = parse_tz(tz);
|
||||
}
|
||||
from_time(time_);
|
||||
time_zone_name_ = tz;
|
||||
}
|
||||
std::string get_timezone() const override
|
||||
{
|
||||
return time_zone_name_;
|
||||
}
|
||||
|
||||
bool same(const abstract_calendar* other) const override
|
||||
{
|
||||
const gregorian_calendar* gcal = dynamic_cast<const gregorian_calendar*>(other);
|
||||
if(!gcal)
|
||||
return false;
|
||||
return gcal->tzoff_ == tzoff_ && gcal->is_local_ == is_local_
|
||||
&& gcal->first_day_of_week_ == first_day_of_week_;
|
||||
}
|
||||
|
||||
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(const std::string& terr)
|
||||
{
|
||||
return new gregorian_calendar(terr);
|
||||
}
|
||||
|
||||
class gregorian_facet : public calendar_facet {
|
||||
public:
|
||||
gregorian_facet(const std::string& terr, size_t refs = 0) : calendar_facet(refs), terr_(terr) {}
|
||||
abstract_calendar* create_calendar() const override { return create_gregorian_calendar(terr_); }
|
||||
|
||||
private:
|
||||
std::string terr_;
|
||||
};
|
||||
|
||||
std::locale install_gregorian_calendar(const std::locale& in, const std::string& terr)
|
||||
{
|
||||
return std::locale(in, new gregorian_facet(terr));
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
// boostinspect:nominmax
|
||||
18
externals/boost/libs/locale/src/boost/locale/util/gregorian.hpp
vendored
Normal file
18
externals/boost/libs/locale/src/boost/locale/util/gregorian.hpp
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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(const std::locale& in, const std::string& terr);
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
#endif
|
||||
92
externals/boost/libs/locale/src/boost/locale/util/iconv.hpp
vendored
Normal file
92
externals/boost/libs/locale/src/boost/locale/util/iconv.hpp
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_ICONV_FIXER_HPP
|
||||
#define BOOST_LOCALE_ICONV_FIXER_HPP
|
||||
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <iconv.h>
|
||||
|
||||
namespace boost { namespace locale {
|
||||
class iconv_handle {
|
||||
iconv_t h_;
|
||||
void close()
|
||||
{
|
||||
if(*this)
|
||||
iconv_close(h_);
|
||||
}
|
||||
|
||||
public:
|
||||
iconv_handle(iconv_t h = iconv_t(-1)) : h_(h) {}
|
||||
iconv_handle(iconv_handle&& rhs) noexcept : h_(exchange(rhs.h_, iconv_t(-1))) {}
|
||||
iconv_handle& operator=(iconv_handle&& rhs) noexcept
|
||||
{
|
||||
h_ = exchange(rhs.h_, iconv_t(-1));
|
||||
return *this;
|
||||
}
|
||||
iconv_handle& operator=(iconv_t h)
|
||||
{
|
||||
close();
|
||||
h_ = h;
|
||||
return *this;
|
||||
}
|
||||
~iconv_handle() { close(); }
|
||||
|
||||
operator iconv_t() const { return h_; }
|
||||
explicit operator bool() const { return h_ != iconv_t(-1); }
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
#if defined(__ICONV_F_HIDE_INVALID) && defined(__FreeBSD__)
|
||||
# define BOOST_LOCALE_ICONV_FUNC __iconv
|
||||
# define BOOST_LOCALE_ICONV_FLAGS , __ICONV_F_HIDE_INVALID, 0
|
||||
|
||||
// GNU variant
|
||||
typedef size_t (*const_iconv_ptr_type)(iconv_t, const char**, size_t*, char**, size_t*, uint32_t, size_t*);
|
||||
// POSIX variant
|
||||
typedef size_t (*nonconst_iconv_ptr_type)(iconv_t, char**, size_t*, char**, size_t*, uint32_t, size_t*);
|
||||
#else
|
||||
# define BOOST_LOCALE_ICONV_FUNC iconv
|
||||
# define BOOST_LOCALE_ICONV_FLAGS
|
||||
|
||||
typedef size_t (*const_iconv_ptr_type)(iconv_t, const char**, size_t*, char**, size_t*);
|
||||
typedef size_t (*nonconst_iconv_ptr_type)(iconv_t, char**, size_t*, char**, size_t*);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline size_t
|
||||
call_iconv_impl(const_iconv_ptr_type ptr, iconv_t d, const char** in, size_t* insize, char** out, size_t* outsize)
|
||||
{
|
||||
return ptr(d, in, insize, out, outsize BOOST_LOCALE_ICONV_FLAGS);
|
||||
}
|
||||
inline size_t call_iconv_impl(nonconst_iconv_ptr_type ptr,
|
||||
iconv_t d,
|
||||
const char** in,
|
||||
size_t* insize,
|
||||
char** out,
|
||||
size_t* outsize)
|
||||
{
|
||||
return ptr(d, const_cast<char**>(in), insize, out, outsize BOOST_LOCALE_ICONV_FLAGS);
|
||||
}
|
||||
|
||||
inline size_t call_iconv(iconv_t d, const char** in, size_t* insize, char** out, size_t* outsize)
|
||||
{
|
||||
return call_iconv_impl(BOOST_LOCALE_ICONV_FUNC, d, in, insize, out, outsize);
|
||||
}
|
||||
|
||||
// Convenience overload when the adjusted in/out ptrs are not required
|
||||
inline size_t call_iconv(iconv_t d, const char* in, size_t* insize, char* out, size_t* outsize)
|
||||
{
|
||||
return call_iconv(d, &in, insize, &out, outsize);
|
||||
}
|
||||
// Disambiguation
|
||||
inline size_t call_iconv(iconv_t d, std::nullptr_t, std::nullptr_t, std::nullptr_t, std::nullptr_t)
|
||||
{
|
||||
return call_iconv_impl(BOOST_LOCALE_ICONV_FUNC, d, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
}} // namespace boost::locale
|
||||
|
||||
#endif
|
||||
52
externals/boost/libs/locale/src/boost/locale/util/info.cpp
vendored
Normal file
52
externals/boost/libs/locale/src/boost/locale/util/info.cpp
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/locale/info.hpp>
|
||||
#include <boost/locale/util.hpp>
|
||||
#include <boost/locale/util/locale_data.hpp>
|
||||
#include <cstdlib>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
|
||||
class simple_info : public info {
|
||||
public:
|
||||
simple_info(const std::string& name, size_t refs = 0) : info(refs), name_(name) { d.parse(name); }
|
||||
std::string get_string_property(string_propery v) const override
|
||||
{
|
||||
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_;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int get_integer_property(integer_property v) const override
|
||||
{
|
||||
switch(v) {
|
||||
case utf8_property: return d.is_utf8();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
locale_data d;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
std::locale create_info(const std::locale& in, const std::string& name)
|
||||
{
|
||||
return std::locale(in, new simple_info(name));
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
160
externals/boost/libs/locale/src/boost/locale/util/locale_data.cpp
vendored
Normal file
160
externals/boost/libs/locale/src/boost/locale/util/locale_data.cpp
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
// Copyright (c) 2022-2023 Alexander Grund
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/util/locale_data.hpp>
|
||||
#include "boost/locale/encoding/conv.hpp"
|
||||
#include "boost/locale/util/encoding.hpp"
|
||||
#include "boost/locale/util/string.hpp"
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
locale_data::locale_data()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
locale_data::locale_data(const std::string& locale_name)
|
||||
{
|
||||
if(!parse(locale_name))
|
||||
throw std::invalid_argument("Failed to parse locale name: " + locale_name);
|
||||
}
|
||||
|
||||
void locale_data::reset()
|
||||
{
|
||||
language_ = "C";
|
||||
country_.clear();
|
||||
encoding_ = "US-ASCII";
|
||||
variant_.clear();
|
||||
utf8_ = false;
|
||||
}
|
||||
|
||||
std::string locale_data::to_string() const
|
||||
{
|
||||
std::string result = language_;
|
||||
if(!country_.empty())
|
||||
(result += '_') += country_;
|
||||
if(!encoding_.empty() && !util::are_encodings_equal(encoding_, "US-ASCII"))
|
||||
(result += '.') += encoding_;
|
||||
if(!variant_.empty())
|
||||
(result += '@') += variant_;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool locale_data::parse(const std::string& locale_name)
|
||||
{
|
||||
reset();
|
||||
return parse_from_lang(locale_name);
|
||||
}
|
||||
|
||||
bool locale_data::parse_from_lang(const std::string& input)
|
||||
{
|
||||
const auto end = input.find_first_of("-_@.");
|
||||
std::string tmp = input.substr(0, end);
|
||||
if(tmp.empty())
|
||||
return false;
|
||||
// lowercase ASCII
|
||||
for(char& c : tmp) {
|
||||
if(is_upper_ascii(c))
|
||||
c += 'a' - 'A';
|
||||
else if(!is_lower_ascii(c))
|
||||
return false;
|
||||
}
|
||||
if(tmp != "c" && tmp != "posix") // Keep default
|
||||
language_ = tmp;
|
||||
|
||||
if(end >= input.size())
|
||||
return true;
|
||||
else if(input[end] == '-' || input[end] == '_')
|
||||
return parse_from_country(input.substr(end + 1));
|
||||
else if(input[end] == '.')
|
||||
return parse_from_encoding(input.substr(end + 1));
|
||||
else {
|
||||
BOOST_ASSERT_MSG(input[end] == '@', "Unexpected delimiter");
|
||||
return parse_from_variant(input.substr(end + 1));
|
||||
}
|
||||
}
|
||||
|
||||
bool locale_data::parse_from_country(const std::string& input)
|
||||
{
|
||||
if(language_ == "C")
|
||||
return false;
|
||||
|
||||
const auto end = input.find_first_of("@.");
|
||||
std::string tmp = input.substr(0, end);
|
||||
if(tmp.empty())
|
||||
return false;
|
||||
|
||||
// Make uppercase
|
||||
for(char& c : tmp) {
|
||||
if(util::is_lower_ascii(c))
|
||||
c += 'A' - 'a';
|
||||
}
|
||||
// If it's ALL uppercase ASCII, assume ISO 3166 country id
|
||||
if(std::find_if_not(tmp.begin(), tmp.end(), util::is_upper_ascii) != tmp.end()) {
|
||||
// else handle special cases:
|
||||
// - en_US_POSIX is an alias for C
|
||||
// - M49 country code: 3 digits
|
||||
if(language_ == "en" && tmp == "US_POSIX") {
|
||||
language_ = "C";
|
||||
tmp.clear();
|
||||
} else if(tmp.size() != 3u || std::find_if_not(tmp.begin(), tmp.end(), util::is_numeric_ascii) != tmp.end())
|
||||
return false;
|
||||
}
|
||||
|
||||
country_ = tmp;
|
||||
if(end >= input.size())
|
||||
return true;
|
||||
else if(input[end] == '.')
|
||||
return parse_from_encoding(input.substr(end + 1));
|
||||
else {
|
||||
BOOST_ASSERT_MSG(input[end] == '@', "Unexpected delimiter");
|
||||
return parse_from_variant(input.substr(end + 1));
|
||||
}
|
||||
}
|
||||
|
||||
bool locale_data::parse_from_encoding(const std::string& input)
|
||||
{
|
||||
const auto end = input.find_first_of('@');
|
||||
std::string tmp = input.substr(0, end);
|
||||
if(tmp.empty())
|
||||
return false;
|
||||
// No assumptions, but uppercase
|
||||
for(char& c : tmp) {
|
||||
if(util::is_lower_ascii(c))
|
||||
c += 'A' - 'a';
|
||||
}
|
||||
encoding_ = tmp;
|
||||
|
||||
utf8_ = util::normalize_encoding(encoding_) == "utf8";
|
||||
|
||||
if(end >= input.size())
|
||||
return true;
|
||||
else {
|
||||
BOOST_ASSERT_MSG(input[end] == '@', "Unexpected delimiter");
|
||||
return parse_from_variant(input.substr(end + 1));
|
||||
}
|
||||
}
|
||||
|
||||
bool locale_data::parse_from_variant(const std::string& input)
|
||||
{
|
||||
if(language_ == "C")
|
||||
return false;
|
||||
if(input.empty())
|
||||
return false;
|
||||
variant_ = input;
|
||||
// No assumptions, just make it lowercase
|
||||
for(char& c : variant_) {
|
||||
if(util::is_upper_ascii(c))
|
||||
c += 'a' - 'A';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
383
externals/boost/libs/locale/src/boost/locale/util/numeric.hpp
vendored
Normal file
383
externals/boost/libs/locale/src/boost/locale/util/numeric.hpp
vendored
Normal file
@@ -0,0 +1,383 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP
|
||||
#define BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP
|
||||
#include <boost/locale/formatting.hpp>
|
||||
#include <boost/locale/info.hpp>
|
||||
#include <boost/predef/os.h>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "boost/locale/util/timezone.hpp"
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
|
||||
template<typename CharType>
|
||||
struct formatting_size_traits {
|
||||
static size_t size(const std::basic_string<CharType>& s, const std::locale& /*l*/) { return s.size(); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct formatting_size_traits<char> {
|
||||
static size_t size(const std::string& s, const std::locale& 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:
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, double val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long double val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, long long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
iter_type do_put(iter_type out, std::ios_base& ios, char_type fill, unsigned long long val) const override
|
||||
{
|
||||
return do_real_put(out, ios, fill, val);
|
||||
}
|
||||
|
||||
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: break;
|
||||
}
|
||||
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,
|
||||
const string_type& format) const
|
||||
{
|
||||
std::string tz = ios_info::get(ios).time_zone();
|
||||
std::tm tm;
|
||||
#if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || 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 BOOST_OS_LINUX || BOOST_OS_BSD_FREE || 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;
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned short& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned int& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, float& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type
|
||||
do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, double& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
long double& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
long long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
iter_type do_get(iter_type in,
|
||||
iter_type end,
|
||||
std::ios_base& ios,
|
||||
std::ios_base::iostate& err,
|
||||
unsigned long long& val) const override
|
||||
{
|
||||
return do_real_get(in, end, ios, err, val);
|
||||
}
|
||||
|
||||
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: break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
#endif
|
||||
47
externals/boost/libs/locale/src/boost/locale/util/timezone.hpp
vendored
Normal file
47
externals/boost/libs/locale/src/boost/locale/util/timezone.hpp
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP
|
||||
#define BOOST_LOCALE_IMPL_UTIL_TIMEZONE_HPP
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
inline int parse_tz(const std::string& 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;
|
||||
const char* 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;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
#endif
|
||||
181
externals/boost/libs/locale/src/boost/locale/util/win_codepages.hpp
vendored
Normal file
181
externals/boost/libs/locale/src/boost/locale/util/win_codepages.hpp
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef BOOST_LOCALE_IMPL_WIN_CODEPAGES_HPP
|
||||
#define BOOST_LOCALE_IMPL_WIN_CODEPAGES_HPP
|
||||
|
||||
#include <boost/locale/config.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace boost { namespace locale { namespace util {
|
||||
|
||||
struct windows_encoding {
|
||||
const char* name;
|
||||
unsigned codepage;
|
||||
unsigned was_tested;
|
||||
};
|
||||
|
||||
inline bool operator<(const windows_encoding& l, const char* name)
|
||||
{
|
||||
return strcmp(l.name, name) < 0;
|
||||
}
|
||||
|
||||
static windows_encoding all_windows_encodings[] = {
|
||||
{"asmo708", 708, 0},
|
||||
{"big5", 950, 0},
|
||||
{"cp1025", 21025, 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},
|
||||
{"cp866", 866, 0},
|
||||
{"cp874", 874, 0},
|
||||
{"cp875", 875, 0},
|
||||
{"cp932", 932, 0},
|
||||
{"cp936", 936, 0},
|
||||
{"csiso2022jp", 50221, 0},
|
||||
{"dos720", 720, 0},
|
||||
{"dos862", 862, 0},
|
||||
{"euccn", 51936, 0},
|
||||
{"eucjp", 20932, 0},
|
||||
{"euckr", 51949, 0},
|
||||
{"gb18030", 54936, 0},
|
||||
{"gb2312", 936, 0},
|
||||
{"gbk", 936, 0},
|
||||
{"hzgb2312", 52936, 0},
|
||||
{"ibm00858", 858, 0},
|
||||
{"ibm00924", 20924, 0},
|
||||
{"ibm01026", 1026, 0},
|
||||
{"ibm01047", 1047, 0},
|
||||
{"ibm01140", 1140, 0},
|
||||
{"ibm01141", 1141, 0},
|
||||
{"ibm01142", 1142, 0},
|
||||
{"ibm01143", 1143, 0},
|
||||
{"ibm01144", 1144, 0},
|
||||
{"ibm01145", 1145, 0},
|
||||
{"ibm01146", 1146, 0},
|
||||
{"ibm01147", 1147, 0},
|
||||
{"ibm01148", 1148, 0},
|
||||
{"ibm01149", 1149, 0},
|
||||
{"ibm037", 37, 0},
|
||||
{"ibm273", 20273, 0},
|
||||
{"ibm277", 20277, 0},
|
||||
{"ibm278", 20278, 0},
|
||||
{"ibm280", 20280, 0},
|
||||
{"ibm284", 20284, 0},
|
||||
{"ibm285", 20285, 0},
|
||||
{"ibm290", 20290, 0},
|
||||
{"ibm297", 20297, 0},
|
||||
{"ibm420", 20420, 0},
|
||||
{"ibm423", 20423, 0},
|
||||
{"ibm424", 20424, 0},
|
||||
{"ibm437", 437, 0},
|
||||
{"ibm500", 500, 0},
|
||||
{"ibm737", 737, 0},
|
||||
{"ibm775", 775, 0},
|
||||
{"ibm850", 850, 0},
|
||||
{"ibm852", 852, 0},
|
||||
{"ibm855", 855, 0},
|
||||
{"ibm857", 857, 0},
|
||||
{"ibm860", 860, 0},
|
||||
{"ibm861", 861, 0},
|
||||
{"ibm863", 863, 0},
|
||||
{"ibm864", 864, 0},
|
||||
{"ibm865", 865, 0},
|
||||
{"ibm869", 869, 0},
|
||||
{"ibm870", 870, 0},
|
||||
{"ibm871", 20871, 0},
|
||||
{"ibm880", 20880, 0},
|
||||
{"ibm905", 20905, 0},
|
||||
{"ibmthai", 20838, 0},
|
||||
{"iso2022jp", 50220, 0},
|
||||
{"iso2022jp", 50222, 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},
|
||||
{"iso88598i", 38598, 0},
|
||||
{"iso88599", 28599, 0},
|
||||
{"johab", 1361, 0},
|
||||
{"koi8r", 20866, 0},
|
||||
{"koi8u", 21866, 0},
|
||||
{"ksc56011987", 949, 0},
|
||||
{"latin1", 28591, 0},
|
||||
{"latin1", 1252, 0},
|
||||
{"macintosh", 10000, 0},
|
||||
{"ms936", 936, 0},
|
||||
{"shiftjis", 932, 0},
|
||||
{"sjis", 932, 0},
|
||||
{"unicodefffe", 1201, 0},
|
||||
{"usascii", 20127, 0},
|
||||
{"utf16", 1200, 0},
|
||||
{"utf32", 12000, 0},
|
||||
{"utf32be", 12001, 0},
|
||||
{"utf7", 65000, 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},
|
||||
{"windows1258", 1258, 0},
|
||||
{"windows874", 874, 0},
|
||||
{"windows932", 932, 0},
|
||||
{"windows936", 936, 0},
|
||||
{"xchinesecns", 20000, 0},
|
||||
{"xchineseeten", 20002, 0},
|
||||
{"xcp20001", 20001, 0},
|
||||
{"xcp20003", 20003, 0},
|
||||
{"xcp20004", 20004, 0},
|
||||
{"xcp20005", 20005, 0},
|
||||
{"xcp20261", 20261, 0},
|
||||
{"xcp20269", 20269, 0},
|
||||
{"xcp20936", 20936, 0},
|
||||
{"xcp20949", 20949, 0},
|
||||
{"xcp50227", 50227, 0},
|
||||
{"xebcdickoreanextended", 20833, 0},
|
||||
{"xeuropa", 29001, 0},
|
||||
{"xia5", 20105, 0},
|
||||
{"xia5german", 20106, 0},
|
||||
{"xia5norwegian", 20108, 0},
|
||||
{"xia5swedish", 20107, 0},
|
||||
{"xisciias", 57006, 0},
|
||||
{"xisciibe", 57003, 0},
|
||||
{"xisciide", 57002, 0},
|
||||
{"xisciigu", 57010, 0},
|
||||
{"xisciika", 57008, 0},
|
||||
{"xisciima", 57009, 0},
|
||||
{"xisciior", 57007, 0},
|
||||
{"xisciipa", 57011, 0},
|
||||
{"xisciita", 57004, 0},
|
||||
{"xisciite", 57005, 0},
|
||||
{"xmacarabic", 10004, 0},
|
||||
{"xmacce", 10029, 0},
|
||||
{"xmacchinesesimp", 10008, 0},
|
||||
{"xmacchinesetrad", 10002, 0},
|
||||
{"xmaccroatian", 10082, 0},
|
||||
{"xmaccyrillic", 10007, 0},
|
||||
{"xmacgreek", 10006, 0},
|
||||
{"xmachebrew", 10005, 0},
|
||||
{"xmacicelandic", 10079, 0},
|
||||
{"xmacjapanese", 10001, 0},
|
||||
{"xmackorean", 10003, 0},
|
||||
{"xmacromanian", 10010, 0},
|
||||
{"xmacthai", 10021, 0},
|
||||
{"xmacturkish", 10081, 0},
|
||||
{"xmacukrainian", 10017, 0},
|
||||
};
|
||||
}}} // namespace boost::locale::util
|
||||
|
||||
#endif
|
||||
29
externals/boost/libs/locale/src/boost/locale/win32/all_generator.hpp
vendored
Normal file
29
externals/boost/libs/locale/src/boost/locale/win32/all_generator.hpp
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://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 <locale>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_win {
|
||||
|
||||
class winlocale;
|
||||
|
||||
std::locale create_convert(const std::locale& in, const winlocale& lc, char_facet_t type);
|
||||
|
||||
std::locale create_collate(const std::locale& in, const winlocale& lc, char_facet_t type);
|
||||
|
||||
std::locale create_formatting(const std::locale& in, const winlocale& lc, char_facet_t type);
|
||||
|
||||
std::locale create_parsing(const std::locale& in, const winlocale& lc, char_facet_t type);
|
||||
|
||||
std::locale create_codecvt(const std::locale& in, char_facet_t type);
|
||||
|
||||
}}} // namespace boost::locale::impl_win
|
||||
|
||||
#endif
|
||||
324
externals/boost/libs/locale/src/boost/locale/win32/api.hpp
vendored
Normal file
324
externals/boost/libs/locale/src/boost/locale/win32/api.hpp
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_LOCALE_IMPL_WIN32_API_HPP
|
||||
#define BOOST_LOCALE_IMPL_WIN32_API_HPP
|
||||
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "boost/locale/win32/lcid.hpp"
|
||||
|
||||
#ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
#endif
|
||||
#ifndef UNICODE
|
||||
# define UNICODE
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <boost/locale/collator.hpp>
|
||||
#include <boost/locale/conversion.hpp>
|
||||
|
||||
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(collate_level level)
|
||||
{
|
||||
switch(level) {
|
||||
case collate_level::primary: return NORM_IGNORESYMBOLS | NORM_IGNORECASE | NORM_IGNORENONSPACE;
|
||||
case collate_level::secondary: return NORM_IGNORESYMBOLS | NORM_IGNORECASE;
|
||||
case collate_level::tertiary: return NORM_IGNORESYMBOLS;
|
||||
case collate_level::quaternary:
|
||||
case collate_level::identical: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class winlocale {
|
||||
public:
|
||||
winlocale() : lcid(0) {}
|
||||
|
||||
winlocale(const std::string& name) { lcid = locale_to_lcid(name); }
|
||||
|
||||
unsigned lcid;
|
||||
|
||||
bool is_c() const { return lcid == 0; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Number Format
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline numeric_info wcsnumformat_l(const winlocale& l)
|
||||
{
|
||||
numeric_info res;
|
||||
res.decimal_point = L'.';
|
||||
unsigned lcid = l.lcid;
|
||||
|
||||
if(lcid == 0)
|
||||
return res;
|
||||
|
||||
// limits according to MSDN
|
||||
constexpr int th_size = 4;
|
||||
constexpr int de_size = 4;
|
||||
constexpr 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) {
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
if(std::numeric_limits<char>::is_signed) {
|
||||
res.grouping += std::numeric_limits<char>::min();
|
||||
} else {
|
||||
res.grouping += std::numeric_limits<char>::max();
|
||||
}
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline std::wstring win_map_string_l(unsigned flags, const wchar_t* begin, const wchar_t* end, const winlocale& l)
|
||||
{
|
||||
std::wstring res;
|
||||
if(end - begin > std::numeric_limits<int>::max())
|
||||
throw std::length_error("String to long for int type");
|
||||
int len = LCMapStringW(l.lcid, flags, begin, static_cast<int>(end - begin), 0, 0);
|
||||
if(len == 0)
|
||||
return res;
|
||||
if(len == std::numeric_limits<int>::max())
|
||||
throw std::length_error("String to long for int type");
|
||||
std::vector<wchar_t> buf(len + 1);
|
||||
int l2 =
|
||||
LCMapStringW(l.lcid, flags, begin, static_cast<int>(end - begin), &buf.front(), static_cast<int>(buf.size()));
|
||||
res.assign(&buf.front(), l2);
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Collation
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline int wcscoll_l(collate_level level,
|
||||
const wchar_t* lb,
|
||||
const wchar_t* le,
|
||||
const wchar_t* rb,
|
||||
const wchar_t* re,
|
||||
const winlocale& l)
|
||||
{
|
||||
if(le - lb > std::numeric_limits<int>::max() || re - rb > std::numeric_limits<int>::max())
|
||||
throw std::length_error("String to long for int type");
|
||||
const int result = CompareStringW(l.lcid,
|
||||
collation_level_to_flag(level),
|
||||
lb,
|
||||
static_cast<int>(le - lb),
|
||||
rb,
|
||||
static_cast<int>(re - rb));
|
||||
return result - 2; // Subtract 2 to get the meaning of <0, ==0, and >0
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Money Format
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::wstring wcsfmon_l(double value, const winlocale& 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(const wchar_t* format, SYSTEMTIME const* tm, const winlocale& 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(const wchar_t* format, SYSTEMTIME const* tm, const winlocale& 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(const wchar_t* begin, const wchar_t* 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, const wchar_t* begin, const wchar_t* 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 = MAP_PRECOMPOSED;
|
||||
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;
|
||||
}
|
||||
|
||||
if(end - begin > std::numeric_limits<int>::max())
|
||||
throw std::length_error("String to long for int type");
|
||||
int len = FoldStringW(flags, begin, static_cast<int>(end - begin), 0, 0);
|
||||
if(len == 0)
|
||||
return std::wstring();
|
||||
if(len == std::numeric_limits<int>::max())
|
||||
throw std::length_error("String to long for int type");
|
||||
std::vector<wchar_t> v(len + 1);
|
||||
len = FoldStringW(flags, begin, static_cast<int>(end - begin), &v.front(), len + 1);
|
||||
return std::wstring(&v.front(), len);
|
||||
}
|
||||
|
||||
inline std::wstring wcsxfrm_l(collate_level level, const wchar_t* begin, const wchar_t* end, const winlocale& l)
|
||||
{
|
||||
int flag = LCMAP_SORTKEY | collation_level_to_flag(level);
|
||||
|
||||
return win_map_string_l(flag, begin, end, l);
|
||||
}
|
||||
|
||||
inline std::wstring towupper_l(const wchar_t* begin, const wchar_t* end, const winlocale& l)
|
||||
{
|
||||
return win_map_string_l(LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING, begin, end, l);
|
||||
}
|
||||
|
||||
inline std::wstring towlower_l(const wchar_t* begin, const wchar_t* end, const winlocale& l)
|
||||
{
|
||||
return win_map_string_l(LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING, begin, end, l);
|
||||
}
|
||||
|
||||
inline std::wstring wcsftime_l(char c, const std::tm* tm, const winlocale& l)
|
||||
{
|
||||
SYSTEMTIME wtm = SYSTEMTIME();
|
||||
wtm.wYear = static_cast<WORD>(tm->tm_year + 1900);
|
||||
wtm.wMonth = static_cast<WORD>(tm->tm_mon + 1);
|
||||
wtm.wDayOfWeek = static_cast<WORD>(tm->tm_wday);
|
||||
wtm.wDay = static_cast<WORD>(tm->tm_mday);
|
||||
wtm.wHour = static_cast<WORD>(tm->tm_hour);
|
||||
wtm.wMinute = static_cast<WORD>(tm->tm_min);
|
||||
wtm.wSecond = static_cast<WORD>(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] Monday first
|
||||
case 'w': // weekday 0,7 0=Sunday
|
||||
case 'W': // week number of year [00,53] Monday 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"";
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_win
|
||||
|
||||
// boostinspect:nominmax
|
||||
#endif
|
||||
121
externals/boost/libs/locale/src/boost/locale/win32/collate.cpp
vendored
Normal file
121
externals/boost/libs/locale/src/boost/locale/win32/collate.cpp
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include "boost/locale/shared/mo_hash.hpp"
|
||||
#include "boost/locale/win32/api.hpp"
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
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) {}
|
||||
int
|
||||
do_compare(collate_level level, const char* lb, const char* le, const char* rb, const char* re) const override
|
||||
{
|
||||
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_);
|
||||
}
|
||||
long do_hash(collate_level level, const char* b, const char* e) const override
|
||||
{
|
||||
std::string key = do_transform(level, b, e);
|
||||
return gnu_gettext::pj_winberger_hash_function(key.c_str(), key.c_str() + key.size());
|
||||
}
|
||||
std::string do_transform(collate_level level, const char* b, const char* e) const override
|
||||
{
|
||||
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;
|
||||
BOOST_LOCALE_START_CONST_CONDITION
|
||||
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);
|
||||
}
|
||||
}
|
||||
BOOST_LOCALE_END_CONST_CONDITION
|
||||
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) {}
|
||||
int do_compare(collate_level level,
|
||||
const wchar_t* lb,
|
||||
const wchar_t* le,
|
||||
const wchar_t* rb,
|
||||
const wchar_t* re) const override
|
||||
{
|
||||
return wcscoll_l(level, lb, le, rb, re, lc_);
|
||||
}
|
||||
long do_hash(collate_level level, const wchar_t* b, const wchar_t* e) const override
|
||||
{
|
||||
std::wstring key = do_transform(level, b, e);
|
||||
const char* begin = reinterpret_cast<const char*>(key.c_str());
|
||||
const char* end = begin + key.size() * sizeof(wchar_t);
|
||||
return gnu_gettext::pj_winberger_hash_function(begin, end);
|
||||
}
|
||||
std::wstring do_transform(collate_level level, const wchar_t* b, const wchar_t* e) const override
|
||||
{
|
||||
return wcsxfrm_l(level, b, e, lc_);
|
||||
}
|
||||
|
||||
private:
|
||||
winlocale lc_;
|
||||
};
|
||||
|
||||
std::locale create_collate(const std::locale& in, const winlocale& lc, char_facet_t type)
|
||||
{
|
||||
if(lc.is_c()) {
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new std::collate_byname<char>("C"));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new std::collate_byname<wchar_t>("C"));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: return std::locale(in, new collate_byname<char16_t>("C"));
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: return std::locale(in, new collate_byname<char32_t>("C"));
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new utf8_collator(lc));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new utf16_collator(lc));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: break;
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_win
|
||||
82
externals/boost/libs/locale/src/boost/locale/win32/converter.cpp
vendored
Normal file
82
externals/boost/libs/locale/src/boost/locale/win32/converter.cpp
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/locale/conversion.hpp>
|
||||
#include <boost/locale/encoding.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include "boost/locale/win32/all_generator.hpp"
|
||||
#include "boost/locale/win32/api.hpp"
|
||||
#include <cstring>
|
||||
#include <locale>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost { namespace locale { namespace impl_win {
|
||||
|
||||
class utf16_converter : public converter<wchar_t> {
|
||||
public:
|
||||
utf16_converter(const winlocale& lc, size_t refs = 0) : converter<wchar_t>(refs), lc_(lc) {}
|
||||
std::wstring convert(converter_base::conversion_type how,
|
||||
const wchar_t* begin,
|
||||
const wchar_t* end,
|
||||
int flags = 0) const override
|
||||
{
|
||||
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);
|
||||
case converter_base::title_case: break;
|
||||
}
|
||||
return std::wstring(begin, end - begin);
|
||||
}
|
||||
|
||||
private:
|
||||
winlocale lc_;
|
||||
};
|
||||
|
||||
class utf8_converter : public converter<char> {
|
||||
public:
|
||||
utf8_converter(const winlocale& lc, size_t refs = 0) : converter<char>(refs), lc_(lc) {}
|
||||
std::string
|
||||
convert(converter_base::conversion_type how, const char* begin, const char* end, int flags = 0) const override
|
||||
{
|
||||
std::wstring tmp = conv::to_utf<wchar_t>(begin, end, "UTF-8");
|
||||
const wchar_t* wb = tmp.c_str();
|
||||
const wchar_t* 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;
|
||||
case title_case: break;
|
||||
}
|
||||
return conv::from_utf(res, "UTF-8");
|
||||
}
|
||||
|
||||
private:
|
||||
winlocale lc_;
|
||||
};
|
||||
|
||||
std::locale create_convert(const std::locale& in, const winlocale& lc, char_facet_t type)
|
||||
{
|
||||
switch(type) {
|
||||
case char_facet_t::nochar: break;
|
||||
case char_facet_t::char_f: return std::locale(in, new utf8_converter(lc));
|
||||
case char_facet_t::wchar_f: return std::locale(in, new utf16_converter(lc));
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
|
||||
case char_facet_t::char16_f: break;
|
||||
#endif
|
||||
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
|
||||
case char_facet_t::char32_f: break;
|
||||
#endif
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}}} // namespace boost::locale::impl_win
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user