3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
29 #include <jmutexautolock.h>
31 #include "common_irrlicht.h"
34 #include "exceptions.h"
37 extern const v3s16 g_6dirs[6];
39 extern const v3s16 g_26dirs[26];
42 extern const v3s16 g_27dirs[27];
44 inline void writeU64(u8 *data, u64 i)
46 data[0] = ((i>>56)&0xff);
47 data[1] = ((i>>48)&0xff);
48 data[2] = ((i>>40)&0xff);
49 data[3] = ((i>>32)&0xff);
50 data[4] = ((i>>24)&0xff);
51 data[5] = ((i>>16)&0xff);
52 data[6] = ((i>> 8)&0xff);
53 data[7] = ((i>> 0)&0xff);
56 inline void writeU32(u8 *data, u32 i)
58 data[0] = ((i>>24)&0xff);
59 data[1] = ((i>>16)&0xff);
60 data[2] = ((i>> 8)&0xff);
61 data[3] = ((i>> 0)&0xff);
64 inline void writeU16(u8 *data, u16 i)
66 data[0] = ((i>> 8)&0xff);
67 data[1] = ((i>> 0)&0xff);
70 inline void writeU8(u8 *data, u8 i)
72 data[0] = ((i>> 0)&0xff);
75 inline u64 readU64(u8 *data)
77 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
78 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
79 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
80 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
83 inline u32 readU32(u8 *data)
85 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
88 inline u16 readU16(u8 *data)
90 return (data[0]<<8) | (data[1]<<0);
93 inline u8 readU8(u8 *data)
98 // Signed variants of the above
100 inline void writeS32(u8 *data, s32 i){
101 writeU32(data, (u32)i);
103 inline s32 readS32(u8 *data){
104 return (s32)readU32(data);
107 inline void writeS16(u8 *data, s16 i){
108 writeU16(data, (u16)i);
110 inline s16 readS16(u8 *data){
111 return (s16)readU16(data);
114 inline void writeV3S32(u8 *data, v3s32 p)
116 writeS32(&data[0], p.X);
117 writeS32(&data[4], p.Y);
118 writeS32(&data[8], p.Z);
121 inline v3s32 readV3S32(u8 *data)
124 p.X = readS32(&data[0]);
125 p.Y = readS32(&data[4]);
126 p.Z = readS32(&data[8]);
130 inline void writeV2S16(u8 *data, v2s16 p)
132 writeS16(&data[0], p.X);
133 writeS16(&data[2], p.Y);
136 inline v2s16 readV2S16(u8 *data)
139 p.X = readS16(&data[0]);
140 p.Y = readS16(&data[2]);
144 inline void writeV2S32(u8 *data, v2s32 p)
146 writeS32(&data[0], p.X);
147 writeS32(&data[2], p.Y);
150 inline v2s32 readV2S32(u8 *data)
153 p.X = readS32(&data[0]);
154 p.Y = readS32(&data[2]);
158 inline void writeV3S16(u8 *data, v3s16 p)
160 writeS16(&data[0], p.X);
161 writeS16(&data[2], p.Y);
162 writeS16(&data[4], p.Z);
165 inline v3s16 readV3S16(u8 *data)
168 p.X = readS16(&data[0]);
169 p.Y = readS16(&data[2]);
170 p.Z = readS16(&data[4]);
175 None of these are used at the moment
178 template <typename T>
188 SharedPtr(SharedPtr<T> &t)
192 refcount = t.refcount;
200 SharedPtr<T> & operator=(T *t)
208 SharedPtr<T> & operator=(SharedPtr<T> &t)
211 refcount = t.refcount;
224 bool operator!=(T *t)
228 bool operator==(T *t)
232 T & operator[](unsigned int i)
239 assert((*refcount) > 0);
252 template <typename T>
256 Buffer(unsigned int size)
261 Buffer(const Buffer &buffer)
263 m_size = buffer.m_size;
264 data = new T[buffer.m_size];
265 memcpy(data, buffer.data, buffer.m_size);
267 Buffer(T *t, unsigned int size)
271 memcpy(data, t, size);
277 T & operator[](unsigned int i) const
281 T * operator*() const
285 unsigned int getSize() const
294 template <typename T>
298 SharedBuffer(unsigned int size)
302 refcount = new unsigned int;
305 SharedBuffer(const SharedBuffer &buffer)
307 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
308 m_size = buffer.m_size;
310 refcount = buffer.refcount;
313 SharedBuffer & operator=(const SharedBuffer & buffer)
315 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
319 m_size = buffer.m_size;
321 refcount = buffer.refcount;
328 SharedBuffer(T *t, unsigned int size)
332 memcpy(data, t, size);
333 refcount = new unsigned int;
339 SharedBuffer(const Buffer<T> &buffer)
341 m_size = buffer.m_size;
342 data = new T[buffer.getSize()];
343 memcpy(data, *buffer, buffer.getSize());
344 refcount = new unsigned int;
351 T & operator[](unsigned int i) const
355 T * operator*() const
359 unsigned int getSize() const
366 assert((*refcount) > 0);
376 unsigned int *refcount;
379 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
381 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
386 class MutexedVariable
389 MutexedVariable(T value):
397 JMutexAutoLock lock(m_mutex);
403 JMutexAutoLock lock(m_mutex);
407 // You'll want to grab this in a SharedPtr
408 JMutexAutoLock * getLock()
410 return new JMutexAutoLock(m_mutex);
413 // You pretty surely want to grab the lock when accessing this
424 class IrrlichtWrapper;
429 TimeTaker(const char *name, u32 *result=NULL);
436 u32 stop(bool quiet=false);
447 // Calculates the borders of a "d-radius" cube
448 inline void getFacePositions(core::list<v3s16> &list, u16 d)
452 list.push_back(v3s16(0,0,0));
458 This is an optimized sequence of coordinates.
460 list.push_back(v3s16( 0, 1, 0)); // top
461 list.push_back(v3s16( 0, 0, 1)); // back
462 list.push_back(v3s16(-1, 0, 0)); // left
463 list.push_back(v3s16( 1, 0, 0)); // right
464 list.push_back(v3s16( 0, 0,-1)); // front
465 list.push_back(v3s16( 0,-1, 0)); // bottom
467 list.push_back(v3s16(-1, 0, 1)); // back left
468 list.push_back(v3s16( 1, 0, 1)); // back right
469 list.push_back(v3s16(-1, 0,-1)); // front left
470 list.push_back(v3s16( 1, 0,-1)); // front right
471 list.push_back(v3s16(-1,-1, 0)); // bottom left
472 list.push_back(v3s16( 1,-1, 0)); // bottom right
473 list.push_back(v3s16( 0,-1, 1)); // bottom back
474 list.push_back(v3s16( 0,-1,-1)); // bottom front
475 list.push_back(v3s16(-1, 1, 0)); // top left
476 list.push_back(v3s16( 1, 1, 0)); // top right
477 list.push_back(v3s16( 0, 1, 1)); // top back
478 list.push_back(v3s16( 0, 1,-1)); // top front
480 list.push_back(v3s16(-1, 1, 1)); // top back-left
481 list.push_back(v3s16( 1, 1, 1)); // top back-right
482 list.push_back(v3s16(-1, 1,-1)); // top front-left
483 list.push_back(v3s16( 1, 1,-1)); // top front-right
484 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
485 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
486 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
487 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
492 // Take blocks in all sides, starting from y=0 and going +-y
493 for(s16 y=0; y<=d-1; y++)
495 // Left and right side, including borders
496 for(s16 z=-d; z<=d; z++)
498 list.push_back(v3s16(d,y,z));
499 list.push_back(v3s16(-d,y,z));
502 list.push_back(v3s16(d,-y,z));
503 list.push_back(v3s16(-d,-y,z));
506 // Back and front side, excluding borders
507 for(s16 x=-d+1; x<=d-1; x++)
509 list.push_back(v3s16(x,y,d));
510 list.push_back(v3s16(x,y,-d));
513 list.push_back(v3s16(x,-y,d));
514 list.push_back(v3s16(x,-y,-d));
519 // Take the bottom and top face with borders
520 // -d<x<d, y=+-d, -d<z<d
521 for(s16 x=-d; x<=d; x++)
522 for(s16 z=-d; z<=d; z++)
524 list.push_back(v3s16(x,-d,z));
525 list.push_back(v3s16(x,d,z));
529 class IndentationRaiser
532 IndentationRaiser(u16 *indentation)
534 m_indentation = indentation;
545 inline s16 getContainerPos(s16 p, s16 d)
547 return (p>=0 ? p : p-d+1) / d;
550 inline v2s16 getContainerPos(v2s16 p, s16 d)
553 getContainerPos(p.X, d),
554 getContainerPos(p.Y, d)
558 inline v3s16 getContainerPos(v3s16 p, s16 d)
561 getContainerPos(p.X, d),
562 getContainerPos(p.Y, d),
563 getContainerPos(p.Z, d)
567 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
570 getContainerPos(p.X, d.X),
571 getContainerPos(p.Y, d.Y)
575 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
578 getContainerPos(p.X, d.X),
579 getContainerPos(p.Y, d.Y),
580 getContainerPos(p.Z, d.Z)
584 inline bool isInArea(v3s16 p, s16 d)
587 p.X >= 0 && p.X < d &&
588 p.Y >= 0 && p.Y < d &&
593 inline bool isInArea(v2s16 p, s16 d)
596 p.X >= 0 && p.X < d &&
601 inline bool isInArea(v3s16 p, v3s16 d)
604 p.X >= 0 && p.X < d.X &&
605 p.Y >= 0 && p.Y < d.Y &&
606 p.Z >= 0 && p.Z < d.Z
610 inline s16 rangelim(s16 i, s16 max)
619 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
621 inline v3s16 arealim(v3s16 p, s16 d)
638 inline std::wstring narrow_to_wide(const std::string& mbs)
640 size_t wcl = mbs.size();
641 Buffer<wchar_t> wcs(wcl+1);
642 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
643 if(l == (size_t)(-1))
644 return L"<invalid multibyte string>";
649 inline std::string wide_to_narrow(const std::wstring& wcs)
651 size_t mbl = wcs.size()*4;
652 SharedBuffer<char> mbs(mbl+1);
653 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
654 if(l == (size_t)(-1))
662 See test.cpp for example cases.
663 wraps degrees to the range of -360...360
664 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
666 inline float wrapDegrees(float f)
668 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
674 // NOTE: This would be used for wrapping to 0...360
680 // 10, 0.5, -0.5, -0.5
685 inline std::string lowercase(const std::string &s)
688 for(size_t i=0; i<s.size(); i++)
691 if(c >= 'A' && c <= 'Z')
698 inline bool is_yes(const std::string &s)
700 std::string s2 = lowercase(trim(s));
701 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
706 inline s32 stoi(const std::string &s, s32 min, s32 max)
708 s32 i = atoi(s.c_str());
716 inline s32 stoi(std::string s)
718 return atoi(s.c_str());
721 inline float stof(std::string s)
724 std::istringstream ss(s);
729 inline std::string itos(s32 i)
731 std::ostringstream o;
736 inline std::string ftos(float f)
738 std::ostringstream o;
743 inline void str_replace(std::string & str, std::string const & pattern,
744 std::string const & replacement)
746 std::string::size_type start = str.find(pattern, 0);
747 while(start != str.npos)
749 str.replace(start, pattern.size(), replacement);
750 start = str.find(pattern, start+replacement.size());
754 inline void str_replace_char(std::string & str, char from, char to)
756 for(unsigned int i=0; i<str.size(); i++)
764 A base class for simple background thread implementation
767 class SimpleThread : public JThread
781 virtual ~SimpleThread()
784 virtual void * Thread() = 0;
788 JMutexAutoLock lock(run_mutex);
791 void setRun(bool a_run)
793 JMutexAutoLock lock(run_mutex);
812 VALUETYPE_FLAG // Doesn't take any arguments
817 ValueSpec(ValueType a_type, const char *a_help=NULL)
834 void writeLines(std::ostream &os)
836 JMutexAutoLock lock(m_mutex);
838 for(core::map<std::string, std::string>::Iterator
839 i = m_settings.getIterator();
840 i.atEnd() == false; i++)
842 std::string name = i.getNode()->getKey();
843 std::string value = i.getNode()->getValue();
844 os<<name<<" = "<<value<<"\n";
848 bool parseConfigLine(const std::string &line)
850 JMutexAutoLock lock(m_mutex);
852 std::string trimmedline = trim(line);
855 if(trimmedline[0] == '#')
858 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
860 Strfnd sf(trim(line));
862 std::string name = sf.next("=");
868 std::string value = sf.next("\n");
871 /*dstream<<"Config name=\""<<name<<"\" value=\""
872 <<value<<"\""<<std::endl;*/
874 m_settings[name] = value;
879 // Returns false on EOF
880 bool parseConfigObject(std::istream &is)
886 NOTE: This function might be expanded to allow multi-line
890 std::getline(is, line);
891 //dstream<<"got line: \""<<line<<"\""<<std::endl;
893 return parseConfigLine(line);
897 Read configuration file
899 Returns true on success
901 bool readConfigFile(const char *filename)
903 std::ifstream is(filename);
904 if(is.good() == false)
906 dstream<<"Error opening configuration file \""
907 <<filename<<"\""<<std::endl;
911 dstream<<"Parsing configuration file: \""
912 <<filename<<"\""<<std::endl;
914 while(parseConfigObject(is));
920 Reads a configuration object from stream (usually a single line)
923 Preserves comments and empty lines.
925 Settings that were added to dst are also added to updated.
926 key of updated is setting name, value of updated is dummy.
930 bool getUpdatedConfigObject(std::istream &is,
931 core::list<std::string> &dst,
932 core::map<std::string, bool> &updated)
934 JMutexAutoLock lock(m_mutex);
939 // NOTE: This function will be expanded to allow multi-line settings
941 std::getline(is, line);
943 std::string trimmedline = trim(line);
945 std::string line_end = "";
946 if(is.eof() == false)
950 if(trimmedline[0] == '#')
952 dst.push_back(line+line_end);
956 Strfnd sf(trim(line));
958 std::string name = sf.next("=");
963 dst.push_back(line+line_end);
967 std::string value = sf.next("\n");
970 if(m_settings.find(name))
972 std::string newvalue = m_settings[name];
974 if(newvalue != value)
976 dstream<<"Changing value of \""<<name<<"\" = \""
977 <<value<<"\" -> \""<<newvalue<<"\""
981 dst.push_back(name + " = " + newvalue + line_end);
983 updated[name] = true;
990 Updates configuration file
992 Returns true on success
994 bool updateConfigFile(const char *filename)
996 dstream<<"Updating configuration file: \""
997 <<filename<<"\""<<std::endl;
999 core::list<std::string> objects;
1000 core::map<std::string, bool> updated;
1002 // Read and modify stuff
1004 std::ifstream is(filename);
1005 if(is.good() == false)
1007 dstream<<"INFO: updateConfigFile():"
1008 " Error opening configuration file"
1010 <<filename<<"\""<<std::endl;
1014 while(getUpdatedConfigObject(is, objects, updated));
1018 JMutexAutoLock lock(m_mutex);
1022 std::ofstream os(filename);
1023 if(os.good() == false)
1025 dstream<<"Error opening configuration file"
1027 <<filename<<"\""<<std::endl;
1034 for(core::list<std::string>::Iterator
1035 i = objects.begin();
1036 i != objects.end(); i++)
1042 Write stuff that was not already in the file
1044 for(core::map<std::string, std::string>::Iterator
1045 i = m_settings.getIterator();
1046 i.atEnd() == false; i++)
1048 if(updated.find(i.getNode()->getKey()))
1050 std::string name = i.getNode()->getKey();
1051 std::string value = i.getNode()->getValue();
1052 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
1054 os<<name<<" = "<<value<<"\n";
1062 NOTE: Types of allowed_options are ignored
1064 returns true on success
1066 bool parseCommandLine(int argc, char *argv[],
1067 core::map<std::string, ValueSpec> &allowed_options)
1074 std::string argname = argv[i];
1075 if(argname.substr(0, 2) != "--")
1077 dstream<<"Invalid command-line parameter \""
1078 <<argname<<"\": --<option> expected."<<std::endl;
1083 std::string name = argname.substr(2);
1085 core::map<std::string, ValueSpec>::Node *n;
1086 n = allowed_options.find(name);
1089 dstream<<"Unknown command-line parameter \""
1090 <<argname<<"\""<<std::endl;
1094 ValueType type = n->getValue().type;
1096 std::string value = "";
1098 if(type == VALUETYPE_FLAG)
1106 dstream<<"Invalid command-line parameter \""
1107 <<name<<"\": missing value"<<std::endl;
1115 dstream<<"Valid command-line parameter: \""
1116 <<name<<"\" = \""<<value<<"\""
1124 void set(std::string name, std::string value)
1126 JMutexAutoLock lock(m_mutex);
1128 m_settings[name] = value;
1131 void setDefault(std::string name, std::string value)
1133 JMutexAutoLock lock(m_mutex);
1135 m_defaults[name] = value;
1138 bool exists(std::string name)
1140 JMutexAutoLock lock(m_mutex);
1142 return (m_settings.find(name) || m_defaults.find(name));
1145 std::string get(std::string name)
1147 JMutexAutoLock lock(m_mutex);
1149 core::map<std::string, std::string>::Node *n;
1150 n = m_settings.find(name);
1153 n = m_defaults.find(name);
1156 dstream<<"INFO: Settings: Setting not found: \""
1157 <<name<<"\""<<std::endl;
1158 throw SettingNotFoundException("Setting not found");
1162 return n->getValue();
1165 bool getBool(std::string name)
1167 return is_yes(get(name));
1170 bool getFlag(std::string name)
1174 return getBool(name);
1176 catch(SettingNotFoundException &e)
1183 bool getBoolAsk(std::string name, std::string question, bool def)
1185 // If it is in settings
1187 return getBool(name);
1191 std::cout<<question<<" [y/N]: ";
1192 std::cin.getline(templine, 10);
1201 float getFloat(std::string name)
1203 return stof(get(name));
1206 u16 getU16(std::string name)
1208 return stoi(get(name), 0, 65535);
1211 u16 getU16Ask(std::string name, std::string question, u16 def)
1213 // If it is in settings
1215 return getU16(name);
1219 std::cout<<question<<" ["<<def<<"]: ";
1220 std::cin.getline(templine, 10);
1226 return stoi(s, 0, 65535);
1229 s16 getS16(std::string name)
1231 return stoi(get(name), -32768, 32767);
1234 s32 getS32(std::string name)
1236 return stoi(get(name));
1239 v3f getV3F(std::string name)
1242 Strfnd f(get(name));
1244 value.X = stof(f.next(","));
1245 value.Y = stof(f.next(","));
1246 value.Z = stof(f.next(")"));
1250 u64 getU64(std::string name)
1253 std::string s = get(name);
1254 std::istringstream ss(s);
1259 void setS32(std::string name, s32 value)
1261 set(name, itos(value));
1264 void setFloat(std::string name, float value)
1266 set(name, ftos(value));
1269 void setV3F(std::string name, v3f value)
1271 std::ostringstream os;
1272 os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
1273 set(name, os.str());
1276 void setU64(std::string name, u64 value)
1278 std::ostringstream os;
1280 set(name, os.str());
1285 JMutexAutoLock lock(m_mutex);
1291 Settings & operator+=(Settings &other)
1293 JMutexAutoLock lock(m_mutex);
1294 JMutexAutoLock lock2(other.m_mutex);
1299 for(core::map<std::string, std::string>::Iterator
1300 i = other.m_settings.getIterator();
1301 i.atEnd() == false; i++)
1303 m_settings.insert(i.getNode()->getKey(),
1304 i.getNode()->getValue());
1307 for(core::map<std::string, std::string>::Iterator
1308 i = other.m_defaults.getIterator();
1309 i.atEnd() == false; i++)
1311 m_defaults.insert(i.getNode()->getKey(),
1312 i.getNode()->getValue());
1317 Settings & operator=(Settings &other)
1319 JMutexAutoLock lock(m_mutex);
1320 JMutexAutoLock lock2(other.m_mutex);
1332 core::map<std::string, std::string> m_settings;
1333 core::map<std::string, std::string> m_defaults;
1334 // All methods that access m_settings/m_defaults directly should lock this.
1339 FIFO queue (well, actually a FILO also)
1341 template<typename T>
1347 m_list.push_back(t);
1352 if(m_list.size() == 0)
1353 throw ItemNotFoundException("Queue: queue is empty");
1355 typename core::list<T>::Iterator begin = m_list.begin();
1357 m_list.erase(begin);
1362 if(m_list.size() == 0)
1363 throw ItemNotFoundException("Queue: queue is empty");
1365 typename core::list<T>::Iterator last = m_list.getLast();
1373 return m_list.size();
1377 core::list<T> m_list;
1381 Thread-safe FIFO queue (well, actually a FILO also)
1384 template<typename T>
1394 JMutexAutoLock lock(m_mutex);
1395 return m_list.size();
1399 JMutexAutoLock lock(m_mutex);
1400 m_list.push_back(t);
1402 T pop_front(u32 wait_time_max_ms=0)
1404 u32 wait_time_ms = 0;
1409 JMutexAutoLock lock(m_mutex);
1411 if(m_list.size() > 0)
1413 typename core::list<T>::Iterator begin = m_list.begin();
1415 m_list.erase(begin);
1419 if(wait_time_ms >= wait_time_max_ms)
1420 throw ItemNotFoundException("MutexedQueue: queue is empty");
1423 // Wait a while before trying again
1428 T pop_back(u32 wait_time_max_ms=0)
1430 u32 wait_time_ms = 0;
1435 JMutexAutoLock lock(m_mutex);
1437 if(m_list.size() > 0)
1439 typename core::list<T>::Iterator last = m_list.getLast();
1445 if(wait_time_ms >= wait_time_max_ms)
1446 throw ItemNotFoundException("MutexedQueue: queue is empty");
1449 // Wait a while before trying again
1460 core::list<T> & getList()
1467 core::list<T> m_list;
1471 A single worker thread - multiple client threads queue framework.
1474 template<typename Caller, typename Data>
1482 template<typename Key, typename T, typename Caller, typename CallerData>
1488 core::list<CallerInfo<Caller, CallerData> > callers;
1491 template<typename Key, typename T, typename Caller, typename CallerData>
1492 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1496 template<typename Key, typename T, typename Caller, typename CallerData>
1504 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1508 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1519 ResultQueue<Key, T, Caller, CallerData> *dest;
1520 core::list<CallerInfo<Caller, CallerData> > callers;
1523 template<typename Key, typename T, typename Caller, typename CallerData>
1529 return m_queue.size();
1532 void add(Key key, Caller caller, CallerData callerdata,
1533 ResultQueue<Key, T, Caller, CallerData> *dest)
1535 JMutexAutoLock lock(m_queue.getMutex());
1538 If the caller is already on the list, only update CallerData
1540 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1541 i = m_queue.getList().begin();
1542 i != m_queue.getList().end(); i++)
1544 GetRequest<Key, T, Caller, CallerData> &request = *i;
1546 if(request.key == key)
1548 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1549 i = request.callers.begin();
1550 i != request.callers.end(); i++)
1552 CallerInfo<Caller, CallerData> &ca = *i;
1553 if(ca.caller == caller)
1555 ca.data = callerdata;
1559 CallerInfo<Caller, CallerData> ca;
1561 ca.data = callerdata;
1562 request.callers.push_back(ca);
1568 Else add a new request to the queue
1571 GetRequest<Key, T, Caller, CallerData> request;
1573 CallerInfo<Caller, CallerData> ca;
1575 ca.data = callerdata;
1576 request.callers.push_back(ca);
1577 request.dest = dest;
1579 m_queue.getList().push_back(request);
1582 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1584 return m_queue.pop_front(wait_if_empty);
1588 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1592 Pseudo-random (VC++ rand() sucks)
1595 void mysrand(unsigned seed);
1596 #define MYRAND_MAX 32767
1598 inline int myrand_range(int min, int max)
1605 return (myrand()%(max-min+1))+min;
1609 Miscellaneous functions
1612 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1613 f32 *distance_ptr=NULL);
1616 Queue with unique values with fast checking of value existence
1619 template<typename Value>
1625 Does nothing if value is already queued.
1628 false: value already exists
1630 bool push_back(Value value)
1632 // Check if already exists
1633 if(m_map.find(value) != NULL)
1637 m_map.insert(value, 0);
1638 m_list.push_back(value);
1645 typename core::list<Value>::Iterator i = m_list.begin();
1647 m_map.remove(value);
1654 assert(m_list.size() == m_map.size());
1655 return m_list.size();
1659 core::map<Value, u8> m_map;
1660 core::list<Value> m_list;
1664 template<typename Key, typename Value>
1671 assert(m_mutex.IsInitialized());
1674 void set(const Key &name, const Value &value)
1676 JMutexAutoLock lock(m_mutex);
1678 m_values[name] = value;
1681 bool get(const Key &name, Value *result)
1683 JMutexAutoLock lock(m_mutex);
1685 typename core::map<Key, Value>::Node *n;
1686 n = m_values.find(name);
1691 *result = n->getValue();
1696 core::map<Key, Value> m_values;
1702 Generates ids for comparable values.
1703 Id=0 is reserved for "no value".
1706 - Returning value by id (very fast)
1707 - Returning id by value
1708 - Generating a new id for a value
1711 - Remove an id/value pair (is possible to implement but slow)
1713 template<typename T>
1714 class MutexedIdGenerator
1717 MutexedIdGenerator()
1720 assert(m_mutex.IsInitialized());
1723 // Returns true if found
1724 bool getValue(u32 id, T &value)
1728 JMutexAutoLock lock(m_mutex);
1729 if(m_id_to_value.size() < id)
1731 value = m_id_to_value[id-1];
1735 // If id exists for value, returns the id.
1736 // Otherwise generates an id for the value.
1737 u32 getId(const T &value)
1739 JMutexAutoLock lock(m_mutex);
1740 typename core::map<T, u32>::Node *n;
1741 n = m_value_to_id.find(value);
1743 return n->getValue();
1744 m_id_to_value.push_back(value);
1745 u32 new_id = m_id_to_value.size();
1746 m_value_to_id.insert(value, new_id);
1752 // Values are stored here at id-1 position (id 1 = [0])
1753 core::array<T> m_id_to_value;
1754 core::map<T, u32> m_value_to_id;
1758 Checks if a string contains only supplied characters
1760 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1762 for(u32 i=0; i<s.size(); i++)
1764 bool confirmed = false;
1765 for(u32 j=0; j<allowed_chars.size(); j++)
1767 if(s[i] == allowed_chars[j])
1773 if(confirmed == false)
1780 Forcefully wraps string into rows using \n
1781 (no word wrap, used for showing paths in gui)
1783 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1786 for(u32 i=0; i<from.size(); i++)
1788 if(i != 0 && i%rowlen == 0)
1798 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1799 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1802 Returns integer position of node in given floating point position
1804 inline v3s16 floatToInt(v3f p, f32 d)
1807 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1808 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1809 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1814 Returns floating point position of node in given integer position
1816 inline v3f intToFloat(v3s16 p, f32 d)
1827 More serialization stuff
1830 // Creates a string with the length as the first two bytes
1831 inline std::string serializeString(const std::string plain)
1833 assert(plain.size() <= 65535);
1835 writeU16((u8*)&buf[0], plain.size());
1842 /*// Reads a string with the length as the first two bytes
1843 inline std::string deSerializeString(const std::string encoded)
1845 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1846 if(s_size > encoded.length() - 2)
1850 s.append(&encoded.c_str()[2], s_size);
1854 // Reads a string with the length as the first two bytes
1855 inline std::string deSerializeString(std::istream &is)
1859 if(is.gcount() != 2)
1860 throw SerializationError("deSerializeString: size not read");
1861 u16 s_size = readU16((u8*)buf);
1864 Buffer<char> buf2(s_size);
1865 is.read(&buf2[0], s_size);
1868 s.append(&buf2[0], s_size);
1872 // Creates a string with the length as the first four bytes
1873 inline std::string serializeLongString(const std::string plain)
1876 writeU32((u8*)&buf[0], plain.size());
1883 /*// Reads a string with the length as the first four bytes
1884 inline std::string deSerializeLongString(const std::string encoded)
1886 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1887 if(s_size > encoded.length() - 4)
1891 s.append(&encoded.c_str()[4], s_size);
1895 // Reads a string with the length as the first four bytes
1896 inline std::string deSerializeLongString(std::istream &is)
1900 if(is.gcount() != 4)
1901 throw SerializationError("deSerializeLongString: size not read");
1902 u32 s_size = readU32((u8*)buf);
1905 Buffer<char> buf2(s_size);
1906 is.read(&buf2[0], s_size);
1909 s.append(&buf2[0], s_size);
1915 inline u32 time_to_daynight_ratio(u32 time_of_day)
1917 const s32 daylength = 16;
1918 const s32 nightlength = 6;
1919 const s32 daytimelength = 8;
1921 s32 t = (((time_of_day)%24000)/(24000/d));
1922 if(t < nightlength/2 || t >= d - nightlength/2)
1924 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1930 // Random helper. Usually d=BS
1931 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1933 return core::aabbox3d<f32>(
1934 (float)p.X * d - 0.5*d,
1935 (float)p.Y * d - 0.5*d,
1936 (float)p.Z * d - 0.5*d,
1937 (float)p.X * d + 0.5*d,
1938 (float)p.Y * d + 0.5*d,
1939 (float)p.Z * d + 0.5*d