2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
26 #include "AddonVersion.h"
27 #include "guilib/LocalizeStrings.h"
28 #include "utils/StringUtils.h"
32 AddonVersion::AddonVersion(const CStdString& version)
34 m_originalVersion = version;
35 if (m_originalVersion.empty())
36 m_originalVersion = "0.0.0";
37 const char *epoch_end = strchr(m_originalVersion.c_str(), ':');
38 if (epoch_end != NULL)
39 mEpoch = atoi(m_originalVersion.c_str());
43 const char *upstream_start;
45 upstream_start = epoch_end + 1;
47 upstream_start = m_originalVersion.c_str();
49 const char *upstream_end = strrchr(upstream_start, '-');
51 if (upstream_end == NULL)
52 upstream_size = strlen(upstream_start);
54 upstream_size = upstream_end - upstream_start;
56 mUpstream = (char*) malloc(upstream_size + 1);
57 strncpy(mUpstream, upstream_start, upstream_size);
58 mUpstream[upstream_size] = '\0';
60 if (upstream_end == NULL)
61 mRevision = strdup("0");
63 mRevision = strdup(upstream_end + 1);
66 /**Compare two components of a Debian-style version. Return -1, 0, or 1
67 * if a is less than, equal to, or greater than b, respectively.
69 int AddonVersion::CompareComponent(const char *a, const char *b)
73 while (*a && *b && !isdigit(*a) && !isdigit(*b))
77 if (*a == '~') return -1;
78 if (*b == '~') return 1;
79 return *a < *b ? -1 : 1;
84 if (*a && *b && (!isdigit(*a) || !isdigit(*b)))
86 if (*a == '~') return -1;
87 if (*b == '~') return 1;
88 return isdigit(*a) ? -1 : 1;
91 char *next_a, *next_b;
92 long int num_a = strtol(a, &next_a, 10);
93 long int num_b = strtol(b, &next_b, 10);
95 return num_a < num_b ? -1 : 1;
103 return *a == '~' ? -1 : 1;
105 return *b == '~' ? 1 : -1;
108 bool AddonVersion::operator<(const AddonVersion& other) const
110 if (Epoch() != other.Epoch())
111 return Epoch() < other.Epoch();
113 int result = CompareComponent(Upstream(), other.Upstream());
117 return (CompareComponent(Revision(), other.Revision()) < 0);
120 bool AddonVersion::operator==(const AddonVersion& other) const
122 return Epoch() == other.Epoch()
123 && CompareComponent(Upstream(), other.Upstream()) == 0
124 && CompareComponent(Revision(), other.Revision()) == 0;
127 bool AddonVersion::empty() const
129 return m_originalVersion.empty() || m_originalVersion == "0.0.0";
132 CStdString AddonVersion::Print() const
134 return StringUtils::Format("%s %s", g_localizeStrings.Get(24051).c_str(), m_originalVersion.c_str());
137 bool AddonVersion::SplitFileName(CStdString& ID, CStdString& version,
138 const CStdString& filename)
140 size_t dpos = filename.rfind("-");
141 if (dpos == std::string::npos)
143 ID = filename.substr(0, dpos);
144 version = filename.substr(dpos + 1);
145 version = version.substr(0, version.size() - 4);
150 bool AddonVersion::Test()
152 AddonVersion v1_0("1.0");
153 AddonVersion v1_00("1.00");
154 AddonVersion v1_0_0("1.0.0");
155 AddonVersion v1_1("1.1");
156 AddonVersion v1_01("1.01");
157 AddonVersion v1_0_1("1.0.1");
161 // These are totally sane
162 ret = (v1_0 < v1_1) && (v1_0 < v1_01) && (v1_0 < v1_0_1) &&
163 (v1_1 > v1_0_1) && (v1_01 > v1_0_1);
165 // These are rather sane
166 ret &= (v1_0 != v1_0_0) && (v1_0 < v1_0_0) && (v1_0_0 > v1_0) &&
167 (v1_00 != v1_0_0) && (v1_00 < v1_0_0) && (v1_0_0 > v1_00);
169 ret &= (v1_0 == v1_00) && !(v1_0 < v1_00) && !(v1_0 > v1_00);
170 ret &= (v1_1 == v1_01) && !(v1_1 < v1_01) && !(v1_1 > v1_01);