|
| 1 | +// |
| 2 | +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2026 |
| 3 | +// |
| 4 | +// Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 5 | +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 6 | +// |
| 7 | +#include "td/telegram/DiffText.h" |
| 8 | + |
| 9 | +#include "td/utils/algorithm.h" |
| 10 | +#include "td/utils/logging.h" |
| 11 | +#include "td/utils/misc.h" |
| 12 | +#include "td/utils/utf8.h" |
| 13 | + |
| 14 | +namespace td { |
| 15 | + |
| 16 | +td_api::object_ptr<td_api::DiffEntityType> DiffText::DiffEntity::get_diff_entity_type_object() const { |
| 17 | + switch (type_) { |
| 18 | + case Type::Insert: |
| 19 | + return td_api::make_object<td_api::diffEntityTypeInsert>(); |
| 20 | + case Type::Replace: |
| 21 | + return td_api::make_object<td_api::diffEntityTypeReplace>(old_text_); |
| 22 | + case Type::Delete: |
| 23 | + return td_api::make_object<td_api::diffEntityTypeDelete>(); |
| 24 | + default: |
| 25 | + UNREACHABLE(); |
| 26 | + return nullptr; |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +td_api::object_ptr<td_api::diffEntity> DiffText::DiffEntity::get_diff_entity_object() const { |
| 31 | + return td_api::make_object<td_api::diffEntity>(offset_, length_, get_diff_entity_type_object()); |
| 32 | +} |
| 33 | + |
| 34 | +bool DiffText::check_entities() const { |
| 35 | + // entities must not intersect and must not begin and end in the middle of characters |
| 36 | + int32 text_len = narrow_cast<int32>(utf8_utf16_length(text_)); |
| 37 | + int32 cur_pos = 0; |
| 38 | + for (auto &entity : entities_) { |
| 39 | + if (entity.offset_ < cur_pos) { |
| 40 | + return false; |
| 41 | + } |
| 42 | + if (entity.length_ < 0 || entity.length_ > text_len - entity.offset_) { |
| 43 | + return false; |
| 44 | + } |
| 45 | + cur_pos = entity.offset_ + entity.length_; |
| 46 | + } |
| 47 | + return true; |
| 48 | +} |
| 49 | + |
| 50 | +DiffText::DiffText(telegram_api::object_ptr<telegram_api::textWithEntities> &&text_with_entities) { |
| 51 | + if (text_with_entities == nullptr) { |
| 52 | + LOG(ERROR) << "Receive no diff text"; |
| 53 | + return; |
| 54 | + } |
| 55 | + |
| 56 | + text_ = std::move(text_with_entities->text_); |
| 57 | + entities_.reserve(text_with_entities->entities_.size()); |
| 58 | + for (auto &server_entity : text_with_entities->entities_) { |
| 59 | + switch (server_entity->get_id()) { |
| 60 | + case telegram_api::messageEntityUnknown::ID: |
| 61 | + break; |
| 62 | + case telegram_api::messageEntityDiffInsert::ID: { |
| 63 | + auto entity = static_cast<const telegram_api::messageEntityDiffInsert *>(server_entity.get()); |
| 64 | + entities_.emplace_back(DiffEntity::Type::Insert, entity->offset_, entity->length_); |
| 65 | + break; |
| 66 | + } |
| 67 | + case telegram_api::messageEntityDiffReplace::ID: { |
| 68 | + auto entity = static_cast<const telegram_api::messageEntityDiffReplace *>(server_entity.get()); |
| 69 | + entities_.emplace_back(DiffEntity::Type::Replace, entity->offset_, entity->length_, entity->old_text_); |
| 70 | + break; |
| 71 | + } |
| 72 | + case telegram_api::messageEntityDiffDelete::ID: { |
| 73 | + auto entity = static_cast<const telegram_api::messageEntityDiffDelete *>(server_entity.get()); |
| 74 | + entities_.emplace_back(DiffEntity::Type::Delete, entity->offset_, entity->length_); |
| 75 | + break; |
| 76 | + } |
| 77 | + default: |
| 78 | + LOG(ERROR) << "Receive diff entity " << to_string(server_entity); |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + if (!check_entities()) { |
| 83 | + LOG(ERROR) << "Receive invalid diff entities in " << to_string(text_with_entities); |
| 84 | + entities_.clear(); |
| 85 | + } else { |
| 86 | + td::remove_if(entities_, [](const auto &entity) { return entity.length_ <= 0; }); |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +td_api::object_ptr<td_api::diffText> DiffText::get_diff_text_object() const { |
| 91 | + return td_api::make_object<td_api::diffText>( |
| 92 | + text_, transform(entities_, [](const DiffEntity &entity) { return entity.get_diff_entity_object(); })); |
| 93 | +} |
| 94 | + |
| 95 | +} // namespace td |
0 commit comments