* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef OMNISTREAM_FILEUTILS_H
#define OMNISTREAM_FILEUTILS_H
#include <filesystem>
#include <string>
#include <vector>
#include <cstdint>
#include <random>
#include <mutex>
#include <functional>
#include <fstream>
#include <system_error>
#include <atomic>
namespace fs = std::filesystem;
class FileUtils {
public:
static void deleteFileOrDirectory(const fs::path& path)
{
auto operation = [](const fs::path& p) {
if (fs::is_directory(p)) {
deleteDirectoryInternal(p);
} else {
fs::remove(p);
}
};
guardIfThreadSafe(operation, path);
};
static void deleteDirectory(const fs::path& directory)
{
guardIfThreadSafe(deleteDirectoryInternal, directory);
};
static void deleteDirectoryQuietly(const fs::path& directory)
{
try {
deleteDirectory(directory);
} catch (...) {
}
};
static void cleanDirectory(const fs::path& directory)
{
guardIfThreadSafe(cleanDirectoryInternal, directory);
};
static std::vector<fs::path> listDirectory(const fs::path& directory)
{
std::vector<fs::path> files;
for (const auto& entry : fs::directory_iterator(directory)) {
files.push_back(entry.path());
}
return files;
};
static std::string getRandomFilename(const std::string& prefix)
{
const std::string ALPHABET = "0123456789abcdef";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, ALPHABET.size() - 1);
std::string filename = prefix;
for (int i = 0; i < 12; i++) {
filename += ALPHABET[dist(gen)];
}
return filename;
};
static std::string readFileUtf8(const fs::path& file)
{
std::ifstream in(file, std::ios::binary);
if (!in) {
throw std::runtime_error("Cannot open file: " + file.string());
}
std::string content(
(std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>()
);
return content;
};
static void writeFileUtf8(const fs::path& file, const std::string& contents)
{
std::ofstream out(file, std::ios::binary);
if (!out) {
throw std::runtime_error("Cannot open file: " + file.string());
}
out.write(contents.data(), contents.size());
};
static bool exists(const fs::path& path)
{
return fs::exists(path);
}
static bool isJarFile(const fs::path& file)
{
return file.extension() == ".jar";
}
static fs::path getCurrentWorkingDirectory()
{
return fs::current_path();
}
private:
static void deleteFileOrDirectoryInternal(const fs::path& path);
static void deleteDirectoryInternal(const fs::path& directory)
{
if (fs::is_directory(directory)) {
cleanDirectoryInternal(directory);
fs::remove(directory);
} else if (fs::exists(directory)) {
throw std::runtime_error(directory.string() + " is not a directory");
}
};
static void cleanDirectoryInternal(const fs::path& directory)
{
if (!fs::exists(directory)) {
throw std::runtime_error("Directory does not exist: " + directory.string());
}
if (!fs::is_directory(directory)) {
throw std::runtime_error("Path is not a directory: " + directory.string());
}
for (const auto& entry : fs::directory_iterator(directory)) {
if (fs::is_directory(entry)) {
deleteDirectoryInternal(entry.path());
} else {
fs::remove(entry.path());
}
}
};
template<typename Func>
static void guardIfThreadSafe(Func&& func, const fs::path& path)
{
func(path);
};
static std::mutex& getGlobalDeleteLock()
{
static std::mutex globalLock;
return globalLock;
}
};
class PathUtils {
public:
static fs::path absolutizePath(const fs::path& path)
{
return fs::absolute(path);
}
static fs::path relativizePath(const fs::path& base, const fs::path& path)
{
return fs::relative(path, base);
}
};
#endif