aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/util/repeated_field_utils.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/protobuf/util/repeated_field_utils.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/protobuf/util/repeated_field_utils.h')
-rw-r--r--library/cpp/protobuf/util/repeated_field_utils.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/library/cpp/protobuf/util/repeated_field_utils.h b/library/cpp/protobuf/util/repeated_field_utils.h
new file mode 100644
index 0000000000..c07bd84647
--- /dev/null
+++ b/library/cpp/protobuf/util/repeated_field_utils.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include <google/protobuf/repeated_field.h>
+#include <util/generic/vector.h>
+
+template <typename T>
+void RemoveRepeatedPtrFieldElement(google::protobuf::RepeatedPtrField<T>* repeated, unsigned index) {
+ google::protobuf::RepeatedPtrField<T> r;
+ Y_ASSERT(index < (unsigned)repeated->size());
+ for (unsigned i = 0; i < (unsigned)repeated->size(); ++i) {
+ if (i == index) {
+ continue;
+ }
+ r.Add()->Swap(repeated->Mutable(i));
+ }
+ r.Swap(repeated);
+}
+
+namespace NProtoBuf {
+ /// Move item to specified position
+ template <typename TRepeated>
+ static void MoveRepeatedFieldItem(TRepeated* field, size_t indexFrom, size_t indexTo) {
+ if (!field->size() || indexFrom >= static_cast<size_t>(field->size()) || indexFrom == indexTo)
+ return;
+ if (indexTo >= static_cast<size_t>(field->size()))
+ indexTo = field->size() - 1;
+ if (indexFrom > indexTo) {
+ for (size_t i = indexFrom; i > indexTo; --i)
+ field->SwapElements(i, i - 1);
+ } else {
+ for (size_t i = indexFrom; i < indexTo; ++i)
+ field->SwapElements(i, i + 1);
+ }
+ }
+
+ template <typename T>
+ static T* InsertRepeatedFieldItem(NProtoBuf::RepeatedPtrField<T>* field, size_t index) {
+ T* ret = field->Add();
+ MoveRepeatedFieldItem(field, field->size() - 1, index);
+ return ret;
+ }
+
+ template <typename TRepeated> // suitable both for RepeatedField and RepeatedPtrField
+ static void RemoveRepeatedFieldItem(TRepeated* field, size_t index) {
+ if ((int)index >= field->size())
+ return;
+
+ for (int i = index + 1; i < field->size(); ++i)
+ field->SwapElements(i - 1, i);
+
+ field->RemoveLast();
+ }
+
+ template <typename TRepeated, typename TPred> // suitable both for RepeatedField and RepeatedPtrField
+ static void RemoveRepeatedFieldItemIf(TRepeated* repeated, TPred p) {
+ auto last = std::remove_if(repeated->begin(), repeated->end(), p);
+ if (last != repeated->end()) {
+ size_t countToRemove = repeated->end() - last;
+ while (countToRemove--)
+ repeated->RemoveLast();
+ }
+ }
+
+ namespace NImpl {
+ template <typename TRepeated>
+ static void ShiftLeft(TRepeated* field, int begIndex, int endIndex, size_t shiftSize) {
+ Y_ASSERT(begIndex <= field->size());
+ Y_ASSERT(endIndex <= field->size());
+ size_t shiftIndex = (int)shiftSize < begIndex ? begIndex - shiftSize : 0;
+ for (int i = begIndex; i < endIndex; ++i, ++shiftIndex)
+ field->SwapElements(shiftIndex, i);
+ }
+ }
+
+ // Remove several items at once, could be more efficient compared to calling RemoveRepeatedFieldItem several times
+ template <typename TRepeated>
+ static void RemoveRepeatedFieldItems(TRepeated* field, const TVector<size_t>& sortedIndices) {
+ if (sortedIndices.empty())
+ return;
+
+ size_t shift = 1;
+ for (size_t i = 1; i < sortedIndices.size(); ++i, ++shift)
+ NImpl::ShiftLeft(field, sortedIndices[i - 1] + 1, sortedIndices[i], shift);
+ NImpl::ShiftLeft(field, sortedIndices.back() + 1, field->size(), shift);
+
+ for (; shift > 0; --shift)
+ field->RemoveLast();
+ }
+
+ template <typename TRepeated>
+ static void ReverseRepeatedFieldItems(TRepeated* field) {
+ for (int i1 = 0, i2 = field->size() - 1; i1 < i2; ++i1, --i2)
+ field->SwapElements(i1, i2);
+ }
+
+}