add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / util / util_cache.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef __UTIL_CACHE_H__
20 #define __UTIL_CACHE_H__
21
22 /* Disk Cache based on Hashing
23  *
24  * To be used to cache expensive computations. The hash key is created from an
25  * arbitrary number of bytes, by hashing the bytes using MD5, which then gives
26  * the file name containing the data. This data then is read from the file
27  * again into the appropriate data structures.
28  *
29  * This way we do not need to accurately track changes, compare dates and
30  * invalidate cache entries, at the cost of exta computation. If everything
31  * is stored in a global cache, computations can perhaps even be shared between
32  * different scenes where it may be hard to detect duplicate work.
33  */
34
35 #include "util_set.h"
36 #include "util_string.h"
37 #include "util_vector.h"
38
39 CCL_NAMESPACE_BEGIN
40
41 class CacheBuffer {
42 public:
43         const void *data;
44         size_t size;
45
46         CacheBuffer(const void *data_, size_t size_)
47         { data = data_; size = size_; }
48 };
49
50 class CacheData {
51 public:
52         vector<CacheBuffer> buffers;
53         string name;
54         string filename;
55         bool have_filename;
56         FILE *f;
57
58         CacheData(const string& name = "");
59         ~CacheData();
60
61         const string& get_filename();
62
63         template<typename T> void add(const vector<T>& data)
64         {
65                 CacheBuffer buffer(data.size()? &data[0]: NULL, data.size()*sizeof(T));
66                 buffers.push_back(buffer);
67         }
68
69         template<typename T> void add(const array<T>& data)
70         {
71                 CacheBuffer buffer(data.size()? &data[0]: NULL, data.size()*sizeof(T));
72                 buffers.push_back(buffer);
73         }
74
75         void add(const void *data, size_t size)
76         {
77                 if(size) {
78                         CacheBuffer buffer(data, size);
79                         buffers.push_back(buffer);
80                 }
81         }
82
83         void add(const int& data)
84         {
85                 CacheBuffer buffer(&data, sizeof(int));
86                 buffers.push_back(buffer);
87         }
88
89         void add(const float& data)
90         {
91                 CacheBuffer buffer(&data, sizeof(float));
92                 buffers.push_back(buffer);
93         }
94
95         void add(const size_t& data)
96         {
97                 CacheBuffer buffer(&data, sizeof(size_t));
98                 buffers.push_back(buffer);
99         }
100
101         template<typename T> void read(array<T>& data)
102         {
103                 size_t size;
104
105                 if(!fread(&size, sizeof(size), 1, f)) {
106                         fprintf(stderr, "Failed to read vector size from cache.\n");
107                         return;
108                 }
109
110                 if(!size)
111                         return;
112
113                 data.resize(size/sizeof(T));
114
115                 if(!fread(&data[0], size, 1, f)) {
116                         fprintf(stderr, "Failed to read vector data from cache (%lu).\n", (unsigned long)size);
117                         return;
118                 }
119         }
120
121         void read(int& data)
122         {
123                 size_t size;
124
125                 if(!fread(&size, sizeof(size), 1, f))
126                         fprintf(stderr, "Failed to read int size from cache.\n");
127                 if(!fread(&data, sizeof(data), 1, f))
128                         fprintf(stderr, "Failed to read int from cache.\n");
129         }
130
131         void read(float& data)
132         {
133                 size_t size;
134
135                 if(!fread(&size, sizeof(size), 1, f))
136                         fprintf(stderr, "Failed to read float size from cache.\n");
137                 if(!fread(&data, sizeof(data), 1, f))
138                         fprintf(stderr, "Failed to read float from cache.\n");
139         }
140
141         void read(size_t& data)
142         {
143                 size_t size;
144
145                 if(!fread(&size, sizeof(size), 1, f))
146                         fprintf(stderr, "Failed to read size_t size from cache.\n");
147                 if(!fread(&data, sizeof(data), 1, f))
148                         fprintf(stderr, "Failed to read size_t from cache.\n");
149         }
150 };
151
152 class Cache {
153 public:
154         static Cache global;
155
156         void insert(CacheData& key, CacheData& value);
157         bool lookup(CacheData& key, CacheData& value);
158
159         void clear_except(const string& name, const set<string>& except);
160
161 protected:
162         string data_filename(CacheData& key);
163 };
164
165 CCL_NAMESPACE_END
166
167 #endif /* __UTIL_CACHE_H__ */
168