| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmDefinitions.h" |
| |
| #include <assert.h> |
| #include <set> |
| #include <utility> |
| |
| cmDefinitions::Def cmDefinitions::NoDef; |
| |
| cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, |
| StackIter begin, |
| StackIter end, bool raise) |
| { |
| assert(begin != end); |
| MapType::iterator i = begin->Map.find(key); |
| if (i != begin->Map.end()) { |
| i->second.Used = true; |
| return i->second; |
| } |
| StackIter it = begin; |
| ++it; |
| if (it == end) { |
| return cmDefinitions::NoDef; |
| } |
| Def const& def = cmDefinitions::GetInternal(key, it, end, raise); |
| if (!raise) { |
| return def; |
| } |
| return begin->Map.insert(MapType::value_type(key, def)).first->second; |
| } |
| |
| const std::string* cmDefinitions::Get(const std::string& key, StackIter begin, |
| StackIter end) |
| { |
| Def const& def = cmDefinitions::GetInternal(key, begin, end, false); |
| return def.Exists ? &def : nullptr; |
| } |
| |
| void cmDefinitions::Raise(const std::string& key, StackIter begin, |
| StackIter end) |
| { |
| cmDefinitions::GetInternal(key, begin, end, true); |
| } |
| |
| bool cmDefinitions::HasKey(const std::string& key, StackIter begin, |
| StackIter end) |
| { |
| for (StackIter it = begin; it != end; ++it) { |
| MapType::const_iterator i = it->Map.find(key); |
| if (i != it->Map.end()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| void cmDefinitions::Set(const std::string& key, const char* value) |
| { |
| Def def(value); |
| this->Map[key] = def; |
| } |
| |
| std::vector<std::string> cmDefinitions::UnusedKeys() const |
| { |
| std::vector<std::string> keys; |
| keys.reserve(this->Map.size()); |
| // Consider local definitions. |
| for (auto const& mi : this->Map) { |
| if (!mi.second.Used) { |
| keys.push_back(mi.first); |
| } |
| } |
| return keys; |
| } |
| |
| cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end) |
| { |
| cmDefinitions closure; |
| std::set<std::string> undefined; |
| for (StackIter it = begin; it != end; ++it) { |
| // Consider local definitions. |
| for (auto const& mi : it->Map) { |
| // Use this key if it is not already set or unset. |
| if (closure.Map.find(mi.first) == closure.Map.end() && |
| undefined.find(mi.first) == undefined.end()) { |
| if (mi.second.Exists) { |
| closure.Map.insert(mi); |
| } else { |
| undefined.insert(mi.first); |
| } |
| } |
| } |
| } |
| return closure; |
| } |
| |
| std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin, |
| StackIter end) |
| { |
| std::set<std::string> bound; |
| std::vector<std::string> defined; |
| |
| for (StackIter it = begin; it != end; ++it) { |
| defined.reserve(defined.size() + it->Map.size()); |
| for (auto const& mi : it->Map) { |
| // Use this key if it is not already set or unset. |
| if (bound.insert(mi.first).second && mi.second.Exists) { |
| defined.push_back(mi.first); |
| } |
| } |
| } |
| |
| return defined; |
| } |