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());
803 inline s32 stoi(std::string s)
805 return atoi(s.c_str());
808 inline s32 stoi(std::wstring s)
810 return atoi(wide_to_narrow(s).c_str());
813 inline float stof(std::string s)
816 std::istringstream ss(s);
821 inline std::string itos(s32 i)
823 std::ostringstream o;
828 inline std::string ftos(float f)
830 std::ostringstream o;
835 inline void str_replace(std::string & str, std::string const & pattern,
836 std::string const & replacement)
838 std::string::size_type start = str.find(pattern, 0);
839 while(start != str.npos)
841 str.replace(start, pattern.size(), replacement);
842 start = str.find(pattern, start+replacement.size());
846 inline void str_replace_char(std::string & str, char from, char to)
848 for(unsigned int i=0; i<str.size(); i++)
856 A base class for simple background thread implementation
859 class SimpleThread : public JThread
873 virtual ~SimpleThread()
876 virtual void * Thread() = 0;
880 JMutexAutoLock lock(run_mutex);
883 void setRun(bool a_run)
885 JMutexAutoLock lock(run_mutex);
904 VALUETYPE_FLAG // Doesn't take any arguments
909 ValueSpec(ValueType a_type, const char *a_help=NULL)
926 void writeLines(std::ostream &os)
928 JMutexAutoLock lock(m_mutex);
930 for(core::map<std::string, std::string>::Iterator
931 i = m_settings.getIterator();
932 i.atEnd() == false; i++)
934 std::string name = i.getNode()->getKey();
935 std::string value = i.getNode()->getValue();
936 os<<name<<" = "<<value<<"\n";
940 bool parseConfigLine(const std::string &line)
942 JMutexAutoLock lock(m_mutex);
944 std::string trimmedline = trim(line);
947 if(trimmedline[0] == '#')
950 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
952 Strfnd sf(trim(line));
954 std::string name = sf.next("=");
960 std::string value = sf.next("\n");
963 /*dstream<<"Config name=\""<<name<<"\" value=\""
964 <<value<<"\""<<std::endl;*/
966 m_settings[name] = value;
971 // Returns false on EOF
972 bool parseConfigObject(std::istream &is)
978 NOTE: This function might be expanded to allow multi-line
982 std::getline(is, line);
983 //dstream<<"got line: \""<<line<<"\""<<std::endl;
985 return parseConfigLine(line);
989 Read configuration file
991 Returns true on success
993 bool readConfigFile(const char *filename)
995 std::ifstream is(filename);
996 if(is.good() == false)
998 dstream<<"Error opening configuration file \""
999 <<filename<<"\""<<std::endl;
1003 dstream<<"Parsing configuration file: \""
1004 <<filename<<"\""<<std::endl;
1006 while(parseConfigObject(is));
1012 Reads a configuration object from stream (usually a single line)
1015 Preserves comments and empty lines.
1017 Settings that were added to dst are also added to updated.
1018 key of updated is setting name, value of updated is dummy.
1020 Returns false on EOF
1022 bool getUpdatedConfigObject(std::istream &is,
1023 core::list<std::string> &dst,
1024 core::map<std::string, bool> &updated)
1026 JMutexAutoLock lock(m_mutex);
1031 // NOTE: This function will be expanded to allow multi-line settings
1033 std::getline(is, line);
1035 std::string trimmedline = trim(line);
1037 std::string line_end = "";
1038 if(is.eof() == false)
1042 if(trimmedline[0] == '#')
1044 dst.push_back(line+line_end);
1048 Strfnd sf(trim(line));
1050 std::string name = sf.next("=");
1055 dst.push_back(line+line_end);
1059 std::string value = sf.next("\n");
1060 value = trim(value);
1062 if(m_settings.find(name))
1064 std::string newvalue = m_settings[name];
1066 if(newvalue != value)
1068 dstream<<"Changing value of \""<<name<<"\" = \""
1069 <<value<<"\" -> \""<<newvalue<<"\""
1073 dst.push_back(name + " = " + newvalue + line_end);
1075 updated[name] = true;
1082 Updates configuration file
1084 Returns true on success
1086 bool updateConfigFile(const char *filename)
1088 dstream<<"Updating configuration file: \""
1089 <<filename<<"\""<<std::endl;
1091 core::list<std::string> objects;
1092 core::map<std::string, bool> updated;
1094 // Read and modify stuff
1096 std::ifstream is(filename);
1097 if(is.good() == false)
1099 dstream<<"INFO: updateConfigFile():"
1100 " Error opening configuration file"
1102 <<filename<<"\""<<std::endl;
1106 while(getUpdatedConfigObject(is, objects, updated));
1110 JMutexAutoLock lock(m_mutex);
1114 std::ofstream os(filename);
1115 if(os.good() == false)
1117 dstream<<"Error opening configuration file"
1119 <<filename<<"\""<<std::endl;
1126 for(core::list<std::string>::Iterator
1127 i = objects.begin();
1128 i != objects.end(); i++)
1134 Write stuff that was not already in the file
1136 for(core::map<std::string, std::string>::Iterator
1137 i = m_settings.getIterator();
1138 i.atEnd() == false; i++)
1140 if(updated.find(i.getNode()->getKey()))
1142 std::string name = i.getNode()->getKey();
1143 std::string value = i.getNode()->getValue();
1144 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1146 os<<name<<" = "<<value<<"\n";
1154 NOTE: Types of allowed_options are ignored
1156 returns true on success
1158 bool parseCommandLine(int argc, char *argv[],
1159 core::map<std::string, ValueSpec> &allowed_options)
1166 std::string argname = argv[i];
1167 if(argname.substr(0, 2) != "--")
1169 dstream<<"Invalid command-line parameter \""
1170 <<argname<<"\": --<option> expected."<<std::endl;
1175 std::string name = argname.substr(2);
1177 core::map<std::string, ValueSpec>::Node *n;
1178 n = allowed_options.find(name);
1181 dstream<<"Unknown command-line parameter \""
1182 <<argname<<"\""<<std::endl;
1186 ValueType type = n->getValue().type;
1188 std::string value = "";
1190 if(type == VALUETYPE_FLAG)
1198 dstream<<"Invalid command-line parameter \""
1199 <<name<<"\": missing value"<<std::endl;
1207 dstream<<"Valid command-line parameter: \""
1208 <<name<<"\" = \""<<value<<"\""
1216 void set(std::string name, std::string value)
1218 JMutexAutoLock lock(m_mutex);
1220 m_settings[name] = value;
1223 void setDefault(std::string name, std::string value)
1225 JMutexAutoLock lock(m_mutex);
1227 m_defaults[name] = value;
1230 bool exists(std::string name)
1232 JMutexAutoLock lock(m_mutex);
1234 return (m_settings.find(name) || m_defaults.find(name));
1237 std::string get(std::string name)
1239 JMutexAutoLock lock(m_mutex);
1241 core::map<std::string, std::string>::Node *n;
1242 n = m_settings.find(name);
1245 n = m_defaults.find(name);
1248 dstream<<"INFO: Settings: Setting not found: \""
1249 <<name<<"\""<<std::endl;
1250 throw SettingNotFoundException("Setting not found");
1254 return n->getValue();
1257 bool getBool(std::string name)
1259 return is_yes(get(name));
1262 bool getFlag(std::string name)
1266 return getBool(name);
1268 catch(SettingNotFoundException &e)
1275 bool getBoolAsk(std::string name, std::string question, bool def)
1277 // If it is in settings
1279 return getBool(name);
1283 std::cout<<question<<" [y/N]: ";
1284 std::cin.getline(templine, 10);
1293 float getFloat(std::string name)
1295 return stof(get(name));
1298 u16 getU16(std::string name)
1300 return stoi(get(name), 0, 65535);
1303 u16 getU16Ask(std::string name, std::string question, u16 def)
1305 // If it is in settings
1307 return getU16(name);
1311 std::cout<<question<<" ["<<def<<"]: ";
1312 std::cin.getline(templine, 10);
1318 return stoi(s, 0, 65535);
1321 s16 getS16(std::string name)
1323 return stoi(get(name), -32768, 32767);
1326 s32 getS32(std::string name)
1328 return stoi(get(name));
1331 v3f getV3F(std::string name)
1334 Strfnd f(get(name));
1336 value.X = stof(f.next(","));
1337 value.Y = stof(f.next(","));
1338 value.Z = stof(f.next(")"));
1342 u64 getU64(std::string name)
1345 std::string s = get(name);
1346 std::istringstream ss(s);
1351 void setBool(std::string name, bool value)
1359 void setS32(std::string name, s32 value)
1361 set(name, itos(value));
1364 void setFloat(std::string name, float value)
1366 set(name, ftos(value));
1369 void setV3F(std::string name, v3f value)
1371 std::ostringstream os;
1372 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1373 set(name, os.str());
1376 void setU64(std::string name, u64 value)
1378 std::ostringstream os;
1380 set(name, os.str());
1385 JMutexAutoLock lock(m_mutex);
1391 Settings & operator+=(Settings &other)
1393 JMutexAutoLock lock(m_mutex);
1394 JMutexAutoLock lock2(other.m_mutex);
1399 for(core::map<std::string, std::string>::Iterator
1400 i = other.m_settings.getIterator();
1401 i.atEnd() == false; i++)
1403 m_settings.insert(i.getNode()->getKey(),
1404 i.getNode()->getValue());
1407 for(core::map<std::string, std::string>::Iterator
1408 i = other.m_defaults.getIterator();
1409 i.atEnd() == false; i++)
1411 m_defaults.insert(i.getNode()->getKey(),
1412 i.getNode()->getValue());
1417 Settings & operator=(Settings &other)
1419 JMutexAutoLock lock(m_mutex);
1420 JMutexAutoLock lock2(other.m_mutex);
1432 core::map<std::string, std::string> m_settings;
1433 core::map<std::string, std::string> m_defaults;
1434 // All methods that access m_settings/m_defaults directly should lock this.
1439 FIFO queue (well, actually a FILO also)
1441 template<typename T>
1447 m_list.push_back(t);
1452 if(m_list.size() == 0)
1453 throw ItemNotFoundException("Queue: queue is empty");
1455 typename core::list<T>::Iterator begin = m_list.begin();
1457 m_list.erase(begin);
1462 if(m_list.size() == 0)
1463 throw ItemNotFoundException("Queue: queue is empty");
1465 typename core::list<T>::Iterator last = m_list.getLast();
1473 return m_list.size();
1477 core::list<T> m_list;
1481 Thread-safe FIFO queue (well, actually a FILO also)
1484 template<typename T>
1494 JMutexAutoLock lock(m_mutex);
1495 return m_list.size();
1499 JMutexAutoLock lock(m_mutex);
1500 m_list.push_back(t);
1502 T pop_front(u32 wait_time_max_ms=0)
1504 u32 wait_time_ms = 0;
1509 JMutexAutoLock lock(m_mutex);
1511 if(m_list.size() > 0)
1513 typename core::list<T>::Iterator begin = m_list.begin();
1515 m_list.erase(begin);
1519 if(wait_time_ms >= wait_time_max_ms)
1520 throw ItemNotFoundException("MutexedQueue: queue is empty");
1523 // Wait a while before trying again
1528 T pop_back(u32 wait_time_max_ms=0)
1530 u32 wait_time_ms = 0;
1535 JMutexAutoLock lock(m_mutex);
1537 if(m_list.size() > 0)
1539 typename core::list<T>::Iterator last = m_list.getLast();
1545 if(wait_time_ms >= wait_time_max_ms)
1546 throw ItemNotFoundException("MutexedQueue: queue is empty");
1549 // Wait a while before trying again
1560 core::list<T> & getList()
1567 core::list<T> m_list;
1571 A single worker thread - multiple client threads queue framework.
1574 template<typename Caller, typename Data>
1582 template<typename Key, typename T, typename Caller, typename CallerData>
1588 core::list<CallerInfo<Caller, CallerData> > callers;
1591 template<typename Key, typename T, typename Caller, typename CallerData>
1592 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1596 template<typename Key, typename T, typename Caller, typename CallerData>
1604 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1608 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1619 ResultQueue<Key, T, Caller, CallerData> *dest;
1620 core::list<CallerInfo<Caller, CallerData> > callers;
1623 template<typename Key, typename T, typename Caller, typename CallerData>
1629 return m_queue.size();
1632 void add(Key key, Caller caller, CallerData callerdata,
1633 ResultQueue<Key, T, Caller, CallerData> *dest)
1635 JMutexAutoLock lock(m_queue.getMutex());
1638 If the caller is already on the list, only update CallerData
1640 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1641 i = m_queue.getList().begin();
1642 i != m_queue.getList().end(); i++)
1644 GetRequest<Key, T, Caller, CallerData> &request = *i;
1646 if(request.key == key)
1648 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1649 i = request.callers.begin();
1650 i != request.callers.end(); i++)
1652 CallerInfo<Caller, CallerData> &ca = *i;
1653 if(ca.caller == caller)
1655 ca.data = callerdata;
1659 CallerInfo<Caller, CallerData> ca;
1661 ca.data = callerdata;
1662 request.callers.push_back(ca);
1668 Else add a new request to the queue
1671 GetRequest<Key, T, Caller, CallerData> request;
1673 CallerInfo<Caller, CallerData> ca;
1675 ca.data = callerdata;
1676 request.callers.push_back(ca);
1677 request.dest = dest;
1679 m_queue.getList().push_back(request);
1682 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1684 return m_queue.pop_front(wait_if_empty);
1688 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1692 Pseudo-random (VC++ rand() sucks)
1695 void mysrand(unsigned seed);
1696 #define MYRAND_MAX 32767
1698 inline int myrand_range(int min, int max)
1705 return (myrand()%(max-min+1))+min;
1709 Miscellaneous functions
1712 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1713 f32 *distance_ptr=NULL);
1716 Queue with unique values with fast checking of value existence
1719 template<typename Value>
1725 Does nothing if value is already queued.
1728 false: value already exists
1730 bool push_back(Value value)
1732 // Check if already exists
1733 if(m_map.find(value) != NULL)
1737 m_map.insert(value, 0);
1738 m_list.push_back(value);
1745 typename core::list<Value>::Iterator i = m_list.begin();
1747 m_map.remove(value);
1754 assert(m_list.size() == m_map.size());
1755 return m_list.size();
1759 core::map<Value, u8> m_map;
1760 core::list<Value> m_list;
1764 template<typename Key, typename Value>
1771 assert(m_mutex.IsInitialized());
1774 void set(const Key &name, const Value &value)
1776 JMutexAutoLock lock(m_mutex);
1778 m_values[name] = value;
1781 bool get(const Key &name, Value *result)
1783 JMutexAutoLock lock(m_mutex);
1785 typename core::map<Key, Value>::Node *n;
1786 n = m_values.find(name);
1791 *result = n->getValue();
1796 core::map<Key, Value> m_values;
1802 Generates ids for comparable values.
1803 Id=0 is reserved for "no value".
1806 - Returning value by id (very fast)
1807 - Returning id by value
1808 - Generating a new id for a value
1811 - Remove an id/value pair (is possible to implement but slow)
1813 template<typename T>
1814 class MutexedIdGenerator
1817 MutexedIdGenerator()
1820 assert(m_mutex.IsInitialized());
1823 // Returns true if found
1824 bool getValue(u32 id, T &value)
1828 JMutexAutoLock lock(m_mutex);
1829 if(m_id_to_value.size() < id)
1831 value = m_id_to_value[id-1];
1835 // If id exists for value, returns the id.
1836 // Otherwise generates an id for the value.
1837 u32 getId(const T &value)
1839 JMutexAutoLock lock(m_mutex);
1840 typename core::map<T, u32>::Node *n;
1841 n = m_value_to_id.find(value);
1843 return n->getValue();
1844 m_id_to_value.push_back(value);
1845 u32 new_id = m_id_to_value.size();
1846 m_value_to_id.insert(value, new_id);
1852 // Values are stored here at id-1 position (id 1 = [0])
1853 core::array<T> m_id_to_value;
1854 core::map<T, u32> m_value_to_id;
1858 Checks if a string contains only supplied characters
1860 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1862 for(u32 i=0; i<s.size(); i++)
1864 bool confirmed = false;
1865 for(u32 j=0; j<allowed_chars.size(); j++)
1867 if(s[i] == allowed_chars[j])
1873 if(confirmed == false)
1880 Forcefully wraps string into rows using \n
1881 (no word wrap, used for showing paths in gui)
1883 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1886 for(u32 i=0; i<from.size(); i++)
1888 if(i != 0 && i%rowlen == 0)
1898 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1899 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1902 Returns integer position of node in given floating point position
1904 inline v3s16 floatToInt(v3f p, f32 d)
1907 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1908 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1909 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1914 Returns floating point position of node in given integer position
1916 inline v3f intToFloat(v3s16 p, f32 d)
1927 More serialization stuff
1930 // Creates a string with the length as the first two bytes
1931 inline std::string serializeString(const std::string &plain)
1933 //assert(plain.size() <= 65535);
1934 if(plain.size() > 65535)
1935 throw SerializationError("String too long for serializeString");
1937 writeU16((u8*)&buf[0], plain.size());
1944 /*// Reads a string with the length as the first two bytes
1945 inline std::string deSerializeString(const std::string encoded)
1947 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1948 if(s_size > encoded.length() - 2)
1952 s.append(&encoded.c_str()[2], s_size);
1956 // Reads a string with the length as the first two bytes
1957 inline std::string deSerializeString(std::istream &is)
1961 if(is.gcount() != 2)
1962 throw SerializationError("deSerializeString: size not read");
1963 u16 s_size = readU16((u8*)buf);
1966 Buffer<char> buf2(s_size);
1967 is.read(&buf2[0], s_size);
1970 s.append(&buf2[0], s_size);
1974 // Creates a string with the length as the first four bytes
1975 inline std::string serializeLongString(const std::string &plain)
1978 writeU32((u8*)&buf[0], plain.size());
1985 /*// Reads a string with the length as the first four bytes
1986 inline std::string deSerializeLongString(const std::string encoded)
1988 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1989 if(s_size > encoded.length() - 4)
1993 s.append(&encoded.c_str()[4], s_size);
1997 // Reads a string with the length as the first four bytes
1998 inline std::string deSerializeLongString(std::istream &is)
2002 if(is.gcount() != 4)
2003 throw SerializationError("deSerializeLongString: size not read");
2004 u32 s_size = readU32((u8*)buf);
2007 Buffer<char> buf2(s_size);
2008 is.read(&buf2[0], s_size);
2011 s.append(&buf2[0], s_size);
2017 inline u32 time_to_daynight_ratio(u32 time_of_day)
2019 const s32 daylength = 16;
2020 const s32 nightlength = 6;
2021 const s32 daytimelength = 8;
2023 s32 t = (((time_of_day)%24000)/(24000/d));
2024 if(t < nightlength/2 || t >= d - nightlength/2)
2027 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
2033 // Random helper. Usually d=BS
2034 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
2036 return core::aabbox3d<f32>(
2037 (float)p.X * d - 0.5*d,
2038 (float)p.Y * d - 0.5*d,
2039 (float)p.Z * d - 0.5*d,
2040 (float)p.X * d + 0.5*d,
2041 (float)p.Y * d + 0.5*d,
2042 (float)p.Z * d + 0.5*d
2046 class IntervalLimiter
2054 dtime: time from last call to this method
2055 wanted_interval: interval wanted
2057 true: action should be skipped
2058 false: action should be done
2060 bool step(float dtime, float wanted_interval)
2062 m_accumulator += dtime;
2063 if(m_accumulator < wanted_interval)
2065 m_accumulator -= wanted_interval;
2069 float m_accumulator;