-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOSVersionsList.cpp
160 lines (125 loc) · 5.26 KB
/
OSVersionsList.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/****************************************************************************/
/* */
/* OSVersionsList class implementation */
/* */
/****************************************************************************/
#include <cstdlib> // NULL definition
#include "OSVersionsList.h"
void OSVersionsList::addVersion(int versionCode) {
if (versionCode <= 0) {
throw InvalidVersionCodeException();
}
// First make sure that the versionCode is indeed larger than the largest
// versionCode we currently have
if ( (!isEmpty()) && (begin()->versionCode >= versionCode) ) {
throw VersionCodeNotLargerThanCurrentException();
}
// The new versionCode is good, allocate a new struct with it and
// insert it into the list
OSVersionData data(versionCode);
insertFront(data);
}
int OSVersionsList::getTopAppId(int versionCode) const {
// Search for the OSVersionData node with the relevant versionCode
// (an exception will be thrown if it is not found)
Iterator iter = getOSVersionDataByVersionCode(versionCode);
// Found our node, return the top app if there is one
if (iter->versionTopAppId == INVALID_VERSION_TOP_APP_ID) {
throw NoSuchAppException();
}
return iter->versionTopAppId;
}
void OSVersionsList::addApp(const AppsListIterator& appDataPtr) {
// Search for the OSVersionData node with the relevant versionCode
// (an exception will be thrown if it is not found)
Iterator iter = getOSVersionDataByVersionCode(appDataPtr->versionCode);
// Found our node, add the app to the versionAppsByDownloadCount tree in it
try {
iter->versionAppsByDownloadCount.addApp(appDataPtr);
} catch (const DuplicateNodeException& e) {
throw AppAlreadyExistsException();
}
// App was successfully added, don't forget to update versionTopAppId and
// versionTopAppDownloadCount if needed
updateVersionTopApp(iter);
}
void OSVersionsList::removeApp(int versionCode, int downloadCount, int appId) {
// Search for the OSVersionData node with the relevant versionCode
// (an exception will be thrown if it is not found)
Iterator iter = getOSVersionDataByVersionCode(versionCode);
// Found our node, remove the app from the versionAppsByDownloadCount tree
// in it
try {
iter->versionAppsByDownloadCount.removeApp(downloadCount, appId);
} catch (const ElementNotFoundException& e) {
throw NoSuchAppException();
}
// App was successfully removed, don't forget to update
// versionTopAppId and versionTopAppDownloadCount if needed
updateVersionTopApp(iter);
}
// Throws NoSuchVersionCodeException if is no such versionCode in the list,
// or there is no versionCode in the list which is larger than the given one
int OSVersionsList::getFollowingVersion(int versionCode) const {
if (versionCode <= 0) {
throw InvalidVersionCodeException();
}
// Iterate over all nodes until one matches the version code
FilterByVersionCodePredicate predicate;
Node* p = mHead;
while (p) {
if (predicate(p->data, (void*) versionCode)) {
// Found it - Return the previous node's versionCode
if (p->prev) {
return p->prev->data->versionCode;
}
// The versionCode given is the largest one, we cannot return
// the following version
throw VersionCodeIsLastException();
}
p = p->next;
}
// Given versionCode is not in the list
throw NoSuchVersionCodeException();
}
AppsByDownloadCountTree* OSVersionsList::getAppsByDownloadCountTree(int versionCode) const {
// Search for the OSVersionData node with the relevant versionCode
// the following version
Iterator iter = getOSVersionDataByVersionCode(versionCode);
return &(iter->versionAppsByDownloadCount);
}
void OSVersionsList::updateVersionTopApp(Iterator& iter) {
try {
AppsListIterator* newTopAppPtr = iter->versionAppsByDownloadCount.getMax();
AppsListIterator newTopApp = *newTopAppPtr;
iter->versionTopAppDownloadCount = newTopApp->downloadCount;
iter->versionTopAppId = newTopApp->appId;
} catch (const ElementNotFoundException& e) {
// This happens when there are no elements in versionAppsByDownloadCount
// In this case update the versionTopApp to an invalid value
iter->versionTopAppDownloadCount = -1;
iter->versionTopAppId = INVALID_VERSION_TOP_APP_ID;
}
}
// Private:
OSVersionsList::Iterator OSVersionsList::getOSVersionDataByVersionCode(int versionCode) const {
if (versionCode <= 0) {
throw InvalidVersionCodeException();
}
Iterator iter;
try {
iter = getIteratorByPredicate(FilterByVersionCodePredicate(),
(void*) versionCode);
} catch (const NoSuchNodeException& e) {
throw NoSuchVersionCodeException();
}
return iter;
}
bool OSVersionsList::FilterByVersionCodePredicate::operator()
(const OSVersionData* dataPtr, void* versionCode) const {
// NOTE: Using "long int" here because on 64-bit machines it is
// not possible to convert void* into int. If we try this we get:
// error: cast from ‘void*’ to ‘int’ loses precision
long int versionCodeInt = (long int) versionCode;
return (dataPtr->versionCode == versionCodeInt);
}