LCOV - code coverage report
Current view: top level - src/presets - preset_manager.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 100.0 % 63 63
Test Date: 2026-06-01 11:15:25 Functions: 100.0 % 5 5

            Line data    Source code
       1              : #include "preset_manager.h"
       2              : #include "preset_manager_impl.h"
       3              : #include <iostream>
       4              : #include <ctime>
       5              : #include <sys/stat.h>
       6              : #include <cstdlib>
       7              : #include <cstring>
       8              : #include <filesystem>
       9              : 
      10              : #ifdef _WIN32
      11              : #include <direct.h>
      12              : #include <io.h>
      13              : #include <windows.h>
      14              : #define MKDIR(path) _mkdir(path)
      15              : #define STAT_STRUCT struct _stat
      16              : #define STAT_FN     _stat
      17              : #elif defined(__APPLE__)
      18              : #include <dirent.h>
      19              : #include <mach-o/dyld.h>
      20              : #define MKDIR(path) mkdir(path, 0755)
      21              : #define STAT_STRUCT struct stat
      22              : #define STAT_FN     stat
      23              : #else
      24              : #include <dirent.h>
      25              : #define MKDIR(path) mkdir(path, 0755)
      26              : #define STAT_STRUCT struct stat
      27              : #define STAT_FN     stat
      28              : #endif
      29              : 
      30              : namespace Amplitron {
      31              : 
      32            2 : std::string PresetManager::last_error_;
      33            2 : std::string PresetManager::custom_presets_dir_;
      34              : 
      35          931 : bool dir_exists(const std::string& path) {
      36          309 :     STAT_STRUCT st;
      37         1514 :     return STAT_FN(path.c_str(), &st) == 0 &&
      38              : #ifdef _WIN32
      39          294 :            (st.st_mode & _S_IFDIR);
      40              : #else
      41          894 :            S_ISDIR(st.st_mode);
      42              : #endif
      43              : }
      44              : 
      45           39 : std::string PresetManager::get_system_presets_dir() {
      46              : #ifdef _WIN32
      47           13 :     const char* pd = std::getenv("ProgramData");
      48           26 :     return pd ? std::string(pd) + "\\Amplitron\\presets" : "";
      49              : #elif defined(__APPLE__)
      50           13 :     return "/Library/Application Support/Amplitron/presets";
      51              : #else
      52           26 :     return "/usr/share/amplitron/presets";
      53              : #endif
      54              : }
      55              : 
      56           60 : std::string PresetManager::get_config_path() {
      57              : #ifdef _WIN32
      58           20 :     const char* appdata = std::getenv("APPDATA");
      59           20 :     if (!appdata) return "amplitron_config.json";
      60           34 :     std::string dir = std::string(appdata) + "\\Amplitron";
      61           17 :     MKDIR(dir.c_str());
      62           17 :     return dir + "\\config.json";
      63              : #else
      64           40 :     const char* home = std::getenv("HOME");
      65           46 :     if (!home) return "amplitron_config.json";
      66           34 :     std::string config_dir = std::string(home) + "/.config/amplitron";
      67              :     try {
      68           36 :         std::filesystem::create_directories(config_dir);
      69           19 :     } catch (...) {}
      70           34 :     return config_dir + "/config.json";
      71              : #endif
      72           56 : }
      73              : 
      74           16 : std::string get_user_presets_dir() {
      75              : #ifdef _WIN32
      76            4 :     const char* appdata = std::getenv("APPDATA");
      77            4 :     if (!appdata) return "";
      78            6 :     return std::string(appdata) + "\\Amplitron\\presets";
      79              : #elif defined(__APPLE__)
      80            6 :     const char* home = std::getenv("HOME");
      81            6 :     if (!home) return "";
      82            5 :     return std::string(home) + "/Library/Application Support/Amplitron/presets";
      83              : #else
      84            6 :     const char* home = std::getenv("HOME");
      85            8 :     if (!home) return "";
      86           10 :     return std::string(home) + "/.config/amplitron/presets";
      87              : #endif
      88            6 : }
      89              : 
      90              : // Clean, robust string migration implementation (No JSON header dependencies)
      91           24 : std::string PresetManager::apply_migrations(const std::string& raw_json_string) {
      92              :     // Find the absolute root opening of the JSON payload
      93           24 :     size_t root_start = raw_json_string.find('{');
      94           24 :     if (root_start == std::string::npos) {
      95            6 :         return raw_json_string;
      96              :     }
      97              : 
      98              :     // Look for a "version" key strictly near the root area (e.g., within the first 100 characters)
      99              :     // This stops nested effect parameters from accidentally triggering a false positive bypass.
     100           18 :     size_t version_pos = raw_json_string.find("\"version\"");
     101           18 :     bool is_root_version = (version_pos != std::string::npos && (version_pos - root_start) < 100);
     102              : 
     103           16 :     if (!is_root_version) {
     104           12 :         std::cout << "[Preset Migration] Upgrading legacy unversioned preset format to Version " 
     105           12 :                   << CURRENT_PRESET_VERSION << std::endl;
     106              : 
     107           12 :         std::string patched = raw_json_string;
     108           12 :         size_t last_bracket = patched.find_last_of('}');
     109              :         
     110           12 :         if (last_bracket != std::string::npos && last_bracket > root_start) {
     111              :             // Find out if there is any content between the root brackets to avoid trailing comma bugs
     112           12 :             size_t content_check = patched.find_first_not_of(" \t\n\r", root_start + 1);
     113           12 :             bool is_empty_json = (content_check == last_bracket);
     114              : 
     115              :             // Construct the exact version upgrade block using our header constant dynamically
     116           12 :             std::string migration_patch;
     117           12 :             if (!is_empty_json) {
     118            6 :                 migration_patch += ",\n";
     119            2 :             }
     120           20 :             migration_patch += "  \"version\": " + std::to_string(CURRENT_PRESET_VERSION) + ",\n";
     121           12 :             migration_patch += "  \"input_gain\": 0.7,\n";
     122           12 :             migration_patch += "  \"output_gain\": 0.8\n";
     123              : 
     124           12 :             patched.insert(last_bracket, migration_patch);
     125           12 :             return patched;
     126           12 :         }
     127           12 :     }
     128              : 
     129            6 :     return raw_json_string;
     130            8 : }
     131              : 
     132              : } // namespace Amplitron
        

Generated by: LCOV version 2.0-1