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"
31 AddonVersion::AddonVersion(const CStdString& version)
33 m_originalVersion = version;
34 if (m_originalVersion.IsEmpty())
35 m_originalVersion = "0.0.0";
36 const char *epoch_end = strchr(m_originalVersion.c_str(), ':');
37 if (epoch_end != NULL)
38 mEpoch = atoi(m_originalVersion.c_str());
42 const char *upstream_start;
44 upstream_start = epoch_end + 1;
46 upstream_start = m_originalVersion.c_str();
48 const char *upstream_end = strrchr(upstream_start, '-');
50 if (upstream_end == NULL)
51 upstream_size = strlen(upstream_start);
53 upstream_size = upstream_end - upstream_start;
55 mUpstream = (char*) malloc(upstream_size + 1);
56 strncpy(mUpstream, upstream_start, upstream_size);
57 mUpstream[upstream_size] = '\0';
59 if (upstream_end == NULL)
60 mRevision = strdup("0");
62 mRevision = strdup(upstream_end + 1);
65 /**Compare two components of a Debian-style version. Return -1, 0, or 1
66 * if a is less than, equal to, or greater than b, respectively.
68 int AddonVersion::CompareComponent(const char *a, const char *b)
72 while (*a && *b && !isdigit(*a) && !isdigit(*b))
76 if (*a == '~') return -1;
77 if (*b == '~') return 1;
78 return *a < *b ? -1 : 1;
83 if (*a && *b && (!isdigit(*a) || !isdigit(*b)))
85 if (*a == '~') return -1;
86 if (*b == '~') return 1;
87 return isdigit(*a) ? -1 : 1;
90 char *next_a, *next_b;
91 long int num_a = strtol(a, &next_a, 10);
92 long int num_b = strtol(b, &next_b, 10);
94 return num_a < num_b ? -1 : 1;
102 return *a == '~' ? -1 : 1;
104 return *b == '~' ? 1 : -1;
107 bool AddonVersion::operator<(const AddonVersion& other) const
109 if (Epoch() != other.Epoch())
110 return Epoch() < other.Epoch();
112 int result = CompareComponent(Upstream(), other.Upstream());
116 return (CompareComponent(Revision(), other.Revision()) < 0);
119 bool AddonVersion::operator==(const AddonVersion& other) const
121 return Epoch() == other.Epoch()
122 && CompareComponent(Upstream(), other.Upstream()) == 0
123 && CompareComponent(Revision(), other.Revision()) == 0;
126 CStdString AddonVersion::Print() const
129 out.Format("%s %s", g_localizeStrings.Get(24051), m_originalVersion); // "Version <str>"
130 return CStdString(out);
133 bool AddonVersion::SplitFileName(CStdString& ID, CStdString& version,
134 const CStdString& filename)
136 int dpos = filename.rfind("-");
139 ID = filename.Mid(0,dpos);
140 version = filename.Mid(dpos+1);
141 version = version.Mid(0,version.size()-4);
146 bool AddonVersion::Test()
148 AddonVersion v1_0("1.0");
149 AddonVersion v1_00("1.00");
150 AddonVersion v1_0_0("1.0.0");
151 AddonVersion v1_1("1.1");
152 AddonVersion v1_01("1.01");
153 AddonVersion v1_0_1("1.0.1");
157 // These are totally sane
158 ret = (v1_0 < v1_1) && (v1_0 < v1_01) && (v1_0 < v1_0_1) &&
159 (v1_1 > v1_0_1) && (v1_01 > v1_0_1);
161 // These are rather sane
162 ret &= (v1_0 != v1_0_0) && (v1_0 < v1_0_0) && (v1_0_0 > v1_0) &&
163 (v1_00 != v1_0_0) && (v1_00 < v1_0_0) && (v1_0_0 > v1_00);
165 ret &= (v1_0 == v1_00) && !(v1_0 < v1_00) && !(v1_0 > v1_00);
166 ret &= (v1_1 == v1_01) && !(v1_1 < v1_01) && !(v1_1 > v1_01);