version 1.8.0
PIString: version functions
This commit is contained in:
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
|
|||||||
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||||
project(pip)
|
project(pip)
|
||||||
set(_PIP_MAJOR 1)
|
set(_PIP_MAJOR 1)
|
||||||
set(_PIP_MINOR 17)
|
set(_PIP_MINOR 18)
|
||||||
set(_PIP_REVISION 0)
|
set(_PIP_REVISION 0)
|
||||||
set(_PIP_SUFFIX alpha)
|
set(_PIP_SUFFIX alpha)
|
||||||
set(_PIP_COMPANY SHS)
|
set(_PIP_COMPANY SHS)
|
||||||
|
|||||||
@@ -211,6 +211,16 @@ piCout << s.find("3"); // 9
|
|||||||
piCout << s.find("3", 4); // 9
|
piCout << s.find("3", 4); // 9
|
||||||
piCout << s.find("3", 10); // -1
|
piCout << s.find("3", 10); // -1
|
||||||
//! [PIString::findLast]
|
//! [PIString::findLast]
|
||||||
|
//! [PIString::findAny]
|
||||||
|
piCout << PIString("1.str").findAny(".,:"); // 1
|
||||||
|
piCout << PIString("1,str").findAny(".,:"); // 1
|
||||||
|
piCout << PIString("1:str").findAny(".,:"); // 1
|
||||||
|
//! [PIString::findAny]
|
||||||
|
//! [PIString::findAnyLast]
|
||||||
|
piCout << PIString("str.0").findAny(".,:"); // 3
|
||||||
|
piCout << PIString("str,0").findAny(".,:"); // 3
|
||||||
|
piCout << PIString("str:0").findAny(".,:"); // 3
|
||||||
|
//! [PIString::findAnyLast]
|
||||||
//! [PIString::findWord]
|
//! [PIString::findWord]
|
||||||
PIString s("this is <PIP>");
|
PIString s("this is <PIP>");
|
||||||
piCout << s.find("this"); // 0
|
piCout << s.find("this"); // 0
|
||||||
|
|||||||
18
main.cpp
18
main.cpp
@@ -118,11 +118,25 @@ PIKbdListener kbd(0, 0, false);
|
|||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
//piCout << PISerial::availableDevicesInfo();
|
//piCout << PISerial::availableDevicesInfo();
|
||||||
PIIODevice * d = PIIODevice::createFromFullPath(argv[1]);
|
/*PIIODevice * d = PIIODevice::createFromFullPath(argv[1]);
|
||||||
piCout << d;
|
piCout << d;
|
||||||
if (d) {
|
if (d) {
|
||||||
d->open();
|
d->open();
|
||||||
piCout << d->constructFullPath() << d->isOpened();
|
piCout << d->constructFullPath() << d->isOpened();
|
||||||
}
|
}*/
|
||||||
|
/*piCout << PIString("1.1,0:1").findAny(".,:");
|
||||||
|
piCout << PIString("1,1,0:1").findAny(".,:");
|
||||||
|
piCout << PIString("1:1,0:1").findAny(".,:");
|
||||||
|
piCout << PIString("1.1,0:1").findAnyLast(".,:");*/
|
||||||
|
piCout << versionNormalize("");
|
||||||
|
piCout << versionNormalize("1");
|
||||||
|
piCout << versionNormalize("1.2");
|
||||||
|
piCout << versionNormalize("1.2.3");
|
||||||
|
piCout << versionNormalize("1.2+rc1.99");
|
||||||
|
piCout << versionNormalize("1.2-alpha");
|
||||||
|
piCout << versionNormalize("1..4_rc2-999");
|
||||||
|
//piCout << versionCompare(".2-alpha", "0.2_alpha");
|
||||||
|
//piCout << versionCompare("1_prebeta", "1.0_alpha");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,48 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*! \fn int versionCompare(const PIString & v0, const PIString & v1, int components = 6)
|
||||||
|
* \relatesalso PIString
|
||||||
|
* \brief Compare two version strings in free notation and returns 0, -1 or 1
|
||||||
|
* \details This function parse version to number codes and labels. Then it
|
||||||
|
* compare no more than "components" codes. If there is no difference, compare
|
||||||
|
* labels. Each label has corresponding integer value, so
|
||||||
|
* "prealpha" < "alpha" < "prebeta" < "beta" < "rcN" < "" < "rN".
|
||||||
|
* Example:
|
||||||
|
* \code
|
||||||
|
* piCout << versionCompare("1.0.0_rc2-999", "1.0.1_rc2-999"); // -1
|
||||||
|
* piCout << versionCompare("1.0.0", "0.9.2"); // 1
|
||||||
|
* piCout << versionCompare("1.0.0_r1", "1.0.0"); // 1
|
||||||
|
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
|
||||||
|
* piCout << versionCompare("1.0.0_r1", "1.0.0", 3); // 0
|
||||||
|
* piCout << versionCompare(".2-alpha", "0.2_alpha"); // 0
|
||||||
|
* piCout << versionCompare("1_prebeta", "1.0_alpha"); // 1
|
||||||
|
* \endcode
|
||||||
|
* \return
|
||||||
|
* * 0 - equal
|
||||||
|
* * 1 - v0 > v1
|
||||||
|
* * -1 - v0 < v1
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* \fn PIString versionNormalize(const PIString & v)
|
||||||
|
* \relatesalso PIString
|
||||||
|
* \brief Converts version string in free notation to classic view
|
||||||
|
* \details Parse version as described in \a versionCompare() and
|
||||||
|
* returns classic view of codes and labels: major.minor.revision[-build][_label].
|
||||||
|
* Example:
|
||||||
|
* \code
|
||||||
|
* piCout << versionNormalize(""); // 0.0.0
|
||||||
|
* piCout << versionNormalize("1"); // 1.0.0
|
||||||
|
* piCout << versionNormalize("1.2"); // 1.2.0
|
||||||
|
* piCout << versionNormalize("1.2.3"); // 1.2.3
|
||||||
|
* piCout << versionNormalize("1.2+rc1.99"); // 1.2.99_rc1
|
||||||
|
* piCout << versionNormalize("1.2-alpha"); // 1.2.0_alpha
|
||||||
|
* piCout << versionNormalize("1..4_rc2-999"); // 1.0.4-999_rc2
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
const char PIString::toBaseN[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
|
||||||
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||||
@@ -760,6 +802,30 @@ int PIString::findRange(const PIChar & start, const PIChar & end, const PIChar &
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIString::findAny(const PIString & str, const int start) const {
|
||||||
|
for (int i = start; i < length(); ++i)
|
||||||
|
if (str.contains(at(i)))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIString::findAnyLast(const PIString & str, const int start) const {
|
||||||
|
for (int i = length() - 1; i >= start; --i)
|
||||||
|
if (str.contains(at(i)))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIString::entries(const PIChar & c) const {
|
||||||
|
int sz = size_s(), ret = 0;
|
||||||
|
for (int i = 0; i < sz; ++i)
|
||||||
|
if (at(i) == c) ++ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIString::startsWith(const PIString & str) const {
|
bool PIString::startsWith(const PIString & str) const {
|
||||||
if (size() < str.size()) return false;
|
if (size() < str.size()) return false;
|
||||||
return str == left(str.size());
|
return str == left(str.size());
|
||||||
@@ -1110,6 +1176,117 @@ inline char chrLwr(char c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const static PIString _versionDelims_ = PIStringAscii("._-+");
|
||||||
|
|
||||||
|
void parseVersion(PIString s, PIVector<int> & codes, PIStringList & strs) {
|
||||||
|
s.trim();
|
||||||
|
if (s.isEmpty()) {
|
||||||
|
codes.resize(3, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int mccnt = 2 - s.entries('.');
|
||||||
|
if (mccnt > 0) {
|
||||||
|
int ind = s.findLast(".") + 1;
|
||||||
|
while (!_versionDelims_.contains(s[ind])) {
|
||||||
|
++ind;
|
||||||
|
if (ind > s.size_s() - 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mccnt; ++i)
|
||||||
|
s.insert(ind, ".0");
|
||||||
|
}
|
||||||
|
PIStringList comps;
|
||||||
|
while (!s.isEmpty()) {
|
||||||
|
int ind = s.findAny(_versionDelims_);
|
||||||
|
if (ind >= 0) {
|
||||||
|
comps << s.takeLeft(ind);
|
||||||
|
s.cutLeft(1).trim();
|
||||||
|
} else {
|
||||||
|
comps << s;
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < comps.size_s(); ++i) {
|
||||||
|
if (comps[i].isEmpty())
|
||||||
|
comps[i] = "0";
|
||||||
|
bool ok = false;
|
||||||
|
int val = comps[i].toInt(-1, &ok);
|
||||||
|
if (ok) {
|
||||||
|
codes << val;
|
||||||
|
} else {
|
||||||
|
strs << comps[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//piCout << codes << strs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int versionLabelValue(PIString s) {
|
||||||
|
int ret = -10000;
|
||||||
|
if (s.isEmpty()) return 0;
|
||||||
|
if (s.startsWith("pre")) {
|
||||||
|
s.cutLeft(3);
|
||||||
|
ret -= 1;
|
||||||
|
}
|
||||||
|
if (s.startsWith("rc")) {
|
||||||
|
s.cutLeft(2);
|
||||||
|
ret += s.toInt();
|
||||||
|
}
|
||||||
|
if (s.startsWith("r")) {
|
||||||
|
s.cutLeft(1);
|
||||||
|
ret += 10000 + s.toInt();
|
||||||
|
}
|
||||||
|
if (s == "alpha") ret -= 4;
|
||||||
|
if (s == "beta" ) ret -= 2;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int versionCompare(const PIString & v0, const PIString & v1, int components) {
|
||||||
|
PIStringList strs[2]; PIVector<int> codes[2];
|
||||||
|
parseVersion(v0.toLowerCase(), codes[0], strs[0]);
|
||||||
|
parseVersion(v1.toLowerCase(), codes[1], strs[1]);
|
||||||
|
//piCout << codes[0] << strs[0];
|
||||||
|
int mc = piMaxi(codes[0].size_s(), codes[1].size_s());
|
||||||
|
if (codes[0].size_s() < mc) codes[0].resize(mc, 0);
|
||||||
|
if (codes[1].size_s() < mc) codes[1].resize(mc, 0);
|
||||||
|
mc = piMaxi(strs[0].size_s(), strs[1].size_s());
|
||||||
|
if (strs[0].size_s() < mc) strs[0].resize(mc, "");
|
||||||
|
if (strs[1].size_s() < mc) strs[1].resize(mc, "");
|
||||||
|
int comps = piMini(components, codes[0].size_s(), codes[1].size_s());
|
||||||
|
if (comps < 1) return (v0 == v1 ? 0 : (v0 > v1 ? 1 : -1));
|
||||||
|
for (int c = 0; c < comps; ++c) {
|
||||||
|
if (codes[0][c] > codes[1][c]) return 1;
|
||||||
|
if (codes[0][c] < codes[1][c]) return -1;
|
||||||
|
}
|
||||||
|
mc = piClampi(mc, 0, components - comps);
|
||||||
|
for (int c = 0; c < mc; ++c) {
|
||||||
|
int lv0 = versionLabelValue(strs[0][c]);
|
||||||
|
int lv1 = versionLabelValue(strs[1][c]);
|
||||||
|
if (lv0 > lv1) return 1;
|
||||||
|
if (lv0 < lv1) return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIString versionNormalize(const PIString & v) {
|
||||||
|
PIStringList strs; PIVector<int> codes;
|
||||||
|
parseVersion(v.toLowerCase(), codes, strs);
|
||||||
|
PIString ret;
|
||||||
|
for (int i = 0; i < codes.size_s(); ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
if (i < 3) ret += ".";
|
||||||
|
else ret += "-";
|
||||||
|
}
|
||||||
|
ret += PIString::fromNumber(codes[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < strs.size_s(); ++i) {
|
||||||
|
ret += "_";
|
||||||
|
ret += strs[i];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PICout operator <<(PICout s, const PIString & v) {
|
PICout operator <<(PICout s, const PIString & v) {
|
||||||
s.space();
|
s.space();
|
||||||
s.quote();
|
s.quote();
|
||||||
@@ -1146,4 +1323,3 @@ PIStringList& PIStringList::removeDuplicates() {
|
|||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -547,7 +547,29 @@ public:
|
|||||||
//! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
|
//! \brief Search range between "start" and "end" symbols at index "start_index" and return first occur position.
|
||||||
//! \details Example: \snippet pistring.cpp PIString::findRange
|
//! \details Example: \snippet pistring.cpp PIString::findRange
|
||||||
int findRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\', const int start_index = 0, int * len = 0) const;
|
int findRange(const PIChar & start, const PIChar & end, const PIChar & shield = '\\', const int start_index = 0, int * len = 0) const;
|
||||||
|
|
||||||
|
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||||
|
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||||
|
int findAny(const PIString & str, const int start = 0) const;
|
||||||
|
|
||||||
|
//! \brief Search any symbol of "str" from symbol at index "start" and return first occur position
|
||||||
|
//! \details Example: \snippet pistring.cpp PIString::findAny
|
||||||
|
int findAny(const char * str, const int start = 0) const {return findAny(PIString(str), start);}
|
||||||
|
|
||||||
|
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||||
|
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||||
|
int findAnyLast(const PIString & str, const int start = 0) const;
|
||||||
|
|
||||||
|
//! \brief Search any symbol of "str" from symbol at index "start" and return last occur position
|
||||||
|
//! \details Example: \snippet pistring.cpp PIString::findAnyLast
|
||||||
|
int findAnyLast(const char * str, const int start = 0) const {return findAnyLast(PIString(str), start);}
|
||||||
|
|
||||||
|
//! \brief Returns number of occurrences of symbol "c"
|
||||||
|
int entries(const PIChar & c) const;
|
||||||
|
|
||||||
|
//! \brief Returns number of occurrences of symbol "c"
|
||||||
|
int entries(char c) const {return entries(PIChar(c));}
|
||||||
|
|
||||||
//! \brief Return if string starts with "str"
|
//! \brief Return if string starts with "str"
|
||||||
bool startsWith(const PIString & str) const;
|
bool startsWith(const PIString & str) const;
|
||||||
|
|
||||||
@@ -785,6 +807,11 @@ inline char chrUpr(char c);
|
|||||||
inline char chrLwr(char c);
|
inline char chrLwr(char c);
|
||||||
|
|
||||||
|
|
||||||
|
int versionCompare(const PIString & v0, const PIString & v1, int components = 6);
|
||||||
|
|
||||||
|
PIString versionNormalize(const PIString & v);
|
||||||
|
|
||||||
|
|
||||||
/*!\brief Strings array class
|
/*!\brief Strings array class
|
||||||
* \details This class is based on \a PIDeque<PIString> and
|
* \details This class is based on \a PIDeque<PIString> and
|
||||||
* expand it functionality. */
|
* expand it functionality. */
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
* This class provide access to serial device, e.g. COM port. It can read,
|
* This class provide access to serial device, e.g. COM port. It can read,
|
||||||
* write, wait for write. There are several read and write functions.
|
* write, wait for write. There are several read and write functions.
|
||||||
*
|
*
|
||||||
* \section PISerial_sec0 FullPath
|
* \section PISerial_sec1 FullPath
|
||||||
* Since version 1.16.0 you can use as \a path DeviceInfo::id() USB identifier.
|
* Since version 1.16.0 you can use as \a path DeviceInfo::id() USB identifier.
|
||||||
* \code
|
* \code
|
||||||
* PISerial * s = new PISerial("0403:6001");
|
* PISerial * s = new PISerial("0403:6001");
|
||||||
|
|||||||
Reference in New Issue
Block a user