Skip to content

Commit

Permalink
馃洜 Fix up the encoding_scheme returns from __select_compile_time_encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePhD committed Oct 9, 2022
1 parent 32174fd commit cf30b7f
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 94 deletions.
34 changes: 18 additions & 16 deletions include/ztd/text/any_encoding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,44 +90,46 @@ namespace ztd { namespace text {
///
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an
/// ztd::text::encoding_scheme first.
template <typename _Encoding, typename... _Args,
::std::enable_if_t<
!::std::is_same_v<_Encoding,
any_byte_encoding> && !::std::is_same_v<_Encoding, __base_t> && !is_specialization_of_v<remove_cvref_t<_Encoding>, ::std::in_place_type_t>>* = nullptr>
any_byte_encoding(_Encoding&& __encoding, _Args&&... __args)
: any_byte_encoding(::std::in_place_type<remove_cvref_t<_Encoding>>, ::std::forward<_Encoding>(__encoding),
::std::forward<_Args>(__args)...) {
template <typename _EncodingArg, typename... _Args,
::std::enable_if_t<!::std::is_same_v<remove_cvref_t<_EncodingArg>, any_byte_encoding> // cf
&& !::std::is_same_v<__txt_detail::__code_unit_or_void_t<remove_cvref_t<_EncodingArg>>, _Byte> // cf
&& !is_specialization_of_v<remove_cvref_t<_EncodingArg>, ::ztd::text::any_byte_encoding> // cf
&& !::std::is_same_v<remove_cvref_t<_EncodingArg>, __base_t> // cf
&& !is_specialization_of_v<remove_cvref_t<_EncodingArg>, ::std::in_place_type_t>>* = nullptr>
any_byte_encoding(_EncodingArg&& __encoding, _Args&&... __args)
: any_byte_encoding(::std::in_place_type<remove_cvref_t<_EncodingArg>>,
::std::forward<_EncodingArg>(__encoding), ::std::forward<_Args>(__args)...) {
}

//////
/// @brief Constructs a ztd::text::any_byte_encoding with the encoding object and any additional arguments.
///
/// @tparam _Encoding The Encoding specified by the `std::in_place_type<...>` argument.
/// @tparam _EncodingArg The Encoding specified by the `std::in_place_type<...>` argument.
///
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage.
///
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an
/// ztd::text::encoding_scheme first.
template <typename _Encoding, typename... _Args,
::std::enable_if_t<!::std::is_same_v<_Byte, code_unit_t<remove_cvref_t<_Encoding>>>>* = nullptr>
any_byte_encoding(::std::in_place_type_t<_Encoding>, _Args&&... __args)
: __base_t(::std::in_place_type_t<encoding_scheme<remove_cvref_t<_Encoding>, endian::native, _Byte>> {},
template <typename _EncodingArg, typename... _Args,
::std::enable_if_t<!::std::is_same_v<_Byte, code_unit_t<remove_cvref_t<_EncodingArg>>>>* = nullptr>
any_byte_encoding(::std::in_place_type_t<_EncodingArg>, _Args&&... __args)
: __base_t(::std::in_place_type_t<encoding_scheme<remove_cvref_t<_EncodingArg>, endian::native, _Byte>> {},
::std::forward<_Args>(__args)...) {
}

//////
/// @brief Constructs a ztd::text::any_byte_encoding with the encoding object and any additional arguments.
///
/// @tparam _Encoding The Encoding specified by the `std::in_place_type<...>` argument.
/// @tparam _EncodingArg The Encoding specified by the `std::in_place_type<...>` argument.
///
/// @param[in] __tag A tag containing the encoding type.
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage.
///
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an
/// ztd::text::encoding_scheme first.
template <typename _Encoding, typename... _Args,
::std::enable_if_t<::std::is_same_v<_Byte, code_unit_t<remove_cvref_t<_Encoding>>>>* = nullptr>
any_byte_encoding(::std::in_place_type_t<_Encoding> __tag, _Args&&... __args)
template <typename _EncodingArg, typename... _Args,
::std::enable_if_t<::std::is_same_v<_Byte, code_unit_t<remove_cvref_t<_EncodingArg>>>>* = nullptr>
any_byte_encoding(::std::in_place_type_t<_EncodingArg> __tag, _Args&&... __args)
: __base_t(::std::move(__tag), ::std::forward<_Args>(__args)...) {
}

Expand Down
5 changes: 2 additions & 3 deletions include/ztd/text/any_encoding_with.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,8 @@ namespace ztd { namespace text {
/// object to store.
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage.
template <typename _Encoding, typename... _Args,
::std::enable_if_t<
!::std::is_same_v<_Encoding,
any_encoding_with> && !is_specialization_of_v<remove_cvref_t<_Encoding>, ::std::in_place_type_t>>* = nullptr>
::std::enable_if_t<!::std::is_same_v<_Encoding, any_encoding_with> && // cf
!is_specialization_of_v<remove_cvref_t<_Encoding>, ::std::in_place_type_t>>* = nullptr>
any_encoding_with(_Encoding&& __encoding, _Args&&... __args)
: any_encoding_with(::std::in_place_type<remove_cvref_t<_Encoding>>, ::std::forward<_Encoding>(__encoding),
::std::forward<_Args>(__args)...) {
Expand Down
135 changes: 95 additions & 40 deletions include/ztd/text/basic_encoding_scheme.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,31 @@ namespace ztd { namespace text {
/// @{

//////
/// @brief Decomposes the provided Encoding type into a specific endianness (big, little, or native) to allow for a
/// single encoding type to be viewed in different ways.
/// @brief Decomposes the provided Encoding type into a specific endianness (big, little, or native) to allow
/// for a single encoding type to be viewed in different ways.
///
/// @tparam _Encoding The encoding type.
/// @tparam _Endian The endianess to use. Defaults to ztd::endian::native.
/// @tparam _Byte The byte type to use. Defaults to ``std::byte``.
///
/// @remarks For example, this can be used to construct a Big Endian UTF-16 by using
/// ``encoding_scheme<ztd::text::utf16_t, ztd::endian::big>``. It can be made interopable with ``unsigned
/// char`` buffers rather than ``std::byte`` buffers by doing: ``ztd::text::encoding_scheme<ztd::text::utf32_t,
/// ztd::endian::native, unsigned char>``.
/// char`` buffers rather than ``std::byte`` buffers by doing:
/// ``ztd::text::encoding_scheme<ztd::text::utf32_t, ztd::endian::native, unsigned char>``.
template <typename _Encoding, endian _Endian = endian::native, typename _Byte = ::std::byte>
class encoding_scheme : public __txt_detail::__is_unicode_encoding_es<encoding_scheme<_Encoding, _Endian, _Byte>,
unwrap_remove_cvref_t<_Encoding>>,
private ebco<_Encoding> {
class encoding_scheme
: public __txt_detail::__is_unicode_encoding_es<encoding_scheme<_Encoding, _Endian, _Byte>,
unwrap_remove_cvref_t<_Encoding>>,
private ebco<_Encoding> {
private:
using __base_t = ebco<_Encoding>;
using _UBaseEncoding = unwrap_remove_cvref_t<_Encoding>;
using _BaseCodeUnit = code_unit_t<_UBaseEncoding>;

public:
///////
//////
/// @brief The encoding type.
//////
/// @brief The encoding type that this scheme wraps.
using encoding_type = _Encoding;
//////
Expand All @@ -93,16 +96,16 @@ namespace ztd { namespace text {
//////
/// @brief The state that can be used between calls to the decode function.
///
/// @remarks Even if the underlying encoding only has a single `state` type, we need to separate the two out
/// in order to generically handle all encodings. Therefore, the encoding_scheme will always have both
/// `encode_state` and `decode_state.`
/// @remarks Even if the underlying encoding only has a single `state` type, we need to separate the two
/// out in order to generically handle all encodings. Therefore, the encoding_scheme will always have
/// both `encode_state` and `decode_state.`
using decode_state = decode_state_t<_UBaseEncoding>;
//////
/// @brief The state that can be used between calls to the encode function.
///
/// @remarks Even if the underlying encoding only has a single `state` type, we need to separate the two out
/// in order to generically handle all encodings. Therefore, the encoding_scheme will always have both
/// `encode_state` and `decode_state.`
/// @remarks Even if the underlying encoding only has a single `state` type, we need to separate the two
/// out in order to generically handle all encodings. Therefore, the encoding_scheme will always have
/// both `encode_state` and `decode_state.`
using encode_state = encode_state_t<_UBaseEncoding>;
//////
/// @brief Whether or not the encode operation can process all forms of input into code point values.
Expand Down Expand Up @@ -131,8 +134,58 @@ namespace ztd { namespace text {
encoded_id_v<_UBaseEncoding>, _Endian, sizeof(code_unit_t<_UBaseEncoding>));

//////
/// @brief Constructs a ztd::text::encoding_scheme with the given arguments.
using __base_t::__base_t;
/// @brief Default constructs a ztd::text::encoding_scheme.
encoding_scheme() = default;

//////
/// @brief Constructs a ztd::text::encoding_scheme with the encoding object and any additional arguments.
///
/// @param[in] __arg0 The first argument used to construct the stored encoding.
/// @param[in] __args Any additional arguments used to construct the stored encoding.
template <typename _Arg0, typename... _Args,
::std::enable_if_t<!::std::is_same_v<remove_cvref_t<_Arg0>, encoding_scheme> // cf
&& !::std::is_same_v<remove_cvref_t<_Arg0>, ::std::in_place_t>>* = nullptr>
constexpr encoding_scheme(_Arg0&& __arg0, _Args&&... __args) noexcept(
::std::is_nothrow_constructible_v<_UBaseEncoding, _Arg0, _Args...>)
: __base_t(::std::forward<_Arg0>(__arg0), ::std::forward<_Args>(__args)...) {
}

//////
/// @brief Constructs a ztd::text::encoding_scheme with the encoding object and any additional arguments.
///
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage.
///
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an
/// ztd::text::encoding_scheme first.
template <typename... _Args>
constexpr encoding_scheme(::std::in_place_t, _Args&&... __args) noexcept(
::std::is_nothrow_constructible_v<_UBaseEncoding, _Args...>)
: __base_t(::std::forward<_Args>(__args)...) {
}

//////
/// @brief Cannot copy-construct a ztd::text::encoding_scheme object.
encoding_scheme(const encoding_scheme&) = default;

//////
/// @brief Cannot copy-assign a ztd::text::encoding_scheme object.
encoding_scheme& operator=(const encoding_scheme&) = default;

//////
/// @brief Move-constructs a ztd::text::encoding_scheme from the provided r-value reference.
///
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function
/// on a moved-fron ztd::text::encoding_scheme, except for destruction, is a violation and invokes
/// Undefined Behavior (generally, a crash).
encoding_scheme(encoding_scheme&&) = default;

//////
/// @brief Move-assigns a ztd::text::encoding_scheme from the provided r-value reference.
///
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function
/// on a moved-fron ztd::text::encoding_scheme, except for destruction, is a violation and may invoke
/// Undefined Behavior (generally, a crash).
encoding_scheme& operator=(encoding_scheme&&) = default;

//////
/// @brief Retrives the underlying encoding object.
Expand Down Expand Up @@ -161,8 +214,8 @@ namespace ztd { namespace text {
//////
/// @brief Returns, the desired replacement code units to use.
///
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down into
/// a contiguous view type formulated from bytes if the wrapped code unit types do not match.
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down
/// into a contiguous view type formulated from bytes if the wrapped code unit types do not match.
template <typename _Unused = encoding_type,
::std::enable_if_t<is_code_units_replaceable_v<_Unused>>* = nullptr>
constexpr decltype(auto) replacement_code_units() const noexcept {
Expand All @@ -177,9 +230,10 @@ namespace ztd { namespace text {
using _TransformedSpan = ::ztd::span<const code_unit>;
_OriginalSpan __guaranteed_code_unit_view(__original);
// transform into proper type...
auto __transformed_ptr = reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data());
auto __transformed_size
= (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit)) / sizeof(const code_unit);
auto __transformed_ptr
= reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data());
auto __transformed_size = (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit))
/ sizeof(const code_unit);
return _TransformedSpan(__transformed_ptr, __transformed_size);
}
}
Expand All @@ -198,8 +252,8 @@ namespace ztd { namespace text {
/// @brief Returns the desired replacement code units to use, or an empty optional-like type if there is
/// nothing present.
///
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down into
/// a contiguous view type formulated from bytes if the wrapped code unit types do not match.
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down
/// into a contiguous view type formulated from bytes if the wrapped code unit types do not match.
template <typename _Unused = encoding_type,
::std::enable_if_t<is_code_units_maybe_replaceable_v<_Unused>>* = nullptr>
constexpr decltype(auto) maybe_replacement_code_units() const noexcept {
Expand All @@ -218,9 +272,10 @@ namespace ztd { namespace text {
decltype(auto) __original = *__maybe_original;
_OriginalSpan __guaranteed_code_unit_view(__original);
// transform into proper type...
auto __transformed_ptr = reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data());
auto __transformed_size
= (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit)) / sizeof(const code_unit);
auto __transformed_ptr
= reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data());
auto __transformed_size = (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit))
/ sizeof(const code_unit);
return _TransformedSpan(__transformed_ptr, __transformed_size);
}
}
Expand Down Expand Up @@ -259,23 +314,23 @@ namespace ztd { namespace text {
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be
/// incremented even if an error occurs due to the semantics of any view that models an input_range.
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler>
constexpr auto decode_one(_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler,
decode_state& __s) const {
constexpr auto decode_one(_InputRange&& __input, _OutputRange&& __output,
_ErrorHandler&& __error_handler, decode_state& __s) const {
using _UInputRange = remove_cvref_t<_InputRange>;
using _UOutputRange = remove_cvref_t<_OutputRange>;
using _CVErrorHandler = ::std::remove_reference_t<_ErrorHandler>;
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, decode_state>;
using _Result
= __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, decode_state>;
using _InByteIt = ranges::word_iterator<_BaseCodeUnit, _UInputRange, _Endian>;
using _InByteSen = ranges::word_sentinel;

ranges::subrange<_InByteIt, _InByteSen> __inbytes(
_InByteIt(::std::forward<_InputRange>(__input)), _InByteSen());
__txt_detail::__scheme_handler<_Byte, _UInputRange, _UOutputRange, _CVErrorHandler>
__intermediate_handler(__error_handler);
auto __result = this->base().decode_one(
::std::move(__inbytes), ::std::forward<_OutputRange>(__output), __intermediate_handler, __s);
return _Result(ranges::reconstruct(
::std::in_place_type<_UInputRange>, ::std::move(__result.input).begin().range()),
return _Result(ranges::reconstruct(::std::in_place_type<_UInputRange>,
::std::move(__result.input).begin().range()),
ranges::reconstruct(::std::in_place_type<_UOutputRange>, ::std::move(__result.output)), __s,
__result.error_code, __result.handled_errors);
}
Expand All @@ -299,7 +354,7 @@ namespace ztd { namespace text {
/// incremented even if an error occurs due to the semantics of any view that models an input_range.
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler>
constexpr auto encode_one(_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler,
encode_state& __s) const {
encode_state& __s) const {
using _UInputRange = remove_cvref_t<_InputRange>;
using _UOutputRange = remove_cvref_t<_OutputRange>;
using _CVErrorHandler = ::std::remove_reference_t<_ErrorHandler>;
Expand All @@ -308,15 +363,15 @@ namespace ztd { namespace text {
using _OutByteSen = ranges::word_sentinel;

ranges::subrange<_OutByteIt, _OutByteSen> __outwords(
_OutByteIt(::std::forward<_OutputRange>(__output)), _OutByteSen());
_OutByteIt(::std::forward<_OutputRange>(__output)), _OutByteSen());
__txt_detail::__scheme_handler<_Byte, _UInputRange, _UOutputRange, _CVErrorHandler>
__intermediate_handler(__error_handler);
__intermediate_handler(__error_handler);
auto __result = this->base().encode_one(
::std::forward<_InputRange>(__input), __outwords, __intermediate_handler, __s);
::std::forward<_InputRange>(__input), __outwords, __intermediate_handler, __s);
return _Result(ranges::reconstruct(::std::in_place_type<_UInputRange>, ::std::move(__result.input)),
ranges::reconstruct(
::std::in_place_type<_UOutputRange>, ::std::move(__result.output).begin().range()),
__s, __result.error_code, __result.handled_errors);
ranges::reconstruct(
::std::in_place_type<_UOutputRange>, ::std::move(__result.output).begin().range()),
__s, __result.error_code, __result.handled_errors);
}
};

Expand All @@ -328,4 +383,4 @@ namespace ztd { namespace text {

#include <ztd/epilogue.hpp>

#endif // ZTD_TEXT_BASIC_ENCODING_SCHEME_HPP
#endif // ZTD_TEXT_BASIC_ENCODING_SCHEME_HPP
4 changes: 2 additions & 2 deletions include/ztd/text/basic_iconv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ namespace ztd { namespace text {
char* __p_faux_drain = __faux_drain;
const ::std::size_t __initial_faux_drain_size = sizeof(__faux_drain);
::std::size_t __faux_drain_size = __initial_faux_drain_size;
char* __p_input = __drain;
const char* __p_input = __drain;
const ::std::size_t __initial_input_size = __initial_drain_size - __drain_size;
::std::size_t __input_size = __initial_input_size;
const ::std::size_t __clear_result = __iconv_functions.convert(
Expand Down Expand Up @@ -162,7 +162,7 @@ namespace ztd { namespace text {
::std::size_t __drain_size = sizeof(__drain);
char __input_write_bom[__max_input_size];
ranges::__rng_detail::__copy_n_unsafe(__input + 0, __max_input_size, __input_write_bom + 0);
char* __p_input_write_bom = __input_write_bom;
const char* __p_input_write_bom = __input_write_bom;
::std::size_t __input_write_bom_size = __from_size;
const ::std::size_t __write_bom_result = ::ztd::plat::icnv::functions().convert(
__desc, &__p_input_write_bom, &__input_write_bom_size, &__p_drain, &__drain_size);
Expand Down

0 comments on commit cf30b7f

Please sign in to comment.