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_6dirs[6];
39 extern const v3s16 g_26dirs[26];
42 extern const v3s16 g_27dirs[27];
44 inline void writeU64(u8 *data, u64 i)
46 data[0] = ((i>>56)&0xff);
47 data[1] = ((i>>48)&0xff);
48 data[2] = ((i>>40)&0xff);
49 data[3] = ((i>>32)&0xff);
50 data[4] = ((i>>24)&0xff);
51 data[5] = ((i>>16)&0xff);
52 data[6] = ((i>> 8)&0xff);
53 data[7] = ((i>> 0)&0xff);
56 inline void writeU32(u8 *data, u32 i)
58 data[0] = ((i>>24)&0xff);
59 data[1] = ((i>>16)&0xff);
60 data[2] = ((i>> 8)&0xff);
61 data[3] = ((i>> 0)&0xff);
64 inline void writeU16(u8 *data, u16 i)
66 data[0] = ((i>> 8)&0xff);
67 data[1] = ((i>> 0)&0xff);
70 inline void writeU8(u8 *data, u8 i)
72 data[0] = ((i>> 0)&0xff);
75 inline u64 readU64(u8 *data)
77 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
78 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
79 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
80 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
83 inline u32 readU32(u8 *data)
85 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
88 inline u16 readU16(u8 *data)
90 return (data[0]<<8) | (data[1]<<0);
93 inline u8 readU8(u8 *data)
98 inline void writeS32(u8 *data, s32 i){
99 writeU32(data, (u32)i);
101 inline s32 readS32(u8 *data){
102 return (s32)readU32(data);
105 inline void writeF1000(u8 *data, f32 i){
106 writeS32(data, i*1000);
108 inline f32 readF1000(u8 *data){
109 return (f32)readS32(data)/1000.;
112 inline void writeS16(u8 *data, s16 i){
113 writeU16(data, (u16)i);
115 inline s16 readS16(u8 *data){
116 return (s16)readU16(data);
119 inline void writeV3S32(u8 *data, v3s32 p)
121 writeS32(&data[0], p.X);
122 writeS32(&data[4], p.Y);
123 writeS32(&data[8], p.Z);
125 inline v3s32 readV3S32(u8 *data)
128 p.X = readS32(&data[0]);
129 p.Y = readS32(&data[4]);
130 p.Z = readS32(&data[8]);
134 inline void writeV3F1000(u8 *data, v3f p)
136 writeF1000(&data[0], p.X);
137 writeF1000(&data[4], p.Y);
138 writeF1000(&data[8], p.Z);
140 inline v3f readV3F1000(u8 *data)
143 p.X = (float)readF1000(&data[0]);
144 p.Y = (float)readF1000(&data[4]);
145 p.Z = (float)readF1000(&data[8]);
149 inline void writeV2S16(u8 *data, v2s16 p)
151 writeS16(&data[0], p.X);
152 writeS16(&data[2], p.Y);
155 inline v2s16 readV2S16(u8 *data)
158 p.X = readS16(&data[0]);
159 p.Y = readS16(&data[2]);
163 inline void writeV2S32(u8 *data, v2s32 p)
165 writeS32(&data[0], p.X);
166 writeS32(&data[2], p.Y);
169 inline v2s32 readV2S32(u8 *data)
172 p.X = readS32(&data[0]);
173 p.Y = readS32(&data[2]);
177 inline void writeV3S16(u8 *data, v3s16 p)
179 writeS16(&data[0], p.X);
180 writeS16(&data[2], p.Y);
181 writeS16(&data[4], p.Z);
184 inline v3s16 readV3S16(u8 *data)
187 p.X = readS16(&data[0]);
188 p.Y = readS16(&data[2]);
189 p.Z = readS16(&data[4]);
194 The above stuff directly interfaced to iostream
197 inline void writeU8(std::ostream &os, u8 p)
200 writeU8((u8*)buf, p);
203 inline u8 readU8(std::istream &is)
207 return readU8((u8*)buf);
210 inline void writeU16(std::ostream &os, u16 p)
213 writeU16((u8*)buf, p);
216 inline u16 readU16(std::istream &is)
220 return readU16((u8*)buf);
223 inline void writeF1000(std::ostream &os, f32 p)
226 writeF1000((u8*)buf, p);
229 inline f32 readF1000(std::istream &is)
233 return readF1000((u8*)buf);
236 inline void writeV3F1000(std::ostream &os, v3f p)
239 writeV3F1000((u8*)buf, p);
242 inline v3f readV3F1000(std::istream &is)
246 return readV3F1000((u8*)buf);
250 None of these are used at the moment
253 template <typename T>
263 SharedPtr(SharedPtr<T> &t)
267 refcount = t.refcount;
275 SharedPtr<T> & operator=(T *t)
283 SharedPtr<T> & operator=(SharedPtr<T> &t)
286 refcount = t.refcount;
299 bool operator!=(T *t)
303 bool operator==(T *t)
307 T & operator[](unsigned int i)
314 assert((*refcount) > 0);
327 template <typename T>
331 Buffer(unsigned int size)
336 Buffer(const Buffer &buffer)
338 m_size = buffer.m_size;
339 data = new T[buffer.m_size];
340 memcpy(data, buffer.data, buffer.m_size);
342 Buffer(T *t, unsigned int size)
346 memcpy(data, t, size);
352 T & operator[](unsigned int i) const
356 T * operator*() const
360 unsigned int getSize() const
369 template <typename T>
373 SharedBuffer(unsigned int size)
377 refcount = new unsigned int;
380 SharedBuffer(const SharedBuffer &buffer)
382 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
383 m_size = buffer.m_size;
385 refcount = buffer.refcount;
388 SharedBuffer & operator=(const SharedBuffer & buffer)
390 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
394 m_size = buffer.m_size;
396 refcount = buffer.refcount;
403 SharedBuffer(T *t, unsigned int size)
407 memcpy(data, t, size);
408 refcount = new unsigned int;
414 SharedBuffer(const Buffer<T> &buffer)
416 m_size = buffer.m_size;
417 data = new T[buffer.getSize()];
418 memcpy(data, *buffer, buffer.getSize());
419 refcount = new unsigned int;
426 T & operator[](unsigned int i) const
430 T * operator*() const
434 unsigned int getSize() const
441 assert((*refcount) > 0);
451 unsigned int *refcount;
454 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
456 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
461 class MutexedVariable
464 MutexedVariable(T value):
472 JMutexAutoLock lock(m_mutex);
478 JMutexAutoLock lock(m_mutex);
482 // You'll want to grab this in a SharedPtr
483 JMutexAutoLock * getLock()
485 return new JMutexAutoLock(m_mutex);
488 // You pretty surely want to grab the lock when accessing this
502 TimeTaker(const char *name, u32 *result=NULL);
509 u32 stop(bool quiet=false);
520 // Calculates the borders of a "d-radius" cube
521 inline void getFacePositions(core::list<v3s16> &list, u16 d)
525 list.push_back(v3s16(0,0,0));
531 This is an optimized sequence of coordinates.
533 list.push_back(v3s16( 0, 1, 0)); // top
534 list.push_back(v3s16( 0, 0, 1)); // back
535 list.push_back(v3s16(-1, 0, 0)); // left
536 list.push_back(v3s16( 1, 0, 0)); // right
537 list.push_back(v3s16( 0, 0,-1)); // front
538 list.push_back(v3s16( 0,-1, 0)); // bottom
540 list.push_back(v3s16(-1, 0, 1)); // back left
541 list.push_back(v3s16( 1, 0, 1)); // back right
542 list.push_back(v3s16(-1, 0,-1)); // front left
543 list.push_back(v3s16( 1, 0,-1)); // front right
544 list.push_back(v3s16(-1,-1, 0)); // bottom left
545 list.push_back(v3s16( 1,-1, 0)); // bottom right
546 list.push_back(v3s16( 0,-1, 1)); // bottom back
547 list.push_back(v3s16( 0,-1,-1)); // bottom front
548 list.push_back(v3s16(-1, 1, 0)); // top left
549 list.push_back(v3s16( 1, 1, 0)); // top right
550 list.push_back(v3s16( 0, 1, 1)); // top back
551 list.push_back(v3s16( 0, 1,-1)); // top front
553 list.push_back(v3s16(-1, 1, 1)); // top back-left
554 list.push_back(v3s16( 1, 1, 1)); // top back-right
555 list.push_back(v3s16(-1, 1,-1)); // top front-left
556 list.push_back(v3s16( 1, 1,-1)); // top front-right
557 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
558 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
559 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
560 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
565 // Take blocks in all sides, starting from y=0 and going +-y
566 for(s16 y=0; y<=d-1; y++)
568 // Left and right side, including borders
569 for(s16 z=-d; z<=d; z++)
571 list.push_back(v3s16(d,y,z));
572 list.push_back(v3s16(-d,y,z));
575 list.push_back(v3s16(d,-y,z));
576 list.push_back(v3s16(-d,-y,z));
579 // Back and front side, excluding borders
580 for(s16 x=-d+1; x<=d-1; x++)
582 list.push_back(v3s16(x,y,d));
583 list.push_back(v3s16(x,y,-d));
586 list.push_back(v3s16(x,-y,d));
587 list.push_back(v3s16(x,-y,-d));
592 // Take the bottom and top face with borders
593 // -d<x<d, y=+-d, -d<z<d
594 for(s16 x=-d; x<=d; x++)
595 for(s16 z=-d; z<=d; z++)
597 list.push_back(v3s16(x,-d,z));
598 list.push_back(v3s16(x,d,z));
602 class IndentationRaiser
605 IndentationRaiser(u16 *indentation)
607 m_indentation = indentation;
618 inline s16 getContainerPos(s16 p, s16 d)
620 return (p>=0 ? p : p-d+1) / d;
623 inline v2s16 getContainerPos(v2s16 p, s16 d)
626 getContainerPos(p.X, d),
627 getContainerPos(p.Y, d)
631 inline v3s16 getContainerPos(v3s16 p, s16 d)
634 getContainerPos(p.X, d),
635 getContainerPos(p.Y, d),
636 getContainerPos(p.Z, d)
640 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
643 getContainerPos(p.X, d.X),
644 getContainerPos(p.Y, d.Y)
648 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
651 getContainerPos(p.X, d.X),
652 getContainerPos(p.Y, d.Y),
653 getContainerPos(p.Z, d.Z)
657 inline bool isInArea(v3s16 p, s16 d)
660 p.X >= 0 && p.X < d &&
661 p.Y >= 0 && p.Y < d &&
666 inline bool isInArea(v2s16 p, s16 d)
669 p.X >= 0 && p.X < d &&
674 inline bool isInArea(v3s16 p, v3s16 d)
677 p.X >= 0 && p.X < d.X &&
678 p.Y >= 0 && p.Y < d.Y &&
679 p.Z >= 0 && p.Z < d.Z
683 inline s16 rangelim(s16 i, s16 max)
692 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
694 inline v3s16 arealim(v3s16 p, s16 d)
711 inline std::wstring narrow_to_wide(const std::string& mbs)
713 size_t wcl = mbs.size();
714 Buffer<wchar_t> wcs(wcl+1);
715 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
716 if(l == (size_t)(-1))
717 return L"<invalid multibyte string>";
722 inline std::string wide_to_narrow(const std::wstring& wcs)
724 size_t mbl = wcs.size()*4;
725 SharedBuffer<char> mbs(mbl+1);
726 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
727 if(l == (size_t)(-1))
735 See test.cpp for example cases.
736 wraps degrees to the range of -360...360
737 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
739 inline float wrapDegrees(float f)
741 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
747 // NOTE: This would be used for wrapping to 0...360
753 // 10, 0.5, -0.5, -0.5
758 inline std::string lowercase(const std::string &s)
761 for(size_t i=0; i<s.size(); i++)
764 if(c >= 'A' && c <= 'Z')
771 inline bool is_yes(const std::string &s)
773 std::string s2 = lowercase(trim(s));
774 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
779 inline s32 stoi(const std::string &s, s32 min, s32 max)
781 s32 i = atoi(s.c_str());
789 inline s32 stoi(std::string s)
791 return atoi(s.c_str());
794 inline float stof(std::string s)
797 std::istringstream ss(s);
802 inline std::string itos(s32 i)
804 std::ostringstream o;
809 inline std::string ftos(float f)
811 std::ostringstream o;
816 inline void str_replace(std::string & str, std::string const & pattern,
817 std::string const & replacement)
819 std::string::size_type start = str.find(pattern, 0);
820 while(start != str.npos)
822 str.replace(start, pattern.size(), replacement);
823 start = str.find(pattern, start+replacement.size());
827 inline void str_replace_char(std::string & str, char from, char to)
829 for(unsigned int i=0; i<str.size(); i++)
837 A base class for simple background thread implementation
840 class SimpleThread : public JThread
854 virtual ~SimpleThread()
857 virtual void * Thread() = 0;
861 JMutexAutoLock lock(run_mutex);
864 void setRun(bool a_run)
866 JMutexAutoLock lock(run_mutex);
885 VALUETYPE_FLAG // Doesn't take any arguments
890 ValueSpec(ValueType a_type, const char *a_help=NULL)
907 void writeLines(std::ostream &os)
909 JMutexAutoLock lock(m_mutex);
911 for(core::map<std::string, std::string>::Iterator
912 i = m_settings.getIterator();
913 i.atEnd() == false; i++)
915 std::string name = i.getNode()->getKey();
916 std::string value = i.getNode()->getValue();
917 os<<name<<" = "<<value<<"\n";
921 bool parseConfigLine(const std::string &line)
923 JMutexAutoLock lock(m_mutex);
925 std::string trimmedline = trim(line);
928 if(trimmedline[0] == '#')
931 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
933 Strfnd sf(trim(line));
935 std::string name = sf.next("=");
941 std::string value = sf.next("\n");
944 /*dstream<<"Config name=\""<<name<<"\" value=\""
945 <<value<<"\""<<std::endl;*/
947 m_settings[name] = value;
952 // Returns false on EOF
953 bool parseConfigObject(std::istream &is)
959 NOTE: This function might be expanded to allow multi-line
963 std::getline(is, line);
964 //dstream<<"got line: \""<<line<<"\""<<std::endl;
966 return parseConfigLine(line);
970 Read configuration file
972 Returns true on success
974 bool readConfigFile(const char *filename)
976 std::ifstream is(filename);
977 if(is.good() == false)
979 dstream<<"Error opening configuration file \""
980 <<filename<<"\""<<std::endl;
984 dstream<<"Parsing configuration file: \""
985 <<filename<<"\""<<std::endl;
987 while(parseConfigObject(is));
993 Reads a configuration object from stream (usually a single line)
996 Preserves comments and empty lines.
998 Settings that were added to dst are also added to updated.
999 key of updated is setting name, value of updated is dummy.
1001 Returns false on EOF
1003 bool getUpdatedConfigObject(std::istream &is,
1004 core::list<std::string> &dst,
1005 core::map<std::string, bool> &updated)
1007 JMutexAutoLock lock(m_mutex);
1012 // NOTE: This function will be expanded to allow multi-line settings
1014 std::getline(is, line);
1016 std::string trimmedline = trim(line);
1018 std::string line_end = "";
1019 if(is.eof() == false)
1023 if(trimmedline[0] == '#')
1025 dst.push_back(line+line_end);
1029 Strfnd sf(trim(line));
1031 std::string name = sf.next("=");
1036 dst.push_back(line+line_end);
1040 std::string value = sf.next("\n");
1041 value = trim(value);
1043 if(m_settings.find(name))
1045 std::string newvalue = m_settings[name];
1047 if(newvalue != value)
1049 dstream<<"Changing value of \""<<name<<"\" = \""
1050 <<value<<"\" -> \""<<newvalue<<"\""
1054 dst.push_back(name + " = " + newvalue + line_end);
1056 updated[name] = true;
1063 Updates configuration file
1065 Returns true on success
1067 bool updateConfigFile(const char *filename)
1069 dstream<<"Updating configuration file: \""
1070 <<filename<<"\""<<std::endl;
1072 core::list<std::string> objects;
1073 core::map<std::string, bool> updated;
1075 // Read and modify stuff
1077 std::ifstream is(filename);
1078 if(is.good() == false)
1080 dstream<<"INFO: updateConfigFile():"
1081 " Error opening configuration file"
1083 <<filename<<"\""<<std::endl;
1087 while(getUpdatedConfigObject(is, objects, updated));
1091 JMutexAutoLock lock(m_mutex);
1095 std::ofstream os(filename);
1096 if(os.good() == false)
1098 dstream<<"Error opening configuration file"
1100 <<filename<<"\""<<std::endl;
1107 for(core::list<std::string>::Iterator
1108 i = objects.begin();
1109 i != objects.end(); i++)
1115 Write stuff that was not already in the file
1117 for(core::map<std::string, std::string>::Iterator
1118 i = m_settings.getIterator();
1119 i.atEnd() == false; i++)
1121 if(updated.find(i.getNode()->getKey()))
1123 std::string name = i.getNode()->getKey();
1124 std::string value = i.getNode()->getValue();
1125 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1127 os<<name<<" = "<<value<<"\n";
1135 NOTE: Types of allowed_options are ignored
1137 returns true on success
1139 bool parseCommandLine(int argc, char *argv[],
1140 core::map<std::string, ValueSpec> &allowed_options)
1147 std::string argname = argv[i];
1148 if(argname.substr(0, 2) != "--")
1150 dstream<<"Invalid command-line parameter \""
1151 <<argname<<"\": --<option> expected."<<std::endl;
1156 std::string name = argname.substr(2);
1158 core::map<std::string, ValueSpec>::Node *n;
1159 n = allowed_options.find(name);
1162 dstream<<"Unknown command-line parameter \""
1163 <<argname<<"\""<<std::endl;
1167 ValueType type = n->getValue().type;
1169 std::string value = "";
1171 if(type == VALUETYPE_FLAG)
1179 dstream<<"Invalid command-line parameter \""
1180 <<name<<"\": missing value"<<std::endl;
1188 dstream<<"Valid command-line parameter: \""
1189 <<name<<"\" = \""<<value<<"\""
1197 void set(std::string name, std::string value)
1199 JMutexAutoLock lock(m_mutex);
1201 m_settings[name] = value;
1204 void setDefault(std::string name, std::string value)
1206 JMutexAutoLock lock(m_mutex);
1208 m_defaults[name] = value;
1211 bool exists(std::string name)
1213 JMutexAutoLock lock(m_mutex);
1215 return (m_settings.find(name) || m_defaults.find(name));
1218 std::string get(std::string name)
1220 JMutexAutoLock lock(m_mutex);
1222 core::map<std::string, std::string>::Node *n;
1223 n = m_settings.find(name);
1226 n = m_defaults.find(name);
1229 dstream<<"INFO: Settings: Setting not found: \""
1230 <<name<<"\""<<std::endl;
1231 throw SettingNotFoundException("Setting not found");
1235 return n->getValue();
1238 bool getBool(std::string name)
1240 return is_yes(get(name));
1243 bool getFlag(std::string name)
1247 return getBool(name);
1249 catch(SettingNotFoundException &e)
1256 bool getBoolAsk(std::string name, std::string question, bool def)
1258 // If it is in settings
1260 return getBool(name);
1264 std::cout<<question<<" [y/N]: ";
1265 std::cin.getline(templine, 10);
1274 float getFloat(std::string name)
1276 return stof(get(name));
1279 u16 getU16(std::string name)
1281 return stoi(get(name), 0, 65535);
1284 u16 getU16Ask(std::string name, std::string question, u16 def)
1286 // If it is in settings
1288 return getU16(name);
1292 std::cout<<question<<" ["<<def<<"]: ";
1293 std::cin.getline(templine, 10);
1299 return stoi(s, 0, 65535);
1302 s16 getS16(std::string name)
1304 return stoi(get(name), -32768, 32767);
1307 s32 getS32(std::string name)
1309 return stoi(get(name));
1312 v3f getV3F(std::string name)
1315 Strfnd f(get(name));
1317 value.X = stof(f.next(","));
1318 value.Y = stof(f.next(","));
1319 value.Z = stof(f.next(")"));
1323 u64 getU64(std::string name)
1326 std::string s = get(name);
1327 std::istringstream ss(s);
1332 void setBool(std::string name, bool value)
1340 void setS32(std::string name, s32 value)
1342 set(name, itos(value));
1345 void setFloat(std::string name, float value)
1347 set(name, ftos(value));
1350 void setV3F(std::string name, v3f value)
1352 std::ostringstream os;
1353 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1354 set(name, os.str());
1357 void setU64(std::string name, u64 value)
1359 std::ostringstream os;
1361 set(name, os.str());
1366 JMutexAutoLock lock(m_mutex);
1372 Settings & operator+=(Settings &other)
1374 JMutexAutoLock lock(m_mutex);
1375 JMutexAutoLock lock2(other.m_mutex);
1380 for(core::map<std::string, std::string>::Iterator
1381 i = other.m_settings.getIterator();
1382 i.atEnd() == false; i++)
1384 m_settings.insert(i.getNode()->getKey(),
1385 i.getNode()->getValue());
1388 for(core::map<std::string, std::string>::Iterator
1389 i = other.m_defaults.getIterator();
1390 i.atEnd() == false; i++)
1392 m_defaults.insert(i.getNode()->getKey(),
1393 i.getNode()->getValue());
1398 Settings & operator=(Settings &other)
1400 JMutexAutoLock lock(m_mutex);
1401 JMutexAutoLock lock2(other.m_mutex);
1413 core::map<std::string, std::string> m_settings;
1414 core::map<std::string, std::string> m_defaults;
1415 // All methods that access m_settings/m_defaults directly should lock this.
1420 FIFO queue (well, actually a FILO also)
1422 template<typename T>
1428 m_list.push_back(t);
1433 if(m_list.size() == 0)
1434 throw ItemNotFoundException("Queue: queue is empty");
1436 typename core::list<T>::Iterator begin = m_list.begin();
1438 m_list.erase(begin);
1443 if(m_list.size() == 0)
1444 throw ItemNotFoundException("Queue: queue is empty");
1446 typename core::list<T>::Iterator last = m_list.getLast();
1454 return m_list.size();
1458 core::list<T> m_list;
1462 Thread-safe FIFO queue (well, actually a FILO also)
1465 template<typename T>
1475 JMutexAutoLock lock(m_mutex);
1476 return m_list.size();
1480 JMutexAutoLock lock(m_mutex);
1481 m_list.push_back(t);
1483 T pop_front(u32 wait_time_max_ms=0)
1485 u32 wait_time_ms = 0;
1490 JMutexAutoLock lock(m_mutex);
1492 if(m_list.size() > 0)
1494 typename core::list<T>::Iterator begin = m_list.begin();
1496 m_list.erase(begin);
1500 if(wait_time_ms >= wait_time_max_ms)
1501 throw ItemNotFoundException("MutexedQueue: queue is empty");
1504 // Wait a while before trying again
1509 T pop_back(u32 wait_time_max_ms=0)
1511 u32 wait_time_ms = 0;
1516 JMutexAutoLock lock(m_mutex);
1518 if(m_list.size() > 0)
1520 typename core::list<T>::Iterator last = m_list.getLast();
1526 if(wait_time_ms >= wait_time_max_ms)
1527 throw ItemNotFoundException("MutexedQueue: queue is empty");
1530 // Wait a while before trying again
1541 core::list<T> & getList()
1548 core::list<T> m_list;
1552 A single worker thread - multiple client threads queue framework.
1555 template<typename Caller, typename Data>
1563 template<typename Key, typename T, typename Caller, typename CallerData>
1569 core::list<CallerInfo<Caller, CallerData> > callers;
1572 template<typename Key, typename T, typename Caller, typename CallerData>
1573 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1577 template<typename Key, typename T, typename Caller, typename CallerData>
1585 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1589 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1600 ResultQueue<Key, T, Caller, CallerData> *dest;
1601 core::list<CallerInfo<Caller, CallerData> > callers;
1604 template<typename Key, typename T, typename Caller, typename CallerData>
1610 return m_queue.size();
1613 void add(Key key, Caller caller, CallerData callerdata,
1614 ResultQueue<Key, T, Caller, CallerData> *dest)
1616 JMutexAutoLock lock(m_queue.getMutex());
1619 If the caller is already on the list, only update CallerData
1621 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1622 i = m_queue.getList().begin();
1623 i != m_queue.getList().end(); i++)
1625 GetRequest<Key, T, Caller, CallerData> &request = *i;
1627 if(request.key == key)
1629 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1630 i = request.callers.begin();
1631 i != request.callers.end(); i++)
1633 CallerInfo<Caller, CallerData> &ca = *i;
1634 if(ca.caller == caller)
1636 ca.data = callerdata;
1640 CallerInfo<Caller, CallerData> ca;
1642 ca.data = callerdata;
1643 request.callers.push_back(ca);
1649 Else add a new request to the queue
1652 GetRequest<Key, T, Caller, CallerData> request;
1654 CallerInfo<Caller, CallerData> ca;
1656 ca.data = callerdata;
1657 request.callers.push_back(ca);
1658 request.dest = dest;
1660 m_queue.getList().push_back(request);
1663 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1665 return m_queue.pop_front(wait_if_empty);
1669 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1673 Pseudo-random (VC++ rand() sucks)
1676 void mysrand(unsigned seed);
1677 #define MYRAND_MAX 32767
1679 inline int myrand_range(int min, int max)
1686 return (myrand()%(max-min+1))+min;
1690 Miscellaneous functions
1693 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1694 f32 *distance_ptr=NULL);
1697 Queue with unique values with fast checking of value existence
1700 template<typename Value>
1706 Does nothing if value is already queued.
1709 false: value already exists
1711 bool push_back(Value value)
1713 // Check if already exists
1714 if(m_map.find(value) != NULL)
1718 m_map.insert(value, 0);
1719 m_list.push_back(value);
1726 typename core::list<Value>::Iterator i = m_list.begin();
1728 m_map.remove(value);
1735 assert(m_list.size() == m_map.size());
1736 return m_list.size();
1740 core::map<Value, u8> m_map;
1741 core::list<Value> m_list;
1745 template<typename Key, typename Value>
1752 assert(m_mutex.IsInitialized());
1755 void set(const Key &name, const Value &value)
1757 JMutexAutoLock lock(m_mutex);
1759 m_values[name] = value;
1762 bool get(const Key &name, Value *result)
1764 JMutexAutoLock lock(m_mutex);
1766 typename core::map<Key, Value>::Node *n;
1767 n = m_values.find(name);
1772 *result = n->getValue();
1777 core::map<Key, Value> m_values;
1783 Generates ids for comparable values.
1784 Id=0 is reserved for "no value".
1787 - Returning value by id (very fast)
1788 - Returning id by value
1789 - Generating a new id for a value
1792 - Remove an id/value pair (is possible to implement but slow)
1794 template<typename T>
1795 class MutexedIdGenerator
1798 MutexedIdGenerator()
1801 assert(m_mutex.IsInitialized());
1804 // Returns true if found
1805 bool getValue(u32 id, T &value)
1809 JMutexAutoLock lock(m_mutex);
1810 if(m_id_to_value.size() < id)
1812 value = m_id_to_value[id-1];
1816 // If id exists for value, returns the id.
1817 // Otherwise generates an id for the value.
1818 u32 getId(const T &value)
1820 JMutexAutoLock lock(m_mutex);
1821 typename core::map<T, u32>::Node *n;
1822 n = m_value_to_id.find(value);
1824 return n->getValue();
1825 m_id_to_value.push_back(value);
1826 u32 new_id = m_id_to_value.size();
1827 m_value_to_id.insert(value, new_id);
1833 // Values are stored here at id-1 position (id 1 = [0])
1834 core::array<T> m_id_to_value;
1835 core::map<T, u32> m_value_to_id;
1839 Checks if a string contains only supplied characters
1841 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1843 for(u32 i=0; i<s.size(); i++)
1845 bool confirmed = false;
1846 for(u32 j=0; j<allowed_chars.size(); j++)
1848 if(s[i] == allowed_chars[j])
1854 if(confirmed == false)
1861 Forcefully wraps string into rows using \n
1862 (no word wrap, used for showing paths in gui)
1864 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1867 for(u32 i=0; i<from.size(); i++)
1869 if(i != 0 && i%rowlen == 0)
1879 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1880 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1883 Returns integer position of node in given floating point position
1885 inline v3s16 floatToInt(v3f p, f32 d)
1888 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1889 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1890 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1895 Returns floating point position of node in given integer position
1897 inline v3f intToFloat(v3s16 p, f32 d)
1908 More serialization stuff
1911 // Creates a string with the length as the first two bytes
1912 inline std::string serializeString(const std::string &plain)
1914 assert(plain.size() <= 65535);
1916 writeU16((u8*)&buf[0], plain.size());
1923 /*// Reads a string with the length as the first two bytes
1924 inline std::string deSerializeString(const std::string encoded)
1926 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1927 if(s_size > encoded.length() - 2)
1931 s.append(&encoded.c_str()[2], s_size);
1935 // Reads a string with the length as the first two bytes
1936 inline std::string deSerializeString(std::istream &is)
1940 if(is.gcount() != 2)
1941 throw SerializationError("deSerializeString: size not read");
1942 u16 s_size = readU16((u8*)buf);
1945 Buffer<char> buf2(s_size);
1946 is.read(&buf2[0], s_size);
1949 s.append(&buf2[0], s_size);
1953 // Creates a string with the length as the first four bytes
1954 inline std::string serializeLongString(const std::string &plain)
1957 writeU32((u8*)&buf[0], plain.size());
1964 /*// Reads a string with the length as the first four bytes
1965 inline std::string deSerializeLongString(const std::string encoded)
1967 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1968 if(s_size > encoded.length() - 4)
1972 s.append(&encoded.c_str()[4], s_size);
1976 // Reads a string with the length as the first four bytes
1977 inline std::string deSerializeLongString(std::istream &is)
1981 if(is.gcount() != 4)
1982 throw SerializationError("deSerializeLongString: size not read");
1983 u32 s_size = readU32((u8*)buf);
1986 Buffer<char> buf2(s_size);
1987 is.read(&buf2[0], s_size);
1990 s.append(&buf2[0], s_size);
1996 inline u32 time_to_daynight_ratio(u32 time_of_day)
1998 const s32 daylength = 16;
1999 const s32 nightlength = 6;
2000 const s32 daytimelength = 8;
2002 s32 t = (((time_of_day)%24000)/(24000/d));
2003 if(t < nightlength/2 || t >= d - nightlength/2)
2006 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2012 // Random helper. Usually d=BS
2013 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2015 return core::aabbox3d<f32>(
2016 (float)p.X * d - 0.5*d,
2017 (float)p.Y * d - 0.5*d,
2018 (float)p.Z * d - 0.5*d,
2019 (float)p.X * d + 0.5*d,
2020 (float)p.Y * d + 0.5*d,
2021 (float)p.Z * d + 0.5*d
2025 class IntervalLimiter
2033 dtime: time from last call to this method
2034 wanted_interval: interval wanted
2036 true: action should be skipped
2037 false: action should be done
2039 bool step(float dtime, float wanted_interval)
2041 m_accumulator += dtime;
2042 if(m_accumulator < wanted_interval)
2044 m_accumulator -= wanted_interval;
2048 float m_accumulator;