diff options
author | thegeorg <thegeorg@yandex-team.ru> | 2022-02-10 16:45:12 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:12 +0300 |
commit | 49116032d905455a7b1c994e4a696afc885c1e71 (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/protoc/src/google/protobuf/compiler/scc.h | |
parent | 4e839db24a3bbc9f1c610c43d6faaaa99824dcca (diff) | |
download | ydb-49116032d905455a7b1c994e4a696afc885c1e71.tar.gz |
Restoring authorship annotation for <thegeorg@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/scc.h')
-rw-r--r-- | contrib/libs/protoc/src/google/protobuf/compiler/scc.h | 328 |
1 files changed, 164 insertions, 164 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/scc.h b/contrib/libs/protoc/src/google/protobuf/compiler/scc.h index 3082e38169..a1394602f7 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/scc.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/scc.h @@ -1,164 +1,164 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__ -#define GOOGLE_PROTOBUF_COMPILER_SCC_H__ - -#include <map> - -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/descriptor.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace compiler { - -// Description of each strongly connected component. Note that the order -// of both the descriptors in this SCC and the order of children is -// deterministic. -struct SCC { - std::vector<const Descriptor*> descriptors; - std::vector<const SCC*> children; - - const Descriptor* GetRepresentative() const { return descriptors[0]; } - - // All messages must necessarily be in the same file. - const FileDescriptor* GetFile() const { return descriptors[0]->file(); } -}; - -// This class is used for analyzing the SCC for each message, to ensure linear -// instead of quadratic performance, if we do this per message we would get -// O(V*(V+E)). -template <class DepsGenerator> -class PROTOC_EXPORT SCCAnalyzer { - public: - explicit SCCAnalyzer() : index_(0) {} - - const SCC* GetSCC(const Descriptor* descriptor) { - if (cache_.count(descriptor)) return cache_[descriptor].scc; - return DFS(descriptor).scc; - } - - private: - struct NodeData { - const SCC* scc; // if null it means its still on the stack - int index; - int lowlink; - }; - - std::map<const Descriptor*, NodeData> cache_; - std::vector<const Descriptor*> stack_; - int index_; - std::vector<std::unique_ptr<SCC>> garbage_bin_; - - SCC* CreateSCC() { - garbage_bin_.emplace_back(new SCC()); - return garbage_bin_.back().get(); - } - - // Tarjan's Strongly Connected Components algo - NodeData DFS(const Descriptor* descriptor) { - // Must not have visited already. - GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); - - // Mark visited by inserting in map. - NodeData& result = cache_[descriptor]; - // Initialize data structures. - result.index = result.lowlink = index_++; - stack_.push_back(descriptor); - - // Recurse the fields / nodes in graph - for (auto dep : DepsGenerator()(descriptor)) { - GOOGLE_CHECK(dep); - if (cache_.count(dep) == 0) { - // unexplored node - NodeData child_data = DFS(dep); - result.lowlink = std::min(result.lowlink, child_data.lowlink); - } else { - NodeData child_data = cache_[dep]; - if (child_data.scc == nullptr) { - // Still in the stack_ so we found a back edge - result.lowlink = std::min(result.lowlink, child_data.index); - } - } - } - if (result.index == result.lowlink) { - // This is the root of a strongly connected component - SCC* scc = CreateSCC(); - while (true) { - const Descriptor* scc_desc = stack_.back(); - scc->descriptors.push_back(scc_desc); - // Remove from stack - stack_.pop_back(); - cache_[scc_desc].scc = scc; - - if (scc_desc == descriptor) break; - } - - // The order of descriptors is random and depends how this SCC was - // discovered. In-order to ensure maximum stability we sort it by name. - std::sort(scc->descriptors.begin(), scc->descriptors.end(), - [](const Descriptor* a, const Descriptor* b) { - return a->full_name() < b->full_name(); - }); - AddChildren(scc); - } - return result; - } - - // Add the SCC's that are children of this SCC to its children. - void AddChildren(SCC* scc) { - std::set<const SCC*> seen; - for (auto descriptor : scc->descriptors) { - for (auto child_msg : DepsGenerator()(descriptor)) { - GOOGLE_CHECK(child_msg); - const SCC* child = GetSCC(child_msg); - if (child == scc) continue; - if (seen.insert(child).second) { - scc->children.push_back(child); - } - } - } - } - - // This is necessary for compiler bug in msvc2015. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer); -}; - -} // namespace compiler -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__ +#define GOOGLE_PROTOBUF_COMPILER_SCC_H__ + +#include <map> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace compiler { + +// Description of each strongly connected component. Note that the order +// of both the descriptors in this SCC and the order of children is +// deterministic. +struct SCC { + std::vector<const Descriptor*> descriptors; + std::vector<const SCC*> children; + + const Descriptor* GetRepresentative() const { return descriptors[0]; } + + // All messages must necessarily be in the same file. + const FileDescriptor* GetFile() const { return descriptors[0]->file(); } +}; + +// This class is used for analyzing the SCC for each message, to ensure linear +// instead of quadratic performance, if we do this per message we would get +// O(V*(V+E)). +template <class DepsGenerator> +class PROTOC_EXPORT SCCAnalyzer { + public: + explicit SCCAnalyzer() : index_(0) {} + + const SCC* GetSCC(const Descriptor* descriptor) { + if (cache_.count(descriptor)) return cache_[descriptor].scc; + return DFS(descriptor).scc; + } + + private: + struct NodeData { + const SCC* scc; // if null it means its still on the stack + int index; + int lowlink; + }; + + std::map<const Descriptor*, NodeData> cache_; + std::vector<const Descriptor*> stack_; + int index_; + std::vector<std::unique_ptr<SCC>> garbage_bin_; + + SCC* CreateSCC() { + garbage_bin_.emplace_back(new SCC()); + return garbage_bin_.back().get(); + } + + // Tarjan's Strongly Connected Components algo + NodeData DFS(const Descriptor* descriptor) { + // Must not have visited already. + GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); + + // Mark visited by inserting in map. + NodeData& result = cache_[descriptor]; + // Initialize data structures. + result.index = result.lowlink = index_++; + stack_.push_back(descriptor); + + // Recurse the fields / nodes in graph + for (auto dep : DepsGenerator()(descriptor)) { + GOOGLE_CHECK(dep); + if (cache_.count(dep) == 0) { + // unexplored node + NodeData child_data = DFS(dep); + result.lowlink = std::min(result.lowlink, child_data.lowlink); + } else { + NodeData child_data = cache_[dep]; + if (child_data.scc == nullptr) { + // Still in the stack_ so we found a back edge + result.lowlink = std::min(result.lowlink, child_data.index); + } + } + } + if (result.index == result.lowlink) { + // This is the root of a strongly connected component + SCC* scc = CreateSCC(); + while (true) { + const Descriptor* scc_desc = stack_.back(); + scc->descriptors.push_back(scc_desc); + // Remove from stack + stack_.pop_back(); + cache_[scc_desc].scc = scc; + + if (scc_desc == descriptor) break; + } + + // The order of descriptors is random and depends how this SCC was + // discovered. In-order to ensure maximum stability we sort it by name. + std::sort(scc->descriptors.begin(), scc->descriptors.end(), + [](const Descriptor* a, const Descriptor* b) { + return a->full_name() < b->full_name(); + }); + AddChildren(scc); + } + return result; + } + + // Add the SCC's that are children of this SCC to its children. + void AddChildren(SCC* scc) { + std::set<const SCC*> seen; + for (auto descriptor : scc->descriptors) { + for (auto child_msg : DepsGenerator()(descriptor)) { + GOOGLE_CHECK(child_msg); + const SCC* child = GetSCC(child_msg); + if (child == scc) continue; + if (seen.insert(child).second) { + scc->children.push_back(child); + } + } + } + } + + // This is necessary for compiler bug in msvc2015. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer); +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__ |