blob: 5507f92f7f4a503b7ee21d820d05788ef96f66f7 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DIAGNOSTICS_BASE_PATH_LITERAL_H_
#define DIAGNOSTICS_BASE_PATH_LITERAL_H_
#include <algorithm>
#include <array>
#include <cstddef>
#include <string>
#include <vector>
#include <base/files/file_path.h>
#include <brillo/brillo_export.h>
namespace diagnostics {
// A helper class to define constexpr paths with concatenation supports. Use
// `MakePathLiteral` helper function to create literals.
// E.g.
// constexpr auto kMyPath = MakePathLiteral("a", "b", "c");
// constexpr auto kMyFile = MakePathLiteral(kMyPath, "myfile");
//
template <std::size_t Size>
class StaticPathLiteral;
class BRILLO_EXPORT PathLiteral {
public:
PathLiteral(const char** tokens, std::size_t size);
template <std::size_t Size>
PathLiteral(StaticPathLiteral<Size> path); // NOLINT(runtime/explicit)
PathLiteral(const PathLiteral&) = delete;
PathLiteral& operator=(const PathLiteral&) = delete;
~PathLiteral();
// Returns relative paths by join each tokens.
base::FilePath ToPath() const;
// Same as above but return std::string.
std::string ToStr() const;
// Returns full paths from root directory.
base::FilePath ToFull() const;
private:
std::vector<const char*> tokens_;
};
template <std::size_t Size>
class StaticPathLiteral {
static_assert(Size >= 1);
public:
constexpr explicit StaticPathLiteral(
const std::array<const char*, Size>& tokens)
: tokens_(tokens) {}
StaticPathLiteral(const StaticPathLiteral&) = default;
StaticPathLiteral& operator=(const StaticPathLiteral&) = default;
~StaticPathLiteral() = default;
constexpr std::array<const char*, Size> tokens() const { return tokens_; }
base::FilePath ToPath() const { return PathLiteral(*this).ToPath(); }
std::string ToStr() const { return PathLiteral(*this).ToStr(); }
base::FilePath ToFull() const { return PathLiteral(*this).ToFull(); }
private:
std::array<const char*, Size> tokens_;
};
template <std::size_t Size>
PathLiteral::PathLiteral(StaticPathLiteral<Size> path)
: PathLiteral(path.tokens().data(), path.tokens().size()) {}
template <std::size_t Size>
constexpr auto MakePathLiteral(const std::array<const char*, Size>& base) {
return StaticPathLiteral<Size>(base);
}
template <std::size_t Size, typename... Types>
constexpr auto MakePathLiteral(const std::array<const char*, Size>& base,
const char* token,
Types... rest) {
std::array<const char*, Size + 1> res;
std::copy(base.begin(), base.end(), res.begin());
res.back() = token;
return MakePathLiteral(res, rest...);
}
template <std::size_t S1, std::size_t S2, typename... Types>
constexpr auto MakePathLiteral(const std::array<const char*, S1>& base,
const StaticPathLiteral<S2>& path,
Types... rest) {
std::array<const char*, S1 + S2> res;
std::copy(base.begin(), base.end(), res.begin());
std::array<const char*, S2> tokens = path.tokens();
std::copy(tokens.begin(), tokens.end(), res.begin() + S1);
return MakePathLiteral(res, rest...);
}
template <std::size_t Size, typename... Types>
constexpr auto MakePathLiteral(const StaticPathLiteral<Size>& base,
Types... rest) {
return MakePathLiteral(base.tokens(), rest...);
}
template <typename... Types>
constexpr auto MakePathLiteral(const char* token, Types... rest) {
std::array<const char*, 1> base;
base[0] = token;
return MakePathLiteral(base, rest...);
}
} // namespace diagnostics
#endif // DIAGNOSTICS_BASE_PATH_LITERAL_H_