blob: 2ef7083a823e659ec4fcab8c25bb6bc645f7f4d9 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "google/protobuf/map.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <string>
#include "absl/base/optimization.h"
#include "absl/log/absl_check.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/port.h"
// Must be included last.
#include "google/protobuf/port_def.inc"
namespace google {
namespace protobuf {
namespace internal {
NodeBase* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {};
void UntypedMapBase::ClearTable(const ClearInput input) {
ABSL_DCHECK_NE(num_buckets_, kGlobalEmptyTableSize);
if (alloc_.arena() == nullptr) {
const auto loop = [&, this](auto destroy_node) {
NodeBase** table = table_;
for (map_index_t b = index_of_first_non_null_, end = num_buckets_;
b < end; ++b) {
for (NodeBase* node = table[b]; node != nullptr;) {
NodeBase* next = node->next;
absl::PrefetchToLocalCacheNta(next);
destroy_node(node);
SizedDelete(node, SizeFromInfo(input.size_info));
node = next;
}
}
};
switch (input.destroy_bits) {
case 0:
loop([](NodeBase*) {});
break;
case kKeyIsString:
loop([](NodeBase* node) {
static_cast<std::string*>(node->GetVoidKey())->~basic_string();
});
break;
case kValueIsString:
loop([size_info = input.size_info](NodeBase* node) {
static_cast<std::string*>(node->GetVoidValue(size_info))
->~basic_string();
});
break;
case kKeyIsString | kValueIsString:
loop([size_info = input.size_info](NodeBase* node) {
static_cast<std::string*>(node->GetVoidKey())->~basic_string();
static_cast<std::string*>(node->GetVoidValue(size_info))
->~basic_string();
});
break;
case kValueIsProto:
loop([size_info = input.size_info](NodeBase* node) {
static_cast<MessageLite*>(node->GetVoidValue(size_info))
->DestroyInstance();
});
break;
case kKeyIsString | kValueIsProto:
loop([size_info = input.size_info](NodeBase* node) {
static_cast<std::string*>(node->GetVoidKey())->~basic_string();
static_cast<MessageLite*>(node->GetVoidValue(size_info))
->DestroyInstance();
});
break;
case kUseDestructFunc:
loop(input.destroy_node);
break;
}
}
if (input.reset_table) {
std::fill(table_, table_ + num_buckets_, nullptr);
num_elements_ = 0;
index_of_first_non_null_ = num_buckets_;
} else {
DeleteTable(table_, num_buckets_);
}
}
size_t UntypedMapBase::SpaceUsedInTable(size_t sizeof_node) const {
size_t size = 0;
// The size of the table.
size += sizeof(void*) * num_buckets_;
// All the nodes.
size += sizeof_node * num_elements_;
return size;
}
} // namespace internal
} // namespace protobuf
} // namespace google
#include "google/protobuf/port_undef.inc"