diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdutils')
64 files changed, 1498 insertions, 841 deletions
diff --git a/protocols/Telegram/tdlib/td/tdutils/CMakeLists.txt b/protocols/Telegram/tdlib/td/tdutils/CMakeLists.txt index e7b4b788a7..4760aab011 100644 --- a/protocols/Telegram/tdlib/td/tdutils/CMakeLists.txt +++ b/protocols/Telegram/tdlib/td/tdutils/CMakeLists.txt @@ -3,12 +3,13 @@ if ((CMAKE_MAJOR_VERSION LESS 3) OR (CMAKE_VERSION VERSION_LESS "3.0.2")) endif() option(TDUTILS_MIME_TYPE "Generate MIME types conversion; requires gperf" ON) +option(TDUTILS_USE_EXTERNAL_DEPENDENCIES "Use external libraries if available" ON) if (NOT DEFINED CMAKE_INSTALL_LIBDIR) set(CMAKE_INSTALL_LIBDIR "lib") endif() -if (NOT ZLIB_FOUND) +if (NOT ZLIB_FOUND AND TDUTILS_USE_EXTERNAL_DEPENDENCIES) find_package(ZLIB) endif() if (ZLIB_FOUND) @@ -24,11 +25,14 @@ if (ZLIB_FOUND) endif() endif() +if (NOT CRC32C_FOUND AND TDUTILS_USE_EXTERNAL_DEPENDENCIES) + find_package(Crc32c QUIET) +endif() if (CRC32C_FOUND) set(TD_HAVE_CRC32C 1) endif() -if (TD_WITH_ABSEIL) +if (TD_WITH_ABSEIL AND TDUTILS_USE_EXTERNAL_DEPENDENCIES) find_package(ABSL QUIET) if (ABSL_FOUND) set(TD_HAVE_ABSL 1) @@ -39,7 +43,6 @@ configure_file(td/utils/config.h.in td/utils/config.h @ONLY) add_subdirectory(generate) -# TDUTILS set_source_files_properties(${TDMIME_AUTO} PROPERTIES GENERATED TRUE) if (CLANG OR GCC) set_property(SOURCE ${TDMIME_AUTO} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-conversion") @@ -104,6 +107,7 @@ set(TDUTILS_SOURCE td/utils/Gzip.cpp td/utils/GzipByteFlow.cpp td/utils/Hints.cpp + td/utils/HttpDate.cpp td/utils/HttpUrl.cpp td/utils/JsonBuilder.cpp td/utils/logging.cpp @@ -120,7 +124,6 @@ set(TDUTILS_SOURCE td/utils/tests.cpp td/utils/Time.cpp td/utils/Timer.cpp - td/utils/TsFileLog.cpp td/utils/tl_parsers.cpp td/utils/translit.cpp td/utils/TsCerr.cpp @@ -136,8 +139,8 @@ set(TDUTILS_SOURCE td/utils/port/EventFdBase.h td/utils/port/FileFd.h td/utils/port/FromApp.h - td/utils/port/IPAddress.h td/utils/port/IoSlice.h + td/utils/port/IPAddress.h td/utils/port/MemoryMapping.h td/utils/port/Mutex.h td/utils/port/path.h @@ -210,8 +213,8 @@ set(TDUTILS_SOURCE td/utils/ExitGuard.h td/utils/FileLog.h td/utils/filesystem.h - td/utils/fixed_vector.h td/utils/find_boundary.h + td/utils/fixed_vector.h td/utils/FlatHashMap.h td/utils/FlatHashMapChunks.h td/utils/FlatHashSet.h @@ -229,6 +232,7 @@ set(TDUTILS_SOURCE td/utils/HazardPointers.h td/utils/Heap.h td/utils/Hints.h + td/utils/HttpDate.h td/utils/HttpUrl.h td/utils/int_types.h td/utils/invoke.h @@ -241,8 +245,8 @@ set(TDUTILS_SOURCE td/utils/MovableValue.h td/utils/MpmcQueue.h td/utils/MpmcWaiter.h - td/utils/MpscPollableQueue.h td/utils/MpscLinkQueue.h + td/utils/MpscPollableQueue.h td/utils/Named.h td/utils/NullLog.h td/utils/ObjectPool.h @@ -345,7 +349,6 @@ set(TDUTILS_TEST_SOURCE PARENT_SCOPE ) -#LIBRARIES add_library(tdutils STATIC ${TDUTILS_SOURCE}) if (NOT CMAKE_CROSSCOMPILING AND TDUTILS_MIME_TYPE) @@ -401,17 +404,17 @@ if (ANDROID) target_link_libraries(tdutils PRIVATE log) endif() -if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") - target_link_directories(tdutils PUBLIC /usr/pkg/gcc12/x86_64--netbsd/lib /usr/pkg/gcc12/i486--netbsdelf/lib) - target_link_libraries(tdutils PUBLIC atomic) +find_package(Atomics REQUIRED) +if (ATOMICS_LIBRARIES) + target_link_libraries(tdutils PUBLIC "${ATOMICS_LIBRARIES}") endif() -install(TARGETS tdutils EXPORT TdTargets +install(TARGETS tdutils EXPORT TdStaticTargets LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) -if (TD_TEST_FOLLY AND ABSL_FOUND) +if (TD_TEST_FOLLY AND ABSL_FOUND AND TDUTILS_USE_EXTERNAL_DEPENDENCIES) find_package(benchmark QUIET) find_package(folly QUIET) find_package(gflags QUIET) diff --git a/protocols/Telegram/tdlib/td/tdutils/generate/auto/extension_to_mime_type.cpp b/protocols/Telegram/tdlib/td/tdutils/generate/auto/extension_to_mime_type.cpp index 809b73df27..f95adb7e23 100644 --- a/protocols/Telegram/tdlib/td/tdutils/generate/auto/extension_to_mime_type.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/generate/auto/extension_to_mime_type.cpp @@ -1,5 +1,5 @@ -/* ANSI-C code produced by gperf version 3.0.1 */ -/* Command-line: 'C:\\Util\\gperf.exe' -m100 --output-file=auto/extension_to_mime_type.cpp auto/extension_to_mime_type.gperf */ +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: 'W:\\Test\\td\\vcpkg\\installed\\x64-windows\\tools\\gperf\\gperf.exe' -m100 --output-file=auto/extension_to_mime_type.cpp auto/extension_to_mime_type.gperf */ /* Computed positions: -k'1-4,6,$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -26,7 +26,7 @@ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ -#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." #endif #line 12 "auto/extension_to_mime_type.gperf" @@ -86,7 +86,7 @@ inline #endif #endif static unsigned int -extension_hash (register const char *str, register unsigned int len) +extension_hash (register const char *str, register size_t len) { static const unsigned short asso_values[] = { @@ -122,7 +122,7 @@ extension_hash (register const char *str, register unsigned int len) 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376, 3376 }; - register int hval = len; + register unsigned int hval = len; switch (hval) { @@ -146,11 +146,8 @@ extension_hash (register const char *str, register unsigned int len) return hval + asso_values[(unsigned char)str[len - 1]]; } -#ifdef __GNUC__ -__inline -#endif const struct extension_and_mime_type * -search_extension (register const char *str, register unsigned int len) +search_extension (register const char *str, register size_t len) { enum { @@ -3036,9 +3033,9 @@ search_extension (register const char *str, register unsigned int len) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - register int key = extension_hash (str, len); + register unsigned int key = extension_hash (str, len); - if (key <= MAX_HASH_VALUE && key >= 0) + if (key <= MAX_HASH_VALUE) { register const char *s = wordlist[key].extension; diff --git a/protocols/Telegram/tdlib/td/tdutils/generate/auto/mime_type_to_extension.cpp b/protocols/Telegram/tdlib/td/tdutils/generate/auto/mime_type_to_extension.cpp index c2e8686590..1138cd050a 100644 --- a/protocols/Telegram/tdlib/td/tdutils/generate/auto/mime_type_to_extension.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/generate/auto/mime_type_to_extension.cpp @@ -1,5 +1,5 @@ -/* ANSI-C code produced by gperf version 3.0.1 */ -/* Command-line: 'C:\\Util\\gperf.exe' -m100 --output-file=auto/mime_type_to_extension.cpp auto/mime_type_to_extension.gperf */ +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: 'W:\\Test\\td\\vcpkg\\installed\\x64-windows\\tools\\gperf\\gperf.exe' -m100 --output-file=auto/mime_type_to_extension.cpp auto/mime_type_to_extension.gperf */ /* Computed positions: -k'1,6-7,9-10,13-18,20,23,25-26,31,36,$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -26,7 +26,7 @@ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ -#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>." +#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>." #endif #line 12 "auto/mime_type_to_extension.gperf" @@ -86,7 +86,7 @@ inline #endif #endif static unsigned int -mime_type_hash (register const char *str, register unsigned int len) +mime_type_hash (register const char *str, register size_t len) { static const unsigned short asso_values[] = { @@ -117,7 +117,7 @@ mime_type_hash (register const char *str, register unsigned int len) 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686, 4686 }; - register int hval = len; + register unsigned int hval = len; switch (hval) { @@ -195,11 +195,8 @@ mime_type_hash (register const char *str, register unsigned int len) return hval + asso_values[(unsigned char)str[len - 1]]; } -#ifdef __GNUC__ -__inline -#endif const struct mime_type_and_extension * -search_mime_type (register const char *str, register unsigned int len) +search_mime_type (register const char *str, register size_t len) { enum { @@ -3010,9 +3007,9 @@ search_mime_type (register const char *str, register unsigned int len) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - register int key = mime_type_hash (str, len); + register unsigned int key = mime_type_hash (str, len); - if (key <= MAX_HASH_VALUE && key >= 0) + if (key <= MAX_HASH_VALUE) { register const char *s = wordlist[key].mime_type; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/BufferedFd.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/BufferedFd.h index 17bef41ffb..4270829cb4 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/BufferedFd.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/BufferedFd.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -24,7 +24,7 @@ template <class FdT> class BufferedFdBase : public FdT { public: BufferedFdBase() = default; - explicit BufferedFdBase(FdT &&fd_); + explicit BufferedFdBase(FdT &&fd); // TODO: make move constructor and move assignment safer Result<size_t> flush_read(size_t max_read = std::numeric_limits<size_t>::max()) TD_WARN_UNUSED_RESULT; @@ -65,7 +65,7 @@ class BufferedFd final : public BufferedFdBase<FdT> { public: BufferedFd(); - explicit BufferedFd(FdT &&fd_); + explicit BufferedFd(FdT &&fd); BufferedFd(BufferedFd &&) noexcept; BufferedFd &operator=(BufferedFd &&) noexcept; BufferedFd(const BufferedFd &) = delete; @@ -93,7 +93,7 @@ class BufferedFd final : public BufferedFdBase<FdT> { /*** BufferedFd ***/ template <class FdT> -BufferedFdBase<FdT>::BufferedFdBase(FdT &&fd_) : FdT(std::move(fd_)) { +BufferedFdBase<FdT>::BufferedFdBase(FdT &&fd) : FdT(std::move(fd)) { } template <class FdT> @@ -166,7 +166,7 @@ BufferedFd<FdT>::BufferedFd() { } template <class FdT> -BufferedFd<FdT>::BufferedFd(FdT &&fd_) : Parent(std::move(fd_)) { +BufferedFd<FdT>::BufferedFd(FdT &&fd) : Parent(std::move(fd)) { init(); } diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/ByteFlow.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/ByteFlow.h index 0d228abcf4..5a685f5e11 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/ByteFlow.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/ByteFlow.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -25,6 +25,7 @@ class ByteFlowInterface { virtual size_t get_write_size() = 0; virtual void reset_need_size() { } + ByteFlowInterface() = default; ByteFlowInterface(const ByteFlowInterface &) = delete; ByteFlowInterface &operator=(const ByteFlowInterface &) = delete; @@ -139,6 +140,7 @@ class ByteFlowBaseCommon : public ByteFlowInterface { bool can_read{true}; bool can_write{true}; Options options_; + void finish(Status status) { stop_flag_ = true; need_size_ = 0; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/ChainScheduler.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/ChainScheduler.h index a7624bb97b..d30b1a062b 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/ChainScheduler.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/ChainScheduler.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -9,8 +9,8 @@ #include "td/utils/algorithm.h" #include "td/utils/common.h" #include "td/utils/Container.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/FlatHashSet.h" -#include "td/utils/HashTableUtils.h" #include "td/utils/List.h" #include "td/utils/logging.h" #include "td/utils/optional.h" @@ -19,7 +19,6 @@ #include "td/utils/VectorQueue.h" #include <functional> -#include <unordered_map> namespace td { @@ -50,7 +49,7 @@ class ChainScheduler final : public ChainSchedulerBase { template <class F> void for_each(F &&f) { - tasks_.for_each([&f](auto, Task &task) { f(task.extra); }); + tasks_.for_each([&f](uint64, Task &task) { f(task.extra); }); } template <class F> @@ -141,11 +140,19 @@ class ChainScheduler final : public ChainSchedulerBase { vector<TaskChainInfo> chains; ExtraT extra; }; - std::unordered_map<ChainId, ChainInfo, Hash<ChainId>> chains_; - std::unordered_map<ChainId, TaskId, Hash<ChainId>> limited_tasks_; + FlatHashMap<ChainId, unique_ptr<ChainInfo>> chains_; + FlatHashMap<ChainId, TaskId> limited_tasks_; Container<Task> tasks_; VectorQueue<TaskId> pending_tasks_; + ChainInfo &get_chain_info(ChainId chain_id) { + auto &chain = chains_[chain_id]; + if (chain == nullptr) { + chain = make_unique<ChainInfo>(); + } + return *chain; + } + void try_start_task(TaskId task_id) { auto *task = tasks_.get(task_id); CHECK(task != nullptr); @@ -172,7 +179,7 @@ class ChainScheduler final : public ChainSchedulerBase { void do_start_task(TaskId task_id, Task *task) { for (TaskChainInfo &task_chain_info : task->chains) { - ChainInfo &chain_info = chains_[task_chain_info.chain_id]; + ChainInfo &chain_info = get_chain_info(task_chain_info.chain_id); chain_info.active_tasks++; task_chain_info.chain_node.generation = chain_info.generation; } @@ -255,14 +262,14 @@ class ChainScheduler final : public ChainSchedulerBase { }; template <class ExtraT> -typename ChainScheduler<ExtraT>::TaskId ChainScheduler<ExtraT>::create_task(Span<ChainScheduler::ChainId> chains, - ExtraT extra) { +typename ChainScheduler<ExtraT>::TaskId ChainScheduler<ExtraT>::create_task(Span<ChainId> chains, ExtraT extra) { auto task_id = tasks_.create(); Task &task = *tasks_.get(task_id); task.extra = std::move(extra); - task.chains = transform(chains, [&](auto chain_id) { + task.chains = transform(chains, [&](ChainId chain_id) { + CHECK(chain_id != 0); TaskChainInfo task_chain_info; - ChainInfo &chain_info = chains_[chain_id]; + ChainInfo &chain_info = get_chain_info(chain_id); task_chain_info.chain_id = chain_id; task_chain_info.chain_info = &chain_info; task_chain_info.chain_node.task_id = task_id; @@ -281,7 +288,7 @@ typename ChainScheduler<ExtraT>::TaskId ChainScheduler<ExtraT>::create_task(Span // TODO: return reference template <class ExtraT> -ExtraT *ChainScheduler<ExtraT>::get_task_extra(ChainScheduler::TaskId task_id) { // may return nullptr +ExtraT *ChainScheduler<ExtraT>::get_task_extra(TaskId task_id) { // may return nullptr auto *task = tasks_.get(task_id); if (task == nullptr) { return nullptr; @@ -310,7 +317,7 @@ optional<ChainSchedulerBase::TaskWithParents> ChainScheduler<ExtraT>::start_next } template <class ExtraT> -void ChainScheduler<ExtraT>::finish_task(ChainScheduler::TaskId task_id) { +void ChainScheduler<ExtraT>::finish_task(TaskId task_id) { auto *task = tasks_.get(task_id); CHECK(task != nullptr); CHECK(to_start_.empty()); @@ -328,7 +335,7 @@ void ChainScheduler<ExtraT>::finish_task(ChainScheduler::TaskId task_id) { } template <class ExtraT> -void ChainScheduler<ExtraT>::reset_task(ChainScheduler::TaskId task_id) { +void ChainScheduler<ExtraT>::reset_task(TaskId task_id) { CHECK(to_start_.empty()); auto *task = tasks_.get(task_id); CHECK(task != nullptr); @@ -351,15 +358,17 @@ StringBuilder &operator<<(StringBuilder &sb, ChainScheduler<ExtraT> &scheduler) // 1 print chains sb << '\n'; for (auto &it : scheduler.chains_) { + CHECK(it.second != nullptr); sb << "ChainId{" << it.first << "}"; - sb << " active_cnt = " << it.second.active_tasks; - sb << " g = " << it.second.generation; + sb << " active_cnt = " << it.second->active_tasks; + sb << " g = " << it.second->generation; sb << ':'; - it.second.chain.foreach( - [&](auto task_id, auto generation) { sb << ' ' << *scheduler.get_task_extra(task_id) << ':' << generation; }); + it.second->chain.foreach([&](typename ChainScheduler<ExtraT>::TaskId task_id, uint64 generation) { + sb << ' ' << *scheduler.get_task_extra(task_id) << ':' << generation; + }); sb << '\n'; } - scheduler.tasks_.for_each([&](auto id, auto &task) { + scheduler.tasks_.for_each([&](uint64, typename ChainScheduler<ExtraT>::Task &task) { sb << "Task: " << task.extra; sb << " state = " << static_cast<int>(task.state); for (auto &task_chain_info : task.chains) { diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/ConcurrentHashTable.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/ConcurrentHashTable.h index 86752ed599..0dfbbe34a5 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/ConcurrentHashTable.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/ConcurrentHashTable.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -113,7 +113,7 @@ class ConcurrentHashMap { } static std::string get_name() { - return "ConcurrrentHashMap"; + return "ConcurrentHashMap"; } static KeyT empty_key() { @@ -308,7 +308,6 @@ class ConcurrentHashMap { continue; } auto node_key = node.key.load(std::memory_order_relaxed); - //LOG(ERROR) << node_key << " " << node_key; auto ok = migrate_to_hash_map_->with_value( node_key, true, [&](auto &node_value) { node_value.store(old_value, std::memory_order_relaxed); }); LOG_CHECK(ok) << "Migration overflow"; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FileLog.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/FileLog.cpp index b89edcfa48..150a2906a5 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FileLog.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FileLog.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -98,7 +98,7 @@ void FileLog::do_append(int log_level, CSlice slice) { auto total_time = Time::now() - start_time; if (total_time >= 0.1 && log_level >= 1) { auto thread_id = get_thread_id(); - auto r_size = fd_.write(PSLICE() << "[ 1][t" << (0 <= thread_id && thread_id < 10 ? " " : "") << thread_id + auto r_size = fd_.write(PSLICE() << "[ 2][t" << (0 <= thread_id && thread_id < 10 ? " " : "") << thread_id << "] !!! Previous logging took " << total_time << " seconds !!!\n"); r_size.ignore(); } diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMap.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMap.h index aa3392831f..6ea919a476 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMap.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMap.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -17,7 +17,7 @@ namespace td { template <class KeyT, class ValueT, class HashT = Hash<KeyT>, class EqT = std::equal_to<KeyT>> -using FlatHashMap = FlatHashTable<MapNode<KeyT, ValueT>, HashT, EqT>; +using FlatHashMap = FlatHashTable<MapNode<KeyT, ValueT, EqT>, HashT, EqT>; //using FlatHashMap = FlatHashMapChunks<KeyT, ValueT, HashT, EqT>; //using FlatHashMap = std::unordered_map<KeyT, ValueT, HashT, EqT>; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMapChunks.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMapChunks.h index af43ebbae2..fcf9d89d60 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMapChunks.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashMapChunks.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -257,7 +257,7 @@ class FlatHashTableChunks { } Iterator find(const KeyT &key) { - if (empty() || is_hash_table_key_empty(key)) { + if (empty() || is_hash_table_key_empty<EqT>(key)) { return end(); } const auto hash = calc_hash(key); @@ -326,7 +326,7 @@ class FlatHashTableChunks { template <class... ArgsT> std::pair<Iterator, bool> emplace(KeyT key, ArgsT &&...args) { - CHECK(!is_hash_table_key_empty(key)); + CHECK(!is_hash_table_key_empty<EqT>(key)); auto it = find(key); if (it != end()) { return {it, false}; @@ -399,13 +399,16 @@ class FlatHashTableChunks { } template <class F> - void remove_if(F &&f) { + bool remove_if(F &&f) { + bool is_removed = false; for (auto it = nodes_.begin(), end = nodes_.end(); it != end; ++it) { if (!it->empty() && f(it->get_public())) { erase_node(it); + is_removed = true; } } try_shrink(); + return is_removed; } private: @@ -562,14 +565,14 @@ class FlatHashTableChunks { }; template <class KeyT, class ValueT, class HashT = Hash<KeyT>, class EqT = std::equal_to<KeyT>> -using FlatHashMapChunks = FlatHashTableChunks<MapNode<KeyT, ValueT>, HashT, EqT>; +using FlatHashMapChunks = FlatHashTableChunks<MapNode<KeyT, ValueT, EqT>, HashT, EqT>; template <class KeyT, class HashT = Hash<KeyT>, class EqT = std::equal_to<KeyT>> -using FlatHashSetChunks = FlatHashTableChunks<SetNode<KeyT>, HashT, EqT>; +using FlatHashSetChunks = FlatHashTableChunks<SetNode<KeyT, EqT>, HashT, EqT>; template <class NodeT, class HashT, class EqT, class FuncT> -void table_remove_if(FlatHashTableChunks<NodeT, HashT, EqT> &table, FuncT &&func) { - table.remove_if(func); +bool table_remove_if(FlatHashTableChunks<NodeT, HashT, EqT> &table, FuncT &&func) { + return table.remove_if(func); } } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashSet.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashSet.h index 80fe5137eb..ca4398fd5d 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashSet.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashSet.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -17,7 +17,7 @@ namespace td { template <class KeyT, class HashT = Hash<KeyT>, class EqT = std::equal_to<KeyT>> -using FlatHashSet = FlatHashTable<SetNode<KeyT>, HashT, EqT>; +using FlatHashSet = FlatHashTable<SetNode<KeyT, EqT>, HashT, EqT>; //using FlatHashSet = FlatHashSetChunks<KeyT, HashT, EqT>; //using FlatHashSet = std::unordered_set<KeyT, HashT, EqT>; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashTable.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashTable.h index da12cf98e8..cd7e7509ae 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashTable.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FlatHashTable.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -308,7 +308,7 @@ class FlatHashTable { template <class... ArgsT> std::pair<NodePointer, bool> emplace(KeyT key, ArgsT &&...args) { - CHECK(!is_hash_table_key_empty(key)); + CHECK(!is_hash_table_key_empty<EqT>(key)); if (unlikely(bucket_count_mask_ == 0)) { CHECK(used_node_count_ == 0); resize(8); @@ -385,9 +385,9 @@ class FlatHashTable { } template <class F> - void remove_if(F &&f) { + bool remove_if(F &&f) { if (empty()) { - return; + return false; } auto it = begin_impl(); @@ -401,9 +401,11 @@ class FlatHashTable { } while (!it->empty()); } auto first_empty = it; + bool is_removed = false; while (it != end) { if (!it->empty() && f(it->get_public())) { erase_node(it); + is_removed = true; } else { ++it; } @@ -411,11 +413,13 @@ class FlatHashTable { for (it = nodes_; it != first_empty;) { if (!it->empty() && f(it->get_public())) { erase_node(it); + is_removed = true; } else { ++it; } } try_shrink(); + return is_removed; } private: @@ -447,7 +451,7 @@ class FlatHashTable { } NodeT *find_impl(const KeyT &key) { - if (unlikely(nodes_ == nullptr) || is_hash_table_key_empty(key)) { + if (unlikely(nodes_ == nullptr) || is_hash_table_key_empty<EqT>(key)) { return nullptr; } auto bucket = calc_bucket(key); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/FloodControlStrict.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/FloodControlStrict.h index e21688717f..ba5be8272f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/FloodControlStrict.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/FloodControlStrict.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -12,7 +12,7 @@ namespace td { -// More strict implementaions of flood control than FloodControlFast. +// More strict implementations of flood control than FloodControlFast. // Should be just fine for small counters. class FloodControlStrict { public: diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.cpp index d837b7ae26..d4ad3c51f8 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -35,12 +35,11 @@ bool GzipByteFlow::loop() { auto r_state = gzip_.run(); auto output_size = gzip_.flush_output(); if (output_size) { - uncommitted_size_ += output_size; - total_output_size_ += output_size; - if (total_output_size_ > max_output_size_) { + if (output_size > max_output_size_ || total_output_size_ > max_output_size_ - output_size) { finish(Status::Error("Max output size limit exceeded")); return false; } + total_output_size_ += output_size; output_.confirm_append(output_size); } diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.h index 77ea62855d..c6611bec3e 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/GzipByteFlow.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -38,7 +38,6 @@ class GzipByteFlow final : public ByteFlowBase { private: Gzip gzip_; - size_t uncommitted_size_ = 0; size_t total_output_size_ = 0; size_t max_output_size_ = std::numeric_limits<size_t>::max(); }; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/Hash.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/Hash.h index 58c10a73ba..969773018f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/Hash.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/Hash.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -15,7 +15,7 @@ #include <utility> namespace td { -// A simple wrapper for absl::flat_hash_map, std::unordered_map and probably some our implementaion of hash map in +// A simple wrapper for absl::flat_hash_map, std::unordered_map and probably some our implementation of hash map in // the future // We will introduce out own Hashing utility like an absl one. diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/HashTableUtils.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/HashTableUtils.h index 8e11f9840f..21d4104daf 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/HashTableUtils.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/HashTableUtils.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -13,9 +13,9 @@ namespace td { -template <class KeyT> +template <class EqT, class KeyT> bool is_hash_table_key_empty(const KeyT &key) { - return key == KeyT(); + return EqT()(key, KeyT()); } inline uint32 randomize_hash(uint32 h) { @@ -69,4 +69,8 @@ inline uint32 Hash<string>::operator()(const string &value) const { return static_cast<uint32>(std::hash<string>()(value)); } +inline uint32 combine_hashes(uint32 first_hash, uint32 second_hash) { + return first_hash * 2023654985u + second_hash; +} + } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/Hints.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/Hints.cpp index e6ddc69e37..4ef7865aa7 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/Hints.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/Hints.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -115,7 +115,7 @@ void Hints::add_search_results(vector<KeyT> &results, const string &word, LOG(DEBUG) << "Search for word " << word; auto it = word_to_keys.lower_bound(word); while (it != word_to_keys.end() && begins_with(it->first, word)) { - results.insert(results.end(), it->second.begin(), it->second.end()); + append(results, it->second); ++it; } } diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.cpp new file mode 100644 index 0000000000..da290ae3a7 --- /dev/null +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.cpp @@ -0,0 +1,92 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/utils/HttpDate.h" + +#include "td/utils/misc.h" +#include "td/utils/Parser.h" +#include "td/utils/Slice.h" + +namespace td { + +Result<int32> HttpDate::to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second) { + if (year < 1970 || year > 2037) { + return Status::Error("Invalid year"); + } + if (month < 1 || month > 12) { + return Status::Error("Invalid month"); + } + if (day < 1 || day > days_in_month(year, month)) { + return Status::Error("Invalid day"); + } + if (hour < 0 || hour >= 24) { + return Status::Error("Invalid hour"); + } + if (minute < 0 || minute >= 60) { + return Status::Error("Invalid minute"); + } + if (second < 0 || second > 60) { + return Status::Error("Invalid second"); + } + + int32 res = 0; + for (int32 y = 1970; y < year; y++) { + res += (is_leap(y) + 365) * seconds_in_day(); + } + for (int32 m = 1; m < month; m++) { + res += days_in_month(year, m) * seconds_in_day(); + } + res += (day - 1) * seconds_in_day(); + res += hour * 60 * 60; + res += minute * 60; + res += second; + return res; +} + +Result<int32> HttpDate::parse_http_date(string slice) { + Parser p(slice); + p.read_till(','); // ignore week day + p.skip(','); + p.skip_whitespaces(); + p.skip_nofail('0'); + TRY_RESULT(day, to_integer_safe<int32>(p.read_word())); + auto month_name = p.read_word(); + to_lower_inplace(month_name); + TRY_RESULT(year, to_integer_safe<int32>(p.read_word())); + p.skip_whitespaces(); + p.skip_nofail('0'); + TRY_RESULT(hour, to_integer_safe<int32>(p.read_till(':'))); + p.skip(':'); + p.skip_nofail('0'); + TRY_RESULT(minute, to_integer_safe<int32>(p.read_till(':'))); + p.skip(':'); + p.skip_nofail('0'); + TRY_RESULT(second, to_integer_safe<int32>(p.read_word())); + auto gmt = p.read_word(); + TRY_STATUS(std::move(p.status())); + if (gmt != "GMT") { + return Status::Error("Timezone must be GMT"); + } + + static Slice month_names[12] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; + + int month = 0; + + for (int m = 1; m <= 12; m++) { + if (month_names[m - 1] == month_name) { + month = m; + break; + } + } + + if (month == 0) { + return Status::Error("Unknown month name"); + } + + return to_unix_time(year, month, day, hour, minute, second); +} + +} // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.h new file mode 100644 index 0000000000..a2daf0784f --- /dev/null +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/HttpDate.h @@ -0,0 +1,34 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 +// +// 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) +// +#pragma once + +#include "td/utils/common.h" +#include "td/utils/Status.h" + +namespace td { + +class HttpDate { + static bool is_leap(int32 year) { + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); + } + + static int32 seconds_in_day() { + return 24 * 60 * 60; + } + + public: + static int32 days_in_month(int32 year, int32 month) { + static int cnt[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + return cnt[month - 1] + (month == 2 && is_leap(year)); + } + + static Result<int32> to_unix_time(int32 year, int32 month, int32 day, int32 hour, int32 minute, int32 second); + + static Result<int32> parse_http_date(string slice); +}; + +} // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.cpp index ad721f497c..a0aebb61c3 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -9,8 +9,7 @@ #include "td/utils/misc.h" #include "td/utils/ScopeGuard.h" #include "td/utils/SliceBuilder.h" - -#include <cstring> +#include "td/utils/utf8.h" namespace td { @@ -140,44 +139,26 @@ Result<MutableSlice> json_string_decode(Parser &parser) { if (!parser.try_skip('"')) { return Status::Error("Opening '\"' expected"); } - auto *cur_src = parser.data().data(); - auto *end_src = parser.data().end(); - auto *end = cur_src; - while (end < end_src && end[0] != '"') { - if (end[0] == '\\') { - end++; - } - end++; - } - if (end >= end_src) { - return Status::Error("Closing '\"' not found"); - } - parser.advance(end + 1 - cur_src); - end_src = end; - - auto *cur_dest = cur_src; - auto *begin_dest = cur_src; - - while (cur_src != end_src) { - auto *slash = static_cast<char *>(std::memchr(cur_src, '\\', end_src - cur_src)); - if (slash == nullptr) { - slash = end_src; + auto data = parser.data(); + auto *result_start = data.ubegin(); + auto *cur_src = result_start; + auto *cur_dest = result_start; + auto *end = data.uend(); + + while (true) { + if (cur_src == end) { + return Status::Error("Closing '\"' not found"); + } + if (*cur_src == '"') { + parser.advance(cur_src + 1 - result_start); + return data.substr(0, cur_dest - result_start); } - std::memmove(cur_dest, cur_src, slash - cur_src); - cur_dest += slash - cur_src; - cur_src = slash; - if (cur_src != end_src) { + if (*cur_src == '\\') { cur_src++; - if (cur_src == end_src) { - // TODO UNREACHABLE(); - return Status::Error("Unexpected end of string"); + if (cur_src == end) { + return Status::Error("Closing '\"' not found"); } switch (*cur_src) { - case '"': - case '\\': - case '/': - *cur_dest++ = *cur_src++; - break; case 'b': *cur_dest++ = '\b'; cur_src++; @@ -200,10 +181,10 @@ Result<MutableSlice> json_string_decode(Parser &parser) { break; case 'u': { cur_src++; - if (cur_src + 4 > end_src) { + if (cur_src + 4 > end) { return Status::Error("\\u has less than 4 symbols"); } - int num = 0; + uint32 num = 0; for (int i = 0; i < 4; i++, cur_src++) { int d = hex_to_int(*cur_src); if (d == 16) { @@ -212,7 +193,7 @@ Result<MutableSlice> json_string_decode(Parser &parser) { num = num * 16 + d; } if (0xD7FF < num && num < 0xE000) { - if (cur_src + 6 <= end_src && cur_src[0] == '\\' && cur_src[1] == 'u') { + if (cur_src + 6 <= end && cur_src[0] == '\\' && cur_src[1] == 'u') { cur_src += 2; int new_num = 0; for (int i = 0; i < 4; i++, cur_src++) { @@ -230,76 +211,46 @@ Result<MutableSlice> json_string_decode(Parser &parser) { } } - if (num < 128) { - *cur_dest++ = static_cast<char>(num); - } else if (num < 0x800) { - *cur_dest++ = static_cast<char>(0xc0 + (num >> 6)); - *cur_dest++ = static_cast<char>(0x80 + (num & 63)); - } else if (num <= 0xffff) { - *cur_dest++ = static_cast<char>(0xe0 + (num >> 12)); - *cur_dest++ = static_cast<char>(0x80 + ((num >> 6) & 63)); - *cur_dest++ = static_cast<char>(0x80 + (num & 63)); - } else { - *cur_dest++ = static_cast<char>(0xf0 + (num >> 18)); - *cur_dest++ = static_cast<char>(0x80 + ((num >> 12) & 63)); - *cur_dest++ = static_cast<char>(0x80 + ((num >> 6) & 63)); - *cur_dest++ = static_cast<char>(0x80 + (num & 63)); - } + cur_dest = append_utf8_character_unsafe(cur_dest, num); break; } + default: + *cur_dest++ = *cur_src++; + break; } + } else { + *cur_dest++ = *cur_src++; } } - CHECK(cur_dest <= end_src); - return MutableSlice(begin_dest, cur_dest); + UNREACHABLE(); + return {}; } Status json_string_skip(Parser &parser) { if (!parser.try_skip('"')) { return Status::Error("Opening '\"' expected"); } - auto *begin_src = parser.data().data(); - auto *cur_src = begin_src; - auto *end_src = parser.data().end(); - auto *end = cur_src; - while (end < end_src && *end != '"') { - if (*end == '\\') { - end++; - } - end++; - } - if (end >= end_src) { - return Status::Error("Closing '\"' not found"); - } - parser.advance(end + 1 - cur_src); - end_src = end; + auto data = parser.data(); + auto *cur_src = data.ubegin(); + auto *end = data.uend(); - while (cur_src != end_src) { - auto *slash = static_cast<char *>(std::memchr(cur_src, '\\', end_src - cur_src)); - if (slash == nullptr) { - slash = end_src; + while (true) { + if (cur_src == end) { + return Status::Error("Closing '\"' not found"); + } + if (*cur_src == '"') { + parser.advance(cur_src + 1 - data.ubegin()); + return Status::OK(); } - cur_src = slash; - if (cur_src != end_src) { + if (*cur_src == '\\') { cur_src++; - if (cur_src == end_src) { - // TODO UNREACHABLE(); - return Status::Error("Unexpected end of string"); + if (cur_src == end) { + return Status::Error("Closing '\"' not found"); } switch (*cur_src) { - case '"': - case '\\': - case '/': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - cur_src++; - break; case 'u': { cur_src++; - if (cur_src + 4 > end_src) { + if (cur_src + 4 > end) { return Status::Error("\\u has less than 4 symbols"); } int num = 0; @@ -311,7 +262,7 @@ Status json_string_skip(Parser &parser) { num = num * 16 + d; } if (0xD7FF < num && num < 0xE000) { - if (cur_src + 6 <= end_src && cur_src[0] == '\\' && cur_src[1] == 'u') { + if (cur_src + 6 <= end && cur_src[0] == '\\' && cur_src[1] == 'u') { cur_src += 2; int new_num = 0; for (int i = 0; i < 4; i++, cur_src++) { @@ -330,9 +281,15 @@ Status json_string_skip(Parser &parser) { } break; } + default: + cur_src++; + break; } + } else { + cur_src++; } } + UNREACHABLE(); return Status::OK(); } @@ -365,7 +322,7 @@ Result<JsonValue> do_json_decode(Parser &parser, int32 max_depth) { case '[': { parser.skip('['); parser.skip_whitespaces(); - std::vector<JsonValue> res; + vector<JsonValue> res; if (parser.try_skip(']')) { return JsonValue::create_array(std::move(res)); } @@ -394,21 +351,21 @@ Result<JsonValue> do_json_decode(Parser &parser, int32 max_depth) { case '{': { parser.skip('{'); parser.skip_whitespaces(); - std::vector<std::pair<MutableSlice, JsonValue>> res; if (parser.try_skip('}')) { - return JsonValue::make_object(std::move(res)); + return JsonValue::make_object(JsonObject()); } + vector<std::pair<Slice, JsonValue>> field_values; while (true) { if (parser.empty()) { return Status::Error("Unexpected string end"); } - TRY_RESULT(key, json_string_decode(parser)); + TRY_RESULT(field, json_string_decode(parser)); parser.skip_whitespaces(); if (!parser.try_skip(':')) { return Status::Error("':' expected"); } TRY_RESULT(value, do_json_decode(parser, max_depth - 1)); - res.emplace_back(key, std::move(value)); + field_values.emplace_back(field, std::move(value)); parser.skip_whitespaces(); if (parser.try_skip('}')) { @@ -423,7 +380,7 @@ Result<JsonValue> do_json_decode(Parser &parser, int32 max_depth) { } return Status::Error("Unexpected symbol while parsing JSON Object"); } - return JsonValue::make_object(std::move(res)); + return JsonValue::make_object(JsonObject(std::move(field_values))); } case '-': case '+': @@ -585,26 +542,38 @@ Slice JsonValue::get_type_name(Type type) { } } -bool has_json_object_field(const JsonObject &object, Slice name) { - for (auto &field_value : object) { +JsonObject::JsonObject(vector<std::pair<Slice, JsonValue>> &&field_values) : field_values_(std::move(field_values)) { +} + +size_t JsonObject::field_count() const { + return field_values_.size(); +} + +JsonValue JsonObject::extract_field(Slice name) { + for (auto &field_value : field_values_) { if (field_value.first == name) { - return true; + return std::move(field_value.second); } } - return false; + return JsonValue(); } -JsonValue get_json_object_field_force(JsonObject &object, Slice name) { - for (auto &field_value : object) { +Result<JsonValue> JsonObject::extract_optional_field(Slice name, JsonValueType type) { + for (auto &field_value : field_values_) { if (field_value.first == name) { + if (type != JsonValue::Type::Null && field_value.second.type() != type) { + return Status::Error(400, PSLICE() + << "Field \"" << name << "\" must be of type " << JsonValue::get_type_name(type)); + } + return std::move(field_value.second); } } return JsonValue(); } -Result<JsonValue> get_json_object_field(JsonObject &object, Slice name, JsonValue::Type type, bool is_optional) { - for (auto &field_value : object) { +Result<JsonValue> JsonObject::extract_required_field(Slice name, JsonValueType type) { + for (auto &field_value : field_values_) { if (field_value.first == name) { if (type != JsonValue::Type::Null && field_value.second.type() != type) { return Status::Error(400, PSLICE() @@ -614,83 +583,163 @@ Result<JsonValue> get_json_object_field(JsonObject &object, Slice name, JsonValu return std::move(field_value.second); } } - if (!is_optional) { - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); + return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); +} + +const JsonValue *JsonObject::get_field(Slice name) const { + for (auto &field_value : field_values_) { + if (field_value.first == name) { + return &field_value.second; + } } - return JsonValue(); + return nullptr; +} + +bool JsonObject::has_field(Slice name) const { + return get_field(name) != nullptr; } -Result<bool> get_json_object_bool_field(JsonObject &object, Slice name, bool is_optional, bool default_value) { - TRY_RESULT(value, get_json_object_field(object, name, JsonValue::Type::Boolean, is_optional)); - if (value.type() == JsonValue::Type::Null) { - return default_value; +Result<bool> JsonObject::get_optional_bool_field(Slice name, bool default_value) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::Boolean) { + return value->get_boolean(); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Boolean"); } - return value.get_boolean(); + return default_value; } -Result<int32> get_json_object_int_field(JsonObject &object, Slice name, bool is_optional, int32 default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return to_integer_safe<int32>(field_value.second.get_string()); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return to_integer_safe<int32>(field_value.second.get_number()); - } +Result<bool> JsonObject::get_required_bool_field(Slice name) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::Boolean) { + return value->get_boolean(); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Boolean"); + } + return Status::Error(400, PSLICE() << "Can't find field \"" << name << '"'); +} + +template <class T> +static Result<T> get_integer_field(Slice name, Slice value) { + auto r_int = to_integer_safe<T>(value); + if (r_int.is_ok()) { + return r_int.ok(); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a valid Number"); +} - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Number"); +Result<int32> JsonObject::get_optional_int_field(Slice name, int32 default_value) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return get_integer_field<int32>(name, value->get_string()); + } + if (value->type() == JsonValue::Type::Number) { + return get_integer_field<int32>(name, value->get_number()); } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); } - if (is_optional) { - return default_value; + return default_value; +} + +Result<int32> JsonObject::get_required_int_field(Slice name) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return get_integer_field<int32>(name, value->get_string()); + } + if (value->type() == JsonValue::Type::Number) { + return get_integer_field<int32>(name, value->get_number()); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); + return Status::Error(400, PSLICE() << "Can't find field \"" << name << '"'); } -Result<int64> get_json_object_long_field(JsonObject &object, Slice name, bool is_optional, int64 default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return to_integer_safe<int64>(field_value.second.get_string()); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return to_integer_safe<int64>(field_value.second.get_number()); - } +Result<int64> JsonObject::get_optional_long_field(Slice name, int64 default_value) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return get_integer_field<int64>(name, value->get_string()); + } + if (value->type() == JsonValue::Type::Number) { + return get_integer_field<int64>(name, value->get_number()); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); + } + return default_value; +} - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); +Result<int64> JsonObject::get_required_long_field(Slice name) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return get_integer_field<int64>(name, value->get_string()); + } + if (value->type() == JsonValue::Type::Number) { + return get_integer_field<int64>(name, value->get_number()); } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be a Number"); } - if (is_optional) { - return default_value; + return Status::Error(400, PSLICE() << "Can't find field \"" << name << '"'); +} + +Result<double> JsonObject::get_optional_double_field(Slice name, double default_value) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::Number) { + return to_double(value->get_number()); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Number"); } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); + return default_value; } -Result<double> get_json_object_double_field(JsonObject &object, Slice name, bool is_optional, double default_value) { - TRY_RESULT(value, get_json_object_field(object, name, JsonValue::Type::Number, is_optional)); - if (value.type() == JsonValue::Type::Null) { - return default_value; +Result<double> JsonObject::get_required_double_field(Slice name) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::Number) { + return to_double(value->get_number()); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type Number"); } - return to_double(value.get_number()); + return Status::Error(400, PSLICE() << "Can't find field \"" << name << '"'); } -Result<string> get_json_object_string_field(JsonObject &object, Slice name, bool is_optional, string default_value) { - for (auto &field_value : object) { - if (field_value.first == name) { - if (field_value.second.type() == JsonValue::Type::String) { - return field_value.second.get_string().str(); - } - if (field_value.second.type() == JsonValue::Type::Number) { - return field_value.second.get_number().str(); - } +Result<string> JsonObject::get_optional_string_field(Slice name, string default_value) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return value->get_string().str(); + } + if (value->type() == JsonValue::Type::Number) { + return value->get_number().str(); + } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type String"); + } + return std::move(default_value); +} - return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type String"); +Result<string> JsonObject::get_required_string_field(Slice name) const { + auto value = get_field(name); + if (value != nullptr) { + if (value->type() == JsonValue::Type::String) { + return value->get_string().str(); + } + if (value->type() == JsonValue::Type::Number) { + return value->get_number().str(); } + return Status::Error(400, PSLICE() << "Field \"" << name << "\" must be of type String"); } - if (is_optional) { - return default_value; + return Status::Error(400, PSLICE() << "Can't find field \"" << name << '"'); +} + +void JsonObject::foreach(const std::function<void(Slice name, const JsonValue &value)> &callback) const { + for (auto &field_value : field_values_) { + callback(field_value.first, field_value.second); } - return Status::Error(400, PSLICE() << "Can't find field \"" << name << "\""); } } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.h index 053f4a0266..3989cf76e7 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/JsonBuilder.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -14,6 +14,7 @@ #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" +#include <functional> #include <new> #include <type_traits> #include <utility> @@ -401,7 +402,7 @@ class JsonObjectScope final : public JsonScope { *sb_ << "}"; } template <class T> - JsonObjectScope &operator()(Slice key, T &&value) { + JsonObjectScope &operator()(Slice field, T &&value) { CHECK(is_active()); if (is_first_) { *sb_ << ","; @@ -409,7 +410,7 @@ class JsonObjectScope final : public JsonScope { is_first_ = true; } jb_->print_offset(); - jb_->enter_value() << key; + jb_->enter_value() << field; if (jb_->is_pretty()) { *sb_ << " : "; } else { @@ -418,10 +419,10 @@ class JsonObjectScope final : public JsonScope { jb_->enter_value() << value; return *this; } - JsonObjectScope &operator<<(const JsonRaw &key_value) { + JsonObjectScope &operator<<(const JsonRaw &field_value) { CHECK(is_active()); is_first_ = true; - jb_->enter_value() << key_value; + jb_->enter_value() << field_value; return *this; } @@ -451,12 +452,62 @@ inline JsonArrayScope JsonBuilder::enter_array() { class JsonValue; -using JsonObject = vector<std::pair<MutableSlice, JsonValue>>; +enum class JsonValueType { Null, Number, Boolean, String, Array, Object }; + using JsonArray = vector<JsonValue>; +class JsonObject { + const JsonValue *get_field(Slice name) const; + + public: + vector<std::pair<Slice, JsonValue>> field_values_; + + JsonObject() = default; + + explicit JsonObject(vector<std::pair<Slice, JsonValue>> &&field_values); + + JsonObject(const JsonObject &) = delete; + JsonObject &operator=(const JsonObject &) = delete; + JsonObject(JsonObject &&) = default; + JsonObject &operator=(JsonObject &&) = default; + ~JsonObject() = default; + + size_t field_count() const; + + JsonValue extract_field(Slice name); + + Result<JsonValue> extract_optional_field(Slice name, JsonValueType type); + + Result<JsonValue> extract_required_field(Slice name, JsonValueType type); + + bool has_field(Slice name) const; + + Result<bool> get_optional_bool_field(Slice name, bool default_value = false) const; + + Result<bool> get_required_bool_field(Slice name) const; + + Result<int32> get_optional_int_field(Slice name, int32 default_value = 0) const; + + Result<int32> get_required_int_field(Slice name) const; + + Result<int64> get_optional_long_field(Slice name, int64 default_value = 0) const; + + Result<int64> get_required_long_field(Slice name) const; + + Result<double> get_optional_double_field(Slice name, double default_value = 0.0) const; + + Result<double> get_required_double_field(Slice name) const; + + Result<string> get_optional_string_field(Slice name, string default_value = string()) const; + + Result<string> get_required_string_field(Slice name) const; + + void foreach(const std::function<void(Slice name, const JsonValue &value)> &callback) const; +}; + class JsonValue final : private Jsonable { public: - enum class Type { Null, Number, Boolean, String, Array, Object }; + using Type = JsonValueType; static Slice get_type_name(Type type); @@ -584,8 +635,8 @@ class JsonValue final : private Jsonable { } case Type::Object: { auto object = scope->enter_object(); - for (auto &key_value : get_object()) { - object(key_value.first, key_value.second); + for (auto &field_value : get_object().field_values_) { + object(field_value.first, field_value.second); } break; } @@ -664,7 +715,7 @@ class JsonValue final : private Jsonable { array_.~vector<JsonValue>(); break; case Type::Object: - object_.~vector<std::pair<MutableSlice, JsonValue>>(); + object_.~JsonObject(); break; } type_ = Type::Null; @@ -841,26 +892,4 @@ auto json_array(const A &a, F &&f) { }); } -bool has_json_object_field(const JsonObject &object, Slice name); - -JsonValue get_json_object_field_force(JsonObject &object, Slice name) TD_WARN_UNUSED_RESULT; - -Result<JsonValue> get_json_object_field(JsonObject &object, Slice name, JsonValue::Type type, - bool is_optional = true) TD_WARN_UNUSED_RESULT; - -Result<bool> get_json_object_bool_field(JsonObject &object, Slice name, bool is_optional = true, - bool default_value = false) TD_WARN_UNUSED_RESULT; - -Result<int32> get_json_object_int_field(JsonObject &object, Slice name, bool is_optional = true, - int32 default_value = 0) TD_WARN_UNUSED_RESULT; - -Result<int64> get_json_object_long_field(JsonObject &object, Slice name, bool is_optional = true, - int64 default_value = 0) TD_WARN_UNUSED_RESULT; - -Result<double> get_json_object_double_field(JsonObject &object, Slice name, bool is_optional = true, - double default_value = 0.0) TD_WARN_UNUSED_RESULT; - -Result<string> get_json_object_string_field(JsonObject &object, Slice name, bool is_optional = true, - string default_value = "") TD_WARN_UNUSED_RESULT; - } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/MapNode.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/MapNode.h index b6c65c812c..9d87aad829 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/MapNode.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/MapNode.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -15,7 +15,7 @@ namespace td { -template <class KeyT, class ValueT, class Enable = void> +template <class KeyT, class ValueT, class EqT, class Enable = void> struct MapNode { using first_type = KeyT; using second_type = ValueT; @@ -72,7 +72,7 @@ struct MapNode { } bool empty() const { - return is_hash_table_key_empty(first); + return is_hash_table_key_empty<EqT>(first); } void clear() { @@ -91,8 +91,8 @@ struct MapNode { } }; -template <class KeyT, class ValueT> -struct MapNode<KeyT, ValueT, typename std::enable_if_t<(sizeof(KeyT) + sizeof(ValueT) > 28 * sizeof(void *))>> { +template <class KeyT, class ValueT, class EqT> +struct MapNode<KeyT, ValueT, EqT, typename std::enable_if_t<(sizeof(KeyT) + sizeof(ValueT) > 28 * sizeof(void *))>> { struct Impl { using first_type = KeyT; using second_type = ValueT; @@ -105,7 +105,7 @@ struct MapNode<KeyT, ValueT, typename std::enable_if_t<(sizeof(KeyT) + sizeof(Va template <class InputKeyT, class... ArgsT> Impl(InputKeyT &&key, ArgsT &&...args) : first(std::forward<InputKeyT>(key)) { new (&second) ValueT(std::forward<ArgsT>(args)...); - DCHECK(!is_hash_table_key_empty(first)); + DCHECK(!is_hash_table_key_empty<EqT>(first)); } Impl(const Impl &) = delete; Impl &operator=(const Impl &) = delete; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/MpmcQueue.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/MpmcQueue.h index a6d1bef7f1..1a08768dd6 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/MpmcQueue.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/MpmcQueue.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -324,7 +324,7 @@ class MpmcQueueOld { char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic<Node *>)]; size_t block_size_; HazardPointers<Node, 1> hazard_pointers_; - // HazardPointers is already padded + // HazardPointers class is already padded }; template <class T> @@ -454,7 +454,7 @@ class MpmcQueue { std::atomic<Node *> read_pos_{nullptr}; char pad2[TD_CONCURRENCY_PAD - sizeof(std::atomic<Node *>)]; HazardPointers<Node, 1> hazard_pointers_; - // HazardPointers is already padded + // HazardPointers class is already padded }; } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/ObjectPool.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/ObjectPool.h index 8f6f4c28ed..2d08d28344 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/ObjectPool.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/ObjectPool.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -14,7 +14,7 @@ #include <utility> namespace td { -// It is draft object pool implementaion +// It is draft object pool implementation // // Compared with std::shared_ptr: // + WeakPtr are much faster. Just pointer copy. No barriers, no atomics. diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/Promise.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/Promise.h index 247593742c..ce4365d2a4 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/Promise.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/Promise.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -116,7 +116,7 @@ class LambdaPromise : public PromiseInterface<ValueT> { } template <class FromT> - explicit LambdaPromise(FromT &&func) : func_(std::forward<FromT>(func)), state_(State::Ready) { + LambdaPromise(FromT &&func) : func_(std::forward<FromT>(func)), state_(State::Ready) { } private: diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/SetNode.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/SetNode.h index cbc218329c..a637a8366f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/SetNode.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/SetNode.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -14,7 +14,7 @@ namespace td { -template <class KeyT, class Enable = void> +template <class KeyT, class EqT, class Enable = void> struct SetNode { using public_key_type = KeyT; using public_type = const KeyT; @@ -54,7 +54,7 @@ struct SetNode { } bool empty() const { - return is_hash_table_key_empty(first); + return is_hash_table_key_empty<EqT>(first); } void clear() { @@ -67,8 +67,8 @@ struct SetNode { } }; -template <class KeyT> -struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void *))>> { +template <class KeyT, class EqT> +struct SetNode<KeyT, EqT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void *))>> { struct Impl { using second_type = KeyT; @@ -76,7 +76,7 @@ struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void template <class InputKeyT> explicit Impl(InputKeyT &&key) : first(std::forward<InputKeyT>(key)) { - DCHECK(!is_hash_table_key_empty(first)); + DCHECK(!is_hash_table_key_empty<EqT>(first)); } Impl(const Impl &) = delete; Impl &operator=(const Impl &) = delete; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.cpp index 941394e191..aa39c6284e 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -8,7 +8,6 @@ #include "td/utils/misc.h" #include "td/utils/port/thread_local.h" -#include "td/utils/Slice.h" #include <cstdio> #include <cstring> @@ -51,6 +50,23 @@ StringBuilder &StringBuilder::operator<<(Slice slice) { return *this; } +void StringBuilder::append_char(size_t count, char c) { + if (unlikely(!reserve(count))) { + if (end_ptr_ < current_ptr_) { + on_error(); + return; + } + auto available_size = static_cast<size_t>(end_ptr_ + RESERVED_SIZE - 1 - current_ptr_); + if (count > available_size) { + error_flag_ = true; + count = available_size; + } + } + + MutableSlice(current_ptr_, count).fill(c); + current_ptr_ += count; +} + template <class T> static char *print_uint(char *current_ptr, T x) { if (x < 100) { diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.h index 2339ef71cb..9251ba2e85 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/StringBuilder.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -13,12 +13,14 @@ #include <cstdlib> #include <memory> #include <type_traits> +#include <utility> namespace td { class StringBuilder { public: explicit StringBuilder(MutableSlice slice, bool use_buffer = false); + StringBuilder() : StringBuilder({}, true) { } @@ -42,6 +44,8 @@ class StringBuilder { *current_ptr_++ = c; } + void append_char(size_t count, char c); + MutableCSlice as_cslice() { if (current_ptr_ >= end_ptr_ + RESERVED_SIZE) { std::abort(); // shouldn't happen @@ -126,6 +130,36 @@ class StringBuilder { StringBuilder &operator<<(const void *ptr); + template <class A, class B> + StringBuilder &operator<<(const std::pair<A, B> &p) { + return *this << '[' << p.first << ';' << p.second << ']'; + } + + template <class T> + StringBuilder &operator<<(const vector<T> &v) { + *this << '{'; + if (!v.empty()) { + *this << v[0]; + size_t len = v.size(); + for (size_t i = 1; i < len; i++) { + *this << ", " << v[i]; + } + } + return *this << '}'; + } + + StringBuilder &operator<<(const vector<bool> &v) { + *this << '{'; + if (!v.empty()) { + *this << v[0]; + size_t len = v.size(); + for (size_t i = 1; i < len; i++) { + *this << ", " << static_cast<bool>(v[i]); + } + } + return *this << '}'; + } + private: char *begin_ptr_; char *current_ptr_; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/TlStorerToString.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/TlStorerToString.h index 7b4873132d..cb144fe1ee 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/TlStorerToString.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/TlStorerToString.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -9,171 +9,137 @@ #include "td/utils/common.h" #include "td/utils/SharedSlice.h" #include "td/utils/Slice.h" -#include "td/utils/SliceBuilder.h" +#include "td/utils/StackAllocator.h" +#include "td/utils/StringBuilder.h" #include "td/utils/UInt.h" namespace td { class TlStorerToString { - string result; - size_t shift = 0; - - void store_field_begin(const char *name) { - result.append(shift, ' '); - if (name && name[0]) { - result += name; - result += " = "; + decltype(StackAllocator::alloc(0)) buffer_ = StackAllocator::alloc(1 << 14); + StringBuilder sb_ = StringBuilder(buffer_.as_slice(), true); + size_t shift_ = 0; + + void store_field_begin(Slice name) { + sb_.append_char(shift_, ' '); + if (!name.empty()) { + sb_ << name << " = "; } } void store_field_end() { - result += '\n'; - } - - void store_long(int64 value) { - result += (PSLICE() << value).c_str(); + sb_.push_back('\n'); } void store_binary(Slice data) { static const char *hex = "0123456789ABCDEF"; - result.append("{ ", 2); + sb_ << "{ "; for (auto c : data) { unsigned char byte = c; - result += hex[byte >> 4]; - result += hex[byte & 15]; - result += ' '; + sb_.push_back(hex[byte >> 4]); + sb_.push_back(hex[byte & 15]); + sb_.push_back(' '); } - result += '}'; + sb_.push_back('}'); } public: TlStorerToString() = default; TlStorerToString(const TlStorerToString &) = delete; TlStorerToString &operator=(const TlStorerToString &) = delete; + TlStorerToString(TlStorerToString &&) = delete; + TlStorerToString &operator=(TlStorerToString &&) = delete; - void store_field(const char *name, bool value) { + void store_field(Slice name, const string &value) { store_field_begin(name); - result += (value ? "true" : "false"); + sb_.push_back('"'); + sb_ << value; + sb_.push_back('"'); store_field_end(); } - void store_field(const char *name, int32 value) { - store_field(name, static_cast<int64>(value)); - } - - void store_field(const char *name, int64 value) { + void store_field(Slice name, const SecureString &value) { store_field_begin(name); - store_long(value); - store_field_end(); - } - - void store_field(const char *name, double value) { - store_field_begin(name); - result += (PSLICE() << value).c_str(); - store_field_end(); - } - - void store_field(const char *name, const char *value) { - store_field_begin(name); - result += value; - store_field_end(); - } - - void store_field(const char *name, const string &value) { - store_field_begin(name); - result += '"'; - result += value; - result += '"'; - store_field_end(); - } - - void store_field(const char *name, const SecureString &value) { - store_field_begin(name); - result.append("<secret>"); + sb_ << "<secret>"; store_field_end(); } template <class T> - void store_field(const char *name, const T &value) { + void store_field(Slice name, const T &value) { store_field_begin(name); - result.append(value.data(), value.size()); + sb_ << value; store_field_end(); } - void store_bytes_field(const char *name, const SecureString &value) { + void store_bytes_field(Slice name, const SecureString &value) { store_field_begin(name); - result.append("<secret>"); + sb_ << "<secret>"; store_field_end(); } template <class BytesT> - void store_bytes_field(const char *name, const BytesT &value) { + void store_bytes_field(Slice name, const BytesT &value) { static const char *hex = "0123456789ABCDEF"; store_field_begin(name); - result.append("bytes ["); - store_long(static_cast<int64>(value.size())); - result.append("] { "); + sb_ << "bytes [" << value.size() << "] { "; size_t len = min(static_cast<size_t>(64), value.size()); for (size_t i = 0; i < len; i++) { int b = value[static_cast<int>(i)] & 0xff; - result += hex[b >> 4]; - result += hex[b & 15]; - result += ' '; + sb_.push_back(hex[b >> 4]); + sb_.push_back(hex[b & 15]); + sb_.push_back(' '); } if (len < value.size()) { - result.append("..."); + sb_ << "..."; } - result += '}'; + sb_.push_back('}'); store_field_end(); } template <class ObjectT> - void store_object_field(const char *name, const ObjectT *value) { + void store_object_field(CSlice name, const ObjectT *value) { if (value == nullptr) { - store_field(name, "null"); + store_field(name, Slice("null")); } else { - value->store(*this, name); + value->store(*this, name.c_str()); } } - void store_field(const char *name, const UInt128 &value) { + void store_field(Slice name, const UInt128 &value) { store_field_begin(name); store_binary(as_slice(value)); store_field_end(); } - void store_field(const char *name, const UInt256 &value) { + void store_field(Slice name, const UInt256 &value) { store_field_begin(name); store_binary(as_slice(value)); store_field_end(); } - void store_vector_begin(const char *field_name, size_t vector_size) { + void store_vector_begin(Slice field_name, size_t vector_size) { store_field_begin(field_name); - result += "vector["; - result += (PSLICE() << vector_size).c_str(); - result += "] {\n"; - shift += 2; + sb_ << "vector[" << vector_size << "] {\n"; + shift_ += 2; } - void store_class_begin(const char *field_name, const char *class_name) { - store_field_begin(field_name); - result += class_name; - result += " {\n"; - shift += 2; + void store_class_begin(const char *field_name, Slice class_name) { + store_field_begin(Slice(field_name)); + sb_ << class_name << " {\n"; + shift_ += 2; } void store_class_end() { - CHECK(shift >= 2); - shift -= 2; - result.append(shift, ' '); - result += "}\n"; + CHECK(shift_ >= 2); + shift_ -= 2; + sb_.append_char(shift_, ' '); + sb_ << "}\n"; } string move_as_string() { - return std::move(result); + return sb_.as_cslice().str(); } }; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/WaitFreeHashSet.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/WaitFreeHashSet.h index fdc6bd2464..ef956a8d30 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/WaitFreeHashSet.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/WaitFreeHashSet.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -56,15 +56,16 @@ class WaitFreeHashSet { } public: - void insert(const KeyT &key) { + bool insert(const KeyT &key) { if (wait_free_storage_ != nullptr) { return get_wait_free_storage(key).insert(key); } - default_set_.insert(key); + auto result = default_set_.insert(key).second; if (default_set_.size() == max_storage_size_) { split_storage(); } + return result; } size_t count(const KeyT &key) const { diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/algorithm.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/algorithm.h index 00aae8f640..7046c8e653 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/algorithm.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/algorithm.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -86,6 +86,54 @@ bool remove(V &v, const T &value) { return true; } +template <class V, class T> +void add_to_top(V &v, size_t max_size, T value) { + size_t size = v.size(); + size_t i; + for (i = 0; i < size; i++) { + if (v[i] == value) { + value = std::move(v[i]); + break; + } + } + if (i == size) { + if (size < max_size || i == 0) { + v.emplace_back(value); + } else { + i--; + } + } + while (i > 0) { + v[i] = std::move(v[i - 1]); + i--; + } + v[0] = std::move(value); +} + +template <class V, class T, class F> +void add_to_top_if(V &v, size_t max_size, T value, const F &is_equal_to_value) { + size_t size = v.size(); + size_t i; + for (i = 0; i < size; i++) { + if (is_equal_to_value(v[i])) { + value = std::move(v[i]); + break; + } + } + if (i == size) { + if (size < max_size || i == 0) { + v.emplace_back(value); + } else { + i--; + } + } + while (i > 0) { + v[i] = std::move(v[i - 1]); + i--; + } + v[0] = std::move(value); +} + template <class V> void unique(V &v) { if (v.empty()) { @@ -119,6 +167,16 @@ bool contains(const V &v, const T &value) { } template <class V, class F> +bool any_of(const V &v, F &&f) { + for (const auto &x : v) { + if (f(x)) { + return true; + } + } + return false; +} + +template <class V, class F> bool all_of(const V &v, F &&f) { for (const auto &x : v) { if (!f(x)) { @@ -196,22 +254,25 @@ detail::reversion_wrapper<T> reversed(T &iterable) { } template <class TableT, class FuncT> -void table_remove_if(TableT &table, FuncT &&func) { +bool table_remove_if(TableT &table, FuncT &&func) { + bool is_removed = false; for (auto it = table.begin(); it != table.end();) { if (func(*it)) { it = table.erase(it); + is_removed = true; } else { ++it; } } + return is_removed; } template <class NodeT, class HashT, class EqT> class FlatHashTable; template <class NodeT, class HashT, class EqT, class FuncT> -void table_remove_if(FlatHashTable<NodeT, HashT, EqT> &table, FuncT &&func) { - table.remove_if(func); +bool table_remove_if(FlatHashTable<NodeT, HashT, EqT> &table, FuncT &&func) { + return table.remove_if(func); } } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/check.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/check.h index 38769f263a..c8068090d8 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/check.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/check.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -8,11 +8,13 @@ #define TD_DUMMY_CHECK(condition) ((void)(condition)) -#define CHECK(condition) \ - if (!(condition)) { \ - ::td::detail::process_check_error(#condition, __FILE__, __LINE__); \ +#define CHECK_IMPL(condition, file, line) \ + if (!(condition)) { \ + ::td::detail::process_check_error(#condition, file, line); \ } +#define CHECK(condition) CHECK_IMPL(condition, __FILE__, __LINE__) + // clang-format off #ifdef NDEBUG #define DCHECK TD_DUMMY_CHECK diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/crypto.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/crypto.cpp index 77c8993ead..dee0e25112 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/crypto.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/crypto.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -13,6 +13,7 @@ #include "td/utils/Destructor.h" #include "td/utils/logging.h" #include "td/utils/misc.h" +#include "td/utils/port/RwMutex.h" #include "td/utils/port/thread_local.h" #include "td/utils/Random.h" #include "td/utils/ScopeGuard.h" @@ -720,7 +721,7 @@ void AesCtrState::decrypt(Slice from, MutableSlice to) { } #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) -static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) { +static void make_digest(Slice data, MutableSlice output, const EVP_MD_CTX *evp_md_ctx) { static TD_THREAD_LOCAL EVP_MD_CTX *ctx; if (unlikely(ctx == nullptr)) { ctx = EVP_MD_CTX_new(); @@ -730,7 +731,7 @@ static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) { ctx = nullptr; })); } - int res = EVP_DigestInit_ex(ctx, evp_md, nullptr); + int res = EVP_MD_CTX_copy_ex(ctx, evp_md_ctx); LOG_IF(FATAL, res != 1); res = EVP_DigestUpdate(ctx, data.ubegin(), data.size()); LOG_IF(FATAL, res != 1); @@ -739,23 +740,27 @@ static void make_digest(Slice data, MutableSlice output, const EVP_MD *evp_md) { EVP_MD_CTX_reset(ctx); } -static void init_thread_local_evp_md(const EVP_MD *&evp_md, const char *algorithm) { - evp_md = EVP_MD_fetch(nullptr, algorithm, nullptr); +static void init_thread_local_evp_md_ctx(const EVP_MD_CTX *&evp_md_ctx, const char *algorithm) { + EVP_MD *evp_md = EVP_MD_fetch(nullptr, algorithm, nullptr); LOG_IF(FATAL, evp_md == nullptr); - detail::add_thread_local_destructor(create_destructor([&evp_md]() mutable { - EVP_MD_free(const_cast<EVP_MD *>(evp_md)); - evp_md = nullptr; + evp_md_ctx = EVP_MD_CTX_new(); + int res = EVP_DigestInit_ex(const_cast<EVP_MD_CTX *>(evp_md_ctx), evp_md, nullptr); + LOG_IF(FATAL, res != 1); + EVP_MD_free(evp_md); + detail::add_thread_local_destructor(create_destructor([&evp_md_ctx]() mutable { + EVP_MD_CTX_free(const_cast<EVP_MD_CTX *>(evp_md_ctx)); + evp_md_ctx = nullptr; })); } #endif void sha1(Slice data, unsigned char output[20]) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - static TD_THREAD_LOCAL const EVP_MD *evp_md; - if (unlikely(evp_md == nullptr)) { - init_thread_local_evp_md(evp_md, "sha1"); + static TD_THREAD_LOCAL const EVP_MD_CTX *evp_md_ctx; + if (unlikely(evp_md_ctx == nullptr)) { + init_thread_local_evp_md_ctx(evp_md_ctx, "sha1"); } - make_digest(data, MutableSlice(output, 20), evp_md); + make_digest(data, MutableSlice(output, 20), evp_md_ctx); #else auto result = SHA1(data.ubegin(), data.size(), output); CHECK(result == output); @@ -765,11 +770,11 @@ void sha1(Slice data, unsigned char output[20]) { void sha256(Slice data, MutableSlice output) { CHECK(output.size() >= 32); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - static TD_THREAD_LOCAL const EVP_MD *evp_md; - if (unlikely(evp_md == nullptr)) { - init_thread_local_evp_md(evp_md, "sha256"); + static TD_THREAD_LOCAL const EVP_MD_CTX *evp_md_ctx; + if (unlikely(evp_md_ctx == nullptr)) { + init_thread_local_evp_md_ctx(evp_md_ctx, "sha256"); } - make_digest(data, output, evp_md); + make_digest(data, output, evp_md_ctx); #else auto result = SHA256(data.ubegin(), data.size(), output.ubegin()); CHECK(result == output.ubegin()); @@ -779,11 +784,11 @@ void sha256(Slice data, MutableSlice output) { void sha512(Slice data, MutableSlice output) { CHECK(output.size() >= 64); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - static TD_THREAD_LOCAL const EVP_MD *evp_md; - if (unlikely(evp_md == nullptr)) { - init_thread_local_evp_md(evp_md, "sha512"); + static TD_THREAD_LOCAL const EVP_MD_CTX *evp_md_ctx; + if (unlikely(evp_md_ctx == nullptr)) { + init_thread_local_evp_md_ctx(evp_md_ctx, "sha512"); } - make_digest(data, output, evp_md); + make_digest(data, output, evp_md_ctx); #else auto result = SHA512(data.ubegin(), data.size(), output.ubegin()); CHECK(result == output.ubegin()); @@ -863,11 +868,11 @@ void Sha256State::init() { } CHECK(!is_inited_); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - static TD_THREAD_LOCAL const EVP_MD *evp_md; - if (unlikely(evp_md == nullptr)) { - init_thread_local_evp_md(evp_md, "sha256"); + static TD_THREAD_LOCAL const EVP_MD_CTX *evp_md_ctx; + if (unlikely(evp_md_ctx == nullptr)) { + init_thread_local_evp_md_ctx(evp_md_ctx, "sha256"); } - int err = EVP_DigestInit_ex(impl_->ctx_, evp_md, nullptr); + int err = EVP_MD_CTX_copy_ex(impl_->ctx_, evp_md_ctx); #else int err = SHA256_Init(&impl_->ctx_); #endif @@ -905,11 +910,11 @@ void Sha256State::extract(MutableSlice output, bool destroy) { void md5(Slice input, MutableSlice output) { CHECK(output.size() >= 16); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) - static TD_THREAD_LOCAL const EVP_MD *evp_md; - if (unlikely(evp_md == nullptr)) { - init_thread_local_evp_md(evp_md, "md5"); + static TD_THREAD_LOCAL const EVP_MD_CTX *evp_md_ctx; + if (unlikely(evp_md_ctx == nullptr)) { + init_thread_local_evp_md_ctx(evp_md_ctx, "md5"); } - make_digest(input, output, evp_md); + make_digest(input, output, evp_md_ctx); #else auto result = MD5(input.ubegin(), input.size(), output.ubegin()); CHECK(result == output.ubegin()); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/emoji.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/emoji.cpp index c3e2514876..b8b5c67342 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/emoji.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/emoji.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -141,7 +141,7 @@ static bool is_emoji_element(Slice str) { bool is_emoji(Slice str) { size_t i = str.substr(0, MAX_EMOJI_LENGTH + 4).find('\xE2'); - if (i == td::Slice::npos) { + if (i == Slice::npos) { return is_emoji_element(str); } diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.cpp index 5a2fc0b268..80d9353a27 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -50,8 +50,8 @@ Result<T> read_file_impl(CSlice path, int64 size, int64 offset) { size = file_size - offset; } auto content = create_empty<T>(narrow_cast<size_t>(size)); - TRY_RESULT(got_size, from_file.pread(as_mutable_slice(content), offset)); - if (got_size != static_cast<size_t>(size)) { + TRY_RESULT(read_size, from_file.pread(as_mutable_slice(content), offset)); + if (read_size != static_cast<size_t>(size)) { return Status::Error("Failed to read file"); } from_file.close(); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.h index c1d232026f..474728d3e7 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/filesystem.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -7,6 +7,7 @@ #pragma once #include "td/utils/buffer.h" +#include "td/utils/common.h" #include "td/utils/SharedSlice.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" @@ -27,7 +28,7 @@ Status write_file(CSlice to, Slice data, WriteFileOptions options = {}) TD_WARN_ string clean_filename(CSlice name); -// writes data to file and ensures that the file is either fully overriden, or is left intact +// writes data to file and ensures that the file is either fully overridden, or is left intact // uses path_tmp to temporary store data, then calls rename Status atomic_write_file(CSlice path, Slice data, CSlice path_tmp = {}); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/format.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/format.h index b7fdf53f2c..cb5220805b 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/format.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/format.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -216,7 +216,7 @@ struct Array { template <class ArrayT> StringBuilder &operator<<(StringBuilder &stream, const Array<ArrayT> &array) { bool first = true; - stream << Slice("{"); + stream << '{'; for (auto &x : array.ref) { if (!first) { stream << Slice(", "); @@ -224,12 +224,12 @@ StringBuilder &operator<<(StringBuilder &stream, const Array<ArrayT> &array) { stream << x; first = false; } - return stream << Slice("}"); + return stream << '}'; } inline StringBuilder &operator<<(StringBuilder &stream, const Array<vector<bool>> &array) { bool first = true; - stream << Slice("{"); + stream << '{'; for (bool x : array.ref) { if (!first) { stream << Slice(", "); @@ -237,7 +237,7 @@ inline StringBuilder &operator<<(StringBuilder &stream, const Array<vector<bool> stream << x; first = false; } - return stream << Slice("}"); + return stream << '}'; } template <class ArrayT> @@ -254,7 +254,7 @@ struct Tagged { template <class ValueT> StringBuilder &operator<<(StringBuilder &stream, const Tagged<ValueT> &tagged) { - return stream << "[" << tagged.tag << ":" << tagged.ref << "]"; + return stream << '[' << tagged.tag << ':' << tagged.ref << ']'; } template <class ValueT> @@ -305,34 +305,8 @@ auto concat(const ArgsT &...args) { return Concat<decltype(std::tie(args...))>{std::tie(args...)}; } -template <class F> -struct Lambda { - const F &f; -}; - -template <class F> -StringBuilder &operator<<(StringBuilder &sb, const Lambda<F> &f) { - f.f(sb); - return sb; -} - -template <class LambdaT> -Lambda<LambdaT> lambda(const LambdaT &lambda) { - return Lambda<LambdaT>{lambda}; -} - } // namespace format using format::tag; -template <class A, class B> -StringBuilder &operator<<(StringBuilder &sb, const std::pair<A, B> &p) { - return sb << "[" << p.first << ";" << p.second << "]"; -} - -template <class T> -StringBuilder &operator<<(StringBuilder &stream, const vector<T> &vec) { - return stream << format::as_array(vec); -} - } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp index cf73f5dfb2..8ddf80643e 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/logging.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -191,8 +191,7 @@ class DefaultLog final : public LogInterface { #elif TD_EMSCRIPTEN switch (log_level) { case VERBOSITY_NAME(FATAL): - emscripten_log(EM_LOG_ERROR | EM_LOG_CONSOLE | EM_LOG_C_STACK | EM_LOG_JS_STACK | EM_LOG_FUNC_PARAMS, "%s", - slice.c_str()); + emscripten_log(EM_LOG_ERROR | EM_LOG_CONSOLE | EM_LOG_C_STACK | EM_LOG_JS_STACK, "%s", slice.c_str()); EM_ASM(throw(UTF8ToString($0)), slice.c_str()); break; case VERBOSITY_NAME(ERROR): diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/misc.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/misc.cpp index 6976ead384..cb3dcac6ab 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/misc.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/misc.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -7,6 +7,8 @@ #include "td/utils/misc.h" #include "td/utils/port/thread_local.h" +#include "td/utils/StackAllocator.h" +#include "td/utils/StringBuilder.h" #include "td/utils/utf8.h" #include <algorithm> @@ -81,11 +83,11 @@ string oneline(Slice str) { namespace detail { Status get_to_integer_safe_error(Slice str) { - auto status = Status::Error(PSLICE() << "Can't parse \"" << str << "\" as an integer"); - if (!check_utf8(status.message())) { - status = Status::Error("Strings must be encoded in UTF-8"); + auto error_message = PSTRING() << "Can't parse as an integer string \"" << str << '"'; + if (!check_utf8(error_message)) { + return Status::Error("Strings must be encoded in UTF-8"); } - return status; + return Status::Error(error_message); } } // namespace detail @@ -201,60 +203,72 @@ string buffer_to_hex(Slice buffer) { return res; } -namespace { +string zero_encode(Slice data) { + auto buffer = StackAllocator::alloc(1024); + auto res = StringBuilder(buffer.as_slice(), true); + for (size_t n = data.size(), i = 0; i < n; i++) { + res.push_back(data[i]); + if (data[i] == 0) { + unsigned char cnt = 1; + while (cnt < 250 && i + cnt < n && data[i + cnt] == data[i]) { + cnt++; + } + res.push_back(static_cast<char>(cnt)); + i += cnt - 1; + } + } + return res.as_cslice().str(); +} -template <class F> -string x_decode(Slice s, F &&f) { - string res; - for (size_t n = s.size(), i = 0; i < n; i++) { - if (i + 1 < n && f(s[i])) { - res.append(static_cast<unsigned char>(s[i + 1]), s[i]); +string zero_decode(Slice data) { + auto buffer = StackAllocator::alloc(1024); + auto res = StringBuilder(buffer.as_slice(), true); + for (size_t n = data.size(), i = 0; i < n; i++) { + if (data[i] == 0 && i + 1 < n) { + for (int cnt = static_cast<unsigned char>(data[i + 1]); cnt > 0; cnt--) { + res.push_back(data[i]); + } i++; continue; } - res.push_back(s[i]); + res.push_back(data[i]); } - return res; + return res.as_cslice().str(); } -template <class F> -string x_encode(Slice s, F &&f) { - string res; - for (size_t n = s.size(), i = 0; i < n; i++) { - res.push_back(s[i]); - if (f(s[i])) { +string zero_one_encode(Slice data) { + auto buffer = StackAllocator::alloc(1024); + auto res = StringBuilder(buffer.as_slice(), true); + for (size_t n = data.size(), i = 0; i < n; i++) { + res.push_back(data[i]); + auto c = static_cast<unsigned char>(data[i]); + if (c == 0 || c == 0xff) { unsigned char cnt = 1; - while (cnt < 250 && i + cnt < n && s[i + cnt] == s[i]) { + while (cnt < 250 && i + cnt < n && data[i + cnt] == data[i]) { cnt++; } res.push_back(static_cast<char>(cnt)); i += cnt - 1; } } - return res; + return res.as_cslice().str(); } -bool is_zero(unsigned char c) { - return c == 0; -} - -bool is_zero_or_one(unsigned char c) { - return c == 0 || c == 0xff; -} - -} // namespace - -std::string zero_encode(Slice data) { - return x_encode(data, is_zero); -} -std::string zero_decode(Slice data) { - return x_decode(data, is_zero); -} -std::string zero_one_encode(Slice data) { - return x_encode(data, is_zero_or_one); -} -std::string zero_one_decode(Slice data) { - return x_decode(data, is_zero_or_one); +string zero_one_decode(Slice data) { + auto buffer = StackAllocator::alloc(1024); + auto res = StringBuilder(buffer.as_slice(), true); + for (size_t n = data.size(), i = 0; i < n; i++) { + auto c = static_cast<unsigned char>(data[i]); + if ((c == 0 || c == 0xff) && i + 1 < n) { + for (int cnt = static_cast<unsigned char>(data[i + 1]); cnt > 0; cnt--) { + res.push_back(data[i]); + } + i++; + continue; + } + res.push_back(data[i]); + } + return res.as_cslice().str(); } } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/optional.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/optional.h index ace463d70d..bb7e4bc813 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/optional.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/optional.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -60,6 +60,9 @@ class optional { T &operator*() { return value(); } + const T &operator*() const { + return value(); + } T unwrap() { CHECK(*this); auto res = std::move(value()); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp index 52c7ef28c5..23f7f33d2b 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FileFd.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -224,10 +224,18 @@ Result<FileFd> FileFd::open(CSlice filepath, int32 flags, int32 mode) { if (flags & WinStat) { native_flags |= FILE_FLAG_BACKUP_SEMANTICS; } - +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) auto handle = CreateFile(w_filepath.c_str(), desired_access, share_mode, nullptr, creation_disposition, native_flags, nullptr); - +#else + CREATEFILE2_EXTENDED_PARAMETERS extended_parameters; + std::memset(&extended_parameters, 0, sizeof(extended_parameters)); + extended_parameters.dwSize = sizeof(extended_parameters); + extended_parameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extended_parameters.dwFileFlags = native_flags; + auto handle = td::CreateFile2FromAppW(w_filepath.c_str(), desired_access, share_mode, creation_disposition, + &extended_parameters); +#endif if (handle == INVALID_HANDLE_VALUE) { return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); } @@ -595,13 +603,7 @@ Result<Stat> FileFd::stat() const { #elif TD_PORT_WINDOWS Stat res; - #ifdef _WIN64 FILE_BASIC_INFO basic_info; - #else - struct __boo : public FILE_BASIC_INFO { - DWORD __tmp; - } basic_info; - #endif auto status = GetFileInformationByHandleEx(get_native_fd().fd(), FileBasicInfo, &basic_info, sizeof(basic_info)); if (!status) { return OS_ERROR("Get FileBasicInfo failed"); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FromApp.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FromApp.h index 1f72eb706c..23125b6c81 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FromApp.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/FromApp.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -53,6 +53,13 @@ T *get_from_app_function(const char *name, T *original_func) { #endif } +inline HANDLE CreateFile2FromAppW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, + _In_ DWORD dwCreationDisposition, + _In_opt_ LPCREATEFILE2_EXTENDED_PARAMETERS pCreateExParams) { + auto func = get_from_app_function<0>("CreateFile2FromAppW", &CreateFile2); + return func(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, pCreateExParams); +} + inline BOOL CreateDirectoryFromAppW(_In_ LPCWSTR lpPathName, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes) { auto func = get_from_app_function<1>("CreateDirectoryFromAppW", &CreateDirectory); return func(lpPathName, lpSecurityAttributes); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.cpp index d7eca3a0d2..72578a9be8 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -369,4 +369,12 @@ Result<ServerSocketFd> ServerSocketFd::open(int32 port, CSlice addr) { return ServerSocketFd(std::move(impl)); } +Result<uint32> ServerSocketFd::maximize_snd_buffer(uint32 max_size) { + return get_native_fd().maximize_snd_buffer(max_size); +} + +Result<uint32> ServerSocketFd::maximize_rcv_buffer(uint32 max_size) { + return get_native_fd().maximize_rcv_buffer(max_size); +} + } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.h index 266e688321..dcee89917f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/ServerSocketFd.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -33,6 +33,9 @@ class ServerSocketFd { ServerSocketFd &operator=(ServerSocketFd &&) noexcept; ~ServerSocketFd(); + Result<uint32> maximize_snd_buffer(uint32 max_size = 0); + Result<uint32> maximize_rcv_buffer(uint32 max_size = 0); + static Result<ServerSocketFd> open(int32 port, CSlice addr = CSlice("0.0.0.0")) TD_WARN_UNUSED_RESULT; PollableFdInfo &get_poll_info(); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.cpp index 68c62ad11b..ac4038c3f9 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -578,7 +578,7 @@ Status get_socket_pending_error(const NativeFd &fd, WSAOVERLAPPED *overlapped, S DWORD flags = 0; BOOL success = WSAGetOverlappedResult(fd.socket(), overlapped, &num_bytes, false, &flags); if (success) { - LOG(ERROR) << "WSAGetOverlappedResult succeded after " << iocp_error; + LOG(ERROR) << "WSAGetOverlappedResult succeeded after " << iocp_error; return iocp_error; } return OS_SOCKET_ERROR(PSLICE() << "Error on " << fd); @@ -717,4 +717,12 @@ Result<size_t> SocketFd::read(MutableSlice slice) { return impl_->read(slice); } +Result<uint32> SocketFd::maximize_snd_buffer(uint32 max_size) { + return get_native_fd().maximize_snd_buffer(max_size); +} + +Result<uint32> SocketFd::maximize_rcv_buffer(uint32 max_size) { + return get_native_fd().maximize_rcv_buffer(max_size); +} + } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.h index 2c4a3746fe..40f3a9321a 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/SocketFd.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -37,6 +37,9 @@ class SocketFd { SocketFd &operator=(SocketFd &&) noexcept; ~SocketFd(); + Result<uint32> maximize_snd_buffer(uint32 max_size = 0); + Result<uint32> maximize_rcv_buffer(uint32 max_size = 0); + static Result<SocketFd> open(const IPAddress &address) TD_WARN_UNUSED_RESULT; PollableFdInfo &get_poll_info(); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.cpp index e5db2c2fb2..cd4641b188 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -790,54 +790,6 @@ const NativeFd &UdpSocketFd::get_native_fd() const { } #if TD_PORT_POSIX -static Result<uint32> maximize_buffer(int socket_fd, int optname, uint32 max_size) { - if (setsockopt(socket_fd, SOL_SOCKET, optname, &max_size, sizeof(max_size)) == 0) { - // fast path - return max_size; - } - - /* Start with the default size. */ - uint32 old_size = 0; - socklen_t intsize = sizeof(old_size); - if (getsockopt(socket_fd, SOL_SOCKET, optname, &old_size, &intsize)) { - return OS_ERROR("getsockopt() failed"); - } -#if TD_LINUX - old_size /= 2; -#endif - - /* Binary-search for the real maximum. */ - uint32 last_good_size = old_size; - uint32 min_size = old_size; - while (min_size <= max_size) { - uint32 avg_size = min_size + (max_size - min_size) / 2; - if (setsockopt(socket_fd, SOL_SOCKET, optname, &avg_size, sizeof(avg_size)) == 0) { - last_good_size = avg_size; - min_size = avg_size + 1; - } else { - max_size = avg_size - 1; - } - } - return last_good_size; -} - -Result<uint32> UdpSocketFd::maximize_snd_buffer(uint32 max_size) { - return maximize_buffer(get_native_fd().fd(), SO_SNDBUF, max_size == 0 ? DEFAULT_UDP_MAX_SND_BUFFER_SIZE : max_size); -} - -Result<uint32> UdpSocketFd::maximize_rcv_buffer(uint32 max_size) { - return maximize_buffer(get_native_fd().fd(), SO_RCVBUF, max_size == 0 ? DEFAULT_UDP_MAX_RCV_BUFFER_SIZE : max_size); -} -#else -Result<uint32> UdpSocketFd::maximize_snd_buffer(uint32 max_size) { - return 0; -} -Result<uint32> UdpSocketFd::maximize_rcv_buffer(uint32 max_size) { - return 0; -} -#endif - -#if TD_PORT_POSIX Status UdpSocketFd::send_message(const OutboundMessage &message, bool &is_sent) { return impl_->send_message(message, is_sent); } @@ -870,4 +822,12 @@ bool UdpSocketFd::is_critical_read_error(const Status &status) { return status.code() == ENOMEM || status.code() == ENOBUFS; } +Result<uint32> UdpSocketFd::maximize_snd_buffer(uint32 max_size) { + return get_native_fd().maximize_snd_buffer(max_size); +} + +Result<uint32> UdpSocketFd::maximize_rcv_buffer(uint32 max_size) { + return get_native_fd().maximize_rcv_buffer(max_size); +} + } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.h index 67cdf801ae..53d7755b69 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/UdpSocketFd.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -83,8 +83,6 @@ class UdpSocketFd { #endif private: - static constexpr uint32 DEFAULT_UDP_MAX_SND_BUFFER_SIZE = (1 << 24); - static constexpr uint32 DEFAULT_UDP_MAX_RCV_BUFFER_SIZE = (1 << 24); std::unique_ptr<detail::UdpSocketFdImpl, detail::UdpSocketFdImplDeleter> impl_; explicit UdpSocketFd(unique_ptr<detail::UdpSocketFdImpl> impl); }; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.cpp index 779a166cc0..479498ee9c 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -12,6 +12,8 @@ #if TD_PORT_POSIX #include <fcntl.h> +#include <sys/socket.h> +#include <sys/types.h> #include <unistd.h> #endif @@ -223,6 +225,45 @@ Status NativeFd::duplicate(const NativeFd &to) const { #endif } +static Result<uint32> maximize_buffer(const NativeFd::Socket &socket, int optname, uint32 max_size) { + if (setsockopt(socket, SOL_SOCKET, optname, reinterpret_cast<const char *>(&max_size), sizeof(max_size)) == 0) { + // fast path + return max_size; + } + + /* Start with the default size. */ + uint32 old_size = 0; + socklen_t intsize = sizeof(old_size); + if (getsockopt(socket, SOL_SOCKET, optname, reinterpret_cast<char *>(&old_size), &intsize)) { + return OS_SOCKET_ERROR("getsockopt() failed"); + } +#if TD_LINUX + old_size /= 2; +#endif + + /* Binary-search for the real maximum. */ + uint32 last_good_size = old_size; + uint32 min_size = old_size; + while (min_size <= max_size) { + uint32 avg_size = min_size + (max_size - min_size) / 2; + if (setsockopt(socket, SOL_SOCKET, optname, reinterpret_cast<const char *>(&avg_size), sizeof(avg_size)) == 0) { + last_good_size = avg_size; + min_size = avg_size + 1; + } else { + max_size = avg_size - 1; + } + } + return last_good_size; +} + +Result<uint32> NativeFd::maximize_snd_buffer(uint32 max_size) const { + return maximize_buffer(socket(), SO_SNDBUF, max_size == 0 ? DEFAULT_MAX_SND_BUFFER_SIZE : max_size); +} + +Result<uint32> NativeFd::maximize_rcv_buffer(uint32 max_size) const { + return maximize_buffer(socket(), SO_RCVBUF, max_size == 0 ? DEFAULT_MAX_RCV_BUFFER_SIZE : max_size); +} + void NativeFd::close() { if (!*this) { return; diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.h index e4eaaa696b..a2af773b0f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/detail/NativeFd.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -49,6 +49,9 @@ class NativeFd { Status duplicate(const NativeFd &to) const; + Result<uint32> maximize_snd_buffer(uint32 max_size = 0) const; + Result<uint32> maximize_rcv_buffer(uint32 max_size = 0) const; + void close(); Fd release(); @@ -61,6 +64,8 @@ class NativeFd { #if TD_PORT_WINDOWS bool is_socket_{false}; #endif + static constexpr uint32 DEFAULT_MAX_SND_BUFFER_SIZE = (1 << 24); + static constexpr uint32 DEFAULT_MAX_RCV_BUFFER_SIZE = (1 << 24); }; StringBuilder &operator<<(StringBuilder &sb, const NativeFd &fd); diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/platform.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/platform.h index 5772948750..7ca7ee20d5 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/platform.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/platform.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -25,6 +25,8 @@ #define TD_DARWIN_IOS 1 #elif TARGET_OS_TV #define TD_DARWIN_TV_OS 1 + #elif TARGET_OS_VISION + #define TD_DARWIN_VISION_OS 1 #elif TARGET_OS_WATCH #define TD_DARWIN_WATCH_OS 1 #else diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/uname.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/uname.cpp index 6da28ee26c..5b9dc855e9 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/port/uname.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/port/uname.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -81,6 +81,8 @@ Slice get_operating_system_version() { return "iOS" + os_version; #elif TD_DARWIN_TV_OS return "tvOS" + os_version; +#elif TD_DARWIN_VISION_OS + return "visionOS" + os_version; #elif TD_DARWIN_WATCH_OS return "watchOS" + os_version; #elif TD_DARWIN_MAC diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.cpp index feeb907cac..9a346a2650 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.cpp @@ -1,12 +1,15 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include "td/utils/tl_parsers.h" +#include "td/utils/format.h" +#include "td/utils/logging.h" #include "td/utils/misc.h" +#include "td/utils/utf8.h" namespace td { @@ -55,4 +58,21 @@ BufferSlice TlBufferParser::as_buffer_slice(Slice slice) { return BufferSlice(slice); } +bool TlBufferParser::is_valid_utf8(CSlice str) const { + if (check_utf8(str)) { + return true; + } + LOG(WARNING) << "Wrong UTF-8 string [[" << str << "]] in " << format::as_hex_dump<4>(parent_->as_slice()); + return false; +} + +size_t TlBufferParser::last_utf8_character_position(Slice str) { + CHECK(!str.empty()); + size_t position = str.size() - 1; + while (position != 0 && !is_utf8_character_first_code_unit(static_cast<unsigned char>(str[position]))) { + position--; + } + return position; +} + } // namespace td diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.h b/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.h index b5d85cc74d..f08009b57a 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.h +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/tl_parsers.h @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -8,13 +8,10 @@ #include "td/utils/buffer.h" #include "td/utils/common.h" -#include "td/utils/format.h" -#include "td/utils/logging.h" #include "td/utils/Slice.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Status.h" #include "td/utils/UInt.h" -#include "td/utils/utf8.h" #include <array> #include <cstring> @@ -207,19 +204,11 @@ class TlBufferParser : public TlParser { c = ' '; } } - if (check_utf8(result)) { + if (is_valid_utf8(result)) { return result; } - CHECK(!result.empty()); - LOG(WARNING) << "Wrong UTF-8 string [[" << result << "]] in " << format::as_hex_dump<4>(parent_->as_slice()); - - // trying to remove last character - size_t new_size = result.size() - 1; - while (new_size != 0 && !is_utf8_character_first_code_unit(static_cast<unsigned char>(result[new_size]))) { - new_size--; - } - result.resize(new_size); - if (check_utf8(result)) { + result.resize(last_utf8_character_position(result)); + if (is_valid_utf8(result)) { return result; } @@ -235,6 +224,10 @@ class TlBufferParser : public TlParser { const BufferSlice *parent_; BufferSlice as_buffer_slice(Slice slice); + + bool is_valid_utf8(CSlice str) const; + + static size_t last_utf8_character_position(Slice str); }; template <> diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/unicode.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/unicode.cpp index df9a22a96b..1c0bbb8028 100644 --- a/protocols/Telegram/tdlib/td/tdutils/td/utils/unicode.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/unicode.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -12,137 +12,137 @@ namespace td { // list of [(range_begin << 5) + range_type] static const uint32 unicode_simple_category_ranges[] = { - 0, 1028, 1056, 1538, 1856, 2081, 2912, 3105, 3936, 5124, 5152, 5441, - 5472, 5699, 5760, 5793, 5824, 5923, 5953, 5984, 6019, 6112, 6145, 6880, - 6913, 7904, 7937, 22592, 22721, 23104, 23553, 23712, 23937, 23968, 24001, 24032, - 28161, 28320, 28353, 28416, 28481, 28608, 28641, 28672, 28865, 28896, 28929, 29024, - 29057, 29088, 29121, 29760, 29793, 32448, 32481, 36928, 37185, 42496, 42529, 43744, - 43809, 43840, 44033, 45344, 47617, 48480, 48609, 48736, 50177, 51552, 52226, 52544, - 52673, 52736, 52769, 55936, 55969, 56000, 56481, 56544, 56769, 56834, 57153, 57248, - 57313, 57344, 57857, 57888, 57921, 58880, 59809, 62656, 63009, 63040, 63490, 63809, - 64864, 65153, 65216, 65345, 65376, 65537, 66240, 66369, 66400, 66689, 66720, 66817, - 66848, 67585, 68384, 68609, 68960, 69121, 69888, 69921, 70112, 70657, 72000, 73857, - 75584, 75681, 75712, 76289, 76320, 76545, 76864, 76994, 77312, 77345, 77856, 77985, - 78240, 78305, 78368, 78433, 79136, 79169, 79392, 79425, 79456, 79553, 79680, 79777, - 79808, 80321, 80352, 80769, 80832, 80865, 80960, 81090, 81409, 81472, 81539, 81728, - 81793, 81824, 82081, 82272, 82401, 82464, 82529, 83232, 83265, 83488, 83521, 83584, - 83617, 83680, 83713, 83776, 84769, 84896, 84929, 84960, 85186, 85504, 85569, 85664, - 86177, 86464, 86497, 86592, 86625, 87328, 87361, 87584, 87617, 87680, 87713, 87872, - 87969, 88000, 88577, 88608, 89089, 89152, 89282, 89600, 89889, 89920, 90273, 90528, - 90593, 90656, 90721, 91424, 91457, 91680, 91713, 91776, 91809, 91968, 92065, 92096, - 93057, 93120, 93153, 93248, 93378, 93696, 93729, 93763, 93952, 94305, 94336, 94369, - 94560, 94657, 94752, 94785, 94912, 95009, 95072, 95105, 95136, 95169, 95232, 95329, - 95392, 95489, 95584, 95681, 96064, 96769, 96800, 97474, 97795, 97888, 98465, 98720, - 98753, 98848, 98881, 99616, 99649, 100160, 100257, 100288, 101121, 101216, 101281, 101312, - 101377, 101440, 101570, 101888, 102147, 102368, 102401, 102432, 102561, 102816, 102849, 102944, - 102977, 103712, 103745, 104064, 104097, 104256, 104353, 104384, 105377, 105440, 105473, 105536, - 105666, 105984, 106017, 106080, 106625, 106912, 106945, 107040, 107073, 108384, 108449, 108480, - 108993, 109024, 109185, 109280, 109315, 109537, 109632, 109762, 110083, 110368, 110401, 110592, - 110753, 111328, 111425, 112192, 112225, 112512, 112545, 112576, 112641, 112864, 113858, 114176, - 114721, 116256, 116289, 116352, 116737, 116960, 117250, 117568, 118817, 118880, 118913, 118944, - 118977, 119136, 119169, 119936, 119969, 120000, 120033, 120352, 120385, 120448, 120737, 120768, - 120833, 120992, 121025, 121056, 121346, 121664, 121729, 121856, 122881, 122912, 123906, 124227, - 124544, 124929, 125184, 125217, 126368, 127233, 127392, 131073, 132448, 133089, 133122, 133440, - 133633, 133824, 133953, 134080, 134177, 134208, 134305, 134368, 134593, 134688, 134817, 135232, - 135617, 135648, 135682, 136000, 136193, 137408, 137441, 137472, 137633, 137664, 137729, 139104, - 139137, 149792, 149825, 149952, 150017, 150240, 150273, 150304, 150337, 150464, 150529, 151840, - 151873, 152000, 152065, 153120, 153153, 153280, 153345, 153568, 153601, 153632, 153665, 153792, - 153857, 154336, 154369, 156192, 156225, 156352, 156417, 158560, 159011, 159648, 159745, 160256, - 160769, 163520, 163585, 163776, 163873, 183712, 183777, 184324, 184353, 185184, 185345, 187744, - 187843, 187937, 188192, 188417, 188992, 189409, 190016, 190465, 191040, 191489, 191904, 191937, - 192032, 192513, 194176, 195297, 195328, 195457, 195488, 195586, 195904, 196099, 196416, 197122, - 197440, 197633, 200480, 200705, 200864, 200929, 202016, 202049, 202080, 202241, 204480, 204801, - 205792, 207042, 207361, 208320, 208385, 208544, 208897, 210304, 210433, 211264, 211458, 211779, - 211808, 212993, 213728, 214017, 215712, 217090, 217408, 217602, 217920, 218337, 218368, 221345, - 222848, 223393, 223648, 223746, 224064, 225377, 226336, 226753, 226818, 227137, 228544, 229377, - 230528, 231426, 231744, 231841, 231938, 232257, 233408, 233473, 233760, 233985, 235360, 235425, - 235520, 236833, 236960, 236993, 237184, 237217, 237280, 237377, 237408, 237569, 243712, 245761, - 254656, 254721, 254912, 254977, 256192, 256257, 256448, 256513, 256768, 256801, 256832, 256865, - 256896, 256929, 256960, 256993, 257984, 258049, 259744, 259777, 260000, 260033, 260064, 260161, - 260256, 260289, 260512, 260609, 260736, 260801, 260992, 261121, 261536, 261697, 261792, 261825, - 262048, 262148, 262496, 263428, 263488, 263652, 263680, 265188, 265216, 265731, 265761, 265792, - 265859, 266048, 266209, 266243, 266560, 266753, 267168, 270401, 270432, 270561, 270592, 270657, - 270976, 271009, 271040, 271137, 271296, 271489, 271520, 271553, 271584, 271617, 271648, 271681, - 271808, 271841, 272192, 272257, 272384, 272545, 272704, 272833, 272864, 272899, 274529, 274595, - 274752, 297987, 299904, 302403, 303104, 323267, 324224, 360449, 367776, 367969, 368096, 368193, - 368256, 368547, 368576, 368641, 369856, 369889, 369920, 370081, 370112, 370177, 371968, 372193, - 372224, 372737, 373472, 373761, 373984, 374017, 374240, 374273, 374496, 374529, 374752, 374785, - 375008, 375041, 375264, 375297, 375520, 375553, 375776, 378337, 378368, 393220, 393248, 393377, - 393443, 393472, 394275, 394560, 394785, 394944, 395011, 395105, 395168, 395297, 398048, 398241, - 398336, 398369, 401248, 401281, 401408, 401569, 402944, 402977, 405984, 406083, 406208, 406529, - 407552, 409089, 409600, 410627, 410944, 411907, 412160, 412195, 412672, 413699, 414016, 415267, - 415744, 425985, 636928, 638977, 1348000, 1350145, 1351616, 1351681, 1360288, 1360385, 1360898, 1361217, - 1361280, 1361921, 1363424, 1363937, 1364928, 1364993, 1367235, 1367552, 1368801, 1369088, 1369153, 1372448, - 1372513, 1374560, 1374721, 1374784, 1374817, 1374848, 1374881, 1375040, 1375809, 1376320, 1376353, 1376448, - 1376481, 1376608, 1376641, 1377376, 1377795, 1377984, 1378305, 1379968, 1380417, 1382016, 1382914, 1383232, - 1384001, 1384192, 1384289, 1384320, 1384353, 1384416, 1384450, 1384769, 1385664, 1385985, 1386720, 1387521, - 1388448, 1388673, 1390176, 1391073, 1391106, 1391424, 1391617, 1391776, 1391809, 1392130, 1392449, 1392608, - 1392641, 1393952, 1394689, 1394784, 1394817, 1395072, 1395202, 1395520, 1395713, 1396448, 1396545, 1396576, - 1396673, 1398272, 1398305, 1398336, 1398433, 1398496, 1398561, 1398720, 1398785, 1398816, 1398849, 1398880, - 1399649, 1399744, 1399809, 1400160, 1400385, 1400480, 1400865, 1401056, 1401121, 1401312, 1401377, 1401568, - 1401857, 1402080, 1402113, 1402336, 1402369, 1403744, 1403777, 1404224, 1404417, 1408096, 1408514, 1408832, - 1409025, 1766528, 1766913, 1767648, 1767777, 1769344, 2039809, 2051520, 2051585, 2054976, 2056193, 2056416, - 2056801, 2056960, 2057121, 2057152, 2057185, 2057504, 2057537, 2057952, 2057985, 2058144, 2058177, 2058208, - 2058241, 2058304, 2058337, 2058400, 2058433, 2061888, 2062945, 2074560, 2075137, 2077184, 2077249, 2078976, - 2080257, 2080640, 2084353, 2084512, 2084545, 2088864, 2089474, 2089792, 2090017, 2090848, 2091041, 2091872, - 2092225, 2095072, 2095169, 2095360, 2095425, 2095616, 2095681, 2095872, 2095937, 2096032, 2097153, 2097536, - 2097569, 2098400, 2098433, 2099040, 2099073, 2099136, 2099169, 2099648, 2099713, 2100160, 2101249, 2105184, - 2105571, 2107008, 2107395, 2109216, 2109763, 2109824, 2117633, 2118560, 2118657, 2120224, 2120739, 2121600, - 2121729, 2122755, 2122880, 2123169, 2123811, 2123841, 2124099, 2124128, 2124289, 2125504, 2125825, 2126784, - 2126849, 2128000, 2128129, 2128384, 2128419, 2128576, 2129921, 2134976, 2135042, 2135360, 2135553, 2136704, - 2136833, 2137984, 2138113, 2139392, 2139649, 2141312, 2141697, 2142048, 2142081, 2142560, 2142593, 2142816, - 2142849, 2142912, 2142945, 2143296, 2143329, 2143808, 2143841, 2144064, 2144097, 2144160, 2146305, 2156256, - 2156545, 2157248, 2157569, 2157824, 2158593, 2158784, 2158817, 2160160, 2160193, 2160480, 2162689, 2162880, - 2162945, 2162976, 2163009, 2164416, 2164449, 2164512, 2164609, 2164640, 2164705, 2165440, 2165507, 2165761, - 2166496, 2166563, 2166785, 2167776, 2168035, 2168320, 2169857, 2170464, 2170497, 2170560, 2170723, 2170881, - 2171587, 2171776, 2171905, 2172736, 2174977, 2176768, 2176899, 2176961, 2177027, 2177536, 2177603, 2179073, - 2179104, 2179585, 2179712, 2179745, 2179840, 2179873, 2180800, 2181123, 2181408, 2182145, 2183075, 2183136, - 2183169, 2184099, 2184192, 2185217, 2185472, 2185505, 2186400, 2186595, 2186752, 2187265, 2188992, 2189313, - 2190016, 2190083, 2190337, 2190944, 2191107, 2191361, 2191936, 2192675, 2192896, 2195457, 2197792, 2199553, - 2201184, 2201601, 2203232, 2203459, 2203649, 2204800, 2205186, 2205504, 2214915, 2215904, 2215937, 2217280, - 2217473, 2217536, 2220033, 2220963, 2221281, 2221312, 2221569, 2222272, 2222627, 2222752, 2223617, 2224192, - 2225665, 2226339, 2226560, 2227201, 2227936, 2228321, 2230016, 2230851, 2231490, 2231808, 2231841, 2231904, - 2231969, 2232000, 2232417, 2233856, 2234881, 2235680, 2235906, 2236224, 2236513, 2237664, 2238146, 2238464, - 2238593, 2238624, 2238689, 2238720, 2238977, 2240096, 2240193, 2240224, 2240609, 2242144, 2242593, 2242720, - 2243074, 2243393, 2243424, 2243457, 2243488, 2243619, 2244256, 2244609, 2245184, 2245217, 2246016, 2246625, - 2246688, 2248705, 2248928, 2248961, 2248992, 2249025, 2249152, 2249185, 2249664, 2249697, 2250016, 2250241, - 2251744, 2252290, 2252608, 2252961, 2253216, 2253281, 2253344, 2253409, 2254112, 2254145, 2254368, 2254401, - 2254464, 2254497, 2254656, 2254753, 2254784, 2255361, 2255392, 2255777, 2255936, 2260993, 2262688, 2263265, - 2263392, 2263554, 2263872, 2264033, 2264128, 2265089, 2266624, 2267265, 2267328, 2267361, 2267392, 2267650, - 2267968, 2273281, 2274784, 2276097, 2276224, 2277377, 2278912, 2279553, 2279584, 2279938, 2280256, 2281473, - 2282848, 2283265, 2283296, 2283522, 2283840, 2285569, 2286432, 2287106, 2287427, 2287488, 2287617, 2287840, - 2293761, 2295168, 2298881, 2300930, 2301251, 2301536, 2301921, 2302176, 2302241, 2302272, 2302337, 2302592, - 2302625, 2302688, 2302721, 2303488, 2303969, 2304000, 2304033, 2304064, 2304514, 2304832, 2307073, 2307328, - 2307393, 2308640, 2309153, 2309184, 2309217, 2309248, 2310145, 2310176, 2310497, 2311776, 2312001, 2312032, - 2312705, 2312736, 2313089, 2314560, 2315169, 2315200, 2315777, 2318112, 2326529, 2326816, 2326849, 2328032, - 2328577, 2328608, 2329090, 2329411, 2330016, 2330177, 2331136, 2334721, 2334944, 2334977, 2335040, 2335073, - 2336288, 2336961, 2336992, 2337282, 2337600, 2337793, 2337984, 2338017, 2338080, 2338113, 2339136, 2339585, - 2339616, 2339842, 2340160, 2350081, 2350688, 2351169, 2351200, 2351233, 2351648, 2351681, 2352768, 2353666, - 2353984, 2356737, 2356768, 2357251, 2357920, 2359297, 2388800, 2392067, 2395616, 2396161, 2402432, 2486785, - 2489888, 2490369, 2524672, 2525217, 2525408, 2654209, 2672864, 2949121, 2967328, 2967553, 2968544, 2968578, - 2968896, 2969089, 2971616, 2971650, 2971968, 2972161, 2973120, 2973697, 2975232, 2975745, 2975872, 2976258, - 2976576, 2976611, 2976832, 2976865, 2977536, 2977697, 2978304, 3000321, 3002371, 3003104, 3006465, 3008864, - 3009025, 3009056, 3011169, 3011584, 3013633, 3013696, 3013729, 3013760, 3014657, 3211008, 3211265, 3250880, - 3252225, 3252512, 3538433, 3538560, 3538593, 3538816, 3538849, 3538912, 3538945, 3548256, 3548737, 3548768, - 3549697, 3549792, 3549857, 3549888, 3550337, 3550464, 3550721, 3563392, 3637249, 3640672, 3640833, 3641248, - 3641345, 3641632, 3641857, 3642176, 3823619, 3824256, 3824643, 3825280, 3828739, 3829536, 3833857, 3836576, - 3836609, 3838880, 3838913, 3838976, 3839041, 3839072, 3839137, 3839200, 3839265, 3839392, 3839425, 3839808, - 3839841, 3839872, 3839905, 3840128, 3840161, 3842240, 3842273, 3842400, 3842465, 3842720, 3842753, 3842976, - 3843009, 3843904, 3843937, 3844064, 3844097, 3844256, 3844289, 3844320, 3844417, 3844640, 3844673, 3855552, - 3855617, 3856416, 3856449, 3857248, 3857281, 3858272, 3858305, 3859104, 3859137, 3860128, 3860161, 3860960, - 3860993, 3861984, 3862017, 3862816, 3862849, 3863840, 3863873, 3864672, 3864705, 3864960, 3865026, 3866624, - 3923969, 3924960, 3925153, 3925344, 3933697, 3935680, 3940353, 3941792, 3942113, 3942336, 3942402, 3942720, - 3942849, 3942880, 3953153, 3954112, 3954689, 3956096, 3956226, 3956544, 3971585, 3972480, 3972610, 3972928, - 3996673, 3996896, 3996929, 3997056, 3997089, 3997152, 3997185, 3997664, 3997697, 4004000, 4004067, 4004352, - 4005889, 4008064, 4008289, 4008320, 4008450, 4008768, 4034083, 4035968, 4036003, 4036096, 4036131, 4036256, - 4038691, 4040128, 4040163, 4040640, 4046849, 4046976, 4047009, 4047872, 4047905, 4047968, 4048001, 4048032, - 4048097, 4048128, 4048161, 4048480, 4048513, 4048640, 4048673, 4048704, 4048737, 4048768, 4048961, 4048992, - 4049121, 4049152, 4049185, 4049216, 4049249, 4049280, 4049313, 4049408, 4049441, 4049504, 4049537, 4049568, - 4049633, 4049664, 4049697, 4049728, 4049761, 4049792, 4049825, 4049856, 4049889, 4049920, 4049953, 4050016, - 4050049, 4050080, 4050145, 4050272, 4050305, 4050528, 4050561, 4050688, 4050721, 4050848, 4050881, 4050912, - 4050945, 4051264, 4051297, 4051840, 4052001, 4052096, 4052129, 4052288, 4052321, 4052864, 4071427, 4071840, - 4161026, 4161344, 4194305, 5561344, 5562369, 5695296, 5695489, 5702592, 5702657, 5887040, 5887489, 6126624, - 6225921, 6243264, 6291457, 6449504, 6449665, 6583808, 4294967295}; + 0, 1028, 1056, 1538, 1856, 2081, 2912, 3105, 3936, 5124, 5152, 5441, + 5472, 5699, 5760, 5793, 5824, 5923, 5953, 5984, 6019, 6112, 6145, 6880, + 6913, 7904, 7937, 22592, 22721, 23104, 23553, 23712, 23937, 23968, 24001, 24032, + 28161, 28320, 28353, 28416, 28481, 28608, 28641, 28672, 28865, 28896, 28929, 29024, + 29057, 29088, 29121, 29760, 29793, 32448, 32481, 36928, 37185, 42496, 42529, 43744, + 43809, 43840, 44033, 45344, 47617, 48480, 48609, 48736, 50177, 51552, 52226, 52544, + 52673, 52736, 52769, 55936, 55969, 56000, 56481, 56544, 56769, 56834, 57153, 57248, + 57313, 57344, 57857, 57888, 57921, 58880, 59809, 62656, 63009, 63040, 63490, 63809, + 64864, 65153, 65216, 65345, 65376, 65537, 66240, 66369, 66400, 66689, 66720, 66817, + 66848, 67585, 68384, 68609, 68960, 69121, 69888, 69921, 70112, 70657, 72000, 73857, + 75584, 75681, 75712, 76289, 76320, 76545, 76864, 76994, 77312, 77345, 77856, 77985, + 78240, 78305, 78368, 78433, 79136, 79169, 79392, 79425, 79456, 79553, 79680, 79777, + 79808, 80321, 80352, 80769, 80832, 80865, 80960, 81090, 81409, 81472, 81539, 81728, + 81793, 81824, 82081, 82272, 82401, 82464, 82529, 83232, 83265, 83488, 83521, 83584, + 83617, 83680, 83713, 83776, 84769, 84896, 84929, 84960, 85186, 85504, 85569, 85664, + 86177, 86464, 86497, 86592, 86625, 87328, 87361, 87584, 87617, 87680, 87713, 87872, + 87969, 88000, 88577, 88608, 89089, 89152, 89282, 89600, 89889, 89920, 90273, 90528, + 90593, 90656, 90721, 91424, 91457, 91680, 91713, 91776, 91809, 91968, 92065, 92096, + 93057, 93120, 93153, 93248, 93378, 93696, 93729, 93763, 93952, 94305, 94336, 94369, + 94560, 94657, 94752, 94785, 94912, 95009, 95072, 95105, 95136, 95169, 95232, 95329, + 95392, 95489, 95584, 95681, 96064, 96769, 96800, 97474, 97795, 97888, 98465, 98720, + 98753, 98848, 98881, 99616, 99649, 100160, 100257, 100288, 101121, 101216, 101281, 101312, + 101377, 101440, 101570, 101888, 102147, 102368, 102401, 102432, 102561, 102816, 102849, 102944, + 102977, 103712, 103745, 104064, 104097, 104256, 104353, 104384, 105377, 105440, 105473, 105536, + 105666, 105984, 106017, 106080, 106625, 106912, 106945, 107040, 107073, 108384, 108449, 108480, + 108993, 109024, 109185, 109280, 109315, 109537, 109632, 109762, 110083, 110368, 110401, 110592, + 110753, 111328, 111425, 112192, 112225, 112512, 112545, 112576, 112641, 112864, 113858, 114176, + 114721, 116256, 116289, 116352, 116737, 116960, 117250, 117568, 118817, 118880, 118913, 118944, + 118977, 119136, 119169, 119936, 119969, 120000, 120033, 120352, 120385, 120448, 120737, 120768, + 120833, 120992, 121025, 121056, 121346, 121664, 121729, 121856, 122881, 122912, 123906, 124227, + 124544, 124929, 125184, 125217, 126368, 127233, 127392, 131073, 132448, 133089, 133122, 133440, + 133633, 133824, 133953, 134080, 134177, 134208, 134305, 134368, 134593, 134688, 134817, 135232, + 135617, 135648, 135682, 136000, 136193, 137408, 137441, 137472, 137633, 137664, 137729, 139104, + 139137, 149792, 149825, 149952, 150017, 150240, 150273, 150304, 150337, 150464, 150529, 151840, + 151873, 152000, 152065, 153120, 153153, 153280, 153345, 153568, 153601, 153632, 153665, 153792, + 153857, 154336, 154369, 156192, 156225, 156352, 156417, 158560, 159011, 159648, 159745, 160256, + 160769, 163520, 163585, 163776, 163873, 183712, 183777, 184324, 184353, 185184, 185345, 187744, + 187843, 187937, 188192, 188417, 188992, 189409, 190016, 190465, 191040, 191489, 191904, 191937, + 192032, 192513, 194176, 195297, 195328, 195457, 195488, 195586, 195904, 196099, 196416, 197122, + 197440, 197633, 200480, 200705, 200864, 200929, 202016, 202049, 202080, 202241, 204480, 204801, + 205792, 207042, 207361, 208320, 208385, 208544, 208897, 210304, 210433, 211264, 211458, 211779, + 211808, 212993, 213728, 214017, 215712, 217090, 217408, 217602, 217920, 218337, 218368, 221345, + 222848, 223393, 223648, 223746, 224064, 225377, 226336, 226753, 226818, 227137, 228544, 229377, + 230528, 231426, 231744, 231841, 231938, 232257, 233408, 233473, 233760, 233985, 235360, 235425, + 235520, 236833, 236960, 236993, 237184, 237217, 237280, 237377, 237408, 237569, 243712, 245761, + 254656, 254721, 254912, 254977, 256192, 256257, 256448, 256513, 256768, 256801, 256832, 256865, + 256896, 256929, 256960, 256993, 257984, 258049, 259744, 259777, 260000, 260033, 260064, 260161, + 260256, 260289, 260512, 260609, 260736, 260801, 260992, 261121, 261536, 261697, 261792, 261825, + 262048, 262148, 262496, 263428, 263488, 263652, 263680, 265188, 265216, 265731, 265761, 265792, + 265859, 266048, 266209, 266243, 266560, 266753, 267168, 270401, 270432, 270561, 270592, 270657, + 270976, 271009, 271040, 271137, 271296, 271489, 271520, 271553, 271584, 271617, 271648, 271681, + 271808, 271841, 272192, 272257, 272384, 272545, 272704, 272833, 272864, 272899, 274529, 274595, + 274752, 297987, 299904, 302403, 303104, 323267, 324224, 360449, 367776, 367969, 368096, 368193, + 368256, 368547, 368576, 368641, 369856, 369889, 369920, 370081, 370112, 370177, 371968, 372193, + 372224, 372737, 373472, 373761, 373984, 374017, 374240, 374273, 374496, 374529, 374752, 374785, + 375008, 375041, 375264, 375297, 375520, 375553, 375776, 378337, 378368, 393220, 393248, 393377, + 393443, 393472, 394275, 394560, 394785, 394944, 395011, 395105, 395168, 395297, 398048, 398241, + 398336, 398369, 401248, 401281, 401408, 401569, 402944, 402977, 405984, 406083, 406208, 406529, + 407552, 409089, 409600, 410627, 410944, 411907, 412160, 412195, 412672, 413699, 414016, 415267, + 415744, 425985, 636928, 638977, 1348000, 1350145, 1351616, 1351681, 1360288, 1360385, 1360898, 1361217, + 1361280, 1361921, 1363424, 1363937, 1364928, 1364993, 1367235, 1367552, 1368801, 1369088, 1369153, 1372448, + 1372513, 1374560, 1374721, 1374784, 1374817, 1374848, 1374881, 1375040, 1375809, 1376320, 1376353, 1376448, + 1376481, 1376608, 1376641, 1377376, 1377795, 1377984, 1378305, 1379968, 1380417, 1382016, 1382914, 1383232, + 1384001, 1384192, 1384289, 1384320, 1384353, 1384416, 1384450, 1384769, 1385664, 1385985, 1386720, 1387521, + 1388448, 1388673, 1390176, 1391073, 1391106, 1391424, 1391617, 1391776, 1391809, 1392130, 1392449, 1392608, + 1392641, 1393952, 1394689, 1394784, 1394817, 1395072, 1395202, 1395520, 1395713, 1396448, 1396545, 1396576, + 1396673, 1398272, 1398305, 1398336, 1398433, 1398496, 1398561, 1398720, 1398785, 1398816, 1398849, 1398880, + 1399649, 1399744, 1399809, 1400160, 1400385, 1400480, 1400865, 1401056, 1401121, 1401312, 1401377, 1401568, + 1401857, 1402080, 1402113, 1402336, 1402369, 1403744, 1403777, 1404224, 1404417, 1408096, 1408514, 1408832, + 1409025, 1766528, 1766913, 1767648, 1767777, 1769344, 2039809, 2051520, 2051585, 2054976, 2056193, 2056416, + 2056801, 2056960, 2057121, 2057152, 2057185, 2057504, 2057537, 2057952, 2057985, 2058144, 2058177, 2058208, + 2058241, 2058304, 2058337, 2058400, 2058433, 2061888, 2062945, 2074560, 2075137, 2077184, 2077249, 2078976, + 2080257, 2080640, 2084353, 2084512, 2084545, 2088864, 2089474, 2089792, 2090017, 2090848, 2091041, 2091872, + 2092225, 2095072, 2095169, 2095360, 2095425, 2095616, 2095681, 2095872, 2095937, 2096032, 2097153, 2097536, + 2097569, 2098400, 2098433, 2099040, 2099073, 2099136, 2099169, 2099648, 2099713, 2100160, 2101249, 2105184, + 2105571, 2107008, 2107395, 2109216, 2109763, 2109824, 2117633, 2118560, 2118657, 2120224, 2120739, 2121600, + 2121729, 2122755, 2122880, 2123169, 2123811, 2123841, 2124099, 2124128, 2124289, 2125504, 2125825, 2126784, + 2126849, 2128000, 2128129, 2128384, 2128419, 2128576, 2129921, 2134976, 2135042, 2135360, 2135553, 2136704, + 2136833, 2137984, 2138113, 2139392, 2139649, 2141312, 2141697, 2142048, 2142081, 2142560, 2142593, 2142816, + 2142849, 2142912, 2142945, 2143296, 2143329, 2143808, 2143841, 2144064, 2144097, 2144160, 2146305, 2156256, + 2156545, 2157248, 2157569, 2157824, 2158593, 2158784, 2158817, 2160160, 2160193, 2160480, 2162689, 2162880, + 2162945, 2162976, 2163009, 2164416, 2164449, 2164512, 2164609, 2164640, 2164705, 2165440, 2165507, 2165761, + 2166496, 2166563, 2166785, 2167776, 2168035, 2168320, 2169857, 2170464, 2170497, 2170560, 2170723, 2170881, + 2171587, 2171776, 2171905, 2172736, 2174977, 2176768, 2176899, 2176961, 2177027, 2177536, 2177603, 2179073, + 2179104, 2179585, 2179712, 2179745, 2179840, 2179873, 2180800, 2181123, 2181408, 2182145, 2183075, 2183136, + 2183169, 2184099, 2184192, 2185217, 2185472, 2185505, 2186400, 2186595, 2186752, 2187265, 2188992, 2189313, + 2190016, 2190083, 2190337, 2190944, 2191107, 2191361, 2191936, 2192675, 2192896, 2195457, 2197792, 2199553, + 2201184, 2201601, 2203232, 2203459, 2203649, 2204800, 2205186, 2205504, 2214915, 2215904, 2215937, 2217280, + 2217473, 2217536, 2220033, 2220963, 2221281, 2221312, 2221569, 2222272, 2222627, 2222752, 2223617, 2224192, + 2225665, 2226339, 2226560, 2227201, 2227936, 2228321, 2230016, 2230851, 2231490, 2231808, 2231841, 2231904, + 2231969, 2232000, 2232417, 2233856, 2234881, 2235680, 2235906, 2236224, 2236513, 2237664, 2238146, 2238464, + 2238593, 2238624, 2238689, 2238720, 2238977, 2240096, 2240193, 2240224, 2240609, 2242144, 2242593, 2242720, + 2243074, 2243393, 2243424, 2243457, 2243488, 2243619, 2244256, 2244609, 2245184, 2245217, 2246016, 2246625, + 2246688, 2248705, 2248928, 2248961, 2248992, 2249025, 2249152, 2249185, 2249664, 2249697, 2250016, 2250241, + 2251744, 2252290, 2252608, 2252961, 2253216, 2253281, 2253344, 2253409, 2254112, 2254145, 2254368, 2254401, + 2254464, 2254497, 2254656, 2254753, 2254784, 2255361, 2255392, 2255777, 2255936, 2260993, 2262688, 2263265, + 2263392, 2263554, 2263872, 2264033, 2264128, 2265089, 2266624, 2267265, 2267328, 2267361, 2267392, 2267650, + 2267968, 2273281, 2274784, 2276097, 2276224, 2277377, 2278912, 2279553, 2279584, 2279938, 2280256, 2281473, + 2282848, 2283265, 2283296, 2283522, 2283840, 2285569, 2286432, 2287106, 2287427, 2287488, 2287617, 2287840, + 2293761, 2295168, 2298881, 2300930, 2301251, 2301536, 2301921, 2302176, 2302241, 2302272, 2302337, 2302592, + 2302625, 2302688, 2302721, 2303488, 2303969, 2304000, 2304033, 2304064, 2304514, 2304832, 2307073, 2307328, + 2307393, 2308640, 2309153, 2309184, 2309217, 2309248, 2310145, 2310176, 2310497, 2311776, 2312001, 2312032, + 2312705, 2312736, 2313089, 2314560, 2315169, 2315200, 2315777, 2318112, 2326529, 2326816, 2326849, 2328032, + 2328577, 2328608, 2329090, 2329411, 2330016, 2330177, 2331136, 2334721, 2334944, 2334977, 2335040, 2335073, + 2336288, 2336961, 2336992, 2337282, 2337600, 2337793, 2337984, 2338017, 2338080, 2338113, 2339136, 2339585, + 2339616, 2339842, 2340160, 2350081, 2350688, 2351169, 2351200, 2351233, 2351648, 2351681, 2352768, 2353666, + 2353984, 2356737, 2356768, 2357251, 2357920, 2359297, 2388800, 2392067, 2395616, 2396161, 2402432, 2486785, + 2489888, 2490369, 2524672, 2525217, 2525408, 2654209, 2672864, 2949121, 2967328, 2967553, 2968544, 2968578, + 2968896, 2969089, 2971616, 2971650, 2971968, 2972161, 2973120, 2973697, 2975232, 2975745, 2975872, 2976258, + 2976576, 2976611, 2976832, 2976865, 2977536, 2977697, 2978304, 3000321, 3002371, 3003104, 3006465, 3008864, + 3009025, 3009056, 3011169, 3011584, 3013633, 3013696, 3013729, 3013760, 3014657, 3211008, 3211265, 3250880, + 3252225, 3252512, 3538433, 3538560, 3538593, 3538816, 3538849, 3538912, 3538945, 3548256, 3548737, 3548768, + 3549697, 3549792, 3549857, 3549888, 3550337, 3550464, 3550721, 3563392, 3637249, 3640672, 3640833, 3641248, + 3641345, 3641632, 3641857, 3642176, 3823619, 3824256, 3824643, 3825280, 3828739, 3829536, 3833857, 3836576, + 3836609, 3838880, 3838913, 3838976, 3839041, 3839072, 3839137, 3839200, 3839265, 3839392, 3839425, 3839808, + 3839841, 3839872, 3839905, 3840128, 3840161, 3842240, 3842273, 3842400, 3842465, 3842720, 3842753, 3842976, + 3843009, 3843904, 3843937, 3844064, 3844097, 3844256, 3844289, 3844320, 3844417, 3844640, 3844673, 3855552, + 3855617, 3856416, 3856449, 3857248, 3857281, 3858272, 3858305, 3859104, 3859137, 3860128, 3860161, 3860960, + 3860993, 3861984, 3862017, 3862816, 3862849, 3863840, 3863873, 3864672, 3864705, 3864960, 3865026, 3866624, + 3923969, 3924960, 3925153, 3925344, 3933697, 3935680, 3940353, 3941792, 3942113, 3942336, 3942402, 3942720, + 3942849, 3942880, 3953153, 3954112, 3954689, 3956096, 3956226, 3956544, 3971585, 3972480, 3972610, 3972928, + 3996673, 3996896, 3996929, 3997056, 3997089, 3997152, 3997185, 3997664, 3997697, 4004000, 4004067, 4004352, + 4005889, 4008064, 4008289, 4008320, 4008450, 4008768, 4034083, 4035968, 4036003, 4036096, 4036131, 4036256, + 4038691, 4040128, 4040163, 4040640, 4046849, 4046976, 4047009, 4047872, 4047905, 4047968, 4048001, 4048032, + 4048097, 4048128, 4048161, 4048480, 4048513, 4048640, 4048673, 4048704, 4048737, 4048768, 4048961, 4048992, + 4049121, 4049152, 4049185, 4049216, 4049249, 4049280, 4049313, 4049408, 4049441, 4049504, 4049537, 4049568, + 4049633, 4049664, 4049697, 4049728, 4049761, 4049792, 4049825, 4049856, 4049889, 4049920, 4049953, 4050016, + 4050049, 4050080, 4050145, 4050272, 4050305, 4050528, 4050561, 4050688, 4050721, 4050848, 4050881, 4050912, + 4050945, 4051264, 4051297, 4051840, 4052001, 4052096, 4052129, 4052288, 4052321, 4052864, 4071427, 4071840, + 4161026, 4161344, 4194305, 5561344, 5562369, 5695296, 5695489, 5702592, 5702657, 5887040, 5887489, 6126624, + 6127105, 6147008, 6225921, 6243264, 6291457, 6449504, 6449665, 6583808, 4294967295}; static const uint16 unicode_simple_category_jump_pos[] = { 1, 9, 27, 27, 27, 27, 36, 44, 55, 55, 57, 63, 68, 75, 86, 91, 102, 114, 119, @@ -198,8 +198,8 @@ static const uint16 unicode_simple_category_jump_pos[] = { 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1428, 1429, 1432, 1432, 1434, 1435, 1442, 1442, 1442, 1448, 1448, 1448, 1448, 1452, 1452, 1452, 1452, 1452, 1452, 1461, 1461, 1465, 1470, 1470, 1470, 1470, 1470, 1470, 1471, 1476, 1480, 1481, 1537, 1546, 1546, 1546, 1546, 1547, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, - 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1551, 1563, - 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566}; + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1550, 1551, 1565, + 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568, 1568}; static const char *unicode_simple_category_table = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" @@ -362,62 +362,63 @@ static const int32 prepare_search_character_ranges[] = { 8032, -8033, 8040, -8033, 8048, -8049, 8072, -8065, 8080, -8081, 8088, -8081, 8096, -8097, 8104, -8097, 8112, -8113, 8120, -8113, 8122, -8049, 8124, 8115, 8125, 32, 8126, 953, 8127, 32, 8130, -8131, 8136, -8051, 8140, 8131, - 8141, 32, 8144, -8145, 8152, -8145, 8154, -8055, 8156, 8156, 8157, 32, - 8160, -8161, 8168, -8161, 8170, -8059, 8172, 8165, 8173, 32, 8176, -8177, - 8184, -8057, 8186, -8061, 8188, 8179, 8189, 32, 8191, 8191, 8192, 32, - 8203, 0, 8208, 32, 8234, 0, 8239, 32, 8288, 0, 8293, 8293, - 8294, 0, 8304, -8305, 8314, 32, 8319, -8320, 8330, 32, 8335, -8336, - 8352, 32, 8385, -8386, 8400, 0, 8433, -8434, 8448, 32, 8450, 99, - 8452, 32, 8455, 603, 8456, 32, 8457, 102, 8458, 8458, 8459, 104, - 8462, -8463, 8464, 105, 8466, 108, 8467, 8467, 8468, 32, 8469, 110, - 8470, 32, 8473, -113, 8476, 114, 8478, 32, 8484, 122, 8485, 32, - 8486, 969, 8487, 32, 8488, 122, 8489, 32, 8490, 107, 8491, 229, - 8492, -99, 8494, 32, 8495, 8495, 8496, -102, 8498, 8526, 8499, 109, - 8500, -8501, 8506, 32, 8508, -8509, 8510, 947, 8511, 960, 8512, 32, - 8517, 100, 8518, -8519, 8522, 32, 8526, 8526, 8527, 32, 8528, -8529, - 8544, -8561, 8560, -8561, 8579, 8580, 8581, -8582, 8586, 32, 8588, -8589, - 8592, 32, 9255, -9256, 9280, 32, 9291, -9292, 9372, 32, 9398, -9425, - 9424, -9425, 9472, 32, 10102, -10103, 10132, 32, 11124, -11125, 11126, 32, - 11158, 11158, 11159, 32, 11264, -11313, 11312, -11313, 11360, 11361, 11362, 619, - 11363, 7549, 11364, 637, 11365, -11366, 11367, 11368, 11369, 11370, 11371, 11372, - 11373, 593, 11374, 625, 11375, 592, 11376, 594, 11377, 2097153, 11380, 11380, - 11381, 11382, 11383, -11384, 11389, 118, 11390, -576, 11392, 2097153, 11492, 11492, - 11493, 32, 11499, 11500, 11501, 11502, 11503, 0, 11506, 11507, 11508, -11509, - 11513, 32, 11517, 11517, 11518, 32, 11520, -11521, 11632, 32, 11633, -11634, - 11647, 0, 11648, -11649, 11744, 0, 11776, 32, 11823, 11823, 11824, 32, - 11870, -11871, 11904, 32, 11930, 11930, 11931, 32, 11935, 11935, 11936, 32, - 12019, -12020, 12272, 32, 12284, -12285, 12288, 32, 12293, -12294, 12296, 32, - 12321, -12322, 12330, 0, 12336, 32, 12337, -12338, 12342, 32, 12344, -12345, - 12349, 32, 12352, -12353, 12441, 0, 12443, 32, 12445, -12446, 12448, 32, - 12449, -12450, 12539, 32, 12540, 0, 12541, -12542, 12688, 32, 12690, -12691, - 12736, 32, 12772, -12773, 12800, 32, 12831, -12832, 12842, 32, 12868, -12869, - 12880, 32, 12881, -12882, 12910, 32, 12928, -12929, 12992, 32, 13008, -13009, - 13055, 32, 13312, -13313, 19904, 32, 19968, -19969, 42128, 32, 42183, -42184, - 42238, 32, 42240, -42241, 42509, 32, 42512, -42513, 42560, 2097153, 42606, 42606, - 42607, 0, 42611, 32, 42612, 0, 42622, 32, 42623, 2097153, 42652, -42653, - 42654, 0, 42656, -42657, 42736, 0, 42738, 32, 42744, -42745, 42752, 32, - 42775, -42776, 42784, 32, 42786, 2097153, 42800, -42801, 42802, 2097153, 42864, -42865, - 42873, 42874, 42875, 42876, 42877, 7545, 42878, 2097153, 42888, 42888, 42889, 32, - 42891, 42892, 42893, 613, 42894, -42895, 42896, 2097153, 42900, -42901, 42902, 2097153, - 42922, 614, 42923, 604, 42924, 609, 42925, 620, 42926, 618, 42927, 42927, - 42928, 670, 42929, 647, 42930, 669, 42931, 43859, 42932, 2097153, 42948, 42900, - 42949, 642, 42950, 7566, 42951, 42952, 42953, 42954, 42955, -42956, 42960, 42961, - 42962, -42963, 42966, 2097153, 42970, -42971, 42994, 99, 42995, 102, 42996, 113, - 42997, 42998, 42999, 42999, 43000, 295, 43001, -43002, 43010, 0, 43011, -43012, - 43014, 0, 43015, -43016, 43019, 0, 43020, -43021, 43043, 0, 43048, 32, - 43052, 0, 43053, -43054, 43062, 32, 43066, -43067, 43124, 32, 43128, -43129, - 43136, 0, 43138, -43139, 43188, 0, 43206, -43207, 43214, 32, 43216, -43217, - 43232, 0, 43250, -43251, 43256, 32, 43259, 43259, 43260, 32, 43261, -43262, - 43263, 0, 43264, -43265, 43302, 0, 43310, 32, 43312, -43313, 43335, 0, - 43348, -43349, 43359, 32, 43360, -43361, 43392, 0, 43396, -43397, 43443, 0, - 43457, 32, 43470, -43471, 43486, 32, 43488, -43489, 43493, 0, 43494, -43495, - 43561, 0, 43575, -43576, 43587, 0, 43588, -43589, 43596, 0, 43598, -43599, - 43612, 32, 43616, -43617, 43639, 32, 43642, 43642, 43643, 0, 43646, -43647, - 43696, 0, 43697, 43697, 43698, 0, 43701, -43702, 43703, 0, 43705, -43706, - 43710, 0, 43712, 43712, 43713, 0, 43714, -43715, 43742, 32, 43744, -43745, - 43755, 0, 43760, 32, 43762, -43763, 43765, 0, 43767, -43768, 43867, 32, - 43868, -43869, 43882, 32, 43884, -43885, 43888, -5025, 43968, -43969, 44003, 0, - 44011, 32, 44012, 0, 44014, -44015, 55296, 0, 57344, -57345, 64286, 0, + 8141, 32, 8144, -8145, 8147, 912, 8148, -8149, 8152, -8145, 8154, -8055, + 8156, 8156, 8157, 32, 8160, -8161, 8163, 944, 8164, -8165, 8168, -8161, + 8170, -8059, 8172, 8165, 8173, 32, 8176, -8177, 8184, -8057, 8186, -8061, + 8188, 8179, 8189, 32, 8191, 8191, 8192, 32, 8203, 0, 8208, 32, + 8234, 0, 8239, 32, 8288, 0, 8293, 8293, 8294, 0, 8304, -8305, + 8314, 32, 8319, -8320, 8330, 32, 8335, -8336, 8352, 32, 8385, -8386, + 8400, 0, 8433, -8434, 8448, 32, 8450, 99, 8452, 32, 8455, 603, + 8456, 32, 8457, 102, 8458, 8458, 8459, 104, 8462, -8463, 8464, 105, + 8466, 108, 8467, 8467, 8468, 32, 8469, 110, 8470, 32, 8473, -113, + 8476, 114, 8478, 32, 8484, 122, 8485, 32, 8486, 969, 8487, 32, + 8488, 122, 8489, 32, 8490, 107, 8491, 229, 8492, -99, 8494, 32, + 8495, 8495, 8496, -102, 8498, 8526, 8499, 109, 8500, -8501, 8506, 32, + 8508, -8509, 8510, 947, 8511, 960, 8512, 32, 8517, 100, 8518, -8519, + 8522, 32, 8526, 8526, 8527, 32, 8528, -8529, 8544, -8561, 8560, -8561, + 8579, 8580, 8581, -8582, 8586, 32, 8588, -8589, 8592, 32, 9255, -9256, + 9280, 32, 9291, -9292, 9372, 32, 9398, -9425, 9424, -9425, 9472, 32, + 10102, -10103, 10132, 32, 11124, -11125, 11126, 32, 11158, 11158, 11159, 32, + 11264, -11313, 11312, -11313, 11360, 11361, 11362, 619, 11363, 7549, 11364, 637, + 11365, -11366, 11367, 11368, 11369, 11370, 11371, 11372, 11373, 593, 11374, 625, + 11375, 592, 11376, 594, 11377, 2097153, 11380, 11380, 11381, 11382, 11383, -11384, + 11389, 118, 11390, -576, 11392, 2097153, 11492, 11492, 11493, 32, 11499, 11500, + 11501, 11502, 11503, 0, 11506, 11507, 11508, -11509, 11513, 32, 11517, 11517, + 11518, 32, 11520, -11521, 11632, 32, 11633, -11634, 11647, 0, 11648, -11649, + 11744, 0, 11776, 32, 11823, 11823, 11824, 32, 11870, -11871, 11904, 32, + 11930, 11930, 11931, 32, 11935, 11935, 11936, 32, 12019, -12020, 12272, 32, + 12293, -12294, 12296, 32, 12321, -12322, 12330, 0, 12336, 32, 12337, -12338, + 12342, 32, 12344, -12345, 12349, 32, 12352, -12353, 12441, 0, 12443, 32, + 12445, -12446, 12448, 32, 12449, -12450, 12539, 32, 12540, 0, 12541, -12542, + 12688, 32, 12690, -12691, 12736, 32, 12772, -12773, 12783, 32, 12784, -12785, + 12800, 32, 12831, -12832, 12842, 32, 12868, -12869, 12880, 32, 12881, -12882, + 12910, 32, 12928, -12929, 12992, 32, 13008, -13009, 13055, 32, 13312, -13313, + 19904, 32, 19968, -19969, 42128, 32, 42183, -42184, 42238, 32, 42240, -42241, + 42509, 32, 42512, -42513, 42560, 2097153, 42606, 42606, 42607, 0, 42611, 32, + 42612, 0, 42622, 32, 42623, 2097153, 42652, -42653, 42654, 0, 42656, -42657, + 42736, 0, 42738, 32, 42744, -42745, 42752, 32, 42775, -42776, 42784, 32, + 42786, 2097153, 42800, -42801, 42802, 2097153, 42864, -42865, 42873, 42874, 42875, 42876, + 42877, 7545, 42878, 2097153, 42888, 42888, 42889, 32, 42891, 42892, 42893, 613, + 42894, -42895, 42896, 2097153, 42900, -42901, 42902, 2097153, 42922, 614, 42923, 604, + 42924, 609, 42925, 620, 42926, 618, 42927, 42927, 42928, 670, 42929, 647, + 42930, 669, 42931, 43859, 42932, 2097153, 42948, 42900, 42949, 642, 42950, 7566, + 42951, 42952, 42953, 42954, 42955, -42956, 42960, 42961, 42962, -42963, 42966, 2097153, + 42970, -42971, 42994, 99, 42995, 102, 42996, 113, 42997, 42998, 42999, 42999, + 43000, 295, 43001, -43002, 43010, 0, 43011, -43012, 43014, 0, 43015, -43016, + 43019, 0, 43020, -43021, 43043, 0, 43048, 32, 43052, 0, 43053, -43054, + 43062, 32, 43066, -43067, 43124, 32, 43128, -43129, 43136, 0, 43138, -43139, + 43188, 0, 43206, -43207, 43214, 32, 43216, -43217, 43232, 0, 43250, -43251, + 43256, 32, 43259, 43259, 43260, 32, 43261, -43262, 43263, 0, 43264, -43265, + 43302, 0, 43310, 32, 43312, -43313, 43335, 0, 43348, -43349, 43359, 32, + 43360, -43361, 43392, 0, 43396, -43397, 43443, 0, 43457, 32, 43470, -43471, + 43486, 32, 43488, -43489, 43493, 0, 43494, -43495, 43561, 0, 43575, -43576, + 43587, 0, 43588, -43589, 43596, 0, 43598, -43599, 43612, 32, 43616, -43617, + 43639, 32, 43642, 43642, 43643, 0, 43646, -43647, 43696, 0, 43697, 43697, + 43698, 0, 43701, -43702, 43703, 0, 43705, -43706, 43710, 0, 43712, 43712, + 43713, 0, 43714, -43715, 43742, 32, 43744, -43745, 43755, 0, 43760, 32, + 43762, -43763, 43765, 0, 43767, -43768, 43867, 32, 43868, -43869, 43882, 32, + 43884, -43885, 43888, -5025, 43968, -43969, 44003, 0, 44011, 32, 44012, 0, + 44014, -44015, 55296, 0, 57344, -57345, 64261, 64262, 64263, -64264, 64286, 0, 64287, -64288, 64297, 32, 64298, -64299, 64434, 32, 64451, -64452, 64830, 32, 64848, -64849, 64975, 32, 65008, -65009, 65020, 32, 65024, 0, 65040, 32, 65050, -65051, 65056, 0, 65072, 32, 65107, 65107, 65108, 32, 65127, 65127, diff --git a/protocols/Telegram/tdlib/td/tdutils/test/ChainScheduler.cpp b/protocols/Telegram/tdlib/td/tdutils/test/ChainScheduler.cpp index 029a4ff366..f93a718138 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/ChainScheduler.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/ChainScheduler.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -116,7 +116,7 @@ TEST(ChainScheduler, Stress) { td::vector<QueryWithParents> active_queries; td::ChainScheduler<QueryPtr> scheduler; - td::vector<td::vector<QueryPtr>> chains(ChainsN); + td::vector<td::vector<QueryPtr>> chains(ChainsN + 1); int inflight_queries{}; int current_query_id{}; int sent_cnt{}; @@ -138,7 +138,7 @@ TEST(ChainScheduler, Stress) { query->id = query_id; int chain_n = rnd.fast(1, ChainsN); td::vector<ChainId> chain_ids(ChainsN); - std::iota(chain_ids.begin(), chain_ids.end(), 0); + std::iota(chain_ids.begin(), chain_ids.end(), 1); td::rand_shuffle(td::as_mutable_span(chain_ids), rnd); chain_ids.resize(chain_n); for (auto chain_id : chain_ids) { @@ -151,7 +151,7 @@ TEST(ChainScheduler, Stress) { }; auto check_parents_ok = [&](const QueryWithParents &query_with_parents) -> bool { - return td::all_of(query_with_parents.parents, [](auto &parent) { return parent->is_ok; }); + return td::all_of(query_with_parents.parents, [](const auto &parent) { return parent->is_ok; }); }; auto to_query_ptr = [&](TaskId task_id) { diff --git a/protocols/Telegram/tdlib/td/tdutils/test/ConcurrentHashMap.cpp b/protocols/Telegram/tdlib/td/tdutils/test/ConcurrentHashMap.cpp index 5ab1f85ad2..7fbe25d0d7 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/ConcurrentHashMap.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/ConcurrentHashMap.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -40,10 +40,6 @@ class ArrayHashMap { public: explicit ArrayHashMap(std::size_t n) : array_(n) { } - struct Node { - std::atomic<KeyT> key{KeyT{}}; - std::atomic<ValueT> value{ValueT{}}; - }; static td::string get_name() { return "ArrayHashMap"; } @@ -201,21 +197,23 @@ class HashMapBenchmark final : public td::Benchmark { void run(int n) final { n = n_; - td::vector<td::thread> threads; - - for (std::size_t i = 0; i < threads_n; i++) { - std::size_t l = n * i / threads_n; - std::size_t r = n * (i + 1) / threads_n; - threads.emplace_back([l, r, this] { - for (size_t i = l; i < r; i++) { - auto x = td::narrow_cast<int>((i + 1) * MUL % n_) + 3; - auto y = td::narrow_cast<int>(i + 2); - hash_map->insert(x, y); - } - }); - } - for (auto &thread : threads) { - thread.join(); + for (int count = 0; count < 1000; count++) { + td::vector<td::thread> threads; + + for (std::size_t i = 0; i < threads_n; i++) { + std::size_t l = n * i / threads_n; + std::size_t r = n * (i + 1) / threads_n; + threads.emplace_back([l, r, this] { + for (size_t i = l; i < r; i++) { + auto x = td::narrow_cast<int>((i + 1) * MUL % n_) + 3; + auto y = td::narrow_cast<int>(i + 2); + hash_map->insert(x, y); + } + }); + } + for (auto &thread : threads) { + thread.join(); + } } } diff --git a/protocols/Telegram/tdlib/td/tdutils/test/MpmcWaiter.cpp b/protocols/Telegram/tdlib/td/tdutils/test/MpmcWaiter.cpp index 9bdabfac57..2040b85225 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/MpmcWaiter.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/MpmcWaiter.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -66,6 +66,7 @@ TEST(MpmcEagerWaiter, stress_one_one) { } TEST(MpmcSleepyWaiter, stress_one_one) { + return; // the test hangs sometimes; run with --filter MpmcSleepyWaiter_stress_one_one --stress to reproduce test_waiter_stress_one_one<td::MpmcSleepyWaiter>(); } diff --git a/protocols/Telegram/tdlib/td/tdutils/test/StealingQueue.cpp b/protocols/Telegram/tdlib/td/tdutils/test/StealingQueue.cpp index c0ccabf793..0a2f0d083a 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/StealingQueue.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/StealingQueue.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -108,7 +108,7 @@ TEST(AtomicRead, simple2) { TEST(StealingQueue, simple) { td::uint64 sum = 0; - std::atomic<td::uint64> got_sum{0}; + std::atomic<td::uint64> check_sum{0}; td::Stage run; td::Stage check; @@ -138,10 +138,10 @@ TEST(StealingQueue, simple) { sum += x_sum[x]; gq.push(x, id); } - got_sum = 0; + check_sum = 0; } run.wait(round * threads_n); - while (got_sum.load() != sum) { + while (check_sum.load() != sum) { auto x = [&] { int res; if (lq[id].local_pop(res)) { @@ -159,8 +159,8 @@ TEST(StealingQueue, simple) { if (x == 0) { continue; } - //LOG(ERROR) << x << " " << got_sum.load() << " " << sum; - got_sum.fetch_add(x, std::memory_order_relaxed); + //LOG(ERROR) << x << " " << check_sum.load() << " " << sum; + check_sum.fetch_add(x, std::memory_order_relaxed); lq[id].local_push(x - 1, [&](auto y) { //LOG(ERROR) << "OVERFLOW"; gq.push(y, id); diff --git a/protocols/Telegram/tdlib/td/tdutils/test/hashset_benchmark.cpp b/protocols/Telegram/tdlib/td/tdutils/test/hashset_benchmark.cpp index dbfcaa992b..35e1ae5a5e 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/hashset_benchmark.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/hashset_benchmark.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -590,7 +590,7 @@ BENCHMARK_TEMPLATE(BM_mask, td::MaskSse2); #endif template <class KeyT, class ValueT, class HashT = td::Hash<KeyT>, class EqT = std::equal_to<KeyT>> -using FlatHashMapImpl = td::FlatHashTable<td::MapNode<KeyT, ValueT>, HashT, EqT>; +using FlatHashMapImpl = td::FlatHashTable<td::MapNode<KeyT, ValueT, EqT>, HashT, EqT>; #define FOR_EACH_TABLE(F) \ F(FlatHashMapImpl) \ diff --git a/protocols/Telegram/tdlib/td/tdutils/test/json.cpp b/protocols/Telegram/tdlib/td/tdutils/test/json.cpp index 8b42751a3d..928dea80eb 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/json.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/json.cpp @@ -1,12 +1,14 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // +#include "td/utils/benchmark.h" #include "td/utils/common.h" #include "td/utils/JsonBuilder.h" #include "td/utils/logging.h" +#include "td/utils/Parser.h" #include "td/utils/Slice.h" #include "td/utils/StringBuilder.h" #include "td/utils/tests.h" @@ -89,3 +91,210 @@ TEST(JSON, kphp) { "{\"keyboard\":[[\"\\u2022 abcdefg\"],[\"\\u2022 hijklmnop\"],[\"\\u2022 " "qrstuvwxyz\"]],\"one_time_keyboard\":true}"); } + +TEST(JSON, json_object_get_field) { + const td::string encoded_object = + "{\"null\":null,\"bool\":true,\"int\":\"1\",\"int2\":2,\"long\":\"123456789012\",\"long2\":2123456789012," + "\"double\":12345678901.1,\"string\":\"string\",\"string2\":12345e+1,\"array\":[],\"object\":{}}"; + { + td::string encoded_object_copy = encoded_object; + auto value = td::json_decode(encoded_object_copy).move_as_ok(); + auto &object = value.get_object(); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("null")), "null"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("bool")), "true"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("bool")), "null"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int")), "\"1\""); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int2")), "2"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("int3")), "null"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("long")), "\"123456789012\""); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("long2")), "2123456789012"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("double")), "12345678901.1"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("string")), "\"string\""); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("string2")), "12345e+1"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("array")), "[]"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("object")), "{}"); + ASSERT_EQ(td::json_encode<td::string>(object.extract_field("")), "null"); + } + + { + td::string encoded_object_copy = encoded_object; + auto value = td::json_decode(encoded_object_copy).move_as_ok(); + auto &object = value.get_object(); + ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_optional_field("int2", td::JsonValue::Type::Number).is_ok()); + ASSERT_TRUE(object.extract_optional_field("int2", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_optional_field("int3", td::JsonValue::Type::Number).is_ok()); + ASSERT_TRUE(object.extract_optional_field("int3", td::JsonValue::Type::Null).is_ok()); + ASSERT_EQ(object.extract_optional_field("int", td::JsonValue::Type::String).ok().get_string(), "1"); + ASSERT_TRUE(object.extract_optional_field("int", td::JsonValue::Type::Number).is_error()); + ASSERT_EQ(object.extract_optional_field("int", td::JsonValue::Type::Null).ok().type(), td::JsonValue::Type::Null); + + ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_required_field("long2", td::JsonValue::Type::Number).is_ok()); + ASSERT_TRUE(object.extract_required_field("long2", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_required_field("long3", td::JsonValue::Type::Number).is_error()); + ASSERT_TRUE(object.extract_required_field("long3", td::JsonValue::Type::Null).is_error()); + ASSERT_EQ(object.extract_required_field("long", td::JsonValue::Type::String).ok().get_string(), "123456789012"); + ASSERT_TRUE(object.extract_required_field("long", td::JsonValue::Type::Number).is_error()); + ASSERT_EQ(object.extract_required_field("long", td::JsonValue::Type::Null).ok().type(), td::JsonValue::Type::Null); + } + + td::string encoded_object_copy = encoded_object; + auto value = td::json_decode(encoded_object_copy).move_as_ok(); + const auto &object = value.get_object(); + ASSERT_TRUE(object.has_field("null")); + ASSERT_TRUE(object.has_field("object")); + ASSERT_TRUE(!object.has_field("")); + ASSERT_TRUE(!object.has_field("objec")); + ASSERT_TRUE(!object.has_field("object2")); + + ASSERT_TRUE(object.get_optional_bool_field("int").is_error()); + ASSERT_EQ(object.get_optional_bool_field("bool").ok(), true); + ASSERT_EQ(object.get_optional_bool_field("bool", false).ok(), true); + ASSERT_EQ(object.get_required_bool_field("bool").ok(), true); + ASSERT_EQ(object.get_optional_bool_field("bool3").ok(), false); + ASSERT_EQ(object.get_optional_bool_field("bool4", true).ok(), true); + ASSERT_TRUE(object.get_required_bool_field("bool5").is_error()); + + ASSERT_TRUE(object.get_optional_int_field("null").is_error()); + ASSERT_EQ(object.get_optional_int_field("int").ok(), 1); + ASSERT_EQ(object.get_optional_int_field("int").ok(), 1); + ASSERT_EQ(object.get_required_int_field("int").ok(), 1); + ASSERT_EQ(object.get_optional_int_field("int2").ok(), 2); + ASSERT_EQ(object.get_optional_int_field("int2").ok(), 2); + ASSERT_EQ(object.get_required_int_field("int2").ok(), 2); + ASSERT_EQ(object.get_optional_int_field("int3").ok(), 0); + ASSERT_EQ(object.get_optional_int_field("int4", 5).ok(), 5); + ASSERT_TRUE(object.get_required_int_field("int5").is_error()); + ASSERT_EQ(object.get_optional_int_field("long").is_error(), true); + ASSERT_EQ(object.get_optional_int_field("long2").is_error(), true); + + ASSERT_TRUE(object.get_optional_long_field("null").is_error()); + ASSERT_EQ(object.get_optional_long_field("long").ok(), 123456789012); + ASSERT_EQ(object.get_optional_long_field("long").ok(), 123456789012); + ASSERT_EQ(object.get_required_long_field("long").ok(), 123456789012); + ASSERT_EQ(object.get_optional_long_field("long2").ok(), 2123456789012); + ASSERT_EQ(object.get_optional_long_field("long2").ok(), 2123456789012); + ASSERT_EQ(object.get_required_long_field("long2").ok(), 2123456789012); + ASSERT_EQ(object.get_optional_long_field("long3").ok(), 0); + ASSERT_EQ(object.get_optional_long_field("long4", 5).ok(), 5); + ASSERT_TRUE(object.get_required_long_field("long5").is_error()); + ASSERT_EQ(object.get_optional_long_field("int").ok(), 1); + ASSERT_EQ(object.get_optional_long_field("int2").ok(), 2); + + auto are_equal_double = [](double lhs, double rhs) { + return rhs - 1e-3 < lhs && lhs < rhs + 1e-3; + }; + + ASSERT_TRUE(object.get_optional_double_field("null").is_error()); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double").ok(), 12345678901.1)); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double").ok(), 12345678901.1)); + ASSERT_TRUE(are_equal_double(object.get_required_double_field("double").ok(), 12345678901.1)); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("long2").ok(), 2123456789012.0)); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("long2").ok(), 2123456789012.0)); + ASSERT_TRUE(are_equal_double(object.get_required_double_field("long2").ok(), 2123456789012.0)); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double3").ok(), 0.0)); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("double4", -5.23).ok(), -5.23)); + ASSERT_TRUE(object.get_required_double_field("double5").is_error()); + ASSERT_TRUE(object.get_optional_double_field("int").is_error()); + ASSERT_TRUE(are_equal_double(object.get_optional_double_field("int2").ok(), 2)); + + ASSERT_TRUE(object.get_optional_string_field("null").is_error()); + ASSERT_EQ(object.get_optional_string_field("string").ok(), "string"); + ASSERT_EQ(object.get_optional_string_field("string").ok(), "string"); + ASSERT_EQ(object.get_required_string_field("string").ok(), "string"); + ASSERT_EQ(object.get_optional_string_field("string2").ok(), "12345e+1"); + ASSERT_EQ(object.get_optional_string_field("string2").ok(), "12345e+1"); + ASSERT_EQ(object.get_required_string_field("string2").ok(), "12345e+1"); + ASSERT_EQ(object.get_optional_string_field("string3").ok(), td::string()); + ASSERT_EQ(object.get_optional_string_field("string4", "abacaba").ok(), "abacaba"); + ASSERT_TRUE(object.get_required_string_field("string5").is_error()); + ASSERT_EQ(object.get_optional_string_field("int").ok(), "1"); + ASSERT_EQ(object.get_optional_string_field("int2").ok(), "2"); +} + +class JsonStringDecodeBenchmark final : public td::Benchmark { + td::string str_; + + public: + explicit JsonStringDecodeBenchmark(td::string str) : str_('"' + str + '"') { + } + + td::string get_description() const final { + return td::string("JsonStringDecodeBenchmark") + str_.substr(1, 6); + } + + void run(int n) final { + for (int i = 0; i < n; i++) { + auto str = str_; + td::Parser parser(str); + td::json_string_decode(parser).ensure(); + } + } +}; + +TEST(JSON, bench_json_string_decode) { + td::bench(JsonStringDecodeBenchmark(td::string(1000, 'a'))); + td::bench(JsonStringDecodeBenchmark(td::string(1000, '\\'))); + td::string str; + for (int i = 32; i < 128; i++) { + if (i == 'u') { + continue; + } + str += "a\\"; + str += static_cast<char>(i); + } + td::bench(JsonStringDecodeBenchmark(str)); +} + +static void test_string_decode(td::string str, const td::string &result) { + auto str_copy = str; + td::Parser skip_parser(str_copy); + auto status = td::json_string_skip(skip_parser); + ASSERT_TRUE(status.is_ok()); + ASSERT_TRUE(skip_parser.empty()); + + td::Parser parser(str); + auto r_value = td::json_string_decode(parser); + ASSERT_TRUE(r_value.is_ok()); + ASSERT_TRUE(parser.empty()); + ASSERT_EQ(result, r_value.ok()); +} + +static void test_string_decode_error(td::string str) { + auto str_copy = str; + td::Parser skip_parser(str_copy); + auto status = td::json_string_skip(skip_parser); + ASSERT_TRUE(status.is_error()); + + td::Parser parser(str); + auto r_value = td::json_string_decode(parser); + ASSERT_TRUE(r_value.is_error()); +} + +TEST(JSON, string_decode) { + test_string_decode("\"\"", ""); + test_string_decode("\"abacaba\"", "abacaba"); + test_string_decode( + "\"\\1\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u00201\\v\\w\\x\\y\\z\\U\\\"\\\\\\/\\+\\-\"", + "1a\bcde\fghijklm\nopq\rs\t 1vwxyzU\"\\/+-"); + test_string_decode("\"\\u0373\\ud7FB\\uD840\\uDC04\\uD840a\\uD840\\u0373\"", + "\xCD\xB3\xED\x9F\xBB\xF0\xA0\x80\x84\xed\xa1\x80\x61\xed\xa1\x80\xCD\xB3"); + + test_string_decode_error(" \"\""); + test_string_decode_error("\""); + test_string_decode_error("\"\\"); + test_string_decode_error("\"\\b'"); + test_string_decode_error("\"\\u\""); + test_string_decode_error("\"\\u123\""); + test_string_decode_error("\"\\u123g\""); + test_string_decode_error("\"\\u123G\""); + test_string_decode_error("\"\\u123 \""); + test_string_decode_error("\"\\ug123\""); + test_string_decode_error("\"\\uG123\""); + test_string_decode_error("\"\\u 123\""); + test_string_decode_error("\"\\uD800\\ug123\""); + test_string_decode_error("\"\\uD800\\u123\""); +} diff --git a/protocols/Telegram/tdlib/td/tdutils/test/misc.cpp b/protocols/Telegram/tdlib/td/tdutils/test/misc.cpp index e1612a9924..cabd4e6efb 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/misc.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/misc.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -7,6 +7,7 @@ #include "td/utils/algorithm.h" #include "td/utils/as.h" #include "td/utils/base64.h" +#include "td/utils/benchmark.h" #include "td/utils/BigNum.h" #include "td/utils/bits.h" #include "td/utils/CancellationToken.h" @@ -82,14 +83,11 @@ TEST(Misc, update_atime_saves_mtime) { r_file.move_as_ok().close(); auto info = td::stat(name).ok(); - td::int32 tests_ok = 0; td::int32 tests_wa = 0; for (int i = 0; i < 10000; i++) { td::update_atime(name).ensure(); auto new_info = td::stat(name).ok(); - if (info.mtime_nsec_ == new_info.mtime_nsec_) { - tests_ok++; - } else { + if (info.mtime_nsec_ != new_info.mtime_nsec_) { tests_wa++; info.mtime_nsec_ = new_info.mtime_nsec_; } @@ -265,6 +263,65 @@ TEST(Misc, base64) { ASSERT_TRUE(td::base64url_encode("ab><cd") == "YWI-PGNk"); } +static void test_zero_encode(td::Slice str, td::Slice expected_zero = td::Slice(), + td::Slice expected_zero_one = td::Slice()) { + auto encoded = td::zero_encode(str); + if (!expected_zero.empty()) { + ASSERT_EQ(encoded, expected_zero); + } + ASSERT_EQ(td::zero_decode(encoded), str); + + encoded = td::zero_one_encode(str); + if (!expected_zero_one.empty()) { + ASSERT_EQ(encoded, expected_zero_one); + } + ASSERT_EQ(td::zero_one_decode(encoded), str); +} + +TEST(Misc, zero_encode) { + td::string str; + for (unsigned char i = 1; i < 255; i++) { + str += static_cast<char>(i); + } + test_zero_encode(str, str, str); + + test_zero_encode(""); + test_zero_encode(td::Slice("\0"), td::Slice("\0\1"), td::Slice("\0\1")); + test_zero_encode(td::Slice("\0\xff\0\xff\0\xff\0\xff\0\xff\0\xff\0\xff"), + td::Slice("\0\1\xff\0\1\xff\0\1\xff\0\1\xff\0\1\xff\0\1\xff\0\1\xff"), + td::Slice("\0\1\xff\1\0\1\xff\1\0\1\xff\1\0\1\xff\1\0\1\xff\1\0\1\xff\1\0\1\xff\1")); + test_zero_encode(td::Slice("\0\0\xff\xff\0\0\xff\xff\0\0\xff\xff\0\0\xff\xff\0\0\xff\xff\0\0\xff\xff"), + td::Slice("\0\2\xff\xff\0\2\xff\xff\0\2\xff\xff\0\2\xff\xff\0\2\xff\xff\0\2\xff\xff"), + td::Slice("\0\2\xff\2\0\2\xff\2\0\2\xff\2\0\2\xff\2\0\2\xff\2\0\2\xff\2")); + test_zero_encode(td::Slice("\0\0\0\0\0\xff\xff\xff\xff\xff"), td::Slice("\0\5\xff\xff\xff\xff\xff"), + td::Slice("\0\5\xff\5")); + test_zero_encode(td::Slice( + "\0\0\0\0\0\xff\xff\xff\xff\xff\0\0\0\0\0\xff\xff\xff\xff\xff\0\0\0\0\0\xff\xff\xff\xff\xff\0\0\0\0\0\xff\xff\xff" + "\xff\xff\0\0\0\0\0\xff\xff\xff\xff\xff\0\0\0\0\0\xff\xff\xff\xff\xff\0\0\0\0\0\xff\xff\xff\xff\xff")); + test_zero_encode(td::string(1000, '\0')); + test_zero_encode(str + td::string(1000, '\0') + str + td::string(1000, '\xff') + str); +} + +class ZeroEncodeBenchmark final : public td::Benchmark { + public: + td::string get_description() const final { + return "ZeroEncodeBenchmark"; + } + + void run(int n) final { + for (int i = 0; i < n; i++) { + zero_encode( + td::Slice("\x02\x00\x00\x02\x01\x00\x00\x00\x19\x01\x00\x00\x7c\xc8\x64\xc1\x04\xec\x82\xb8\x20\x9e\xa0\x8d" + "\x1e\xbe\xb2\x79\xc4\x5a\x4c\x1e\x49\x1e\x00\x00\xa9\xa7\x31\x1b\x80\x9f\x11\x46\xfc\x97\xde\x6a" + "\x18\x6e\xc0\x73\x01\x00\x00\x00\x02\x00\x00\x00\x6d\x00\x00\x00\x30\x04")); + } + } +}; + +TEST(Misc, bench_zero_encode) { + td::bench(ZeroEncodeBenchmark()); +} + template <class T> static void test_remove_if(td::vector<int> v, const T &func, const td::vector<int> &expected) { td::remove_if(v, func); @@ -349,6 +406,49 @@ TEST(Misc, remove) { test_remove(v, 1, v); } +static void test_add_to_top(td::vector<int> v, size_t max_size, int new_value, const td::vector<int> &expected) { + auto u = v; + td::add_to_top(v, max_size, new_value); + ASSERT_EQ(expected, v); + + td::add_to_top_if(u, max_size, new_value, [new_value](int value) { return value == new_value; }); + ASSERT_EQ(expected, u); +} + +static void test_add_to_top_if(td::vector<int> v, int max_size, int new_value, const td::vector<int> &expected) { + td::add_to_top_if(v, max_size, new_value, [new_value](int value) { return value % 10 == new_value % 10; }); + ASSERT_EQ(expected, v); +} + +TEST(Misc, add_to_top) { + test_add_to_top({}, 0, 1, {1}); + test_add_to_top({}, 1, 1, {1}); + test_add_to_top({}, 6, 1, {1}); + + test_add_to_top({1, 2, 3, 4, 5, 6}, 3, 2, {2, 1, 3, 4, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 6, 1, {1, 2, 3, 4, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 7, 1, {1, 2, 3, 4, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 6, 2, {2, 1, 3, 4, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 7, 2, {2, 1, 3, 4, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 6, 4, {4, 1, 2, 3, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 7, 4, {4, 1, 2, 3, 5, 6}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 6, 6, {6, 1, 2, 3, 4, 5}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 7, 6, {6, 1, 2, 3, 4, 5}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 6, 7, {7, 1, 2, 3, 4, 5}); + test_add_to_top({1, 2, 3, 4, 5, 6}, 7, 7, {7, 1, 2, 3, 4, 5, 6}); + + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 6, 11, {1, 2, 3, 4, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 7, 21, {1, 2, 3, 4, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 6, 32, {2, 1, 3, 4, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 7, 42, {2, 1, 3, 4, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 6, 54, {4, 1, 2, 3, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 7, 64, {4, 1, 2, 3, 5, 6}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 6, 76, {6, 1, 2, 3, 4, 5}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 7, 86, {6, 1, 2, 3, 4, 5}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 6, 97, {97, 1, 2, 3, 4, 5}); + test_add_to_top_if({1, 2, 3, 4, 5, 6}, 7, 87, {87, 1, 2, 3, 4, 5, 6}); +} + static void test_unique(td::vector<int> v, const td::vector<int> &expected) { auto v_str = td::transform(v, &td::to_string<int>); auto expected_str = td::transform(expected, &td::to_string<int>); diff --git a/protocols/Telegram/tdlib/td/tdutils/test/pq.cpp b/protocols/Telegram/tdlib/td/tdutils/test/pq.cpp index 0983ea814c..b499b31e0f 100644 --- a/protocols/Telegram/tdlib/td/tdutils/test/pq.cpp +++ b/protocols/Telegram/tdlib/td/tdutils/test/pq.cpp @@ -1,5 +1,5 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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) @@ -112,8 +112,8 @@ static void test_pq_slow(td::uint64 first, td::uint64 second) { td::BigNum p_res = td::BigNum::from_binary(p_str); td::BigNum q_res = td::BigNum::from_binary(q_str); - LOG_CHECK(p_str == p.to_binary()) << td::tag("got", p_res.to_decimal()) << td::tag("expected", first); - LOG_CHECK(q_str == q.to_binary()) << td::tag("got", q_res.to_decimal()) << td::tag("expected", second); + LOG_CHECK(p_str == p.to_binary()) << td::tag("receive", p_res.to_decimal()) << td::tag("expected", first); + LOG_CHECK(q_str == q.to_binary()) << td::tag("receive", q_res.to_decimal()) << td::tag("expected", second); } #endif |