1 #ifndef HEADER_RESOURCEPACK_H 2 #define HEADER_RESOURCEPACK_H 3 4 #include "Log.h" 5 #include "Random.h" 6 #include "INamed.h" 7 #include "ResourceException.h" 8 9 #include <string> 10 #include <vector> 11 #include <map> 12 13 /** 14 * Share resources. 15 */ 16 template <class T> 17 class ResourcePack : public INamed { 18 public: 19 typedef std::vector<T> t_range; 20 protected: 21 typedef std::multimap<std::string,T> t_reses; 22 typedef typename t_reses::iterator t_resIterator; 23 typedef typename t_reses::const_iterator t_constIterator; 24 t_reses m_reses; 25 26 public: 27 /** 28 * Frees the given resource. 29 */ 30 virtual void unloadRes(T res) = 0; 31 32 //NOTE: we cannot call virtual functions from desctructor, 33 // call removeAll before delete ~ResourcePack()34 virtual ~ResourcePack() 35 { 36 if (!m_reses.empty()) { 37 LOG_WARNING(ExInfo("resources are not released") 38 .addInfo("pack", toString())); 39 } 40 } 41 //----------------------------------------------------------------- 42 /** 43 * Free all resources. 44 * NOTE: we cannot call virtual functions from desctructor 45 */ removeAll()46 void removeAll() 47 { 48 t_resIterator end = m_reses.end(); 49 for (t_resIterator item = m_reses.begin(); item != end; ++item) { 50 unloadRes(item->second); 51 } 52 m_reses.clear(); 53 } 54 //----------------------------------------------------------------- 55 /** 56 * Unload all resources with this name. 57 */ removeRes(const std::string & name)58 void removeRes(const std::string &name) 59 { 60 std::pair<t_resIterator, t_resIterator> range = 61 m_reses.equal_range(name); 62 while (range.first != range.second) { 63 unloadRes(range.first->second); 64 ++(range.first); 65 } 66 m_reses.erase(name); 67 LOG_DEBUG(ExInfo("removed resources") 68 .addInfo("name", name)); 69 } 70 71 //----------------------------------------------------------------- 72 /** 73 * Store resource under this name. 74 */ addRes(const std::string & name,T res)75 void addRes(const std::string &name, T res) 76 { 77 m_reses.insert( 78 std::pair<std::string,T>(name, res)); 79 } 80 //----------------------------------------------------------------- 81 /** 82 * Get resource with this name. 83 */ 84 T getRes(const std::string &name, int rank=0) 85 { 86 std::pair<t_resIterator, t_resIterator> range = 87 m_reses.equal_range(name); 88 for (int i = 0; i < rank && range.first != range.second; ++i) { 89 ++(range.first); 90 } 91 if (range.second == range.first) { 92 throw ResourceException(ExInfo("no such resource at index") 93 .addInfo("name", name) 94 .addInfo("index", rank) 95 .addInfo("pack", toString())); 96 } 97 return range.first->second; 98 } 99 //----------------------------------------------------------------- 100 /** 101 * Get all resources with this name. 102 * NOTE: range can be empty. 103 */ getRange(const std::string & name)104 t_range getRange(const std::string &name) 105 { 106 t_range result; 107 std::pair<t_resIterator, t_resIterator> range = 108 m_reses.equal_range(name); 109 while (range.first != range.second) { 110 result.push_back(range.first->second); 111 range.first++; 112 } 113 114 return result; 115 } 116 //----------------------------------------------------------------- 117 /** 118 * Get resource at random index or return NULL. 119 */ getRandomRes(const std::string & name)120 T getRandomRes(const std::string &name) 121 { 122 T result = NULL; 123 typename t_reses::size_type count = m_reses.count(name); 124 if (count > 0) { 125 result = getRes(name, Random::randomInt(count)); 126 } 127 else { 128 LOG_WARNING(ExInfo("no such resource") 129 .addInfo("name", name) 130 .addInfo("pack", toString())); 131 } 132 return result; 133 } 134 //----------------------------------------------------------------- 135 /** 136 * Count resources with this name. 137 */ countRes(const std::string & name)138 int countRes(const std::string &name) 139 { 140 return m_reses.count(name); 141 } 142 //----------------------------------------------------------------- toString()143 std::string toString() const 144 { 145 ExInfo available_res = ExInfo("resources") 146 .addInfo("name", getName()); 147 148 t_constIterator end = m_reses.end(); 149 for (t_constIterator item = m_reses.begin(); item != end; ++item) { 150 available_res.addInfo("key", item->first); 151 } 152 return available_res.info(); 153 } 154 155 }; 156 157 #endif 158 159