+struct bpph **bpph_list_add(struct bpph **list, struct bpph *new)
+{
+ struct bpph **cur, *bpph, **result;
+
+ if (list)
+ for (cur = list; *cur; cur++) {
+ bpph = *cur;
+
+ if (!strcmp(bpph->self_link, new->self_link))
+ return list;
+ }
+
+ result = (struct bpph **)list_add((void **)list, new);
+
+ free(list);
+
+ return result;
+}
+
+struct bpph **bpph_list_append_list(struct bpph **list1, struct bpph **list2)
+{
+ struct bpph **cur;
+
+ if (!list2)
+ return list1;
+
+ for (cur = list2; *cur; cur++)
+ list1 = bpph_list_add(list1, *cur);
+
+ return list1;
+}
+
+time_t ddts_get_last_date(struct daily_download_total **ddts)
+{
+ struct daily_download_total **cur;
+ time_t t, last_t;
+
+ if (!ddts)
+ return 0;
+
+ last_t = 0;
+ for (cur = ddts; *cur; cur++) {
+ t = mktime(&(*cur)->date);
+ if (t > last_t)
+ last_t = t;
+ }
+
+ return last_t;
+}
+
+int ddts_length(struct daily_download_total **ddts)
+{
+ int n;
+ struct daily_download_total **cur;
+
+ n = 0;
+
+ if (ddts)
+ for (cur = ddts; *cur; cur++)
+ n++;
+
+ return n;
+}
+
+struct daily_download_total *ddt_clone(struct daily_download_total *ddt)
+{
+ struct daily_download_total *new;
+
+ new = malloc(sizeof(struct daily_download_total));
+
+ new->date = ddt->date;
+ new->count = ddt->count;
+
+ return new;
+}
+
+struct daily_download_total **
+ddts_clone(struct daily_download_total **ddts)
+{
+ int n, i;
+ struct daily_download_total **new;
+
+ n = ddts_length(ddts);
+
+ new = malloc((n + 1) * sizeof(struct daily_download_total *));
+
+ for (i = 0; i < n; i++)
+ new[i] = ddt_clone(ddts[i]);
+
+ new[n] = NULL;
+
+ return new;
+}
+
+/*
+ Return a newly allocated list with an additional ddt.
+ All ddts are cloned.
+ */
+static struct daily_download_total **add_ddt
+(struct daily_download_total **totals, struct daily_download_total *total)
+{
+ struct daily_download_total **cur, **ddts, **result;
+ struct daily_download_total *item;
+
+ if (totals) {
+ cur = totals;
+ while (*cur) {
+ item = *cur;
+
+ if (item->date.tm_year == total->date.tm_year &&
+ item->date.tm_mon == total->date.tm_mon &&
+ item->date.tm_mday == total->date.tm_mday) {
+ item->count = total->count;
+ return totals;
+ }
+
+ cur++;
+ }
+ }
+
+ ddts = ddts_clone(totals);
+
+ result = (struct daily_download_total **)
+ list_add((void **)ddts, ddt_clone((void *)total));
+
+ free(ddts);
+
+ return result;
+}
+
+struct daily_download_total **
+ddts_merge(struct daily_download_total **ddts1,
+ struct daily_download_total **ddts2)
+{
+ struct daily_download_total **ddts, **cur, **tmp;
+
+ if (ddts1) {
+ ddts = ddts_clone(ddts1);
+ } else {
+ ddts = malloc(sizeof(struct daily_download_total *));
+ ddts[0] = NULL;
+ }
+
+ if (ddts2)
+ for (cur = ddts2; *cur; cur++) {
+ tmp = add_ddt(ddts, *cur);
+ if (tmp != ddts) {
+ daily_download_total_list_free(ddts);
+ ddts = tmp;
+ }
+ }
+
+ return ddts;
+}
+
+int ddts_get_count(struct daily_download_total **ddts)
+{
+ struct daily_download_total **cur;
+ int i;
+
+ i = 0;
+ for (cur = ddts; *cur; cur++)
+ i += (*cur)->count;
+
+ return i;
+}