| 19 | constexpr uint8_t MAX_POINTER_SENSITIVITY = 10; |
| 20 | |
| 21 | bool load(TrackballSettings& settings) { |
| 22 | std::map<std::string, std::string> map; |
| 23 | if (!file::loadPropertiesFile(SETTINGS_FILE, map)) { |
| 24 | return false; |
| 25 | } |
| 26 | |
| 27 | auto tb_enabled = map.find(KEY_TRACKBALL_ENABLED); |
| 28 | auto tb_mode = map.find(KEY_TRACKBALL_MODE); |
| 29 | auto enc_sens = map.find(KEY_ENCODER_SENSITIVITY); |
| 30 | auto ptr_sens = map.find(KEY_POINTER_SENSITIVITY); |
| 31 | |
| 32 | // Safe integer parsing without exceptions |
| 33 | auto safeParseUint8 = [](const std::string& str, uint8_t defaultVal) -> uint8_t { |
| 34 | if (str.empty()) return defaultVal; |
| 35 | unsigned int val = 0; |
| 36 | for (char c : str) { |
| 37 | if (c < '0' || c > '9') return defaultVal; |
| 38 | if (val > 25) return defaultVal; // Early exit: val*10+9 would exceed 255 |
| 39 | val = val * 10 + (c - '0'); |
| 40 | if (val > 255) return defaultVal; |
| 41 | } |
| 42 | return static_cast<uint8_t>(val); |
| 43 | }; |
| 44 | |
| 45 | auto isTrueValue = [](const std::string& s) { |
| 46 | return s == "1" || s == "true" || s == "True" || s == "TRUE"; |
| 47 | }; |
| 48 | settings.trackballEnabled = (tb_enabled != map.end()) ? isTrueValue(tb_enabled->second) : true; |
| 49 | settings.trackballMode = (tb_mode != map.end() && tb_mode->second == "1") ? TrackballMode::Pointer : TrackballMode::Encoder; |
| 50 | settings.encoderSensitivity = (enc_sens != map.end()) ? safeParseUint8(enc_sens->second, MIN_ENCODER_SENSITIVITY) : MIN_ENCODER_SENSITIVITY; |
| 51 | settings.pointerSensitivity = (ptr_sens != map.end()) ? safeParseUint8(ptr_sens->second, MAX_POINTER_SENSITIVITY) : MAX_POINTER_SENSITIVITY; |
| 52 | |
| 53 | // Clamp values to valid ranges |
| 54 | settings.encoderSensitivity = std::clamp(settings.encoderSensitivity, MIN_ENCODER_SENSITIVITY, MAX_ENCODER_SENSITIVITY); |
| 55 | settings.pointerSensitivity = std::clamp(settings.pointerSensitivity, MIN_POINTER_SENSITIVITY, MAX_POINTER_SENSITIVITY); |
| 56 | |
| 57 | return true; |
| 58 | } |
| 59 | |
| 60 | TrackballSettings getDefault() { |
| 61 | return TrackballSettings{ |
no test coverage detected