summary refs log tree commit diff stats
path: root/index_gmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'index_gmi.c')
-rw-r--r--index_gmi.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/index_gmi.c b/index_gmi.c
new file mode 100644
index 0000000..7f16a42
--- /dev/null
+++ b/index_gmi.c
@@ -0,0 +1,185 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <gemtext.h>
+
+#include "gemlog.h"
+
+static int
+find_latest_year(struct gemlog_entry **feed)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year > ret)
+			ret = feed[i]->date.tm_year;
+	}
+	return ret;
+}
+
+static int
+find_latest_month(struct gemlog_entry **feed, int year)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year) {
+			if (feed[i]->date.tm_mon > ret)
+				ret = feed[i]->date.tm_mon;
+		}
+	}
+	return ret;
+}
+
+static int
+find_latest_day(struct gemlog_entry **feed, int year, int month)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month) {
+			if (feed[i]->date.tm_mday > ret)
+				ret = feed[i]->date.tm_mday;
+		}
+	}
+	return ret;
+}
+
+static int
+find_latest_hour(struct gemlog_entry **feed, int year, int month, int day)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month && feed[i]->date.tm_mday == day) {
+			if (feed[i]->date.tm_hour > ret)
+				ret = feed[i]->date.tm_hour;
+		}
+	}
+	return ret;
+}
+
+static int
+gemlog_write_index_hour(struct gemlog_entry **feed, int fd, int year, int month, int day, int hour)
+{
+	int i;
+	int labellen;
+	char *labelbuf;
+	char timestamp[11]; /* 1990-01-01\0 */
+	char pathbuf[PATH_MAX+1];
+	struct gemtext *out;
+
+	labellen = 0;
+
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year
+		 && feed[i]->date.tm_mon  == month
+		 && feed[i]->date.tm_mday == day
+		 && feed[i]->date.tm_hour == hour) {
+			strftime(timestamp, sizeof(timestamp), "%F", &(feed[i]->date));
+			labellen += strlen(timestamp);
+			labellen += 2; /* ": " */
+			labellen += strlen(feed[i]->title);
+			labelbuf = malloc(labellen+1);
+			if (labelbuf == NULL)
+				return -1;
+			strlcpy(labelbuf, timestamp, labellen+1);
+			strlcat(labelbuf, ": ", labellen+1);
+			strlcat(labelbuf, feed[i]->title, labellen+1);
+			snprintf(pathbuf, sizeof(pathbuf), "%d/%d/%d/%d/%s", year+1900, month+1, day, hour, GEMLOG_CONTENT_FILENAME);
+			out = gemtext_link_new(pathbuf, labelbuf);
+			free(labelbuf);
+			if (out == NULL)
+				return -1;
+			if (gemtext_encode_fd(out, fd) == -1) {
+				gemtext_free(out);
+				return -1;
+			}
+			gemtext_free(out);
+			if (write(fd, "\n", strlen("\n")) == -1)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_day(struct gemlog_entry **feed, int fd, int year, int month, int day)
+{
+	int hour;
+
+	for (hour = find_latest_hour(feed, year, month, day); hour != 0; hour--) {
+		if (gemlog_write_index_hour(feed, fd, year, month, day, hour) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_month(struct gemlog_entry **feed, int fd, int year, int month)
+{
+	int day;
+
+	for (day = find_latest_day(feed, year, month); day != 0; day--) {
+		if (gemlog_write_index_day(feed, fd, year, month, day) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_year(struct gemlog_entry **feed, int fd, int year)
+{
+	int month;
+
+	for (month = find_latest_month(feed, year); month != 0; month--) {
+		if (gemlog_write_index_month(feed, fd, year, month) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+int
+gemlog_write_index(struct gemlog_entry **feed, const char *path)
+{
+	int year;
+	int fd;
+
+	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC);
+	if (fd == -1)
+		return -1;
+	if (chmod(path, 0644) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	for (year = find_latest_year(feed); year != 0; year--) {
+		if (gemlog_write_index_year(feed, fd, year) == -1) {
+			close(fd);
+			return -1;
+		}
+	}
+
+	close(fd);
+	return 0;
+}