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
30 #include <jmutexautolock.h>
32 #include "common_irrlicht.h"
35 #include "exceptions.h"
38 extern const v3s16 g_6dirs[6];
40 extern const v3s16 g_26dirs[26];
43 extern const v3s16 g_27dirs[27];
45 inline void writeU64(u8 *data, u64 i)
47 data[0] = ((i>>56)&0xff);
48 data[1] = ((i>>48)&0xff);
49 data[2] = ((i>>40)&0xff);
50 data[3] = ((i>>32)&0xff);
51 data[4] = ((i>>24)&0xff);
52 data[5] = ((i>>16)&0xff);
53 data[6] = ((i>> 8)&0xff);
54 data[7] = ((i>> 0)&0xff);
57 inline void writeU32(u8 *data, u32 i)
59 data[0] = ((i>>24)&0xff);
60 data[1] = ((i>>16)&0xff);
61 data[2] = ((i>> 8)&0xff);
62 data[3] = ((i>> 0)&0xff);
65 inline void writeU16(u8 *data, u16 i)
67 data[0] = ((i>> 8)&0xff);
68 data[1] = ((i>> 0)&0xff);
71 inline void writeU8(u8 *data, u8 i)
73 data[0] = ((i>> 0)&0xff);
76 inline u64 readU64(u8 *data)
78 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
79 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
80 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
81 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
84 inline u32 readU32(u8 *data)
86 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
89 inline u16 readU16(u8 *data)
91 return (data[0]<<8) | (data[1]<<0);
94 inline u8 readU8(u8 *data)
99 inline void writeS32(u8 *data, s32 i){
100 writeU32(data, (u32)i);
102 inline s32 readS32(u8 *data){
103 return (s32)readU32(data);
106 inline void writeF1000(u8 *data, f32 i){
107 writeS32(data, i*1000);
109 inline f32 readF1000(u8 *data){
110 return (f32)readS32(data)/1000.;
113 inline void writeS16(u8 *data, s16 i){
114 writeU16(data, (u16)i);
116 inline s16 readS16(u8 *data){
117 return (s16)readU16(data);
120 inline void writeV3S32(u8 *data, v3s32 p)
122 writeS32(&data[0], p.X);
123 writeS32(&data[4], p.Y);
124 writeS32(&data[8], p.Z);
126 inline v3s32 readV3S32(u8 *data)
129 p.X = readS32(&data[0]);
130 p.Y = readS32(&data[4]);
131 p.Z = readS32(&data[8]);
135 inline void writeV3F1000(u8 *data, v3f p)
137 writeF1000(&data[0], p.X);
138 writeF1000(&data[4], p.Y);
139 writeF1000(&data[8], p.Z);
141 inline v3f readV3F1000(u8 *data)
144 p.X = (float)readF1000(&data[0]);
145 p.Y = (float)readF1000(&data[4]);
146 p.Z = (float)readF1000(&data[8]);
150 inline void writeV2S16(u8 *data, v2s16 p)
152 writeS16(&data[0], p.X);
153 writeS16(&data[2], p.Y);
156 inline v2s16 readV2S16(u8 *data)
159 p.X = readS16(&data[0]);
160 p.Y = readS16(&data[2]);
164 inline void writeV2S32(u8 *data, v2s32 p)
166 writeS32(&data[0], p.X);
167 writeS32(&data[2], p.Y);
170 inline v2s32 readV2S32(u8 *data)
173 p.X = readS32(&data[0]);
174 p.Y = readS32(&data[2]);
178 inline void writeV3S16(u8 *data, v3s16 p)
180 writeS16(&data[0], p.X);
181 writeS16(&data[2], p.Y);
182 writeS16(&data[4], p.Z);
185 inline v3s16 readV3S16(u8 *data)
188 p.X = readS16(&data[0]);
189 p.Y = readS16(&data[2]);
190 p.Z = readS16(&data[4]);
195 The above stuff directly interfaced to iostream
198 inline void writeU8(std::ostream &os, u8 p)
201 writeU8((u8*)buf, p);
204 inline u8 readU8(std::istream &is)
208 return readU8((u8*)buf);
211 inline void writeU16(std::ostream &os, u16 p)
214 writeU16((u8*)buf, p);
217 inline u16 readU16(std::istream &is)
221 return readU16((u8*)buf);
224 inline void writeU32(std::ostream &os, u16 p)
227 writeU16((u8*)buf, p);
230 inline u16 readU32(std::istream &is)
234 return readU32((u8*)buf);
237 inline void writeF1000(std::ostream &os, f32 p)
240 writeF1000((u8*)buf, p);
243 inline f32 readF1000(std::istream &is)
247 // TODO: verify if this gets rid of the valgrind warning
248 //if(is.gcount() != 2)
250 return readF1000((u8*)buf);
253 inline void writeV3F1000(std::ostream &os, v3f p)
256 writeV3F1000((u8*)buf, p);
259 inline v3f readV3F1000(std::istream &is)
263 return readV3F1000((u8*)buf);
267 None of these are used at the moment
270 template <typename T>
280 SharedPtr(SharedPtr<T> &t)
284 refcount = t.refcount;
292 SharedPtr<T> & operator=(T *t)
300 SharedPtr<T> & operator=(SharedPtr<T> &t)
303 refcount = t.refcount;
316 bool operator!=(T *t)
320 bool operator==(T *t)
324 T & operator[](unsigned int i)
331 assert((*refcount) > 0);
344 template <typename T>
348 Buffer(unsigned int size)
353 Buffer(const Buffer &buffer)
355 m_size = buffer.m_size;
356 data = new T[buffer.m_size];
357 memcpy(data, buffer.data, buffer.m_size);
359 Buffer(T *t, unsigned int size)
363 memcpy(data, t, size);
369 T & operator[](unsigned int i) const
373 T * operator*() const
377 unsigned int getSize() const
386 template <typename T>
394 refcount = new unsigned int;
397 SharedBuffer(unsigned int size)
401 data = new T[m_size];
404 refcount = new unsigned int;
407 SharedBuffer(const SharedBuffer &buffer)
409 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
410 m_size = buffer.m_size;
412 refcount = buffer.refcount;
415 SharedBuffer & operator=(const SharedBuffer & buffer)
417 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
421 m_size = buffer.m_size;
423 refcount = buffer.refcount;
430 SharedBuffer(T *t, unsigned int size)
435 data = new T[m_size];
436 memcpy(data, t, m_size);
440 refcount = new unsigned int;
446 SharedBuffer(const Buffer<T> &buffer)
448 m_size = buffer.getSize();
451 data = new T[m_size];
452 memcpy(data, *buffer, buffer.getSize());
456 refcount = new unsigned int;
463 T & operator[](unsigned int i) const
468 T * operator*() const
472 unsigned int getSize() const
479 assert((*refcount) > 0);
490 unsigned int *refcount;
493 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
495 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
500 class MutexedVariable
503 MutexedVariable(T value):
511 JMutexAutoLock lock(m_mutex);
517 JMutexAutoLock lock(m_mutex);
521 // You'll want to grab this in a SharedPtr
522 JMutexAutoLock * getLock()
524 return new JMutexAutoLock(m_mutex);
527 // You pretty surely want to grab the lock when accessing this
541 TimeTaker(const char *name, u32 *result=NULL);
548 u32 stop(bool quiet=false);
559 // Calculates the borders of a "d-radius" cube
560 inline void getFacePositions(core::list<v3s16> &list, u16 d)
564 list.push_back(v3s16(0,0,0));
570 This is an optimized sequence of coordinates.
572 list.push_back(v3s16( 0, 1, 0)); // top
573 list.push_back(v3s16( 0, 0, 1)); // back
574 list.push_back(v3s16(-1, 0, 0)); // left
575 list.push_back(v3s16( 1, 0, 0)); // right
576 list.push_back(v3s16( 0, 0,-1)); // front
577 list.push_back(v3s16( 0,-1, 0)); // bottom
579 list.push_back(v3s16(-1, 0, 1)); // back left
580 list.push_back(v3s16( 1, 0, 1)); // back right
581 list.push_back(v3s16(-1, 0,-1)); // front left
582 list.push_back(v3s16( 1, 0,-1)); // front right
583 list.push_back(v3s16(-1,-1, 0)); // bottom left
584 list.push_back(v3s16( 1,-1, 0)); // bottom right
585 list.push_back(v3s16( 0,-1, 1)); // bottom back
586 list.push_back(v3s16( 0,-1,-1)); // bottom front
587 list.push_back(v3s16(-1, 1, 0)); // top left
588 list.push_back(v3s16( 1, 1, 0)); // top right
589 list.push_back(v3s16( 0, 1, 1)); // top back
590 list.push_back(v3s16( 0, 1,-1)); // top front
592 list.push_back(v3s16(-1, 1, 1)); // top back-left
593 list.push_back(v3s16( 1, 1, 1)); // top back-right
594 list.push_back(v3s16(-1, 1,-1)); // top front-left
595 list.push_back(v3s16( 1, 1,-1)); // top front-right
596 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
597 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
598 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
599 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
604 // Take blocks in all sides, starting from y=0 and going +-y
605 for(s16 y=0; y<=d-1; y++)
607 // Left and right side, including borders
608 for(s16 z=-d; z<=d; z++)
610 list.push_back(v3s16(d,y,z));
611 list.push_back(v3s16(-d,y,z));
614 list.push_back(v3s16(d,-y,z));
615 list.push_back(v3s16(-d,-y,z));
618 // Back and front side, excluding borders
619 for(s16 x=-d+1; x<=d-1; x++)
621 list.push_back(v3s16(x,y,d));
622 list.push_back(v3s16(x,y,-d));
625 list.push_back(v3s16(x,-y,d));
626 list.push_back(v3s16(x,-y,-d));
631 // Take the bottom and top face with borders
632 // -d<x<d, y=+-d, -d<z<d
633 for(s16 x=-d; x<=d; x++)
634 for(s16 z=-d; z<=d; z++)
636 list.push_back(v3s16(x,-d,z));
637 list.push_back(v3s16(x,d,z));
641 class IndentationRaiser
644 IndentationRaiser(u16 *indentation)
646 m_indentation = indentation;
657 inline s16 getContainerPos(s16 p, s16 d)
659 return (p>=0 ? p : p-d+1) / d;
662 inline v2s16 getContainerPos(v2s16 p, s16 d)
665 getContainerPos(p.X, d),
666 getContainerPos(p.Y, d)
670 inline v3s16 getContainerPos(v3s16 p, s16 d)
673 getContainerPos(p.X, d),
674 getContainerPos(p.Y, d),
675 getContainerPos(p.Z, d)
679 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
682 getContainerPos(p.X, d.X),
683 getContainerPos(p.Y, d.Y)
687 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
690 getContainerPos(p.X, d.X),
691 getContainerPos(p.Y, d.Y),
692 getContainerPos(p.Z, d.Z)
696 inline bool isInArea(v3s16 p, s16 d)
699 p.X >= 0 && p.X < d &&
700 p.Y >= 0 && p.Y < d &&
705 inline bool isInArea(v2s16 p, s16 d)
708 p.X >= 0 && p.X < d &&
713 inline bool isInArea(v3s16 p, v3s16 d)
716 p.X >= 0 && p.X < d.X &&
717 p.Y >= 0 && p.Y < d.Y &&
718 p.Z >= 0 && p.Z < d.Z
722 inline s16 rangelim(s16 i, s16 max)
731 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
733 inline v3s16 arealim(v3s16 p, s16 d)
750 inline std::wstring narrow_to_wide(const std::string& mbs)
752 size_t wcl = mbs.size();
753 Buffer<wchar_t> wcs(wcl+1);
754 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
755 if(l == (size_t)(-1))
756 return L"<invalid multibyte string>";
761 inline std::string wide_to_narrow(const std::wstring& wcs)
763 size_t mbl = wcs.size()*4;
764 SharedBuffer<char> mbs(mbl+1);
765 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
766 if(l == (size_t)(-1))
773 // Split a string using the given delimiter. Returns a vector containing
774 // the component parts.
775 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
777 std::vector<std::wstring> parts;
778 std::wstringstream sstr(str);
780 while(std::getline(sstr, part, delimiter))
781 parts.push_back(part);
787 See test.cpp for example cases.
788 wraps degrees to the range of -360...360
789 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
791 inline float wrapDegrees(float f)
793 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
799 // NOTE: This would be used for wrapping to 0...360
805 // 10, 0.5, -0.5, -0.5
810 inline std::string lowercase(const std::string &s)
813 for(size_t i=0; i<s.size(); i++)
816 if(c >= 'A' && c <= 'Z')
823 inline bool is_yes(const std::string &s)
825 std::string s2 = lowercase(trim(s));
826 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
831 inline s32 stoi(const std::string &s, s32 min, s32 max)
833 s32 i = atoi(s.c_str());
842 // MSVC2010 includes it's own versions of these
843 #if !defined(_MSC_VER) || _MSC_VER < 1600
845 inline s32 stoi(std::string s)
847 return atoi(s.c_str());
850 inline s32 stoi(std::wstring s)
852 return atoi(wide_to_narrow(s).c_str());
855 inline float stof(std::string s)
858 std::istringstream ss(s);
865 inline std::string itos(s32 i)
867 std::ostringstream o;
872 inline std::string ftos(float f)
874 std::ostringstream o;
879 inline void str_replace(std::string & str, std::string const & pattern,
880 std::string const & replacement)
882 std::string::size_type start = str.find(pattern, 0);
883 while(start != str.npos)
885 str.replace(start, pattern.size(), replacement);
886 start = str.find(pattern, start+replacement.size());
890 inline void str_replace_char(std::string & str, char from, char to)
892 for(unsigned int i=0; i<str.size(); i++)
900 A base class for simple background thread implementation
903 class SimpleThread : public JThread
917 virtual ~SimpleThread()
920 virtual void * Thread() = 0;
924 JMutexAutoLock lock(run_mutex);
927 void setRun(bool a_run)
929 JMutexAutoLock lock(run_mutex);
948 VALUETYPE_FLAG // Doesn't take any arguments
953 ValueSpec(ValueType a_type, const char *a_help=NULL)
970 void writeLines(std::ostream &os)
972 JMutexAutoLock lock(m_mutex);
974 for(core::map<std::string, std::string>::Iterator
975 i = m_settings.getIterator();
976 i.atEnd() == false; i++)
978 std::string name = i.getNode()->getKey();
979 std::string value = i.getNode()->getValue();
980 os<<name<<" = "<<value<<"\n";
984 bool parseConfigLine(const std::string &line)
986 JMutexAutoLock lock(m_mutex);
988 std::string trimmedline = trim(line);
991 if(trimmedline[0] == '#')
994 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
996 Strfnd sf(trim(line));
998 std::string name = sf.next("=");
1004 std::string value = sf.next("\n");
1005 value = trim(value);
1007 /*dstream<<"Config name=\""<<name<<"\" value=\""
1008 <<value<<"\""<<std::endl;*/
1010 m_settings[name] = value;
1015 // Returns false on EOF
1016 bool parseConfigObject(std::istream &is)
1022 NOTE: This function might be expanded to allow multi-line
1026 std::getline(is, line);
1027 //dstream<<"got line: \""<<line<<"\""<<std::endl;
1029 return parseConfigLine(line);
1033 Read configuration file
1035 Returns true on success
1037 bool readConfigFile(const char *filename)
1039 std::ifstream is(filename);
1040 if(is.good() == false)
1042 dstream<<"Error opening configuration file \""
1043 <<filename<<"\""<<std::endl;
1047 dstream<<"Parsing configuration file: \""
1048 <<filename<<"\""<<std::endl;
1050 while(parseConfigObject(is));
1056 Reads a configuration object from stream (usually a single line)
1059 Preserves comments and empty lines.
1061 Settings that were added to dst are also added to updated.
1062 key of updated is setting name, value of updated is dummy.
1064 Returns false on EOF
1066 bool getUpdatedConfigObject(std::istream &is,
1067 core::list<std::string> &dst,
1068 core::map<std::string, bool> &updated)
1070 JMutexAutoLock lock(m_mutex);
1075 // NOTE: This function will be expanded to allow multi-line settings
1077 std::getline(is, line);
1079 std::string trimmedline = trim(line);
1081 std::string line_end = "";
1082 if(is.eof() == false)
1086 if(trimmedline[0] == '#')
1088 dst.push_back(line+line_end);
1092 Strfnd sf(trim(line));
1094 std::string name = sf.next("=");
1099 dst.push_back(line+line_end);
1103 std::string value = sf.next("\n");
1104 value = trim(value);
1106 if(m_settings.find(name))
1108 std::string newvalue = m_settings[name];
1110 if(newvalue != value)
1112 dstream<<"Changing value of \""<<name<<"\" = \""
1113 <<value<<"\" -> \""<<newvalue<<"\""
1117 dst.push_back(name + " = " + newvalue + line_end);
1119 updated[name] = true;
1126 Updates configuration file
1128 Returns true on success
1130 bool updateConfigFile(const char *filename)
1132 dstream<<"Updating configuration file: \""
1133 <<filename<<"\""<<std::endl;
1135 core::list<std::string> objects;
1136 core::map<std::string, bool> updated;
1138 // Read and modify stuff
1140 std::ifstream is(filename);
1141 if(is.good() == false)
1143 dstream<<"INFO: updateConfigFile():"
1144 " Error opening configuration file"
1146 <<filename<<"\""<<std::endl;
1150 while(getUpdatedConfigObject(is, objects, updated));
1154 JMutexAutoLock lock(m_mutex);
1158 std::ofstream os(filename);
1159 if(os.good() == false)
1161 dstream<<"Error opening configuration file"
1163 <<filename<<"\""<<std::endl;
1170 for(core::list<std::string>::Iterator
1171 i = objects.begin();
1172 i != objects.end(); i++)
1178 Write stuff that was not already in the file
1180 for(core::map<std::string, std::string>::Iterator
1181 i = m_settings.getIterator();
1182 i.atEnd() == false; i++)
1184 if(updated.find(i.getNode()->getKey()))
1186 std::string name = i.getNode()->getKey();
1187 std::string value = i.getNode()->getValue();
1188 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1190 os<<name<<" = "<<value<<"\n";
1198 NOTE: Types of allowed_options are ignored
1200 returns true on success
1202 bool parseCommandLine(int argc, char *argv[],
1203 core::map<std::string, ValueSpec> &allowed_options)
1210 std::string argname = argv[i];
1211 if(argname.substr(0, 2) != "--")
1213 dstream<<"Invalid command-line parameter \""
1214 <<argname<<"\": --<option> expected."<<std::endl;
1219 std::string name = argname.substr(2);
1221 core::map<std::string, ValueSpec>::Node *n;
1222 n = allowed_options.find(name);
1225 dstream<<"Unknown command-line parameter \""
1226 <<argname<<"\""<<std::endl;
1230 ValueType type = n->getValue().type;
1232 std::string value = "";
1234 if(type == VALUETYPE_FLAG)
1242 dstream<<"Invalid command-line parameter \""
1243 <<name<<"\": missing value"<<std::endl;
1251 dstream<<"Valid command-line parameter: \""
1252 <<name<<"\" = \""<<value<<"\""
1260 void set(std::string name, std::string value)
1262 JMutexAutoLock lock(m_mutex);
1264 m_settings[name] = value;
1267 void setDefault(std::string name, std::string value)
1269 JMutexAutoLock lock(m_mutex);
1271 m_defaults[name] = value;
1274 bool exists(std::string name)
1276 JMutexAutoLock lock(m_mutex);
1278 return (m_settings.find(name) || m_defaults.find(name));
1281 std::string get(std::string name)
1283 JMutexAutoLock lock(m_mutex);
1285 core::map<std::string, std::string>::Node *n;
1286 n = m_settings.find(name);
1289 n = m_defaults.find(name);
1292 dstream<<"INFO: Settings: Setting not found: \""
1293 <<name<<"\""<<std::endl;
1294 throw SettingNotFoundException("Setting not found");
1298 return n->getValue();
1301 bool getBool(std::string name)
1303 return is_yes(get(name));
1306 bool getFlag(std::string name)
1310 return getBool(name);
1312 catch(SettingNotFoundException &e)
1319 bool getBoolAsk(std::string name, std::string question, bool def)
1321 // If it is in settings
1323 return getBool(name);
1327 std::cout<<question<<" [y/N]: ";
1328 std::cin.getline(templine, 10);
1337 float getFloat(std::string name)
1339 return stof(get(name));
1342 u16 getU16(std::string name)
1344 return stoi(get(name), 0, 65535);
1347 u16 getU16Ask(std::string name, std::string question, u16 def)
1349 // If it is in settings
1351 return getU16(name);
1355 std::cout<<question<<" ["<<def<<"]: ";
1356 std::cin.getline(templine, 10);
1362 return stoi(s, 0, 65535);
1365 s16 getS16(std::string name)
1367 return stoi(get(name), -32768, 32767);
1370 s32 getS32(std::string name)
1372 return stoi(get(name));
1375 v3f getV3F(std::string name)
1378 Strfnd f(get(name));
1380 value.X = stof(f.next(","));
1381 value.Y = stof(f.next(","));
1382 value.Z = stof(f.next(")"));
1386 u64 getU64(std::string name)
1389 std::string s = get(name);
1390 std::istringstream ss(s);
1395 void setBool(std::string name, bool value)
1403 void setS32(std::string name, s32 value)
1405 set(name, itos(value));
1408 void setFloat(std::string name, float value)
1410 set(name, ftos(value));
1413 void setV3F(std::string name, v3f value)
1415 std::ostringstream os;
1416 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1417 set(name, os.str());
1420 void setU64(std::string name, u64 value)
1422 std::ostringstream os;
1424 set(name, os.str());
1429 JMutexAutoLock lock(m_mutex);
1435 Settings & operator+=(Settings &other)
1437 JMutexAutoLock lock(m_mutex);
1438 JMutexAutoLock lock2(other.m_mutex);
1443 for(core::map<std::string, std::string>::Iterator
1444 i = other.m_settings.getIterator();
1445 i.atEnd() == false; i++)
1447 m_settings.insert(i.getNode()->getKey(),
1448 i.getNode()->getValue());
1451 for(core::map<std::string, std::string>::Iterator
1452 i = other.m_defaults.getIterator();
1453 i.atEnd() == false; i++)
1455 m_defaults.insert(i.getNode()->getKey(),
1456 i.getNode()->getValue());
1461 Settings & operator=(Settings &other)
1463 JMutexAutoLock lock(m_mutex);
1464 JMutexAutoLock lock2(other.m_mutex);
1476 core::map<std::string, std::string> m_settings;
1477 core::map<std::string, std::string> m_defaults;
1478 // All methods that access m_settings/m_defaults directly should lock this.
1483 FIFO queue (well, actually a FILO also)
1485 template<typename T>
1491 m_list.push_back(t);
1496 if(m_list.size() == 0)
1497 throw ItemNotFoundException("Queue: queue is empty");
1499 typename core::list<T>::Iterator begin = m_list.begin();
1501 m_list.erase(begin);
1506 if(m_list.size() == 0)
1507 throw ItemNotFoundException("Queue: queue is empty");
1509 typename core::list<T>::Iterator last = m_list.getLast();
1517 return m_list.size();
1521 core::list<T> m_list;
1525 Thread-safe FIFO queue (well, actually a FILO also)
1528 template<typename T>
1538 JMutexAutoLock lock(m_mutex);
1539 return m_list.size();
1543 JMutexAutoLock lock(m_mutex);
1544 m_list.push_back(t);
1546 T pop_front(u32 wait_time_max_ms=0)
1548 u32 wait_time_ms = 0;
1553 JMutexAutoLock lock(m_mutex);
1555 if(m_list.size() > 0)
1557 typename core::list<T>::Iterator begin = m_list.begin();
1559 m_list.erase(begin);
1563 if(wait_time_ms >= wait_time_max_ms)
1564 throw ItemNotFoundException("MutexedQueue: queue is empty");
1567 // Wait a while before trying again
1572 T pop_back(u32 wait_time_max_ms=0)
1574 u32 wait_time_ms = 0;
1579 JMutexAutoLock lock(m_mutex);
1581 if(m_list.size() > 0)
1583 typename core::list<T>::Iterator last = m_list.getLast();
1589 if(wait_time_ms >= wait_time_max_ms)
1590 throw ItemNotFoundException("MutexedQueue: queue is empty");
1593 // Wait a while before trying again
1604 core::list<T> & getList()
1611 core::list<T> m_list;
1615 A single worker thread - multiple client threads queue framework.
1618 template<typename Caller, typename Data>
1626 template<typename Key, typename T, typename Caller, typename CallerData>
1632 core::list<CallerInfo<Caller, CallerData> > callers;
1635 template<typename Key, typename T, typename Caller, typename CallerData>
1636 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1640 template<typename Key, typename T, typename Caller, typename CallerData>
1648 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1652 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1663 ResultQueue<Key, T, Caller, CallerData> *dest;
1664 core::list<CallerInfo<Caller, CallerData> > callers;
1667 template<typename Key, typename T, typename Caller, typename CallerData>
1673 return m_queue.size();
1676 void add(Key key, Caller caller, CallerData callerdata,
1677 ResultQueue<Key, T, Caller, CallerData> *dest)
1679 JMutexAutoLock lock(m_queue.getMutex());
1682 If the caller is already on the list, only update CallerData
1684 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1685 i = m_queue.getList().begin();
1686 i != m_queue.getList().end(); i++)
1688 GetRequest<Key, T, Caller, CallerData> &request = *i;
1690 if(request.key == key)
1692 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1693 i = request.callers.begin();
1694 i != request.callers.end(); i++)
1696 CallerInfo<Caller, CallerData> &ca = *i;
1697 if(ca.caller == caller)
1699 ca.data = callerdata;
1703 CallerInfo<Caller, CallerData> ca;
1705 ca.data = callerdata;
1706 request.callers.push_back(ca);
1712 Else add a new request to the queue
1715 GetRequest<Key, T, Caller, CallerData> request;
1717 CallerInfo<Caller, CallerData> ca;
1719 ca.data = callerdata;
1720 request.callers.push_back(ca);
1721 request.dest = dest;
1723 m_queue.getList().push_back(request);
1726 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1728 return m_queue.pop_front(wait_if_empty);
1732 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1736 Pseudo-random (VC++ rand() sucks)
1739 void mysrand(unsigned seed);
1740 #define MYRAND_MAX 32767
1742 inline int myrand_range(int min, int max)
1744 if(max-min > MYRAND_MAX)
1746 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1754 return (myrand()%(max-min+1))+min;
1758 Miscellaneous functions
1761 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1762 f32 *distance_ptr=NULL);
1765 Queue with unique values with fast checking of value existence
1768 template<typename Value>
1774 Does nothing if value is already queued.
1777 false: value already exists
1779 bool push_back(Value value)
1781 // Check if already exists
1782 if(m_map.find(value) != NULL)
1786 m_map.insert(value, 0);
1787 m_list.push_back(value);
1794 typename core::list<Value>::Iterator i = m_list.begin();
1796 m_map.remove(value);
1803 assert(m_list.size() == m_map.size());
1804 return m_list.size();
1808 core::map<Value, u8> m_map;
1809 core::list<Value> m_list;
1813 template<typename Key, typename Value>
1820 assert(m_mutex.IsInitialized());
1823 void set(const Key &name, const Value &value)
1825 JMutexAutoLock lock(m_mutex);
1827 m_values[name] = value;
1830 bool get(const Key &name, Value *result)
1832 JMutexAutoLock lock(m_mutex);
1834 typename core::map<Key, Value>::Node *n;
1835 n = m_values.find(name);
1841 *result = n->getValue();
1847 core::map<Key, Value> m_values;
1853 Generates ids for comparable values.
1854 Id=0 is reserved for "no value".
1857 - Returning value by id (very fast)
1858 - Returning id by value
1859 - Generating a new id for a value
1862 - Remove an id/value pair (is possible to implement but slow)
1864 template<typename T>
1865 class MutexedIdGenerator
1868 MutexedIdGenerator()
1871 assert(m_mutex.IsInitialized());
1874 // Returns true if found
1875 bool getValue(u32 id, T &value)
1879 JMutexAutoLock lock(m_mutex);
1880 if(m_id_to_value.size() < id)
1882 value = m_id_to_value[id-1];
1886 // If id exists for value, returns the id.
1887 // Otherwise generates an id for the value.
1888 u32 getId(const T &value)
1890 JMutexAutoLock lock(m_mutex);
1891 typename core::map<T, u32>::Node *n;
1892 n = m_value_to_id.find(value);
1894 return n->getValue();
1895 m_id_to_value.push_back(value);
1896 u32 new_id = m_id_to_value.size();
1897 m_value_to_id.insert(value, new_id);
1903 // Values are stored here at id-1 position (id 1 = [0])
1904 core::array<T> m_id_to_value;
1905 core::map<T, u32> m_value_to_id;
1909 Checks if a string contains only supplied characters
1911 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1913 for(u32 i=0; i<s.size(); i++)
1915 bool confirmed = false;
1916 for(u32 j=0; j<allowed_chars.size(); j++)
1918 if(s[i] == allowed_chars[j])
1924 if(confirmed == false)
1931 Forcefully wraps string into rows using \n
1932 (no word wrap, used for showing paths in gui)
1934 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1937 for(u32 i=0; i<from.size(); i++)
1939 if(i != 0 && i%rowlen == 0)
1949 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1950 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1953 Returns integer position of node in given floating point position
1955 inline v3s16 floatToInt(v3f p, f32 d)
1958 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1959 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1960 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1965 Returns floating point position of node in given integer position
1967 inline v3f intToFloat(v3s16 p, f32 d)
1978 More serialization stuff
1981 // Creates a string with the length as the first two bytes
1982 inline std::string serializeString(const std::string &plain)
1984 //assert(plain.size() <= 65535);
1985 if(plain.size() > 65535)
1986 throw SerializationError("String too long for serializeString");
1988 writeU16((u8*)&buf[0], plain.size());
1995 // Creates a string with the length as the first two bytes from wide string
1996 inline std::string serializeWideString(const std::wstring &plain)
1998 //assert(plain.size() <= 65535);
1999 if(plain.size() > 65535)
2000 throw SerializationError("String too long for serializeString");
2002 writeU16((u8*)buf, plain.size());
2005 for(u32 i=0; i<plain.size(); i++)
2007 writeU16((u8*)buf, plain[i]);
2013 // Reads a string with the length as the first two bytes
2014 inline std::string deSerializeString(std::istream &is)
2018 if(is.gcount() != 2)
2019 throw SerializationError("deSerializeString: size not read");
2020 u16 s_size = readU16((u8*)buf);
2023 Buffer<char> buf2(s_size);
2024 is.read(&buf2[0], s_size);
2027 s.append(&buf2[0], s_size);
2031 // Reads a wide string with the length as the first two bytes
2032 inline std::wstring deSerializeWideString(std::istream &is)
2036 if(is.gcount() != 2)
2037 throw SerializationError("deSerializeString: size not read");
2038 u16 s_size = readU16((u8*)buf);
2043 for(u32 i=0; i<s_size; i++)
2045 is.read(&buf[0], 2);
2046 wchar_t c16 = readU16((u8*)buf);
2052 // Creates a string with the length as the first four bytes
2053 inline std::string serializeLongString(const std::string &plain)
2056 writeU32((u8*)&buf[0], plain.size());
2063 // Reads a string with the length as the first four bytes
2064 inline std::string deSerializeLongString(std::istream &is)
2068 if(is.gcount() != 4)
2069 throw SerializationError("deSerializeLongString: size not read");
2070 u32 s_size = readU32((u8*)buf);
2073 Buffer<char> buf2(s_size);
2074 is.read(&buf2[0], s_size);
2077 s.append(&buf2[0], s_size);
2083 inline u32 time_to_daynight_ratio(u32 time_of_day)
2085 const s32 daylength = 16;
2086 const s32 nightlength = 6;
2087 const s32 daytimelength = 8;
2089 s32 t = (((time_of_day)%24000)/(24000/d));
2090 if(t < nightlength/2 || t >= d - nightlength/2)
2093 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2099 // Random helper. Usually d=BS
2100 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2102 return core::aabbox3d<f32>(
2103 (float)p.X * d - 0.5*d,
2104 (float)p.Y * d - 0.5*d,
2105 (float)p.Z * d - 0.5*d,
2106 (float)p.X * d + 0.5*d,
2107 (float)p.Y * d + 0.5*d,
2108 (float)p.Z * d + 0.5*d
2112 class IntervalLimiter
2120 dtime: time from last call to this method
2121 wanted_interval: interval wanted
2123 true: action should be skipped
2124 false: action should be done
2126 bool step(float dtime, float wanted_interval)
2128 m_accumulator += dtime;
2129 if(m_accumulator < wanted_interval)
2131 m_accumulator -= wanted_interval;
2135 float m_accumulator;
2138 std::string translatePassword(std::string playername, std::wstring password);