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