1
0
Fork 0
flightgear/src/Add-ons/AddonVersion.hxx

181 lines
6.8 KiB
C++
Raw Normal View History

Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface This commit adds C++ classes for add-on management, most notably AddonManager, Addon and AddonVersion. The AddonManager is used to register add-ons. It relies on an std::map<std::string, AddonRef> to hold the metadata of each registered add-on (keys of the std::map are add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>). Accessor methods are available for: - retrieving the list of registered or loaded add-ons (terminology explained in $FG_ROOT/Docs/README.add-ons); - checking if a particular add-on has already been registered or loaded; - for each add-on, obtaining an Addon instance which can be queried for its name, id, version, base path, the minimum and maximum FlightGear versions it requires, its base node in the Property Tree, its order in the load sequence, short and long description strings, home page, etc. The most important metadata is made accessible in the Property Tree under /addons/by-id/<addon-id> and the property /addons/by-id/<addon-id>/loaded can be checked or listened to, in order to determine when a particular add-on is loaded. There is also a Nasal interface to access add-on metadata in a convenient way. In order to provide this metadata, each add-on must from now on have in its base directory a file called 'addon-metadata.xml'. All this is documented in much more detail in $FG_ROOT/Docs/README.add-ons. Mailing-list discussion: https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 13:58:14 +01:00
// -*- coding: utf-8 -*-
//
// AddonVersion.hxx --- Version class for FlightGear add-ons
// Copyright (C) 2017 Florent Rougon
//
// 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 2 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, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#ifndef FG_ADDONVERSION_HXX
#define FG_ADDONVERSION_HXX
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <simgear/nasal/cppbind/NasalCallContext.hxx>
#include <simgear/nasal/cppbind/NasalHash.hxx>
#include <simgear/structure/SGReferenced.hxx>
#include "addon_fwd.hxx"
namespace flightgear
{
namespace addons
{
Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface This commit adds C++ classes for add-on management, most notably AddonManager, Addon and AddonVersion. The AddonManager is used to register add-ons. It relies on an std::map<std::string, AddonRef> to hold the metadata of each registered add-on (keys of the std::map are add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>). Accessor methods are available for: - retrieving the list of registered or loaded add-ons (terminology explained in $FG_ROOT/Docs/README.add-ons); - checking if a particular add-on has already been registered or loaded; - for each add-on, obtaining an Addon instance which can be queried for its name, id, version, base path, the minimum and maximum FlightGear versions it requires, its base node in the Property Tree, its order in the load sequence, short and long description strings, home page, etc. The most important metadata is made accessible in the Property Tree under /addons/by-id/<addon-id> and the property /addons/by-id/<addon-id>/loaded can be checked or listened to, in order to determine when a particular add-on is loaded. There is also a Nasal interface to access add-on metadata in a convenient way. In order to provide this metadata, each add-on must from now on have in its base directory a file called 'addon-metadata.xml'. All this is documented in much more detail in $FG_ROOT/Docs/README.add-ons. Mailing-list discussion: https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 13:58:14 +01:00
// Order matters for the sorting/comparison functions
enum class AddonVersionSuffixPrereleaseType {
alpha = 0,
beta,
candidate,
none
};
// ***************************************************************************
// * AddonVersionSuffix *
// ***************************************************************************
class AddonVersionSuffix
{
public:
AddonVersionSuffix(AddonVersionSuffixPrereleaseType _preReleaseType
= AddonVersionSuffixPrereleaseType::none,
int preReleaseNum = 0, bool developmental = false,
int devNum = 0);
// Construct from a string. The empty string is a valid input.
AddonVersionSuffix(const std::string& suffix);
AddonVersionSuffix(const char* suffix);
// Construct from a tuple
explicit AddonVersionSuffix(
const std::tuple<AddonVersionSuffixPrereleaseType, int, bool, int>& t);
// Return all components of an AddonVersionSuffix instance as a tuple.
// Beware, this is not suitable for sorting! cf. genSortKey() below.
std::tuple<AddonVersionSuffixPrereleaseType, int, bool, int> makeTuple() const;
// String representation of an AddonVersionSuffix
std::string str() const;
private:
// Extract all components from a string representing a version suffix.
// The components of the return value are, in this order:
//
// preReleaseType, preReleaseNum, developmental, devNum
//
// Note: the empty string is a valid input.
static std::tuple<AddonVersionSuffixPrereleaseType, int, bool, int>
suffixStringToTuple(const std::string& suffix);
// String representation of the release type component: "a", "b", "rc" or "".
static std::string releaseTypeStr(AddonVersionSuffixPrereleaseType);
// Useful for comparisons/sorting purposes
std::tuple<int,
std::underlying_type<AddonVersionSuffixPrereleaseType>::type,
int, int, int> genSortKey() const;
friend bool operator==(const AddonVersionSuffix& lhs,
const AddonVersionSuffix& rhs);
friend bool operator<(const AddonVersionSuffix& lhs,
const AddonVersionSuffix& rhs);
AddonVersionSuffixPrereleaseType _preReleaseType;
int _preReleaseNum; // integer >= 1 (0 when not applicable)
bool _developmental; // whether the suffix ends with '.devN'
int _devNum; // integer >= 1 (0 when not applicable)
};
// operator==() and operator<() are declared above.
bool operator!=(const AddonVersionSuffix& lhs, const AddonVersionSuffix& rhs);
bool operator> (const AddonVersionSuffix& lhs, const AddonVersionSuffix& rhs);
bool operator<=(const AddonVersionSuffix& lhs, const AddonVersionSuffix& rhs);
bool operator>=(const AddonVersionSuffix& lhs, const AddonVersionSuffix& rhs);
std::ostream& operator<<(std::ostream&, const AddonVersionSuffix&);
// ***************************************************************************
// * AddonVersion *
// ***************************************************************************
// I suggest to use either the year-based FlightGear-type versioning, or
// semantic versioning (<http://semver.org/>). For the suffix, we allow things
// like "a1" (alpha1), "b2" (beta2), "rc4" (release candidate 4), "a1.dev3"
// (development release for "a1", which sorts before "a1"), etc. It's a subset
// of the syntax allowed in <https://www.python.org/dev/peps/pep-0440/>.
class AddonVersion : public SGReferenced
{
public:
AddonVersion(int major = 0, int minor = 0, int patchLevel = 0,
AddonVersionSuffix suffix = AddonVersionSuffix());
AddonVersion(const std::string& version);
AddonVersion(const char* version);
explicit AddonVersion(const std::tuple<int, int, int, AddonVersionSuffix>& t);
// Using the method names major() and minor() can lead to incomprehensible
// errors such as "major is not a member of flightgear::AddonVersion"
// because of a hideous glibc bug[1]: major() and minor() are defined by
// standard headers as *macros*!
//
// [1] https://bugzilla.redhat.com/show_bug.cgi?id=130601
int majorNumber() const;
int minorNumber() const;
int patchLevel() const;
AddonVersionSuffix suffix() const;
std::string suffixStr() const;
std::string str() const;
// For the Nasal bindings (otherwise, we have operator==(), etc.)
bool equal(const nasal::CallContext& ctx) const;
bool nonEqual(const nasal::CallContext& ctx) const;
bool lowerThan(const nasal::CallContext& ctx) const;
bool lowerThanOrEqual(const nasal::CallContext& ctx) const;
bool greaterThan(const nasal::CallContext& ctx) const;
bool greaterThanOrEqual(const nasal::CallContext& ctx) const;
static void setupGhost(nasal::Hash& addonsModule);
private:
// Useful for comparisons/sorting purposes
std::tuple<int, int, int, AddonVersionSuffix> makeTuple() const;
static std::tuple<int, int, int, AddonVersionSuffix>
versionStringToTuple(const std::string& versionStr);
friend bool operator==(const AddonVersion& lhs, const AddonVersion& rhs);
friend bool operator<(const AddonVersion& lhs, const AddonVersion& rhs);
int _major;
int _minor;
int _patchLevel;
AddonVersionSuffix _suffix;
};
// operator==() and operator<() are declared above.
bool operator!=(const AddonVersion& lhs, const AddonVersion& rhs);
bool operator> (const AddonVersion& lhs, const AddonVersion& rhs);
bool operator<=(const AddonVersion& lhs, const AddonVersion& rhs);
bool operator>=(const AddonVersion& lhs, const AddonVersion& rhs);
std::ostream& operator<<(std::ostream&, const AddonVersion&);
} // of namespace addons
Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface This commit adds C++ classes for add-on management, most notably AddonManager, Addon and AddonVersion. The AddonManager is used to register add-ons. It relies on an std::map<std::string, AddonRef> to hold the metadata of each registered add-on (keys of the std::map are add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>). Accessor methods are available for: - retrieving the list of registered or loaded add-ons (terminology explained in $FG_ROOT/Docs/README.add-ons); - checking if a particular add-on has already been registered or loaded; - for each add-on, obtaining an Addon instance which can be queried for its name, id, version, base path, the minimum and maximum FlightGear versions it requires, its base node in the Property Tree, its order in the load sequence, short and long description strings, home page, etc. The most important metadata is made accessible in the Property Tree under /addons/by-id/<addon-id> and the property /addons/by-id/<addon-id>/loaded can be checked or listened to, in order to determine when a particular add-on is loaded. There is also a Nasal interface to access add-on metadata in a convenient way. In order to provide this metadata, each add-on must from now on have in its base directory a file called 'addon-metadata.xml'. All this is documented in much more detail in $FG_ROOT/Docs/README.add-ons. Mailing-list discussion: https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 13:58:14 +01:00
} // of namespace flightgear
#endif // of FG_ADDONVERSION_HXX