update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -1,18 +1,16 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_BOUNDARY_HPP_INCLUDED
#define BOOST_LOCALE_BOUNDARY_HPP_INCLUDED
#include <boost/locale/boundary/types.hpp>
#include <boost/locale/boundary/facets.hpp>
#include <boost/locale/boundary/segment.hpp>
#include <boost/locale/boundary/boundary_point.hpp>
#include <boost/locale/boundary/facets.hpp>
#include <boost/locale/boundary/index.hpp>
#include <boost/locale/boundary/segment.hpp>
#include <boost/locale/boundary/types.hpp>
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,41 +1,37 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_BOUNDARY_BOUNDARY_POINT_HPP_INCLUDED
#define BOOST_LOCALE_BOUNDARY_BOUNDARY_POINT_HPP_INCLUDED
#include <boost/locale/boundary/types.hpp>
#include <string>
namespace boost {
namespace locale {
namespace boundary {
namespace boost { namespace locale { namespace boundary {
///
/// \addtogroup boundary
/// @{
/// \brief This class represents a boundary point in the text.
///
/// \brief This class represents a boundary point in the text.
///
/// It represents a pair - an iterator and a rule that defines this
/// It represents a pair - an iterator and a rule that defines this
/// point.
///
/// This type of object is dereference by the iterators of boundary_point_index. Using a rule()
/// member function you can get the reason why this specific boundary point was selected.
/// This type of object is dereferenced by the iterators of boundary_point_index. Using a rule()
/// member function you can get the reason why this specific boundary point was selected.
///
/// For example, When you use a sentence boundary analysis, the (rule() & \ref sentence_term) != 0 means
/// For example, when you use sentence boundary analysis, the (rule() & \ref sentence_term) != 0 means
/// that this boundary point was selected because a sentence terminator (like .?!) was spotted
/// and the (rule() & \ref sentence_sep)!=0 means that a separator like line feed or carriage
/// return was observed.
///
/// \note
///
/// - The beginning of analyzed range is always considered a boundary point and its rule is always 0.
/// - when using a word boundary analysis the returned rule relates to a chunk of text preceding
/// - The beginning of the analyzed range is always considered a boundary point and its rule is always 0.
/// - When using word boundary analysis, the returned rule relates to a chunk of text preceding
/// this point.
///
/// \see
@@ -45,139 +41,81 @@ namespace boundary {
/// - \ref segment_index
///
template<typename IteratorType>
class boundary_point {
class boundary_point {
public:
///
/// The type of the base iterator that iterates the original text
///
typedef IteratorType iterator_type;
///
/// Empty default constructor
///
boundary_point() : rule_(0) {}
///
/// Create a new boundary_point using iterator \p and a rule \a r
///
boundary_point(iterator_type p,rule_type r) :
iterator_(p),
rule_(r)
{
}
///
boundary_point(iterator_type p, rule_type r) : iterator_(p), rule_(r) {}
/// Set an new iterator value \a i
///
void iterator(iterator_type i)
{
iterator_ = i;
}
///
/// Set an new rule value \a r
///
void rule(rule_type r)
{
rule_ = r;
}
///
void iterator(iterator_type i) { iterator_ = i; }
/// Fetch an iterator
///
iterator_type iterator() const
{
return iterator_;
}
///
iterator_type iterator() const { return iterator_; }
/// Set an new rule value \a r
void rule(rule_type r) { rule_ = r; }
/// Fetch a rule
///
rule_type rule() const
{
return rule_;
}
///
rule_type rule() const { return rule_; }
/// Check if two boundary points are the same
///
bool operator==(boundary_point const &other) const
bool operator==(const boundary_point& other) const
{
return iterator_ == other.iterator_ && rule_ = other.rule_;
}
///
/// Check if two boundary points are different
///
bool operator!=(boundary_point const &other) const
{
return !(*this==other);
}
///
/// Check if the boundary point points to same location as an iterator \a other
///
bool operator==(iterator_type const &other) const
{
return iterator_ == other;
}
///
/// Check if the boundary point points to different location from an iterator \a other
///
bool operator!=(iterator_type const &other) const
{
return iterator_ != other;
}
bool operator!=(const boundary_point& other) const { return !(*this == other); }
/// Check if the boundary point points to same location as an iterator \a other
bool operator==(const iterator_type& other) const { return iterator_ == other; }
/// Check if the boundary point points to different location from an iterator \a other
bool operator!=(const iterator_type& other) const { return iterator_ != other; }
///
/// Automatic cast to the iterator it represents
///
operator iterator_type ()const
{
return iterator_;
}
operator iterator_type() const { return iterator_; }
private:
iterator_type iterator_;
rule_type rule_;
};
///
/// Check if the boundary point \a r points to same location as an iterator \a l
///
template<typename BaseIterator>
bool operator==(BaseIterator const &l,boundary_point<BaseIterator> const &r)
bool operator==(const BaseIterator& l, const boundary_point<BaseIterator>& r)
{
return r==l;
return r == l;
}
///
/// Check if the boundary point \a r points to different location from an iterator \a l
///
template<typename BaseIterator>
bool operator!=(BaseIterator const &l,boundary_point<BaseIterator> const &r)
bool operator!=(const BaseIterator& l, const boundary_point<BaseIterator>& r)
{
return r!=l;
return r != l;
}
/// @}
typedef boundary_point<std::string::const_iterator> sboundary_point; ///< convenience typedef
typedef boundary_point<std::wstring::const_iterator> wsboundary_point; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef boundary_point<std::u16string::const_iterator> u16sboundary_point;///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef boundary_point<std::u32string::const_iterator> u32sboundary_point;///< convenience typedef
#endif
typedef boundary_point<char const *> cboundary_point; ///< convenience typedef
typedef boundary_point<wchar_t const *> wcboundary_point; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef boundary_point<char16_t const *> u16cboundary_point; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef boundary_point<char32_t const *> u32cboundary_point; ///< convenience typedef
#endif
} // boundary
} // locale
} // boost
typedef boundary_point<std::string::const_iterator> sboundary_point; ///< convenience typedef
typedef boundary_point<std::wstring::const_iterator> wsboundary_point; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef boundary_point<std::u16string::const_iterator> u16sboundary_point; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef boundary_point<std::u32string::const_iterator> u32sboundary_point; ///< convenience typedef
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
typedef boundary_point<const char*> cboundary_point; ///< convenience typedef
typedef boundary_point<const wchar_t*> wcboundary_point; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef boundary_point<const char16_t*> u16cboundary_point; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef boundary_point<const char32_t*> u32cboundary_point; ///< convenience typedef
#endif
}}} // namespace boost::locale::boundary
#endif

View File

@@ -1,203 +1,83 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_BOUNDARY_FACETS_HPP_INCLUDED
#define BOOST_LOCALE_BOUNDARY_FACETS_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <boost/locale/boundary/types.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/detail/facet_id.hpp>
#include <boost/locale/detail/is_supported_char.hpp>
#include <locale>
#include <vector>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale {
namespace boost {
namespace locale {
/// \brief This namespace contains all operations required for boundary analysis of text
namespace boundary {
/// \addtogroup boundary
///
/// \brief This namespae contains all operations required for boundary analysis of text
/// @{
/// \brief This structure is used for representing boundary points
/// that follow the offset.
struct break_info {
/// Create empty break point at beginning
break_info() : offset(0), rule(0) {}
/// Create an empty break point at offset v.
/// it is useful for order comparison with other points.
break_info(size_t v) : offset(v), rule(0) {}
/// Offset from the beginning of the text where a break occurs.
size_t offset;
/// The identification of this break point according to
/// various break types
rule_type rule;
/// Compare two break points' offset. Allows to search with
/// standard algorithms over the index.
bool operator<(const break_info& other) const { return offset < other.offset; }
};
/// This type holds the analysis of the text - all its break points
/// with marks
typedef std::vector<break_info> index_type;
/// \brief This facet generates an index for boundary analysis of a given text.
///
namespace boundary {
///
/// \addtogroup boundary
///
/// @{
/// It is implemented for supported character types, at least \c char, \c wchar_t
template<typename Char>
class BOOST_SYMBOL_VISIBLE boundary_indexing : public std::locale::facet,
public boost::locale::detail::facet_id<boundary_indexing<Char>> {
BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char);
public:
/// Default constructor typical for facets
boundary_indexing(size_t refs = 0) : std::locale::facet(refs) {}
/// Create index for boundary type \a t for text in range [begin,end)
///
/// The returned value is an index of type \ref index_type. Note that this
/// index is never empty, even if the range [begin,end) is empty it consists
/// of at least one boundary point with the offset 0.
virtual index_type map(boundary_type t, const Char* begin, const Char* end) const = 0;
};
///
/// \brief This structure is used for representing boundary point
/// that follows the offset.
///
struct break_info {
///
/// Create empty break point at beginning
///
break_info() :
offset(0),
rule(0)
{
}
///
/// Create empty break point at offset v.
/// it is useful for order comparison with other points.
///
break_info(size_t v) :
offset(v),
rule(0)
{
}
///
/// Offset from the beggining of the text where a break occurs.
///
size_t offset;
///
/// The identification of this break point according to
/// various break types
///
rule_type rule;
///
/// Compare two break points' offset. Allows to search with
/// standard algorithms over the index.
///
bool operator<(break_info const &other) const
{
return offset < other.offset;
}
};
///
/// This type holds the analysis of the text - all its break points
/// with marks
///
typedef std::vector<break_info> index_type;
template<typename CharType>
class boundary_indexing;
#ifdef BOOST_LOCALE_DOXYGEN
///
/// \brief This facet generates an index for boundary analysis
/// for a given text.
///
/// It is specialized for 4 types of characters \c char_t, \c wchar_t, \c char16_t and \c char32_t
///
template<typename Char>
class BOOST_LOCALE_DECL boundary_indexing : public std::locale::facet {
public:
///
/// Default constructor typical for facets
///
boundary_indexing(size_t refs=0) : std::locale::facet(refs)
{
}
///
/// Create index for boundary type \a t for text in range [begin,end)
///
/// The returned value is an index of type \ref index_type. Note that this
/// index is never empty, even if the range [begin,end) is empty it consists
/// of at least one boundary point with the offset 0.
///
virtual index_type map(boundary_type t,Char const *begin,Char const *end) const = 0;
///
/// Identification of this facet
///
static std::locale::id id;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#else
template<>
class BOOST_LOCALE_DECL boundary_indexing<char> : public std::locale::facet {
public:
boundary_indexing(size_t refs=0) : std::locale::facet(refs)
{
}
virtual index_type map(boundary_type t,char const *begin,char const *end) const = 0;
static std::locale::id id;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
template<>
class BOOST_LOCALE_DECL boundary_indexing<wchar_t> : public std::locale::facet {
public:
boundary_indexing(size_t refs=0) : std::locale::facet(refs)
{
}
virtual index_type map(boundary_type t,wchar_t const *begin,wchar_t const *end) const = 0;
static std::locale::id id;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<>
class BOOST_LOCALE_DECL boundary_indexing<char16_t> : public std::locale::facet {
public:
boundary_indexing(size_t refs=0) : std::locale::facet(refs)
{
}
virtual index_type map(boundary_type t,char16_t const *begin,char16_t const *end) const = 0;
static std::locale::id id;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<>
class BOOST_LOCALE_DECL boundary_indexing<char32_t> : public std::locale::facet {
public:
boundary_indexing(size_t refs=0) : std::locale::facet(refs)
{
}
virtual index_type map(boundary_type t,char32_t const *begin,char32_t const *end) const = 0;
static std::locale::id id;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#endif
#endif
///
/// @}
///
} // boundary
} // locale
} // boost
/// @}
} // namespace boundary
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +1,82 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_BOUNDARY_SEGMENT_HPP_INCLUDED
#define BOOST_LOCALE_BOUNDARY_SEGMENT_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <locale>
#include <string>
#include <boost/locale/util/string.hpp>
#include <iosfwd>
#include <iterator>
#include <locale>
#include <string>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
namespace locale {
namespace boundary {
namespace boost { namespace locale { namespace boundary {
/// \cond INTERNAL
namespace details {
template<typename LeftIterator,typename RightIterator>
int compare_text(LeftIterator l_begin,LeftIterator l_end,RightIterator r_begin,RightIterator r_end)
namespace detail {
template<typename LeftIterator, typename RightIterator>
int compare_text(LeftIterator l_begin, LeftIterator l_end, RightIterator r_begin, RightIterator r_end)
{
typedef LeftIterator left_iterator;
typedef typename std::iterator_traits<left_iterator>::value_type char_type;
typedef std::char_traits<char_type> traits;
while(l_begin!=l_end && r_begin!=r_end) {
while(l_begin != l_end && r_begin != r_end) {
char_type lchar = *l_begin++;
char_type rchar = *r_begin++;
if(traits::eq(lchar,rchar))
if(traits::eq(lchar, rchar))
continue;
if(traits::lt(lchar,rchar))
if(traits::lt(lchar, rchar))
return -1;
else
return 1;
}
if(l_begin==l_end && r_begin==r_end)
if(l_begin == l_end && r_begin == r_end)
return 0;
if(l_begin==l_end)
if(l_begin == l_end)
return -1;
else
return 1;
}
template<typename Left,typename Right>
int compare_text(Left const &l,Right const &r)
template<typename Left, typename Right>
int compare_text(const Left& l, const Right& r)
{
return compare_text(l.begin(),l.end(),r.begin(),r.end());
}
template<typename Left,typename Char>
int compare_string(Left const &l,Char const *begin)
{
Char const *end = begin;
while(*end!=0)
end++;
return compare_text(l.begin(),l.end(),begin,end);
return compare_text(l.begin(), l.end(), r.begin(), r.end());
}
template<typename Right,typename Char>
int compare_string(Char const *begin,Right const &r)
template<typename Left, typename Char>
int compare_string(const Left& l, const Char* begin)
{
Char const *end = begin;
while(*end!=0)
end++;
return compare_text(begin,end,r.begin(),r.end());
return compare_text(l.begin(), l.end(), begin, util::str_end(begin));
}
}
template<typename Right, typename Char>
int compare_string(const Char* begin, const Right& r)
{
return compare_text(begin, util::str_end(begin), r.begin(), r.end());
}
} // namespace detail
/// \endcond
///
/// \addtogroup boundary
/// @{
///
/// \brief a segment object that represents a pair of two iterators that define the range where
/// this segment exits and a rule that defines it.
///
/// This type of object is dereferenced by the iterators of segment_index. Using a rule() member function
/// you can get a specific rule this segment was selected with. For example, when you use
/// word boundary analysis, you can check if the specific word contains Kana letters by checking (rule() & \ref word_kana)!=0
/// For a sentence analysis you can check if the sentence is selected because a sentence terminator is found (\ref sentence_term) or
/// there is a line break (\ref sentence_sep).
/// word boundary analysis, you can check if the specific word contains Kana letters by checking (rule() & \ref
/// word_kana)!=0 For a sentence analysis you can check if the sentence is selected because a sentence terminator is
/// found (\ref sentence_term) or there is a line break (\ref sentence_sep).
///
/// This object can be automatically converted to std::basic_string with the same type of character. It is also
/// valid range that has begin() and end() member functions returning iterators on the location of the segment.
@@ -95,389 +84,294 @@ namespace boundary {
/// \see
///
/// - \ref segment_index
/// - \ref boundary_point
/// - \ref boundary_point_index
///
/// - \ref boundary_point
/// - \ref boundary_point_index
template<typename IteratorType>
class segment : public std::pair<IteratorType,IteratorType> {
class segment : public std::pair<IteratorType, IteratorType> {
public:
///
/// The type of the underlying character
///
/// The type of the underlying character
typedef typename std::iterator_traits<IteratorType>::value_type char_type;
///
/// The type of the string it is converted to
///
typedef std::basic_string<char_type> string_type;
///
/// The value that iterators return - the character itself
///
typedef char_type value_type;
///
/// The iterator that allows to iterate the range
///
typedef IteratorType iterator;
///
/// The iterator that allows to iterate the range
///
typedef IteratorType const_iterator;
///
/// The type that represent a difference between two iterators
///
typedef typename std::iterator_traits<IteratorType>::difference_type difference_type;
///
/// Default constructor
///
segment() {}
///
segment() : rule_(0) {}
/// Create a segment using two iterators and a rule that represents this point
///
segment(iterator b,iterator e,rule_type r) :
std::pair<IteratorType,IteratorType>(b,e),
rule_(r)
{
}
///
segment(iterator b, iterator e, rule_type r) : std::pair<IteratorType, IteratorType>(b, e), rule_(r) {}
/// Set the start of the range
///
void begin(iterator const &v)
{
this->first = v;
}
///
void begin(const iterator& v) { this->first = v; }
/// Set the end of the range
///
void end(iterator const &v)
{
this->second = v;
}
void end(const iterator& v) { this->second = v; }
///
/// Get the start of the range
///
IteratorType begin() const
{
return this->first;
}
///
IteratorType begin() const { return this->first; }
/// Set the end of the range
///
IteratorType end() const
{
return this->second;
}
IteratorType end() const { return this->second; }
///
/// Convert the range to a string automatically
///
template <class T, class A>
operator std::basic_string<char_type, T, A> ()const
template<class T, class A>
operator std::basic_string<char_type, T, A>() const
{
return std::basic_string<char_type, T, A>(this->first, this->second);
}
///
/// Create a string from the range explicitly
///
string_type str() const
{
return string_type(begin(),end());
}
string_type str() const { return string_type(begin(), end()); }
///
/// Get the length of the text chunk
///
size_t length() const { return std::distance(begin(), end()); }
size_t length() const
{
return std::distance(begin(),end());
}
///
/// Check if the segment is empty
///
bool empty() const
{
return begin() == end();
}
bool empty() const { return begin() == end(); }
///
/// Get the rule that is used for selection of this segment.
///
rule_type rule() const
{
return rule_;
}
///
rule_type rule() const { return rule_; }
/// Set a rule that is used for segment selection
///
void rule(rule_type r)
{
rule_ = r;
}
void rule(rule_type r) { rule_ = r; }
// make sure we override std::pair's operator==
/// Compare two segments
bool operator==(segment const &other)
{
return details::compare_text(*this,other) == 0;
}
bool operator==(const segment& other) const { return detail::compare_text(*this, other) == 0; }
/// Compare two segments
bool operator!=(segment const &other)
{
return details::compare_text(*this,other) != 0;
}
bool operator!=(const segment& other) const { return detail::compare_text(*this, other) != 0; }
private:
rule_type rule_;
};
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator==(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator==(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) == 0;
return detail::compare_text(l, r) == 0;
}
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator!=(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator!=(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) != 0;
return detail::compare_text(l, r) != 0;
}
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator<(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator<(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) < 0;
return detail::compare_text(l, r) < 0;
}
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator<=(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator<=(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) <= 0;
return detail::compare_text(l, r) <= 0;
}
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator>(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator>(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) > 0;
return detail::compare_text(l, r) > 0;
}
/// Compare two segments
template<typename IteratorL,typename IteratorR>
bool operator>=(segment<IteratorL> const &l,segment<IteratorR> const &r)
template<typename IteratorL, typename IteratorR>
bool operator>=(const segment<IteratorL>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) >= 0;
return detail::compare_text(l, r) >= 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator==(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator==(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) == 0;
return detail::compare_text(l, r) == 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator!=(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator!=(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) != 0;
return detail::compare_text(l, r) != 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator<(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator<(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) < 0;
return detail::compare_text(l, r) < 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator<=(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator<=(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) <= 0;
return detail::compare_text(l, r) <= 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator>(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator>(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) > 0;
return detail::compare_text(l, r) > 0;
}
/// Compare string and segment
template<typename CharType,typename Traits,typename Alloc,typename IteratorR>
bool operator>=(std::basic_string<CharType,Traits,Alloc> const &l,segment<IteratorR> const &r)
template<typename CharType, typename Traits, typename Alloc, typename IteratorR>
bool operator>=(const std::basic_string<CharType, Traits, Alloc>& l, const segment<IteratorR>& r)
{
return details::compare_text(l,r) >= 0;
return detail::compare_text(l, r) >= 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator==(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator==(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) == 0;
return detail::compare_text(l, r) == 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator!=(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator!=(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) != 0;
return detail::compare_text(l, r) != 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator<(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator<(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) < 0;
return detail::compare_text(l, r) < 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator<=(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator<=(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) <= 0;
return detail::compare_text(l, r) <= 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator>(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator>(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) > 0;
return detail::compare_text(l, r) > 0;
}
/// Compare string and segment
template<typename Iterator,typename CharType,typename Traits,typename Alloc>
bool operator>=(segment<Iterator> const &l,std::basic_string<CharType,Traits,Alloc> const &r)
template<typename Iterator, typename CharType, typename Traits, typename Alloc>
bool operator>=(const segment<Iterator>& l, const std::basic_string<CharType, Traits, Alloc>& r)
{
return details::compare_text(l,r) >= 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator==(CharType const *l,segment<IteratorR> const &r)
{
return details::compare_string(l,r) == 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator!=(CharType const *l,segment<IteratorR> const &r)
{
return details::compare_string(l,r) != 0;
return detail::compare_text(l, r) >= 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator<(CharType const *l,segment<IteratorR> const &r)
template<typename CharType, typename IteratorR>
bool operator==(const CharType* l, const segment<IteratorR>& r)
{
return details::compare_string(l,r) < 0;
return detail::compare_string(l, r) == 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator<=(CharType const *l,segment<IteratorR> const &r)
template<typename CharType, typename IteratorR>
bool operator!=(const CharType* l, const segment<IteratorR>& r)
{
return details::compare_string(l,r) <= 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator>(CharType const *l,segment<IteratorR> const &r)
{
return details::compare_string(l,r) > 0;
}
/// Compare C string and segment
template<typename CharType,typename IteratorR>
bool operator>=(CharType const *l,segment<IteratorR> const &r)
{
return details::compare_string(l,r) >= 0;
return detail::compare_string(l, r) != 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator==(segment<Iterator> const &l,CharType const *r)
template<typename CharType, typename IteratorR>
bool operator<(const CharType* l, const segment<IteratorR>& r)
{
return details::compare_string(l,r) == 0;
return detail::compare_string(l, r) < 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator!=(segment<Iterator> const &l,CharType const *r)
template<typename CharType, typename IteratorR>
bool operator<=(const CharType* l, const segment<IteratorR>& r)
{
return details::compare_string(l,r) != 0;
return detail::compare_string(l, r) <= 0;
}
/// Compare C string and segment
template<typename CharType, typename IteratorR>
bool operator>(const CharType* l, const segment<IteratorR>& r)
{
return detail::compare_string(l, r) > 0;
}
/// Compare C string and segment
template<typename CharType, typename IteratorR>
bool operator>=(const CharType* l, const segment<IteratorR>& r)
{
return detail::compare_string(l, r) >= 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator<(segment<Iterator> const &l,CharType const *r)
template<typename Iterator, typename CharType>
bool operator==(const segment<Iterator>& l, const CharType* r)
{
return details::compare_string(l,r) < 0;
return detail::compare_string(l, r) == 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator<=(segment<Iterator> const &l,CharType const *r)
template<typename Iterator, typename CharType>
bool operator!=(const segment<Iterator>& l, const CharType* r)
{
return details::compare_string(l,r) <= 0;
return detail::compare_string(l, r) != 0;
}
/// Compare C string and segment
template<typename Iterator, typename CharType>
bool operator<(const segment<Iterator>& l, const CharType* r)
{
return detail::compare_string(l, r) < 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator>(segment<Iterator> const &l,CharType const *r)
template<typename Iterator, typename CharType>
bool operator<=(const segment<Iterator>& l, const CharType* r)
{
return details::compare_string(l,r) > 0;
return detail::compare_string(l, r) <= 0;
}
/// Compare C string and segment
template<typename Iterator,typename CharType>
bool operator>=(segment<Iterator> const &l,CharType const *r)
template<typename Iterator, typename CharType>
bool operator>(const segment<Iterator>& l, const CharType* r)
{
return details::compare_string(l,r) >= 0;
return detail::compare_string(l, r) > 0;
}
/// Compare C string and segment
template<typename Iterator, typename CharType>
bool operator>=(const segment<Iterator>& l, const CharType* r)
{
return detail::compare_string(l, r) >= 0;
}
typedef segment<std::string::const_iterator> ssegment; ///< convenience typedef
typedef segment<std::wstring::const_iterator> wssegment; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef segment<std::u16string::const_iterator> u16ssegment; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef segment<std::u32string::const_iterator> u32ssegment; ///< convenience typedef
#endif
typedef segment<const char*> csegment; ///< convenience typedef
typedef segment<const wchar_t*> wcsegment; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef segment<const char16_t*> u16csegment; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef segment<const char32_t*> u32csegment; ///< convenience typedef
#endif
typedef segment<std::string::const_iterator> ssegment; ///< convenience typedef
typedef segment<std::wstring::const_iterator> wssegment; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef segment<std::u16string::const_iterator> u16ssegment;///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef segment<std::u32string::const_iterator> u32ssegment;///< convenience typedef
#endif
typedef segment<char const *> csegment; ///< convenience typedef
typedef segment<wchar_t const *> wcsegment; ///< convenience typedef
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
typedef segment<char16_t const *> u16csegment; ///< convenience typedef
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
typedef segment<char32_t const *> u32csegment; ///< convenience typedef
#endif
///
/// Write the segment to the stream character by character
///
template<typename CharType,typename TraitsType,typename Iterator>
std::basic_ostream<CharType,TraitsType> &operator<<(
std::basic_ostream<CharType,TraitsType> &out,
segment<Iterator> const &tok)
template<typename CharType, typename TraitsType, typename Iterator>
std::basic_ostream<CharType, TraitsType>& operator<<(std::basic_ostream<CharType, TraitsType>& out,
const segment<Iterator>& seg)
{
for(Iterator p=tok.begin(),e=tok.end();p!=e;++p)
out << *p;
for(const auto& p : seg)
out << p;
return out;
}
/// @}
} // boundary
} // locale
} // boost
}}} // namespace boost::locale::boundary
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,136 +1,110 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_BOUNDARY_TYPES_HPP_INCLUDED
#define BOOST_LOCALE_BOUNDARY_TYPES_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/assert.hpp>
#include <cstdint>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale {
namespace boost {
namespace locale {
/// \brief This namespace contains all operations required for boundary analysis of text
namespace boundary {
/// \defgroup boundary Boundary Analysis
///
/// \brief This namespase contains all operations required for boundary analysis of text
/// This module contains all operations required for boundary analysis of text: character, word, like and
/// sentence boundaries
///
namespace boundary {
///
/// \defgroup boundary Boundary Analysis
///
/// This module contains all operations required for boundary analysis of text: character, word, like and sentence boundaries
///
/// @{
///
/// @{
///
/// This type describes a possible boundary analysis alternatives.
///
enum boundary_type {
character, ///< Analyse the text for character boundaries
word, ///< Analyse the text for word boundaries
sentence, ///< Analyse the text for Find sentence boundaries
line ///< Analyse the text for positions suitable for line breaks
};
/// This type describes a possible boundary analysis alternatives.
enum boundary_type {
character, ///< Analyse the text for character boundaries
word, ///< Analyse the text for word boundaries
sentence, ///< Analyse the text for Find sentence boundaries
line ///< Analyse the text for positions suitable for line breaks
};
///
/// \brief Flags used with word boundary analysis -- the type of the word, line or sentence boundary found.
///
/// It is a bit-mask that represents various combinations of rules used to select this specific boundary.
///
typedef uint32_t rule_type;
/// \brief Flags used with word boundary analysis -- the type of the word, line or sentence boundary found.
///
/// It is a bit-mask that represents various combinations of rules used to select this specific boundary.
typedef uint32_t rule_type;
///
/// \anchor bl_boundary_word_rules
/// \name Flags that describe a type of word selected
/// @{
static const rule_type
word_none = 0x0000F, ///< Not a word, like white space or punctuation mark
word_number = 0x000F0, ///< Word that appear to be a number
word_letter = 0x00F00, ///< Word that contains letters, excluding kana and ideographic characters
word_kana = 0x0F000, ///< Word that contains kana characters
word_ideo = 0xF0000, ///< Word that contains ideographic characters
word_any = 0xFFFF0, ///< Any word including numbers, 0 is special flag, equivalent to 15
word_letters = 0xFFF00, ///< Any word, excluding numbers but including letters, kana and ideograms.
word_kana_ideo = 0xFF000, ///< Word that includes kana or ideographic characters
word_mask = 0xFFFFF; ///< Full word mask - select all possible variants
/// @}
/// \anchor bl_boundary_word_rules
/// \name Flags that describe a type of word selected
/// @{
constexpr rule_type word_none = 0x0000F, ///< Not a word, like white space or punctuation mark
word_number = 0x000F0, ///< Word that appear to be a number
word_letter = 0x00F00, ///< Word that contains letters, excluding kana and ideographic characters
word_kana = 0x0F000, ///< Word that contains kana characters
word_ideo = 0xF0000, ///< Word that contains ideographic characters
word_any = 0xFFFF0, ///< Any word including numbers, 0 is special flag, equivalent to 15
word_letters = 0xFFF00, ///< Any word, excluding numbers but including letters, kana and ideograms.
word_kana_ideo = 0xFF000, ///< Word that includes kana or ideographic characters
word_mask = 0xFFFFF; ///< Full word mask - select all possible variants
/// @}
///
/// \anchor bl_boundary_line_rules
/// \name Flags that describe a type of line break
/// @{
static const rule_type
line_soft = 0x0F, ///< Soft line break: optional but not required
line_hard = 0xF0, ///< Hard line break: like break is required (as per CR/LF)
line_any = 0xFF, ///< Soft or Hard line break
line_mask = 0xFF; ///< Select all types of line breaks
/// @}
///
/// \anchor bl_boundary_sentence_rules
/// \name Flags that describe a type of sentence break
///
/// @{
static const rule_type
sentence_term = 0x0F, ///< \brief The sentence was terminated with a sentence terminator
/// like ".", "!" possible followed by hard separator like CR, LF, PS
sentence_sep = 0xF0, ///< \brief The sentence does not contain terminator like ".", "!" but ended with hard separator
/// like CR, LF, PS or end of input.
sentence_any = 0xFF, ///< Either first or second sentence break type;.
sentence_mask = 0xFF; ///< Select all sentence breaking points
/// \anchor bl_boundary_line_rules
/// \name Flags that describe a type of line break
/// @{
constexpr rule_type line_soft = 0x0F, ///< Soft line break: optional but not required
line_hard = 0xF0, ///< Hard line break: like break is required (as per CR/LF)
line_any = 0xFF, ///< Soft or Hard line break
line_mask = 0xFF; ///< Select all types of line breaks
///@}
/// @}
///
/// \name Flags that describe a type of character break.
///
/// At this point break iterator does not distinguish different
/// kinds of characters so it is used for consistency.
///@{
static const rule_type
character_any = 0xF, ///< Not in use, just for consistency
character_mask = 0xF; ///< Select all character breaking points
/// \anchor bl_boundary_sentence_rules
/// \name Flags that describe a type of sentence break
///
/// @{
constexpr rule_type sentence_term = 0x0F, ///< \brief The sentence was terminated with a sentence terminator
/// like ".", "!" possible followed by hard separator like CR, LF, PS
sentence_sep =
0xF0, ///< \brief The sentence does not contain terminator like ".", "!" but ended with hard separator
/// like CR, LF, PS or end of input.
sentence_any = 0xFF, ///< Either first or second sentence break type;.
sentence_mask = 0xFF; ///< Select all sentence breaking points
///@}
///@}
///
/// This function returns the mask that covers all variants for specific boundary type
///
inline rule_type boundary_rule(boundary_type t)
{
switch(t) {
/// \name Flags that describe a type of character break.
///
/// At this point break iterator does not distinguish different
/// kinds of characters so it is used for consistency.
///@{
constexpr rule_type character_any = 0xF, ///< Not in use, just for consistency
character_mask = 0xF; ///< Select all character breaking points
///@}
/// This function returns the mask that covers all variants for specific boundary type
inline rule_type boundary_rule(boundary_type t)
{
switch(t) {
case character: return character_mask;
case word: return word_mask;
case sentence: return sentence_mask;
case line: return line_mask;
default: return 0;
}
case word: return word_mask;
case sentence: return sentence_mask;
case line: return line_mask;
}
return 0;
}
///
///@}
///
} // boundary
} // locale
} // boost
///@}
} // namespace boundary
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,86 +1,71 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_COLLATOR_HPP_INCLUDED
#define BOOST_LOCALE_COLLATOR_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <locale>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
namespace locale {
namespace boost { namespace locale {
class info;
///
/// \defgroup collation Collation
/// \defgroup collation Collation
///
/// This module introduces collation related classes
///
/// @{
///
/// \brief a base class that includes collation level flags
///
class collator_base {
public:
///
/// Unicode collation level types
///
typedef enum {
primary = 0, ///< 1st collation level: base letters
secondary = 1, ///< 2nd collation level: letters and accents
tertiary = 2, ///< 3rd collation level: letters, accents and case
quaternary = 3, ///< 4th collation level: letters, accents, case and punctuation
identical = 4 ///< identical collation level: include code-point comparison
} level_type;
/// Unicode collation level types
enum class collate_level {
primary = 0, ///< 1st collation level: base letters
secondary = 1, ///< 2nd collation level: letters and accents
tertiary = 2, ///< 3rd collation level: letters, accents and case
quaternary = 3, ///< 4th collation level: letters, accents, case and punctuation
identical = 4 ///< identical collation level: include code-point comparison
};
///
/// \brief Collation facet.
class BOOST_DEPRECATED("Use collate_level") collator_base {
public:
using level_type = collate_level;
static constexpr auto primary = collate_level::primary;
static constexpr auto secondary = collate_level::secondary;
static constexpr auto tertiary = collate_level::tertiary;
static constexpr auto quaternary = collate_level::quaternary;
static constexpr auto identical = collate_level::identical;
};
/// \brief Collation facet.
///
/// It reimplements standard C++ std::collate,
/// allowing usage of std::locale for direct string comparison
///
template<typename CharType>
class collator :
public std::collate<CharType>,
public collator_base
{
class collator : public std::collate<CharType> {
public:
///
/// Type of the underlying character
///
typedef CharType char_type;
///
/// Type of string used with this facet
///
typedef std::basic_string<CharType> string_type;
///
/// Compare two strings in rage [b1,e1), [b2,e2) according using a collation level \a level. Calls do_compare
///
/// Returns -1 if the first of the two strings sorts before the seconds, returns 1 if sorts after and 0 if
/// they considered equal.
///
int compare(level_type level,
char_type const *b1,char_type const *e1,
char_type const *b2,char_type const *e2) const
int compare(collate_level level,
const char_type* b1,
const char_type* e1,
const char_type* b2,
const char_type* e2) const
{
return do_compare(level,b1,e1,b2,e2);
return do_compare(level, b1, e1, b2, e2);
}
///
/// Create a binary string that can be compared to other in order to get collation order. The string is created
/// for text in range [b,e). It is useful for collation of multiple strings for text.
///
@@ -90,47 +75,35 @@ namespace locale {
/// \endcode
///
/// Calls do_transform
///
string_type transform(level_type level,char_type const *b,char_type const *e) const
string_type transform(collate_level level, const char_type* b, const char_type* e) const
{
return do_transform(level,b,e);
return do_transform(level, b, e);
}
///
/// Calculate a hash of a text in range [b,e). The value can be used for collation sensitive string comparison.
///
/// If compare(level,b1,e1,b2,e2) == 0 then hash(level,b1,e1) == hash(level,b2,e2)
///
/// Calls do_hash
///
long hash(level_type level,char_type const *b,char_type const *e) const
{
return do_hash(level,b,e);
}
long hash(collate_level level, const char_type* b, const char_type* e) const { return do_hash(level, b, e); }
///
/// Compare two strings \a l and \a r using collation level \a level
///
/// Returns -1 if the first of the two strings sorts before the seconds, returns 1 if sorts after and 0 if
/// they considered equal.
///
///
int compare(level_type level,string_type const &l,string_type const &r) const
int compare(collate_level level, const string_type& l, const string_type& r) const
{
return do_compare(level,l.data(),l.data()+l.size(),r.data(),r.data()+r.size());
return do_compare(level, l.data(), l.data() + l.size(), r.data(), r.data() + r.size());
}
///
/// Calculate a hash that can be used for collation sensitive string comparison of a string \a s
///
/// If compare(level,s1,s2) == 0 then hash(level,s1) == hash(level,s2)
///
long hash(level_type level,string_type const &s) const
long hash(collate_level level, const string_type& s) const
{
return do_hash(level,s.data(),s.data()+s.size());
return do_hash(level, s.data(), s.data() + s.size());
}
///
/// Create a binary string from string \a s, that can be compared to other, useful for collation of multiple
/// strings.
///
@@ -138,124 +111,92 @@ namespace locale {
/// \code
/// compare(level,s1,s2) == sign( transform(level,s1).compare(transform(level,s2)) );
/// \endcode
///
string_type transform(level_type level,string_type const &s) const
string_type transform(collate_level level, const string_type& s) const
{
return do_transform(level,s.data(),s.data()+s.size());
return do_transform(level, s.data(), s.data() + s.size());
}
protected:
///
/// constructor of the collator object
///
collator(size_t refs = 0) : std::collate<CharType>(refs)
{
}
collator(size_t refs = 0) : std::collate<CharType>(refs) {}
virtual ~collator()
{
}
///
/// This function is used to override default collation function that does not take in account collation level.
/// Uses primary level
///
virtual int do_compare( char_type const *b1,char_type const *e1,
char_type const *b2,char_type const *e2) const
int
do_compare(const char_type* b1, const char_type* e1, const char_type* b2, const char_type* e2) const override
{
return do_compare(identical,b1,e1,b2,e2);
return do_compare(collate_level::identical, b1, e1, b2, e2);
}
///
/// This function is used to override default collation function that does not take in account collation level.
/// Uses primary level
///
virtual string_type do_transform(char_type const *b,char_type const *e) const
string_type do_transform(const char_type* b, const char_type* e) const override
{
return do_transform(identical,b,e);
return do_transform(collate_level::identical, b, e);
}
///
/// This function is used to override default collation function that does not take in account collation level.
/// Uses primary level
///
virtual long do_hash(char_type const *b,char_type const *e) const
long do_hash(const char_type* b, const char_type* e) const override
{
return do_hash(identical,b,e);
return do_hash(collate_level::identical, b, e);
}
///
/// Actual function that performs comparison between the strings. For details see compare member function. Can be overridden.
///
virtual int do_compare( level_type level,
char_type const *b1,char_type const *e1,
char_type const *b2,char_type const *e2) const = 0;
///
/// Actual function that performs transformation. For details see transform member function. Can be overridden.
///
virtual string_type do_transform(level_type level,char_type const *b,char_type const *e) const = 0;
///
/// Actual function that calculates hash. For details see hash member function. Can be overridden.
///
virtual long do_hash(level_type level,char_type const *b,char_type const *e) const = 0;
/// Actual function that performs comparison between the strings. For details see compare member function. Can
/// be overridden.
virtual int do_compare(collate_level level,
const char_type* b1,
const char_type* e1,
const char_type* b2,
const char_type* e2) const = 0;
/// Actual function that performs transformation. For details see transform member function. Can be overridden.
virtual string_type do_transform(collate_level level, const char_type* b, const char_type* e) const = 0;
/// Actual function that calculates hash. For details see hash member function. Can be overridden.
virtual long do_hash(collate_level level, const char_type* b, const char_type* e) const = 0;
};
///
/// \brief This class can be used in STL algorithms and containers for comparison of strings
/// with a level other than primary
///
/// For example:
///
/// \code
/// std::map<std::string,std::string,comparator<char,collator_base::secondary> > data;
/// std::map<std::string,std::string,comparator<char,collate_level::secondary> > data;
/// \endcode
///
/// Would create a map the keys of which are sorted using secondary collation level
///
template<typename CharType,collator_base::level_type default_level = collator_base::identical>
struct comparator
{
/// Would create a map the keys of which are sorted using secondary collation level
template<typename CharType, collate_level default_level = collate_level::identical>
struct comparator {
public:
///
/// Create a comparator class for locale \a l and with collation leval \a level
///
/// \note throws std::bad_cast if l does not have \ref collator facet installed
///
comparator(std::locale const &l=std::locale(),collator_base::level_type level=default_level) :
locale_(l),
level_(level)
/// \throws std::bad_cast: \a l does not have \ref collator facet installed
comparator(const std::locale& l = std::locale(), collate_level level = default_level) :
locale_(l), level_(level)
{}
/// Compare two strings -- equivalent to return left < right according to collation rules
bool operator()(const std::basic_string<CharType>& left, const std::basic_string<CharType>& right) const
{
return std::use_facet<collator<CharType>>(locale_).compare(level_, left, right) < 0;
}
///
/// Compare two strings -- equivalent to return left < right according to collation rules
///
bool operator()(std::basic_string<CharType> const &left,std::basic_string<CharType> const &right) const
{
return std::use_facet<collator<CharType> >(locale_).compare(level_,left,right) < 0;
}
private:
std::locale locale_;
collator_base::level_type level_;
collate_level level_;
};
///
///@}
///
} // locale
} // boost
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
///
/// \example collate.cpp
/// Example of using collation functions
///
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#endif

View File

@@ -1,37 +1,87 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_CONFIG_HPP_INCLUDED
#define BOOST_LOCALE_CONFIG_HPP_INCLUDED
#include <boost/locale/definitions.hpp>
#include <boost/config.hpp>
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_LOCALE_DYN_LINK)
# ifdef BOOST_LOCALE_SOURCE
# define BOOST_LOCALE_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_LOCALE_DECL BOOST_SYMBOL_IMPORT
# endif // BOOST_LOCALE_SOURCE
#else
# define BOOST_LOCALE_DECL
#endif // BOOST_LOCALE_DYN_LINK
//
// Automatically link to the correct build variant where possible.
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_LOCALE_NO_LIB) && !defined(BOOST_LOCALE_SOURCE)
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#define BOOST_LIB_NAME boost_locale
# define BOOST_LIB_NAME boost_locale
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_LOCALE_DYN_LINK)
# define BOOST_DYN_LINK
#endif
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_LOCALE_DYN_LINK)
# define BOOST_DYN_LINK
# endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
# include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
// Check for some C++11 features to provide easier checks for what is missing
// shortly after the requirement of C++11 in Boost 1.81
// clang-format off
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \
defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || \
defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || \
defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) || \
defined(BOOST_NO_CXX11_NOEXCEPT) || \
defined(BOOST_NO_CXX11_OVERRIDE) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
defined(BOOST_NO_CXX11_SMART_PTR) || \
defined(BOOST_NO_CXX11_STATIC_ASSERT)
// clang-format on
# error "Boost.Locale requires C++11 since Boost 1.81."
#endif
#ifdef _MSC_VER
// Denote a constant condition, e.g. for if(sizeof(...
# define BOOST_LOCALE_START_CONST_CONDITION __pragma(warning(push)) __pragma(warning(disable : 4127))
# define BOOST_LOCALE_END_CONST_CONDITION __pragma(warning(pop))
#else
# define BOOST_LOCALE_START_CONST_CONDITION
# define BOOST_LOCALE_END_CONST_CONDITION
#endif
/// \cond INTERNAL
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// Internal define to check if we have access to the Win32 API
# define BOOST_LOCALE_USE_WIN32_API 1
#else
# define BOOST_LOCALE_USE_WIN32_API 0
#endif
// To be used to suppress false positives of UBSAN
#if defined(__clang__) && defined(__has_attribute)
# if __has_attribute(no_sanitize)
# define BOOST_LOCALE_NO_SANITIZE(what) __attribute__((no_sanitize(what)))
# endif
#endif
#if !defined(BOOST_LOCALE_NO_SANITIZE)
# define BOOST_LOCALE_NO_SANITIZE(what)
#endif
/// \endcond
#endif // boost/locale/config.hpp
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,372 +1,243 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_CONVERTER_HPP_INCLUDED
#define BOOST_LOCALE_CONVERTER_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/detail/facet_id.hpp>
#include <boost/locale/detail/is_supported_char.hpp>
#include <boost/locale/util/string.hpp>
#include <locale>
namespace boost {
namespace locale {
///
/// \defgroup convert Text Conversions
///
/// This module provides various function for string manipulation like Unicode normalization, case conversion etc.
/// @{
///
///
/// \brief This class provides base flags for text manipulation. It is used as base for converter facet.
///
class converter_base {
public:
///
/// The flag used for facet - the type of operation to perform
///
typedef enum {
normalization, ///< Apply Unicode normalization on the text
upper_case, ///< Convert text to upper case
lower_case, ///< Convert text to lower case
case_folding, ///< Fold case in the text
title_case ///< Convert text to title case
} conversion_type;
};
template<typename CharType>
class converter;
#ifdef BOOST_LOCALE_DOXYGEN
///
/// \brief The facet that implements text manipulation
///
/// It is used to performs text conversion operations defined by \ref conversion_type. It is specialized
/// for four types of characters \c char, \c wchar_t, \c char16_t, \c char32_t
///
template<typename Char>
class BOOST_LOCALE_DECL converter: public converter_base, public std::locale::facet {
public:
/// Locale identification
static std::locale::id id;
/// Standard constructor
converter(size_t refs = 0) : std::locale::facet(refs)
{
}
///
/// Convert text in range [\a begin, \a end) according to conversion method \a how. Parameter
/// \a flags is used for specification of normalization method like nfd, nfc etc.
///
virtual std::basic_string<Char> convert(conversion_type how,Char const *begin,Char const *end,int flags = 0) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale {
/// \defgroup convert Text Conversions
///
/// This module provides various function for string manipulation like Unicode normalization, case conversion etc.
/// @{
/// \brief This class provides base flags for text manipulation. It is used as base for converter facet.
class converter_base {
public:
/// The flag used for facet - the type of operation to perform
enum conversion_type {
normalization, ///< Apply Unicode normalization on the text
upper_case, ///< Convert text to upper case
lower_case, ///< Convert text to lower case
case_folding, ///< Fold case in the text
title_case ///< Convert text to title case
};
#else
};
template<>
class BOOST_LOCALE_DECL converter<char> : public converter_base, public std::locale::facet {
public:
static std::locale::id id;
/// \brief The facet that implements text manipulation
///
/// It is used to perform text conversion operations defined by \ref converter_base::conversion_type.
/// It is implemented for supported character types, at least \c char, \c wchar_t
template<typename Char>
class BOOST_SYMBOL_VISIBLE converter : public converter_base,
public std::locale::facet,
public detail::facet_id<converter<Char>> {
BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char);
converter(size_t refs = 0) : std::locale::facet(refs)
{
}
virtual std::string convert(conversion_type how,char const *begin,char const *end,int flags = 0) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
public:
/// Standard constructor
converter(size_t refs = 0) : std::locale::facet(refs) {}
/// Convert text in range [\a begin, \a end) according to conversion method \a how. Parameter
/// \a flags is used for specification of normalization method like nfd, nfc etc.
virtual std::basic_string<Char>
convert(conversion_type how, const Char* begin, const Char* end, int flags = 0) const = 0;
};
template<>
class BOOST_LOCALE_DECL converter<wchar_t> : public converter_base, public std::locale::facet {
public:
static std::locale::id id;
converter(size_t refs = 0) : std::locale::facet(refs)
{
}
virtual std::wstring convert(conversion_type how,wchar_t const *begin,wchar_t const *end,int flags = 0) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
/// The type that defined <a href="http://unicode.org/reports/tr15/#Norm_Forms">normalization form</a>
enum norm_type {
norm_nfd, ///< Canonical decomposition
norm_nfc, ///< Canonical decomposition followed by canonical composition
norm_nfkd, ///< Compatibility decomposition
norm_nfkc, ///< Compatibility decomposition followed by canonical composition.
norm_default = norm_nfc, ///< Default normalization - canonical decomposition followed by canonical composition
};
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<>
class BOOST_LOCALE_DECL converter<char16_t> : public converter_base, public std::locale::facet {
public:
static std::locale::id id;
converter(size_t refs = 0) : std::locale::facet(refs)
{
}
virtual std::u16string convert(conversion_type how,char16_t const *begin,char16_t const *end,int flags = 0) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#endif
/// Normalize Unicode string in range [begin,end) according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> normalize(const CharType* begin,
const CharType* end,
norm_type n = norm_default,
const std::locale& loc = std::locale())
{
return std::use_facet<converter<CharType>>(loc).convert(converter_base::normalization, begin, end, n);
}
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<>
class BOOST_LOCALE_DECL converter<char32_t> : public converter_base, public std::locale::facet {
public:
static std::locale::id id;
converter(size_t refs = 0) : std::locale::facet(refs)
{
}
virtual std::u32string convert(conversion_type how,char32_t const *begin,char32_t const *end,int flags = 0) const = 0;
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#endif
};
#endif
/// Normalize Unicode string \a str according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> normalize(const std::basic_string<CharType>& str,
norm_type n = norm_default,
const std::locale& loc = std::locale())
{
return normalize(str.data(), str.data() + str.size(), n, loc);
}
#endif
/// Normalize NULL terminated Unicode string \a str according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType>
normalize(const CharType* str, norm_type n = norm_default, const std::locale& loc = std::locale())
{
return normalize(str, util::str_end(str), n, loc);
}
///
/// The type that defined <a href="http://unicode.org/reports/tr15/#Norm_Forms">normalization form</a>
///
///////////////////////////////////////////////////
typedef enum {
norm_nfd, ///< Canonical decomposition
norm_nfc, ///< Canonical decomposition followed by canonical composition
norm_nfkd, ///< Compatibility decomposition
norm_nfkc, ///< Compatibility decomposition followed by canonical composition.
norm_default = norm_nfc, ///< Default normalization - canonical decomposition followed by canonical composition
} norm_type;
///
/// Normalize Unicode string \a str according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> normalize(std::basic_string<CharType> const &str,norm_type n=norm_default,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::normalization,str.data(),str.data() + str.size(),n);
}
/// Convert a string in range [begin,end) to upper case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType>
to_upper(const CharType* begin, const CharType* end, const std::locale& loc = std::locale())
{
return std::use_facet<converter<CharType>>(loc).convert(converter_base::upper_case, begin, end);
}
///
/// Normalize NUL terminated Unicode string \a str according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> normalize(CharType const *str,norm_type n=norm_default,std::locale const &loc=std::locale())
{
CharType const *end=str;
while(*end)
end++;
return std::use_facet<converter<CharType> >(loc).convert(converter_base::normalization,str,end,n);
}
///
/// Normalize Unicode string in range [begin,end) according to \ref norm_type "normalization form" \a n
///
/// Note: This function receives only Unicode strings, i.e.: UTF-8, UTF-16 or UTF-32. It does not take
/// in account the locale encoding, because Unicode decomposition and composition are meaningless outside
/// of a Unicode character set.
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> normalize( CharType const *begin,
CharType const *end,
norm_type n=norm_default,
std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::normalization,begin,end,n);
}
/// Convert a string \a str to upper case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_upper(const std::basic_string<CharType>& str, const std::locale& loc = std::locale())
{
return to_upper(str.data(), str.data() + str.size(), loc);
}
///////////////////////////////////////////////////
///
/// Convert a string \a str to upper case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
/// Convert a NULL terminated string \a str to upper case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_upper(const CharType* str, const std::locale& loc = std::locale())
{
return to_upper(str, util::str_end(str), loc);
}
template<typename CharType>
std::basic_string<CharType> to_upper(std::basic_string<CharType> const &str,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::upper_case,str.data(),str.data()+str.size());
}
///
/// Convert a NUL terminated string \a str to upper case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_upper(CharType const *str,std::locale const &loc=std::locale())
{
CharType const *end=str;
while(*end)
end++;
return std::use_facet<converter<CharType> >(loc).convert(converter_base::upper_case,str,end);
}
///
/// Convert a string in range [begin,end) to upper case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_upper(CharType const *begin,CharType const *end,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::upper_case,begin,end);
}
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///
/// Convert a string \a str to lower case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
/// Convert a string in range [begin,end) to lower case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType>
to_lower(const CharType* begin, const CharType* end, const std::locale& loc = std::locale())
{
return std::use_facet<converter<CharType>>(loc).convert(converter_base::lower_case, begin, end);
}
template<typename CharType>
std::basic_string<CharType> to_lower(std::basic_string<CharType> const &str,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::lower_case,str.data(),str.data()+str.size());
}
///
/// Convert a NUL terminated string \a str to lower case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_lower(CharType const *str,std::locale const &loc=std::locale())
{
CharType const *end=str;
while(*end)
end++;
return std::use_facet<converter<CharType> >(loc).convert(converter_base::lower_case,str,end);
}
///
/// Convert a string in range [begin,end) to lower case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_lower(CharType const *begin,CharType const *end,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::lower_case,begin,end);
}
///////////////////////////////////////////////////
///
/// Convert a string \a str to title case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
/// Convert a string \a str to lower case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_lower(const std::basic_string<CharType>& str, const std::locale& loc = std::locale())
{
return to_lower(str.data(), str.data() + str.size(), loc);
}
template<typename CharType>
std::basic_string<CharType> to_title(std::basic_string<CharType> const &str,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::title_case,str.data(),str.data()+str.size());
}
///
/// Convert a NUL terminated string \a str to title case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_title(CharType const *str,std::locale const &loc=std::locale())
{
CharType const *end=str;
while(*end)
end++;
return std::use_facet<converter<CharType> >(loc).convert(converter_base::title_case,str,end);
}
///
/// Convert a string in range [begin,end) to title case according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> to_title(CharType const *begin,CharType const *end,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::title_case,begin,end);
}
/// Convert a NULL terminated string \a str to lower case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_lower(const CharType* str, const std::locale& loc = std::locale())
{
return to_lower(str, util::str_end(str), loc);
}
///////////////////////////////////////////////////
///
/// Fold case of a string \a str according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
///////////////////////////////////////////////////
template<typename CharType>
std::basic_string<CharType> fold_case(std::basic_string<CharType> const &str,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::case_folding,str.data(),str.data()+str.size());
}
///
/// Fold case of a NUL terminated string \a str according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> fold_case(CharType const *str,std::locale const &loc=std::locale())
{
CharType const *end=str;
while(*end)
end++;
return std::use_facet<converter<CharType> >(loc).convert(converter_base::case_folding,str,end);
}
///
/// Fold case of a string in range [begin,end) according to locale \a loc
///
/// \note throws std::bad_cast if loc does not have \ref converter facet installed
///
template<typename CharType>
std::basic_string<CharType> fold_case(CharType const *begin,CharType const *end,std::locale const &loc=std::locale())
{
return std::use_facet<converter<CharType> >(loc).convert(converter_base::case_folding,begin,end);
}
/// Convert a string in range [begin,end) to title case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType>
to_title(const CharType* begin, const CharType* end, const std::locale& loc = std::locale())
{
return std::use_facet<converter<CharType>>(loc).convert(converter_base::title_case, begin, end);
}
///
///@}
///
} // locale
/// Convert a string \a str to title case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_title(const std::basic_string<CharType>& str, const std::locale& loc = std::locale())
{
return to_title(str.data(), str.data() + str.size(), loc);
}
} // boost
/// Convert a NULL terminated string \a str to title case according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> to_title(const CharType* str, const std::locale& loc = std::locale())
{
return to_title(str, util::str_end(str), loc);
}
///////////////////////////////////////////////////
/// Fold case of a string in range [begin,end) according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType>
fold_case(const CharType* begin, const CharType* end, const std::locale& loc = std::locale())
{
return std::use_facet<converter<CharType>>(loc).convert(converter_base::case_folding, begin, end);
}
/// Fold case of a string \a str according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> fold_case(const std::basic_string<CharType>& str,
const std::locale& loc = std::locale())
{
return fold_case(str.data(), str.data() + str.size(), loc);
}
/// Fold case of a NULL terminated string \a str according to locale \a loc
///
/// \throws std::bad_cast: \a loc does not have \ref converter facet installed
template<typename CharType>
std::basic_string<CharType> fold_case(const CharType* str, const std::locale& loc = std::locale())
{
return fold_case(str, util::str_end(str), loc);
}
///@}
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
///
/// \example conversions.cpp
///
/// Example of using various text conversion functions.
@@ -374,7 +245,5 @@ namespace boost {
/// \example wconversions.cpp
///
/// Example of using various text conversion functions with wide strings.
///
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,263 +1,185 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_DATE_TIME_FACET_HPP_INCLUDED
#define BOOST_LOCALE_DATE_TIME_FACET_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/cstdint.hpp>
#include <boost/locale/detail/facet_id.hpp>
#include <cstdint>
#include <locale>
namespace boost {
namespace locale {
///
/// \brief Namespace that contains various types for manipulation with dates
///
namespace period {
///
/// \brief This namespace holds a enum of various period types like era, year, month, etc..
///
namespace marks {
/// \brief the type that defines a flag that holds a period identifier
enum period_mark {
invalid, ///< Special invalid value, should not be used directly
era, ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
year, ///< Year, it is calendar specific, for example 2011 in Gregorian calendar.
extended_year, ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
month, ///< The month of year, calendar specific, in Gregorian [0..11]
day, ///< The day of month, calendar specific, in Gregorian [1..31]
day_of_year, ///< The number of day in year, starting from 1, in Gregorian [1..366]
day_of_week, ///< Day of week, Sunday=1, Monday=2,..., Saturday=7.
///< Note that updating this value respects local day of week, so for example,
///< If first day of week is Monday and the current day is Tuesday then setting
///< the value to Sunday (1) would forward the date by 5 days forward and not backward
///< by two days as it could be expected if the numbers were taken as is.
day_of_week_in_month, ///< Original number of the day of the week in month. For example 1st Sunday,
///< 2nd Sunday, etc. in Gregorian [1..5]
day_of_week_local, ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
hour, ///< 24 clock hour [0..23]
hour_12, ///< 12 clock hour [0..11]
am_pm, ///< am or pm marker [0..1]
minute, ///< minute [0..59]
second, ///< second [0..59]
week_of_year, ///< The week number in the year
week_of_month, ///< The week number within current month
first_day_of_week, ///< First day of week, constant, for example Sunday in US = 1, Monday in France = 2
};
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
} // marks
namespace boost { namespace locale {
///
/// \brief This class holds a type that represents certain period of time like
/// year, hour, second and so on.
///
/// It can be created from either marks::period_mark type or by using shortcuts in period
/// namespace - calling functions like period::year(), period::hour() and so on.
///
/// Basically it represents the same object as enum marks::period_mark but allows to
/// provide save operator overloading that would not collide with casing of enum to
/// numeric values.
///
class period_type {
public:
///
/// Create a period of specific type, default is invalid.
///
period_type(marks::period_mark m = marks::invalid) : mark_(m)
{
}
///
/// Get the value of marks::period_mark it was created with.
///
marks::period_mark mark() const
{
return mark_;
}
/// \brief Namespace that contains various types for manipulation with dates
namespace period {
///
/// Check if two periods are the same
///
bool operator==(period_type const &other) const
{
return mark()==other.mark();
}
///
/// Check if two periods are different
///
bool operator!=(period_type const &other) const
{
return mark()!=other.mark();
}
private:
marks::period_mark mark_;
/// \brief This namespace holds a enum of various period types like era, year, month, etc..
namespace marks {
/// \brief the type that defines a flag that holds a period identifier
enum period_mark {
invalid, ///< Special invalid value, should not be used directly
era, ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1]
year, ///< Year, it is calendar specific, for example 2011 in Gregorian calendar.
extended_year, ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1.
month, ///< The month of year, calendar specific, in Gregorian [0..11]
day, ///< The day of month, calendar specific, in Gregorian [1..31]
day_of_year, ///< The number of day in year, starting from 1, in Gregorian [1..366]
day_of_week, ///< Day of week, Sunday=1, Monday=2,..., Saturday=7.
///< Note that updating this value respects local day of week, so for example,
///< If first day of week is Monday and the current day is Tuesday then setting
///< the value to Sunday (1) would forward the date by 5 days forward and not backward
///< by two days as it could be expected if the numbers were taken as is.
day_of_week_in_month, ///< Original number of the day of the week in month. For example 1st Sunday,
///< 2nd Sunday, etc. in Gregorian [1..5]
day_of_week_local, ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7]
hour, ///< 24 clock hour [0..23]
hour_12, ///< 12 clock hour [0..11]
am_pm, ///< am or pm marker [0..1]
minute, ///< minute [0..59]
second, ///< second [0..59]
week_of_year, ///< The week number in the year
week_of_month, ///< The week number within current month
first_day_of_week, ///< First day of week, constant, for example Sunday in US = 1, Monday in France = 2
};
} // namespace period
} // namespace marks
/// \brief This class holds a type that represents certain period of time like
/// year, hour, second and so on.
///
/// Structure that define POSIX time, seconds and milliseconds
/// since Jan 1, 1970, 00:00 not including leap seconds.
/// It can be created from either marks::period_mark type or by using shortcuts in period
/// namespace - calling functions like period::year(), period::hour() and so on.
///
struct posix_time {
int64_t seconds; ///< Seconds since epoch
uint32_t nanoseconds; ///< Nanoseconds resolution
};
///
/// This class defines generic calendar class, it is used by date_time and calendar
/// objects internally. It is less useful for end users, but it is build for localization
/// backend implementation
///
class abstract_calendar {
/// Basically it represents the same object as enum marks::period_mark but allows to
/// provide save operator overloading that would not collide with casing of enum to
/// numeric values.
class period_type {
public:
/// Create a period of specific type, default is invalid.
period_type(marks::period_mark m = marks::invalid) : mark_(m) {}
///
/// Type that defines how to fetch the value
///
typedef enum {
absolute_minimum, ///< Absolute possible minimum for the value, for example for day is 1
actual_minimum, ///< Actual minimal value for this period.
greatest_minimum, ///< Maximal minimum value that can be for this period
current, ///< Current value of this period
least_maximum, ///< The last maximal value for this period, For example for Gregorian calendar
///< day it is 28
actual_maximum, ///< Actual maximum, for it can be 28, 29, 30, 31 for day according to current month
absolute_maximum, ///< Maximal value, for Gregorian day it would be 31.
} value_type;
/// Get the value of marks::period_mark it was created with.
marks::period_mark mark() const { return mark_; }
///
/// A way to update the value
///
typedef enum {
move, ///< Change the value up or down effecting others for example 1990-12-31 + 1 day = 1991-01-01
roll, ///< Change the value up or down not effecting others for example 1990-12-31 + 1 day = 1990-12-01
} update_type;
///
/// Information about calendar
///
typedef enum {
is_gregorian, ///< Check if the calendar is Gregorian
is_dst ///< Check if the current time is in daylight time savings
} calendar_option_type;
///
/// Make a polymorphic copy of the calendar
///
virtual abstract_calendar *clone() const = 0;
///
/// Set specific \a value for period \a p, note not all values are settable.
///
/// After call of set_value you may want to call normalize() function to make sure
/// vall periods are updated, if you set sereral fields that are part of single
/// date/time representation you should call set_value several times and then
/// call normalize().
///
/// If normalize() is not called after set_value, the behavior is undefined
///
virtual void set_value(period::marks::period_mark p,int value) = 0;
///
/// Recalculate all periods after setting them, should be called after use of set_value() function.
///
virtual void normalize() = 0;
///
/// Get specific value for period \a p according to a value_type \a v
///
virtual int get_value(period::marks::period_mark p,value_type v) const = 0;
///
/// Set current time point
///
virtual void set_time(posix_time const &p) = 0;
///
/// Get current time point
///
virtual posix_time get_time() const = 0;
///
/// Set option for calendar, for future use
///
virtual void set_option(calendar_option_type opt,int v) = 0;
///
/// Get option for calendar, currently only check if it is Gregorian calendar
///
virtual int get_option(calendar_option_type opt) const = 0;
///
/// Adjust period's \a p value by \a difference items using a update_type \a u.
/// Note: not all values are adjustable
///
virtual void adjust_value(period::marks::period_mark p,update_type u,int difference) = 0;
///
/// Calculate the difference between this calendar and \a other in \a p units
///
virtual int difference(abstract_calendar const *other,period::marks::period_mark p) const = 0;
///
/// Set time zone, empty - use system
///
virtual void set_timezone(std::string const &tz) = 0;
///
/// Get current time zone, empty - system one
///
virtual std::string get_timezone() const = 0;
///
/// Check of two calendars have same rules
///
virtual bool same(abstract_calendar const *other) const = 0;
virtual ~abstract_calendar()
{
}
/// Check if two periods are the same
bool operator==(const period_type& other) const { return mark() == other.mark(); }
/// Check if two periods are different
bool operator!=(const period_type& other) const { return mark() != other.mark(); }
private:
marks::period_mark mark_;
};
///
/// \brief the facet that generates calendar for specific locale
///
class BOOST_LOCALE_DECL calendar_facet : public std::locale::facet {
public:
///
/// Basic constructor
///
calendar_facet(size_t refs = 0) : std::locale::facet(refs)
{
}
///
/// Create a new calendar that points to current point of time.
///
virtual abstract_calendar *create_calendar() const = 0;
} // namespace period
///
/// Locale id (needed to work with std::locale)
///
static std::locale::id id;
/// Structure that define POSIX time, seconds and milliseconds
/// since Jan 1, 1970, 00:00 not including leap seconds.
struct posix_time {
int64_t seconds; ///< Seconds since epoch
uint32_t nanoseconds; ///< Nanoseconds resolution
};
/// This class defines generic calendar class, it is used by date_time and calendar
/// objects internally. It is less useful for end users, but it is build for localization
/// backend implementation
class BOOST_SYMBOL_VISIBLE abstract_calendar {
public:
/// Type that defines how to fetch the value
enum value_type {
absolute_minimum, ///< Absolute possible minimum for the value, for example for day is 1
actual_minimum, ///< Actual minimal value for this period.
greatest_minimum, ///< Maximal minimum value that can be for this period
current, ///< Current value of this period
least_maximum, ///< The last maximal value for this period, For example for Gregorian calendar
///< day it is 28
actual_maximum, ///< Actual maximum, for it can be 28, 29, 30, 31 for day according to current month
absolute_maximum, ///< Maximal value, for Gregorian day it would be 31.
};
} // locale
} // boost
/// A way to update the value
enum update_type {
move, ///< Change the value up or down effecting others for example 1990-12-31 + 1 day = 1991-01-01
roll, ///< Change the value up or down not effecting others for example 1990-12-31 + 1 day = 1990-12-01
};
/// Information about calendar
enum calendar_option_type {
is_gregorian, ///< Check if the calendar is Gregorian
is_dst ///< Check if the current time is in daylight time savings
};
/// Make a polymorphic copy of the calendar
virtual abstract_calendar* clone() const = 0;
/// Set specific \a value for period \a p, note not all values are settable.
///
/// After calling set_value you may want to call normalize() function to make sure
/// all periods are updated, if you set several fields that are part of a single
/// date/time representation you should call set_value several times and then
/// call normalize().
///
/// If normalize() is not called after set_value, the behavior is undefined
virtual void set_value(period::marks::period_mark m, int value) = 0;
/// Recalculate all periods after setting them, should be called after use of set_value() function.
virtual void normalize() = 0;
/// Get specific value for period \a p according to a value_type \a v
virtual int get_value(period::marks::period_mark m, value_type v) const = 0;
/// Set current time point
virtual void set_time(const posix_time& p) = 0;
/// Get current time point
virtual posix_time get_time() const = 0;
/// Get current time since epoch in milliseconds
virtual double get_time_ms() const = 0;
/// Set option for calendar, for future use
virtual void set_option(calendar_option_type opt, int v) = 0;
/// Get option for calendar, currently only check if it is Gregorian calendar
virtual int get_option(calendar_option_type opt) const = 0;
/// Adjust period's \a p value by \a difference items using a update_type \a u.
/// Note: not all values are adjustable
virtual void adjust_value(period::marks::period_mark m, update_type u, int difference) = 0;
/// Calculate the difference between this calendar and \a other in \a p units
virtual int difference(const abstract_calendar& other, period::marks::period_mark m) const = 0;
/// Set time zone, empty - use system
virtual void set_timezone(const std::string& tz) = 0;
/// Get current time zone, empty - system one
virtual std::string get_timezone() const = 0;
/// Check of two calendars have same rules
virtual bool same(const abstract_calendar* other) const = 0;
virtual ~abstract_calendar() = default;
};
/// \brief the facet that generates calendar for specific locale
class BOOST_SYMBOL_VISIBLE calendar_facet : public std::locale::facet, public detail::facet_id<calendar_facet> {
public:
/// Basic constructor
calendar_facet(size_t refs = 0) : std::locale::facet(refs) {}
/// Create a new calendar that points to current point of time.
virtual abstract_calendar* create_calendar() const = 0;
};
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,32 +0,0 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_LOCALE_DEFINITIONS_HPP_INCLUDED
#define BOOST_LOCALE_DEFINITIONS_HPP_INCLUDED
#include <boost/config.hpp>
// Support older ICU versions
#ifndef BOOST_SYMBOL_VISIBLE
# define BOOST_SYMBOL_VISIBLE
#endif
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_LOCALE_DYN_LINK)
# ifdef BOOST_LOCALE_SOURCE
# define BOOST_LOCALE_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_LOCALE_DECL BOOST_SYMBOL_IMPORT
# endif // BOOST_LOCALE_SOURCE
#endif // DYN_LINK
#ifndef BOOST_LOCALE_DECL
# define BOOST_LOCALE_DECL
#endif
#endif // boost/locale/config.hpp
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -0,0 +1,58 @@
//
// 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_DETAIL_ENCODING_HPP_INCLUDED
#define BOOST_LOCALE_DETAIL_ENCODING_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <boost/locale/encoding_errors.hpp>
#include <boost/utility/string_view.hpp>
#include <memory>
#include <string>
/// \cond INTERNAL
namespace boost { namespace locale { namespace conv { namespace detail {
template<typename CharIn, typename CharOut>
class BOOST_SYMBOL_VISIBLE charset_converter {
public:
using char_out_type = CharOut;
using char_in_type = CharIn;
using string_type = std::basic_string<CharOut>;
virtual ~charset_converter() = default;
virtual string_type convert(const CharIn* begin, const CharIn* end) = 0;
string_type convert(const boost::basic_string_view<CharIn>& text)
{
return convert(text.data(), text.data() + text.length());
}
};
using narrow_converter = charset_converter<char, char>;
template<typename CharType>
using utf_encoder = charset_converter<char, CharType>;
template<typename CharType>
using utf_decoder = charset_converter<CharType, char>;
enum class conv_backend { Default, IConv, ICU, WinAPI };
template<typename Char>
BOOST_LOCALE_DECL std::unique_ptr<utf_encoder<Char>>
make_utf_encoder(const std::string& charset, method_type how, conv_backend impl = conv_backend::Default);
template<typename Char>
BOOST_LOCALE_DECL std::unique_ptr<utf_decoder<Char>>
make_utf_decoder(const std::string& charset, method_type how, conv_backend impl = conv_backend::Default);
BOOST_LOCALE_DECL std::unique_ptr<narrow_converter>
make_narrow_converter(const std::string& src_encoding,
const std::string& target_encoding,
method_type how,
conv_backend impl = conv_backend::Default);
}}}} // namespace boost::locale::conv::detail
/// \endcond
#endif

View File

@@ -0,0 +1,35 @@
//
// 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_DETAIL_FACET_ID_HPP_INCLUDED
#define BOOST_LOCALE_DETAIL_FACET_ID_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <locale>
/// \cond INTERNAL
namespace boost { namespace locale { namespace detail {
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wundefined-var-template"
#endif
/// CRTP base class to hold the id required for facets
///
/// Required because the id needs to be defined in a CPP file and hence ex/imported for shared libraries.
/// However the virtual classes need to be declared as BOOST_VISIBLE to combine the VTables because otherwise
/// casts/virtual-calls might be flagged as invalid by UBSAN
template<class Derived>
struct BOOST_LOCALE_DECL facet_id {
static std::locale::id id;
};
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
}}} // namespace boost::locale::detail
/// \endcond
#endif

View File

@@ -0,0 +1,44 @@
//
// 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_DETAIL_IS_SUPPORTED_CHAR_HPP_INCLUDED
#define BOOST_LOCALE_DETAIL_IS_SUPPORTED_CHAR_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <type_traits>
/// \cond INTERNAL
namespace boost { namespace locale { namespace detail {
/// Trait, returns true iff the argument is a supported character type
template<typename Char>
struct is_supported_char : std::false_type {};
template<>
struct is_supported_char<char> : std::true_type {};
template<>
struct is_supported_char<wchar_t> : std::true_type {};
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<>
struct is_supported_char<char16_t> : std::true_type {};
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<>
struct is_supported_char<char32_t> : std::true_type {};
#endif
template<typename Char>
using enable_if_is_supported_char = typename std::enable_if<is_supported_char<Char>::value>::type;
}}} // namespace boost::locale::detail
#define BOOST_LOCALE_ASSERT_IS_SUPPORTED(Char) \
static_assert(boost::locale::detail::is_supported_char<Char>::value, "Unsupported Char type")
/// \endcond
#endif

View File

@@ -1,248 +1,314 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_ENCODING_HPP_INCLUDED
#define BOOST_LOCALE_ENCODING_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/info.hpp>
#include <boost/locale/detail/encoding.hpp>
#include <boost/locale/encoding_errors.hpp>
#include <boost/locale/encoding_utf.hpp>
namespace boost {
namespace locale {
///
/// \brief Namespace that contains all functions related to character set conversion
///
namespace conv {
///
/// \defgroup codepage Character conversion functions
///
/// @{
///
/// convert string to UTF string from text in range [begin,end) encoded with \a charset according to policy \a how
///
template<typename CharType>
std::basic_string<CharType> to_utf(char const *begin,char const *end,std::string const &charset,method_type how=default_method);
///
/// convert UTF text in range [begin,end) to a text encoded with \a charset according to policy \a how
///
template<typename CharType>
std::string from_utf(CharType const *begin,CharType const *end,std::string const &charset,method_type how=default_method);
///
/// convert string to UTF string from text in range [begin,end) encoded according to locale \a loc according to policy \a how
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::basic_string<CharType> to_utf(char const *begin,char const *end,std::locale const &loc,method_type how=default_method)
{
return to_utf<CharType>(begin,end,std::use_facet<info>(loc).encoding(),how);
}
///
/// convert UTF text in range [begin,end) to a text encoded according to locale \a loc according to policy \a how
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::string from_utf(CharType const *begin,CharType const *end,std::locale const &loc,method_type how=default_method)
{
return from_utf(begin,end,std::use_facet<info>(loc).encoding(),how);
}
///
/// convert a string \a text encoded with \a charset to UTF string
///
template<typename CharType>
std::basic_string<CharType> to_utf(std::string const &text,std::string const &charset,method_type how=default_method)
{
return to_utf<CharType>(text.c_str(),text.c_str()+text.size(),charset,how);
}
///
/// Convert a \a text from \a charset to UTF string
///
template<typename CharType>
std::string from_utf(std::basic_string<CharType> const &text,std::string const &charset,method_type how=default_method)
{
return from_utf(text.c_str(),text.c_str()+text.size(),charset,how);
}
///
/// Convert a \a text from \a charset to UTF string
///
template<typename CharType>
std::basic_string<CharType> to_utf(char const *text,std::string const &charset,method_type how=default_method)
{
char const *text_end = text;
while(*text_end)
text_end++;
return to_utf<CharType>(text,text_end,charset,how);
}
///
/// Convert a \a text from UTF to \a charset
///
template<typename CharType>
std::string from_utf(CharType const *text,std::string const &charset,method_type how=default_method)
{
CharType const *text_end = text;
while(*text_end)
text_end++;
return from_utf(text,text_end,charset,how);
}
///
/// Convert a \a text in locale encoding given by \a loc to UTF
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::basic_string<CharType> to_utf(std::string const &text,std::locale const &loc,method_type how=default_method)
{
return to_utf<CharType>(text.c_str(),text.c_str()+text.size(),loc,how);
}
///
/// Convert a \a text in UTF to locale encoding given by \a loc
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::string from_utf(std::basic_string<CharType> const &text,std::locale const &loc,method_type how=default_method)
{
return from_utf(text.c_str(),text.c_str()+text.size(),loc,how);
}
///
/// Convert a \a text in locale encoding given by \a loc to UTF
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::basic_string<CharType> to_utf(char const *text,std::locale const &loc,method_type how=default_method)
{
char const *text_end = text;
while(*text_end)
text_end++;
return to_utf<CharType>(text,text_end,loc,how);
}
///
/// Convert a \a text in UTF to locale encoding given by \a loc
///
/// \note throws std::bad_cast if the loc does not have \ref info facet installed
///
template<typename CharType>
std::string from_utf(CharType const *text,std::locale const &loc,method_type how=default_method)
{
CharType const *text_end = text;
while(*text_end)
text_end++;
return from_utf(text,text_end,loc,how);
}
///
/// Convert a text in range [begin,end) to \a to_encoding from \a from_encoding
///
BOOST_LOCALE_DECL
std::string between(char const *begin,
char const *end,
std::string const &to_encoding,
std::string const &from_encoding,
method_type how=default_method);
///
/// Convert a \a text to \a to_encoding from \a from_encoding
///
inline
std::string between(char const *text,
std::string const &to_encoding,
std::string const &from_encoding,
method_type how=default_method)
{
char const *end=text;
while(*end)
end++;
return boost::locale::conv::between(text,end,to_encoding,from_encoding,how);
}
///
/// Convert a \a text to \a to_encoding from \a from_encoding
///
inline
std::string between(std::string const &text,
std::string const &to_encoding,
std::string const &from_encoding,
method_type how=default_method)
{
return boost::locale::conv::between(text.c_str(),text.c_str()+text.size(),to_encoding,from_encoding,how);
}
/// \cond INTERNAL
template<>
BOOST_LOCALE_DECL std::basic_string<char> to_utf(char const *begin,char const *end,std::string const &charset,method_type how);
template<>
BOOST_LOCALE_DECL std::string from_utf(char const *begin,char const *end,std::string const &charset,method_type how);
template<>
BOOST_LOCALE_DECL std::basic_string<wchar_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how);
template<>
BOOST_LOCALE_DECL std::string from_utf(wchar_t const *begin,wchar_t const *end,std::string const &charset,method_type how);
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<>
BOOST_LOCALE_DECL std::basic_string<char16_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how);
template<>
BOOST_LOCALE_DECL std::string from_utf(char16_t const *begin,char16_t const *end,std::string const &charset,method_type how);
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<>
BOOST_LOCALE_DECL std::basic_string<char32_t> to_utf(char const *begin,char const *end,std::string const &charset,method_type how);
template<>
BOOST_LOCALE_DECL std::string from_utf(char32_t const *begin,char32_t const *end,std::string const &charset,method_type how);
#endif
/// \endcond
/// @}
} // conv
} // locale
} // boost
#include <boost/locale/info.hpp>
#include <boost/locale/util/string.hpp>
#include <memory>
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale {
/// \brief Namespace that contains all functions related to character set conversion
namespace conv {
/// \defgroup Charset conversion functions
///
/// @{
/// convert text in range [begin,end) encoded with \a charset to UTF according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
BOOST_LOCALE_DECL std::basic_string<CharType>
to_utf(const char* begin, const char* end, const std::string& charset, method_type how = default_method);
/// convert UTF text in range [begin,end) to text encoded with \a charset according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
BOOST_LOCALE_DECL std::string from_utf(const CharType* begin,
const CharType* end,
const std::string& charset,
method_type how = default_method);
/// convert \a text encoded with \a charset to UTF according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::basic_string<CharType>
to_utf(const std::string& text, const std::string& charset, method_type how = default_method)
{
return to_utf<CharType>(text.c_str(), text.c_str() + text.size(), charset, how);
}
/// Convert \a text encoded with \a charset to UTF according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::basic_string<CharType>
to_utf(const char* text, const std::string& charset, method_type how = default_method)
{
return to_utf<CharType>(text, util::str_end(text), charset, how);
}
/// convert text in range [begin,end) in locale encoding given by \a loc to UTF according to
/// policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::basic_string<CharType>
to_utf(const char* begin, const char* end, const std::locale& loc, method_type how = default_method)
{
return to_utf<CharType>(begin, end, std::use_facet<info>(loc).encoding(), how);
}
/// Convert \a text in locale encoding given by \a loc to UTF according to policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::basic_string<CharType>
to_utf(const std::string& text, const std::locale& loc, method_type how = default_method)
{
return to_utf<CharType>(text, std::use_facet<info>(loc).encoding(), how);
}
/// Convert \a text in locale encoding given by \a loc to UTF according to policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::basic_string<CharType> to_utf(const char* text, const std::locale& loc, method_type how = default_method)
{
return to_utf<CharType>(text, std::use_facet<info>(loc).encoding(), how);
}
/// convert \a text from UTF to text encoded with \a charset according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::string
from_utf(const std::basic_string<CharType>& text, const std::string& charset, method_type how = default_method)
{
return from_utf(text.c_str(), text.c_str() + text.size(), charset, how);
}
/// Convert \a text from UTF to \a charset according to policy \a how
///
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::string from_utf(const CharType* text, const std::string& charset, method_type how = default_method)
{
return from_utf(text, util::str_end(text), charset, how);
}
/// Convert UTF text in range [begin,end) to text in locale encoding given by \a loc according to policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::string
from_utf(const CharType* begin, const CharType* end, const std::locale& loc, method_type how = default_method)
{
return from_utf(begin, end, std::use_facet<info>(loc).encoding(), how);
}
/// Convert \a text from UTF to locale encoding given by \a loc according to policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::string
from_utf(const std::basic_string<CharType>& text, const std::locale& loc, method_type how = default_method)
{
return from_utf(text, std::use_facet<info>(loc).encoding(), how);
}
/// Convert \a text from UTF to locale encoding given by \a loc according to policy \a how
///
/// \throws std::bad_cast: \a loc does not have \ref info facet installed
/// \throws invalid_charset_error: Character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
template<typename CharType>
std::string from_utf(const CharType* text, const std::locale& loc, method_type how = default_method)
{
return from_utf(text, std::use_facet<info>(loc).encoding(), how);
}
/// Convert a text in range [begin,end) to \a to_encoding from \a from_encoding according to
/// policy \a how
///
/// \throws invalid_charset_error: Either character set is not supported
/// \throws conversion_error: when the conversion fails (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
BOOST_LOCALE_DECL
std::string between(const char* begin,
const char* end,
const std::string& to_encoding,
const std::string& from_encoding,
method_type how = default_method);
/// Convert \a text to \a to_encoding from \a from_encoding according to
/// policy \a how
///
/// \throws invalid_charset_error: Either character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
inline std::string between(const char* text,
const std::string& to_encoding,
const std::string& from_encoding,
method_type how = default_method)
{
return between(text, util::str_end(text), to_encoding, from_encoding, how);
}
/// Convert \a text to \a to_encoding from \a from_encoding according to
/// policy \a how
///
/// \throws invalid_charset_error: Either character set is not supported
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be
/// encoded or decoded)
inline std::string between(const std::string& text,
const std::string& to_encoding,
const std::string& from_encoding,
method_type how = default_method)
{
return between(text.c_str(), text.c_str() + text.size(), to_encoding, from_encoding, how);
}
/// @}
/// Converter class to decode a narrow string using a local encoding and encode it with UTF
template<typename CharType>
class utf_encoder {
std::unique_ptr<detail::utf_encoder<CharType>> impl_;
public:
using char_type = CharType;
using string_type = std::basic_string<CharType>;
/// Create an instance to convert text encoded with \a charset to UTF according to policy \a how
///
/// Note: When converting only a single text \ref to_utf is likely faster.
/// \throws invalid_charset_error: Character set is not supported
utf_encoder(const std::string& charset, method_type how = default_method) :
impl_(detail::make_utf_encoder<CharType>(charset, how))
{}
/// Convert text in range [begin,end) to UTF
///
/// \throws conversion_error: Conversion failed
string_type convert(const char* begin, const char* end) const { return impl_->convert(begin, end); }
/// Convert \a text to UTF
///
/// \throws conversion_error: Conversion failed
string_type convert(const boost::string_view& text) const { return impl_->convert(text); }
/// Convert \a text to UTF
///
/// \throws conversion_error: Conversion failed
string_type operator()(const boost::string_view& text) const { return convert(text); }
};
/// Converter class to decode an UTF string and encode it using a local encoding
template<typename CharType>
class utf_decoder {
std::unique_ptr<detail::utf_decoder<CharType>> impl_;
public:
using char_type = CharType;
using stringview_type = boost::basic_string_view<CharType>;
/// Create an instance to convert UTF text to text encoded with \a charset according to policy \a how
///
/// Note: When converting only a single text \ref from_utf is likely faster.
/// \throws invalid_charset_error: Character set is not supported
utf_decoder(const std::string& charset, method_type how = default_method) :
impl_(detail::make_utf_decoder<CharType>(charset, how))
{}
/// Convert UTF text in range [begin,end) to local encoding
///
/// \throws conversion_error: Conversion failed
std::string convert(const CharType* begin, const CharType* end) const { return impl_->convert(begin, end); }
/// Convert \a text from UTF to local encoding
///
/// \throws conversion_error: Conversion failed
std::string convert(const stringview_type& text) const { return impl_->convert(text); }
/// Convert \a text from UTF to local encoding
///
/// \throws conversion_error: Conversion failed
std::string operator()(const stringview_type& text) const { return convert(text); }
};
class narrow_converter {
std::unique_ptr<detail::narrow_converter> impl_;
public:
/// Create converter to convert text from \a src_encoding to \a target_encoding according to policy \a how
///
/// \throws invalid_charset_error: Either character set is not supported
narrow_converter(const std::string& src_encoding,
const std::string& target_encoding,
method_type how = default_method) :
impl_(detail::make_narrow_converter(src_encoding, target_encoding, how))
{}
/// Convert text in range [begin,end)
///
/// \throws conversion_error: Conversion failed
std::string convert(const char* begin, const char* end) const { return impl_->convert(begin, end); }
/// Convert \a text
///
/// \throws conversion_error: Conversion failed
std::string convert(const boost::string_view& text) const { return impl_->convert(text); }
/// Convert \a text
///
/// \throws conversion_error: Conversion failed
std::string operator()(const boost::string_view& text) const { return convert(text); }
};
} // namespace conv
}} // namespace boost::locale
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,75 +1,55 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_ENCODING_ERRORS_HPP_INCLUDED
#define BOOST_LOCALE_ENCODING_ERRORS_HPP_INCLUDED
#include <boost/locale/definitions.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/config.hpp>
#include <stdexcept>
namespace boost {
namespace locale {
namespace conv {
///
/// \addtogroup codepage
///
/// @{
///
/// \brief The excepton that is thrown in case of conversion error
///
class BOOST_SYMBOL_VISIBLE conversion_error : public std::runtime_error {
public:
conversion_error() : std::runtime_error("Conversion failed") {}
};
///
/// \brief This exception is thrown in case of use of unsupported
/// or invalid character set
///
class BOOST_SYMBOL_VISIBLE invalid_charset_error : public std::runtime_error {
public:
/// Create an error for charset \a charset
invalid_charset_error(std::string charset) :
std::runtime_error("Invalid or unsupported charset:" + charset)
{
}
};
///
/// enum that defines conversion policy
///
typedef enum {
skip = 0, ///< Skip illegal/unconvertable characters
stop = 1, ///< Stop conversion and throw conversion_error
default_method = skip ///< Default method - skip
} method_type;
/// @}
} // conv
} // locale
} // boost
#include <string>
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale { namespace conv {
/// \addtogroup codepage
///
/// @{
/// \brief The exception that is thrown in case of conversion error
class BOOST_SYMBOL_VISIBLE conversion_error : public std::runtime_error {
public:
conversion_error() : std::runtime_error("Conversion failed") {}
};
/// \brief This exception is thrown in case of use of unsupported
/// or invalid character set
class BOOST_SYMBOL_VISIBLE invalid_charset_error : public std::runtime_error {
public:
/// Create an error for charset \a charset
invalid_charset_error(const std::string& charset) :
std::runtime_error("Invalid or unsupported charset: " + charset)
{}
};
/// enum that defines conversion policy
enum method_type {
skip = 0, ///< Skip illegal/unconvertible characters
stop = 1, ///< Stop conversion and throw conversion_error
default_method = skip ///< Default method - skip
};
/// @}
}}} // namespace boost::locale::conv
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,93 +1,71 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_ENCODING_UTF_HPP_INCLUDED
#define BOOST_LOCALE_ENCODING_UTF_HPP_INCLUDED
#include <boost/locale/utf.hpp>
#include <boost/locale/encoding_errors.hpp>
#include <boost/locale/utf.hpp>
#include <boost/locale/util/string.hpp>
#include <iterator>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
namespace locale {
namespace conv {
///
/// \addtogroup codepage
///
/// @{
///
/// Convert a Unicode text in range [begin,end) to other Unicode encoding
///
template<typename CharOut,typename CharIn>
std::basic_string<CharOut>
utf_to_utf(CharIn const *begin,CharIn const *end,method_type how = default_method)
{
std::basic_string<CharOut> result;
result.reserve(end-begin);
typedef std::back_insert_iterator<std::basic_string<CharOut> > inserter_type;
inserter_type inserter(result);
utf::code_point c;
while(begin!=end) {
c=utf::utf_traits<CharIn>::template decode<CharIn const *>(begin,end);
if(c==utf::illegal || c==utf::incomplete) {
if(how==stop)
throw conversion_error();
}
else {
utf::utf_traits<CharOut>::template encode<inserter_type>(c,inserter);
}
}
return result;
}
///
/// Convert a Unicode NUL terminated string \a str other Unicode encoding
///
template<typename CharOut,typename CharIn>
std::basic_string<CharOut>
utf_to_utf(CharIn const *str,method_type how = default_method)
{
CharIn const *end = str;
while(*end)
end++;
return utf_to_utf<CharOut,CharIn>(str,end,how);
}
///
/// Convert a Unicode string \a str other Unicode encoding
///
template<typename CharOut,typename CharIn>
std::basic_string<CharOut>
utf_to_utf(std::basic_string<CharIn> const &str,method_type how = default_method)
{
return utf_to_utf<CharOut,CharIn>(str.c_str(),str.c_str()+str.size(),how);
}
/// @}
} // conv
} // locale
} // boost
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale { namespace conv {
/// \addtogroup codepage
///
/// @{
/// Convert a Unicode text in range [begin,end) to other Unicode encoding
///
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded)
template<typename CharOut, typename CharIn>
std::basic_string<CharOut> utf_to_utf(const CharIn* begin, const CharIn* end, method_type how = default_method)
{
std::basic_string<CharOut> result;
result.reserve(end - begin);
std::back_insert_iterator<std::basic_string<CharOut>> inserter(result);
while(begin != end) {
const utf::code_point c = utf::utf_traits<CharIn>::decode(begin, end);
if(c == utf::illegal || c == utf::incomplete) {
if(how == stop)
throw conversion_error();
} else
utf::utf_traits<CharOut>::encode(c, inserter);
}
return result;
}
/// Convert a Unicode NULL terminated string \a str other Unicode encoding
///
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded)
template<typename CharOut, typename CharIn>
std::basic_string<CharOut> utf_to_utf(const CharIn* str, method_type how = default_method)
{
return utf_to_utf<CharOut, CharIn>(str, util::str_end(str), how);
}
/// Convert a Unicode string \a str other Unicode encoding
///
/// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded)
template<typename CharOut, typename CharIn>
std::basic_string<CharOut> utf_to_utf(const std::basic_string<CharIn>& str, method_type how = default_method)
{
return utf_to_utf<CharOut, CharIn>(str.c_str(), str.c_str() + str.size(), how);
}
/// @}
}}} // namespace boost::locale::conv
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,507 +1,445 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
// Copyright (c) 2021-2023 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_LOCALE_FORMAT_HPP_INCLUDED
#define BOOST_LOCALE_FORMAT_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/message.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/hold_ptr.hpp>
#include <boost/locale/message.hpp>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
namespace locale {
///
/// \defgroup format Format
///
/// This module provides printf like functionality integrated into iostreams and suitable for localization
///
/// @{
///
namespace boost { namespace locale {
/// \cond INTERNAL
namespace details {
/// \defgroup format Format
///
/// This module provides printf like functionality integrated into iostreams and suitable for localization
///
/// @{
/// \cond INTERNAL
namespace detail {
template<typename CharType>
struct formattible {
typedef std::basic_ostream<CharType> stream_type;
typedef void (*writer_type)(stream_type& output, const void* ptr);
formattible() noexcept : pointer_(nullptr), writer_(&formattible::void_write) {}
formattible(const formattible&) noexcept = default;
formattible(formattible&&) noexcept = default;
formattible& operator=(const formattible&) noexcept = default;
formattible& operator=(formattible&&) noexcept = default;
template<typename Type>
explicit formattible(const Type& value) noexcept
{
pointer_ = static_cast<const void*>(&value);
writer_ = &write<Type>;
}
friend stream_type& operator<<(stream_type& out, const formattible& fmt)
{
fmt.writer_(out, fmt.pointer_);
return out;
}
private:
static void void_write(stream_type& output, const void* /*ptr*/)
{
CharType empty_string[1] = {0};
output << empty_string;
}
template<typename Type>
static void write(stream_type& output, const void* ptr)
{
output << *static_cast<const Type*>(ptr);
}
const void* pointer_;
writer_type writer_;
}; // formattible
class BOOST_LOCALE_DECL format_parser {
public:
format_parser(std::ios_base& ios, void*, void (*imbuer)(void*, const std::locale&));
~format_parser();
format_parser(const format_parser&) = delete;
format_parser& operator=(const format_parser&) = delete;
unsigned get_position();
void set_one_flag(const std::string& key, const std::string& value);
template<typename CharType>
struct formattible {
typedef std::basic_ostream<CharType> stream_type;
typedef void (*writer_type)(stream_type &output,void const *ptr);
formattible() :
pointer_(0),
writer_(&formattible::void_write)
{
}
formattible(formattible const &other) :
pointer_(other.pointer_),
writer_(other.writer_)
{
void set_flag_with_str(const std::string& key, const std::basic_string<CharType>& value)
{
if(key == "ftime" || key == "strftime") {
as::strftime(ios_);
ios_info::get(ios_).date_time_pattern(value);
}
}
void restore();
formattible const &operator=(formattible const &other)
{
if(this != &other) {
pointer_=other.pointer_;
writer_=other.writer_;
}
return *this;
}
template<typename Type>
formattible(Type const &value)
{
pointer_ = static_cast<void const *>(&value);
writer_ = &write<Type>;
}
private:
void imbue(const std::locale&);
template<typename Type>
formattible const &operator=(Type const &other)
{
*this = formattible(other);
return *this;
}
std::ios_base& ios_;
struct data;
hold_ptr<data> d;
};
friend stream_type &operator<<(stream_type &out,formattible const &fmt)
{
fmt.writer_(out,fmt.pointer_);
return out;
}
} // namespace detail
private:
static void void_write(stream_type &output,void const * /*ptr*/)
{
CharType empty_string[1]={0};
output<<empty_string;
}
/// \endcond
template<typename Type>
static void write(stream_type &output,void const *ptr)
{
output << *static_cast<Type const *>(ptr);
}
void const *pointer_;
writer_type writer_;
}; // formattible
class BOOST_LOCALE_DECL format_parser {
public:
format_parser(std::ios_base &ios,void *,void (*imbuer)(void *,std::locale const &));
~format_parser();
unsigned get_position();
void set_one_flag(std::string const &key,std::string const &value);
template<typename CharType>
void set_flag_with_str(std::string const &key,std::basic_string<CharType> const &value)
{
if(key=="ftime" || key=="strftime") {
as::strftime(ios_);
ios_info::get(ios_).date_time_pattern(value);
}
}
void restore();
private:
void imbue(std::locale const &);
format_parser(format_parser const &);
void operator=(format_parser const &);
std::ios_base &ios_;
struct data;
hold_ptr<data> d;
};
}
/// \brief a printf like class that allows type-safe and locale aware message formatting
///
/// This class creates a formatted message similar to printf or boost::format and receives
/// formatted entries via operator %.
///
/// For example
/// \code
/// std::cout << format("Hello {1}, you are {2} years old") % name % age << std::endl;
/// \endcode
///
/// Formatting is enclosed between curly brackets \c { \c } and defined by a comma separated list of flags in the
/// format key[=value] value may also be text included between single quotes \c ' that is used for special purposes
/// where inclusion of non-ASCII text is allowed
///
/// Including of literal \c { and \c } is possible by specifying double brackets \c {{ and \c }} accordingly.
///
///
/// For example:
///
/// \code
/// std::cout << format("The height of water at {1,time} is {2,num=fixed,precision=3}") % time % height;
/// \endcode
///
/// The special key -- a number without a value defines the position of an input parameter.
/// List of keys:
/// - \c [0-9]+ -- digits, the index of a formatted parameter -- mandatory key.
/// - \c num or \c number -- format a number. Optional values are:
/// - \c hex -- display hexadecimal number
/// - \c oct -- display in octal format
/// - \c sci or \c scientific -- display in scientific format
/// - \c fix or \c fixed -- display in fixed format
/// .
/// For example \c number=sci
/// - \c cur or \c currency -- format currency. Optional values are:
///
/// - \c iso -- display using ISO currency symbol.
/// - \c nat or \c national -- display using national currency symbol.
/// .
/// - \c per or \c percent -- format percent value.
/// - \c date, \c time , \c datetime or \c dt -- format date, time or date and time. Optional values are:
/// - \c s or \c short -- display in short format
/// - \c m or \c medium -- display in medium format.
/// - \c l or \c long -- display in long format.
/// - \c f or \c full -- display in full format.
/// .
/// - \c ftime with string (quoted) parameter -- display as with \c strftime see, \c as::ftime manipulator
/// - \c spell or \c spellout -- spell the number.
/// - \c ord or \c ordinal -- format ordinal number (1st, 2nd... etc)
/// - \c left or \c < -- align to left.
/// - \c right or \c > -- align to right.
/// - \c width or \c w -- set field width (requires parameter).
/// - \c precision or \c p -- set precision (requires parameter).
/// - \c locale -- with parameter -- switch locale for current operation. This command generates locale
/// with formatting facets giving more fine grained control of formatting. For example:
/// \code
/// std::cout << format("Today {1,date} ({1,date,locale=he_IL.UTF-8@calendar=hebrew,date} Hebrew Date)") % date;
/// \endcode
/// - \c timezone or \c tz -- the name of the timezone to display the time in. For example:\n
/// \code
/// std::cout << format("Time is: Local {1,time}, ({1,time,tz=EET} Eastern European Time)") % date;
/// \endcode
/// - \c local - display the time in local time
/// - \c gmt - display the time in UTC time scale
/// \code
/// std::cout << format("Local time is: {1,time,local}, universal time is {1,time,gmt}") % time;
/// \endcode
///
///
/// Invalid formatting strings are silently ignored.
/// This protects against a translator crashing the program in an unexpected location.
template<typename CharType>
class basic_format {
int throw_if_params_bound() const;
public:
typedef CharType char_type; ///< Underlying character type
typedef basic_message<char_type> message_type; ///< The translation message type
/// \cond INTERNAL
typedef detail::formattible<CharType> formattible_type;
/// \endcond
typedef std::basic_string<CharType> string_type; ///< string type for this type of character
typedef std::basic_ostream<CharType> stream_type; ///< output stream type for this type of character
/// Create a format class for \a format_string
basic_format(const string_type& format_string) : format_(format_string), translate_(false), parameters_count_(0)
{}
/// Create a format class using message \a trans. The message if translated first according
/// to the rules of the target locale and then interpreted as a format string
basic_format(const message_type& trans) : message_(trans), translate_(true), parameters_count_(0) {}
/// Non-copyable
basic_format(const basic_format& other) = delete;
void operator=(const basic_format& other) = delete;
/// Moveable
basic_format(basic_format&& other) :
message_((other.throw_if_params_bound(), std::move(other.message_))), format_(std::move(other.format_)),
translate_(other.translate_), parameters_count_(0)
{}
basic_format& operator=(basic_format&& other)
{
other.throw_if_params_bound();
message_ = std::move(other.message_);
format_ = std::move(other.format_);
translate_ = other.translate_;
parameters_count_ = 0;
ext_params_.clear();
return *this;
}
/// Add new parameter to the format list. The object should be a type
/// with defined expression out << object where \c out is \c std::basic_ostream.
///
/// \brief a printf like class that allows type-safe and locale aware message formatting
///
/// This class creates a formatted message similar to printf or boost::format and receives
/// formatted entries via operator %.
///
/// For example
/// A reference to the object is stored, so do not store the format object longer
/// than the lifetime of the parameter.
/// It is advisable to directly print the result:
/// \code
/// cout << format("Hello {1}, you are {2} years old") % name % age << endl;
/// basic_format<char> fmt("{0}");
/// fmt % (5 + 2); // INVALID: Dangling reference
/// int i = 42;
/// return fmt % i; // INVALID: Dangling reference
/// std::cout << fmt % (5 + 2); // OK, print immediately
/// return (fmt % (5 + 2)).str(); // OK, convert immediately to string
/// \endcode
///
/// Formatting is enclosed between curly brackets \c { \c } and defined by a comma separated list of flags in the format key[=value]
/// value may also be text included between single quotes \c ' that is used for special purposes where inclusion of non-ASCII
/// text is allowed
///
/// Including of literal \c { and \c } is possible by specifying double brackets \c {{ and \c }} accordingly.
///
///
/// For example:
///
/// \code
/// cout << format("The height of water at {1,time} is {2,num=fixed,precision=3}") % time % height;
/// \endcode
///
/// The special key -- a number without a value defines the position of an input parameter.
/// List of keys:
/// - \c [0-9]+ -- digits, the index of a formatted parameter -- mandatory key.
/// - \c num or \c number -- format a number. Optional values are:
/// - \c hex -- display hexadecimal number
/// - \c oct -- display in octal format
/// - \c sci or \c scientific -- display in scientific format
/// - \c fix or \c fixed -- display in fixed format
/// .
/// For example \c number=sci
/// - \c cur or \c currency -- format currency. Optional values are:
///
/// - \c iso -- display using ISO currency symbol.
/// - \c nat or \c national -- display using national currency symbol.
/// .
/// - \c per or \c percent -- format percent value.
/// - \c date, \c time , \c datetime or \c dt -- format date, time or date and time. Optional values are:
/// - \c s or \c short -- display in short format
/// - \c m or \c medium -- display in medium format.
/// - \c l or \c long -- display in long format.
/// - \c f or \c full -- display in full format.
/// .
/// - \c ftime with string (quoted) parameter -- display as with \c strftime see, \c as::ftime manipulator
/// - \c spell or \c spellout -- spell the number.
/// - \c ord or \c ordinal -- format ordinal number (1st, 2nd... etc)
/// - \c left or \c < -- align to left.
/// - \c right or \c > -- align to right.
/// - \c width or \c w -- set field width (requires parameter).
/// - \c precision or \c p -- set precision (requires parameter).
/// - \c locale -- with parameter -- switch locale for current operation. This command generates locale
/// with formatting facets giving more fine grained control of formatting. For example:
/// \code
/// cout << format("Today {1,date} ({1,date,locale=he_IL.UTF-8@calendar=hebrew,date} Hebrew Date)") % date;
/// \endcode
/// - \c timezone or \c tz -- the name of the timezone to display the time in. For example:\n
/// \code
/// cout << format("Time is: Local {1,time}, ({1,time,tz=EET} Eastern European Time)") % date;
/// \endcode
/// - \c local - display the time in local time
/// - \c gmt - display the time in UTC time scale
/// \code
/// cout << format("Local time is: {1,time,local}, universal time is {1,time,gmt}") % time;
/// \endcode
///
///
/// Invalid formatting strings are slightly ignored. This would prevent from translator
/// to crash the program in unexpected location.
///
template<typename CharType>
class basic_format {
template<typename Formattible>
basic_format& operator%(const Formattible& object)
{
add(formattible_type(object));
return *this;
}
/// Format a string using a locale \a loc
string_type str(const std::locale& loc = std::locale()) const
{
std::basic_ostringstream<CharType> buffer;
buffer.imbue(loc);
write(buffer);
return buffer.str();
}
/// write a formatted string to output stream \a out using out's locale
void write(stream_type& out) const
{
string_type format;
if(translate_)
format = message_.str(out.getloc(), ios_info::get(out).domain_id());
else
format = format_;
format_output(out, format);
}
private:
class format_guard {
public:
typedef CharType char_type; ///< Underlying character type
typedef basic_message<char_type> message_type; ///< The translation message type
/// \cond INTERNAL
typedef details::formattible<CharType> formattible_type;
/// \endcond
typedef std::basic_string<CharType> string_type; ///< string type for this type of character
typedef std::basic_ostream<CharType> stream_type; ///< output stream type for this type of character
///
/// Create a format class for \a format_string
///
basic_format(string_type format_string) :
format_(format_string),
translate_(false),
parameters_count_(0)
format_guard(detail::format_parser& fmt) : fmt_(fmt), restored_(false) {}
void restore()
{
if(restored_)
return;
fmt_.restore();
restored_ = true;
}
///
/// Create a format class using message \a trans. The message if translated first according
/// to the rules of target locale and then interpreted as format string
///
basic_format(message_type const &trans) :
message_(trans),
translate_(true),
parameters_count_(0)
~format_guard()
{
// clang-format off
try { restore(); } catch(...) {}
// clang-format on
}
///
/// Add new parameter to format list. The object should be a type
/// with defined expression out << object where \c out is \c std::basic_ostream.
///
template<typename Formattible>
basic_format &operator % (Formattible const &object)
{
add(formattible_type(object));
return *this;
}
///
/// Format a string using a locale \a loc
///
string_type str(std::locale const &loc = std::locale()) const
{
std::basic_ostringstream<CharType> buffer;
buffer.imbue(loc);
write(buffer);
return buffer.str();
}
///
/// write a formatted string to output stream \a out using out's locale
///
void write(stream_type &out) const
{
string_type format;
if(translate_)
format = message_.str(out.getloc(),ios_info::get(out).domain_id());
else
format = format_;
format_output(out,format);
}
private:
detail::format_parser& fmt_;
bool restored_;
};
class format_guard {
public:
format_guard(details::format_parser &fmt) :
fmt_(&fmt),
restored_(false)
{
}
void restore()
{
if(restored_)
return;
fmt_->restore();
restored_ = true;
}
~format_guard()
{
try {
restore();
}
catch(...) {
}
}
private:
details::format_parser *fmt_;
bool restored_;
};
void format_output(stream_type &out,string_type const &sformat) const
{
char_type obrk='{';
char_type cbrk='}';
char_type eq='=';
char_type comma=',';
char_type quote='\'';
void format_output(stream_type& out, const string_type& sformat) const
{
constexpr char_type obrk = '{';
constexpr char_type cbrk = '}';
constexpr char_type eq = '=';
constexpr char_type comma = ',';
constexpr char_type quote = '\'';
size_t pos = 0;
size_t size=sformat.size();
CharType const *format=sformat.c_str();
while(format[pos]!=0) {
if(format[pos] != obrk) {
if(format[pos]==cbrk && format[pos+1]==cbrk) {
out << cbrk;
pos+=2;
}
else {
out<<format[pos];
const size_t size = sformat.size();
const CharType* format = sformat.c_str();
for(size_t pos = 0; format[pos];) {
if(format[pos] != obrk) {
if(format[pos] == cbrk && format[pos + 1] == cbrk) {
out << cbrk;
pos += 2;
} else {
out << format[pos];
pos++;
}
continue;
}
pos++;
if(format[pos] == obrk) {
out << obrk;
continue;
}
detail::format_parser fmt(out, static_cast<void*>(&out), &basic_format::imbue_locale);
format_guard guard(fmt);
while(pos < size) {
std::string key;
std::string svalue;
string_type value;
bool use_svalue = true;
for(char_type c = format[pos]; !(c == 0 || c == comma || c == eq || c == cbrk); c = format[++pos]) {
key += static_cast<char>(c);
}
if(format[pos] == eq) {
pos++;
if(format[pos] == quote) {
pos++;
}
continue;
}
if(pos+1 < size && format[pos+1]==obrk) {
out << obrk;
pos+=2;
continue;
}
pos++;
details::format_parser fmt(out,static_cast<void *>(&out),&basic_format::imbue_locale);
format_guard guard(fmt);
while(pos < size) {
std::string key;
std::string svalue;
string_type value;
bool use_svalue = true;
for(;format[pos];pos++) {
char_type c=format[pos];
if(c==comma || c==eq || c==cbrk)
break;
else {
key+=static_cast<char>(c);
}
}
if(format[pos]==eq) {
pos++;
if(format[pos]==quote) {
pos++;
use_svalue = false;
while(format[pos]) {
if(format[pos]==quote) {
if(format[pos+1]==quote) {
value+=quote;
pos+=2;
}
else {
pos++;
break;
}
}
else {
value+=format[pos];
use_svalue = false;
while(format[pos]) {
if(format[pos] == quote) {
if(format[pos + 1] == quote) {
value += quote;
pos += 2;
} else {
pos++;
break;
}
}
}
else {
char_type c;
while((c=format[pos])!=0 && c!=comma && c!=cbrk) {
svalue+=static_cast<char>(c);
} else {
value += format[pos];
pos++;
}
}
} else {
char_type c;
while((c = format[pos]) != 0 && c != comma && c != cbrk) {
svalue += static_cast<char>(c);
pos++;
}
}
}
if(use_svalue) {
fmt.set_one_flag(key,svalue);
}
else
fmt.set_flag_with_str(key,value);
if(format[pos]==comma) {
pos++;
continue;
}
else if(format[pos]==cbrk) {
if(use_svalue)
fmt.set_one_flag(key, svalue);
else
fmt.set_flag_with_str(key, value);
if(format[pos] == comma)
pos++;
else {
if(format[pos] == cbrk) {
unsigned position = fmt.get_position();
out << get(position);
guard.restore();
pos++;
break;
}
else {
guard.restore();
break;
}
break;
}
}
}
//
// Non-copyable
//
basic_format(basic_format const &other);
void operator=(basic_format const &other);
void add(formattible_type const &param)
{
if(parameters_count_ >= base_params_)
ext_params_.push_back(param);
else
parameters_[parameters_count_] = param;
parameters_count_++;
}
formattible_type get(unsigned id) const
{
if(id >= parameters_count_)
return formattible_type();
else if(id >= base_params_)
return ext_params_[id - base_params_];
else
return parameters_[id];
}
static void imbue_locale(void *ptr,std::locale const &l)
{
reinterpret_cast<stream_type *>(ptr)->imbue(l);
}
static unsigned const base_params_ = 8;
message_type message_;
string_type format_;
bool translate_;
formattible_type parameters_[base_params_];
unsigned parameters_count_;
std::vector<formattible_type> ext_params_;
};
///
/// Write formatted message to stream.
///
/// This operator actually causes actual text formatting. It uses the locale of \a out stream
///
template<typename CharType>
std::basic_ostream<CharType> &operator<<(std::basic_ostream<CharType> &out,basic_format<CharType> const &fmt)
{
fmt.write(out);
return out;
}
void add(const formattible_type& param)
{
if(parameters_count_ >= base_params_)
ext_params_.push_back(param);
else
parameters_[parameters_count_] = param;
parameters_count_++;
}
///
/// Definition of char based format
///
typedef basic_format<char> format;
formattible_type get(unsigned id) const
{
if(id >= parameters_count_)
return formattible_type();
else if(id >= base_params_)
return ext_params_[id - base_params_];
else
return parameters_[id];
}
///
/// Definition of wchar_t based format
///
typedef basic_format<wchar_t> wformat;
static void imbue_locale(void* ptr, const std::locale& l) { static_cast<stream_type*>(ptr)->imbue(l); }
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
///
/// Definition of char16_t based format
///
typedef basic_format<char16_t> u16format;
#endif
static constexpr unsigned base_params_ = 8;
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
///
/// Definition of char32_t based format
///
typedef basic_format<char32_t> u32format;
#endif
message_type message_;
string_type format_;
bool translate_;
///
/// @}
///
formattible_type parameters_[base_params_];
unsigned parameters_count_;
std::vector<formattible_type> ext_params_;
};
/// Write formatted message to stream.
///
/// This operator actually causes actual text formatting. It uses the locale of \a out stream
template<typename CharType>
std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& out, const basic_format<CharType>& fmt)
{
fmt.write(out);
return out;
}
}
/// Definition of char based format
typedef basic_format<char> format;
/// Definition of wchar_t based format
typedef basic_format<wchar_t> wformat;
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
/// Definition of char16_t based format
typedef basic_format<char16_t> u16format;
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
/// Definition of char32_t based format
typedef basic_format<char32_t> u32format;
#endif
template<typename CharType>
int basic_format<CharType>::throw_if_params_bound() const
{
if(parameters_count_)
throw std::invalid_argument("Can't move a basic_format with bound parameters");
return 0;
}
/// @}
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
///
/// \example hello.cpp
///
/// Basic example of using various functions provided by this library
@@ -509,8 +447,5 @@ namespace boost {
/// \example whello.cpp
///
/// Basic example of using various functions with wide strings provided by this library
///
///
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,236 +1,236 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_GENERATOR_HPP
#define BOOST_LOCALE_GENERATOR_HPP
#include <boost/locale/config.hpp>
#include <boost/cstdint.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <string>
#include <boost/locale/hold_ptr.hpp>
#include <cstdint>
#include <locale>
#include <memory>
#include <boost/locale/hold_ptr.hpp>
#include <string>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
template<typename Type>
class shared_ptr;
///
/// \brief This is the main namespace that encloses all localization classes
///
namespace locale {
class localization_backend;
class localization_backend_manager;
/// Type that specifies the character type that locales can be generated for
///
/// \brief This is the main namespace that encloses all localization classes
/// Supports bitwise OR and bitwise AND (the latter returning if the type is set)
enum class char_facet_t : uint32_t {
nochar = 0, ///< Unspecified character category for character independent facets
char_f = 1 << 0, ///< 8-bit character facets
wchar_f = 1 << 1, ///< wide character facets
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
char16_f = 1 << 2, ///< C++11 char16_t facets
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
char32_f = 1 << 3, ///< C++11 char32_t facets
#endif
};
typedef BOOST_DEPRECATED("Use char_facet_t") char_facet_t character_facet_type;
/// First facet specific for character type
constexpr char_facet_t character_facet_first = char_facet_t::char_f;
/// Last facet specific for character type
constexpr char_facet_t character_facet_last =
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
char_facet_t::char32_f;
#elif defined BOOST_LOCALE_ENABLE_CHAR16_T
char_facet_t::char16_f;
#else
char_facet_t::wchar_f;
#endif
/// Special mask -- generate all
constexpr char_facet_t all_characters = char_facet_t(0xFFFFFFFFu);
/// Type used for more fine grained generation of facets
///
namespace locale {
/// Supports bitwise OR and bitwise AND (the latter returning if the type is set)
enum class category_t : uint32_t {
convert = 1 << 0, ///< Generate conversion facets
collation = 1 << 1, ///< Generate collation facets
formatting = 1 << 2, ///< Generate numbers, currency, date-time formatting facets
parsing = 1 << 3, ///< Generate numbers, currency, date-time formatting facets
message = 1 << 4, ///< Generate message facets
codepage = 1 << 5, ///< Generate character set conversion facets (derived from std::codecvt)
boundary = 1 << 6, ///< Generate boundary analysis facet
calendar = 1 << 16, ///< Generate boundary analysis facet
information = 1 << 17, ///< Generate general locale information facet
};
typedef BOOST_DEPRECATED("Use category_t") category_t locale_category_type;
class localization_backend;
class localization_backend_manager;
/// First facet specific for character
constexpr category_t per_character_facet_first = category_t::convert;
/// Last facet specific for character
constexpr category_t per_character_facet_last = category_t::boundary;
/// First character independent facet
constexpr category_t non_character_facet_first = category_t::calendar;
/// Last character independent facet
constexpr category_t non_character_facet_last = category_t::information;
/// First category facet
constexpr category_t category_first = category_t::convert;
/// Last category facet
constexpr category_t category_last = category_t::information;
/// Generate all of them
constexpr category_t all_categories = category_t(0xFFFFFFFFu);
static const uint32_t nochar_facet = 0; ///< Unspecified character category for character independent facets
static const uint32_t char_facet = 1 << 0; ///< 8-bit character facets
static const uint32_t wchar_t_facet = 1 << 1; ///< wide character facets
static const uint32_t char16_t_facet = 1 << 2; ///< C++0x char16_t facets
static const uint32_t char32_t_facet = 1 << 3; ///< C++0x char32_t facets
/// \brief the major class used for locale generation
///
/// This class is used for specification of all parameters required for locale generation and
/// caching. This class const member functions are thread safe if locale class implementation is thread safe.
class BOOST_LOCALE_DECL generator {
public:
/// Create new generator using global localization_backend_manager
generator();
/// Create new generator using specific localization_backend_manager
generator(const localization_backend_manager&);
static const uint32_t character_first_facet = char_facet; ///< First facet specific for character type
static const uint32_t character_last_facet = char32_t_facet; ///< Last facet specific for character type
static const uint32_t all_characters = 0xFFFF; ///< Special mask -- generate all
typedef uint32_t character_facet_type; ///<type that specifies the character type that locales can be generated for
~generator();
static const uint32_t convert_facet = 1 << 0; ///< Generate conversion facets
static const uint32_t collation_facet = 1 << 1; ///< Generate collation facets
static const uint32_t formatting_facet= 1 << 2; ///< Generate numbers, currency, date-time formatting facets
static const uint32_t parsing_facet = 1 << 3; ///< Generate numbers, currency, date-time formatting facets
static const uint32_t message_facet = 1 << 4; ///< Generate message facets
static const uint32_t codepage_facet = 1 << 5; ///< Generate character set conversion facets (derived from std::codecvt)
static const uint32_t boundary_facet = 1 << 6; ///< Generate boundary analysis facet
static const uint32_t per_character_facet_first = convert_facet; ///< First facet specific for character
static const uint32_t per_character_facet_last = boundary_facet; ///< Last facet specific for character
/// Set types of facets that should be generated, default all
void categories(category_t cats);
/// Get types of facets that should be generated, default all
category_t categories() const;
static const uint32_t calendar_facet = 1 << 16; ///< Generate boundary analysis facet
static const uint32_t information_facet = 1 << 17; ///< Generate general locale information facet
static const uint32_t non_character_facet_first = calendar_facet; ///< First character independent facet
static const uint32_t non_character_facet_last = information_facet;///< Last character independent facet
static const uint32_t all_categories = 0xFFFFFFFFu; ///< Generate all of them
typedef uint32_t locale_category_type; ///< a type used for more fine grained generation of facets
/// Set the characters type for which the facets should be generated, default all supported
void characters(char_facet_t chars);
/// Get the characters type for which the facets should be generated, default all supported
char_facet_t characters() const;
/// Add a new domain of messages that would be generated. It should be set in order to enable
/// messages support.
///
/// \brief the major class used for locale generation
/// Messages domain has following format: "name" or "name/encoding"
/// where name is the base name of the "mo" file where the catalog is stored
/// without ".mo" extension. For example for file \c /usr/share/locale/he/LC_MESSAGES/blog.mo
/// it would be \c blog.
///
/// This class is used for specification of all parameters required for locale generation and
/// caching. This class const member functions are thread safe if locale class implementation is thread safe.
/// You can optionally specify the encoding of the keys in the sources by adding "/encoding_name"
/// For example blog/cp1255.
///
/// If not defined all keys are assumed to be UTF-8 encoded.
///
/// \note When you select a domain for the program using dgettext or message API, you
/// do not specify the encoding part. So for example if the provided
/// domain name was "blog/windows-1255" then for translation
/// you should use dgettext("blog","Hello")
void add_messages_domain(const std::string& domain);
class BOOST_LOCALE_DECL generator {
public:
/// Set default message domain. If this member was not called, the first added messages domain is used.
/// If the domain \a domain is not added yet it is added.
void set_default_messages_domain(const std::string& domain);
///
/// Create new generator using global localization_backend_manager
///
generator();
///
/// Create new generator using specific localization_backend_manager
///
generator(localization_backend_manager const &);
/// Remove all added domains from the list
void clear_domains();
~generator();
/// Add a search path where dictionaries are looked in.
///
/// \note
///
/// - Under the Windows platform the path is treated as a path in the locale's encoding so
/// if you create locale "en_US.windows-1251" then path would be treated as cp1255,
/// and if it is en_US.UTF-8 it is treated as UTF-8. File name is always opened with
/// a wide file name as wide file names are the native file name on Windows.
///
/// - Under POSIX platforms all paths passed as-is regardless of encoding as narrow
/// encodings are the native encodings for POSIX platforms.
///
void add_messages_path(const std::string& path);
///
/// Set types of facets that should be generated, default all
///
void categories(locale_category_type cats);
///
/// Get types of facets that should be generated, default all
///
locale_category_type categories() const;
///
/// Set the characters type for which the facets should be generated, default all supported
///
void characters(character_facet_type chars);
///
/// Get the characters type for which the facets should be generated, default all supported
///
character_facet_type characters() const;
/// Remove all added paths
void clear_paths();
///
/// Add a new domain of messages that would be generated. It should be set in order to enable
/// messages support.
///
/// Messages domain has following format: "name" or "name/encoding"
/// where name is the base name of the "mo" file where the catalog is stored
/// without ".mo" extension. For example for file \c /usr/share/locale/he/LC_MESSAGES/blog.mo
/// it would be \c blog.
///
/// You can optionally specify the encoding of the keys in the sources by adding "/encoding_name"
/// For example blog/cp1255.
///
/// If not defined all keys are assumed to be UTF-8 encoded.
///
/// \note When you select a domain for the program using dgettext or message API, you
/// do not specify the encoding part. So for example if the provided
/// domain name was "blog/windows-1255" then for translation
/// you should use dgettext("blog","Hello")
///
///
void add_messages_domain(std::string const &domain);
///
/// Set default message domain. If this member was not called, the first added messages domain is used.
/// If the domain \a domain is not added yet it is added.
///
void set_default_messages_domain(std::string const &domain);
/// Remove all cached locales
void clear_cache();
///
/// Remove all added domains from the list
///
void clear_domains();
/// Turn locale caching ON
void locale_cache_enabled(bool on);
///
/// Add a search path where dictionaries are looked in.
///
/// \note
///
/// - Under the Windows platform the path is treated as a path in the locale's encoding so
/// if you create locale "en_US.windows-1251" then path would be treated as cp1255,
/// and if it is en_US.UTF-8 it is treated as UTF-8. File name is always opened with
/// a wide file name as wide file names are the native file name on Windows.
///
/// - Under POSIX platforms all paths passed as-is regardless of encoding as narrow
/// encodings are the native encodings for POSIX platforms.
///
///
void add_messages_path(std::string const &path);
/// Get locale cache option
bool locale_cache_enabled() const;
///
/// Remove all added paths
///
void clear_paths();
/// Check if by default ANSI encoding is selected or UTF-8 onces. The default is false.
bool use_ansi_encoding() const;
///
/// Remove all cached locales
///
void clear_cache();
/// Select ANSI encodings as default system encoding rather then UTF-8 by default
/// under Windows.
///
/// The default is the most portable and most powerful encoding, UTF-8, but the user
/// can select "system" one if dealing with legacy applications
void use_ansi_encoding(bool enc);
///
/// Turn locale caching ON
///
void locale_cache_enabled(bool on);
/// Generate a locale with id \a id
std::locale generate(const std::string& id) const;
/// Generate a locale with id \a id. Use \a base as a locale to which all facets are added,
/// instead of std::locale::classic().
std::locale generate(const std::locale& base, const std::string& id) const;
/// Shortcut to generate(id)
std::locale operator()(const std::string& id) const { return generate(id); }
///
/// Get locale cache option
///
bool locale_cache_enabled() const;
private:
void set_all_options(localization_backend& backend, const std::string& id) const;
///
/// Check if by default ANSI encoding is selected or UTF-8 onces. The default is false.
///
bool use_ansi_encoding() const;
generator(const generator&);
void operator=(const generator&);
///
/// Select ANSI encodings as default system encoding rather then UTF-8 by default
/// under Windows.
///
/// The default is the most portable and most powerful encoding, UTF-8, but the user
/// can select "system" one if dealing with legacy applications
///
void use_ansi_encoding(bool enc);
///
/// Generate a locale with id \a id
///
std::locale generate(std::string const &id) const;
///
/// Generate a locale with id \a id. Use \a base as a locale to which all facets are added,
/// instead of std::locale::classic().
///
std::locale generate(std::locale const &base,std::string const &id) const;
///
/// Shortcut to generate(id)
///
std::locale operator()(std::string const &id) const
{
return generate(id);
}
///
/// Set backend specific option
///
void set_option(std::string const &name,std::string const &value);
///
/// Clear backend specific options
///
void clear_options();
private:
void set_all_options(shared_ptr<localization_backend> backend,std::string const &id) const;
generator(generator const &);
void operator=(generator const &);
struct data;
hold_ptr<data> d;
};
struct data;
hold_ptr<data> d;
};
constexpr char_facet_t operator|(const char_facet_t lhs, const char_facet_t rhs)
{
return char_facet_t(static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
}
}
constexpr char_facet_t operator^(const char_facet_t lhs, const char_facet_t rhs)
{
return char_facet_t(static_cast<uint32_t>(lhs) ^ static_cast<uint32_t>(rhs));
}
constexpr bool operator&(const char_facet_t lhs, const char_facet_t rhs)
{
return (static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)) != 0u;
}
// Prefix increment: Return the next value
BOOST_CXX14_CONSTEXPR inline char_facet_t& operator++(char_facet_t& v)
{
return v = char_facet_t(static_cast<uint32_t>(v) ? static_cast<uint32_t>(v) << 1 : 1);
}
constexpr category_t operator|(const category_t lhs, const category_t rhs)
{
return category_t(static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
}
constexpr category_t operator^(const category_t lhs, const category_t rhs)
{
return category_t(static_cast<uint32_t>(lhs) ^ static_cast<uint32_t>(rhs));
}
constexpr bool operator&(const category_t lhs, const category_t rhs)
{
return (static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)) != 0u;
}
// Prefix increment: Return the next value
BOOST_CXX14_CONSTEXPR inline category_t& operator++(category_t& v)
{
return v = category_t(static_cast<uint32_t>(v) << 1);
}
} // namespace locale
} // namespace boost
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,167 +1,124 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_LOCLAE_GNU_GETTEXT_HPP
#define BOOST_LOCLAE_GNU_GETTEXT_HPP
#include <boost/locale/detail/is_supported_char.hpp>
#include <boost/locale/message.hpp>
#include <boost/function.hpp>
#include <functional>
#include <stdexcept>
#include <type_traits>
#include <vector>
namespace boost {
namespace locale {
/// \addtogroup message
/// @{
///
/// \brief This namespace holds classes that provide GNU Gettext message catalogs support.
///
namespace gnu_gettext {
///
/// \brief This structure holds all information required for creating gnu-gettext message catalogs,
///
/// The user is expected to set its parameters to load these catalogs correctly. This structure
/// also allows providing functions for charset conversion. Note, you need to provide them,
/// so this structure is not useful for wide characters without subclassing and it will also
/// ignore gettext catalogs that use a charset different from \a encoding.
///
struct messages_info {
messages_info() :
language("C"),
locale_category("LC_MESSAGES")
{
}
std::string language; ///< The language we load the catalog for, like "ru", "en", "de"
std::string country; ///< The country we load the catalog for, like "US", "IL"
std::string variant; ///< Language variant, like "euro" so it would look for catalog like de_DE\@euro
std::string encoding; ///< Required target charset encoding. Ignored for wide characters.
///< For narrow, should specify the correct encoding required for this catalog
std::string locale_category; ///< Locale category, is set by default to LC_MESSAGES, but may be changed
///
/// \brief This type represents GNU Gettext domain name for the messages.
///
/// It consists of two parameters:
///
/// - name - the name of the domain - used for opening the file name
/// - encoding - the encoding of the keys in the sources, default - UTF-8
///
struct domain {
std::string name; ///< The name of the domain
std::string encoding; ///< The character encoding for the domain
domain() {}
///
/// Create a domain object from the name that can hold an encoding after symbol "/"
/// such that if n is "hello/cp1255" then the name would be "hello" and "encoding" would
/// be "cp1255" and if n is "hello" then the name would be the same but encoding would be
/// "UTF-8"
///
domain(std::string const &n)
{
size_t pos = n.find("/");
if(pos==std::string::npos) {
name = n;
encoding = "UTF-8";
}
else {
name = n.substr(0,pos);
encoding = n.substr(pos+1);
}
}
///
/// Check whether two objects are equivalent, only names are compared, encoding is ignored
///
bool operator==(domain const &other) const
{
return name==other.name;
}
///
/// Check whether two objects are distinct, only names are compared, encoding is ignored
///
bool operator!=(domain const &other) const
{
return !(*this==other);
}
};
typedef std::vector<domain> domains_type; ///< Type that defines a list of domains that are loaded
///< The first one is the default one
domains_type domains; ///< Message domains - application name, like my_app. So files named my_app.mo
///< would be loaded
std::vector<std::string> paths; ///< Paths to search files in. Under MS Windows it uses encoding
///< parameter to convert them to wide OS specific paths.
///
/// The callback for custom file system support. This callback should read the file named \a file_name
/// encoded in \a encoding character set into std::vector<char> and return it.
///
/// - If the file does not exist, it should return an empty vector.
/// - If a error occurs during file read it should throw a error.
///
/// \note The user should support only the encodings the locales are created for. So if the user
/// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter.
///
typedef function<
std::vector<char>(
std::string const &file_name,
std::string const &encoding
)
> callback_type;
///
/// The callback for handling custom file systems, if it is empty, the real OS file-system
/// is being used.
///
callback_type callback;
};
///
/// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
/// information about where to read them from and uses it for character set conversion (if needed)
///
template<typename CharType>
message_format<CharType> *create_messages_facet(messages_info const &info);
/// \cond INTERNAL
template<>
BOOST_LOCALE_DECL message_format<char> *create_messages_facet(messages_info const &info);
template<>
BOOST_LOCALE_DECL message_format<wchar_t> *create_messages_facet(messages_info const &info);
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<>
BOOST_LOCALE_DECL message_format<char16_t> *create_messages_facet(messages_info const &info);
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<>
BOOST_LOCALE_DECL message_format<char32_t> *create_messages_facet(messages_info const &info);
#endif
/// \endcond
} // gnu_gettext
/// @}
} // locale
} // boost
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4251) // "identifier" : class "type" needs to have dll-interface...
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
namespace boost { namespace locale {
/// \addtogroup message
/// @{
/// \brief This namespace holds classes that provide GNU Gettext message catalogs support.
namespace gnu_gettext {
/// \brief This structure holds all information required for creating gnu-gettext message catalogs,
///
/// The user is expected to set its parameters to load these catalogs correctly. This structure
/// also allows providing functions for charset conversion. Note, you need to provide them,
/// so this structure is not useful for wide characters without subclassing and it will also
/// ignore gettext catalogs that use a charset different from \a encoding.
struct BOOST_LOCALE_DECL messages_info {
messages_info() : language("C"), locale_category("LC_MESSAGES") {}
std::string language; ///< The language we load the catalog for, like "ru", "en", "de"
std::string country; ///< The country we load the catalog for, like "US", "IL"
std::string variant; ///< Language variant, like "euro" so it would look for catalog like de_DE\@euro
std::string encoding; ///< Required target charset encoding. Ignored for wide characters.
///< For narrow, should specify the correct encoding required for this catalog
std::string locale_category; ///< Locale category, is set by default to LC_MESSAGES, but may be changed
///
/// \brief This type represents GNU Gettext domain name for the messages.
///
/// It consists of two parameters:
///
/// - name - the name of the domain - used for opening the file name
/// - encoding - the encoding of the keys in the sources, default - UTF-8
///
struct domain {
std::string name; ///< The name of the domain
std::string encoding; ///< The character encoding for the domain
domain() = default;
/// Create a domain object from the name that can hold an encoding after symbol "/"
/// such that if n is "hello/cp1255" then the name would be "hello" and "encoding" would
/// be "cp1255" and if n is "hello" then the name would be the same but encoding would be
/// "UTF-8"
domain(const std::string& n)
{
const size_t pos = n.find('/');
if(pos == std::string::npos) {
name = n;
encoding = "UTF-8";
} else {
name = n.substr(0, pos);
encoding = n.substr(pos + 1);
}
}
/// Check whether two objects are equivalent, only names are compared, encoding is ignored
bool operator==(const domain& other) const { return name == other.name; }
/// Check whether two objects are distinct, only names are compared, encoding is ignored
bool operator!=(const domain& other) const { return !(*this == other); }
};
typedef std::vector<domain> domains_type; ///< Type that defines a list of domains that are loaded
///< The first one is the default one
domains_type domains; ///< Message domains - application name, like my_app. So files named my_app.mo
///< would be loaded
std::vector<std::string> paths; ///< Paths to search files in. Under MS Windows it uses encoding
///< parameter to convert them to wide OS specific paths.
/// The callback for custom file system support. This callback should read the file named \a file_name
/// encoded in \a encoding character set into std::vector<char> and return it.
///
/// - If the file does not exist, it should return an empty vector.
/// - If an error occurs during file read it should throw an exception.
///
/// \note The user should support only the encodings the locales are created for. So if the user
/// uses only one encoding or the file system is encoding agnostic, he may ignore the \a encoding parameter.
typedef std::function<std::vector<char>(const std::string& file_name, const std::string& encoding)>
callback_type;
/// The callback for handling custom file systems, if it is empty, the real OS file-system
/// is being used.
callback_type callback;
/// Get paths to folders which may contain catalog files
std::vector<std::string> get_catalog_paths() const;
private:
/// Get a list of folder names for the language, country and variant
std::vector<std::string> get_lang_folders() const;
};
/// Create a message_format facet using GNU Gettext catalogs. It uses \a info structure to get
/// information about where to read them from and uses it for character set conversion (if needed)
template<typename CharType, class = boost::locale::detail::enable_if_is_supported_char<CharType>>
BOOST_LOCALE_DECL message_format<CharType>* create_messages_facet(const messages_info& info);
} // namespace gnu_gettext
/// @}
}} // namespace boost::locale
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif

View File

@@ -1,93 +1,87 @@
//
// Copyright (c) 2010 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2010 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_LOCALE_HOLD_PTR_H
#define BOOST_LOCALE_HOLD_PTR_H
namespace boost {
namespace locale {
///
/// \brief a smart pointer similar to std::auto_ptr but it is non-copyable and the
#include <boost/locale/config.hpp>
#include <boost/core/exchange.hpp>
namespace boost { namespace locale {
/// \brief a smart pointer similar to std::unique_ptr but the
/// underlying object has the same constness as the pointer itself (unlike an ordinary pointer).
///
template<typename T>
class hold_ptr {
hold_ptr(hold_ptr const &other); // non copyable
hold_ptr const &operator=(hold_ptr const &other); // non assignable
public:
///
/// Create new empty pointer
///
hold_ptr() : ptr_(0) {}
///
hold_ptr() : ptr_(nullptr) {}
/// Create a pointer that holds \a v, ownership is transferred to smart pointer
///
explicit hold_ptr(T *v) : ptr_(v) {}
explicit hold_ptr(T* v) : ptr_(v) {}
///
/// Destroy smart pointer and the object it owns.
///
~hold_ptr()
~hold_ptr() { delete ptr_; }
// Non-copyable
hold_ptr(const hold_ptr&) = delete;
hold_ptr& operator=(const hold_ptr&) = delete;
// Movable
hold_ptr(hold_ptr&& other) noexcept : ptr_(exchange(other.ptr_, nullptr)) {}
hold_ptr& operator=(hold_ptr&& other) noexcept
{
delete ptr_;
swap(other);
return *this;
}
///
/// Get a const pointer to the object
///
T const *get() const { return ptr_; }
///
/// Get a mutable pointer to the object
///
T *get() { return ptr_; }
T const* get() const { return ptr_; }
/// Get a mutable pointer to the object
T* get() { return ptr_; }
/// Explicitly convertible to bool. Returns: get() != nullptr
explicit operator bool() const { return ptr_ != nullptr; }
///
/// Get a const reference to the object
///
T const &operator *() const { return *ptr_; }
///
T const& operator*() const { return *ptr_; }
/// Get a mutable reference to the object
///
T &operator *() { return *ptr_; }
///
T& operator*() { return *ptr_; }
/// Get a const pointer to the object
///
T const *operator->() const { return ptr_; }
///
/// Get a mutable pointer to the object
///
T *operator->() { return ptr_; }
T const* operator->() const { return ptr_; }
/// Get a mutable pointer to the object
T* operator->() { return ptr_; }
///
/// Transfer an ownership on the pointer to user
///
T *release() { T *tmp=ptr_; ptr_=0; return tmp; }
T* release()
{
T* tmp = ptr_;
ptr_ = nullptr;
return tmp;
}
///
/// Set new value to pointer, previous object is destroyed, ownership on new object is transferred
///
void reset(T *p=0)
void reset(T* p = nullptr)
{
if(ptr_) delete ptr_;
ptr_=p;
if(ptr_)
delete ptr_;
ptr_ = p;
}
/// Swap two pointers
void swap(hold_ptr &other)
void swap(hold_ptr& other) noexcept
{
T *tmp=other.ptr_;
other.ptr_=ptr_;
ptr_=tmp;
T* tmp = other.ptr_;
other.ptr_ = ptr_;
ptr_ = tmp;
}
private:
T *ptr_;
T* ptr_;
};
} // locale
} // boost
}} // namespace boost::locale
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,125 +1,71 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_INFO_HPP_INCLUDED
#define BOOST_LOCALE_INFO_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <boost/locale/detail/facet_id.hpp>
#include <locale>
#include <string>
namespace boost {
namespace locale {
///
/// \brief a facet that holds general information about locale
///
/// This facet should be always created in order to make all Boost.Locale functions work
///
class BOOST_LOCALE_DECL info : public std::locale::facet
{
public:
static std::locale::id id; ///< This member uniquely defines this facet, required by STL
///
/// String information about the locale
///
enum string_propery {
language_property, ///< ISO 639 language id
country_property, ///< ISO 3166 country id
variant_property, ///< Variant for locale
encoding_property, ///< encoding name
name_property ///< locale name
};
///
/// Integer information about locale
///
enum integer_property {
utf8_property ///< Non zero value if uses UTF-8 encoding
};
///
/// Standard facet's constructor
///
info(size_t refs = 0) : std::locale::facet(refs)
{
}
///
/// Get language name
///
std::string language() const
{
return get_string_property(language_property);
}
///
/// Get country name
///
std::string country() const
{
return get_string_property(country_property);
}
///
/// Get locale variant
///
std::string variant() const
{
return get_string_property(variant_property);
}
///
/// Get encoding
///
std::string encoding() const
{
return get_string_property(encoding_property);
}
///
/// Get the name of the locale, like en_US.UTF-8
///
std::string name() const
{
return get_string_property(name_property);
}
///
/// True if the underlying encoding is UTF-8 (for char streams and strings)
///
bool utf8() const
{
return get_integer_property(utf8_property) != 0;
}
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER)
std::locale::id& __get_id (void) const { return id; }
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
protected:
///
/// Get string property by its id \a v
///
virtual std::string get_string_property(string_propery v) const = 0;
///
/// Get integer property by its id \a v
///
virtual int get_integer_property(integer_property v) const = 0;
namespace boost { namespace locale {
/// \brief a facet that holds general information about locale
///
/// This facet should be always created in order to make all Boost.Locale functions work
class BOOST_SYMBOL_VISIBLE info : public std::locale::facet, public detail::facet_id<info> {
public:
/// String information about the locale
enum string_propery {
language_property, ///< ISO 639 language id
country_property, ///< ISO 3166 country id
variant_property, ///< Variant for locale
encoding_property, ///< encoding name
name_property ///< locale name
};
}
}
/// Integer information about locale
enum integer_property {
utf8_property ///< Non zero value if uses UTF-8 encoding
};
/// Standard facet's constructor
info(size_t refs = 0) : std::locale::facet(refs) {}
/// Get language name
std::string language() const { return get_string_property(language_property); }
/// Get country name
std::string country() const { return get_string_property(country_property); }
/// Get locale variant
std::string variant() const { return get_string_property(variant_property); }
/// Get encoding
std::string encoding() const { return get_string_property(encoding_property); }
/// Get the name of the locale, like en_US.UTF-8
std::string name() const { return get_string_property(name_property); }
/// True if the underlying encoding is UTF-8 (for char streams and strings)
bool utf8() const { return get_integer_property(utf8_property) != 0; }
protected:
/// Get string property by its id \a v
virtual std::string get_string_property(string_propery v) const = 0;
/// Get integer property by its id \a v
virtual int get_integer_property(integer_property v) const = 0;
};
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,187 +1,129 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_LOCALIZATION_BACKEND_HPP
#define BOOST_LOCALE_LOCALIZATION_BACKEND_HPP
#include <boost/locale/config.hpp>
#include <boost/locale/generator.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <string>
#include <locale>
#include <vector>
#include <memory>
#include <boost/locale/hold_ptr.hpp>
namespace boost {
namespace locale {
///
/// \brief this class represents a localization backend that can be used for localizing your application.
///
/// Backends are usually registered inside the localization backends manager and allow transparent support
/// of different backends, so a user can switch the backend by simply linking the application to the correct one.
///
/// Backends may support different tuning options, but these are the default options available to the user
/// for all of them
///
/// -# \c locale - the name of the locale in POSIX format like en_US.UTF-8
/// -# \c use_ansi_encoding - select system locale using ANSI codepages rather then UTF-8 under Windows
/// by default
/// -# \c message_path - path to the location of message catalogs (vector of strings)
/// -# \c message_application - the name of applications that use message catalogs (vector of strings)
///
/// Each backend can be installed with a different default priotiry so when you work with two different backends, you
/// can specify priotiry so this backend will be chosen according to their priority.
///
class localization_backend {
localization_backend(localization_backend const &);
void operator=(localization_backend const &);
public:
localization_backend()
{
}
virtual ~localization_backend()
{
}
///
/// Make a polymorphic copy of the backend
///
virtual localization_backend *clone() const = 0;
///
/// Set option for backend, for example "locale" or "encoding"
///
virtual void set_option(std::string const &name,std::string const &value) = 0;
///
/// Clear all options
///
virtual void clear_options() = 0;
///
/// Create a facet for category \a category and character type \a type
///
virtual std::locale install(std::locale const &base,locale_category_type category,character_facet_type type = nochar_facet) = 0;
}; // localization_backend
///
/// \brief Localization backend manager is a class that holds various backend and allows creation
/// of their combination or selection
///
class BOOST_LOCALE_DECL localization_backend_manager {
public:
///
/// New empty localization_backend_manager
///
localization_backend_manager();
///
/// Copy localization_backend_manager
///
localization_backend_manager(localization_backend_manager const &);
///
/// Assign localization_backend_manager
///
localization_backend_manager const &operator=(localization_backend_manager const &);
///
/// Destructor
///
~localization_backend_manager();
#if !defined(BOOST_LOCALE_HIDE_AUTO_PTR) && !defined(BOOST_NO_AUTO_PTR)
///
/// Create new localization backend according to current settings.
///
std::auto_ptr<localization_backend> get() const;
///
/// Add new backend to the manager, each backend should be uniquely defined by its name.
///
/// This library provides: "icu", "posix", "winapi" and "std" backends.
///
void add_backend(std::string const &name,std::auto_ptr<localization_backend> backend);
#endif
///
/// Create new localization backend according to current settings. Ownership is passed to caller
///
localization_backend *create() const;
///
/// Add new backend to the manager, each backend should be uniquely defined by its name.
/// ownership on backend is transfered
///
/// This library provides: "icu", "posix", "winapi" and "std" backends.
///
void adopt_backend(std::string const &name,localization_backend *backend);
#ifndef BOOST_NO_CXX11_SMART_PTR
///
/// Create new localization backend according to current settings.
///
std::unique_ptr<localization_backend> get_unique_ptr() const;
///
/// Add new backend to the manager, each backend should be uniquely defined by its name.
///
/// This library provides: "icu", "posix", "winapi" and "std" backends.
///
void add_backend(std::string const &name,std::unique_ptr<localization_backend> backend);
#endif
///
/// Clear backend
///
void remove_all_backends();
///
/// Get list of all available backends
///
std::vector<std::string> get_all_backends() const;
///
/// Select specific backend by name for a category \a category. It allows combining different
/// backends for user preferences.
///
void select(std::string const &backend_name,locale_category_type category = all_categories);
///
/// Set new global backend manager, the old one is returned.
///
/// This function is thread safe
///
static localization_backend_manager global(localization_backend_manager const &);
///
/// Get global backend manager
///
/// This function is thread safe
///
static localization_backend_manager global();
private:
class impl;
hold_ptr<impl> pimpl_;
};
} // locale
} // boost
#include <locale>
#include <memory>
#include <string>
#include <vector>
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost { namespace locale {
/// \brief this class represents a localization backend that can be used for localizing your application.
///
/// Backends are usually registered inside the localization backends manager and allow transparent support
/// of different backends, so a user can switch the backend by simply linking the application to the correct one.
///
/// Backends may support different tuning options, but these are the default options available to the user
/// for all of them
///
/// -# \c locale - the name of the locale in POSIX format like en_US.UTF-8
/// -# \c use_ansi_encoding - select system locale using ANSI codepages rather then UTF-8 under Windows
/// by default
/// -# \c message_path - path to the location of message catalogs (vector of strings)
/// -# \c message_application - the name of applications that use message catalogs (vector of strings)
///
/// Each backend can be installed with a different default priority so when you work with two different backends,
/// you can specify priority so this backend will be chosen according to their priority.
class BOOST_LOCALE_DECL localization_backend {
protected:
localization_backend(const localization_backend&) = default;
localization_backend& operator=(const localization_backend&) = default;
public:
localization_backend() = default;
virtual ~localization_backend();
/// Make a polymorphic copy of the backend
virtual localization_backend* clone() const = 0;
/// Set option for backend, for example "locale" or "encoding"
virtual void set_option(const std::string& name, const std::string& value) = 0;
/// Clear all options
virtual void clear_options() = 0;
/// Create a facet for category \a category and character type \a type
virtual std::locale install(const std::locale& base, category_t category, char_facet_t type) = 0;
}; // localization_backend
/// \brief Localization backend manager is a class that holds various backend and allows creation
/// of their combination or selection
class BOOST_LOCALE_DECL localization_backend_manager {
public:
/// New empty localization_backend_manager
localization_backend_manager();
/// Copy localization_backend_manager
localization_backend_manager(const localization_backend_manager&);
/// Assign localization_backend_manager
localization_backend_manager& operator=(const localization_backend_manager&);
/// Move construct localization_backend_manager
localization_backend_manager(localization_backend_manager&&) noexcept;
/// Move assign localization_backend_manager
localization_backend_manager& operator=(localization_backend_manager&&) noexcept;
/// Destructor
~localization_backend_manager();
/// Create new localization backend according to current settings. Ownership is passed to caller
std::unique_ptr<localization_backend> create() const;
BOOST_DEPRECATED("This function is deprecated, use 'create()' instead")
std::unique_ptr<localization_backend> get() const { return create(); } // LCOV_EXCL_LINE
BOOST_DEPRECATED("This function is deprecated, use 'create()' instead")
std::unique_ptr<localization_backend> get_unique_ptr() const { return create(); } // LCOV_EXCL_LINE
/// Add new backend to the manager, each backend should be uniquely defined by its name.
///
/// This library provides: "icu", "posix", "winapi" and "std" backends.
void add_backend(const std::string& name, std::unique_ptr<localization_backend> backend);
// clang-format off
BOOST_DEPRECATED("This function is deprecated, use 'add_backend' instead")
void adopt_backend(const std::string& name, localization_backend* backend) { add_backend(name, std::unique_ptr<localization_backend>(backend)); } // LCOV_EXCL_LINE
// clang-format on
/// Clear backend
void remove_all_backends();
/// Get list of all available backends
std::vector<std::string> get_all_backends() const;
/// Select specific backend by name for a category \a category. It allows combining different
/// backends for user preferences.
void select(const std::string& backend_name, category_t category = all_categories);
/// Set new global backend manager, the old one is returned.
///
/// This function is thread safe
static localization_backend_manager global(const localization_backend_manager&);
/// Get global backend manager
///
/// This function is thread safe
static localization_backend_manager global();
private:
class impl;
hold_ptr<impl> pimpl_;
};
}} // namespace boost::locale
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +1,40 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_TIME_ZONE_HPP_INCLUDED
#define BOOST_LOCALE_TIME_ZONE_HPP_INCLUDED
#include <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <string>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
namespace boost {
namespace locale {
///
/// \addtogroup date_time
///
/// @{
namespace boost { namespace locale {
/// \addtogroup date_time
///
/// @{
///
/// \brief namespace that holds functions for operating with global
/// time zone
///
namespace time_zone {
///
/// Get global time zone identifier. If empty, system time zone is used
///
BOOST_LOCALE_DECL std::string global();
///
/// Set global time zone identifier returning previous one. If empty, system time zone is used
///
BOOST_LOCALE_DECL std::string global(std::string const &new_tz);
}
/// \brief namespace that holds functions for operating with global
/// time zone
namespace time_zone {
/// Get global time zone identifier. If empty, system time zone is used
BOOST_LOCALE_DECL std::string global();
/// Set global time zone identifier returning previous one. If empty, system time zone is used
BOOST_LOCALE_DECL std::string global(const std::string& new_tz);
} // namespace time_zone
/// @}
/// @}
} // locale
} // boost
}} // namespace boost::locale
#ifdef BOOST_MSVC
#pragma warning(pop)
# pragma warning(pop)
#endif
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,460 +1,371 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_UTF_HPP_INCLUDED
#define BOOST_LOCALE_UTF_HPP_INCLUDED
#include <boost/cstdint.hpp>
namespace boost {
namespace locale {
///
/// \brief Namespace that holds basic operations on UTF encoded sequences
///
/// All functions defined in this namespace do not require linking with Boost.Locale library
///
namespace utf {
/// \cond INTERNAL
#ifdef __GNUC__
# define BOOST_LOCALE_LIKELY(x) __builtin_expect((x),1)
# define BOOST_LOCALE_UNLIKELY(x) __builtin_expect((x),0)
#else
# define BOOST_LOCALE_LIKELY(x) (x)
# define BOOST_LOCALE_UNLIKELY(x) (x)
#endif
/// \endcond
#include <boost/locale/config.hpp>
#include <cstdint>
namespace boost { namespace locale {
/// \brief Namespace that holds basic operations on UTF encoded sequences
///
/// \brief The integral type that can hold a Unicode code point
///
typedef uint32_t code_point;
/// All functions defined in this namespace do not require linking with Boost.Locale library
namespace utf {
/// \brief The integral type that can hold a Unicode code point
using code_point = uint32_t;
///
/// \brief Special constant that defines illegal code point
///
static const code_point illegal = 0xFFFFFFFFu;
/// \brief Special constant that defines illegal code point
constexpr code_point illegal = 0xFFFFFFFFu;
/// \brief Special constant that defines incomplete code point
constexpr code_point incomplete = 0xFFFFFFFEu;
///
/// \brief Special constant that defines incomplete code point
///
static const code_point incomplete = 0xFFFFFFFEu;
/// Either a length/size or an error (illegal/incomplete)
using len_or_error = code_point;
///
/// \brief the function checks if \a v is a valid code point
///
inline bool is_valid_codepoint(code_point v)
{
if(v>0x10FFFF)
return false;
if(0xD800 <=v && v<= 0xDFFF) // surragates
return false;
return true;
}
#ifdef BOOST_LOCALE_DOXYGEN
///
/// \brief UTF Traits class - functions to convert UTF sequences to and from Unicode code points
///
template<typename CharType,int size=sizeof(CharType)>
struct utf_traits {
///
/// The type of the character
///
typedef CharType char_type;
///
/// Read one code point from the range [p,e) and return it.
///
/// - If the sequence that was read is incomplete sequence returns \ref incomplete,
/// - If illegal sequence detected returns \ref illegal
///
/// Requirements
///
/// - Iterator is valid input iterator
///
/// Postconditions
///
/// - p points to the last consumed character
///
template<typename Iterator>
static code_point decode(Iterator &p,Iterator e);
///
/// Maximal width of valid sequence in the code units:
///
/// - UTF-8 - 4
/// - UTF-16 - 2
/// - UTF-32 - 1
///
static const int max_width;
///
/// The width of specific code point in the code units.
///
/// Requirement: value is a valid Unicode code point
/// Returns value in range [1..max_width]
///
static int width(code_point value);
///
/// Get the size of the trail part of variable length encoded sequence.
///
/// Returns -1 if C is not valid lead character
///
static int trail_length(char_type c);
///
/// Returns true if c is trail code unit, always false for UTF-32
///
static bool is_trail(char_type c);
///
/// Returns true if c is lead code unit, always true of UTF-32
///
static bool is_lead(char_type c);
///
/// Convert valid Unicode code point \a value to the UTF sequence.
///
/// Requirements:
///
/// - \a value is valid code point
/// - \a out is an output iterator should be able to accept at least width(value) units
///
/// Returns the iterator past the last written code unit.
///
template<typename Iterator>
static Iterator encode(code_point value,Iterator out);
///
/// Decodes valid UTF sequence that is pointed by p into code point.
///
/// If the sequence is invalid or points to end the behavior is undefined
///
template<typename Iterator>
static code_point decode_valid(Iterator &p);
};
#else
template<typename CharType,int size=sizeof(CharType)>
struct utf_traits;
template<typename CharType>
struct utf_traits<CharType,1> {
typedef CharType char_type;
static int trail_length(char_type ci)
{
unsigned char c = ci;
if(c < 128)
return 0;
if(BOOST_LOCALE_UNLIKELY(c < 194))
return -1;
if(c < 224)
return 1;
if(c < 240)
return 2;
if(BOOST_LOCALE_LIKELY(c <=244))
return 3;
return -1;
}
static const int max_width = 4;
static int width(code_point value)
{
if(value <=0x7F) {
return 1;
}
else if(value <=0x7FF) {
return 2;
}
else if(BOOST_LOCALE_LIKELY(value <=0xFFFF)) {
return 3;
}
else {
return 4;
}
}
static bool is_trail(char_type ci)
{
unsigned char c=ci;
return (c & 0xC0)==0x80;
}
static bool is_lead(char_type ci)
{
return !is_trail(ci);
}
template<typename Iterator>
static code_point decode(Iterator &p,Iterator e)
{
if(BOOST_LOCALE_UNLIKELY(p==e))
return incomplete;
unsigned char lead = *p++;
// First byte is fully validated here
int trail_size = trail_length(lead);
if(BOOST_LOCALE_UNLIKELY(trail_size < 0))
return illegal;
//
// Ok as only ASCII may be of size = 0
// also optimize for ASCII text
//
if(trail_size == 0)
return lead;
code_point c = lead & ((1<<(6-trail_size))-1);
// Read the rest
unsigned char tmp;
switch(trail_size) {
case 3:
if(BOOST_LOCALE_UNLIKELY(p==e))
return incomplete;
tmp = *p++;
if (!is_trail(tmp))
return illegal;
c = (c << 6) | ( tmp & 0x3F);
case 2:
if(BOOST_LOCALE_UNLIKELY(p==e))
return incomplete;
tmp = *p++;
if (!is_trail(tmp))
return illegal;
c = (c << 6) | ( tmp & 0x3F);
case 1:
if(BOOST_LOCALE_UNLIKELY(p==e))
return incomplete;
tmp = *p++;
if (!is_trail(tmp))
return illegal;
c = (c << 6) | ( tmp & 0x3F);
}
// Check code point validity: no surrogates and
// valid range
if(BOOST_LOCALE_UNLIKELY(!is_valid_codepoint(c)))
return illegal;
// make sure it is the most compact representation
if(BOOST_LOCALE_UNLIKELY(width(c)!=trail_size + 1))
return illegal;
return c;
}
template<typename Iterator>
static code_point decode_valid(Iterator &p)
{
unsigned char lead = *p++;
if(lead < 192)
return lead;
int trail_size;
if(lead < 224)
trail_size = 1;
else if(BOOST_LOCALE_LIKELY(lead < 240)) // non-BMP rare
trail_size = 2;
else
trail_size = 3;
code_point c = lead & ((1<<(6-trail_size))-1);
switch(trail_size) {
case 3:
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
case 2:
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
case 1:
c = (c << 6) | ( static_cast<unsigned char>(*p++) & 0x3F);
}
return c;
}
template<typename Iterator>
static Iterator encode(code_point value,Iterator out)
{
if(value <= 0x7F) {
*out++ = static_cast<char_type>(value);
}
else if(value <= 0x7FF) {
*out++ = static_cast<char_type>((value >> 6) | 0xC0);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
}
else if(BOOST_LOCALE_LIKELY(value <= 0xFFFF)) {
*out++ = static_cast<char_type>((value >> 12) | 0xE0);
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
}
else {
*out++ = static_cast<char_type>((value >> 18) | 0xF0);
*out++ = static_cast<char_type>(((value >> 12) & 0x3F) | 0x80);
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
}
return out;
}
}; // utf8
template<typename CharType>
struct utf_traits<CharType,2> {
typedef CharType char_type;
// See RFC 2781
static bool is_first_surrogate(uint16_t x)
{
return 0xD800 <=x && x<= 0xDBFF;
}
static bool is_second_surrogate(uint16_t x)
{
return 0xDC00 <=x && x<= 0xDFFF;
}
static code_point combine_surrogate(uint16_t w1,uint16_t w2)
{
return ((code_point(w1 & 0x3FF) << 10) | (w2 & 0x3FF)) + 0x10000;
}
static int trail_length(char_type c)
{
if(is_first_surrogate(c))
return 1;
if(is_second_surrogate(c))
return -1;
return 0;
}
///
/// Returns true if c is trail code unit, always false for UTF-32
///
static bool is_trail(char_type c)
{
return is_second_surrogate(c);
}
///
/// Returns true if c is lead code unit, always true of UTF-32
///
static bool is_lead(char_type c)
{
return !is_second_surrogate(c);
}
template<typename It>
static code_point decode(It &current,It last)
{
if(BOOST_LOCALE_UNLIKELY(current == last))
return incomplete;
uint16_t w1=*current++;
if(BOOST_LOCALE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) {
return w1;
}
if(w1 > 0xDBFF)
return illegal;
if(current==last)
return incomplete;
uint16_t w2=*current++;
if(w2 < 0xDC00 || 0xDFFF < w2)
return illegal;
return combine_surrogate(w1,w2);
}
template<typename It>
static code_point decode_valid(It &current)
{
uint16_t w1=*current++;
if(BOOST_LOCALE_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) {
return w1;
}
uint16_t w2=*current++;
return combine_surrogate(w1,w2);
}
static const int max_width = 2;
static int width(code_point u)
{
return u>=0x10000 ? 2 : 1;
}
template<typename It>
static It encode(code_point u,It out)
{
if(BOOST_LOCALE_LIKELY(u<=0xFFFF)) {
*out++ = static_cast<char_type>(u);
}
else {
u -= 0x10000;
*out++ = static_cast<char_type>(0xD800 | (u>>10));
*out++ = static_cast<char_type>(0xDC00 | (u & 0x3FF));
}
return out;
}
}; // utf16;
template<typename CharType>
struct utf_traits<CharType,4> {
typedef CharType char_type;
static int trail_length(char_type c)
{
if(is_valid_codepoint(c))
return 0;
return -1;
}
static bool is_trail(char_type /*c*/)
{
return false;
}
static bool is_lead(char_type /*c*/)
/// \brief the function checks if \a v is a valid code point
inline bool is_valid_codepoint(code_point v)
{
if(v > 0x10FFFF)
return false;
if(0xD800 <= v && v <= 0xDFFF) // surrogates
return false;
return true;
}
template<typename It>
static code_point decode_valid(It &current)
{
return *current++;
}
#ifdef BOOST_LOCALE_DOXYGEN
template<typename It>
static code_point decode(It &current,It last)
{
if(BOOST_LOCALE_UNLIKELY(current == last))
return boost::locale::utf::incomplete;
code_point c=*current++;
if(BOOST_LOCALE_UNLIKELY(!is_valid_codepoint(c)))
return boost::locale::utf::illegal;
return c;
}
static const int max_width = 1;
static int width(code_point /*u*/)
{
return 1;
}
template<typename It>
static It encode(code_point u,It out)
{
*out++ = static_cast<char_type>(u);
return out;
}
/// \brief UTF Traits class - functions to convert UTF sequences to and from Unicode code points
template<typename CharType, int size = sizeof(CharType)>
struct utf_traits {
/// The type of the character
typedef CharType char_type;
}; // utf32
/// Read one code point from the range [p,e) and return it.
///
/// - If the sequence that was read is incomplete sequence returns \ref incomplete,
/// - If illegal sequence detected returns \ref illegal
///
/// Requirements
///
/// - Iterator is valid input iterator
///
/// Postconditions
///
/// - p points to the last consumed character
template<typename Iterator>
static code_point decode(Iterator& p, Iterator e);
#endif
/// Maximal width of valid sequence in the code units:
///
/// - UTF-8 - 4
/// - UTF-16 - 2
/// - UTF-32 - 1
static constexpr int max_width;
/// The width of specific code point in the code units.
///
/// Requirement: value is a valid Unicode code point
/// Returns value in range [1..max_width]
static int width(code_point value);
} // utf
} // locale
} // boost
/// Get the size of the trail part of variable length encoded sequence.
///
/// Returns -1 if C is not valid lead character
static int trail_length(char_type c);
/// Returns true if c is trail code unit, always false for UTF-32
static bool is_trail(char_type c);
/// Returns true if c is lead code unit, always true of UTF-32
static bool is_lead(char_type c);
/// Convert valid Unicode code point \a value to the UTF sequence.
///
/// Requirements:
///
/// - \a value is valid code point
/// - \a out is an output iterator should be able to accept at least width(value) units
///
/// Returns the iterator past the last written code unit.
template<typename Iterator>
static Iterator encode(code_point value, Iterator out);
/// Decodes valid UTF sequence that is pointed by p into code point.
///
/// If the sequence is invalid or points to end the behavior is undefined
template<typename Iterator>
static code_point decode_valid(Iterator& p);
};
#else
template<typename CharType, int size = sizeof(CharType)>
struct utf_traits;
template<typename CharType>
struct utf_traits<CharType, 1> {
typedef CharType char_type;
static int trail_length(char_type ci)
{
unsigned char c = ci;
if(c < 128)
return 0;
if(BOOST_UNLIKELY(c < 194))
return -1;
if(c < 224)
return 1;
if(c < 240)
return 2;
if(BOOST_LIKELY(c <= 244))
return 3;
return -1;
}
static constexpr int max_width = 4;
static int width(code_point value)
{
if(value <= 0x7F)
return 1;
else if(value <= 0x7FF)
return 2;
else if(BOOST_LIKELY(value <= 0xFFFF))
return 3;
else
return 4;
}
static bool is_trail(char_type ci)
{
unsigned char c = ci;
return (c & 0xC0) == 0x80;
}
static bool is_lead(char_type ci) { return !is_trail(ci); }
template<typename Iterator>
static code_point decode(Iterator& p, Iterator e)
{
if(BOOST_UNLIKELY(p == e))
return incomplete;
unsigned char lead = *p++;
// First byte is fully validated here
int trail_size = trail_length(lead);
if(BOOST_UNLIKELY(trail_size < 0))
return illegal;
// Ok as only ASCII may be of size = 0
// also optimize for ASCII text
if(trail_size == 0)
return lead;
code_point c = lead & ((1 << (6 - trail_size)) - 1);
// Read the rest
unsigned char tmp;
switch(trail_size) {
case 3:
if(BOOST_UNLIKELY(p == e))
return incomplete;
tmp = *p++;
if(!is_trail(tmp))
return illegal;
c = (c << 6) | (tmp & 0x3F);
BOOST_FALLTHROUGH;
case 2:
if(BOOST_UNLIKELY(p == e))
return incomplete;
tmp = *p++;
if(!is_trail(tmp))
return illegal;
c = (c << 6) | (tmp & 0x3F);
BOOST_FALLTHROUGH;
case 1:
if(BOOST_UNLIKELY(p == e))
return incomplete;
tmp = *p++;
if(!is_trail(tmp))
return illegal;
c = (c << 6) | (tmp & 0x3F);
}
// Check code point validity: no surrogates and
// valid range
if(BOOST_UNLIKELY(!is_valid_codepoint(c)))
return illegal;
// make sure it is the most compact representation
if(BOOST_UNLIKELY(width(c) != trail_size + 1))
return illegal;
return c;
}
template<typename Iterator>
static code_point decode_valid(Iterator& p)
{
unsigned char lead = *p++;
if(lead < 192)
return lead;
int trail_size;
if(lead < 224)
trail_size = 1;
else if(BOOST_LIKELY(lead < 240)) // non-BMP rare
trail_size = 2;
else
trail_size = 3;
code_point c = lead & ((1 << (6 - trail_size)) - 1);
switch(trail_size) {
case 3: c = (c << 6) | (static_cast<unsigned char>(*p++) & 0x3F); BOOST_FALLTHROUGH;
case 2: c = (c << 6) | (static_cast<unsigned char>(*p++) & 0x3F); BOOST_FALLTHROUGH;
case 1: c = (c << 6) | (static_cast<unsigned char>(*p++) & 0x3F);
}
return c;
}
template<typename Iterator>
static Iterator encode(code_point value, Iterator out)
{
if(value <= 0x7F)
*out++ = static_cast<char_type>(value);
else if(value <= 0x7FF) {
*out++ = static_cast<char_type>((value >> 6) | 0xC0);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
} else if(BOOST_LIKELY(value <= 0xFFFF)) {
*out++ = static_cast<char_type>((value >> 12) | 0xE0);
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
} else {
*out++ = static_cast<char_type>((value >> 18) | 0xF0);
*out++ = static_cast<char_type>(((value >> 12) & 0x3F) | 0x80);
*out++ = static_cast<char_type>(((value >> 6) & 0x3F) | 0x80);
*out++ = static_cast<char_type>((value & 0x3F) | 0x80);
}
return out;
}
}; // utf8
template<typename CharType>
struct utf_traits<CharType, 2> {
typedef CharType char_type;
// See RFC 2781
static bool is_first_surrogate(uint16_t x) { return 0xD800 <= x && x <= 0xDBFF; }
static bool is_second_surrogate(uint16_t x) { return 0xDC00 <= x && x <= 0xDFFF; }
static code_point combine_surrogate(uint16_t w1, uint16_t w2)
{
return ((code_point(w1 & 0x3FF) << 10) | (w2 & 0x3FF)) + 0x10000;
}
static int trail_length(char_type c)
{
if(is_first_surrogate(c))
return 1;
if(is_second_surrogate(c))
return -1;
return 0;
}
/// Returns true if c is trail code unit, always false for UTF-32
static bool is_trail(char_type c) { return is_second_surrogate(c); }
/// Returns true if c is lead code unit, always true of UTF-32
static bool is_lead(char_type c) { return !is_second_surrogate(c); }
template<typename It>
static code_point decode(It& current, It last)
{
if(BOOST_UNLIKELY(current == last))
return incomplete;
uint16_t w1 = *current++;
if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1))
return w1;
if(w1 > 0xDBFF)
return illegal;
if(current == last)
return incomplete;
uint16_t w2 = *current++;
if(w2 < 0xDC00 || 0xDFFF < w2)
return illegal;
return combine_surrogate(w1, w2);
}
template<typename It>
static code_point decode_valid(It& current)
{
uint16_t w1 = *current++;
if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1))
return w1;
uint16_t w2 = *current++;
return combine_surrogate(w1, w2);
}
static constexpr int max_width = 2;
static int width(code_point u) { return u >= 0x10000 ? 2 : 1; }
template<typename It>
static It encode(code_point u, It out)
{
if(BOOST_LIKELY(u <= 0xFFFF))
*out++ = static_cast<char_type>(u);
else {
u -= 0x10000;
*out++ = static_cast<char_type>(0xD800 | (u >> 10));
*out++ = static_cast<char_type>(0xDC00 | (u & 0x3FF));
}
return out;
}
}; // utf16;
template<typename CharType>
struct utf_traits<CharType, 4> {
typedef CharType char_type;
static int trail_length(char_type c)
{
if(is_valid_codepoint(c))
return 0;
return -1;
}
static bool is_trail(char_type /*c*/) { return false; }
static bool is_lead(char_type /*c*/) { return true; }
template<typename It>
static code_point decode_valid(It& current)
{
return *current++;
}
template<typename It>
static code_point decode(It& current, It last)
{
if(BOOST_UNLIKELY(current == last))
return boost::locale::utf::incomplete;
code_point c = *current++;
if(BOOST_UNLIKELY(!is_valid_codepoint(c)))
return boost::locale::utf::illegal;
return c;
}
static constexpr int max_width = 1;
static int width(code_point /*u*/) { return 1; }
template<typename It>
static It encode(code_point u, It out)
{
*out++ = static_cast<char_type>(u);
return out;
}
}; // utf32
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
} // namespace utf
}} // namespace boost::locale
#endif

View File

@@ -1,69 +1,56 @@
//
// Copyright (c) 2015 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright (c) 2015 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_LOCALE_UTF8_CODECVT_HPP
#define BOOST_LOCALE_UTF8_CODECVT_HPP
#include <boost/locale/utf.hpp>
#include <boost/locale/generic_codecvt.hpp>
#include <boost/cstdint.hpp>
#include <boost/locale/utf.hpp>
#include <boost/assert.hpp>
#include <cstdint>
#include <locale>
namespace boost {
namespace locale {
namespace boost { namespace locale {
///
/// \brief Geneneric utf8 codecvt facet, it allows to convert UTF-8 strings to UTF-16 and UTF-32 using wchar_t, char32_t and char16_t
///
template<typename CharType>
class utf8_codecvt : public generic_codecvt<CharType,utf8_codecvt<CharType> >
{
public:
struct state_type {};
/// \brief Geneneric utf8 codecvt facet, it allows to convert UTF-8 strings to UTF-16 and UTF-32 using wchar_t,
/// char32_t and char16_t
template<typename CharType>
class utf8_codecvt : public generic_codecvt<CharType, utf8_codecvt<CharType>> {
public:
struct state_type {};
utf8_codecvt(size_t refs = 0) : generic_codecvt<CharType,utf8_codecvt<CharType> >(refs)
{
}
utf8_codecvt(size_t refs = 0) : generic_codecvt<CharType, utf8_codecvt<CharType>>(refs) {}
static int max_encoding_length()
{
return 4;
}
static int max_encoding_length() { return 4; }
static state_type initial_state(generic_codecvt_base::initial_convertion_state /* unused */)
{
return state_type();
}
static utf::code_point to_unicode(state_type &,char const *&begin,char const *end)
{
char const *p=begin;
static state_type initial_state(generic_codecvt_base::initial_convertion_state /* unused */)
{
return state_type();
}
static utf::code_point to_unicode(state_type&, const char*& begin, const char* end)
{
const char* p = begin;
utf::code_point c = utf::utf_traits<char>::decode(p,end);
if(c!=utf::illegal && c!=utf::incomplete)
begin = p;
return c;
}
utf::code_point c = utf::utf_traits<char>::decode(p, end);
if(c != utf::illegal && c != utf::incomplete)
begin = p;
return c;
}
static utf::code_point from_unicode(state_type &,utf::code_point u,char *begin,char const *end)
{
if(!utf::is_valid_codepoint(u))
return utf::illegal;
int width;
if((width=utf::utf_traits<char>::width(u)) > end - begin)
return utf::incomplete;
utf::utf_traits<char>::encode(u,begin);
return width;
}
};
static utf::len_or_error from_unicode(state_type&, utf::code_point u, char* begin, const char* end)
{
BOOST_ASSERT(utf::is_valid_codepoint(u));
const auto width = utf::utf_traits<char>::width(u);
if(width > end - begin)
return utf::incomplete;
utf::utf_traits<char>::encode(u, begin);
return width;
}
};
} // locale
} // namespace boost
}} // namespace boost::locale
#endif
///
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -1,286 +1,210 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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_HPP
#define BOOST_LOCALE_UTIL_HPP
#include <locale>
#include <typeinfo>
#include <boost/cstdint.hpp>
#include <boost/locale/utf.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/utf.hpp>
#include <boost/assert.hpp>
#include <cstdint>
#include <locale>
#include <memory>
#include <typeinfo>
#include <vector>
namespace boost {
namespace locale {
///
/// \brief This namespace provides various utility function useful for Boost.Locale backends
/// implementations
///
namespace util {
///
/// \brief Return default system locale name in POSIX format.
///
/// This function tries to detect the locale using, LC_CTYPE, LC_ALL and LANG environment
/// variables in this order and if all of them unset, in POSIX platforms it returns "C"
///
/// On Windows additionally to check the above environment variables, this function
/// tries to creates locale name from ISO-339 and ISO-3199 country codes defined
/// for user default locale.
/// If \a use_utf8_on_windows is true it sets the encoding to UTF-8, otherwise, if system
/// locale supports ANSI code-page it defines the ANSI encoding like windows-1252, otherwise it fall-backs
/// to UTF-8 encoding if ANSI code-page is not available.
///
BOOST_LOCALE_DECL
std::string get_system_locale(bool use_utf8_on_windows = false);
namespace boost { namespace locale {
/// \brief This namespace provides various utility function useful for Boost.Locale's backends
/// implementations
namespace util {
///
/// \brief Installs information facet to locale in based on locale name \a name
///
/// This function installs boost::locale::info facet into the locale \a in and returns
/// newly created locale.
///
/// Note: all information is based only on parsing of string \a name;
///
/// The name has following format: language[_COUNTRY][.encoding][\@variant]
/// Where language is ISO-639 language code like "en" or "ru", COUNTRY is ISO-3166
/// country identifier like "US" or "RU". the Encoding is a charracter set name
/// like UTF-8 or ISO-8859-1. Variant is backend specific variant like \c euro or
/// calendar=hebrew.
///
/// If some parameters are missing they are specified as blanks, default encoding
/// is assumed to be US-ASCII and missing language is assumed to be "C"
///
BOOST_LOCALE_DECL
std::locale create_info(std::locale const &in,std::string const &name);
/// \brief Return default system locale name in POSIX format.
///
/// This function tries to detect the locale using LC_ALL, LC_CTYPE and LANG environment
/// variables in this order and if all of them are unset, on POSIX platforms it returns "C".
/// On Windows additionally to the above environment variables, this function
/// tries to create the locale name from ISO-639 and ISO-3166 country codes defined
/// for the users default locale.
/// If \a use_utf8_on_windows is true it sets the encoding to UTF-8,
/// otherwise, if the system locale supports ANSI codepages it defines the ANSI encoding, e.g. windows-1252,
/// otherwise (if ANSI codepage is not available) it uses UTF-8 encoding.
BOOST_LOCALE_DECL
std::string get_system_locale(bool use_utf8_on_windows = false);
/// \brief Installs information facet to locale \a in based on locale name \a name
///
/// This function installs boost::locale::info facet into the locale \a in and returns
/// newly created locale.
///
/// Note: all information is based only on parsing of string \a name;
///
/// The name has following format: language[_COUNTRY][.encoding][\@variant]
/// Where language is ISO-639 language code like "en" or "ru", COUNTRY is ISO-3166
/// country identifier like "US" or "RU". the Encoding is a character set name
/// like UTF-8 or ISO-8859-1. Variant is backend specific variant like \c euro or
/// calendar=hebrew.
///
/// If some parameters are missing they are specified as blanks, default encoding
/// is assumed to be US-ASCII and missing language is assumed to be "C"
BOOST_LOCALE_DECL
std::locale create_info(const std::locale& in, const std::string& name);
///
/// \brief This class represent a simple stateless converter from UCS-4 and to UCS-4 for
/// each single code point
///
/// This class is used for creation of std::codecvt facet for converting utf-16/utf-32 encoding
/// to encoding supported by this converter
///
/// Please note, this converter should be fully stateless. Fully stateless means it should
/// never assume that it is called in any specific order on the text. Even if the
/// encoding itself seems to be stateless like windows-1255 or shift-jis, some
/// encoders (most notably iconv) can actually compose several code-point into one or
/// decompose them in case composite characters are found. So be very careful when implementing
/// these converters for certain character set.
///
class base_converter {
public:
/// \brief This class represent a simple stateless converter from UCS-4 and to UCS-4 for
/// each single code point
///
/// This class is used for creation of std::codecvt facet for converting utf-16/utf-32 encoding
/// to encoding supported by this converter
///
/// Please note, this converter should be fully stateless. Fully stateless means it should
/// never assume that it is called in any specific order on the text. Even if the
/// encoding itself seems to be stateless like windows-1255 or shift-jis, some
/// encoders (most notably iconv) can actually compose several code-point into one or
/// decompose them in case composite characters are found. So be very careful when implementing
/// these converters for certain character set.
class BOOST_LOCALE_DECL base_converter {
public:
/// This value should be returned when an illegal input sequence or code-point is observed:
/// For example if a UCS-32 code-point is in the range reserved for UTF-16 surrogates
/// or an invalid UTF-8 sequence is found
static constexpr utf::code_point illegal = utf::illegal;
///
/// This value should be returned when an illegal input sequence or code-point is observed:
/// For example if a UCS-32 code-point is in the range reserved for UTF-16 surrogates
/// or an invalid UTF-8 sequence is found
///
static const uint32_t illegal=utf::illegal;
/// This value is returned in following cases: The of incomplete input sequence was found or
/// insufficient output buffer was provided so complete output could not be written.
static constexpr utf::code_point incomplete = utf::incomplete;
///
/// This value is returned in following cases: The of incomplete input sequence was found or
/// insufficient output buffer was provided so complete output could not be written.
///
static const uint32_t incomplete=utf::incomplete;
virtual ~base_converter()
{
}
///
/// Return the maximal length that one Unicode code-point can be converted to, for example
/// for UTF-8 it is 4, for Shift-JIS it is 2 and ISO-8859-1 is 1
///
virtual int max_len() const
{
return 1;
}
///
/// Returns true if calling the functions from_unicode, to_unicode, and max_len is thread safe.
///
/// Rule of thumb: if this class' implementation uses simple tables that are unchanged
/// or is purely algorithmic like UTF-8 - so it does not share any mutable bit for
/// independent to_unicode, from_unicode calls, you may set it to true, otherwise,
/// for example if you use iconv_t descriptor or UConverter as conversion object return false,
/// and this object will be cloned for each use.
///
virtual bool is_thread_safe() const
{
return false;
}
///
/// Create a polymorphic copy of this object, usually called only if is_thread_safe() return false
///
virtual base_converter *clone() const
{
BOOST_ASSERT(typeid(*this)==typeid(base_converter));
return new base_converter();
}
virtual ~base_converter();
///
/// Convert a single character starting at begin and ending at most at end to Unicode code-point.
///
/// if valid input sequence found in [\a begin,\a code_point_end) such as \a begin < \a code_point_end && \a code_point_end <= \a end
/// it is converted to its Unicode code point equivalent, \a begin is set to \a code_point_end
///
/// if incomplete input sequence found in [\a begin,\a end), i.e. there my be such \a code_point_end that \a code_point_end > \a end
/// and [\a begin, \a code_point_end) would be valid input sequence, then \a incomplete is returned begin stays unchanged, for example
/// for UTF-8 conversion a *begin = 0xc2, \a begin +1 = \a end is such situation.
///
/// if invalid input sequence found, i.e. there is a sequence [\a begin, \a code_point_end) such as \a code_point_end <= \a end
/// that is illegal for this encoding, \a illegal is returned and begin stays unchanged. For example if *begin = 0xFF and begin < end
/// for UTF-8, then \a illegal is returned.
///
///
virtual uint32_t to_unicode(char const *&begin,char const *end)
{
if(begin == end)
return incomplete;
unsigned char cp = *begin;
if(cp <= 0x7F) {
begin++;
return cp;
/// Return the maximal length that one Unicode code-point can be converted to, for example
/// for UTF-8 it is 4, for Shift-JIS it is 2 and ISO-8859-1 is 1
virtual int max_len() const { return 1; }
/// Returns true if calling the functions from_unicode, to_unicode, and max_len is thread safe.
///
/// Rule of thumb: if this class' implementation uses simple tables that are unchanged
/// or is purely algorithmic like UTF-8 - so it does not share any mutable bit for
/// independent to_unicode, from_unicode calls, you may set it to true, otherwise,
/// for example if you use iconv_t descriptor or UConverter as conversion object return false,
/// and this object will be cloned for each use.
virtual bool is_thread_safe() const { return false; }
/// Create a polymorphic copy of this object, usually called only if is_thread_safe() return false
virtual base_converter* clone() const
{
BOOST_ASSERT(typeid(*this) == typeid(base_converter));
return new base_converter();
}
return illegal;
}
///
/// Convert a single code-point \a u into encoding and store it in [begin,end) range.
///
/// If u is invalid Unicode code-point, or it can not be mapped correctly to represented character set,
/// \a illegal should be returned
///
/// If u can be converted to a sequence of bytes c1, ... , cN (1<= N <= max_len() ) then
///
/// -# If end - begin >= N, c1, ... cN are written starting at begin and N is returned
/// -# If end - begin < N, incomplete is returned, it is unspecified what would be
/// stored in bytes in range [begin,end)
virtual uint32_t from_unicode(uint32_t u,char *begin,char const *end)
{
if(begin==end)
return incomplete;
if(u >= 0x80)
/// Convert a single character starting at begin and ending at most at end to Unicode code-point.
///
/// if valid input sequence found in [\a begin,\a code_point_end) such as \a begin < \a code_point_end && \a
/// code_point_end <= \a end it is converted to its Unicode code point equivalent, \a begin is set to \a
/// code_point_end
///
/// if incomplete input sequence found in [\a begin,\a end), i.e. there my be such \a code_point_end that \a
/// code_point_end > \a end and [\a begin, \a code_point_end) would be valid input sequence, then \a
/// incomplete is returned begin stays unchanged, for example for UTF-8 conversion a *begin = 0xc2, \a begin
/// +1 = \a end is such situation.
///
/// if invalid input sequence found, i.e. there is a sequence [\a begin, \a code_point_end) such as \a
/// code_point_end <= \a end that is illegal for this encoding, \a illegal is returned and begin stays
/// unchanged. For example if *begin = 0xFF and begin < end for UTF-8, then \a illegal is returned.
virtual utf::code_point to_unicode(const char*& begin, const char* end)
{
if(begin == end)
return incomplete;
unsigned char cp = *begin;
if(cp <= 0x7F) {
begin++;
return cp;
}
return illegal;
*begin = static_cast<char>(u);
return 1;
}
/// Convert a single code-point \a u into encoding and store it in [begin,end) range.
///
/// If u is invalid Unicode code-point, or it can not be mapped correctly to represented character set,
/// \a illegal should be returned
///
/// If u can be converted to a sequence of bytes c1, ... , cN (1<= N <= max_len() ) then
///
/// -# If end - begin >= N, c1, ... cN are written starting at begin and N is returned
/// -# If end - begin < N, incomplete is returned, it is unspecified what would be
/// stored in bytes in range [begin,end)
virtual utf::len_or_error from_unicode(utf::code_point u, char* begin, const char* end)
{
if(begin == end)
return incomplete;
if(u >= 0x80)
return illegal;
*begin = static_cast<char>(u);
return 1;
}
};
/// This function creates a \a base_converter that can be used for conversion between UTF-8 and
/// Unicode code points
BOOST_LOCALE_DECL std::unique_ptr<base_converter> create_utf8_converter();
BOOST_DEPRECATED("This function is deprecated, use 'create_utf8_converter()'")
inline std::unique_ptr<base_converter> create_utf8_converter_unique_ptr()
{
return create_utf8_converter();
}
};
#if !defined(BOOST_LOCALE_HIDE_AUTO_PTR) && !defined(BOOST_NO_AUTO_PTR)
///
/// This function creates a \a base_converter that can be used for conversion between UTF-8 and
/// unicode code points
///
BOOST_LOCALE_DECL std::auto_ptr<base_converter> create_utf8_converter();
///
/// This function creates a \a base_converter that can be used for conversion between single byte
/// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points,
///
/// If \a encoding is not supported, empty pointer is returned. You should check if
/// std::auto_ptr<base_converter>::get() != 0
///
BOOST_LOCALE_DECL std::auto_ptr<base_converter> create_simple_converter(std::string const &encoding);
/// This function creates a \a base_converter that can be used for conversion between single byte
/// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points,
///
/// If \a encoding is not supported, empty pointer is returned.
/// So you should check whether the returned pointer is valid/non-NULL
BOOST_LOCALE_DECL std::unique_ptr<base_converter> create_simple_converter(const std::string& encoding);
BOOST_DEPRECATED("This function is deprecated, use 'create_simple_converter()'")
inline std::unique_ptr<base_converter> create_simple_converter_unique_ptr(const std::string& encoding)
{
return create_simple_converter(encoding);
}
///
/// Install codecvt facet into locale \a in and return new locale that is based on \a in and uses new
/// facet.
///
/// codecvt facet would convert between narrow and wide/char16_t/char32_t encodings using \a cvt converter.
/// If \a cvt is null pointer, always failure conversion would be used that fails on every first input or output.
///
/// Note: the codecvt facet handles both UTF-16 and UTF-32 wide encodings, it knows to break and join
/// Unicode code-points above 0xFFFF to and from surrogate pairs correctly. \a cvt should be unaware
/// of wide encoding type
///
BOOST_LOCALE_DECL
std::locale create_codecvt(std::locale const &in,std::auto_ptr<base_converter> cvt,character_facet_type type);
#endif
/// Install codecvt facet into locale \a in and return new locale that is based on \a in and uses new
/// facet.
///
/// codecvt facet would convert between narrow and wide/char16_t/char32_t encodings using \a cvt converter.
/// If \a cvt is null pointer, always failure conversion would be used that fails on every first input or
/// output.
///
/// Note: the codecvt facet handles both UTF-16 and UTF-32 wide encodings, it knows to break and join
/// Unicode code-points above 0xFFFF to and from surrogate pairs correctly. \a cvt should be unaware
/// of wide encoding type
BOOST_LOCALE_DECL
std::locale create_codecvt(const std::locale& in, std::unique_ptr<base_converter> cvt, char_facet_t type);
#ifndef BOOST_NO_CXX11_SMART_PTR
///
/// This function creates a \a base_converter that can be used for conversion between UTF-8 and
/// unicode code points
///
BOOST_LOCALE_DECL std::unique_ptr<base_converter> create_utf8_converter_unique_ptr();
///
/// This function creates a \a base_converter that can be used for conversion between single byte
/// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points,
///
/// If \a encoding is not supported, empty pointer is returned. You should check if
/// std::unique_ptr<base_converter>::get() != 0
///
BOOST_LOCALE_DECL std::unique_ptr<base_converter> create_simple_converter_unique_ptr(std::string const &encoding);
BOOST_DEPRECATED("This function is deprecated, use 'create_codecvt()'")
inline std::locale create_codecvt_from_pointer(const std::locale& in, base_converter* cvt, char_facet_t type)
{
return create_codecvt(in, std::unique_ptr<base_converter>(cvt), type);
}
///
/// Install codecvt facet into locale \a in and return new locale that is based on \a in and uses new
/// facet.
///
/// codecvt facet would convert between narrow and wide/char16_t/char32_t encodings using \a cvt converter.
/// If \a cvt is null pointer, always failure conversion would be used that fails on every first input or output.
///
/// Note: the codecvt facet handles both UTF-16 and UTF-32 wide encodings, it knows to break and join
/// Unicode code-points above 0xFFFF to and from surrogate pairs correctly. \a cvt should be unaware
/// of wide encoding type
///
BOOST_LOCALE_DECL
std::locale create_codecvt(std::locale const &in,std::unique_ptr<base_converter> cvt,character_facet_type type);
#endif
BOOST_DEPRECATED("This function is deprecated, use 'create_utf8_converter()'")
BOOST_LOCALE_DECL base_converter* create_utf8_converter_new_ptr();
///
/// This function creates a \a base_converter that can be used for conversion between UTF-8 and
/// unicode code points
///
BOOST_LOCALE_DECL base_converter *create_utf8_converter_new_ptr();
///
/// This function creates a \a base_converter that can be used for conversion between single byte
/// character encodings like ISO-8859-1, koi8-r, windows-1255 and Unicode code points,
///
/// If \a encoding is not supported, empty pointer is returned. You should check if
/// std::unique_ptr<base_converter>::get() != 0
///
BOOST_LOCALE_DECL base_converter *create_simple_converter_new_ptr(std::string const &encoding);
BOOST_DEPRECATED("This function is deprecated, use 'create_simple_converter()'")
BOOST_LOCALE_DECL base_converter* create_simple_converter_new_ptr(const std::string& encoding);
///
/// Install codecvt facet into locale \a in and return new locale that is based on \a in and uses new
/// facet.
///
/// codecvt facet would convert between narrow and wide/char16_t/char32_t encodings using \a cvt converter.
/// If \a cvt is null pointer, always failure conversion would be used that fails on every first input or output.
///
/// Note: the codecvt facet handles both UTF-16 and UTF-32 wide encodings, it knows to break and join
/// Unicode code-points above 0xFFFF to and from surrogate pairs correctly. \a cvt should be unaware
/// of wide encoding type
///
/// ownership of cvt is transfered
///
BOOST_LOCALE_DECL
std::locale create_codecvt_from_pointer(std::locale const &in,base_converter *cvt,character_facet_type type);
/// 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.
BOOST_LOCALE_DECL
std::locale create_utf8_codecvt(const std::locale& in, char_facet_t type);
///
/// 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.
///
BOOST_LOCALE_DECL
std::locale create_utf8_codecvt(std::locale const &in,character_facet_type type);
///
/// 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 boost::locale::conv::invalid_charset_error if the chacater set is not supported or isn't single byte character
/// set
BOOST_LOCALE_DECL
std::locale create_simple_codecvt(std::locale const &in,std::string const &encoding,character_facet_type type);
} // util
} // locale
} // boost
/// 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 boost::locale::conv::invalid_charset_error: Character set is not supported or isn't a single
/// byte character set
BOOST_LOCALE_DECL
std::locale create_simple_codecvt(const std::locale& in, const std::string& encoding, char_facet_t type);
} // namespace util
}} // namespace boost::locale
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4

View File

@@ -0,0 +1,78 @@
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
// Copyright (c) 2023 Alexander Grund
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_LOCALE_UTIL_LOCALE_DATA_HPP
#define BOOST_LOCALE_UTIL_LOCALE_DATA_HPP
#include <boost/locale/config.hpp>
#include <string>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4251)
#endif
namespace boost { namespace locale { namespace util {
/// Holder and parser for locale names/identifiers
class BOOST_LOCALE_DECL locale_data {
std::string language_;
std::string country_;
std::string encoding_;
std::string variant_;
bool utf8_;
public:
/// Default to C locale with US-ASCII encoding
locale_data();
/// Construct from the parsed locale \see \ref parse
///
/// \throws std::invalid_argument: parsing failed
explicit locale_data(const std::string& locale_name);
/// Return language (usually 2 lowercase letters, i.e. ISO-639 or 'C')
const std::string& language() const { return language_; }
/// Return country (usually 2 uppercase letters, i.e. ISO-3166)
const std::string& country() const { return country_; }
/// Return encoding/codeset, e.g. ISO8859-1 or UTF-8
const std::string& encoding() const { return encoding_; }
/// Set encoding, will be made uppercase by default as-if it was parsed
/// Returns \c *this for chaining
locale_data& encoding(std::string new_encoding, bool uppercase = true);
/// Return variant/modifier, e.g. euro or stroke
const std::string& variant() const { return variant_; }
/// Return iff the encoding is UTF-8
bool is_utf8() const { return utf8_; }
/// Parse a locale identifier of the form `[language[_territory][.codeset][@modifier]]`
///
/// Allows a dash as the delimiter: `[language-territory]`
/// Return true if the identifier is valid:
/// - `language` is given and consists of ASCII letters
/// - `territory`, if given, consists of ASCII letters
/// - Any field started by a delimiter (`_`, `-`, `.`, `@`) is not empty
/// Otherwise parsing is aborted. Valid values already parsed stay set, other are defaulted.
bool parse(const std::string& locale_name);
/// Get a representation in the form `[language[_territory][.codeset][@modifier]]`
/// codeset is omitted if it is US-ASCII
std::string to_string() const;
private:
void reset();
bool parse_from_lang(const std::string& input);
bool parse_from_country(const std::string& input);
bool parse_from_encoding(const std::string& input);
bool parse_from_variant(const std::string& input);
};
}}} // namespace boost::locale::util
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif

View File

@@ -0,0 +1,46 @@
//
// 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_STRING_HPP
#define BOOST_LOCALE_UTIL_STRING_HPP
#include <boost/locale/config.hpp>
#include <limits>
namespace boost { namespace locale { namespace util {
/// Return the end of a C-string, i.e. the pointer to the trailing NULL byte
template<typename Char>
Char* str_end(Char* str)
{
while(*str)
++str;
return str;
}
inline constexpr bool is_upper_ascii(const char c)
{
return 'A' <= c && c <= 'Z';
}
inline constexpr bool is_lower_ascii(const char c)
{
return 'a' <= c && c <= 'z';
}
inline constexpr bool is_numeric_ascii(const char c)
{
return '0' <= c && c <= '9';
}
/// Cast an unsigned char to a (possibly signed) char avoiding implementation defined behavior
constexpr char to_char(unsigned char c)
{
return static_cast<char>((c - std::numeric_limits<char>::min()) + std::numeric_limits<char>::min());
}
}}} // namespace boost::locale::util
#endif