summaryrefslogtreecommitdiff
path: root/src/bookmarks.c
blob: babfc32382593d61143c175304eae763cce69f11 (plain)
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
#include "bookmarks.h"

#include <the_Foundation/file.h>
#include <the_Foundation/path.h>

void init_Bookmark(iBookmark *d) {
    init_String(&d->url);
    init_String(&d->title);
    init_String(&d->tags);
    iZap(d->when);
}

void deinit_Bookmark(iBookmark *d) {
    deinit_String(&d->tags);
    deinit_String(&d->title);
    deinit_String(&d->url);
}

iDefineTypeConstruction(Bookmark)

static int cmpTimeDescending_Bookmark_(const iBookmark **a, const iBookmark **b) {
    return iCmp(seconds_Time(&(*b)->when), seconds_Time(&(*a)->when));
}

/*----------------------------------------------------------------------------------------------*/

static const char *fileName_Bookmarks_ = "bookmarks.txt";

struct Impl_Bookmarks {
    iArray bookmarks;
};

iDefineTypeConstruction(Bookmarks)

void init_Bookmarks(iBookmarks *d) {
    init_Array(&d->bookmarks, sizeof(iBookmark));
}

void deinit_Bookmarks(iBookmarks *d) {
    clear_Bookmarks(d);
    deinit_Array(&d->bookmarks);
}

void clear_Bookmarks(iBookmarks *d) {
    iForEach(Array, i, &d->bookmarks) {
        deinit_Bookmark(i.value);
    }
    clear_Array(&d->bookmarks);
}

void load_Bookmarks(iBookmarks *d, const char *dirPath) {
    clear_Bookmarks(d);
    iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_));
    if (open_File(f, readOnly_FileMode | text_FileMode)) {
        const iRangecc src = range_Block(collect_Block(readAll_File(f)));
        iRangecc line = iNullRange;
        while (nextSplit_Rangecc(&src, "\n", &line)) {
            iBookmark bm;
            init_Bookmark(&bm);
            char *endPos;
            initSeconds_Time(&bm.when, strtod(line.start, &endPos));
            line.start = skipSpace_CStr(endPos);
            setRange_String(&bm.url, line);
            nextSplit_Rangecc(&src, "\n", &line);
            setRange_String(&bm.title, line);
            nextSplit_Rangecc(&src, "\n", &line);
            setRange_String(&bm.tags, line);
            pushBack_Array(&d->bookmarks, &bm);
        }
    }
    iRelease(f);
}

void save_Bookmarks(const iBookmarks *d, const char *dirPath) {
    iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_));
    if (open_File(f, writeOnly_FileMode | text_FileMode)) {
        iString *str = collectNew_String();
        iConstForEach(Array, i, &d->bookmarks) {
            const iBookmark *bm = i.value;
            format_String(str, "%lf %s\%s\n%s\n", seconds_Time(&bm->when), cstr_String(&bm->url),
                          cstr_String(&bm->title), cstr_String(&bm->tags));
            writeData_File(f, cstr_String(str), size_String(str));
        }
    }
    iRelease(f);
}

void add_Bookmarks(iBookmarks *d, const iString *url, const iString *title, const iString *tags) {
    iBookmark bm;
    init_Bookmark(&bm);
    set_String(&bm.url, url);
    set_String(&bm.title, title);
    set_String(&bm.tags, tags);
    initCurrent_Time(&bm.when);
    pushBack_Array(&d->bookmarks, &bm);
}

const iPtrArray *list_Bookmarks(const iBookmarks *d, iBookmarksFilterFunc filter,
                                iBookmarksCompareFunc cmp) {
    iPtrArray *list = collectNew_PtrArray();
    iConstForEach(Array, i, &d->bookmarks) {
        if (!filter || filter(i.value)) {
            pushBack_PtrArray(list, i.value);
        }
    }
    if (!cmp) cmp = cmpTimeDescending_Bookmark_;
    sort_Array(list, (int (*)(const void *, const void *)) cmp);
    return list;
}