cppx-core
utf16-surrogate-pairs.hpp
Go to the documentation of this file.
1 #pragma once // Source encoding: UTF-8 with BOM (π is a lowercase Greek "pi").
2 #include <cppx-core/collections/Range_.hpp> // cppx::Range_
3 #include <cppx-core/language/types/byte-types.hpp> // cppx::(Byte, magnitude_bits_per_)
4 #include <cppx-core/meta-template/Enable_if_.hpp> // cppx::Enable_if_
5 #include <cppx-core/meta-type/type-traits.hpp> // cppx::Item_for_iterator_
6 
7 #include <c/assert.hpp> // assert
8 #include <c/stdint.hpp> // uint32_t
9 
10 namespace cppx::utf16
11 {
12  constexpr uint32_t first_beyond = 1uL << 16; // 0x10000
13  constexpr unsigned max_value = first_beyond - 1; // 0xFFFF
14 
15  // UTF-16 surrogate pair value ranges:
16  constexpr Range_<unsigned> range_of_pair_value_1( 0xD800, 0xDBFF );
17  constexpr Range_<unsigned> range_of_pair_value_2( 0xDC00, 0xDFFF );
18 
19  inline constexpr auto code_from_pair( const unsigned v1, const unsigned v2 ) noexcept
20  -> uint32_t
21  {
22  //assert( range_of_pair_value_1.contains( v1 ) );
23  //assert( range_of_pair_value_2.contains( v2 ) );
24  return first_beyond + (
25  ((v1 - range_of_pair_value_1.lower()) << 10) |
26  (v2 - range_of_pair_value_2.lower())
27  );
28  }
29 
30  inline constexpr auto pair_value_1_from( const uint32_t code )
31  -> unsigned
32  {
33  // assert( code > max_value )
34  return ((code - first_beyond) >> 10) + range_of_pair_value_1.lower();
35  }
36 
37  inline constexpr auto pair_value_2_from( const uint32_t code )
38  -> unsigned
39  {
40  // assert( code > max_value )
41  return (code & 0x3FFu) + range_of_pair_value_2.lower();
42  }
43 
44  template<
45  class Out_iterator,
46  class = Enable_if_<(magnitude_bits_per_<Item_for_iterator_<Out_iterator>> >= 16)>
47  >
48  auto from_code_point( const uint32_t code_point, const Out_iterator destination )
49  -> Out_iterator
50  {
51  using Out_value = Item_for_iterator_<Out_iterator>;
52  if( code_point < max_value )
53  {
54  *destination = static_cast<Out_value>( code_point );
55  return next( destination );
56  }
57 
58  Out_iterator it = destination;
59  *it = static_cast<Out_value>( pair_value_1_from( code_point ) ); ++it;
60  *it = static_cast<Out_value>( pair_value_2_from( code_point ) ); ++it;
61  return it;
62  }
63 
64 } // namespace cppx::utf16
constexpr unsigned max_value
auto from_code_point(const uint32_t code_point, const Out_iterator destination) -> Out_iterator
constexpr Range_< unsigned > range_of_pair_value_2(0xDC00, 0xDFFF)
constexpr auto pair_value_1_from(const uint32_t code) -> unsigned
constexpr uint32_t first_beyond
constexpr Range_< unsigned > range_of_pair_value_1(0xD800, 0xDBFF)
constexpr auto code_from_pair(const unsigned v1, const unsigned v2) noexcept -> uint32_t
auto next(P_< const char > p) -> P_< const char >
typename std::iterator_traits< Iterator >::value_type Item_for_iterator_
Definition: type-traits.hpp:50
std::enable_if_t< condition, Result > Enable_if_
Just more readable than enable_if_t.
Byte and Signed_byte, + std::byte support definitions as_number and as_std_byte.
constexpr auto pair_value_2_from(const uint32_t code) -> unsigned