chris-website/source/nl/netsoj/chris/blog/cache.d

92 lines
2.2 KiB
D

import std.experimental.logger;
import std.traits;
import article;
import page;
import project;
/**
* Default ordering and list with pointers to ordered articles.
* (Note: this is code which will actually be compiled and passed on!)
*/
GenericCache!(Article, "a.firstPublished > b.firstPublished") articles;
GenericCache!(Page, "a.title < b.title") pages;
GenericCache!(Project, "a.title < b.title") projects;
/**
* In memory cache of T (where T is like a page). Right now it simply holds everything in memory.
*
* At a later date, this cache might start unloading lesser-accessed items, and load them later
* again if needed.
*/
struct GenericCache(T, string sortOrder)
if (isImplicitlyConvertible!(T, Page)) {
public:
void addItem(T item) {
logf("Added %s '%s'", T.stringof, item.slug);
m_map[item.slug] = item;
sortItems();
}
void removeItem(T item) {
logf("Removed %s '%s'", T.stringof, item.slug);
m_map.remove(item.slug);
sortItems();
}
void removeItemByName(string name) {
foreach(item; m_map.byValue) {
if (item.name == name) removeItem(item);
}
}
void changeItem(T item) {
import std.algorithm;
import std.range;
auto r = m_map.byValue.find!((a,b) => a.name == b.name)(item);
if (r.empty()) {
warningf("Could not find old %s with name %s", T.stringof, item.name);
return;
}
T oldItem = r.front;
if (oldItem.slug != item.slug) {
logf("Slug of %s '%s' changed to '%s'", T.stringof, oldItem.slug, item.slug);
m_map.remove(oldItem.slug);
}
m_map[item.slug] = item;
sortItems();
}
/**
* Overload []-operator to redirect to our internal map.
*/
T opIndex(string key) {
return m_map[key];
}
T* opBinaryRight(string op)(const scope string key) {
static if (op == "in") {
return key in m_map;
} else static assert(false, "Operation " ~ op ~ "is not supported on this class");
}
T[] sortedList() {
return m_publicItems;
}
private:
T[string] m_map;
T[] m_publicItems;
void sortItems() {
import std.algorithm;
import std.array;
m_publicItems = sort!sortOrder(m_map.values)
.filter!(x => !x.isHidden)
.array;
}
}