blob: aa19744e590e608ebb87ff692b75aacc3549d54c [file]
// Copyright 2026 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/crash_reports/program_shortname.h"
#include <algorithm>
#include <optional>
#include <string>
namespace forensics::crash_reports {
namespace {
// Shorten |program_name| into a shortname by removing the "fuchsia-pkg://" prefix if present and
// replacing all '/' with ':'.
//
// For example `fuchsia-pkg://fuchsia.com/foo-bar#meta/foo_bar.cm` becomes
// `fuchsia.com:foo-bar#meta:foo_bar.cm`.
std::string Shorten(std::string program_name) {
// Remove leading whitespace.
const size_t first_non_whitespace = program_name.find_first_not_of(' ');
if (first_non_whitespace == std::string::npos) {
return "";
}
program_name = program_name.substr(first_non_whitespace);
// Remove the "fuchsia-pkg://" prefix if present.
const std::string fuchsia_pkg_prefix("fuchsia-pkg://");
if (program_name.find(fuchsia_pkg_prefix) == 0) {
program_name.erase(/*pos=*/0u, /*len=*/fuchsia_pkg_prefix.size());
}
std::replace(program_name.begin(), program_name.end(), '/', ':');
// Remove all repeating ':'.
for (size_t idx = program_name.find("::"); idx != std::string::npos;
idx = program_name.find("::")) {
program_name.erase(idx, 1);
}
// Remove trailing white space.
const size_t last_non_whitespace = program_name.find_last_not_of(' ');
return (last_non_whitespace == std::string::npos)
? ""
: program_name.substr(0, last_non_whitespace + 1);
}
} // namespace
std::optional<ProgramShortname> ProgramShortname::Create(std::string program_name) {
const std::string shortened = Shorten(std::move(program_name));
if (shortened.empty()) {
return std::nullopt;
}
return ProgramShortname(shortened);
}
std::string ProgramShortname::Logname() const {
std::string name = value_;
// Find the last colon in |name|.
const size_t last_colon = name.find_last_of(":");
if (last_colon == std::string::npos) {
return name;
}
// Remove everything leading up to the last colon.
name.erase(name.begin(), name.begin() + last_colon + 1);
// Determine if there's a ".cm" suffix in |name|.
const size_t cm_suffix = name.rfind(".cm");
if (cm_suffix == std::string::npos) {
return name;
}
// Erase the ".cm" and everything after it.
name.erase(name.begin() + cm_suffix, name.end());
return name;
}
} // namespace forensics::crash_reports