pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/common/SemanticVersion.cc

299 lines
7.8 KiB
C++

/*
* Copyright (C) 2016 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include "SemanticVersion.hh"
using namespace gazebo;
using namespace common;
namespace gazebo
{
namespace common
{
class SemanticVersionPrivate
{
/// \brief Major revision (incompatible api changes)
public: unsigned int maj = 0;
/// \brief Minor revision (backwards compatible new functionality)
public: unsigned int min = 0;
/// \brief Patch (bug fixes)
public: unsigned int patch = 0;
/// \brief Optional pre-release info. A prerelease string may be
/// denoted by appending a hyphen and a series of dot separated
/// identifiers immediately following the patch version
public: std::string prerelease = "";
/// \brief Optional build meta-data. Build metadata may be denoted by
/// appending a plus sign and a series of dot separated identifiers
/// immediately following the patch or pre-release version
public: std::string build = "";
};
}
}
/////////////////////////////////////////////////
SemanticVersion::SemanticVersion()
: dataPtr(new SemanticVersionPrivate())
{
}
/////////////////////////////////////////////////
SemanticVersion::SemanticVersion(const std::string &_versionStr)
: dataPtr(new SemanticVersionPrivate())
{
this->Parse(_versionStr);
}
/////////////////////////////////////////////////
SemanticVersion::SemanticVersion(const unsigned int _major,
const unsigned int _minor,
const unsigned int _patch,
const std::string &_prerelease,
const std::string &_build)
: dataPtr(new SemanticVersionPrivate())
{
this->dataPtr->maj = _major;
this->dataPtr->min = _minor;
this->dataPtr->patch = _patch;
this->dataPtr->prerelease = _prerelease;
this->dataPtr->build = _build;
}
/////////////////////////////////////////////////
SemanticVersion::SemanticVersion(const SemanticVersion &_copy)
: dataPtr(new SemanticVersionPrivate())
{
*this->dataPtr = *_copy.dataPtr;
}
/////////////////////////////////////////////////
SemanticVersion& SemanticVersion::operator=(const SemanticVersion &_other)
{
*this->dataPtr = *_other.dataPtr;
return *this;
}
/////////////////////////////////////////////////
SemanticVersion::~SemanticVersion()
{
}
/////////////////////////////////////////////////
std::string SemanticVersion::Version() const
{
std::string result = std::to_string(this->dataPtr->maj) + "." +
std::to_string(this->dataPtr->min) + "." +
std::to_string(this->dataPtr->patch);
if (!this->dataPtr->prerelease.empty())
result += "-" + this->dataPtr->prerelease;
if (!this->dataPtr->build.empty())
result += "+" + this->dataPtr->build;
return result;
}
/////////////////////////////////////////////////
bool SemanticVersion::operator<(const SemanticVersion &_other) const
{
if (this == &_other)
return false;
if (this->dataPtr->maj < _other.dataPtr->maj)
{
return true;
}
if (this->dataPtr->maj > _other.dataPtr->maj)
{
return false;
}
if (this->dataPtr->min < _other.dataPtr->min)
{
return true;
}
if (this->dataPtr->min > _other.dataPtr->min)
{
return false;
}
if (this->dataPtr->patch < _other.dataPtr->patch)
{
return true;
}
if (this->dataPtr->patch > _other.dataPtr->patch)
{
return false;
}
// If this version has prelrease and the _other doesn't, then this
// version is lower. We don't compare the prerelease strings because
// they can contain any alphanumeric values.
if (!this->dataPtr->prerelease.empty() && _other.dataPtr->prerelease.empty())
return true;
// _other is equal
return false;
}
/////////////////////////////////////////////////
bool SemanticVersion::operator<=(const SemanticVersion &_other) const
{
return (_other > *this) || (_other == *this);
}
/////////////////////////////////////////////////
bool SemanticVersion::operator>(const SemanticVersion &_other) const
{
return (_other < *this);
}
/////////////////////////////////////////////////
bool SemanticVersion::operator>=(const SemanticVersion &_other) const
{
return (_other < *this) || (_other == *this);
}
/////////////////////////////////////////////////
bool SemanticVersion::operator==(const SemanticVersion &_other) const
{
if (this == &_other)
return true;
return (_other.dataPtr->maj == this->dataPtr->maj)
&& (_other.dataPtr->min == this->dataPtr->min)
&& (_other.dataPtr->patch == this->dataPtr->patch);
}
/////////////////////////////////////////////////
bool SemanticVersion::operator!=(const SemanticVersion &_other) const
{
return !(*this == _other);
}
/////////////////////////////////////////////////
unsigned int SemanticVersion::Major() const
{
return this->dataPtr->maj;
}
/////////////////////////////////////////////////
unsigned int SemanticVersion::Minor() const
{
return this->dataPtr->min;
}
/////////////////////////////////////////////////
unsigned int SemanticVersion::Patch() const
{
return this->dataPtr->patch;
}
/////////////////////////////////////////////////
std::string SemanticVersion::Prerelease() const
{
return this->dataPtr->prerelease;
}
/////////////////////////////////////////////////
std::string SemanticVersion::Build() const
{
return this->dataPtr->build;
}
/////////////////////////////////////////////////
bool SemanticVersion::Parse(const std::string &_versionStr)
{
if (_versionStr.empty())
return false;
size_t numericEnd = _versionStr.size();
size_t prereleaseStart = _versionStr.find("-");
size_t buildStart = _versionStr.find("+");
// Build meta data, if present, must be after prerelease string, if
// present
if (buildStart != std::string::npos &&
prereleaseStart != std::string::npos &&
buildStart < prereleaseStart)
{
return false;
}
// Check if a prerelease version is present
if (prereleaseStart != std::string::npos)
{
// Set the end of the numeric (major.minor.patch) portion to the
// start of the prerelease
numericEnd = prereleaseStart;
// Check if build metadata is present
if (buildStart != std::string::npos)
{
// Set prerelease to the portion between "-" and "+"
this->dataPtr->prerelease = _versionStr.substr(numericEnd + 1,
buildStart - numericEnd - 1);
// Get the build metadata.
this->dataPtr->build = _versionStr.substr(buildStart + 1);
}
else
{
// Set prerelease to the portion between "-" and the string's end
this->dataPtr->prerelease = _versionStr.substr(numericEnd + 1);
}
}
// Check if build metadata is present
else if (buildStart != std::string::npos)
{
// Set the end of the numeric (major.minor.patch) portion to the
// start of the build metadata
numericEnd = buildStart;
// Pre-release info can't follow the build metadata.
this->dataPtr->build = _versionStr.substr(numericEnd + 1);
}
std::string numeric = _versionStr.substr(0, numericEnd);
std::istringstream is(numeric);
std::string token;
for (int i = 0; std::getline(is, token, '.'); ++i)
{
switch (i)
{
default:
case 0:
this->dataPtr->maj = std::stoi(token);
break;
case 1:
this->dataPtr->min = std::stoi(token);
break;
case 2:
this->dataPtr->patch = std::stoi(token);
break;
};
}
return true;
}