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>
33 #include "common_irrlicht.h"
35 #include "exceptions.h"
37 #include "strfnd.h" // For trim()
39 extern const v3s16 g_6dirs[6];
41 extern const v3s16 g_26dirs[26];
44 extern const v3s16 g_27dirs[27];
46 inline void writeU64(u8 *data, u64 i)
48 data[0] = ((i>>56)&0xff);
49 data[1] = ((i>>48)&0xff);
50 data[2] = ((i>>40)&0xff);
51 data[3] = ((i>>32)&0xff);
52 data[4] = ((i>>24)&0xff);
53 data[5] = ((i>>16)&0xff);
54 data[6] = ((i>> 8)&0xff);
55 data[7] = ((i>> 0)&0xff);
58 inline void writeU32(u8 *data, u32 i)
60 data[0] = ((i>>24)&0xff);
61 data[1] = ((i>>16)&0xff);
62 data[2] = ((i>> 8)&0xff);
63 data[3] = ((i>> 0)&0xff);
66 inline void writeU16(u8 *data, u16 i)
68 data[0] = ((i>> 8)&0xff);
69 data[1] = ((i>> 0)&0xff);
72 inline void writeU8(u8 *data, u8 i)
74 data[0] = ((i>> 0)&0xff);
77 inline u64 readU64(u8 *data)
79 return ((u64)data[0]<<56) | ((u64)data[1]<<48)
80 | ((u64)data[2]<<40) | ((u64)data[3]<<32)
81 | ((u64)data[4]<<24) | ((u64)data[5]<<16)
82 | ((u64)data[6]<<8) | ((u64)data[7]<<0);
85 inline u32 readU32(u8 *data)
87 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
90 inline u16 readU16(u8 *data)
92 return (data[0]<<8) | (data[1]<<0);
95 inline u8 readU8(u8 *data)
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 writeS8(u8 *data, s8 i){
115 writeU8(data, (u8)i);
117 inline s8 readS8(u8 *data){
118 return (s8)readU8(data);
121 inline void writeF1000(u8 *data, f32 i){
122 writeS32(data, i*1000);
124 inline f32 readF1000(u8 *data){
125 return (f32)readS32(data)/1000.;
128 inline void writeV3S32(u8 *data, v3s32 p)
130 writeS32(&data[0], p.X);
131 writeS32(&data[4], p.Y);
132 writeS32(&data[8], p.Z);
134 inline v3s32 readV3S32(u8 *data)
137 p.X = readS32(&data[0]);
138 p.Y = readS32(&data[4]);
139 p.Z = readS32(&data[8]);
143 inline void writeV3F1000(u8 *data, v3f p)
145 writeF1000(&data[0], p.X);
146 writeF1000(&data[4], p.Y);
147 writeF1000(&data[8], p.Z);
149 inline v3f readV3F1000(u8 *data)
152 p.X = (float)readF1000(&data[0]);
153 p.Y = (float)readF1000(&data[4]);
154 p.Z = (float)readF1000(&data[8]);
158 inline void writeV2F1000(u8 *data, v2f p)
160 writeF1000(&data[0], p.X);
161 writeF1000(&data[4], p.Y);
163 inline v2f readV2F1000(u8 *data)
166 p.X = (float)readF1000(&data[0]);
167 p.Y = (float)readF1000(&data[4]);
171 inline void writeV2S16(u8 *data, v2s16 p)
173 writeS16(&data[0], p.X);
174 writeS16(&data[2], p.Y);
177 inline v2s16 readV2S16(u8 *data)
180 p.X = readS16(&data[0]);
181 p.Y = readS16(&data[2]);
185 inline void writeV2S32(u8 *data, v2s32 p)
187 writeS32(&data[0], p.X);
188 writeS32(&data[2], p.Y);
191 inline v2s32 readV2S32(u8 *data)
194 p.X = readS32(&data[0]);
195 p.Y = readS32(&data[2]);
199 inline void writeV3S16(u8 *data, v3s16 p)
201 writeS16(&data[0], p.X);
202 writeS16(&data[2], p.Y);
203 writeS16(&data[4], p.Z);
206 inline v3s16 readV3S16(u8 *data)
209 p.X = readS16(&data[0]);
210 p.Y = readS16(&data[2]);
211 p.Z = readS16(&data[4]);
216 The above stuff directly interfaced to iostream
219 inline void writeU8(std::ostream &os, u8 p)
222 writeU8((u8*)buf, p);
225 inline u8 readU8(std::istream &is)
229 return readU8((u8*)buf);
232 inline void writeU16(std::ostream &os, u16 p)
235 writeU16((u8*)buf, p);
238 inline u16 readU16(std::istream &is)
242 return readU16((u8*)buf);
245 inline void writeU32(std::ostream &os, u32 p)
248 writeU32((u8*)buf, p);
251 inline u32 readU32(std::istream &is)
255 return readU32((u8*)buf);
258 inline void writeS32(std::ostream &os, s32 p)
261 writeS32((u8*)buf, p);
264 inline s32 readS32(std::istream &is)
268 return readS32((u8*)buf);
271 inline void writeS16(std::ostream &os, s16 p)
274 writeS16((u8*)buf, p);
277 inline s16 readS16(std::istream &is)
281 return readS16((u8*)buf);
284 inline void writeS8(std::ostream &os, s8 p)
287 writeS8((u8*)buf, p);
290 inline s8 readS8(std::istream &is)
294 return readS8((u8*)buf);
297 inline void writeF1000(std::ostream &os, f32 p)
300 writeF1000((u8*)buf, p);
303 inline f32 readF1000(std::istream &is)
307 return readF1000((u8*)buf);
310 inline void writeV3F1000(std::ostream &os, v3f p)
313 writeV3F1000((u8*)buf, p);
316 inline v3f readV3F1000(std::istream &is)
320 return readV3F1000((u8*)buf);
323 inline void writeV2F1000(std::ostream &os, v2f p)
326 writeV2F1000((u8*)buf, p);
329 inline v2f readV2F1000(std::istream &is)
333 return readV2F1000((u8*)buf);
336 inline void writeV2S16(std::ostream &os, v2s16 p)
339 writeV2S16((u8*)buf, p);
342 inline v2s16 readV2S16(std::istream &is)
346 return readV2S16((u8*)buf);
349 inline void writeV3S16(std::ostream &os, v3s16 p)
352 writeV3S16((u8*)buf, p);
355 inline v3s16 readV3S16(std::istream &is)
359 return readV3S16((u8*)buf);
363 None of these are used at the moment
366 template <typename T>
376 SharedPtr(SharedPtr<T> &t)
380 refcount = t.refcount;
388 SharedPtr<T> & operator=(T *t)
396 SharedPtr<T> & operator=(SharedPtr<T> &t)
399 refcount = t.refcount;
412 bool operator!=(T *t)
416 bool operator==(T *t)
420 T & operator[](unsigned int i)
427 assert((*refcount) > 0);
440 template <typename T>
449 Buffer(unsigned int size)
457 Buffer(const Buffer &buffer)
459 m_size = buffer.m_size;
462 data = new T[buffer.m_size];
463 memcpy(data, buffer.data, buffer.m_size);
468 Buffer(const T *t, unsigned int size)
474 memcpy(data, t, size);
483 Buffer& operator=(const Buffer &buffer)
488 m_size = buffer.m_size;
491 data = new T[buffer.m_size];
492 memcpy(data, buffer.data, buffer.m_size);
498 T & operator[](unsigned int i) const
502 T * operator*() const
506 unsigned int getSize() const
520 template <typename T>
528 refcount = new unsigned int;
531 SharedBuffer(unsigned int size)
535 data = new T[m_size];
538 refcount = new unsigned int;
541 SharedBuffer(const SharedBuffer &buffer)
543 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
544 m_size = buffer.m_size;
546 refcount = buffer.refcount;
549 SharedBuffer & operator=(const SharedBuffer & buffer)
551 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
555 m_size = buffer.m_size;
557 refcount = buffer.refcount;
564 SharedBuffer(T *t, unsigned int size)
569 data = new T[m_size];
570 memcpy(data, t, m_size);
574 refcount = new unsigned int;
580 SharedBuffer(const Buffer<T> &buffer)
582 m_size = buffer.getSize();
585 data = new T[m_size];
586 memcpy(data, *buffer, buffer.getSize());
590 refcount = new unsigned int;
597 T & operator[](unsigned int i) const
602 T * operator*() const
606 unsigned int getSize() const
610 operator Buffer<T>() const
612 return Buffer<T>(data, m_size);
617 assert((*refcount) > 0);
628 unsigned int *refcount;
631 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
633 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
638 class MutexedVariable
641 MutexedVariable(T value):
649 JMutexAutoLock lock(m_mutex);
655 JMutexAutoLock lock(m_mutex);
659 // You'll want to grab this in a SharedPtr
660 JMutexAutoLock * getLock()
662 return new JMutexAutoLock(m_mutex);
665 // You pretty surely want to grab the lock when accessing this
679 TimeTaker(const char *name, u32 *result=NULL);
686 u32 stop(bool quiet=false);
697 // Tests if two strings are equal, optionally case insensitive
698 inline bool str_equal(const std::wstring& s1, const std::wstring& s2,
699 bool case_insensitive = false)
703 if(s1.size() != s2.size())
705 for(size_t i = 0; i < s1.size(); ++i)
706 if(tolower(s1[i]) != tolower(s2[i]))
716 // Tests if the second string is a prefix of the first, optionally case insensitive
717 inline bool str_starts_with(const std::wstring& str, const std::wstring& prefix,
718 bool case_insensitive = false)
720 if(str.size() < prefix.size())
724 for(size_t i = 0; i < prefix.size(); ++i)
725 if(tolower(str[i]) != tolower(prefix[i]))
730 for(size_t i = 0; i < prefix.size(); ++i)
731 if(str[i] != prefix[i])
737 // Calculates the borders of a "d-radius" cube
738 inline void getFacePositions(core::list<v3s16> &list, u16 d)
742 list.push_back(v3s16(0,0,0));
748 This is an optimized sequence of coordinates.
750 list.push_back(v3s16( 0, 1, 0)); // top
751 list.push_back(v3s16( 0, 0, 1)); // back
752 list.push_back(v3s16(-1, 0, 0)); // left
753 list.push_back(v3s16( 1, 0, 0)); // right
754 list.push_back(v3s16( 0, 0,-1)); // front
755 list.push_back(v3s16( 0,-1, 0)); // bottom
757 list.push_back(v3s16(-1, 0, 1)); // back left
758 list.push_back(v3s16( 1, 0, 1)); // back right
759 list.push_back(v3s16(-1, 0,-1)); // front left
760 list.push_back(v3s16( 1, 0,-1)); // front right
761 list.push_back(v3s16(-1,-1, 0)); // bottom left
762 list.push_back(v3s16( 1,-1, 0)); // bottom right
763 list.push_back(v3s16( 0,-1, 1)); // bottom back
764 list.push_back(v3s16( 0,-1,-1)); // bottom front
765 list.push_back(v3s16(-1, 1, 0)); // top left
766 list.push_back(v3s16( 1, 1, 0)); // top right
767 list.push_back(v3s16( 0, 1, 1)); // top back
768 list.push_back(v3s16( 0, 1,-1)); // top front
770 list.push_back(v3s16(-1, 1, 1)); // top back-left
771 list.push_back(v3s16( 1, 1, 1)); // top back-right
772 list.push_back(v3s16(-1, 1,-1)); // top front-left
773 list.push_back(v3s16( 1, 1,-1)); // top front-right
774 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
775 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
776 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
777 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
782 // Take blocks in all sides, starting from y=0 and going +-y
783 for(s16 y=0; y<=d-1; y++)
785 // Left and right side, including borders
786 for(s16 z=-d; z<=d; z++)
788 list.push_back(v3s16(d,y,z));
789 list.push_back(v3s16(-d,y,z));
792 list.push_back(v3s16(d,-y,z));
793 list.push_back(v3s16(-d,-y,z));
796 // Back and front side, excluding borders
797 for(s16 x=-d+1; x<=d-1; x++)
799 list.push_back(v3s16(x,y,d));
800 list.push_back(v3s16(x,y,-d));
803 list.push_back(v3s16(x,-y,d));
804 list.push_back(v3s16(x,-y,-d));
809 // Take the bottom and top face with borders
810 // -d<x<d, y=+-d, -d<z<d
811 for(s16 x=-d; x<=d; x++)
812 for(s16 z=-d; z<=d; z++)
814 list.push_back(v3s16(x,-d,z));
815 list.push_back(v3s16(x,d,z));
819 class IndentationRaiser
822 IndentationRaiser(u16 *indentation)
824 m_indentation = indentation;
835 inline s16 getContainerPos(s16 p, s16 d)
837 return (p>=0 ? p : p-d+1) / d;
840 inline v2s16 getContainerPos(v2s16 p, s16 d)
843 getContainerPos(p.X, d),
844 getContainerPos(p.Y, d)
848 inline v3s16 getContainerPos(v3s16 p, s16 d)
851 getContainerPos(p.X, d),
852 getContainerPos(p.Y, d),
853 getContainerPos(p.Z, d)
857 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
860 getContainerPos(p.X, d.X),
861 getContainerPos(p.Y, d.Y)
865 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
868 getContainerPos(p.X, d.X),
869 getContainerPos(p.Y, d.Y),
870 getContainerPos(p.Z, d.Z)
874 inline bool isInArea(v3s16 p, s16 d)
877 p.X >= 0 && p.X < d &&
878 p.Y >= 0 && p.Y < d &&
883 inline bool isInArea(v2s16 p, s16 d)
886 p.X >= 0 && p.X < d &&
891 inline bool isInArea(v3s16 p, v3s16 d)
894 p.X >= 0 && p.X < d.X &&
895 p.Y >= 0 && p.Y < d.Y &&
896 p.Z >= 0 && p.Z < d.Z
900 inline s16 rangelim(s16 i, s16 max)
909 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
911 inline v3s16 arealim(v3s16 p, s16 d)
928 inline std::wstring narrow_to_wide(const std::string& mbs)
930 size_t wcl = mbs.size();
931 Buffer<wchar_t> wcs(wcl+1);
932 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
933 if(l == (size_t)(-1))
934 return L"<invalid multibyte string>";
939 inline std::string wide_to_narrow(const std::wstring& wcs)
941 size_t mbl = wcs.size()*4;
942 SharedBuffer<char> mbs(mbl+1);
943 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
944 if(l == (size_t)(-1))
951 // Split a string using the given delimiter. Returns a vector containing
952 // the component parts.
953 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
955 std::vector<std::wstring> parts;
956 std::wstringstream sstr(str);
958 while(std::getline(sstr, part, delimiter))
959 parts.push_back(part);
965 See test.cpp for example cases.
966 wraps degrees to the range of -360...360
967 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
969 inline float wrapDegrees(float f)
971 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
977 // NOTE: This would be used for wrapping to 0...360
983 // 10, 0.5, -0.5, -0.5
988 /* Wrap to 0...360 */
989 inline float wrapDegrees_0_360(float f)
991 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
1003 // 10, 0.5, -0.5, -0.5
1008 /* Wrap to -180...180 */
1009 inline float wrapDegrees_180(float f)
1012 f = wrapDegrees_0_360(f);
1017 inline std::string lowercase(const std::string &s)
1020 for(size_t i=0; i<s.size(); i++)
1023 if(c >= 'A' && c <= 'Z')
1030 inline bool is_yes(const std::string &s)
1032 std::string s2 = lowercase(trim(s));
1033 if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
1038 inline s32 mystoi(const std::string &s, s32 min, s32 max)
1040 s32 i = atoi(s.c_str());
1049 // MSVC2010 includes it's own versions of these
1050 //#if !defined(_MSC_VER) || _MSC_VER < 1600
1052 inline s32 mystoi(const std::string &s)
1054 return atoi(s.c_str());
1057 inline s32 mystoi(const std::wstring &s)
1059 return atoi(wide_to_narrow(s).c_str());
1062 inline float mystof(const std::string &s)
1064 // This crap causes a segfault in certain cases on MinGW
1066 std::istringstream ss(s);
1069 // This works in that case
1070 return atof(s.c_str());
1078 inline std::string itos(s32 i)
1080 std::ostringstream o;
1085 inline std::string ftos(float f)
1087 std::ostringstream o;
1092 inline void str_replace(std::string & str, std::string const & pattern,
1093 std::string const & replacement)
1095 std::string::size_type start = str.find(pattern, 0);
1096 while(start != str.npos)
1098 str.replace(start, pattern.size(), replacement);
1099 start = str.find(pattern, start+replacement.size());
1103 inline void str_replace_char(std::string & str, char from, char to)
1105 for(unsigned int i=0; i<str.size(); i++)
1113 A base class for simple background thread implementation
1116 class SimpleThread : public JThread
1130 virtual ~SimpleThread()
1133 virtual void * Thread() = 0;
1137 JMutexAutoLock lock(run_mutex);
1140 void setRun(bool a_run)
1142 JMutexAutoLock lock(run_mutex);
1155 FIFO queue (well, actually a FILO also)
1157 template<typename T>
1163 m_list.push_back(t);
1168 if(m_list.size() == 0)
1169 throw ItemNotFoundException("Queue: queue is empty");
1171 typename core::list<T>::Iterator begin = m_list.begin();
1173 m_list.erase(begin);
1178 if(m_list.size() == 0)
1179 throw ItemNotFoundException("Queue: queue is empty");
1181 typename core::list<T>::Iterator last = m_list.getLast();
1189 return m_list.size();
1193 core::list<T> m_list;
1197 Thread-safe FIFO queue (well, actually a FILO also)
1200 template<typename T>
1210 JMutexAutoLock lock(m_mutex);
1211 return m_list.size();
1215 JMutexAutoLock lock(m_mutex);
1216 m_list.push_back(t);
1218 T pop_front(u32 wait_time_max_ms=0)
1220 u32 wait_time_ms = 0;
1225 JMutexAutoLock lock(m_mutex);
1227 if(m_list.size() > 0)
1229 typename core::list<T>::Iterator begin = m_list.begin();
1231 m_list.erase(begin);
1235 if(wait_time_ms >= wait_time_max_ms)
1236 throw ItemNotFoundException("MutexedQueue: queue is empty");
1239 // Wait a while before trying again
1244 T pop_back(u32 wait_time_max_ms=0)
1246 u32 wait_time_ms = 0;
1251 JMutexAutoLock lock(m_mutex);
1253 if(m_list.size() > 0)
1255 typename core::list<T>::Iterator last = m_list.getLast();
1261 if(wait_time_ms >= wait_time_max_ms)
1262 throw ItemNotFoundException("MutexedQueue: queue is empty");
1265 // Wait a while before trying again
1276 core::list<T> & getList()
1283 core::list<T> m_list;
1287 A single worker thread - multiple client threads queue framework.
1290 template<typename Caller, typename Data>
1298 template<typename Key, typename T, typename Caller, typename CallerData>
1304 core::list<CallerInfo<Caller, CallerData> > callers;
1307 template<typename Key, typename T, typename Caller, typename CallerData>
1308 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1312 template<typename Key, typename T, typename Caller, typename CallerData>
1320 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1324 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1335 ResultQueue<Key, T, Caller, CallerData> *dest;
1336 core::list<CallerInfo<Caller, CallerData> > callers;
1339 template<typename Key, typename T, typename Caller, typename CallerData>
1345 return m_queue.size();
1348 void add(Key key, Caller caller, CallerData callerdata,
1349 ResultQueue<Key, T, Caller, CallerData> *dest)
1351 JMutexAutoLock lock(m_queue.getMutex());
1354 If the caller is already on the list, only update CallerData
1356 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1357 i = m_queue.getList().begin();
1358 i != m_queue.getList().end(); i++)
1360 GetRequest<Key, T, Caller, CallerData> &request = *i;
1362 if(request.key == key)
1364 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1365 i = request.callers.begin();
1366 i != request.callers.end(); i++)
1368 CallerInfo<Caller, CallerData> &ca = *i;
1369 if(ca.caller == caller)
1371 ca.data = callerdata;
1375 CallerInfo<Caller, CallerData> ca;
1377 ca.data = callerdata;
1378 request.callers.push_back(ca);
1384 Else add a new request to the queue
1387 GetRequest<Key, T, Caller, CallerData> request;
1389 CallerInfo<Caller, CallerData> ca;
1391 ca.data = callerdata;
1392 request.callers.push_back(ca);
1393 request.dest = dest;
1395 m_queue.getList().push_back(request);
1398 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1400 return m_queue.pop_front(wait_if_empty);
1404 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1408 Pseudo-random (VC++ rand() sucks)
1411 void mysrand(unsigned seed);
1412 #define MYRAND_MAX 32767
1414 int myrand_range(int min, int max);
1417 Miscellaneous functions
1420 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1421 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1424 Queue with unique values with fast checking of value existence
1427 template<typename Value>
1433 Does nothing if value is already queued.
1436 false: value already exists
1438 bool push_back(Value value)
1440 // Check if already exists
1441 if(m_map.find(value) != NULL)
1445 m_map.insert(value, 0);
1446 m_list.push_back(value);
1453 typename core::list<Value>::Iterator i = m_list.begin();
1455 m_map.remove(value);
1462 assert(m_list.size() == m_map.size());
1463 return m_list.size();
1467 core::map<Value, u8> m_map;
1468 core::list<Value> m_list;
1472 template<typename Key, typename Value>
1479 assert(m_mutex.IsInitialized());
1482 void set(const Key &name, const Value &value)
1484 JMutexAutoLock lock(m_mutex);
1486 m_values[name] = value;
1489 bool get(const Key &name, Value *result)
1491 JMutexAutoLock lock(m_mutex);
1493 typename core::map<Key, Value>::Node *n;
1494 n = m_values.find(name);
1500 *result = n->getValue();
1506 core::map<Key, Value> m_values;
1512 Generates ids for comparable values.
1513 Id=0 is reserved for "no value".
1516 - Returning value by id (very fast)
1517 - Returning id by value
1518 - Generating a new id for a value
1521 - Remove an id/value pair (is possible to implement but slow)
1523 template<typename T>
1524 class MutexedIdGenerator
1527 MutexedIdGenerator()
1530 assert(m_mutex.IsInitialized());
1533 // Returns true if found
1534 bool getValue(u32 id, T &value)
1538 JMutexAutoLock lock(m_mutex);
1539 if(m_id_to_value.size() < id)
1541 value = m_id_to_value[id-1];
1545 // If id exists for value, returns the id.
1546 // Otherwise generates an id for the value.
1547 u32 getId(const T &value)
1549 JMutexAutoLock lock(m_mutex);
1550 typename core::map<T, u32>::Node *n;
1551 n = m_value_to_id.find(value);
1553 return n->getValue();
1554 m_id_to_value.push_back(value);
1555 u32 new_id = m_id_to_value.size();
1556 m_value_to_id.insert(value, new_id);
1562 // Values are stored here at id-1 position (id 1 = [0])
1563 core::array<T> m_id_to_value;
1564 core::map<T, u32> m_value_to_id;
1568 Checks if a string contains only supplied characters
1570 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1572 for(u32 i=0; i<s.size(); i++)
1574 bool confirmed = false;
1575 for(u32 j=0; j<allowed_chars.size(); j++)
1577 if(s[i] == allowed_chars[j])
1583 if(confirmed == false)
1590 Forcefully wraps string into rows using \n
1591 (no word wrap, used for showing paths in gui)
1593 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1596 for(u32 i=0; i<from.size(); i++)
1598 if(i != 0 && i%rowlen == 0)
1608 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1609 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1612 Returns nearest 32-bit integer for given floating point number.
1613 <cmath> and <math.h> in VC++ don't provide round().
1615 inline s32 myround(f32 f)
1617 return floor(f + 0.5);
1621 Returns integer position of node in given floating point position
1623 inline v3s16 floatToInt(v3f p, f32 d)
1626 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1627 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1628 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1633 Returns floating point position of node in given integer position
1635 inline v3f intToFloat(v3s16 p, f32 d)
1646 More serialization stuff
1649 // Creates a string with the length as the first two bytes
1650 inline std::string serializeString(const std::string &plain)
1652 //assert(plain.size() <= 65535);
1653 if(plain.size() > 65535)
1654 throw SerializationError("String too long for serializeString");
1656 writeU16((u8*)&buf[0], plain.size());
1663 // Creates a string with the length as the first two bytes from wide string
1664 inline std::string serializeWideString(const std::wstring &plain)
1666 //assert(plain.size() <= 65535);
1667 if(plain.size() > 65535)
1668 throw SerializationError("String too long for serializeString");
1670 writeU16((u8*)buf, plain.size());
1673 for(u32 i=0; i<plain.size(); i++)
1675 writeU16((u8*)buf, plain[i]);
1681 // Reads a string with the length as the first two bytes
1682 inline std::string deSerializeString(std::istream &is)
1686 if(is.gcount() != 2)
1687 throw SerializationError("deSerializeString: size not read");
1688 u16 s_size = readU16((u8*)buf);
1691 Buffer<char> buf2(s_size);
1692 is.read(&buf2[0], s_size);
1695 s.append(&buf2[0], s_size);
1699 // Reads a wide string with the length as the first two bytes
1700 inline std::wstring deSerializeWideString(std::istream &is)
1704 if(is.gcount() != 2)
1705 throw SerializationError("deSerializeString: size not read");
1706 u16 s_size = readU16((u8*)buf);
1711 for(u32 i=0; i<s_size; i++)
1713 is.read(&buf[0], 2);
1714 wchar_t c16 = readU16((u8*)buf);
1720 // Creates a string with the length as the first four bytes
1721 inline std::string serializeLongString(const std::string &plain)
1724 writeU32((u8*)&buf[0], plain.size());
1731 // Reads a string with the length as the first four bytes
1732 inline std::string deSerializeLongString(std::istream &is)
1736 if(is.gcount() != 4)
1737 throw SerializationError("deSerializeLongString: size not read");
1738 u32 s_size = readU32((u8*)buf);
1741 Buffer<char> buf2(s_size);
1742 is.read(&buf2[0], s_size);
1745 s.append(&buf2[0], s_size);
1749 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
1750 std::string serializeJsonString(const std::string &plain);
1752 // Reads a string encoded in JSON format
1753 std::string deSerializeJsonString(std::istream &is);
1757 // Random helper. Usually d=BS
1758 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1760 return core::aabbox3d<f32>(
1761 (float)p.X * d - 0.5*d,
1762 (float)p.Y * d - 0.5*d,
1763 (float)p.Z * d - 0.5*d,
1764 (float)p.X * d + 0.5*d,
1765 (float)p.Y * d + 0.5*d,
1766 (float)p.Z * d + 0.5*d
1770 class IntervalLimiter
1778 dtime: time from last call to this method
1779 wanted_interval: interval wanted
1781 true: action should be skipped
1782 false: action should be done
1784 bool step(float dtime, float wanted_interval)
1786 m_accumulator += dtime;
1787 if(m_accumulator < wanted_interval)
1789 m_accumulator -= wanted_interval;
1793 float m_accumulator;
1797 Splits a list into "pages". For example, the list [1,2,3,4,5] split
1798 into two pages would be [1,2,3],[4,5]. This function computes the
1799 minimum and maximum indices of a single page.
1801 length: Length of the list that should be split
1802 page: Page number, 1 <= page <= pagecount
1803 pagecount: The number of pages, >= 1
1804 minindex: Receives the minimum index (inclusive).
1805 maxindex: Receives the maximum index (exclusive).
1807 Ensures 0 <= minindex <= maxindex <= length.
1809 inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
1811 if(length < 1 || pagecount < 1 || page < 1 || page > pagecount)
1813 // Special cases or invalid parameters
1814 minindex = maxindex = 0;
1816 else if(pagecount <= length)
1818 // Less pages than entries in the list:
1819 // Each page contains at least one entry
1820 minindex = (length * (page-1) + (pagecount-1)) / pagecount;
1821 maxindex = (length * page + (pagecount-1)) / pagecount;
1825 // More pages than entries in the list:
1826 // Make sure the empty pages are at the end
1840 std::string translatePassword(std::string playername, std::wstring password);
1842 enum PointedThingType
1844 POINTEDTHING_NOTHING,
1851 PointedThingType type;
1852 v3s16 node_undersurface;
1853 v3s16 node_abovesurface;
1857 std::string dump() const;
1858 void serialize(std::ostream &os) const;
1859 void deSerialize(std::istream &is);
1860 bool operator==(const PointedThing &pt2) const;
1861 bool operator!=(const PointedThing &pt2) const;