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());
1463 Settings & operator=(Settings &other)
1465 JMutexAutoLock lock(m_mutex);
1466 JMutexAutoLock lock2(other.m_mutex);
1478 core::map<std::string, std::string> m_settings;
1479 core::map<std::string, std::string> m_defaults;
1480 // All methods that access m_settings/m_defaults directly should lock this.
1485 FIFO queue (well, actually a FILO also)
1487 template<typename T>
1493 m_list.push_back(t);
1498 if(m_list.size() == 0)
1499 throw ItemNotFoundException("Queue: queue is empty");
1501 typename core::list<T>::Iterator begin = m_list.begin();
1503 m_list.erase(begin);
1508 if(m_list.size() == 0)
1509 throw ItemNotFoundException("Queue: queue is empty");
1511 typename core::list<T>::Iterator last = m_list.getLast();
1519 return m_list.size();
1523 core::list<T> m_list;
1527 Thread-safe FIFO queue (well, actually a FILO also)
1530 template<typename T>
1540 JMutexAutoLock lock(m_mutex);
1541 return m_list.size();
1545 JMutexAutoLock lock(m_mutex);
1546 m_list.push_back(t);
1548 T pop_front(u32 wait_time_max_ms=0)
1550 u32 wait_time_ms = 0;
1555 JMutexAutoLock lock(m_mutex);
1557 if(m_list.size() > 0)
1559 typename core::list<T>::Iterator begin = m_list.begin();
1561 m_list.erase(begin);
1565 if(wait_time_ms >= wait_time_max_ms)
1566 throw ItemNotFoundException("MutexedQueue: queue is empty");
1569 // Wait a while before trying again
1574 T pop_back(u32 wait_time_max_ms=0)
1576 u32 wait_time_ms = 0;
1581 JMutexAutoLock lock(m_mutex);
1583 if(m_list.size() > 0)
1585 typename core::list<T>::Iterator last = m_list.getLast();
1591 if(wait_time_ms >= wait_time_max_ms)
1592 throw ItemNotFoundException("MutexedQueue: queue is empty");
1595 // Wait a while before trying again
1606 core::list<T> & getList()
1613 core::list<T> m_list;
1617 A single worker thread - multiple client threads queue framework.
1620 template<typename Caller, typename Data>
1628 template<typename Key, typename T, typename Caller, typename CallerData>
1634 core::list<CallerInfo<Caller, CallerData> > callers;
1637 template<typename Key, typename T, typename Caller, typename CallerData>
1638 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1642 template<typename Key, typename T, typename Caller, typename CallerData>
1650 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1654 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1665 ResultQueue<Key, T, Caller, CallerData> *dest;
1666 core::list<CallerInfo<Caller, CallerData> > callers;
1669 template<typename Key, typename T, typename Caller, typename CallerData>
1675 return m_queue.size();
1678 void add(Key key, Caller caller, CallerData callerdata,
1679 ResultQueue<Key, T, Caller, CallerData> *dest)
1681 JMutexAutoLock lock(m_queue.getMutex());
1684 If the caller is already on the list, only update CallerData
1686 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1687 i = m_queue.getList().begin();
1688 i != m_queue.getList().end(); i++)
1690 GetRequest<Key, T, Caller, CallerData> &request = *i;
1692 if(request.key == key)
1694 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1695 i = request.callers.begin();
1696 i != request.callers.end(); i++)
1698 CallerInfo<Caller, CallerData> &ca = *i;
1699 if(ca.caller == caller)
1701 ca.data = callerdata;
1705 CallerInfo<Caller, CallerData> ca;
1707 ca.data = callerdata;
1708 request.callers.push_back(ca);
1714 Else add a new request to the queue
1717 GetRequest<Key, T, Caller, CallerData> request;
1719 CallerInfo<Caller, CallerData> ca;
1721 ca.data = callerdata;
1722 request.callers.push_back(ca);
1723 request.dest = dest;
1725 m_queue.getList().push_back(request);
1728 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1730 return m_queue.pop_front(wait_if_empty);
1734 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1738 Pseudo-random (VC++ rand() sucks)
1741 void mysrand(unsigned seed);
1742 #define MYRAND_MAX 32767
1744 inline int myrand_range(int min, int max)
1746 if(max-min > MYRAND_MAX)
1748 dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
1756 return (myrand()%(max-min+1))+min;
1760 Miscellaneous functions
1763 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1764 f32 *distance_ptr=NULL);
1767 Queue with unique values with fast checking of value existence
1770 template<typename Value>
1776 Does nothing if value is already queued.
1779 false: value already exists
1781 bool push_back(Value value)
1783 // Check if already exists
1784 if(m_map.find(value) != NULL)
1788 m_map.insert(value, 0);
1789 m_list.push_back(value);
1796 typename core::list<Value>::Iterator i = m_list.begin();
1798 m_map.remove(value);
1805 assert(m_list.size() == m_map.size());
1806 return m_list.size();
1810 core::map<Value, u8> m_map;
1811 core::list<Value> m_list;
1815 template<typename Key, typename Value>
1822 assert(m_mutex.IsInitialized());
1825 void set(const Key &name, const Value &value)
1827 JMutexAutoLock lock(m_mutex);
1829 m_values[name] = value;
1832 bool get(const Key &name, Value *result)
1834 JMutexAutoLock lock(m_mutex);
1836 typename core::map<Key, Value>::Node *n;
1837 n = m_values.find(name);
1843 *result = n->getValue();
1849 core::map<Key, Value> m_values;
1855 Generates ids for comparable values.
1856 Id=0 is reserved for "no value".
1859 - Returning value by id (very fast)
1860 - Returning id by value
1861 - Generating a new id for a value
1864 - Remove an id/value pair (is possible to implement but slow)
1866 template<typename T>
1867 class MutexedIdGenerator
1870 MutexedIdGenerator()
1873 assert(m_mutex.IsInitialized());
1876 // Returns true if found
1877 bool getValue(u32 id, T &value)
1881 JMutexAutoLock lock(m_mutex);
1882 if(m_id_to_value.size() < id)
1884 value = m_id_to_value[id-1];
1888 // If id exists for value, returns the id.
1889 // Otherwise generates an id for the value.
1890 u32 getId(const T &value)
1892 JMutexAutoLock lock(m_mutex);
1893 typename core::map<T, u32>::Node *n;
1894 n = m_value_to_id.find(value);
1896 return n->getValue();
1897 m_id_to_value.push_back(value);
1898 u32 new_id = m_id_to_value.size();
1899 m_value_to_id.insert(value, new_id);
1905 // Values are stored here at id-1 position (id 1 = [0])
1906 core::array<T> m_id_to_value;
1907 core::map<T, u32> m_value_to_id;
1911 Checks if a string contains only supplied characters
1913 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1915 for(u32 i=0; i<s.size(); i++)
1917 bool confirmed = false;
1918 for(u32 j=0; j<allowed_chars.size(); j++)
1920 if(s[i] == allowed_chars[j])
1926 if(confirmed == false)
1933 Forcefully wraps string into rows using \n
1934 (no word wrap, used for showing paths in gui)
1936 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1939 for(u32 i=0; i<from.size(); i++)
1941 if(i != 0 && i%rowlen == 0)
1951 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1952 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1955 Returns integer position of node in given floating point position
1957 inline v3s16 floatToInt(v3f p, f32 d)
1960 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1961 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1962 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1967 Returns floating point position of node in given integer position
1969 inline v3f intToFloat(v3s16 p, f32 d)
1980 More serialization stuff
1983 // Creates a string with the length as the first two bytes
1984 inline std::string serializeString(const std::string &plain)
1986 //assert(plain.size() <= 65535);
1987 if(plain.size() > 65535)
1988 throw SerializationError("String too long for serializeString");
1990 writeU16((u8*)&buf[0], plain.size());
1997 // Creates a string with the length as the first two bytes from wide string
1998 inline std::string serializeWideString(const std::wstring &plain)
2000 //assert(plain.size() <= 65535);
2001 if(plain.size() > 65535)
2002 throw SerializationError("String too long for serializeString");
2004 writeU16((u8*)buf, plain.size());
2007 for(u32 i=0; i<plain.size(); i++)
2009 writeU16((u8*)buf, plain[i]);
2015 // Reads a string with the length as the first two bytes
2016 inline std::string deSerializeString(std::istream &is)
2020 if(is.gcount() != 2)
2021 throw SerializationError("deSerializeString: size not read");
2022 u16 s_size = readU16((u8*)buf);
2025 Buffer<char> buf2(s_size);
2026 is.read(&buf2[0], s_size);
2029 s.append(&buf2[0], s_size);
2033 // Reads a wide string with the length as the first two bytes
2034 inline std::wstring deSerializeWideString(std::istream &is)
2038 if(is.gcount() != 2)
2039 throw SerializationError("deSerializeString: size not read");
2040 u16 s_size = readU16((u8*)buf);
2045 for(u32 i=0; i<s_size; i++)
2047 is.read(&buf[0], 2);
2048 wchar_t c16 = readU16((u8*)buf);
2054 // Creates a string with the length as the first four bytes
2055 inline std::string serializeLongString(const std::string &plain)
2058 writeU32((u8*)&buf[0], plain.size());
2065 // Reads a string with the length as the first four bytes
2066 inline std::string deSerializeLongString(std::istream &is)
2070 if(is.gcount() != 4)
2071 throw SerializationError("deSerializeLongString: size not read");
2072 u32 s_size = readU32((u8*)buf);
2075 Buffer<char> buf2(s_size);
2076 is.read(&buf2[0], s_size);
2079 s.append(&buf2[0], s_size);
2085 inline u32 time_to_daynight_ratio(u32 time_of_day)
2087 const s32 daylength = 16;
2088 const s32 nightlength = 6;
2089 const s32 daytimelength = 8;
2091 s32 t = (((time_of_day)%24000)/(24000/d));
2092 if(t < nightlength/2 || t >= d - nightlength/2)
2095 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2101 // Random helper. Usually d=BS
2102 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2104 return core::aabbox3d<f32>(
2105 (float)p.X * d - 0.5*d,
2106 (float)p.Y * d - 0.5*d,
2107 (float)p.Z * d - 0.5*d,
2108 (float)p.X * d + 0.5*d,
2109 (float)p.Y * d + 0.5*d,
2110 (float)p.Z * d + 0.5*d
2114 class IntervalLimiter
2122 dtime: time from last call to this method
2123 wanted_interval: interval wanted
2125 true: action should be skipped
2126 false: action should be done
2128 bool step(float dtime, float wanted_interval)
2130 m_accumulator += dtime;
2131 if(m_accumulator < wanted_interval)
2133 m_accumulator -= wanted_interval;
2137 float m_accumulator;
2140 std::string translatePassword(std::string playername, std::wstring password);