some cleanup
[ppastats.git] / src / lp.c
1 /*
2  * Copyright (C) 2011-2014 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "list.h"
25 #include "lp.h"
26 #include <ptime.h>
27
28 struct distro_series *distro_series_new(const char *name,
29                                         const char *version,
30                                         const char *title,
31                                         const char *displayname)
32 {
33         struct distro_series *d;
34
35         d = malloc(sizeof(struct distro_series));
36
37         d->name = strdup(name);
38         d->version = strdup(version);
39         d->title = strdup(title);
40         d->displayname = strdup(displayname);
41
42         return d;
43 }
44
45 void distro_series_free(struct distro_series *d)
46 {
47         if (d) {
48                 free(d->name);
49                 free(d->version);
50                 free(d->title);
51                 free(d->displayname);
52
53                 free(d);
54         }
55 }
56
57 void bpph_free(struct bpph *b)
58 {
59         if (b) {
60                 free(b->binary_package_name);
61                 free(b->binary_package_version);
62                 free(b->distro_arch_series_link);
63                 free(b->self_link);
64                 free(b->status);
65                 free(b);
66         }
67 }
68
69 struct bpph *bpph_new(const char *binary_package_name,
70                       const char *binary_package_version,
71                       const char *distro_arch_series_link,
72                       const char *self_link,
73                       const char *status,
74                       int architecture_specific,
75                       time_t date_created)
76 {
77         struct bpph *h;
78
79         h = malloc(sizeof(struct bpph));
80
81         h->binary_package_name = strdup(binary_package_name);
82         h->binary_package_version = strdup(binary_package_version);
83         h->distro_arch_series_link = strdup(distro_arch_series_link);
84         h->self_link = strdup(self_link);
85         h->architecture_specific = architecture_specific;
86         h->status = strdup(status);
87         h->date_created = date_created;
88
89         return h;
90 }
91
92 void bpph_list_free(struct bpph **list)
93 {
94         struct bpph **l_cur = list;
95
96         while (*l_cur) {
97                 bpph_free(*l_cur);
98                 l_cur++;
99         }
100
101         free(list);
102 }
103
104 char *get_archive_url(const char *owner, const char *ppa)
105 {
106         char *url = malloc(strlen(URL_BASE_LP)
107                            +strlen("/~")
108                            +strlen(owner)
109                            +strlen("/+archive/")
110                            +strlen(ppa)
111                            +1);
112
113         strcpy(url, URL_BASE_LP);
114         strcat(url, "/~");
115         strcat(url, owner);
116         strcat(url, "/+archive/");
117         strcat(url, ppa);
118
119         return url;
120 }
121
122 struct distro_arch_series *distro_arch_series_new(const char *display_name,
123                                                   const char *title,
124                                                   const char *architecture_tag,
125                                                   int is_nominated_arch_indep,
126                                                   const char *distroseries_link)
127 {
128         struct distro_arch_series *d;
129
130         d = malloc(sizeof(struct distro_arch_series));
131
132         d->display_name = strdup(display_name);
133         d->title = strdup(title);
134         d->architecture_tag = strdup(architecture_tag);
135         d->is_nominated_arch_indep = is_nominated_arch_indep;
136         d->distroseries_link = strdup(distroseries_link);
137
138         return d;
139 }
140
141 void distro_arch_series_free(struct distro_arch_series *d)
142 {
143         free(d->display_name);
144         free(d->title);
145         free(d->architecture_tag);
146         free(d->distroseries_link);
147
148         free(d);
149 }
150
151 void distro_arch_series_list_free(struct distro_arch_series **list)
152 {
153         if (list) {
154                 while (*list) {
155                         distro_arch_series_free(*list);
156                         list++;
157                 }
158                 free(list);
159         }
160 }
161
162 void daily_download_total_list_free(struct daily_download_total **list)
163 {
164         if (list) {
165                 struct daily_download_total **cur = list;
166
167                 while (*cur) {
168                         free(*cur);
169                         cur++;
170                 }
171
172                 free(list);
173         }
174 }
175
176 struct bpph **bpph_list_add(struct bpph **list, struct bpph *new)
177 {
178         struct bpph **cur, *bpph, **result;
179
180         if (list)
181                 for (cur = list; *cur; cur++) {
182                         bpph = *cur;
183
184                         if (!strcmp(bpph->self_link, new->self_link))
185                                 return list;
186                 }
187
188         result = (struct bpph **)list_add((void **)list, new);
189
190         free(list);
191
192         return result;
193 }
194
195 struct bpph **bpph_list_append_list(struct bpph **list1, struct bpph **list2)
196 {
197         struct bpph **cur;
198
199         if (!list2)
200                 return list1;
201
202         for (cur = list2; *cur; cur++)
203                 list1 = bpph_list_add(list1, *cur);
204
205         return list1;
206 }
207
208 time_t ddts_get_last_date(struct daily_download_total **ddts)
209 {
210         struct daily_download_total **cur;
211         time_t t, last_t;
212
213         if (!ddts)
214                 return 0;
215
216         last_t = 0;
217         for (cur = ddts; *cur; cur++) {
218                 t = mktime(&(*cur)->date);
219                 if (t > last_t)
220                         last_t = t;
221         }
222
223         return last_t;
224 }
225
226 int ddts_length(struct daily_download_total **ddts)
227 {
228         int n;
229         struct daily_download_total **cur;
230
231         n = 0;
232
233         if (ddts)
234                 for (cur = ddts; *cur; cur++)
235                         n++;
236
237         return n;
238 }
239
240 struct daily_download_total *ddt_clone(struct daily_download_total *ddt)
241 {
242         struct daily_download_total *new;
243
244         new = malloc(sizeof(struct daily_download_total));
245
246         new->date = ddt->date;
247         new->count = ddt->count;
248
249         return new;
250 }
251
252 struct daily_download_total **
253 ddts_clone(struct daily_download_total **ddts)
254 {
255         int n, i;
256         struct daily_download_total **new;
257
258         n = ddts_length(ddts);
259
260         new = malloc((n + 1) * sizeof(struct daily_download_total *));
261
262         for (i = 0; i < n; i++)
263                 new[i] = ddt_clone(ddts[i]);
264
265         new[n] = NULL;
266
267         return new;
268 }
269
270 /*
271   Return a newly allocated list with an additional ddt.
272   All ddts are cloned.
273  */
274 static struct daily_download_total **add_ddt
275 (struct daily_download_total **totals, struct daily_download_total *total)
276 {
277         struct daily_download_total **cur, **ddts, **result;
278         struct daily_download_total *item;
279
280         if (totals) {
281                 cur = totals;
282                 while (*cur) {
283                         item = *cur;
284
285                         if (item->date.tm_year == total->date.tm_year &&
286                             item->date.tm_mon == total->date.tm_mon &&
287                             item->date.tm_mday == total->date.tm_mday) {
288                                 item->count = total->count;
289                                 return totals;
290                         }
291
292                         cur++;
293                 }
294         }
295
296         ddts = ddts_clone(totals);
297
298         result = (struct daily_download_total **)
299                 list_add((void **)ddts, ddt_clone((void *)total));
300
301         free(ddts);
302
303         return result;
304 }
305
306 struct daily_download_total **
307 ddts_merge(struct daily_download_total **ddts1,
308            struct daily_download_total **ddts2)
309 {
310         struct daily_download_total **ddts, **cur, **tmp;
311
312         if (ddts1) {
313                 ddts = ddts_clone(ddts1);
314         } else {
315                 ddts = malloc(sizeof(struct daily_download_total *));
316                 ddts[0] = NULL;
317         }
318
319         if (ddts2)
320                 for (cur = ddts2; *cur; cur++) {
321                         tmp = add_ddt(ddts, *cur);
322                         if (tmp != ddts) {
323                                 daily_download_total_list_free(ddts);
324                                 ddts = tmp;
325                         }
326                 }
327
328         return ddts;
329 }
330
331 int ddts_get_count(struct daily_download_total **ddts)
332 {
333         struct daily_download_total **cur;
334         int i;
335
336         i = 0;
337         for (cur = ddts; *cur; cur++)
338                 i += (*cur)->count;
339
340         return i;
341 }