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 writeF1000(std::ostream &os, f32 p)
227 writeF1000((u8*)buf, p);
230 inline f32 readF1000(std::istream &is)
234 return readF1000((u8*)buf);
237 inline void writeV3F1000(std::ostream &os, v3f p)
240 writeV3F1000((u8*)buf, p);
243 inline v3f readV3F1000(std::istream &is)
247 return readV3F1000((u8*)buf);
251 None of these are used at the moment
254 template <typename T>
264 SharedPtr(SharedPtr<T> &t)
268 refcount = t.refcount;
276 SharedPtr<T> & operator=(T *t)
284 SharedPtr<T> & operator=(SharedPtr<T> &t)
287 refcount = t.refcount;
300 bool operator!=(T *t)
304 bool operator==(T *t)
308 T & operator[](unsigned int i)
315 assert((*refcount) > 0);
328 template <typename T>
332 Buffer(unsigned int size)
337 Buffer(const Buffer &buffer)
339 m_size = buffer.m_size;
340 data = new T[buffer.m_size];
341 memcpy(data, buffer.data, buffer.m_size);
343 Buffer(T *t, unsigned int size)
347 memcpy(data, t, size);
353 T & operator[](unsigned int i) const
357 T * operator*() const
361 unsigned int getSize() const
370 template <typename T>
374 SharedBuffer(unsigned int size)
378 refcount = new unsigned int;
381 SharedBuffer(const SharedBuffer &buffer)
383 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
384 m_size = buffer.m_size;
386 refcount = buffer.refcount;
389 SharedBuffer & operator=(const SharedBuffer & buffer)
391 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
395 m_size = buffer.m_size;
397 refcount = buffer.refcount;
404 SharedBuffer(T *t, unsigned int size)
408 memcpy(data, t, size);
409 refcount = new unsigned int;
415 SharedBuffer(const Buffer<T> &buffer)
417 m_size = buffer.m_size;
418 data = new T[buffer.getSize()];
419 memcpy(data, *buffer, buffer.getSize());
420 refcount = new unsigned int;
427 T & operator[](unsigned int i) const
431 T * operator*() const
435 unsigned int getSize() const
442 assert((*refcount) > 0);
452 unsigned int *refcount;
455 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
457 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
462 class MutexedVariable
465 MutexedVariable(T value):
473 JMutexAutoLock lock(m_mutex);
479 JMutexAutoLock lock(m_mutex);
483 // You'll want to grab this in a SharedPtr
484 JMutexAutoLock * getLock()
486 return new JMutexAutoLock(m_mutex);
489 // You pretty surely want to grab the lock when accessing this
503 TimeTaker(const char *name, u32 *result=NULL);
510 u32 stop(bool quiet=false);
521 // Calculates the borders of a "d-radius" cube
522 inline void getFacePositions(core::list<v3s16> &list, u16 d)
526 list.push_back(v3s16(0,0,0));
532 This is an optimized sequence of coordinates.
534 list.push_back(v3s16( 0, 1, 0)); // top
535 list.push_back(v3s16( 0, 0, 1)); // back
536 list.push_back(v3s16(-1, 0, 0)); // left
537 list.push_back(v3s16( 1, 0, 0)); // right
538 list.push_back(v3s16( 0, 0,-1)); // front
539 list.push_back(v3s16( 0,-1, 0)); // bottom
541 list.push_back(v3s16(-1, 0, 1)); // back left
542 list.push_back(v3s16( 1, 0, 1)); // back right
543 list.push_back(v3s16(-1, 0,-1)); // front left
544 list.push_back(v3s16( 1, 0,-1)); // front right
545 list.push_back(v3s16(-1,-1, 0)); // bottom left
546 list.push_back(v3s16( 1,-1, 0)); // bottom right
547 list.push_back(v3s16( 0,-1, 1)); // bottom back
548 list.push_back(v3s16( 0,-1,-1)); // bottom front
549 list.push_back(v3s16(-1, 1, 0)); // top left
550 list.push_back(v3s16( 1, 1, 0)); // top right
551 list.push_back(v3s16( 0, 1, 1)); // top back
552 list.push_back(v3s16( 0, 1,-1)); // top front
554 list.push_back(v3s16(-1, 1, 1)); // top back-left
555 list.push_back(v3s16( 1, 1, 1)); // top back-right
556 list.push_back(v3s16(-1, 1,-1)); // top front-left
557 list.push_back(v3s16( 1, 1,-1)); // top front-right
558 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
559 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
560 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
561 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
566 // Take blocks in all sides, starting from y=0 and going +-y
567 for(s16 y=0; y<=d-1; y++)
569 // Left and right side, including borders
570 for(s16 z=-d; z<=d; z++)
572 list.push_back(v3s16(d,y,z));
573 list.push_back(v3s16(-d,y,z));
576 list.push_back(v3s16(d,-y,z));
577 list.push_back(v3s16(-d,-y,z));
580 // Back and front side, excluding borders
581 for(s16 x=-d+1; x<=d-1; x++)
583 list.push_back(v3s16(x,y,d));
584 list.push_back(v3s16(x,y,-d));
587 list.push_back(v3s16(x,-y,d));
588 list.push_back(v3s16(x,-y,-d));
593 // Take the bottom and top face with borders
594 // -d<x<d, y=+-d, -d<z<d
595 for(s16 x=-d; x<=d; x++)
596 for(s16 z=-d; z<=d; z++)
598 list.push_back(v3s16(x,-d,z));
599 list.push_back(v3s16(x,d,z));
603 class IndentationRaiser
606 IndentationRaiser(u16 *indentation)
608 m_indentation = indentation;
619 inline s16 getContainerPos(s16 p, s16 d)
621 return (p>=0 ? p : p-d+1) / d;
624 inline v2s16 getContainerPos(v2s16 p, s16 d)
627 getContainerPos(p.X, d),
628 getContainerPos(p.Y, d)
632 inline v3s16 getContainerPos(v3s16 p, s16 d)
635 getContainerPos(p.X, d),
636 getContainerPos(p.Y, d),
637 getContainerPos(p.Z, d)
641 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
644 getContainerPos(p.X, d.X),
645 getContainerPos(p.Y, d.Y)
649 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
652 getContainerPos(p.X, d.X),
653 getContainerPos(p.Y, d.Y),
654 getContainerPos(p.Z, d.Z)
658 inline bool isInArea(v3s16 p, s16 d)
661 p.X >= 0 && p.X < d &&
662 p.Y >= 0 && p.Y < d &&
667 inline bool isInArea(v2s16 p, s16 d)
670 p.X >= 0 && p.X < d &&
675 inline bool isInArea(v3s16 p, v3s16 d)
678 p.X >= 0 && p.X < d.X &&
679 p.Y >= 0 && p.Y < d.Y &&
680 p.Z >= 0 && p.Z < d.Z
684 inline s16 rangelim(s16 i, s16 max)
693 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
695 inline v3s16 arealim(v3s16 p, s16 d)
712 inline std::wstring narrow_to_wide(const std::string& mbs)
714 size_t wcl = mbs.size();
715 Buffer<wchar_t> wcs(wcl+1);
716 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
717 if(l == (size_t)(-1))
718 return L"<invalid multibyte string>";
723 inline std::string wide_to_narrow(const std::wstring& wcs)
725 size_t mbl = wcs.size()*4;
726 SharedBuffer<char> mbs(mbl+1);
727 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
728 if(l == (size_t)(-1))
735 // Split a string using the given delimiter. Returns a vector containing
736 // the component parts.
737 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
739 std::vector<std::wstring> parts;
740 std::wstringstream sstr(str);
742 while(std::getline(sstr, part, delimiter))
743 parts.push_back(part);
749 See test.cpp for example cases.
750 wraps degrees to the range of -360...360
751 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
753 inline float wrapDegrees(float f)
755 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
761 // NOTE: This would be used for wrapping to 0...360
767 // 10, 0.5, -0.5, -0.5
772 inline std::string lowercase(const std::string &s)
775 for(size_t i=0; i<s.size(); i++)
778 if(c >= 'A' && c <= 'Z')
785 inline bool is_yes(const std::string &s)
787 std::string s2 = lowercase(trim(s));
788 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
793 inline s32 stoi(const std::string &s, s32 min, s32 max)
795 s32 i = atoi(s.c_str());
804 // MSVC2010 includes it's own versions of these
805 #if !defined(_MSC_VER) || _MSC_VER < 1600
807 inline s32 stoi(std::string s)
809 return atoi(s.c_str());
812 inline s32 stoi(std::wstring s)
814 return atoi(wide_to_narrow(s).c_str());
817 inline float stof(std::string s)
820 std::istringstream ss(s);
827 inline std::string itos(s32 i)
829 std::ostringstream o;
834 inline std::string ftos(float f)
836 std::ostringstream o;
841 inline void str_replace(std::string & str, std::string const & pattern,
842 std::string const & replacement)
844 std::string::size_type start = str.find(pattern, 0);
845 while(start != str.npos)
847 str.replace(start, pattern.size(), replacement);
848 start = str.find(pattern, start+replacement.size());
852 inline void str_replace_char(std::string & str, char from, char to)
854 for(unsigned int i=0; i<str.size(); i++)
862 A base class for simple background thread implementation
865 class SimpleThread : public JThread
879 virtual ~SimpleThread()
882 virtual void * Thread() = 0;
886 JMutexAutoLock lock(run_mutex);
889 void setRun(bool a_run)
891 JMutexAutoLock lock(run_mutex);
910 VALUETYPE_FLAG // Doesn't take any arguments
915 ValueSpec(ValueType a_type, const char *a_help=NULL)
932 void writeLines(std::ostream &os)
934 JMutexAutoLock lock(m_mutex);
936 for(core::map<std::string, std::string>::Iterator
937 i = m_settings.getIterator();
938 i.atEnd() == false; i++)
940 std::string name = i.getNode()->getKey();
941 std::string value = i.getNode()->getValue();
942 os<<name<<" = "<<value<<"\n";
946 bool parseConfigLine(const std::string &line)
948 JMutexAutoLock lock(m_mutex);
950 std::string trimmedline = trim(line);
953 if(trimmedline[0] == '#')
956 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
958 Strfnd sf(trim(line));
960 std::string name = sf.next("=");
966 std::string value = sf.next("\n");
969 /*dstream<<"Config name=\""<<name<<"\" value=\""
970 <<value<<"\""<<std::endl;*/
972 m_settings[name] = value;
977 // Returns false on EOF
978 bool parseConfigObject(std::istream &is)
984 NOTE: This function might be expanded to allow multi-line
988 std::getline(is, line);
989 //dstream<<"got line: \""<<line<<"\""<<std::endl;
991 return parseConfigLine(line);
995 Read configuration file
997 Returns true on success
999 bool readConfigFile(const char *filename)
1001 std::ifstream is(filename);
1002 if(is.good() == false)
1004 dstream<<"Error opening configuration file \""
1005 <<filename<<"\""<<std::endl;
1009 dstream<<"Parsing configuration file: \""
1010 <<filename<<"\""<<std::endl;
1012 while(parseConfigObject(is));
1018 Reads a configuration object from stream (usually a single line)
1021 Preserves comments and empty lines.
1023 Settings that were added to dst are also added to updated.
1024 key of updated is setting name, value of updated is dummy.
1026 Returns false on EOF
1028 bool getUpdatedConfigObject(std::istream &is,
1029 core::list<std::string> &dst,
1030 core::map<std::string, bool> &updated)
1032 JMutexAutoLock lock(m_mutex);
1037 // NOTE: This function will be expanded to allow multi-line settings
1039 std::getline(is, line);
1041 std::string trimmedline = trim(line);
1043 std::string line_end = "";
1044 if(is.eof() == false)
1048 if(trimmedline[0] == '#')
1050 dst.push_back(line+line_end);
1054 Strfnd sf(trim(line));
1056 std::string name = sf.next("=");
1061 dst.push_back(line+line_end);
1065 std::string value = sf.next("\n");
1066 value = trim(value);
1068 if(m_settings.find(name))
1070 std::string newvalue = m_settings[name];
1072 if(newvalue != value)
1074 dstream<<"Changing value of \""<<name<<"\" = \""
1075 <<value<<"\" -> \""<<newvalue<<"\""
1079 dst.push_back(name + " = " + newvalue + line_end);
1081 updated[name] = true;
1088 Updates configuration file
1090 Returns true on success
1092 bool updateConfigFile(const char *filename)
1094 dstream<<"Updating configuration file: \""
1095 <<filename<<"\""<<std::endl;
1097 core::list<std::string> objects;
1098 core::map<std::string, bool> updated;
1100 // Read and modify stuff
1102 std::ifstream is(filename);
1103 if(is.good() == false)
1105 dstream<<"INFO: updateConfigFile():"
1106 " Error opening configuration file"
1108 <<filename<<"\""<<std::endl;
1112 while(getUpdatedConfigObject(is, objects, updated));
1116 JMutexAutoLock lock(m_mutex);
1120 std::ofstream os(filename);
1121 if(os.good() == false)
1123 dstream<<"Error opening configuration file"
1125 <<filename<<"\""<<std::endl;
1132 for(core::list<std::string>::Iterator
1133 i = objects.begin();
1134 i != objects.end(); i++)
1140 Write stuff that was not already in the file
1142 for(core::map<std::string, std::string>::Iterator
1143 i = m_settings.getIterator();
1144 i.atEnd() == false; i++)
1146 if(updated.find(i.getNode()->getKey()))
1148 std::string name = i.getNode()->getKey();
1149 std::string value = i.getNode()->getValue();
1150 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1152 os<<name<<" = "<<value<<"\n";
1160 NOTE: Types of allowed_options are ignored
1162 returns true on success
1164 bool parseCommandLine(int argc, char *argv[],
1165 core::map<std::string, ValueSpec> &allowed_options)
1172 std::string argname = argv[i];
1173 if(argname.substr(0, 2) != "--")
1175 dstream<<"Invalid command-line parameter \""
1176 <<argname<<"\": --<option> expected."<<std::endl;
1181 std::string name = argname.substr(2);
1183 core::map<std::string, ValueSpec>::Node *n;
1184 n = allowed_options.find(name);
1187 dstream<<"Unknown command-line parameter \""
1188 <<argname<<"\""<<std::endl;
1192 ValueType type = n->getValue().type;
1194 std::string value = "";
1196 if(type == VALUETYPE_FLAG)
1204 dstream<<"Invalid command-line parameter \""
1205 <<name<<"\": missing value"<<std::endl;
1213 dstream<<"Valid command-line parameter: \""
1214 <<name<<"\" = \""<<value<<"\""
1222 void set(std::string name, std::string value)
1224 JMutexAutoLock lock(m_mutex);
1226 m_settings[name] = value;
1229 void setDefault(std::string name, std::string value)
1231 JMutexAutoLock lock(m_mutex);
1233 m_defaults[name] = value;
1236 bool exists(std::string name)
1238 JMutexAutoLock lock(m_mutex);
1240 return (m_settings.find(name) || m_defaults.find(name));
1243 std::string get(std::string name)
1245 JMutexAutoLock lock(m_mutex);
1247 core::map<std::string, std::string>::Node *n;
1248 n = m_settings.find(name);
1251 n = m_defaults.find(name);
1254 dstream<<"INFO: Settings: Setting not found: \""
1255 <<name<<"\""<<std::endl;
1256 throw SettingNotFoundException("Setting not found");
1260 return n->getValue();
1263 bool getBool(std::string name)
1265 return is_yes(get(name));
1268 bool getFlag(std::string name)
1272 return getBool(name);
1274 catch(SettingNotFoundException &e)
1281 bool getBoolAsk(std::string name, std::string question, bool def)
1283 // If it is in settings
1285 return getBool(name);
1289 std::cout<<question<<" [y/N]: ";
1290 std::cin.getline(templine, 10);
1299 float getFloat(std::string name)
1301 return stof(get(name));
1304 u16 getU16(std::string name)
1306 return stoi(get(name), 0, 65535);
1309 u16 getU16Ask(std::string name, std::string question, u16 def)
1311 // If it is in settings
1313 return getU16(name);
1317 std::cout<<question<<" ["<<def<<"]: ";
1318 std::cin.getline(templine, 10);
1324 return stoi(s, 0, 65535);
1327 s16 getS16(std::string name)
1329 return stoi(get(name), -32768, 32767);
1332 s32 getS32(std::string name)
1334 return stoi(get(name));
1337 v3f getV3F(std::string name)
1340 Strfnd f(get(name));
1342 value.X = stof(f.next(","));
1343 value.Y = stof(f.next(","));
1344 value.Z = stof(f.next(")"));
1348 u64 getU64(std::string name)
1351 std::string s = get(name);
1352 std::istringstream ss(s);
1357 void setBool(std::string name, bool value)
1365 void setS32(std::string name, s32 value)
1367 set(name, itos(value));
1370 void setFloat(std::string name, float value)
1372 set(name, ftos(value));
1375 void setV3F(std::string name, v3f value)
1377 std::ostringstream os;
1378 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1379 set(name, os.str());
1382 void setU64(std::string name, u64 value)
1384 std::ostringstream os;
1386 set(name, os.str());
1391 JMutexAutoLock lock(m_mutex);
1397 Settings & operator+=(Settings &other)
1399 JMutexAutoLock lock(m_mutex);
1400 JMutexAutoLock lock2(other.m_mutex);
1405 for(core::map<std::string, std::string>::Iterator
1406 i = other.m_settings.getIterator();
1407 i.atEnd() == false; i++)
1409 m_settings.insert(i.getNode()->getKey(),
1410 i.getNode()->getValue());
1413 for(core::map<std::string, std::string>::Iterator
1414 i = other.m_defaults.getIterator();
1415 i.atEnd() == false; i++)
1417 m_defaults.insert(i.getNode()->getKey(),
1418 i.getNode()->getValue());
1423 Settings & operator=(Settings &other)
1425 JMutexAutoLock lock(m_mutex);
1426 JMutexAutoLock lock2(other.m_mutex);
1438 core::map<std::string, std::string> m_settings;
1439 core::map<std::string, std::string> m_defaults;
1440 // All methods that access m_settings/m_defaults directly should lock this.
1445 FIFO queue (well, actually a FILO also)
1447 template<typename T>
1453 m_list.push_back(t);
1458 if(m_list.size() == 0)
1459 throw ItemNotFoundException("Queue: queue is empty");
1461 typename core::list<T>::Iterator begin = m_list.begin();
1463 m_list.erase(begin);
1468 if(m_list.size() == 0)
1469 throw ItemNotFoundException("Queue: queue is empty");
1471 typename core::list<T>::Iterator last = m_list.getLast();
1479 return m_list.size();
1483 core::list<T> m_list;
1487 Thread-safe FIFO queue (well, actually a FILO also)
1490 template<typename T>
1500 JMutexAutoLock lock(m_mutex);
1501 return m_list.size();
1505 JMutexAutoLock lock(m_mutex);
1506 m_list.push_back(t);
1508 T pop_front(u32 wait_time_max_ms=0)
1510 u32 wait_time_ms = 0;
1515 JMutexAutoLock lock(m_mutex);
1517 if(m_list.size() > 0)
1519 typename core::list<T>::Iterator begin = m_list.begin();
1521 m_list.erase(begin);
1525 if(wait_time_ms >= wait_time_max_ms)
1526 throw ItemNotFoundException("MutexedQueue: queue is empty");
1529 // Wait a while before trying again
1534 T pop_back(u32 wait_time_max_ms=0)
1536 u32 wait_time_ms = 0;
1541 JMutexAutoLock lock(m_mutex);
1543 if(m_list.size() > 0)
1545 typename core::list<T>::Iterator last = m_list.getLast();
1551 if(wait_time_ms >= wait_time_max_ms)
1552 throw ItemNotFoundException("MutexedQueue: queue is empty");
1555 // Wait a while before trying again
1566 core::list<T> & getList()
1573 core::list<T> m_list;
1577 A single worker thread - multiple client threads queue framework.
1580 template<typename Caller, typename Data>
1588 template<typename Key, typename T, typename Caller, typename CallerData>
1594 core::list<CallerInfo<Caller, CallerData> > callers;
1597 template<typename Key, typename T, typename Caller, typename CallerData>
1598 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1602 template<typename Key, typename T, typename Caller, typename CallerData>
1610 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1614 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1625 ResultQueue<Key, T, Caller, CallerData> *dest;
1626 core::list<CallerInfo<Caller, CallerData> > callers;
1629 template<typename Key, typename T, typename Caller, typename CallerData>
1635 return m_queue.size();
1638 void add(Key key, Caller caller, CallerData callerdata,
1639 ResultQueue<Key, T, Caller, CallerData> *dest)
1641 JMutexAutoLock lock(m_queue.getMutex());
1644 If the caller is already on the list, only update CallerData
1646 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1647 i = m_queue.getList().begin();
1648 i != m_queue.getList().end(); i++)
1650 GetRequest<Key, T, Caller, CallerData> &request = *i;
1652 if(request.key == key)
1654 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1655 i = request.callers.begin();
1656 i != request.callers.end(); i++)
1658 CallerInfo<Caller, CallerData> &ca = *i;
1659 if(ca.caller == caller)
1661 ca.data = callerdata;
1665 CallerInfo<Caller, CallerData> ca;
1667 ca.data = callerdata;
1668 request.callers.push_back(ca);
1674 Else add a new request to the queue
1677 GetRequest<Key, T, Caller, CallerData> request;
1679 CallerInfo<Caller, CallerData> ca;
1681 ca.data = callerdata;
1682 request.callers.push_back(ca);
1683 request.dest = dest;
1685 m_queue.getList().push_back(request);
1688 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1690 return m_queue.pop_front(wait_if_empty);
1694 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1698 Pseudo-random (VC++ rand() sucks)
1701 void mysrand(unsigned seed);
1702 #define MYRAND_MAX 32767
1704 inline int myrand_range(int min, int max)
1711 return (myrand()%(max-min+1))+min;
1715 Miscellaneous functions
1718 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1719 f32 *distance_ptr=NULL);
1722 Queue with unique values with fast checking of value existence
1725 template<typename Value>
1731 Does nothing if value is already queued.
1734 false: value already exists
1736 bool push_back(Value value)
1738 // Check if already exists
1739 if(m_map.find(value) != NULL)
1743 m_map.insert(value, 0);
1744 m_list.push_back(value);
1751 typename core::list<Value>::Iterator i = m_list.begin();
1753 m_map.remove(value);
1760 assert(m_list.size() == m_map.size());
1761 return m_list.size();
1765 core::map<Value, u8> m_map;
1766 core::list<Value> m_list;
1770 template<typename Key, typename Value>
1777 assert(m_mutex.IsInitialized());
1780 void set(const Key &name, const Value &value)
1782 JMutexAutoLock lock(m_mutex);
1784 m_values[name] = value;
1787 bool get(const Key &name, Value *result)
1789 JMutexAutoLock lock(m_mutex);
1791 typename core::map<Key, Value>::Node *n;
1792 n = m_values.find(name);
1798 *result = n->getValue();
1804 core::map<Key, Value> m_values;
1810 Generates ids for comparable values.
1811 Id=0 is reserved for "no value".
1814 - Returning value by id (very fast)
1815 - Returning id by value
1816 - Generating a new id for a value
1819 - Remove an id/value pair (is possible to implement but slow)
1821 template<typename T>
1822 class MutexedIdGenerator
1825 MutexedIdGenerator()
1828 assert(m_mutex.IsInitialized());
1831 // Returns true if found
1832 bool getValue(u32 id, T &value)
1836 JMutexAutoLock lock(m_mutex);
1837 if(m_id_to_value.size() < id)
1839 value = m_id_to_value[id-1];
1843 // If id exists for value, returns the id.
1844 // Otherwise generates an id for the value.
1845 u32 getId(const T &value)
1847 JMutexAutoLock lock(m_mutex);
1848 typename core::map<T, u32>::Node *n;
1849 n = m_value_to_id.find(value);
1851 return n->getValue();
1852 m_id_to_value.push_back(value);
1853 u32 new_id = m_id_to_value.size();
1854 m_value_to_id.insert(value, new_id);
1860 // Values are stored here at id-1 position (id 1 = [0])
1861 core::array<T> m_id_to_value;
1862 core::map<T, u32> m_value_to_id;
1866 Checks if a string contains only supplied characters
1868 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1870 for(u32 i=0; i<s.size(); i++)
1872 bool confirmed = false;
1873 for(u32 j=0; j<allowed_chars.size(); j++)
1875 if(s[i] == allowed_chars[j])
1881 if(confirmed == false)
1888 Forcefully wraps string into rows using \n
1889 (no word wrap, used for showing paths in gui)
1891 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1894 for(u32 i=0; i<from.size(); i++)
1896 if(i != 0 && i%rowlen == 0)
1906 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1907 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1910 Returns integer position of node in given floating point position
1912 inline v3s16 floatToInt(v3f p, f32 d)
1915 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1916 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1917 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1922 Returns floating point position of node in given integer position
1924 inline v3f intToFloat(v3s16 p, f32 d)
1935 More serialization stuff
1938 // Creates a string with the length as the first two bytes
1939 inline std::string serializeString(const std::string &plain)
1941 //assert(plain.size() <= 65535);
1942 if(plain.size() > 65535)
1943 throw SerializationError("String too long for serializeString");
1945 writeU16((u8*)&buf[0], plain.size());
1952 /*// Reads a string with the length as the first two bytes
1953 inline std::string deSerializeString(const std::string encoded)
1955 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1956 if(s_size > encoded.length() - 2)
1960 s.append(&encoded.c_str()[2], s_size);
1964 // Reads a string with the length as the first two bytes
1965 inline std::string deSerializeString(std::istream &is)
1969 if(is.gcount() != 2)
1970 throw SerializationError("deSerializeString: size not read");
1971 u16 s_size = readU16((u8*)buf);
1974 Buffer<char> buf2(s_size);
1975 is.read(&buf2[0], s_size);
1978 s.append(&buf2[0], s_size);
1982 // Creates a string with the length as the first four bytes
1983 inline std::string serializeLongString(const std::string &plain)
1986 writeU32((u8*)&buf[0], plain.size());
1993 /*// Reads a string with the length as the first four bytes
1994 inline std::string deSerializeLongString(const std::string encoded)
1996 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1997 if(s_size > encoded.length() - 4)
2001 s.append(&encoded.c_str()[4], s_size);
2005 // Reads a string with the length as the first four bytes
2006 inline std::string deSerializeLongString(std::istream &is)
2010 if(is.gcount() != 4)
2011 throw SerializationError("deSerializeLongString: size not read");
2012 u32 s_size = readU32((u8*)buf);
2015 Buffer<char> buf2(s_size);
2016 is.read(&buf2[0], s_size);
2019 s.append(&buf2[0], s_size);
2025 inline u32 time_to_daynight_ratio(u32 time_of_day)
2027 const s32 daylength = 16;
2028 const s32 nightlength = 6;
2029 const s32 daytimelength = 8;
2031 s32 t = (((time_of_day)%24000)/(24000/d));
2032 if(t < nightlength/2 || t >= d - nightlength/2)
2035 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2041 // Random helper. Usually d=BS
2042 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2044 return core::aabbox3d<f32>(
2045 (float)p.X * d - 0.5*d,
2046 (float)p.Y * d - 0.5*d,
2047 (float)p.Z * d - 0.5*d,
2048 (float)p.X * d + 0.5*d,
2049 (float)p.Y * d + 0.5*d,
2050 (float)p.Z * d + 0.5*d
2054 class IntervalLimiter
2062 dtime: time from last call to this method
2063 wanted_interval: interval wanted
2065 true: action should be skipped
2066 false: action should be done
2068 bool step(float dtime, float wanted_interval)
2070 m_accumulator += dtime;
2071 if(m_accumulator < wanted_interval)
2073 m_accumulator -= wanted_interval;
2077 float m_accumulator;