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(std::string s)
1054 return atoi(s.c_str());
1057 inline s32 mystoi(std::wstring s)
1059 return atoi(wide_to_narrow(s).c_str());
1062 inline float mystof(std::string s)
1065 std::istringstream ss(s);
1075 inline std::string itos(s32 i)
1077 std::ostringstream o;
1082 inline std::string ftos(float f)
1084 std::ostringstream o;
1089 inline void str_replace(std::string & str, std::string const & pattern,
1090 std::string const & replacement)
1092 std::string::size_type start = str.find(pattern, 0);
1093 while(start != str.npos)
1095 str.replace(start, pattern.size(), replacement);
1096 start = str.find(pattern, start+replacement.size());
1100 inline void str_replace_char(std::string & str, char from, char to)
1102 for(unsigned int i=0; i<str.size(); i++)
1110 A base class for simple background thread implementation
1113 class SimpleThread : public JThread
1127 virtual ~SimpleThread()
1130 virtual void * Thread() = 0;
1134 JMutexAutoLock lock(run_mutex);
1137 void setRun(bool a_run)
1139 JMutexAutoLock lock(run_mutex);
1152 FIFO queue (well, actually a FILO also)
1154 template<typename T>
1160 m_list.push_back(t);
1165 if(m_list.size() == 0)
1166 throw ItemNotFoundException("Queue: queue is empty");
1168 typename core::list<T>::Iterator begin = m_list.begin();
1170 m_list.erase(begin);
1175 if(m_list.size() == 0)
1176 throw ItemNotFoundException("Queue: queue is empty");
1178 typename core::list<T>::Iterator last = m_list.getLast();
1186 return m_list.size();
1190 core::list<T> m_list;
1194 Thread-safe FIFO queue (well, actually a FILO also)
1197 template<typename T>
1207 JMutexAutoLock lock(m_mutex);
1208 return m_list.size();
1212 JMutexAutoLock lock(m_mutex);
1213 m_list.push_back(t);
1215 T pop_front(u32 wait_time_max_ms=0)
1217 u32 wait_time_ms = 0;
1222 JMutexAutoLock lock(m_mutex);
1224 if(m_list.size() > 0)
1226 typename core::list<T>::Iterator begin = m_list.begin();
1228 m_list.erase(begin);
1232 if(wait_time_ms >= wait_time_max_ms)
1233 throw ItemNotFoundException("MutexedQueue: queue is empty");
1236 // Wait a while before trying again
1241 T pop_back(u32 wait_time_max_ms=0)
1243 u32 wait_time_ms = 0;
1248 JMutexAutoLock lock(m_mutex);
1250 if(m_list.size() > 0)
1252 typename core::list<T>::Iterator last = m_list.getLast();
1258 if(wait_time_ms >= wait_time_max_ms)
1259 throw ItemNotFoundException("MutexedQueue: queue is empty");
1262 // Wait a while before trying again
1273 core::list<T> & getList()
1280 core::list<T> m_list;
1284 A single worker thread - multiple client threads queue framework.
1287 template<typename Caller, typename Data>
1295 template<typename Key, typename T, typename Caller, typename CallerData>
1301 core::list<CallerInfo<Caller, CallerData> > callers;
1304 template<typename Key, typename T, typename Caller, typename CallerData>
1305 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1309 template<typename Key, typename T, typename Caller, typename CallerData>
1317 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1321 GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1332 ResultQueue<Key, T, Caller, CallerData> *dest;
1333 core::list<CallerInfo<Caller, CallerData> > callers;
1336 template<typename Key, typename T, typename Caller, typename CallerData>
1342 return m_queue.size();
1345 void add(Key key, Caller caller, CallerData callerdata,
1346 ResultQueue<Key, T, Caller, CallerData> *dest)
1348 JMutexAutoLock lock(m_queue.getMutex());
1351 If the caller is already on the list, only update CallerData
1353 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1354 i = m_queue.getList().begin();
1355 i != m_queue.getList().end(); i++)
1357 GetRequest<Key, T, Caller, CallerData> &request = *i;
1359 if(request.key == key)
1361 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1362 i = request.callers.begin();
1363 i != request.callers.end(); i++)
1365 CallerInfo<Caller, CallerData> &ca = *i;
1366 if(ca.caller == caller)
1368 ca.data = callerdata;
1372 CallerInfo<Caller, CallerData> ca;
1374 ca.data = callerdata;
1375 request.callers.push_back(ca);
1381 Else add a new request to the queue
1384 GetRequest<Key, T, Caller, CallerData> request;
1386 CallerInfo<Caller, CallerData> ca;
1388 ca.data = callerdata;
1389 request.callers.push_back(ca);
1390 request.dest = dest;
1392 m_queue.getList().push_back(request);
1395 GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1397 return m_queue.pop_front(wait_if_empty);
1401 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1405 Pseudo-random (VC++ rand() sucks)
1408 void mysrand(unsigned seed);
1409 #define MYRAND_MAX 32767
1411 int myrand_range(int min, int max);
1414 Miscellaneous functions
1417 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1418 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1421 Queue with unique values with fast checking of value existence
1424 template<typename Value>
1430 Does nothing if value is already queued.
1433 false: value already exists
1435 bool push_back(Value value)
1437 // Check if already exists
1438 if(m_map.find(value) != NULL)
1442 m_map.insert(value, 0);
1443 m_list.push_back(value);
1450 typename core::list<Value>::Iterator i = m_list.begin();
1452 m_map.remove(value);
1459 assert(m_list.size() == m_map.size());
1460 return m_list.size();
1464 core::map<Value, u8> m_map;
1465 core::list<Value> m_list;
1469 template<typename Key, typename Value>
1476 assert(m_mutex.IsInitialized());
1479 void set(const Key &name, const Value &value)
1481 JMutexAutoLock lock(m_mutex);
1483 m_values[name] = value;
1486 bool get(const Key &name, Value *result)
1488 JMutexAutoLock lock(m_mutex);
1490 typename core::map<Key, Value>::Node *n;
1491 n = m_values.find(name);
1497 *result = n->getValue();
1503 core::map<Key, Value> m_values;
1509 Generates ids for comparable values.
1510 Id=0 is reserved for "no value".
1513 - Returning value by id (very fast)
1514 - Returning id by value
1515 - Generating a new id for a value
1518 - Remove an id/value pair (is possible to implement but slow)
1520 template<typename T>
1521 class MutexedIdGenerator
1524 MutexedIdGenerator()
1527 assert(m_mutex.IsInitialized());
1530 // Returns true if found
1531 bool getValue(u32 id, T &value)
1535 JMutexAutoLock lock(m_mutex);
1536 if(m_id_to_value.size() < id)
1538 value = m_id_to_value[id-1];
1542 // If id exists for value, returns the id.
1543 // Otherwise generates an id for the value.
1544 u32 getId(const T &value)
1546 JMutexAutoLock lock(m_mutex);
1547 typename core::map<T, u32>::Node *n;
1548 n = m_value_to_id.find(value);
1550 return n->getValue();
1551 m_id_to_value.push_back(value);
1552 u32 new_id = m_id_to_value.size();
1553 m_value_to_id.insert(value, new_id);
1559 // Values are stored here at id-1 position (id 1 = [0])
1560 core::array<T> m_id_to_value;
1561 core::map<T, u32> m_value_to_id;
1565 Checks if a string contains only supplied characters
1567 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1569 for(u32 i=0; i<s.size(); i++)
1571 bool confirmed = false;
1572 for(u32 j=0; j<allowed_chars.size(); j++)
1574 if(s[i] == allowed_chars[j])
1580 if(confirmed == false)
1587 Forcefully wraps string into rows using \n
1588 (no word wrap, used for showing paths in gui)
1590 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1593 for(u32 i=0; i<from.size(); i++)
1595 if(i != 0 && i%rowlen == 0)
1605 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1606 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1609 Returns nearest 32-bit integer for given floating point number.
1610 <cmath> and <math.h> in VC++ don't provide round().
1612 inline s32 myround(f32 f)
1614 return floor(f + 0.5);
1618 Returns integer position of node in given floating point position
1620 inline v3s16 floatToInt(v3f p, f32 d)
1623 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1624 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1625 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1630 Returns floating point position of node in given integer position
1632 inline v3f intToFloat(v3s16 p, f32 d)
1643 More serialization stuff
1646 // Creates a string with the length as the first two bytes
1647 inline std::string serializeString(const std::string &plain)
1649 //assert(plain.size() <= 65535);
1650 if(plain.size() > 65535)
1651 throw SerializationError("String too long for serializeString");
1653 writeU16((u8*)&buf[0], plain.size());
1660 // Creates a string with the length as the first two bytes from wide string
1661 inline std::string serializeWideString(const std::wstring &plain)
1663 //assert(plain.size() <= 65535);
1664 if(plain.size() > 65535)
1665 throw SerializationError("String too long for serializeString");
1667 writeU16((u8*)buf, plain.size());
1670 for(u32 i=0; i<plain.size(); i++)
1672 writeU16((u8*)buf, plain[i]);
1678 // Reads a string with the length as the first two bytes
1679 inline std::string deSerializeString(std::istream &is)
1683 if(is.gcount() != 2)
1684 throw SerializationError("deSerializeString: size not read");
1685 u16 s_size = readU16((u8*)buf);
1688 Buffer<char> buf2(s_size);
1689 is.read(&buf2[0], s_size);
1692 s.append(&buf2[0], s_size);
1696 // Reads a wide string with the length as the first two bytes
1697 inline std::wstring deSerializeWideString(std::istream &is)
1701 if(is.gcount() != 2)
1702 throw SerializationError("deSerializeString: size not read");
1703 u16 s_size = readU16((u8*)buf);
1708 for(u32 i=0; i<s_size; i++)
1710 is.read(&buf[0], 2);
1711 wchar_t c16 = readU16((u8*)buf);
1717 // Creates a string with the length as the first four bytes
1718 inline std::string serializeLongString(const std::string &plain)
1721 writeU32((u8*)&buf[0], plain.size());
1728 // Reads a string with the length as the first four bytes
1729 inline std::string deSerializeLongString(std::istream &is)
1733 if(is.gcount() != 4)
1734 throw SerializationError("deSerializeLongString: size not read");
1735 u32 s_size = readU32((u8*)buf);
1738 Buffer<char> buf2(s_size);
1739 is.read(&buf2[0], s_size);
1742 s.append(&buf2[0], s_size);
1746 // Creates a string encoded in JSON format (almost equivalent to a C string literal)
1747 std::string serializeJsonString(const std::string &plain);
1749 // Reads a string encoded in JSON format
1750 std::string deSerializeJsonString(std::istream &is);
1754 inline u32 time_to_daynight_ratio(u32 time_of_day)
1756 s32 t = time_of_day%24000;
1757 if(t < 4500 || t >= 19500)
1759 else if(t < 5000 || t >= 19000)
1761 else if(t < 5500 || t >= 18500)
1763 else if(t < 6000 || t >= 18000)
1769 // Random helper. Usually d=BS
1770 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1772 return core::aabbox3d<f32>(
1773 (float)p.X * d - 0.5*d,
1774 (float)p.Y * d - 0.5*d,
1775 (float)p.Z * d - 0.5*d,
1776 (float)p.X * d + 0.5*d,
1777 (float)p.Y * d + 0.5*d,
1778 (float)p.Z * d + 0.5*d
1782 class IntervalLimiter
1790 dtime: time from last call to this method
1791 wanted_interval: interval wanted
1793 true: action should be skipped
1794 false: action should be done
1796 bool step(float dtime, float wanted_interval)
1798 m_accumulator += dtime;
1799 if(m_accumulator < wanted_interval)
1801 m_accumulator -= wanted_interval;
1805 float m_accumulator;
1809 Splits a list into "pages". For example, the list [1,2,3,4,5] split
1810 into two pages would be [1,2,3],[4,5]. This function computes the
1811 minimum and maximum indices of a single page.
1813 length: Length of the list that should be split
1814 page: Page number, 1 <= page <= pagecount
1815 pagecount: The number of pages, >= 1
1816 minindex: Receives the minimum index (inclusive).
1817 maxindex: Receives the maximum index (exclusive).
1819 Ensures 0 <= minindex <= maxindex <= length.
1821 inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex)
1823 if(length < 1 || pagecount < 1 || page < 1 || page > pagecount)
1825 // Special cases or invalid parameters
1826 minindex = maxindex = 0;
1828 else if(pagecount <= length)
1830 // Less pages than entries in the list:
1831 // Each page contains at least one entry
1832 minindex = (length * (page-1) + (pagecount-1)) / pagecount;
1833 maxindex = (length * page + (pagecount-1)) / pagecount;
1837 // More pages than entries in the list:
1838 // Make sure the empty pages are at the end
1852 std::string translatePassword(std::string playername, std::wstring password);
1854 enum PointedThingType
1856 POINTEDTHING_NOTHING,
1863 PointedThingType type;
1864 v3s16 node_undersurface;
1865 v3s16 node_abovesurface;
1869 std::string dump() const;
1870 void serialize(std::ostream &os) const;
1871 void deSerialize(std::istream &is);
1872 bool operator==(const PointedThing &pt2) const;
1873 bool operator!=(const PointedThing &pt2) const;