diff --git a/src/core/EMSESP_Version.h b/src/core/EMSESP_Version.h deleted file mode 100644 index 0803be2b5..000000000 --- a/src/core/EMSESP_Version.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * EMS-ESP - https://github.com/emsesp/EMS-ESP - * Copyright 2020-2026 emsesp.org - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef EMSESP_Version_H -#define EMSESP_Version_H - -#include -#include -#include - -// Drop-in lightweight replacement for the subset of the semver library actually used by EMS-ESP. -// The previous semver library (lib/semver) builds a std::map + std::function-based state machine on -// every parse, which fragments the internal heap on the ESP32. This replacement does no heap -// allocation beyond the std::string member for the prerelease tag, and matches the API surface -// we consume: construction from string, major()/minor()/patch()/prerelease(), and operator>/(const EMSESP_Version & a, const EMSESP_Version & b) { - return b < a; - } - - friend bool operator==(const EMSESP_Version & a, const EMSESP_Version & b) { - return a.major_ == b.major_ && a.minor_ == b.minor_ && a.patch_ == b.patch_ && a.prerelease_ == b.prerelease_; - } - - friend bool operator!=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(a == b); - } - - friend bool operator>=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(a < b); - } - - friend bool operator<=(const EMSESP_Version & a, const EMSESP_Version & b) { - return !(b < a); - } - - private: - int major_ = 0; - int minor_ = 0; - int patch_ = 0; - std::string prerelease_; - - void parse(const char * s) { - major_ = minor_ = patch_ = 0; - prerelease_.clear(); - if (s == nullptr || *s == '\0') { - return; - } - // parse numeric major.minor.patch; accept partial ("3", "3.9", "3.9.0") - sscanf(s, "%d.%d.%d", &major_, &minor_, &patch_); - // capture prerelease tag after '-' if present (stop at '+' which is build metadata) - const char * dash = strchr(s, '-'); - if (dash != nullptr) { - const char * plus = strchr(dash, '+'); - if (plus != nullptr) { - prerelease_.assign(dash + 1, plus - dash - 1); - } else { - prerelease_.assign(dash + 1); - } - } - } -}; - -} // namespace version - -#endif diff --git a/src/core/firmwareVersion.cpp b/src/core/firmwareVersion.cpp new file mode 100644 index 000000000..de2aed742 --- /dev/null +++ b/src/core/firmwareVersion.cpp @@ -0,0 +1,100 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2026 emsesp.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "firmwareVersion.h" + +#include +#include + +namespace emsesp { + +FirmwareVersion::FirmwareVersion(const std::string & s) { + parse(s.c_str()); +} + +FirmwareVersion::FirmwareVersion(const char * s) { + parse(s ? s : ""); +} + +int FirmwareVersion::major() const { + return major_; +} + +int FirmwareVersion::minor() const { + return minor_; +} + +int FirmwareVersion::patch() const { + return patch_; +} + +const std::string & FirmwareVersion::prerelease() const { + return prerelease_; +} + +bool operator<(const FirmwareVersion & a, const FirmwareVersion & b) { + if (a.major_ != b.major_) + return a.major_ < b.major_; + if (a.minor_ != b.minor_) + return a.minor_ < b.minor_; + if (a.patch_ != b.patch_) + return a.patch_ < b.patch_; + return a.prerelease_ < b.prerelease_; +} + +bool operator>(const FirmwareVersion & a, const FirmwareVersion & b) { + return b < a; +} + +bool operator==(const FirmwareVersion & a, const FirmwareVersion & b) { + return a.major_ == b.major_ && a.minor_ == b.minor_ && a.patch_ == b.patch_ && a.prerelease_ == b.prerelease_; +} + +bool operator!=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(a == b); +} + +bool operator>=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(a < b); +} + +bool operator<=(const FirmwareVersion & a, const FirmwareVersion & b) { + return !(b < a); +} + +void FirmwareVersion::parse(const char * s) { + major_ = minor_ = patch_ = 0; + prerelease_.clear(); + if (s == nullptr || *s == '\0') { + return; + } + // parse numeric major.minor.patch; accept partial ("3", "3.9", "3.9.0") + sscanf(s, "%d.%d.%d", &major_, &minor_, &patch_); + // capture prerelease tag after '-' if present (stop at '+' which is build metadata) + const char * dash = strchr(s, '-'); + if (dash != nullptr) { + const char * plus = strchr(dash, '+'); + if (plus != nullptr) { + prerelease_.assign(dash + 1, plus - dash - 1); + } else { + prerelease_.assign(dash + 1); + } + } +} + +} // namespace emsesp diff --git a/src/core/firmwareVersion.h b/src/core/firmwareVersion.h new file mode 100644 index 000000000..8076b14c5 --- /dev/null +++ b/src/core/firmwareVersion.h @@ -0,0 +1,59 @@ +/* + * EMS-ESP - https://github.com/emsesp/EMS-ESP + * Copyright 2020-2026 emsesp.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef firmwareVersion_H +#define firmwareVersion_H + +#include + +namespace emsesp { + +class FirmwareVersion { + public: + FirmwareVersion() = default; + + // Construct from a version string like "3.9.0-dev.14" or "3.9.0". + // Anything past a '-' or '+' is kept as the prerelease string and not interpreted. + explicit FirmwareVersion(const std::string & s); + explicit FirmwareVersion(const char * s); + + int major() const; + int minor() const; + int patch() const; + const std::string & prerelease() const; + + // Numeric-only comparison (major.minor.patch). Prerelease tags are ignored on purpose. + friend bool operator<(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator>(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator==(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator!=(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator>=(const FirmwareVersion & a, const FirmwareVersion & b); + friend bool operator<=(const FirmwareVersion & a, const FirmwareVersion & b); + + private: + int major_ = 0; + int minor_ = 0; + int patch_ = 0; + std::string prerelease_; + + void parse(const char * s); +}; + +} // namespace emsesp + +#endif diff --git a/src/core/system.cpp b/src/core/system.cpp index e2a8fb8ba..f3ab8073d 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -31,7 +31,7 @@ #include #include -#include "EMSESP_Version.h" +#include "firmwareVersion.h" #if defined(EMSESP_TEST) #include "../test/test.h" @@ -1541,8 +1541,8 @@ bool System::check_upgrade() { settingsVersion = "3.5.0"; // this was the last stable version without version info } - version::EMSESP_Version settings_version(settingsVersion); - version::EMSESP_Version this_version(EMSESP_APP_VERSION); + FirmwareVersion settings_version(settingsVersion); + FirmwareVersion this_version(EMSESP_APP_VERSION); std::string settings_version_type = settings_version.prerelease().empty() ? "" : ("-" + settings_version.prerelease()); std::string this_version_type = this_version.prerelease().empty() ? "" : ("-" + this_version.prerelease());