1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 #include "IAILibraryManager.h"
4
5 #include "AILibraryManager.h"
6 #include "AIInterfaceKey.h"
7 #include "SkirmishAIKey.h"
8 #include "System/FileSystem/SimpleParser.h" // for Split()
9
10 #include <climits>
11 #include <cstdio>
12 #include <cstring>
13
14 IAILibraryManager* IAILibraryManager::myAILibraryManager = NULL;
15
GetInstance()16 IAILibraryManager* IAILibraryManager::GetInstance() {
17
18 if (myAILibraryManager == NULL) {
19 myAILibraryManager = new CAILibraryManager();
20 }
21
22 return myAILibraryManager;
23 }
24
Destroy()25 void IAILibraryManager::Destroy() {
26
27 IAILibraryManager* tmp = myAILibraryManager;
28 myAILibraryManager = NULL;
29 delete tmp;
30 }
31
OutputAIInterfacesInfo()32 void IAILibraryManager::OutputAIInterfacesInfo() {
33
34 const IAILibraryManager* myLibManager = IAILibraryManager::GetInstance();
35 const T_interfaceSpecs& keys =
36 myLibManager->GetInterfaceKeys();
37
38 printf("#\n");
39 printf("# Available Spring Skirmish AIs\n");
40 printf("# -----------------------------\n");
41 printf("# %-20s %s\n", "[Name]", "[Version]");
42
43 T_interfaceSpecs::const_iterator key;
44 for (key = keys.begin(); key != keys.end(); ++key) {
45 printf(" %-20s %s\n",
46 key->GetShortName().c_str(), key->GetVersion().c_str());
47 }
48
49 printf("#\n");
50 }
51
ResolveSkirmishAIKey(const SkirmishAIKey & skirmishAIKey) const52 SkirmishAIKey IAILibraryManager::ResolveSkirmishAIKey(
53 const SkirmishAIKey& skirmishAIKey) const {
54
55 std::vector<SkirmishAIKey> fittingKeys
56 = FittingSkirmishAIKeys(skirmishAIKey);
57 if (!fittingKeys.empty()) {
58 // look for the one with the highest version number,
59 // in case there are multiple fitting ones.
60 size_t bestIndex = 0;
61 const std::string* bestVersion = &(fittingKeys[0].GetVersion());
62 for (size_t k = 1; k < fittingKeys.size(); ++k) {
63 if (IAILibraryManager::VersionCompare(fittingKeys[k].GetVersion(), *bestVersion) > 0) {
64 bestIndex = k;
65 bestVersion = &(fittingKeys[k].GetVersion());
66 }
67 }
68 bestVersion = NULL;
69 return fittingKeys[bestIndex];
70 } else {
71 return SkirmishAIKey();
72 }
73 }
74
OutputSkirmishAIInfo()75 void IAILibraryManager::OutputSkirmishAIInfo() {
76
77 const IAILibraryManager* myLibManager = IAILibraryManager::GetInstance();
78 const T_skirmishAIKeys& keys = myLibManager->GetSkirmishAIKeys();
79
80 printf("#\n");
81 printf("# Available Spring Skirmish AIs\n");
82 printf("# -----------------------------\n");
83 printf("# %-20s %-20s %-20s %s\n",
84 "[Name]", "[Version]", "[Interface-name]", "[Interface-version]");
85
86 T_skirmishAIKeys::const_iterator key;
87 for (key = keys.begin(); key != keys.end(); ++key) {
88 printf("# %-20s %-20s %-20s %s\n",
89 key->GetShortName().c_str(),
90 key->GetVersion().c_str(),
91 key->GetInterface().GetShortName().c_str(),
92 key->GetInterface().GetVersion().c_str());
93 }
94
95 const T_dupSkirm& duplicateSkirmishAIInfos =
96 myLibManager->GetDuplicateSkirmishAIInfos();
97 for (T_dupSkirm::const_iterator info = duplicateSkirmishAIInfos.begin();
98 info != duplicateSkirmishAIInfos.end(); ++info) {
99 printf("# WARNING: Duplicate Skirmish AI Info found:\n");
100 printf("# \tfor Skirmish AI: %s %s\n",
101 info->first.GetShortName().c_str(),
102 info->first.GetVersion().c_str());
103 printf("# \tin files:\n");
104 std::set<std::string>::const_iterator dir;
105 for (dir = info->second.begin(); dir != info->second.end(); ++dir) {
106 printf("# \t%s\n", dir->c_str());
107 }
108 }
109
110 printf("#\n");
111 }
112
VersionCompare(const std::string & version1,const std::string & version2)113 int IAILibraryManager::VersionCompare(
114 const std::string& version1,
115 const std::string& version2)
116 {
117 const std::vector<std::string>& parts1 = CSimpleParser::Split(version1, ".");
118 const std::vector<std::string>& parts2 = CSimpleParser::Split(version2, ".");
119 unsigned int maxParts = parts1.size() > parts2.size() ? parts1.size() : parts2.size();
120
121 int diff = 0;
122 for (unsigned int i=0; i < maxParts; ++i) {
123 const std::string& v1p = i < parts1.size() ? parts1.at(i) : "0";
124 const std::string& v2p = i < parts2.size() ? parts2.at(i) : "0";
125 diff += (1<<((maxParts-i)*2)) * v1p.compare(v2p);
126 }
127
128 // computed the sing of diff -> 1, 0 or -1
129 int sign = (diff != 0) | -(int)((unsigned int)((int)diff) >> (sizeof(int) * CHAR_BIT - 1));
130
131 return sign;
132 }
133