| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/forensics/utils/inspect_node_manager.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <algorithm> | |
| #include "src/lib/fxl/strings/split_string.h" | |
| namespace forensics { | |
| namespace { | |
| // The ASCII bell character (0x07) will be used to replace all backslashes. | |
| constexpr uint8_t kBackslashReplacement = 0x07; | |
| void ReplaceCharInString(char to_replace, char replace_with, std::string* str) { | |
| for (size_t i = 0; i < str->size(); ++i) { | |
| if ((*str)[i] == to_replace) { | |
| (*str)[i] = replace_with; | |
| } | |
| } | |
| } | |
| } // namespace | |
| using fxl::kSplitWantNonEmpty; | |
| using fxl::kTrimWhitespace; | |
| using fxl::SplitStringCopy; | |
| using inspect::Node; | |
| bool InspectNodeManager::ManagedNodeBase::HasChild(const std::string& child) const { | |
| return children_.find(child) != children_.end(); | |
| } | |
| InspectNodeManager::ManagedNode& InspectNodeManager::ManagedNodeBase::GetChild( | |
| const std::string& child) { | |
| if (!HasChild(child)) { | |
| children_.emplace(child, ManagedNode(GetNode().CreateChild(child))); | |
| } | |
| return children_.at(child); | |
| } | |
| bool InspectNodeManager::ManagedNodeBase::RemoveChild(const std::string& child) { | |
| return children_.erase(child) != 0; | |
| } | |
| Node& InspectNodeManager::Get(const std::string& path) { | |
| ManagedNodeBase* node = &root_; | |
| const auto split_path = SplitAndDesanitize(path); | |
| for (auto child : split_path) { | |
| // Create the child if it doesn't exist, then get the child. | |
| node = &node->GetChild(child); | |
| } | |
| return node->GetNode(); | |
| } | |
| bool InspectNodeManager::Remove(const std::string& path) { | |
| ManagedNodeBase* node = &root_; | |
| const auto split_path = SplitAndDesanitize(path); | |
| // Find the parent node. | |
| for (size_t i = 0; i < split_path.size() - 1; ++i) { | |
| // Return early if a node in the path doesn't exist. | |
| if (!node->HasChild(split_path[i])) { | |
| return false; | |
| } | |
| node = &node->GetChild(split_path[i]); | |
| } | |
| return node->RemoveChild(split_path.back()); | |
| } | |
| std::string InspectNodeManager::SanitizeString(std::string str) { | |
| ReplaceCharInString('/', kBackslashReplacement, &str); | |
| return str; | |
| } | |
| std::vector<std::string> InspectNodeManager::SplitAndDesanitize(const std::string& path) { | |
| std::vector<std::string> split_path = | |
| SplitStringCopy(path, "/", kTrimWhitespace, kSplitWantNonEmpty); | |
| for (auto& part : split_path) { | |
| ReplaceCharInString(kBackslashReplacement, '/', &part); | |
| } | |
| return split_path; | |
| } | |
| } // namespace forensics |