zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Database.hxx
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib 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 Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef ZENI_DATABASE_HXX
19 #define ZENI_DATABASE_HXX
20 
21 // HXXed below
22 #include <Zeni/Resource.h>
23 
24 #include <Zeni/Database.h>
25 
26 #include <Zeni/XML.h>
27 
28 #include <algorithm>
29 #include <iostream>
30 
31 namespace Zeni {
32  template <class TYPE>
34  : ptr(0),
35  lent(false)
36  {
37  }
38 
39  template <class TYPE>
41  : ptr(0),
42  filename(filename_),
43  lent(false)
44  {
45  }
46 
47  template <class TYPE>
49  const String &filename_,
50  const bool &lent_,
51  const bool &keep_)
52  : ptr(ptr_),
53  filename(filename_),
54  lent(lent_),
55  keep(keep_)
56  {
57  }
58 
59  template <class TYPE>
61  return filename == rhs.filename;
62  }
63 
64  template <class TYPE>
66  : id(0)
67  {
68  }
69 
70  template <class TYPE>
71  Database<TYPE>::Lookup::Lookup(const unsigned long &id_, const Handle &handle_)
72  : id(id_)
73  {
74  handles.push_front(handle_);
75  }
76 
77  template <class TYPE>
78  Database<TYPE>::Database(const String &filename, const String &xml_identifier)
79  : m_xml_identifier(xml_identifier),
80  m_lost(true)
81  {
82  m_filenames.push_front(filename);
83  }
84 
85  template <class TYPE>
87  uninit();
88  }
89 
90  template <class TYPE>
91  unsigned long Database<TYPE>::give(const String &name, TYPE * const &type, const bool &keep, const String &filename) {
92  if(!type)
94 
95  Lookup *&lr = m_lookups[name];
96  if(!lr)
97  lr = new Lookup();
98 
99  if(!lr->id)
100  lr->id = get_Resource().assign();
101 
102  typename Lookup::Handles::iterator it = std::find(lr->handles.begin(), lr->handles.end(), typename Lookup::Handle(filename));
103 
104  if(it != lr->handles.end()) {
105  if(!it->lent)
106  delete it->ptr;
107  lr->handles.erase(it);
108  }
109 
110  lr->handles.push_front(typename Lookup::Handle(type, filename, false, keep));
111 
112  m_entries[lr->id] = type;
113 
114  return lr->id;
115  }
116 
117  template <class TYPE>
118  unsigned long Database<TYPE>::lend(const String &name, TYPE * const &type, const bool &keep) {
119  if(!type)
120  throw Null_Database_Entry_Set();
121 
122  Lookup *&lr = m_lookups[name];
123  if(!lr)
124  lr = new Lookup();
125 
126  if(!lr->id)
127  lr->id = get_Resource().assign();
128 
129  typename Lookup::Handles::iterator it = std::find(lr->handles.begin(), lr->handles.end(), typename Lookup::Handle(""));
130 
131  if(it != lr->handles.end()) {
132  if(!it->lent)
133  delete it->ptr;
134  lr->handles.erase(it);
135  }
136 
137  lr->handles.push_front(typename Lookup::Handle(type, "", true, keep));
138 
139  m_entries[lr->id] = type;
140 
141  return lr->id;
142  }
143 
144  template <class TYPE>
146  typename Lookups::iterator it = m_lookups.find(name);
147 
148  if(it == m_lookups.end())
149  throw Database_Entry_Not_Found("*::" + name);
150 
151  Lookup &lr = *it->second;
152  typename Lookup::Handles::iterator jt = std::find(lr.handles.begin(), lr.handles.end(), typename Lookup::Handle(filename));
153 
154  if(jt == lr.handles.end())
155  throw Database_Entry_Not_Found(filename + "::" + name);
156 
157  if(!jt->lent)
158  delete jt->ptr;
159 
160  lr.handles.erase(jt);
161 
162  if(lr.handles.empty()) {
163  m_entries.erase(lr.id);
164  delete it->second;
165  m_lookups.erase(it);
166  }
167  else
168  m_entries[lr.id] = lr.handles.begin()->ptr;
169  }
170 
171  template <class TYPE>
172  unsigned long Database<TYPE>::get_id(const String &name) const {
173  typename Lookups::const_iterator it = m_lookups.find(name);
174 
175  if(it == m_lookups.end() || !it->second->id)
176  throw Database_Entry_Not_Found(name);
177 
178  return it->second->id;
179  }
180 
181  template <class TYPE>
182  unsigned long Database<TYPE>::find(const String &name) const {
183  typename Lookups::const_iterator it = m_lookups.find(name);
184 
185  if(it != m_lookups.end() && it->second->id && find(it->second->id))
186  return it->second->id;
187 
188  return 0;
189  }
190 
191  template <class TYPE>
192  bool Database<TYPE>::find(const unsigned long &id) const {
193  return m_entries.find(id) != m_entries.end();
194  }
195 
196  template <class TYPE>
197  TYPE & Database<TYPE>::operator[](const unsigned long &id) const {
198  typename Entries::const_iterator it = m_entries.find(id);
199 
200  if(it == m_entries.end() || !it->second) {
201  char buf[64];
202 #ifdef _WINDOWS
203  sprintf_s
204 #else
205  sprintf
206 #endif
207  (buf, "ID = %u", static_cast<unsigned int>(id));
208  throw Database_Entry_Not_Found(buf);
209  }
210 
211  return *it->second;
212  }
213 
214  template <class TYPE>
216  return (*this)[get_id(name)];
217  }
218 
219  template <class TYPE>
221  uninit();
222  }
223 
224  template <class TYPE>
226  Filenames::iterator it = std::find(m_filenames.begin(), m_filenames.end(), filename);
227  if(it != m_filenames.end())
228  m_filenames.erase(it);
229  m_filenames.push_front(filename);
230 
231 #ifdef ANDROID
232  XML_Document types_xml;
233  {
234  String memory;
235  types_xml.load_mem(File_Ops::load_asset(memory, filename));
236  }
237 #else
238  XML_Document types_xml(filename.c_str());
239 #endif
240 
241  XML_Element_c types = types_xml[m_xml_identifier];
242  String name;
243 
244  try {
245  for(XML_Element_c it = types.first(); it.good(); it = it.next()) {
246  name = it.value();
247 
248  if(!give_priority(name, false, false, filename)) {
249  TYPE * const type = load(it, name, filename);
250  if(!type)
251  throw Database_Load_Entry_Failed(name);
252 
253  give(name, type, false, filename);
254  }
255  }
256  }
257  catch(...)
258  {
259  const String error = "Error loading '" + m_xml_identifier + "' entry '" + name + "'";
260  std::cerr << error << std::endl;
261  message_box(error);
262  throw;
263  }
264 
265  on_load();
266  }
267 
268  template <class TYPE>
270  Filenames::iterator it = std::find(m_filenames.begin(), m_filenames.end(), filename);
271  if(it == m_filenames.end())
272  throw Database_File_Not_Loaded(filename);
273 
274  for(typename Lookups::iterator it = m_lookups.begin();
275  it != m_lookups.end();
276  ++it)
277  {
278  for(typename Lookup::Handles::iterator jt = it->second->handles.begin();
279  jt != it->second->handles.end();)
280  {
281  if(jt->filename != filename)
282  ++jt;
283  else {
284  if(!jt->lent)
285  delete jt->ptr;
286  jt = it->second->handles.erase(jt);
287  }
288  }
289 
290  if(!it->second->handles.empty()) {
291  m_entries[it->second->id] = it->second->handles.begin()->ptr;
292 // ++it;
293  }
294  else {
295  m_entries.erase(it->second->id);
296 // delete it->second;
297 // it = m_lookups.erase(it);
298  }
299  }
300 
301  m_filenames.erase(it);
302 
303  if(m_filenames.empty())
304  on_clear();
305  }
306 
307  template <class TYPE>
309  lose_resources();
310  init();
311  }
312 
313  template <class TYPE>
315  const Filenames old = m_filenames;
316 
317  for(Filenames::const_reverse_iterator it = old.rbegin();
318  it != old.rend();
319  ++it)
320  {
321  ZENI_LOGD((String("Loading ") + *it).c_str());
322  load_file(*it);
323  ZENI_LOGD((String("Loaded ") + *it).c_str());
324  }
325 
326  m_lost = false;
327  }
328 
329  template <class TYPE>
331  on_clear();
332 
333  m_entries.clear();
334 
335  for(typename Lookups::iterator it = m_lookups.begin();
336  it != m_lookups.end();
337  ++it)
338  {
339  for(typename Lookup::Handles::iterator jt = it->second->handles.begin();
340  jt != it->second->handles.end();
341  ++jt)
342  {
343  if(!jt->lent)
344  delete jt->ptr;
345  }
346 
347  delete it->second;
348  }
349 
350  m_lookups.clear();
351  }
352 
353  template <class TYPE>
355  const bool &lent,
356  const bool &keep,
357  const String &filename)
358  {
359  const typename Lookups::const_iterator it = m_lookups.find(name);
360  if(it == m_lookups.end())
361  return false;
362 
363  typename Lookup::Handles &lhr = it->second->handles;
364  typename Lookup::Handles::iterator jt = std::find(lhr.begin(), lhr.end(), typename Lookup::Handle(filename));
365  if(jt == lhr.end())
366  return false;
367 
368  if(jt->lent != lent || jt->keep != keep)
369  return false;
370 
371  const typename Lookup::Handle handle = *jt;
372  lhr.erase(jt);
373  lhr.push_front(handle);
374 
375  m_entries[it->second->id] = handle.ptr;
376 
377  return true;
378  }
379 
380  template <class TYPE>
382  return m_lost;
383  }
384 
385  template <class TYPE>
387  on_lose();
388 
389  for(typename Lookups::iterator it = m_lookups.begin();
390  it != m_lookups.end();
391  ++it)
392  {
393  for(typename Lookup::Handles::iterator jt = it->second->handles.begin();
394  jt != it->second->handles.end();)
395  {
396  if(jt->keep)
397  ++jt;
398  else {
399  if(!jt->lent)
400  delete jt->ptr;
401  jt = it->second->handles.erase(jt);
402  }
403  }
404 
405  if(!it->second->handles.empty())
406  m_entries[it->second->id] = it->second->handles.begin()->ptr;
407  else
408  m_entries.erase(it->second->id);
409  }
410 
411  m_lost = true;
412  }
413 
414  template <class TYPE>
416  if(m_lost)
417  init();
418  }
419 
420 }
421 
422 #include <Zeni/Resource.hxx>
423 
424 #endif
Definition: Database.h:150
void lose_resources()
Wipe losable resources and prepare to reload them when they are next needed.
Definition: Database.hxx:386
static String & load_asset(String &memory, const String &filename)
Load a file into memory.
Definition: File_Ops.cpp:190
GLsizei GLenum GLenum * types
Definition: glew.h:3769
Definition: Database.h:142
unsigned long give(const String &name, TYPE *const &type, const bool &keep, const String &filename="")
Add an entry (which it will later delete)
Definition: Database.hxx:91
unsigned long lend(const String &name, TYPE *const &type, const bool &keep)
Add an entry (which it will NEVER delete)
Definition: Database.hxx:118
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
Definition: Database.h:146
static void init(struct bs2b *bs2b)
Definition: bs2b.c:46
unsigned long get_id(const String &name) const
Get an id by name, possibly throwing an Error.
Definition: Database.hxx:172
const char * c_str() const
Definition: String.cpp:467
EGLImageKHR EGLint * name
Definition: eglext.h:284
void load_mem(const String &data)
Definition: XML.cpp:262
unsigned long assign()
Get a value, unique within this run of the program.
Definition: Resource.hxx:25
void reload()
lose_resources + init
Definition: Database.hxx:308
GLuint id
Definition: gl2ext.h:1142
void load_file(const String &filename)
Load all resources from a given file, giving them highest priority.
Definition: Database.hxx:225
A Texture Database Singleton.
Definition: Database.h:46
void clear()
Permanently clear all resources.
Definition: Database.hxx:220
virtual ~Database()
Definition: Database.hxx:86
FT_Error error
Definition: cffdrivr.c:407
#define true
Definition: ftrandom.c:49
void ZENI_LOGD(const Zeni::String &str)
Definition: Android.h:50
A class to open an XML file and manage the root node.
Definition: XML.h:111
TYPE & operator[](const String &name) const
Get a TYPE by name.
Definition: Database.hxx:215
Resource & get_Resource()
Get access to the singleton.
Definition: Resource.cpp:35
void message_box(const char *const &msg)
Definition: Error.h:60
bool operator==(const Handle &rhs) const
Definition: Database.hxx:60
unsigned long find(const String &name) const
Get an id by name, without throwing an Error.
Definition: Database.hxx:182
void unlose_resources()
If resources have been lost, then reload them.
Definition: Database.hxx:415
GLenum GLuint GLsizei const GLchar * buf
Definition: glew.h:2539
const bool & lost_resources()
Check to see if resources have been lost.
Definition: Database.hxx:381
bool give_priority(const String &name, const bool &lent, const bool &keep, const String &filename="")
If &#39;lent&#39;, &#39;keep&#39;, and &#39;filename&#39; match, give priority over other &#39;name&#39; entries. ...
Definition: Database.hxx:354
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:284
Definition: infutil.h:15
XML_Element_c first() const
Get the first subelement.
Definition: XML.cpp:44
#define false
Definition: ftrandom.c:50
void unload_file(const String &filename)
Unload all resources from a given file, reloading lower priority resources.
Definition: Database.hxx:269
bool good() const
Test to see if the Element is valid.
Definition: XML.cpp:64