diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-08-06 05:57:21 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-08-06 05:57:21 +0200 |
commit | 9f1fddc47ce10fbc65cdeaa70461063b9921434e (patch) | |
tree | e9a8f19fa2ea5445e62ac2f4f8a488c591805347 /src/Utils.cpp | |
parent | b778fd7cc654f28a2bfe0ff74537f120241b289c (diff) |
Copy Config from gpu-screen-recorder-gtk, make it more modern and efficient with string_view and variant, use string_view in gsr info parsing
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r-- | src/Utils.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 0000000..4252de8 --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,176 @@ +#include "../include/Utils.hpp" +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <pwd.h> +#include <limits.h> +#include <string.h> +#include <sys/stat.h> + +namespace gsr { + void string_split_char(std::string_view str, char delimiter, StringSplitCallback callback_func) { + size_t index = 0; + while(index < str.size()) { + size_t new_index = str.find(delimiter, index); + if(new_index == std::string_view::npos) + new_index = str.size(); + + if(!callback_func(str.substr(index, new_index - index))) + break; + + index = new_index + 1; + } + } + + std::optional<KeyValue> parse_key_value(std::string_view line) { + const size_t space_index = line.find(' '); + if(space_index == std::string_view::npos) + return std::nullopt; + return KeyValue{line.substr(0, space_index), line.substr(space_index + 1)}; + } + + std::string get_home_dir() { + const char *home_dir = getenv("HOME"); + if(!home_dir) { + passwd *pw = getpwuid(getuid()); + home_dir = pw->pw_dir; + } + + if(!home_dir) { + fprintf(stderr, "Error: Failed to get home directory of user, using /tmp directory\n"); + home_dir = "/tmp"; + } + + return home_dir; + } + + std::string get_config_dir() { + std::string config_dir; + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + if(xdg_config_home) { + config_dir = xdg_config_home; + } else { + config_dir = get_home_dir() + "/.config"; + } + config_dir += "/gpu-screen-recorder"; + return config_dir; + } + + // Whoever designed xdg-user-dirs is retarded. Why are some XDG variables environment variables + // while others are in this pseudo shell config file ~/.config/user-dirs.dirs + std::map<std::string, std::string> get_xdg_variables() { + std::string user_dirs_filepath; + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + if(xdg_config_home) { + user_dirs_filepath = xdg_config_home; + } else { + user_dirs_filepath = get_home_dir() + "/.config"; + } + + user_dirs_filepath += "/user-dirs.dirs"; + + std::map<std::string, std::string> result; + FILE *f = fopen(user_dirs_filepath.c_str(), "rb"); + if(!f) + return result; + + char line[PATH_MAX]; + while(fgets(line, sizeof(line), f)) { + int len = strlen(line); + if(len < 2) + continue; + + if(line[0] == '#') + continue; + + if(line[len - 1] == '\n') { + line[len - 1] = '\0'; + len--; + } + + if(line[len - 1] != '"') + continue; + + line[len - 1] = '\0'; + len--; + + const char *sep = strchr(line, '='); + if(!sep) + continue; + + if(sep[1] != '\"') + continue; + + std::string value(sep + 2); + if(strncmp(value.c_str(), "$HOME/", 6) == 0) + value = get_home_dir() + value.substr(5); + + std::string key(line, sep - line); + result[std::move(key)] = std::move(value); + } + + fclose(f); + return result; + } + + std::string get_videos_dir() { + auto xdg_vars = get_xdg_variables(); + std::string xdg_videos_dir = xdg_vars["XDG_VIDEOS_DIR"]; + if(xdg_videos_dir.empty()) + xdg_videos_dir = get_home_dir() + "/Videos"; + return xdg_videos_dir; + } + + int create_directory_recursive(char *path) { + int path_len = strlen(path); + char *p = path; + char *end = path + path_len; + for(;;) { + char *slash_p = strchr(p, '/'); + + // Skips first '/', we don't want to try and create the root directory + if(slash_p == path) { + ++p; + continue; + } + + if(!slash_p) + slash_p = end; + + char prev_char = *slash_p; + *slash_p = '\0'; + int err = mkdir(path, S_IRWXU); + *slash_p = prev_char; + + if(err == -1 && errno != EEXIST) + return err; + + if(slash_p == end) + break; + else + p = slash_p + 1; + } + return 0; + } + + bool file_get_content(const char *filepath, std::string &file_content) { + file_content.clear(); + bool success = false; + + FILE *file = fopen(filepath, "rb"); + if(!file) + return success; + + fseek(file, 0, SEEK_END); + long file_size = ftell(file); + if(file_size != -1) { + file_content.resize(file_size); + fseek(file, 0, SEEK_SET); + if((long)fread(&file_content[0], 1, file_size, file) == file_size) + success = true; + } + + fclose(file); + return success; + } +}
\ No newline at end of file |