aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bstree.c183
-rw-r--r--src/components.c29
-rw-r--r--src/render.c52
-rw-r--r--src/site.c262
4 files changed, 180 insertions, 346 deletions
diff --git a/src/bstree.c b/src/bstree.c
deleted file mode 100644
index 7d4f14f..0000000
--- a/src/bstree.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2021 Yaroslav de la Peña Smirnov
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#include "bstree.h"
-
-#include <stdlib.h>
-
-struct bstree *
-bstree_new(bst_cmp_fn bstcmp, bst_free_fn bstfree)
-{
- struct bstree *tree = malloc(sizeof *tree);
- tree->root = NULL;
- tree->cmp = bstcmp;
- tree->free = bstfree;
-
- return tree;
-}
-
-struct bstnode *
-bstree_add(struct bstree *tree, void *val)
-{
- struct bstnode **cur;
- struct bstnode *prev = NULL;
- cur = &tree->root;
- while (*cur != NULL) {
- prev = *cur;
- if (tree->cmp(val, prev->value) < 0) {
- cur = &prev->left;
- } else {
- cur = &prev->right;
- }
- }
- *cur = calloc(1, sizeof **cur);
- (*cur)->value = val;
- (*cur)->parent = prev;
-
- return *cur;
-}
-
-struct bstnode *
-bstree_search(struct bstree *tree, void *val)
-{
- struct bstnode *node = tree->root;
- while (node != NULL) {
- int res;
- if ((res = tree->cmp(val, node->value)) == 0) {
- break;
- }
- if (res < 0) {
- node = node->left;
- } else {
- node = node->right;
- }
- }
-
- return node;
-}
-
-#define bstree_extreme(node, d) \
- while (node != NULL && node->d != NULL) { \
- node = node->d; \
- }
-
-struct bstnode *
-bstree_max(struct bstnode *node)
-{
- bstree_extreme(node, right)
- return node;
-}
-
-struct bstnode *
-bstree_min(struct bstnode *node)
-{
- bstree_extreme(node, left)
- return node;
-}
-
-#define bstree_xcessor(na, d, m) \
- if (na->d != NULL) { \
- return bstree_##m(na->d); \
- } \
- struct bstnode *nb = na->parent; \
- while (nb != NULL && nb->d == na) { \
- na = nb; \
- nb = nb->parent; \
- } \
- return nb
-
-struct bstnode *
-bstree_successor(struct bstnode *na)
-{
- bstree_xcessor(na, right, min);
-}
-
-struct bstnode *
-bstree_predecessor(struct bstnode *na)
-{
- bstree_xcessor(na, left, max);
-}
-
-bool
-bstree_inorder_walk(struct bstnode *node, bst_walk_cb cb, void *data)
-{
- if (node->left != NULL) {
- if (!bstree_inorder_walk(node->left, cb, data)) return false;
- }
- if (!cb(node, data)) return false;
- if (node->right != NULL) {
- return bstree_inorder_walk(node->right, cb, data);
- }
- return true;
-}
-
-static void
-bstree_transplant(struct bstree *tree, struct bstnode *a, struct bstnode *b)
-{
- if (a->parent == NULL) {
- tree->root = b;
- } else if (a == a->parent->left) {
- a->parent->left = b;
- } else {
- a->parent->right = b;
- }
- if (b != NULL) {
- b->parent = a->parent;
- }
-}
-
-void
-bstree_remove(struct bstree *tree, struct bstnode *na)
-{
- if (na->left == NULL) {
- bstree_transplant(tree, na, na->right);
- } else if (na->right == NULL) {
- bstree_transplant(tree, na, na->left);
- } else {
- struct bstnode *nb = bstree_min(na->right);
- if (nb->parent != na) {
- bstree_transplant(tree, nb, nb->right);
- nb->right = na->right;
- nb->right->parent = nb;
- }
- bstree_transplant(tree, na, nb);
- nb->left = na->left;
- nb->left->parent = nb;
- }
- tree->free(na->value);
- free(na);
-}
-
-static void
-bstree_subdestroy(struct bstree *tree, struct bstnode *node)
-{
- if (node->right) bstree_subdestroy(tree, node->right);
- if (node->left) bstree_subdestroy(tree, node->left);
- tree->free(node->value);
- free(node);
-}
-
-void
-bstree_destroy(struct bstree *tree)
-{
- if (tree->root) bstree_subdestroy(tree, tree->root);
- free(tree);
-}
diff --git a/src/components.c b/src/components.c
index aeb14b1..f3d79d1 100644
--- a/src/components.c
+++ b/src/components.c
@@ -175,17 +175,16 @@ image_new(char *src, const struct stat *pstat, struct album *album)
}
int
-image_cmp(const void *a, const void *b)
+image_cmp(const void *va, const void *vb)
{
+ struct image *a = *(struct image **)va, *b = *(struct image **)vb;
/* Compare in ascending order */
- return (((struct image *)a)->tstamp > ((struct image *)b)->tstamp)
- - (((struct image *)a)->tstamp < ((struct image *)b)->tstamp);
+ return (a->tstamp > b->tstamp) - (a->tstamp < b->tstamp);
}
void
-image_destroy(void *data)
+image_destroy(struct image *image)
{
- struct image *image = data;
free(image->source);
free(image->url);
free(image->url_image);
@@ -213,7 +212,7 @@ album_new(struct album_config *conf, struct site *site, const char *src,
album->config = conf;
album->source = strdup(src);
album->slug = slugify(rsrc, site->config->base_url, &album->url);
- album->images = bstree_new(image_cmp, image_destroy);
+ album->images = vector_new_with_cap(64);
album->tstamp = MAXTIME;
album->preserved = hmap_new();
album->map = roscha_object_new(hmap_new());
@@ -223,11 +222,11 @@ album_new(struct album_config *conf, struct site *site, const char *src,
}
int
-album_cmp(const void *a, const void *b)
+album_cmp(const void *va, const void *vb)
{
+ struct album *a = *(struct album **)va, *b = *(struct album **)vb;
/* Compare in descending order */
- return (((struct album *)a)->tstamp < ((struct album *)b)->tstamp)
- - (((struct album *)a)->tstamp > ((struct album *)b)->tstamp);
+ return (a->tstamp < b->tstamp) - (a->tstamp > b->tstamp);
}
@@ -238,7 +237,7 @@ album_add_image(struct album *album, struct image *image)
album->tstamp = image->tstamp;
album->datestr = image->datestr;
}
- bstree_add(album->images, image);
+ vector_push(album->images, image);
}
void
@@ -251,15 +250,19 @@ album_set_year(struct album *album)
}
void
-album_destroy(void *data)
+album_destroy(struct album *album)
{
- struct album *album = data;
if (album->config != NULL) {
album_config_destroy(album->config);
}
+ size_t i;
+ struct image *img;
+ vector_foreach(album->images, i, img) {
+ image_destroy(img);
+ }
+ vector_free(album->images);
free(album->source);
free(album->url);
- bstree_destroy(album->images);
hmap_free(album->preserved);
roscha_object_unref(album->map);
roscha_object_unref(album->thumbs);
diff --git a/src/render.c b/src/render.c
index bc9b8df..9dbbe2a 100644
--- a/src/render.c
+++ b/src/render.c
@@ -7,33 +7,33 @@
#include "log.h"
#include "site.h"
-/* TODO: refactor to use roscha instead of unja */
-
-static bool
-images_walk(struct bstnode *node, void *data)
+static void
+images_walk(struct vector *images)
{
- struct image *image = node->value;
-
- roscha_hmap_set_new(image->map, "source", (slice_whole(image->url_image)));
- roscha_hmap_set_new(image->map, "date", (slice_whole(image->datestr)));
- struct bstnode *prev = bstree_predecessor(node),
- *next = bstree_successor(node);
- char *url;
- if (prev) {
- url = ((struct image *)prev->value)->url;
- roscha_hmap_set_new(image->map, "prev", (slice_whole(url)));
- }
- if (next) {
- url = ((struct image *)next->value)->url;
- roscha_hmap_set_new(image->map, "next", (slice_whole(url)));
- }
-
- roscha_hmap_set_new(image->thumb, "link", (slice_whole(image->url)));
- roscha_hmap_set_new(image->thumb, "source", (slice_whole(image->url_thumb)));
+ size_t i;
+ struct image *image;
+ size_t last = images->len - 1;
+
+ vector_foreach(images, i, image) {
+ roscha_hmap_set_new(image->map, "source", (slice_whole(image->url_image)));
+ roscha_hmap_set_new(image->map, "date", (slice_whole(image->datestr)));
+ char *url;
+ if (i > 0) {
+ struct image *prev = images->values[i - 1];
+ url = prev->url;
+ roscha_hmap_set_new(image->map, "prev", (slice_whole(url)));
+ }
+ if (i < last) {
+ struct image *next = images->values[i + 1];
+ url = next->url;
+ roscha_hmap_set_new(image->map, "next", (slice_whole(url)));
+ }
- roscha_vector_push(image->album->thumbs, image->thumb);
+ roscha_hmap_set_new(image->thumb, "link", (slice_whole(image->url)));
+ roscha_hmap_set_new(image->thumb, "source", (slice_whole(image->url_thumb)));
- return true;
+ roscha_vector_push(image->album->thumbs, image->thumb);
+ }
}
static inline void
@@ -84,7 +84,7 @@ render_set_album_vars(struct render *r, struct album *album)
roscha_hmap_set_new(album->map, "date", (slice_whole(album->datestr)));
roscha_hmap_set_new(album->map, "year", (slice_whole(album->year)));
- bstree_inorder_walk(album->images->root, images_walk, NULL);
+ images_walk(album->images);
roscha_hmap_set(album->map, "thumbs", album->thumbs);
@@ -182,7 +182,7 @@ done:
bool
render_init(struct render *r, const char *root, struct site_config *conf,
- struct bstree *albums)
+ struct vector *albums)
{
char *tmplpath = joinpath(root, TEMPLATESDIR);
struct stat tstat;
diff --git a/src/site.c b/src/site.c
index eedd30b..3937376 100644
--- a/src/site.c
+++ b/src/site.c
@@ -33,32 +33,33 @@ prerm_imagedir(const char *path, void *data)
return false;
}
if (S_ISDIR(st.st_mode)) {
- struct image *old = image_old(&st);
- struct bstnode *imnode = bstree_add(album->images, old),
- *prev = bstree_predecessor(imnode),
- *next = bstree_successor(imnode);
+ struct image *prev, *next = NULL;
+ size_t i;
+ vector_foreach(album->images, i, prev) {
+ if (prev->tstamp > st.st_mtim.tv_sec) {
+ prev = next;
+ break;
+ }
+ next = prev;
+ }
if (prev) {
- struct image *imprev = (struct image *)prev->value;
- if (!imprev->modified) {
- joinpathb(htmlpath, imprev->dst, index_html);
- if (!render_make_image(&album->site->render, htmlpath, imprev)) {
+ if (!prev->modified) {
+ joinpathb(htmlpath, prev->dst, index_html);
+ if (!render_make_image(&album->site->render, htmlpath, prev)) {
goto fail;
}
}
}
- if (next) {
- struct image *imnext = (struct image *)next->value;
- if (!imnext->modified) {
- joinpathb(htmlpath, imnext->dst, index_html);
- if (!render_make_image(&album->site->render, htmlpath, imnext)) {
+ if (next != prev) {
+ if (!next->modified) {
+ joinpathb(htmlpath, next->dst, index_html);
+ if (!render_make_image(&album->site->render, htmlpath, next)) {
goto fail;
}
}
}
- bstree_remove(album->images, imnode);
return true;
fail:
- bstree_remove(album->images, imnode);
return false;
}
return true;
@@ -120,131 +121,134 @@ magick_fail:
}
static bool
-images_walk(struct bstnode *node, void *data)
+images_walk(struct site *site, struct vector *images)
{
- struct site *site = data;
- struct image *image = node->value;
- struct stat dstat;
- struct timespec ddate = { .tv_sec = image->tstamp, .tv_nsec = 0 };
- int imgupdate, thumbupdate;
- char htmlpath[PATH_MAX];
- const char *base = rbasename(image->dst);
-
- log_printl(LOG_DEBUG, "Image: %s, datetime %s", image->basename,
- image->datestr);
-
- if (!nmkdir(image->dst, &dstat, site->dry_run)) return false;
-
- imgupdate = file_is_uptodate(image->dst_image, &image->modtime);
- if (imgupdate == -1) goto magick_fail;
- thumbupdate = file_is_uptodate(image->dst_image, &image->modtime);
- if (thumbupdate == -1) goto magick_fail;
- if (!site->dry_run && (!imgupdate || !thumbupdate)) {
- TRYWAND(site->wand, MagickReadImage(site->wand, image->source));
- }
- if (!imgupdate && !optimize_image(site->wand, image->dst_image,
- &site->config->images, &image->modtime, site->dry_run)) {
- goto magick_fail;
- }
- if (!thumbupdate && !optimize_image(site->wand, image->dst_thumb,
- &site->config->thumbnails, &image->modtime, site->dry_run)) {
- goto magick_fail;
- }
- if (!site->dry_run && (!imgupdate || !thumbupdate)) {
- MagickRemoveImage(site->wand);
- }
+ size_t i;
+ struct image *image;
+
+ vector_foreach(images, i, image) {
+ struct stat dstat;
+ struct timespec ddate = { .tv_sec = image->tstamp, .tv_nsec = 0 };
+ int imgupdate, thumbupdate;
+ char htmlpath[PATH_MAX];
+ const char *base = rbasename(image->dst);
+
+ log_printl(LOG_DEBUG, "Image: %s, datetime %s", image->basename,
+ image->datestr);
+
+ if (!nmkdir(image->dst, &dstat, site->dry_run)) return false;
+
+ imgupdate = file_is_uptodate(image->dst_image, &image->modtime);
+ if (imgupdate == -1) goto magick_fail;
+ thumbupdate = file_is_uptodate(image->dst_image, &image->modtime);
+ if (thumbupdate == -1) goto magick_fail;
+ if (!site->dry_run && (!imgupdate || !thumbupdate)) {
+ TRYWAND(site->wand, MagickReadImage(site->wand, image->source));
+ }
+ if (!imgupdate && !optimize_image(site->wand, image->dst_image,
+ &site->config->images, &image->modtime, site->dry_run)) {
+ goto magick_fail;
+ }
+ if (!thumbupdate && !optimize_image(site->wand, image->dst_thumb,
+ &site->config->thumbnails, &image->modtime, site->dry_run)) {
+ goto magick_fail;
+ }
+ if (!site->dry_run && (!imgupdate || !thumbupdate)) {
+ MagickRemoveImage(site->wand);
+ }
- joinpathb(htmlpath, image->dst, index_html);
- hmap_set(image->album->preserved, base, (char *)base);
+ joinpathb(htmlpath, image->dst, index_html);
+ hmap_set(image->album->preserved, base, (char *)base);
- int isupdate = file_is_uptodate(htmlpath, &site->render.modtime);
- if (isupdate == -1) return false;
- if (isupdate == 0) {
- if (!render_make_image(&site->render, htmlpath, image)) {
- return false;
- }
- image->modified = true;
- image->album->images_updated++;
- /* Check if previous image wasn't updated, if so, render it */
- struct bstnode *prev = bstree_predecessor(node);
- if (prev) {
- struct image *iprev = prev->value;
- if (!iprev->modified) {
- joinpathb(htmlpath, iprev->dst, index_html);
- if (!render_make_image(&site->render, htmlpath, iprev)) {
- return false;
+ int isupdate = file_is_uptodate(htmlpath, &site->render.modtime);
+ if (isupdate == -1) return false;
+ if (isupdate == 0) {
+ if (!render_make_image(&site->render, htmlpath, image)) {
+ return false;
+ }
+ image->modified = true;
+ image->album->images_updated++;
+ /* Check if previous image wasn't updated, if so, render it */
+ if (i > 0) {
+ struct image *prev = images->values[i - 1];
+ if (!prev->modified) {
+ joinpathb(htmlpath, prev->dst, index_html);
+ if (!render_make_image(&site->render, htmlpath, prev)) {
+ return false;
+ }
+ goto success;
}
- goto success;
}
- }
- goto success;
- }
+ goto success;
+ }
- /*
- * Render anyway if next image doesn't exist yet in directory or if previous
- * image was updated.
- */
- struct bstnode *next = bstree_successor(node), *prev = NULL;
- if (next) {
- struct image *inext = next->value;
- if (access(inext->dst, F_OK) != 0) {
- image->album->images_updated++;
- return render_make_image(&site->render, htmlpath, image);
+ /*
+ * Render anyway if next image doesn't exist yet in directory or if
+ * previous image was updated.
+ */
+ if (i < images->len - 1) {
+ struct image *next = images->values[i + 1];
+ if (access(next->dst, F_OK) != 0) {
+ image->album->images_updated++;
+ return render_make_image(&site->render, htmlpath, image);
+ }
}
- }
- if ((prev = bstree_predecessor(node)) != NULL) {
- struct image *iprev = prev->value;
- if (iprev->modified) {
- image->album->images_updated++;
- return render_make_image(&site->render, htmlpath, image);
+ if (i > 0) {
+ struct image *prev = images->values[i - 1];
+ if (prev->modified) {
+ image->album->images_updated++;
+ return render_make_image(&site->render, htmlpath, image);
+ }
}
- }
-success:
- if (!site->dry_run) setdatetime(image->dst, &ddate);
+ success:
+ if (!site->dry_run) setdatetime(image->dst, &ddate);
+ continue;
+ magick_fail:
+ return false;
+ }
return true;
-magick_fail:
- return false;
}
static bool
-albums_walk(struct bstnode *node, void *data)
+albums_walk(struct site *site)
{
- struct site *site = data;
- struct album *album = node->value;
- struct stat dstat;
- if (!nmkdir(album->slug, &dstat, site->dry_run)) return false;
-
- hmap_set(site->album_dirs, album->slug, (char *)album->slug);
- if (!site->dry_run) {
- if (!render_set_album_vars(&site->render, album)) return false;
+ size_t i;
+ struct album *album;
- }
+ vector_foreach(site->albums, i, album) {
+ struct stat dstat;
+ if (!nmkdir(album->slug, &dstat, site->dry_run)) return false;
- log_printl(LOG_DEBUG, "Album: %s, datetime %s", album->slug, album->datestr);
- if (!bstree_inorder_walk(album->images->root, images_walk, site)) {
- return false;
- }
+ hmap_set(site->album_dirs, album->slug, (char *)album->slug);
+ if (!site->dry_run) {
+ if (!render_set_album_vars(&site->render, album)) return false;
- hmap_set(album->preserved, index_html, (char *)index_html);
- ssize_t deleted = rmextra(album->slug, album->preserved, prerm_imagedir,
- album, site->dry_run);
- if (deleted < 0) {
- log_printl_errno(LOG_ERROR,
- "Something happened while deleting extraneous files");
- } else {
- album->images_updated += deleted;
- }
- if (album->images_updated > 0) {
- site->render.albums_updated++;
- }
+ }
- char htmlpath[PATH_MAX];
- joinpathb(htmlpath, album->slug, index_html);
- if (!render_make_album(&site->render, htmlpath, album)) return false;
+ log_printl(LOG_DEBUG, "Album: %s, datetime %s", album->slug, album->datestr);
+ if (!images_walk(site, album->images)) {
+ return false;
+ }
+ hmap_set(album->preserved, index_html, (char *)index_html);
+ ssize_t deleted = rmextra(album->slug, album->preserved, prerm_imagedir,
+ album, site->dry_run);
+ if (deleted < 0) {
+ log_printl_errno(LOG_ERROR,
+ "Something happened while deleting extraneous files");
+ } else {
+ album->images_updated += deleted;
+ }
+ if (album->images_updated > 0) {
+ site->render.albums_updated++;
+ }
+ char htmlpath[PATH_MAX];
+ joinpathb(htmlpath, album->slug, index_html);
+ if (!render_make_album(&site->render, htmlpath, album)) return false;
+ }
return true;
}
@@ -304,9 +308,11 @@ traverse(struct site *site, const char *path, struct stat *dstat)
free(subpath);
}
- if (album->images->root != NULL) {
+ if (album->images->len != 0) {
album_set_year(album);
- bstree_add(site->albums, album);
+ qsort(album->images->values,
+ album->images->len, sizeof(void *), image_cmp);
+ vector_push(site->albums, album);
closedir(dir);
return true;
}
@@ -333,7 +339,7 @@ site_build(struct site *site)
return false;
}
- if (!bstree_inorder_walk(site->albums->root, albums_walk, (void *)site)) {
+ if (!albums_walk(site)) {
return false;
}
@@ -371,6 +377,7 @@ site_load(struct site *site)
}
if (!traverse(site, site->content_dir, &cstat)) return false;
+ qsort(site->albums->values, site->albums->len, sizeof(void *), album_cmp);
return render_init(&site->render, site->root_dir, site->config, site->albums);
}
@@ -380,7 +387,7 @@ site_init(struct site *site)
{
site->config = site_config_init();
if (!site_config_read_ini(site->root_dir, site->config)) return false;
- site->albums = bstree_new(album_cmp, album_destroy);
+ site->albums = vector_new();
if (site->root_dir == NULL) {
site->root_dir = malloc(PATH_MAX);
@@ -405,7 +412,14 @@ site_init(struct site *site)
void
site_deinit(struct site *site)
{
- if (site->albums) bstree_destroy(site->albums);
+ if (site->albums) {
+ size_t i;
+ struct album *a;
+ vector_foreach(site->albums, i, a) {
+ album_destroy(a);
+ }
+ vector_free(site->albums);
+ }
site_config_destroy(site->config);
free(site->content_dir);
free(site->root_dir);