diff --git a/cplusplus/src/include/utils.hpp b/cplusplus/src/include/utils.hpp index 1212b54d..47be8e2f 100644 --- a/cplusplus/src/include/utils.hpp +++ b/cplusplus/src/include/utils.hpp @@ -1,105 +1,47 @@ #pragma once -#include -#include -#include -#include -#ifdef _WIN32 -#include -#include -#define PATH_SEPARATOR "\\" -#else -#include -#include -#include -#define PATH_SEPARATOR "/" -#endif -char* get_parent_directory(char* path, const uint32_t levels) { -#ifdef _WIN32 - static char drive[_MAX_DRIVE]; - static char dir[_MAX_DIR]; - _splitpath(path, drive, dir, NULL, NULL); - for (uint32_t i = 0; i < levels; ++i) { - size_t len = strlen(dir); - if (len > 1 && (dir[len - 1] == '\\' || dir[len - 1] == '/')) { - dir[len - 1] = '\0'; - } - char* last_slash = strrchr(dir, '\\'); - if (!last_slash) last_slash = strrchr(dir, '/'); - if (last_slash) *last_slash = '\0'; - } - static char parent_dir[_MAX_PATH]; - snprintf(parent_dir, sizeof(parent_dir), "%s%s", drive, dir); - return parent_dir; -#else - char* dir = dirname(path); - for (uint32_t i = 0; i < levels; ++i) { - dir = dirname(dir); - if (strcmp(dir, "/") == 0 || strcmp(dir, ".") == 0) { - break; - } - } - return dir; -#endif -} +#include +#include +#include +#include +#include +#include +#include -std::string get_data_file(const char *name) { - const char* start = __FILE__; -#ifdef _WIN32 - char absolute_path[MAX_PATH]; - if (!_fullpath(absolute_path, start, MAX_PATH)) { - perror("_fullpath"); - return NULL; - } -#else - char* absolute_path = realpath(start, NULL); - if (!absolute_path) { - perror("realpath"); - return NULL; - } -#endif - char* parents_dir = get_parent_directory(absolute_path, 3); - const size_t p_len = strlen(parents_dir), - name_len = strlen(name); - char *file_path = (char *)malloc(p_len + name_len + 8); - memcpy(file_path, parents_dir, p_len); - memcpy(file_path + p_len, PATH_SEPARATOR "_data" PATH_SEPARATOR, 7); - memcpy(file_path + p_len + 7, name, name_len); - file_path[p_len + name_len + 7] = 0; - FILE* file = fopen(file_path, "r"); -#ifndef _WIN32 - free(absolute_path); -#endif -// free(parents_dir); - free(file_path); - if (!file) { - perror("fopen"); - return NULL; - } +namespace fs = std::filesystem; - fseek(file, 0, SEEK_END); - size_t length = ftell(file); - fseek(file, 0, SEEK_SET); +namespace FileUtils { + fs::path FileUtils::get_parent_directory(const fs::path& path, uint32_t levels); + std::string get_data_file(const std::string& name); +}; - char* buffer = (char*)malloc(length + 1); - if (!buffer) { - perror("malloc"); - fclose(file); - return NULL; - } +inline +fs::path FileUtils::get_parent_directory(const fs::path& path, uint32_t levels) { + fs::path p(path); + for (uint32_t i = 0; i < levels && p.has_parent_path(); ++i) + p = p.parent_path(); + return p.string(); +} - const size_t ret_code = fread(buffer, 1, length, file); - if (ret_code != length) { - if (feof(file)) - printf("Error reading %s: unexpected end of file, read %" PRIu64 " of %" PRIu64 " bytes expected\n", name, (uint64_t)ret_code, (uint64_t)length); - else if (ferror(file)) - perror("Error reading data file"); - } +std::string FileUtils::get_data_file(const std::string& name) { + try { + fs::path parent_dir = get_parent_directory(fs::path(__FILE__), 4); + fs::path file_path = parent_dir / "_data" / name; - buffer[length] = 0; - fclose(file); + std::ifstream file(file_path, std::ios::binary | std::ios::ate); + if (!file) + throw std::runtime_error("Failed to open file: " + file_path.string()); - std::string ret(buffer); - free(buffer); - return ret; + std::ifstream::pos_type file_size = file.tellg(); + file.seekg(0, std::ios::beg); + + std::vector buffer(static_cast(file_size)); + if (!file.read(buffer.data(), file_size)) + throw std::runtime_error("Failed to read file: " + file_path.string()); + + return std::string(buffer.begin(), buffer.end()); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return {}; + } } diff --git a/cplusplus/src/p0022.cpp b/cplusplus/src/p0022.cpp index bcd60e26..dbce2531 100644 --- a/cplusplus/src/p0022.cpp +++ b/cplusplus/src/p0022.cpp @@ -22,7 +22,7 @@ uint64_t p0022() { uint64_t answer = 0; - std::string fstring = get_data_file("p0022_names.txt"); + std::string fstring = FileUtils::get_data_file("p0022_names.txt"); const uint32_t name_count = 5163; std::vector names(5163, ""); size_t idx = 0, i = 0, pi = 0; diff --git a/docs/src/cplusplus/lib/macros.rst b/docs/src/cplusplus/lib/macros.rst index 1ec65874..2c6e560f 100644 --- a/docs/src/cplusplus/lib/macros.rst +++ b/docs/src/cplusplus/lib/macros.rst @@ -44,6 +44,6 @@ View source code :source:`cplusplus/src/include/macros.hpp` .. c:namespace-pop:: -.. literalinclude:: ../../../../cplusplus/src/include/macros.h +.. literalinclude:: ../../../../cplusplus/src/include/macros.hpp :language: C++ :linenos: diff --git a/docs/src/cplusplus/lib/math.rst b/docs/src/cplusplus/lib/math.rst index 3137abd7..be885a77 100644 --- a/docs/src/cplusplus/lib/math.rst +++ b/docs/src/cplusplus/lib/math.rst @@ -30,6 +30,6 @@ Includes .. c:namespace-pop:: -.. literalinclude:: ../../../../cplusplus/src/include/math.h +.. literalinclude:: ../../../../cplusplus/src/include/math.hpp :language: C++ :linenos: diff --git a/docs/src/cplusplus/lib/utils.rst b/docs/src/cplusplus/lib/utils.rst index ae46bfa8..cfd29103 100644 --- a/docs/src/cplusplus/lib/utils.rst +++ b/docs/src/cplusplus/lib/utils.rst @@ -3,17 +3,17 @@ utils.hpp View source code :source:`cplusplus/src/include/utils.hpp` -.. cpp:namespace-push:: utils +.. cpp:namespace-push:: FileUtils -.. cpp:function:: std::string get_data_file(const char *name) +.. cpp:function:: std::string get_data_file(const std::string& name) Return a character array containing the whole contents of a file found in _data. -.. cpp:function:: char *get_parent_directory(const char *name, const uint32_t levels) +.. cpp:function:: std::filesystem::path get_parent_directory(const std::filesystem::path& path, uint32_t levels) .. cpp:namespace-pop:: -.. literalinclude:: ../../../../cplusplus/src/include/utils.h +.. literalinclude:: ../../../../cplusplus/src/include/utils.hpp :language: C++ :linenos: