Line data Source code
1 : /**
2 : * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "plugin_pkg_version.h"
12 :
13 : #include <algorithm>
14 : #include <cctype>
15 : #include <fstream>
16 : #include <sstream>
17 : #include <vector>
18 :
19 : #include "tsd_util_func.h"
20 :
21 : namespace tsd {
22 : namespace {
23 : const std::string PKG_SUFFIX = ".tar.gz";
24 : const std::string INI_SUFFIX = ".ini";
25 : const std::string KEY_VERSION = "version";
26 : const std::string KEY_TIMESTAMP = "timestamp";
27 : } // namespace
28 :
29 3 : std::string PluginPkgVersionUtil::GetIniNameByPkgName(const std::string& pkgName)
30 : {
31 5 : if (pkgName.size() > PKG_SUFFIX.size() &&
32 2 : pkgName.compare(pkgName.size() - PKG_SUFFIX.size(), PKG_SUFFIX.size(), PKG_SUFFIX) == 0) {
33 2 : return pkgName.substr(0U, pkgName.size() - PKG_SUFFIX.size()) + INI_SUFFIX;
34 : }
35 1 : return pkgName + INI_SUFFIX;
36 : }
37 :
38 12 : bool PluginPkgVersionUtil::ParseLine(const std::string& line, std::string& key, std::string& value)
39 : {
40 12 : std::string trimmed = line;
41 12 : TrimWhitespace(trimmed);
42 12 : if (trimmed.empty() || trimmed[0] == '#' || trimmed[0] == ';') {
43 3 : return false;
44 : }
45 9 : auto pos = trimmed.find('=');
46 9 : if (pos == std::string::npos || pos == 0U) {
47 2 : return false;
48 : }
49 7 : key = trimmed.substr(0U, pos);
50 7 : value = trimmed.substr(pos + 1U);
51 7 : TrimWhitespace(key);
52 7 : TrimWhitespace(value);
53 7 : return !key.empty();
54 12 : }
55 :
56 5 : bool PluginPkgVersionUtil::ParseIniFile(const std::string& iniPath, PluginPkgVersion& info)
57 : {
58 5 : std::ifstream ifs(iniPath);
59 5 : if (!ifs.is_open()) {
60 2 : return false;
61 : }
62 3 : info.version.clear();
63 3 : info.timestamp.clear();
64 3 : constexpr int32_t kMaxLines = 10;
65 3 : int32_t lineCount = 0;
66 3 : std::string line;
67 7 : while (lineCount < kMaxLines && std::getline(ifs, line)) {
68 6 : ++lineCount;
69 6 : std::string k;
70 6 : std::string v;
71 6 : if (!ParseLine(line, k, v)) {
72 1 : continue;
73 : }
74 : // key 大小写不敏感,统一转小写后再比较,兼容 Version=/VERSION=/version= 等写法
75 5 : std::transform(
76 41 : k.begin(), k.end(), k.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
77 5 : if (k == KEY_VERSION) {
78 2 : info.version = v;
79 3 : } else if (k == KEY_TIMESTAMP) {
80 3 : info.timestamp = v;
81 : }
82 5 : if (!info.version.empty() && !info.timestamp.empty()) {
83 2 : break;
84 : }
85 9 : }
86 3 : return !info.version.empty();
87 5 : }
88 :
89 16 : int32_t PluginPkgVersionUtil::CompareVersion(const std::string& versionA, const std::string& versionB)
90 : {
91 16 : std::vector<std::string> partsA = SplitByChar(versionA, '.');
92 16 : std::vector<std::string> partsB = SplitByChar(versionB, '.');
93 16 : size_t n = std::max(partsA.size(), partsB.size());
94 46 : for (size_t i = 0U; i < n; ++i) {
95 41 : const std::string& a = (i < partsA.size()) ? partsA[i] : std::string("0");
96 40 : const std::string& b = (i < partsB.size()) ? partsB[i] : std::string("0");
97 40 : int32_t cmp = CompareSegmentNumeric(a, b);
98 40 : if (cmp != 0) {
99 10 : return cmp;
100 : }
101 50 : }
102 6 : return 0;
103 16 : }
104 :
105 6 : int32_t PluginPkgVersionUtil::CompareTimestamp(const std::string& timestampA, const std::string& timestampB)
106 : {
107 6 : if (timestampA == timestampB) {
108 3 : return 0;
109 : }
110 3 : return (timestampA < timestampB) ? -1 : 1;
111 : }
112 :
113 8 : int32_t PluginPkgVersionUtil::Compare(const PluginPkgVersion& a, const PluginPkgVersion& b)
114 : {
115 8 : int32_t cmp = CompareVersion(a.version, b.version);
116 8 : if (cmp != 0) {
117 5 : return cmp;
118 : }
119 3 : return CompareTimestamp(a.timestamp, b.timestamp);
120 : }
121 :
122 : } // namespace tsd
|