/************************************************************************************************** * * Copyright (c) 2019-2024 Axera Semiconductor Co., Ltd. All Rights Reserved. * * This source file is the property of Axera Semiconductor Co., Ltd. and * may not be copied or distributed in any isomorphic form without the prior * written consent of Axera Semiconductor Co., Ltd. * **************************************************************************************************/ #pragma once #include #include #if defined(ENV_HAS_STD_FILESYSTEM) #include #endif // ENV_HAS_STD_FILESYSTEM #if defined(ENV_HAS_POSIX_FILE_STAT) #include #include #include #include #include "utilities/scalar_guard.hpp" #endif // ENV_HAS_POSIX_FILE_STAT #if defined(ENV_HAS_WIN_API) #include #endif // ENV_HAS_WIN_API #include namespace utilities { constexpr auto error_size = static_cast(-1); enum class file_type { none, not_found, regular, directory, symlink, block, character, fifo, socket, unknown, }; inline bool exists(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::exists(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) struct ::stat path_stat{}; return 0 == ::stat(path.c_str(), &path_stat); #else #error "Unsupported platform, native file system API is required." #endif } inline uintmax_t file_size(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::file_size(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) struct ::stat path_stat{}; if (0 == ::stat(path.c_str(), &path_stat)) { return path_stat.st_size; } return error_size; #else #error "Unsupported platform, native file system API is required." #endif } inline file_type status(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) if (!exists(path)) { return file_type::not_found; } const auto status = std::filesystem::status(path); if (std::filesystem::is_regular_file(status)) { return file_type::regular; } if (std::filesystem::is_directory(status)) { return file_type::directory; } if (std::filesystem::is_symlink(status)) { return file_type::symlink; } if (std::filesystem::is_block_file(status)) { return file_type::block; } if (std::filesystem::is_character_file(status)) { return file_type::character; } if (std::filesystem::is_fifo(status)) { return file_type::fifo; } if (std::filesystem::is_socket(status)) { return file_type::socket; } return file_type::unknown; #elif defined(ENV_HAS_POSIX_FILE_STAT) struct ::stat path_stat{}; if (0 != ::stat(path.c_str(), &path_stat)) { return file_type::not_found; } if (S_ISREG(path_stat.st_mode)) { return file_type::regular; } if (S_ISDIR(path_stat.st_mode)) { return file_type::directory; } if (S_ISLNK(path_stat.st_mode)) { return file_type::symlink; } if (S_ISBLK(path_stat.st_mode)) { return file_type::block; } if (S_ISCHR(path_stat.st_mode)) { return file_type::character; } if (S_ISFIFO(path_stat.st_mode)) { return file_type::fifo; } if (S_ISSOCK(path_stat.st_mode)) { return file_type::socket; } return file_type::unknown; #else #error "Unsupported platform, native file system API is required." #endif } inline bool is_regular_file(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::is_regular_file(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) struct ::stat path_stat{}; return 0 == ::stat(path.c_str(), &path_stat) && S_ISREG(path_stat.st_mode); #else #error "Unsupported platform, native file system API is required." #endif } inline bool is_directory(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::is_directory(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) struct ::stat path_stat{}; return 0 == ::stat(path.c_str(), &path_stat) && S_ISDIR(path_stat.st_mode); #else #error "Unsupported platform, native file system API is required." #endif } inline bool is_empty(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::is_empty(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) if (!exists(path)) return false; if (is_regular_file(path)) return 0 == file_size(path); if (is_directory(path)) { auto dir = scalar_guard(::opendir(path.c_str()), ::closedir); if (nullptr == dir.get()) { return false; } struct ::dirent* entry; while ((entry = ::readdir(dir.get())) != nullptr) { if (0 != ::strcmp(entry->d_name, ".") && 0 != ::strcmp(entry->d_name, "..")) { return false; } } return true; } return false; #else #error "Unsupported platform, native file system API is required." #endif } inline bool read(const std::string& file, void* data, const uintmax_t& size) { std::ifstream stream; stream.open(file, std::ios_base::binary | std::ios_base::in); if (stream.is_open()) { stream.read(static_cast(data), static_cast(size)); stream.close(); return true; } return false; } inline bool write(const std::string& file, const void* data, const uintmax_t& size) { std::ofstream stream; stream.open(file, std::ios_base::binary | std::ios_base::out); if (stream.is_open()) { stream.write(static_cast(data), static_cast(size)); stream.close(); return true; } return false; } inline bool create_directory(const std::string& path) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::create_directories(path); #elif defined(ENV_HAS_POSIX_FILE_STAT) return 0 == ::mkdir(path.c_str(), 0755); #else #error "Unsupported platform, native file system API is required." #endif } inline std::string get_file_name(const std::string& file) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::path(file).filename().string(); #else if (const auto pos = file.find_last_of("/\\"); std::string::npos != pos) { return file.substr(pos + 1); } return file; #endif } inline std::string get_file_extension(const std::string& file) { #if defined(ENV_HAS_STD_FILESYSTEM) return std::filesystem::path(file).extension().string(); #else if (const auto pos = file.find_last_of('.'); std::string::npos != pos) { return file.substr(pos + 1); } return ""; #endif } inline std::string get_legal_name(const std::string& name) { std::string temp = name; size_t pos = temp.find_last_of("/\\"); if (pos != std::string::npos) pos = 0; for (size_t i = pos; i < temp.size(); ++i) if (!(::isalnum(temp[i]) || '-' == temp[i] || '_' == temp[i])) temp[i] = '_'; return temp; } }