| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #pragma once
- #include "lang/lang_tag.h"
- enum lngtag_count : int;
- namespace Lang {
- namespace details {
- inline constexpr auto kPluralCount = 6;
- template <typename Tag>
- inline constexpr ushort TagValue();
- template <typename P>
- using S = std::decay_t<decltype(std::declval<P>()(QString()))>;
- [[nodiscard]] QString Current(ushort key);
- [[nodiscard]] rpl::producer<QString> Value(ushort key);
- [[nodiscard]] bool IsNonDefaultPlural(ushort keyBase);
- template <int Index, typename Type, typename Tuple>
- [[nodiscard]] Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) {
- return accumulated;
- }
- template <
- int Index,
- typename Type,
- typename Tuple,
- typename Tag,
- typename ...Tags>
- [[nodiscard]] Type ReplaceUnwrapTuple(
- Type accumulated,
- const Tuple &tuple,
- Tag tag,
- Tags ...tags) {
- return ReplaceUnwrapTuple<Index + 1>(
- ReplaceTag<Type>::Call(
- std::move(accumulated),
- tag,
- std::get<Index>(tuple)),
- tuple,
- tags...);
- }
- template <typename ...Tags>
- struct ReplaceUnwrap;
- template <>
- struct ReplaceUnwrap<> {
- template <typename Type>
- [[nodiscard]] static Type Call(Type accumulated) {
- return accumulated;
- }
- };
- template <typename Tag, typename ...Tags>
- struct ReplaceUnwrap<Tag, Tags...> {
- template <typename Type, typename Value, typename ...Values>
- [[nodiscard]] static Type Call(
- Type accumulated,
- const Value &value,
- const Values &...values) {
- return ReplaceUnwrap<Tags...>::Call(
- ReplaceTag<Type>::Call(
- std::move(accumulated),
- TagValue<Tag>(),
- value),
- values...);
- }
- };
- template <typename ...Tags>
- struct Producer {
- template <typename P, typename ...Values>
- [[nodiscard]] static rpl::producer<S<P>> Combine(ushort base, P p, Values &...values) {
- return rpl::combine(
- Value(base),
- std::move(values)...
- ) | rpl::map([p = std::move(p)](auto tuple) {
- return ReplaceUnwrapTuple<1>(p(std::get<0>(tuple)), tuple, TagValue<Tags>()...);
- });
- }
- template <typename P, typename ...Values>
- [[nodiscard]] static S<P> Current(ushort base, P p, const Values &...values) {
- return ReplaceUnwrap<Tags...>::Call(
- p(Lang::details::Current(base)),
- values...);
- }
- };
- template <>
- struct Producer<> {
- template <typename P>
- [[nodiscard]] static rpl::producer<S<P>> Combine(ushort base, P p) {
- return Value(base) | rpl::map(std::move(p));
- }
- template <typename P>
- [[nodiscard]] static S<P> Current(ushort base, P p) {
- return p(Lang::details::Current(base));
- }
- };
- template <typename ...Tags>
- struct Producer<lngtag_count, Tags...> {
- template <typename P, typename ...Values>
- [[nodiscard]] static rpl::producer<S<P>> Combine(
- ushort base,
- P p,
- lngtag_count type,
- rpl::producer<float64> &count,
- Values &...values) {
- return rpl::combine(
- Value(base),
- Value(base + 1),
- Value(base + 2),
- Value(base + 3),
- Value(base + 4),
- Value(base + 5),
- std::move(count),
- std::move(values)...
- ) | rpl::map([base, type, p = std::move(p)](auto tuple) {
- auto plural = Plural(base, std::get<6>(tuple), type);
- const auto select = [&] {
- switch (plural.keyShift) {
- case 0: return std::get<0>(tuple);
- case 1: return std::get<1>(tuple);
- case 2: return std::get<2>(tuple);
- case 3: return std::get<3>(tuple);
- case 4: return std::get<4>(tuple);
- case 5: return std::get<5>(tuple);
- }
- Unexpected("Lang shift value in Plural result.");
- };
- return ReplaceUnwrapTuple<7>(
- ReplaceTag<S<P>>::Call(
- p(select()),
- TagValue<lngtag_count>(),
- StartReplacements<S<P>>::Call(
- std::move(plural.replacement))),
- tuple,
- TagValue<Tags>()...);
- });
- }
- template <typename P, typename ...Values>
- [[nodiscard]] static S<P> Current(
- ushort base,
- P p,
- lngtag_count type,
- float64 count,
- const Values &...values) {
- auto plural = Plural(base, count, type);
- return ReplaceUnwrap<Tags...>::Call(
- ReplaceTag<S<P>>::Call(
- p(Lang::details::Current(base + plural.keyShift)),
- TagValue<lngtag_count>(),
- StartReplacements<S<P>>::Call(
- std::move(plural.replacement))),
- values...);
- }
- };
- } // namespace details
- } // namespace Lang
|