summaryrefslogtreecommitdiff
path: root/cache.h
blob: 93aff9f18f9bce7523a654566a4866fe8114dad3 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * $Id: cache.h,v 1.1 2004/06/05 01:40:13 lordjaxom Exp $
 */

#ifndef VDR_TEXT2SKIN_CACHE_HPP
#define VDR_TEXT2SKIN_CACHE_HPP

#include "common.h"

// template class generic cache

template<class K,class D>
class cText2SkinCache {
private:
	struct Item {
		K      _key;
		D      _data;
		time_t _lastUsed;

		Item  *_next;
		Item  *_prev;

		Item() { _next = _prev = NULL; }
	};

	typedef map <K,Item*> DataMap;

	DataMap _items;
	int     _maxItems;
	Item   *_first;
	Item   *_last;
		
	void Unlink(Item *item);
	void Update(Item *item);
	void Delete(Item *item);
	void Delete(K &key, D &data);

public:
	cText2SkinCache(int maxItems);
	~cText2SkinCache();

	bool Contains(const K &key);
	D &operator[](const K &key);
};

template<class K,class D>
inline void cText2SkinCache<K,D>::Unlink(Item *item) {
	if (item == _first) {
		_first = item->_next;
		if (_first)
			_first->_prev = NULL;
		else
			_last = NULL;
	} else if (item == _last) {
		_last = item->_prev;
		_last->_next = NULL;
	} else {
		item->_prev->_next = item->_next;
		item->_next->_prev = item->_prev;
	}
}

template<class K,class D>
inline void cText2SkinCache<K,D>::Delete(Item *item) {
	Delete(item->_key, item->_data);
	delete item;
}

template<class K,class D>
inline void cText2SkinCache<K,D>::Delete(K &key, D &Data) {
}

template<class K,class D>
inline void cText2SkinCache<K,D>::Update(Item *item) {
	item->_lastUsed = time_ms();
	if (item->_next != NULL || item->_prev != NULL)
		Unlink(item);

	item->_next = NULL;
	item->_prev = _last;
	if (_last)
		_last->_next = item;
	_last = item;
	if (!_first)
		_first = item;

	while ((int)_items.size() > _maxItems) {
		Item *aged = _first;
		_items.erase(aged->_key);
		Unlink(aged);
		Delete(aged);
	}
}

template<class K,class D>
inline bool cText2SkinCache<K,D>::Contains(const K &key) {
	return (_items.find(key) != _items.end());
}

template<class K,class D>
cText2SkinCache<K,D>::cText2SkinCache(int maxItems) {
	_maxItems = maxItems;
	_first = _last = NULL;
}

template<class K,class D>
cText2SkinCache<K,D>::~cText2SkinCache() {
}

template<class K,class D>
D &cText2SkinCache<K,D>::operator[](const K &key) {
	Item *item;
	if (Contains(key)) {
		item = _items[key];
	} else {
		item = new Item;
		item->_key = key;
		_items[key] = item;
	}
	Update(item);
	return item->_data;
}

#endif // VDR_TEXT2SKIN_CACHE_HPP