3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
29 #include <jmutexautolock.h>
31 #include "common_irrlicht.h"
34 #include "exceptions.h"
37 extern const v3s16 g_26dirs[26];
40 extern const v3s16 g_27dirs[27];
42 inline void writeU32(u8 *data, u32 i)
44 data[0] = ((i>>24)&0xff);
45 data[1] = ((i>>16)&0xff);
46 data[2] = ((i>> 8)&0xff);
47 data[3] = ((i>> 0)&0xff);
50 inline void writeU16(u8 *data, u16 i)
52 data[0] = ((i>> 8)&0xff);
53 data[1] = ((i>> 0)&0xff);
56 inline void writeU8(u8 *data, u8 i)
58 data[0] = ((i>> 0)&0xff);
61 inline u32 readU32(u8 *data)
63 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
66 inline u16 readU16(u8 *data)
68 return (data[0]<<8) | (data[1]<<0);
71 inline u8 readU8(u8 *data)
76 // Signed variants of the above
78 inline void writeS32(u8 *data, s32 i){
79 writeU32(data, (u32)i);
81 inline s32 readS32(u8 *data){
82 return (s32)readU32(data);
85 inline void writeS16(u8 *data, s16 i){
86 writeU16(data, (u16)i);
88 inline s16 readS16(u8 *data){
89 return (s16)readU16(data);
92 inline void writeV3S32(u8 *data, v3s32 p)
94 writeS32(&data[0], p.X);
95 writeS32(&data[4], p.Y);
96 writeS32(&data[8], p.Z);
99 inline v3s32 readV3S32(u8 *data)
102 p.X = readS32(&data[0]);
103 p.Y = readS32(&data[4]);
104 p.Z = readS32(&data[8]);
108 inline void writeV2S16(u8 *data, v2s16 p)
110 writeS16(&data[0], p.X);
111 writeS16(&data[2], p.Y);
114 inline v2s16 readV2S16(u8 *data)
117 p.X = readS16(&data[0]);
118 p.Y = readS16(&data[2]);
122 inline void writeV2S32(u8 *data, v2s32 p)
124 writeS32(&data[0], p.X);
125 writeS32(&data[2], p.Y);
128 inline v2s32 readV2S32(u8 *data)
131 p.X = readS32(&data[0]);
132 p.Y = readS32(&data[2]);
136 inline void writeV3S16(u8 *data, v3s16 p)
138 writeS16(&data[0], p.X);
139 writeS16(&data[2], p.Y);
140 writeS16(&data[4], p.Z);
143 inline v3s16 readV3S16(u8 *data)
146 p.X = readS16(&data[0]);
147 p.Y = readS16(&data[2]);
148 p.Z = readS16(&data[4]);
153 None of these are used at the moment
156 template <typename T>
166 SharedPtr(SharedPtr<T> &t)
170 refcount = t.refcount;
178 SharedPtr<T> & operator=(T *t)
186 SharedPtr<T> & operator=(SharedPtr<T> &t)
189 refcount = t.refcount;
202 bool operator!=(T *t)
206 bool operator==(T *t)
210 T & operator[](unsigned int i)
217 assert((*refcount) > 0);
230 template <typename T>
234 Buffer(unsigned int size)
239 Buffer(const Buffer &buffer)
241 m_size = buffer.m_size;
242 data = new T[buffer.m_size];
243 memcpy(data, buffer.data, buffer.m_size);
245 Buffer(T *t, unsigned int size)
249 memcpy(data, t, size);
255 T & operator[](unsigned int i) const
259 T * operator*() const
263 unsigned int getSize() const
272 template <typename T>
276 SharedBuffer(unsigned int size)
280 refcount = new unsigned int;
283 SharedBuffer(const SharedBuffer &buffer)
285 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
286 m_size = buffer.m_size;
288 refcount = buffer.refcount;
291 SharedBuffer & operator=(const SharedBuffer & buffer)
293 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
297 m_size = buffer.m_size;
299 refcount = buffer.refcount;
306 SharedBuffer(T *t, unsigned int size)
310 memcpy(data, t, size);
311 refcount = new unsigned int;
317 SharedBuffer(const Buffer<T> &buffer)
319 m_size = buffer.m_size;
320 data = new T[buffer.getSize()];
321 memcpy(data, *buffer, buffer.getSize());
322 refcount = new unsigned int;
329 T & operator[](unsigned int i) const
333 T * operator*() const
337 unsigned int getSize() const
344 assert((*refcount) > 0);
354 unsigned int *refcount;
357 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
359 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
364 class MutexedVariable
367 MutexedVariable(T value):
375 JMutexAutoLock lock(m_mutex);
381 JMutexAutoLock lock(m_mutex);
385 // You'll want to grab this in a SharedPtr
386 JMutexAutoLock * getLock()
388 return new JMutexAutoLock(m_mutex);
391 // You pretty surely want to grab the lock when accessing this
402 class IrrlichtWrapper;
407 TimeTaker(const char *name, u32 *result=NULL);
414 u32 stop(bool quiet=false);
425 // Calculates the borders of a "d-radius" cube
426 inline void getFacePositions(core::list<v3s16> &list, u16 d)
430 list.push_back(v3s16(0,0,0));
436 This is an optimized sequence of coordinates.
438 list.push_back(v3s16( 0, 1, 0)); // top
439 list.push_back(v3s16( 0, 0, 1)); // back
440 list.push_back(v3s16(-1, 0, 0)); // left
441 list.push_back(v3s16( 1, 0, 0)); // right
442 list.push_back(v3s16( 0, 0,-1)); // front
443 list.push_back(v3s16( 0,-1, 0)); // bottom
445 list.push_back(v3s16(-1, 0, 1)); // back left
446 list.push_back(v3s16( 1, 0, 1)); // back right
447 list.push_back(v3s16(-1, 0,-1)); // front left
448 list.push_back(v3s16( 1, 0,-1)); // front right
449 list.push_back(v3s16(-1,-1, 0)); // bottom left
450 list.push_back(v3s16( 1,-1, 0)); // bottom right
451 list.push_back(v3s16( 0,-1, 1)); // bottom back
452 list.push_back(v3s16( 0,-1,-1)); // bottom front
453 list.push_back(v3s16(-1, 1, 0)); // top left
454 list.push_back(v3s16( 1, 1, 0)); // top right
455 list.push_back(v3s16( 0, 1, 1)); // top back
456 list.push_back(v3s16( 0, 1,-1)); // top front
458 list.push_back(v3s16(-1, 1, 1)); // top back-left
459 list.push_back(v3s16( 1, 1, 1)); // top back-right
460 list.push_back(v3s16(-1, 1,-1)); // top front-left
461 list.push_back(v3s16( 1, 1,-1)); // top front-right
462 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
463 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
464 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
465 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
470 // Take blocks in all sides, starting from y=0 and going +-y
471 for(s16 y=0; y<=d-1; y++)
473 // Left and right side, including borders
474 for(s16 z=-d; z<=d; z++)
476 list.push_back(v3s16(d,y,z));
477 list.push_back(v3s16(-d,y,z));
480 list.push_back(v3s16(d,-y,z));
481 list.push_back(v3s16(-d,-y,z));
484 // Back and front side, excluding borders
485 for(s16 x=-d+1; x<=d-1; x++)
487 list.push_back(v3s16(x,y,d));
488 list.push_back(v3s16(x,y,-d));
491 list.push_back(v3s16(x,-y,d));
492 list.push_back(v3s16(x,-y,-d));
497 // Take the bottom and top face with borders
498 // -d<x<d, y=+-d, -d<z<d
499 for(s16 x=-d; x<=d; x++)
500 for(s16 z=-d; z<=d; z++)
502 list.push_back(v3s16(x,-d,z));
503 list.push_back(v3s16(x,d,z));
507 class IndentationRaiser
510 IndentationRaiser(u16 *indentation)
512 m_indentation = indentation;
523 inline s16 getContainerPos(s16 p, s16 d)
525 return (p>=0 ? p : p-d+1) / d;
528 inline v2s16 getContainerPos(v2s16 p, s16 d)
531 getContainerPos(p.X, d),
532 getContainerPos(p.Y, d)
536 inline v3s16 getContainerPos(v3s16 p, s16 d)
539 getContainerPos(p.X, d),
540 getContainerPos(p.Y, d),
541 getContainerPos(p.Z, d)
545 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
548 getContainerPos(p.X, d.X),
549 getContainerPos(p.Y, d.Y)
553 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
556 getContainerPos(p.X, d.X),
557 getContainerPos(p.Y, d.Y),
558 getContainerPos(p.Z, d.Z)
562 inline bool isInArea(v3s16 p, s16 d)
565 p.X >= 0 && p.X < d &&
566 p.Y >= 0 && p.Y < d &&
571 inline bool isInArea(v2s16 p, s16 d)
574 p.X >= 0 && p.X < d &&
579 inline bool isInArea(v3s16 p, v3s16 d)
582 p.X >= 0 && p.X < d.X &&
583 p.Y >= 0 && p.Y < d.Y &&
584 p.Z >= 0 && p.Z < d.Z
588 inline s16 rangelim(s16 i, s16 max)
597 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
599 inline v3s16 arealim(v3s16 p, s16 d)
616 inline std::wstring narrow_to_wide(const std::string& mbs)
618 size_t wcl = mbs.size();
619 SharedBuffer<wchar_t> wcs(wcl+1);
620 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
625 inline std::string wide_to_narrow(const std::wstring& wcs)
627 size_t mbl = wcs.size()*4;
628 SharedBuffer<char> mbs(mbl+1);
629 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
638 See test.cpp for example cases.
639 wraps degrees to the range of -360...360
640 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
642 inline float wrapDegrees(float f)
644 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
650 // NOTE: This would be used for wrapping to 0...360
656 // 10, 0.5, -0.5, -0.5
661 inline std::string lowercase(const std::string &s)
664 for(size_t i=0; i<s.size(); i++)
667 if(c >= 'A' && c <= 'Z')
674 inline bool is_yes(const std::string &s)
676 std::string s2 = lowercase(trim(s));
677 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
682 inline s32 stoi(const std::string &s, s32 min, s32 max)
684 s32 i = atoi(s.c_str());
692 inline s32 stoi(std::string s)
694 return atoi(s.c_str());
697 inline float stof(std::string s)
700 std::istringstream ss(s);
705 inline std::string itos(s32 i)
707 std::ostringstream o;
712 inline std::string ftos(float f)
714 std::ostringstream o;
719 inline void str_replace(std::string & str, std::string const & pattern,
720 std::string const & replacement)
722 std::string::size_type start = str.find(pattern, 0);
723 while(start != str.npos)
725 str.replace(start, pattern.size(), replacement);
726 start = str.find(pattern, start+replacement.size());
730 inline void str_replace_char(std::string & str, char from, char to)
732 for(unsigned int i=0; i<str.size(); i++)
740 A base class for simple background thread implementation
743 class SimpleThread : public JThread
757 virtual ~SimpleThread()
760 virtual void * Thread() = 0;
764 JMutexAutoLock lock(run_mutex);
767 void setRun(bool a_run)
769 JMutexAutoLock lock(run_mutex);
788 VALUETYPE_FLAG // Doesn't take any arguments
793 ValueSpec(ValueType a_type, const char *a_help=NULL)
810 void writeLines(std::ostream &os)
812 JMutexAutoLock lock(m_mutex);
814 for(core::map<std::string, std::string>::Iterator
815 i = m_settings.getIterator();
816 i.atEnd() == false; i++)
818 std::string name = i.getNode()->getKey();
819 std::string value = i.getNode()->getValue();
820 os<<name<<" = "<<value<<"\n";
824 bool parseConfigLine(const std::string &line)
826 JMutexAutoLock lock(m_mutex);
828 std::string trimmedline = trim(line);
831 if(trimmedline[0] == '#')
834 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
836 Strfnd sf(trim(line));
838 std::string name = sf.next("=");
844 std::string value = sf.next("\n");
847 /*dstream<<"Config name=\""<<name<<"\" value=\""
848 <<value<<"\""<<std::endl;*/
850 m_settings[name] = value;
855 // Returns false on EOF
856 bool parseConfigObject(std::istream &is)
862 NOTE: This function might be expanded to allow multi-line
866 std::getline(is, line);
867 //dstream<<"got line: \""<<line<<"\""<<std::endl;
869 return parseConfigLine(line);
873 Read configuration file
875 Returns true on success
877 bool readConfigFile(const char *filename)
879 std::ifstream is(filename);
880 if(is.good() == false)
882 dstream<<"Error opening configuration file \""
883 <<filename<<"\""<<std::endl;
887 dstream<<"Parsing configuration file: \""
888 <<filename<<"\""<<std::endl;
890 while(parseConfigObject(is));
896 Reads a configuration object from stream (usually a single line)
899 Preserves comments and empty lines.
901 Settings that were added to dst are also added to updated.
902 key of updated is setting name, value of updated is dummy.
906 bool getUpdatedConfigObject(std::istream &is,
907 core::list<std::string> &dst,
908 core::map<std::string, bool> &updated)
910 JMutexAutoLock lock(m_mutex);
915 // NOTE: This function will be expanded to allow multi-line settings
917 std::getline(is, line);
919 std::string trimmedline = trim(line);
921 std::string line_end = "";
922 if(is.eof() == false)
926 if(trimmedline[0] == '#')
928 dst.push_back(line+line_end);
932 Strfnd sf(trim(line));
934 std::string name = sf.next("=");
939 dst.push_back(line+line_end);
943 std::string value = sf.next("\n");
946 if(m_settings.find(name))
948 std::string newvalue = m_settings[name];
950 if(newvalue != value)
952 dstream<<"Changing value of \""<<name<<"\" = \""
953 <<value<<"\" -> \""<<newvalue<<"\""
957 dst.push_back(name + " = " + newvalue + line_end);
959 updated[name] = true;
966 Updates configuration file
968 Returns true on success
970 bool updateConfigFile(const char *filename)
972 dstream<<"Updating configuration file: \""
973 <<filename<<"\""<<std::endl;
975 core::list<std::string> objects;
976 core::map<std::string, bool> updated;
978 // Read and modify stuff
980 std::ifstream is(filename);
981 if(is.good() == false)
983 dstream<<"INFO: updateConfigFile():"
984 " Error opening configuration file"
986 <<filename<<"\""<<std::endl;
990 while(getUpdatedConfigObject(is, objects, updated));
994 JMutexAutoLock lock(m_mutex);
998 std::ofstream os(filename);
999 if(os.good() == false)
1001 dstream<<"Error opening configuration file"
1003 <<filename<<"\""<<std::endl;
1010 for(core::list<std::string>::Iterator
1011 i = objects.begin();
1012 i != objects.end(); i++)
1018 Write stuff that was not already in the file
1020 for(core::map<std::string, std::string>::Iterator
1021 i = m_settings.getIterator();
1022 i.atEnd() == false; i++)
1024 if(updated.find(i.getNode()->getKey()))
1026 std::string name = i.getNode()->getKey();
1027 std::string value = i.getNode()->getValue();
1028 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1030 os<<name<<" = "<<value<<"\n";
1038 NOTE: Types of allowed_options are ignored
1040 returns true on success
1042 bool parseCommandLine(int argc, char *argv[],
1043 core::map<std::string, ValueSpec> &allowed_options)
1050 std::string argname = argv[i];
1051 if(argname.substr(0, 2) != "--")
1053 dstream<<"Invalid command-line parameter \""
1054 <<argname<<"\": --<option> expected."<<std::endl;
1059 std::string name = argname.substr(2);
1061 core::map<std::string, ValueSpec>::Node *n;
1062 n = allowed_options.find(name);
1065 dstream<<"Unknown command-line parameter \""
1066 <<argname<<"\""<<std::endl;
1070 ValueType type = n->getValue().type;
1072 std::string value = "";
1074 if(type == VALUETYPE_FLAG)
1082 dstream<<"Invalid command-line parameter \""
1083 <<name<<"\": missing value"<<std::endl;
1091 dstream<<"Valid command-line parameter: \""
1092 <<name<<"\" = \""<<value<<"\""
1100 void set(std::string name, std::string value)
1102 JMutexAutoLock lock(m_mutex);
1104 m_settings[name] = value;
1107 void setDefault(std::string name, std::string value)
1109 JMutexAutoLock lock(m_mutex);
1111 m_defaults[name] = value;
1114 bool exists(std::string name)
1116 JMutexAutoLock lock(m_mutex);
1118 return (m_settings.find(name) || m_defaults.find(name));
1121 std::string get(std::string name)
1123 JMutexAutoLock lock(m_mutex);
1125 core::map<std::string, std::string>::Node *n;
1126 n = m_settings.find(name);
1129 n = m_defaults.find(name);
1132 dstream<<"INFO: Settings: Setting not found: \""
1133 <<name<<"\""<<std::endl;
1134 throw SettingNotFoundException("Setting not found");
1138 return n->getValue();
1141 bool getBool(std::string name)
1143 return is_yes(get(name));
1146 bool getFlag(std::string name)
1150 return getBool(name);
1152 catch(SettingNotFoundException &e)
1159 bool getBoolAsk(std::string name, std::string question, bool def)
1161 // If it is in settings
1163 return getBool(name);
1167 std::cout<<question<<" [y/N]: ";
1168 std::cin.getline(templine, 10);
1177 float getFloat(std::string name)
1179 return stof(get(name));
1182 u16 getU16(std::string name)
1184 return stoi(get(name), 0, 65535);
1187 u16 getU16Ask(std::string name, std::string question, u16 def)
1189 // If it is in settings
1191 return getU16(name);
1195 std::cout<<question<<" ["<<def<<"]: ";
1196 std::cin.getline(templine, 10);
1202 return stoi(s, 0, 65535);
1205 s16 getS16(std::string name)
1207 return stoi(get(name), -32768, 32767);
1210 s32 getS32(std::string name)
1212 return stoi(get(name));
1215 v3f getV3F(std::string name)
1218 Strfnd f(get(name));
1220 value.X = stof(f.next(","));
1221 value.Y = stof(f.next(","));
1222 value.Z = stof(f.next(")"));
1226 u64 getU64(std::string name)
1229 std::string s = get(name);
1230 std::istringstream ss(s);
1235 void setS32(std::string name, s32 value)
1237 set(name, itos(value));
1240 void setFloat(std::string name, float value)
1242 set(name, ftos(value));
1245 void setV3F(std::string name, v3f value)
1247 std::ostringstream os;
1248 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1249 set(name, os.str());
1252 void setU64(std::string name, u64 value)
1254 std::ostringstream os;
1256 set(name, os.str());
1261 JMutexAutoLock lock(m_mutex);
1267 Settings & operator+=(Settings &other)
1269 JMutexAutoLock lock(m_mutex);
1270 JMutexAutoLock lock2(other.m_mutex);
1275 for(core::map<std::string, std::string>::Iterator
1276 i = other.m_settings.getIterator();
1277 i.atEnd() == false; i++)
1279 m_settings.insert(i.getNode()->getKey(),
1280 i.getNode()->getValue());
1283 for(core::map<std::string, std::string>::Iterator
1284 i = other.m_defaults.getIterator();
1285 i.atEnd() == false; i++)
1287 m_defaults.insert(i.getNode()->getKey(),
1288 i.getNode()->getValue());
1293 Settings & operator=(Settings &other)
1295 JMutexAutoLock lock(m_mutex);
1296 JMutexAutoLock lock2(other.m_mutex);
1308 core::map<std::string, std::string> m_settings;
1309 core::map<std::string, std::string> m_defaults;
1310 // All methods that access m_settings/m_defaults directly should lock this.
1317 template<typename T>
1323 m_list.push_back(t);
1328 if(m_list.size() == 0)
1329 throw ItemNotFoundException("MutexedQueue: queue is empty");
1331 typename core::list<T>::Iterator begin = m_list.begin();
1333 m_list.erase(begin);
1339 return m_list.size();
1343 core::list<T> m_list;
1347 Thread-safe FIFO queue
1350 template<typename T>
1360 return m_list.size();
1364 JMutexAutoLock lock(m_mutex);
1365 m_list.push_back(t);
1367 T pop_front(u32 wait_time_max_ms=0)
1369 u32 wait_time_ms = 0;
1374 JMutexAutoLock lock(m_mutex);
1376 if(m_list.size() > 0)
1378 typename core::list<T>::Iterator begin = m_list.begin();
1380 m_list.erase(begin);
1384 if(wait_time_ms >= wait_time_max_ms)
1385 throw ItemNotFoundException("MutexedQueue: queue is empty");
1388 // Wait a while before trying again
1399 core::list<T> & getList()
1406 core::list<T> m_list;
1409 template<typename Caller, typename Data>
1417 template<typename Key, typename T, typename Caller, typename CallerData>
1423 core::list<CallerInfo<Caller, CallerData> > callers;
1426 template<typename Key, typename T, typename Caller, typename CallerData>
1427 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1431 template<typename Key, typename T, typename Caller, typename CallerData>
1439 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1443 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1454 ResultQueue<Key, T, Caller, CallerData> *dest;
1455 core::list<CallerInfo<Caller, CallerData> > callers;
1459 Quickhands for typical request-result queues.
1460 Used for distributing work between threads.
1463 template<typename Key, typename T, typename Caller, typename CallerData>
1469 return m_queue.size();
1472 void add(Key key, Caller caller, CallerData callerdata,
1473 ResultQueue<Key, T, Caller, CallerData> *dest)
1475 JMutexAutoLock lock(m_queue.getMutex());
1478 If the caller is already on the list, only update CallerData
1480 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1481 i = m_queue.getList().begin();
1482 i != m_queue.getList().end(); i++)
1484 GetRequest<Key, T, Caller, CallerData> &request = *i;
1486 if(request.key == key)
1488 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1489 i = request.callers.begin();
1490 i != request.callers.end(); i++)
1492 CallerInfo<Caller, CallerData> &ca = *i;
1493 if(ca.caller == caller)
1495 ca.data = callerdata;
1499 CallerInfo<Caller, CallerData> ca;
1501 ca.data = callerdata;
1502 request.callers.push_back(ca);
1508 Else add a new request to the queue
1511 GetRequest<Key, T, Caller, CallerData> request;
1513 CallerInfo<Caller, CallerData> ca;
1515 ca.data = callerdata;
1516 request.callers.push_back(ca);
1517 request.dest = dest;
1519 m_queue.getList().push_back(request);
1522 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1524 return m_queue.pop_front(wait_if_empty);
1528 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1532 Pseudo-random (VC++ rand() sucks)
1535 void mysrand(unsigned seed);
1536 #define MYRAND_MAX 32767
1538 inline int myrand_range(int min, int max)
1545 return (myrand()%(max-min+1))+min;
1549 Miscellaneous functions
1552 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1553 f32 *distance_ptr=NULL);
1556 Queue with unique values with fast checking of value existence
1559 template<typename Value>
1565 Does nothing if value is already queued.
1568 false: value already exists
1570 bool push_back(Value value)
1572 // Check if already exists
1573 if(m_map.find(value) != NULL)
1577 m_map.insert(value, 0);
1578 m_list.push_back(value);
1585 typename core::list<Value>::Iterator i = m_list.begin();
1587 m_map.remove(value);
1594 assert(m_list.size() == m_map.size());
1595 return m_list.size();
1599 core::map<Value, u8> m_map;
1600 core::list<Value> m_list;
1604 template<typename Key, typename Value>
1611 assert(m_mutex.IsInitialized());
1614 void set(const Key &name, const Value &value)
1616 JMutexAutoLock lock(m_mutex);
1618 m_values[name] = value;
1621 bool get(const Key &name, Value *result)
1623 JMutexAutoLock lock(m_mutex);
1625 typename core::map<Key, Value>::Node *n;
1626 n = m_values.find(name);
1631 *result = n->getValue();
1636 core::map<Key, Value> m_values;
1642 Generates ids for comparable values.
1643 Id=0 is reserved for "no value".
1646 - Returning value by id (very fast)
1647 - Returning id by value
1648 - Generating a new id for a value
1651 - Remove an id/value pair (is possible to implement but slow)
1653 template<typename T>
1654 class MutexedIdGenerator
1657 MutexedIdGenerator()
1660 assert(m_mutex.IsInitialized());
1663 // Returns true if found
1664 bool getValue(u32 id, T &value)
1668 JMutexAutoLock lock(m_mutex);
1669 if(m_id_to_value.size() < id)
1671 value = m_id_to_value[id-1];
1675 // If id exists for value, returns the id.
1676 // Otherwise generates an id for the value.
1677 u32 getId(const T &value)
1679 JMutexAutoLock lock(m_mutex);
1680 typename core::map<T, u32>::Node *n;
1681 n = m_value_to_id.find(value);
1683 return n->getValue();
1684 m_id_to_value.push_back(value);
1685 u32 new_id = m_id_to_value.size();
1686 m_value_to_id.insert(value, new_id);
1692 // Values are stored here at id-1 position (id 1 = [0])
1693 core::array<T> m_id_to_value;
1694 core::map<T, u32> m_value_to_id;
1698 Checks if a string contains only supplied characters
1700 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1702 for(u32 i=0; i<s.size(); i++)
1704 bool confirmed = false;
1705 for(u32 j=0; j<allowed_chars.size(); j++)
1707 if(s[i] == allowed_chars[j])
1713 if(confirmed == false)
1720 Forcefully wraps string into rows using \n
1721 (no word wrap, used for showing paths in gui)
1723 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1726 for(u32 i=0; i<from.size(); i++)
1728 if(i != 0 && i%rowlen == 0)
1738 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1739 #define MYMAX(a,b) ((a)>(b)?(a):(b))