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;
1470 template<typename Caller, typename Data>
1478 template<typename Key, typename T, typename Caller, typename CallerData>
1484 core::list<CallerInfo<Caller, CallerData> > callers;
1487 template<typename Key, typename T, typename Caller, typename CallerData>
1488 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1492 template<typename Key, typename T, typename Caller, typename CallerData>
1500 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1504 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1515 ResultQueue<Key, T, Caller, CallerData> *dest;
1516 core::list<CallerInfo<Caller, CallerData> > callers;
1520 Quickhands for typical request-result queues.
1521 Used for distributing work between threads.
1524 template<typename Key, typename T, typename Caller, typename CallerData>
1530 return m_queue.size();
1533 void add(Key key, Caller caller, CallerData callerdata,
1534 ResultQueue<Key, T, Caller, CallerData> *dest)
1536 JMutexAutoLock lock(m_queue.getMutex());
1539 If the caller is already on the list, only update CallerData
1541 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1542 i = m_queue.getList().begin();
1543 i != m_queue.getList().end(); i++)
1545 GetRequest<Key, T, Caller, CallerData> &request = *i;
1547 if(request.key == key)
1549 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1550 i = request.callers.begin();
1551 i != request.callers.end(); i++)
1553 CallerInfo<Caller, CallerData> &ca = *i;
1554 if(ca.caller == caller)
1556 ca.data = callerdata;
1560 CallerInfo<Caller, CallerData> ca;
1562 ca.data = callerdata;
1563 request.callers.push_back(ca);
1569 Else add a new request to the queue
1572 GetRequest<Key, T, Caller, CallerData> request;
1574 CallerInfo<Caller, CallerData> ca;
1576 ca.data = callerdata;
1577 request.callers.push_back(ca);
1578 request.dest = dest;
1580 m_queue.getList().push_back(request);
1583 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1585 return m_queue.pop_front(wait_if_empty);
1589 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1593 Pseudo-random (VC++ rand() sucks)
1596 void mysrand(unsigned seed);
1597 #define MYRAND_MAX 32767
1599 inline int myrand_range(int min, int max)
1606 return (myrand()%(max-min+1))+min;
1610 Miscellaneous functions
1613 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range,
1614 f32 *distance_ptr=NULL);
1617 Queue with unique values with fast checking of value existence
1620 template<typename Value>
1626 Does nothing if value is already queued.
1629 false: value already exists
1631 bool push_back(Value value)
1633 // Check if already exists
1634 if(m_map.find(value) != NULL)
1638 m_map.insert(value, 0);
1639 m_list.push_back(value);
1646 typename core::list<Value>::Iterator i = m_list.begin();
1648 m_map.remove(value);
1655 assert(m_list.size() == m_map.size());
1656 return m_list.size();
1660 core::map<Value, u8> m_map;
1661 core::list<Value> m_list;
1665 template<typename Key, typename Value>
1672 assert(m_mutex.IsInitialized());
1675 void set(const Key &name, const Value &value)
1677 JMutexAutoLock lock(m_mutex);
1679 m_values[name] = value;
1682 bool get(const Key &name, Value *result)
1684 JMutexAutoLock lock(m_mutex);
1686 typename core::map<Key, Value>::Node *n;
1687 n = m_values.find(name);
1692 *result = n->getValue();
1697 core::map<Key, Value> m_values;
1703 Generates ids for comparable values.
1704 Id=0 is reserved for "no value".
1707 - Returning value by id (very fast)
1708 - Returning id by value
1709 - Generating a new id for a value
1712 - Remove an id/value pair (is possible to implement but slow)
1714 template<typename T>
1715 class MutexedIdGenerator
1718 MutexedIdGenerator()
1721 assert(m_mutex.IsInitialized());
1724 // Returns true if found
1725 bool getValue(u32 id, T &value)
1729 JMutexAutoLock lock(m_mutex);
1730 if(m_id_to_value.size() < id)
1732 value = m_id_to_value[id-1];
1736 // If id exists for value, returns the id.
1737 // Otherwise generates an id for the value.
1738 u32 getId(const T &value)
1740 JMutexAutoLock lock(m_mutex);
1741 typename core::map<T, u32>::Node *n;
1742 n = m_value_to_id.find(value);
1744 return n->getValue();
1745 m_id_to_value.push_back(value);
1746 u32 new_id = m_id_to_value.size();
1747 m_value_to_id.insert(value, new_id);
1753 // Values are stored here at id-1 position (id 1 = [0])
1754 core::array<T> m_id_to_value;
1755 core::map<T, u32> m_value_to_id;
1759 Checks if a string contains only supplied characters
1761 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1763 for(u32 i=0; i<s.size(); i++)
1765 bool confirmed = false;
1766 for(u32 j=0; j<allowed_chars.size(); j++)
1768 if(s[i] == allowed_chars[j])
1774 if(confirmed == false)
1781 Forcefully wraps string into rows using \n
1782 (no word wrap, used for showing paths in gui)
1784 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1787 for(u32 i=0; i<from.size(); i++)
1789 if(i != 0 && i%rowlen == 0)
1799 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1800 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1803 Returns integer position of node in given floating point position
1805 inline v3s16 floatToInt(v3f p, f32 d)
1808 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1809 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1810 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1815 Returns floating point position of node in given integer position
1817 inline v3f intToFloat(v3s16 p, f32 d)
1828 More serialization stuff
1831 // Creates a string with the length as the first two bytes
1832 inline std::string serializeString(const std::string plain)
1834 assert(plain.size() <= 65535);
1836 writeU16((u8*)&buf[0], plain.size());
1843 // Reads a string with the length as the first two bytes
1844 inline std::string deSerializeString(const std::string encoded)
1846 u16 s_size = readU16((u8*)&encoded.c_str()[0]);
1849 s.append(&encoded.c_str()[2], s_size);
1853 // Reads a string with the length as the first two bytes
1854 inline std::string deSerializeString(std::istream &is)
1858 if(is.gcount() != 2)
1859 throw SerializationError("deSerializeString: size not read");
1860 u16 s_size = readU16((u8*)buf);
1863 Buffer<char> buf2(s_size);
1864 is.read(&buf2[0], s_size);
1867 s.append(&buf2[0], s_size);
1871 // Creates a string with the length as the first four bytes
1872 inline std::string serializeLongString(const std::string plain)
1875 writeU32((u8*)&buf[0], plain.size());
1882 // Reads a string with the length as the first four bytes
1883 inline std::string deSerializeLongString(const std::string encoded)
1885 u32 s_size = readU32((u8*)&encoded.c_str()[0]);
1888 s.append(&encoded.c_str()[2], s_size);
1892 // Reads a string with the length as the first four bytes
1893 inline std::string deSerializeLongString(std::istream &is)
1897 if(is.gcount() != 4)
1898 throw SerializationError("deSerializeLongString: size not read");
1899 u32 s_size = readU32((u8*)buf);
1902 Buffer<char> buf2(s_size);
1903 is.read(&buf2[0], s_size);
1906 s.append(&buf2[0], s_size);
1912 inline u32 time_to_daynight_ratio(u32 time_of_day)
1914 const s32 daylength = 16;
1915 const s32 nightlength = 6;
1916 const s32 daytimelength = 8;
1918 s32 t = (((time_of_day)%24000)/(24000/d));
1919 if(t < nightlength/2 || t >= d - nightlength/2)
1921 else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1927 // Random helper. Usually d=BS
1928 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1930 return core::aabbox3d<f32>(
1931 (float)p.X * d - 0.5*d,
1932 (float)p.Y * d - 0.5*d,
1933 (float)p.Z * d - 0.5*d,
1934 (float)p.X * d + 0.5*d,
1935 (float)p.Y * d + 0.5*d,
1936 (float)p.Z * d + 0.5*d