]> git.lizzy.rs Git - dragonfireclient.git/blob - src/utility.h
Use the logger; also, default to not showing much crap in console. Use --info-on...
[dragonfireclient.git] / src / utility.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #ifndef UTILITY_HEADER
21 #define UTILITY_HEADER
22
23 #include <iostream>
24 #include <fstream>
25 #include <string>
26 #include <sstream>
27 #include <vector>
28 #include <jthread.h>
29 #include <jmutex.h>
30 #include <jmutexautolock.h>
31 #include <cstring>
32
33 #include "common_irrlicht.h"
34 #include "debug.h"
35 #include "strfnd.h"
36 #include "exceptions.h"
37 #include "porting.h"
38
39 extern const v3s16 g_6dirs[6];
40
41 extern const v3s16 g_26dirs[26];
42
43 // 26th is (0,0,0)
44 extern const v3s16 g_27dirs[27];
45
46 inline void writeU64(u8 *data, u64 i)
47 {
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);
56 }
57
58 inline void writeU32(u8 *data, u32 i)
59 {
60         data[0] = ((i>>24)&0xff);
61         data[1] = ((i>>16)&0xff);
62         data[2] = ((i>> 8)&0xff);
63         data[3] = ((i>> 0)&0xff);
64 }
65
66 inline void writeU16(u8 *data, u16 i)
67 {
68         data[0] = ((i>> 8)&0xff);
69         data[1] = ((i>> 0)&0xff);
70 }
71
72 inline void writeU8(u8 *data, u8 i)
73 {
74         data[0] = ((i>> 0)&0xff);
75 }
76
77 inline u64 readU64(u8 *data)
78 {
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);
83 }
84
85 inline u32 readU32(u8 *data)
86 {
87         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
88 }
89
90 inline u16 readU16(u8 *data)
91 {
92         return (data[0]<<8) | (data[1]<<0);
93 }
94
95 inline u8 readU8(u8 *data)
96 {
97         return (data[0]<<0);
98 }
99
100 inline void writeS32(u8 *data, s32 i){
101         writeU32(data, (u32)i);
102 }
103 inline s32 readS32(u8 *data){
104         return (s32)readU32(data);
105 }
106
107 inline void writeF1000(u8 *data, f32 i){
108         writeS32(data, i*1000);
109 }
110 inline f32 readF1000(u8 *data){
111         return (f32)readS32(data)/1000.;
112 }
113
114 inline void writeS16(u8 *data, s16 i){
115         writeU16(data, (u16)i);
116 }
117 inline s16 readS16(u8 *data){
118         return (s16)readU16(data);
119 }
120
121 inline void writeV3S32(u8 *data, v3s32 p)
122 {
123         writeS32(&data[0], p.X);
124         writeS32(&data[4], p.Y);
125         writeS32(&data[8], p.Z);
126 }
127 inline v3s32 readV3S32(u8 *data)
128 {
129         v3s32 p;
130         p.X = readS32(&data[0]);
131         p.Y = readS32(&data[4]);
132         p.Z = readS32(&data[8]);
133         return p;
134 }
135
136 inline void writeV3F1000(u8 *data, v3f p)
137 {
138         writeF1000(&data[0], p.X);
139         writeF1000(&data[4], p.Y);
140         writeF1000(&data[8], p.Z);
141 }
142 inline v3f readV3F1000(u8 *data)
143 {
144         v3f p;
145         p.X = (float)readF1000(&data[0]);
146         p.Y = (float)readF1000(&data[4]);
147         p.Z = (float)readF1000(&data[8]);
148         return p;
149 }
150
151 inline void writeV2S16(u8 *data, v2s16 p)
152 {
153         writeS16(&data[0], p.X);
154         writeS16(&data[2], p.Y);
155 }
156
157 inline v2s16 readV2S16(u8 *data)
158 {
159         v2s16 p;
160         p.X = readS16(&data[0]);
161         p.Y = readS16(&data[2]);
162         return p;
163 }
164
165 inline void writeV2S32(u8 *data, v2s32 p)
166 {
167         writeS32(&data[0], p.X);
168         writeS32(&data[2], p.Y);
169 }
170
171 inline v2s32 readV2S32(u8 *data)
172 {
173         v2s32 p;
174         p.X = readS32(&data[0]);
175         p.Y = readS32(&data[2]);
176         return p;
177 }
178
179 inline void writeV3S16(u8 *data, v3s16 p)
180 {
181         writeS16(&data[0], p.X);
182         writeS16(&data[2], p.Y);
183         writeS16(&data[4], p.Z);
184 }
185
186 inline v3s16 readV3S16(u8 *data)
187 {
188         v3s16 p;
189         p.X = readS16(&data[0]);
190         p.Y = readS16(&data[2]);
191         p.Z = readS16(&data[4]);
192         return p;
193 }
194
195 /*
196         The above stuff directly interfaced to iostream
197 */
198
199 inline void writeU8(std::ostream &os, u8 p)
200 {
201         char buf[1];
202         writeU8((u8*)buf, p);
203         os.write(buf, 1);
204 }
205 inline u8 readU8(std::istream &is)
206 {
207         char buf[1];
208         is.read(buf, 1);
209         return readU8((u8*)buf);
210 }
211
212 inline void writeU16(std::ostream &os, u16 p)
213 {
214         char buf[2];
215         writeU16((u8*)buf, p);
216         os.write(buf, 2);
217 }
218 inline u16 readU16(std::istream &is)
219 {
220         char buf[2];
221         is.read(buf, 2);
222         return readU16((u8*)buf);
223 }
224
225 inline void writeU32(std::ostream &os, u16 p)
226 {
227         char buf[4];
228         writeU16((u8*)buf, p);
229         os.write(buf, 4);
230 }
231 inline u16 readU32(std::istream &is)
232 {
233         char buf[4];
234         is.read(buf, 4);
235         return readU32((u8*)buf);
236 }
237
238 inline void writeF1000(std::ostream &os, f32 p)
239 {
240         char buf[4];
241         writeF1000((u8*)buf, p);
242         os.write(buf, 4);
243 }
244 inline f32 readF1000(std::istream &is)
245 {
246         char buf[4];
247         is.read(buf, 4);
248         return readF1000((u8*)buf);
249 }
250
251 inline void writeV3F1000(std::ostream &os, v3f p)
252 {
253         char buf[12];
254         writeV3F1000((u8*)buf, p);
255         os.write(buf, 12);
256 }
257 inline v3f readV3F1000(std::istream &is)
258 {
259         char buf[12];
260         is.read(buf, 12);
261         return readV3F1000((u8*)buf);
262 }
263
264 /*
265         None of these are used at the moment
266 */
267
268 template <typename T>
269 class SharedPtr
270 {
271 public:
272         SharedPtr(T *t=NULL)
273         {
274                 refcount = new int;
275                 *refcount = 1;
276                 ptr = t;
277         }
278         SharedPtr(SharedPtr<T> &t)
279         {
280                 //*this = t;
281                 drop();
282                 refcount = t.refcount;
283                 (*refcount)++;
284                 ptr = t.ptr;
285         }
286         ~SharedPtr()
287         {
288                 drop();
289         }
290         SharedPtr<T> & operator=(T *t)
291         {
292                 drop();
293                 refcount = new int;
294                 *refcount = 1;
295                 ptr = t;
296                 return *this;
297         }
298         SharedPtr<T> & operator=(SharedPtr<T> &t)
299         {
300                 drop();
301                 refcount = t.refcount;
302                 (*refcount)++;
303                 ptr = t.ptr;
304                 return *this;
305         }
306         T* operator->()
307         {
308                 return ptr;
309         }
310         T & operator*()
311         {
312                 return *ptr;
313         }
314         bool operator!=(T *t)
315         {
316                 return ptr != t;
317         }
318         bool operator==(T *t)
319         {
320                 return ptr == t;
321         }
322         T & operator[](unsigned int i)
323         {
324                 return ptr[i];
325         }
326 private:
327         void drop()
328         {
329                 assert((*refcount) > 0);
330                 (*refcount)--;
331                 if(*refcount == 0)
332                 {
333                         delete refcount;
334                         if(ptr != NULL)
335                                 delete ptr;
336                 }
337         }
338         T *ptr;
339         int *refcount;
340 };
341
342 template <typename T>
343 class Buffer
344 {
345 public:
346         Buffer(unsigned int size)
347         {
348                 m_size = size;
349                 data = new T[size];
350         }
351         Buffer(const Buffer &buffer)
352         {
353                 m_size = buffer.m_size;
354                 data = new T[buffer.m_size];
355                 memcpy(data, buffer.data, buffer.m_size);
356         }
357         Buffer(T *t, unsigned int size)
358         {
359                 m_size = size;
360                 data = new T[size];
361                 memcpy(data, t, size);
362         }
363         ~Buffer()
364         {
365                 delete[] data;
366         }
367         T & operator[](unsigned int i) const
368         {
369                 return data[i];
370         }
371         T * operator*() const
372         {
373                 return data;
374         }
375         unsigned int getSize() const
376         {
377                 return m_size;
378         }
379 private:
380         T *data;
381         unsigned int m_size;
382 };
383
384 template <typename T>
385 class SharedBuffer
386 {
387 public:
388         SharedBuffer()
389         {
390                 m_size = 0;
391                 data = NULL;
392                 refcount = new unsigned int;
393                 (*refcount) = 1;
394         }
395         SharedBuffer(unsigned int size)
396         {
397                 m_size = size;
398                 if(m_size != 0)
399                         data = new T[m_size];
400                 else
401                         data = NULL;
402                 refcount = new unsigned int;
403                 (*refcount) = 1;
404         }
405         SharedBuffer(const SharedBuffer &buffer)
406         {
407                 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
408                 m_size = buffer.m_size;
409                 data = buffer.data;
410                 refcount = buffer.refcount;
411                 (*refcount)++;
412         }
413         SharedBuffer & operator=(const SharedBuffer & buffer)
414         {
415                 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
416                 if(this == &buffer)
417                         return *this;
418                 drop();
419                 m_size = buffer.m_size;
420                 data = buffer.data;
421                 refcount = buffer.refcount;
422                 (*refcount)++;
423                 return *this;
424         }
425         /*
426                 Copies whole buffer
427         */
428         SharedBuffer(T *t, unsigned int size)
429         {
430                 m_size = size;
431                 if(m_size != 0)
432                 {
433                         data = new T[m_size];
434                         memcpy(data, t, m_size);
435                 }
436                 else
437                         data = NULL;
438                 refcount = new unsigned int;
439                 (*refcount) = 1;
440         }
441         /*
442                 Copies whole buffer
443         */
444         SharedBuffer(const Buffer<T> &buffer)
445         {
446                 m_size = buffer.getSize();
447                 if(m_size != 0)
448                 {
449                         data = new T[m_size];
450                         memcpy(data, *buffer, buffer.getSize());
451                 }
452                 else
453                         data = NULL;
454                 refcount = new unsigned int;
455                 (*refcount) = 1;
456         }
457         ~SharedBuffer()
458         {
459                 drop();
460         }
461         T & operator[](unsigned int i) const
462         {
463                 //assert(i < m_size)
464                 return data[i];
465         }
466         T * operator*() const
467         {
468                 return data;
469         }
470         unsigned int getSize() const
471         {
472                 return m_size;
473         }
474 private:
475         void drop()
476         {
477                 assert((*refcount) > 0);
478                 (*refcount)--;
479                 if(*refcount == 0)
480                 {
481                         if(data)
482                                 delete[] data;
483                         delete refcount;
484                 }
485         }
486         T *data;
487         unsigned int m_size;
488         unsigned int *refcount;
489 };
490
491 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
492 {
493         SharedBuffer<u8> b((u8*)string, strlen(string)+1);
494         return b;
495 }
496
497 template<typename T>
498 class MutexedVariable
499 {
500 public:
501         MutexedVariable(T value):
502                 m_value(value)
503         {
504                 m_mutex.Init();
505         }
506
507         T get()
508         {
509                 JMutexAutoLock lock(m_mutex);
510                 return m_value;
511         }
512
513         void set(T value)
514         {
515                 JMutexAutoLock lock(m_mutex);
516                 m_value = value;
517         }
518         
519         // You'll want to grab this in a SharedPtr
520         JMutexAutoLock * getLock()
521         {
522                 return new JMutexAutoLock(m_mutex);
523         }
524         
525         // You pretty surely want to grab the lock when accessing this
526         T m_value;
527
528 private:
529         JMutex m_mutex;
530 };
531
532 /*
533         TimeTaker
534 */
535
536 class TimeTaker
537 {
538 public:
539         TimeTaker(const char *name, u32 *result=NULL);
540
541         ~TimeTaker()
542         {
543                 stop();
544         }
545
546         u32 stop(bool quiet=false);
547
548         u32 getTime();
549
550 private:
551         const char *m_name;
552         u32 m_time1;
553         bool m_running;
554         u32 *m_result;
555 };
556
557 #ifndef SERVER
558 // Sets the color of all vertices in the mesh
559 void setMeshVerticesColor(scene::IMesh* mesh, video::SColor& color);
560 #endif
561
562 // Calculates the borders of a "d-radius" cube
563 inline void getFacePositions(core::list<v3s16> &list, u16 d)
564 {
565         if(d == 0)
566         {
567                 list.push_back(v3s16(0,0,0));
568                 return;
569         }
570         if(d == 1)
571         {
572                 /*
573                         This is an optimized sequence of coordinates.
574                 */
575                 list.push_back(v3s16( 0, 1, 0)); // top
576                 list.push_back(v3s16( 0, 0, 1)); // back
577                 list.push_back(v3s16(-1, 0, 0)); // left
578                 list.push_back(v3s16( 1, 0, 0)); // right
579                 list.push_back(v3s16( 0, 0,-1)); // front
580                 list.push_back(v3s16( 0,-1, 0)); // bottom
581                 // 6
582                 list.push_back(v3s16(-1, 0, 1)); // back left
583                 list.push_back(v3s16( 1, 0, 1)); // back right
584                 list.push_back(v3s16(-1, 0,-1)); // front left
585                 list.push_back(v3s16( 1, 0,-1)); // front right
586                 list.push_back(v3s16(-1,-1, 0)); // bottom left
587                 list.push_back(v3s16( 1,-1, 0)); // bottom right
588                 list.push_back(v3s16( 0,-1, 1)); // bottom back
589                 list.push_back(v3s16( 0,-1,-1)); // bottom front
590                 list.push_back(v3s16(-1, 1, 0)); // top left
591                 list.push_back(v3s16( 1, 1, 0)); // top right
592                 list.push_back(v3s16( 0, 1, 1)); // top back
593                 list.push_back(v3s16( 0, 1,-1)); // top front
594                 // 18
595                 list.push_back(v3s16(-1, 1, 1)); // top back-left
596                 list.push_back(v3s16( 1, 1, 1)); // top back-right
597                 list.push_back(v3s16(-1, 1,-1)); // top front-left
598                 list.push_back(v3s16( 1, 1,-1)); // top front-right
599                 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
600                 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
601                 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
602                 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
603                 // 26
604                 return;
605         }
606
607         // Take blocks in all sides, starting from y=0 and going +-y
608         for(s16 y=0; y<=d-1; y++)
609         {
610                 // Left and right side, including borders
611                 for(s16 z=-d; z<=d; z++)
612                 {
613                         list.push_back(v3s16(d,y,z));
614                         list.push_back(v3s16(-d,y,z));
615                         if(y != 0)
616                         {
617                                 list.push_back(v3s16(d,-y,z));
618                                 list.push_back(v3s16(-d,-y,z));
619                         }
620                 }
621                 // Back and front side, excluding borders
622                 for(s16 x=-d+1; x<=d-1; x++)
623                 {
624                         list.push_back(v3s16(x,y,d));
625                         list.push_back(v3s16(x,y,-d));
626                         if(y != 0)
627                         {
628                                 list.push_back(v3s16(x,-y,d));
629                                 list.push_back(v3s16(x,-y,-d));
630                         }
631                 }
632         }
633
634         // Take the bottom and top face with borders
635         // -d<x<d, y=+-d, -d<z<d
636         for(s16 x=-d; x<=d; x++)
637         for(s16 z=-d; z<=d; z++)
638         {
639                 list.push_back(v3s16(x,-d,z));
640                 list.push_back(v3s16(x,d,z));
641         }
642 }
643
644 class IndentationRaiser
645 {
646 public:
647         IndentationRaiser(u16 *indentation)
648         {
649                 m_indentation = indentation;
650                 (*m_indentation)++;
651         }
652         ~IndentationRaiser()
653         {
654                 (*m_indentation)--;
655         }
656 private:
657         u16 *m_indentation;
658 };
659
660 inline s16 getContainerPos(s16 p, s16 d)
661 {
662         return (p>=0 ? p : p-d+1) / d;
663 }
664
665 inline v2s16 getContainerPos(v2s16 p, s16 d)
666 {
667         return v2s16(
668                 getContainerPos(p.X, d),
669                 getContainerPos(p.Y, d)
670         );
671 }
672
673 inline v3s16 getContainerPos(v3s16 p, s16 d)
674 {
675         return v3s16(
676                 getContainerPos(p.X, d),
677                 getContainerPos(p.Y, d),
678                 getContainerPos(p.Z, d)
679         );
680 }
681
682 inline v2s16 getContainerPos(v2s16 p, v2s16 d)
683 {
684         return v2s16(
685                 getContainerPos(p.X, d.X),
686                 getContainerPos(p.Y, d.Y)
687         );
688 }
689
690 inline v3s16 getContainerPos(v3s16 p, v3s16 d)
691 {
692         return v3s16(
693                 getContainerPos(p.X, d.X),
694                 getContainerPos(p.Y, d.Y),
695                 getContainerPos(p.Z, d.Z)
696         );
697 }
698
699 inline bool isInArea(v3s16 p, s16 d)
700 {
701         return (
702                 p.X >= 0 && p.X < d &&
703                 p.Y >= 0 && p.Y < d &&
704                 p.Z >= 0 && p.Z < d
705         );
706 }
707
708 inline bool isInArea(v2s16 p, s16 d)
709 {
710         return (
711                 p.X >= 0 && p.X < d &&
712                 p.Y >= 0 && p.Y < d
713         );
714 }
715
716 inline bool isInArea(v3s16 p, v3s16 d)
717 {
718         return (
719                 p.X >= 0 && p.X < d.X &&
720                 p.Y >= 0 && p.Y < d.Y &&
721                 p.Z >= 0 && p.Z < d.Z
722         );
723 }
724
725 inline s16 rangelim(s16 i, s16 max)
726 {
727         if(i < 0)
728                 return 0;
729         if(i > max)
730                 return max;
731         return i;
732 }
733
734 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
735
736 inline v3s16 arealim(v3s16 p, s16 d)
737 {
738         if(p.X < 0)
739                 p.X = 0;
740         if(p.Y < 0)
741                 p.Y = 0;
742         if(p.Z < 0)
743                 p.Z = 0;
744         if(p.X > d-1)
745                 p.X = d-1;
746         if(p.Y > d-1)
747                 p.Y = d-1;
748         if(p.Z > d-1)
749                 p.Z = d-1;
750         return p;
751 }
752
753 inline std::wstring narrow_to_wide(const std::string& mbs)
754 {
755         size_t wcl = mbs.size();
756         Buffer<wchar_t> wcs(wcl+1);
757         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
758         if(l == (size_t)(-1))
759                 return L"<invalid multibyte string>";
760         wcs[l] = 0;
761         return *wcs;
762 }
763
764 inline std::string wide_to_narrow(const std::wstring& wcs)
765 {
766         size_t mbl = wcs.size()*4;
767         SharedBuffer<char> mbs(mbl+1);
768         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
769         if(l == (size_t)(-1))
770                 mbs[0] = 0;
771         else
772                 mbs[l] = 0;
773         return *mbs;
774 }
775
776 // Split a string using the given delimiter. Returns a vector containing
777 // the component parts.
778 inline std::vector<std::wstring> str_split(const std::wstring &str, wchar_t delimiter)
779 {
780         std::vector<std::wstring> parts;
781         std::wstringstream sstr(str);
782         std::wstring part;
783         while(std::getline(sstr, part, delimiter))
784                 parts.push_back(part);
785         return parts;
786 }
787
788
789 /*
790         See test.cpp for example cases.
791         wraps degrees to the range of -360...360
792         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
793 */
794 inline float wrapDegrees(float f)
795 {
796         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
797         // This results in
798         // 10, 720, -1, -361
799         int i = floor(f);
800         // 0, 2, 0, -1
801         int l = i / 360;
802         // NOTE: This would be used for wrapping to 0...360
803         // 0, 2, -1, -2
804         /*if(i < 0)
805                 l -= 1;*/
806         // 0, 720, 0, -360
807         int k = l * 360;
808         // 10, 0.5, -0.5, -0.5
809         f -= float(k);
810         return f;
811 }
812
813 /* Wrap to 0...360 */
814 inline float wrapDegrees_0_360(float f)
815 {
816         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
817         // This results in
818         // 10, 720, -1, -361
819         int i = floor(f);
820         // 0, 2, 0, -1
821         int l = i / 360;
822         // Wrap to 0...360
823         // 0, 2, -1, -2
824         if(i < 0)
825                 l -= 1;
826         // 0, 720, 0, -360
827         int k = l * 360;
828         // 10, 0.5, -0.5, -0.5
829         f -= float(k);
830         return f;
831 }
832
833 /* Wrap to -180...180 */
834 inline float wrapDegrees_180(float f)
835 {
836         f += 180;
837         f = wrapDegrees_0_360(f);
838         f -= 180;
839         return f;
840 }
841
842 inline std::string lowercase(const std::string &s)
843 {
844         std::string s2;
845         for(size_t i=0; i<s.size(); i++)
846         {
847                 char c = s[i];
848                 if(c >= 'A' && c <= 'Z')
849                         c -= 'A' - 'a';
850                 s2 += c;
851         }
852         return s2;
853 }
854
855 inline bool is_yes(const std::string &s)
856 {
857         std::string s2 = lowercase(trim(s));
858         if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
859                 return true;
860         return false;
861 }
862
863 inline s32 stoi(const std::string &s, s32 min, s32 max)
864 {
865         s32 i = atoi(s.c_str());
866         if(i < min)
867                 i = min;
868         if(i > max)
869                 i = max;
870         return i;
871 }
872
873
874 // MSVC2010 includes it's own versions of these
875 #if !defined(_MSC_VER) || _MSC_VER < 1600
876
877 inline s32 stoi(std::string s)
878 {
879         return atoi(s.c_str());
880 }
881
882 inline s32 stoi(std::wstring s)
883 {
884         return atoi(wide_to_narrow(s).c_str());
885 }
886
887 inline float stof(std::string s)
888 {
889         float f;
890         std::istringstream ss(s);
891         ss>>f;
892         return f;
893 }
894
895 #endif
896
897 inline std::string itos(s32 i)
898 {
899         std::ostringstream o;
900         o<<i;
901         return o.str();
902 }
903
904 inline std::string ftos(float f)
905 {
906         std::ostringstream o;
907         o<<f;
908         return o.str();
909 }
910
911 inline void str_replace(std::string & str, std::string const & pattern,
912                 std::string const & replacement)
913 {
914         std::string::size_type start = str.find(pattern, 0);
915         while(start != str.npos)
916         {
917                 str.replace(start, pattern.size(), replacement);
918                 start = str.find(pattern, start+replacement.size());
919         }
920 }
921
922 inline void str_replace_char(std::string & str, char from, char to)
923 {
924         for(unsigned int i=0; i<str.size(); i++)
925         {
926                 if(str[i] == from)
927                         str[i] = to;
928         }
929 }
930
931 /*
932         A base class for simple background thread implementation
933 */
934
935 class SimpleThread : public JThread
936 {
937         bool run;
938         JMutex run_mutex;
939
940 public:
941
942         SimpleThread():
943                 JThread(),
944                 run(true)
945         {
946                 run_mutex.Init();
947         }
948
949         virtual ~SimpleThread()
950         {}
951
952         virtual void * Thread() = 0;
953
954         bool getRun()
955         {
956                 JMutexAutoLock lock(run_mutex);
957                 return run;
958         }
959         void setRun(bool a_run)
960         {
961                 JMutexAutoLock lock(run_mutex);
962                 run = a_run;
963         }
964
965         void stop()
966         {
967                 setRun(false);
968                 while(IsRunning())
969                         sleep_ms(100);
970         }
971 };
972
973 /*
974         FIFO queue (well, actually a FILO also)
975 */
976 template<typename T>
977 class Queue
978 {
979 public:
980         void push_back(T t)
981         {
982                 m_list.push_back(t);
983         }
984         
985         T pop_front()
986         {
987                 if(m_list.size() == 0)
988                         throw ItemNotFoundException("Queue: queue is empty");
989
990                 typename core::list<T>::Iterator begin = m_list.begin();
991                 T t = *begin;
992                 m_list.erase(begin);
993                 return t;
994         }
995         T pop_back()
996         {
997                 if(m_list.size() == 0)
998                         throw ItemNotFoundException("Queue: queue is empty");
999
1000                 typename core::list<T>::Iterator last = m_list.getLast();
1001                 T t = *last;
1002                 m_list.erase(last);
1003                 return t;
1004         }
1005
1006         u32 size()
1007         {
1008                 return m_list.size();
1009         }
1010
1011 protected:
1012         core::list<T> m_list;
1013 };
1014
1015 /*
1016         Thread-safe FIFO queue (well, actually a FILO also)
1017 */
1018
1019 template<typename T>
1020 class MutexedQueue
1021 {
1022 public:
1023         MutexedQueue()
1024         {
1025                 m_mutex.Init();
1026         }
1027         u32 size()
1028         {
1029                 JMutexAutoLock lock(m_mutex);
1030                 return m_list.size();
1031         }
1032         void push_back(T t)
1033         {
1034                 JMutexAutoLock lock(m_mutex);
1035                 m_list.push_back(t);
1036         }
1037         T pop_front(u32 wait_time_max_ms=0)
1038         {
1039                 u32 wait_time_ms = 0;
1040
1041                 for(;;)
1042                 {
1043                         {
1044                                 JMutexAutoLock lock(m_mutex);
1045
1046                                 if(m_list.size() > 0)
1047                                 {
1048                                         typename core::list<T>::Iterator begin = m_list.begin();
1049                                         T t = *begin;
1050                                         m_list.erase(begin);
1051                                         return t;
1052                                 }
1053
1054                                 if(wait_time_ms >= wait_time_max_ms)
1055                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1056                         }
1057
1058                         // Wait a while before trying again
1059                         sleep_ms(10);
1060                         wait_time_ms += 10;
1061                 }
1062         }
1063         T pop_back(u32 wait_time_max_ms=0)
1064         {
1065                 u32 wait_time_ms = 0;
1066
1067                 for(;;)
1068                 {
1069                         {
1070                                 JMutexAutoLock lock(m_mutex);
1071
1072                                 if(m_list.size() > 0)
1073                                 {
1074                                         typename core::list<T>::Iterator last = m_list.getLast();
1075                                         T t = *last;
1076                                         m_list.erase(last);
1077                                         return t;
1078                                 }
1079
1080                                 if(wait_time_ms >= wait_time_max_ms)
1081                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1082                         }
1083
1084                         // Wait a while before trying again
1085                         sleep_ms(10);
1086                         wait_time_ms += 10;
1087                 }
1088         }
1089
1090         JMutex & getMutex()
1091         {
1092                 return m_mutex;
1093         }
1094
1095         core::list<T> & getList()
1096         {
1097                 return m_list;
1098         }
1099
1100 protected:
1101         JMutex m_mutex;
1102         core::list<T> m_list;
1103 };
1104
1105 /*
1106         A single worker thread - multiple client threads queue framework.
1107 */
1108
1109 template<typename Caller, typename Data>
1110 class CallerInfo
1111 {
1112 public:
1113         Caller caller;
1114         Data data;
1115 };
1116
1117 template<typename Key, typename T, typename Caller, typename CallerData>
1118 class GetResult
1119 {
1120 public:
1121         Key key;
1122         T item;
1123         core::list<CallerInfo<Caller, CallerData> > callers;
1124 };
1125
1126 template<typename Key, typename T, typename Caller, typename CallerData>
1127 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1128 {
1129 };
1130
1131 template<typename Key, typename T, typename Caller, typename CallerData>
1132 class GetRequest
1133 {
1134 public:
1135         GetRequest()
1136         {
1137                 dest = NULL;
1138         }
1139         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1140         {
1141                 dest = a_dest;
1142         }
1143         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1144                         Key a_key)
1145         {
1146                 dest = a_dest;
1147                 key = a_key;
1148         }
1149         ~GetRequest()
1150         {
1151         }
1152         
1153         Key key;
1154         ResultQueue<Key, T, Caller, CallerData> *dest;
1155         core::list<CallerInfo<Caller, CallerData> > callers;
1156 };
1157
1158 template<typename Key, typename T, typename Caller, typename CallerData>
1159 class RequestQueue
1160 {
1161 public:
1162         u32 size()
1163         {
1164                 return m_queue.size();
1165         }
1166
1167         void add(Key key, Caller caller, CallerData callerdata,
1168                         ResultQueue<Key, T, Caller, CallerData> *dest)
1169         {
1170                 JMutexAutoLock lock(m_queue.getMutex());
1171                 
1172                 /*
1173                         If the caller is already on the list, only update CallerData
1174                 */
1175                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1176                                 i = m_queue.getList().begin();
1177                                 i != m_queue.getList().end(); i++)
1178                 {
1179                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1180
1181                         if(request.key == key)
1182                         {
1183                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1184                                                 i = request.callers.begin();
1185                                                 i != request.callers.end(); i++)
1186                                 {
1187                                         CallerInfo<Caller, CallerData> &ca = *i;
1188                                         if(ca.caller == caller)
1189                                         {
1190                                                 ca.data = callerdata;
1191                                                 return;
1192                                         }
1193                                 }
1194                                 CallerInfo<Caller, CallerData> ca;
1195                                 ca.caller = caller;
1196                                 ca.data = callerdata;
1197                                 request.callers.push_back(ca);
1198                                 return;
1199                         }
1200                 }
1201
1202                 /*
1203                         Else add a new request to the queue
1204                 */
1205
1206                 GetRequest<Key, T, Caller, CallerData> request;
1207                 request.key = key;
1208                 CallerInfo<Caller, CallerData> ca;
1209                 ca.caller = caller;
1210                 ca.data = callerdata;
1211                 request.callers.push_back(ca);
1212                 request.dest = dest;
1213                 
1214                 m_queue.getList().push_back(request);
1215         }
1216
1217         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1218         {
1219                 return m_queue.pop_front(wait_if_empty);
1220         }
1221
1222 private:
1223         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1224 };
1225
1226 /*
1227         Pseudo-random (VC++ rand() sucks)
1228 */
1229 int myrand(void);
1230 void mysrand(unsigned seed);
1231 #define MYRAND_MAX 32767
1232
1233 int myrand_range(int min, int max);
1234
1235 /*
1236         Miscellaneous functions
1237 */
1238
1239 bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,
1240                 f32 camera_fov, f32 range, f32 *distance_ptr=NULL);
1241
1242 /*
1243         Queue with unique values with fast checking of value existence
1244 */
1245
1246 template<typename Value>
1247 class UniqueQueue
1248 {
1249 public:
1250         
1251         /*
1252                 Does nothing if value is already queued.
1253                 Return value:
1254                         true: value added
1255                         false: value already exists
1256         */
1257         bool push_back(Value value)
1258         {
1259                 // Check if already exists
1260                 if(m_map.find(value) != NULL)
1261                         return false;
1262
1263                 // Add
1264                 m_map.insert(value, 0);
1265                 m_list.push_back(value);
1266                 
1267                 return true;
1268         }
1269
1270         Value pop_front()
1271         {
1272                 typename core::list<Value>::Iterator i = m_list.begin();
1273                 Value value = *i;
1274                 m_map.remove(value);
1275                 m_list.erase(i);
1276                 return value;
1277         }
1278
1279         u32 size()
1280         {
1281                 assert(m_list.size() == m_map.size());
1282                 return m_list.size();
1283         }
1284
1285 private:
1286         core::map<Value, u8> m_map;
1287         core::list<Value> m_list;
1288 };
1289
1290 #if 1
1291 template<typename Key, typename Value>
1292 class MutexedMap
1293 {
1294 public:
1295         MutexedMap()
1296         {
1297                 m_mutex.Init();
1298                 assert(m_mutex.IsInitialized());
1299         }
1300         
1301         void set(const Key &name, const Value &value)
1302         {
1303                 JMutexAutoLock lock(m_mutex);
1304
1305                 m_values[name] = value;
1306         }
1307         
1308         bool get(const Key &name, Value *result)
1309         {
1310                 JMutexAutoLock lock(m_mutex);
1311
1312                 typename core::map<Key, Value>::Node *n;
1313                 n = m_values.find(name);
1314
1315                 if(n == NULL)
1316                         return false;
1317                 
1318                 if(result != NULL)
1319                         *result = n->getValue();
1320                         
1321                 return true;
1322         }
1323
1324 private:
1325         core::map<Key, Value> m_values;
1326         JMutex m_mutex;
1327 };
1328 #endif
1329
1330 /*
1331         Generates ids for comparable values.
1332         Id=0 is reserved for "no value".
1333
1334         Is fast at:
1335         - Returning value by id (very fast)
1336         - Returning id by value
1337         - Generating a new id for a value
1338
1339         Is not able to:
1340         - Remove an id/value pair (is possible to implement but slow)
1341 */
1342 template<typename T>
1343 class MutexedIdGenerator
1344 {
1345 public:
1346         MutexedIdGenerator()
1347         {
1348                 m_mutex.Init();
1349                 assert(m_mutex.IsInitialized());
1350         }
1351         
1352         // Returns true if found
1353         bool getValue(u32 id, T &value)
1354         {
1355                 if(id == 0)
1356                         return false;
1357                 JMutexAutoLock lock(m_mutex);
1358                 if(m_id_to_value.size() < id)
1359                         return false;
1360                 value = m_id_to_value[id-1];
1361                 return true;
1362         }
1363         
1364         // If id exists for value, returns the id.
1365         // Otherwise generates an id for the value.
1366         u32 getId(const T &value)
1367         {
1368                 JMutexAutoLock lock(m_mutex);
1369                 typename core::map<T, u32>::Node *n;
1370                 n = m_value_to_id.find(value);
1371                 if(n != NULL)
1372                         return n->getValue();
1373                 m_id_to_value.push_back(value);
1374                 u32 new_id = m_id_to_value.size();
1375                 m_value_to_id.insert(value, new_id);
1376                 return new_id;
1377         }
1378
1379 private:
1380         JMutex m_mutex;
1381         // Values are stored here at id-1 position (id 1 = [0])
1382         core::array<T> m_id_to_value;
1383         core::map<T, u32> m_value_to_id;
1384 };
1385
1386 /*
1387         Checks if a string contains only supplied characters
1388 */
1389 inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
1390 {
1391         for(u32 i=0; i<s.size(); i++)
1392         {
1393                 bool confirmed = false;
1394                 for(u32 j=0; j<allowed_chars.size(); j++)
1395                 {
1396                         if(s[i] == allowed_chars[j])
1397                         {
1398                                 confirmed = true;
1399                                 break;
1400                         }
1401                 }
1402                 if(confirmed == false)
1403                         return false;
1404         }
1405         return true;
1406 }
1407
1408 /*
1409         Forcefully wraps string into rows using \n
1410         (no word wrap, used for showing paths in gui)
1411 */
1412 inline std::string wrap_rows(const std::string &from, u32 rowlen)
1413 {
1414         std::string to;
1415         for(u32 i=0; i<from.size(); i++)
1416         {
1417                 if(i != 0 && i%rowlen == 0)
1418                         to += '\n';
1419                 to += from[i];
1420         }
1421         return to;
1422 }
1423
1424 /*
1425         Some helper stuff
1426 */
1427 #define MYMIN(a,b) ((a)<(b)?(a):(b))
1428 #define MYMAX(a,b) ((a)>(b)?(a):(b))
1429
1430 /*
1431         Returns integer position of node in given floating point position
1432 */
1433 inline v3s16 floatToInt(v3f p, f32 d)
1434 {
1435         v3s16 p2(
1436                 (p.X + (p.X>0 ? d/2 : -d/2))/d,
1437                 (p.Y + (p.Y>0 ? d/2 : -d/2))/d,
1438                 (p.Z + (p.Z>0 ? d/2 : -d/2))/d);
1439         return p2;
1440 }
1441
1442 /*
1443         Returns floating point position of node in given integer position
1444 */
1445 inline v3f intToFloat(v3s16 p, f32 d)
1446 {
1447         v3f p2(
1448                 (f32)p.X * d,
1449                 (f32)p.Y * d,
1450                 (f32)p.Z * d
1451         );
1452         return p2;
1453 }
1454
1455 /*
1456         More serialization stuff
1457 */
1458
1459 // Creates a string with the length as the first two bytes
1460 inline std::string serializeString(const std::string &plain)
1461 {
1462         //assert(plain.size() <= 65535);
1463         if(plain.size() > 65535)
1464                 throw SerializationError("String too long for serializeString");
1465         char buf[2];
1466         writeU16((u8*)&buf[0], plain.size());
1467         std::string s;
1468         s.append(buf, 2);
1469         s.append(plain);
1470         return s;
1471 }
1472
1473 // Creates a string with the length as the first two bytes from wide string
1474 inline std::string serializeWideString(const std::wstring &plain)
1475 {
1476         //assert(plain.size() <= 65535);
1477         if(plain.size() > 65535)
1478                 throw SerializationError("String too long for serializeString");
1479         char buf[2];
1480         writeU16((u8*)buf, plain.size());
1481         std::string s;
1482         s.append(buf, 2);
1483         for(u32 i=0; i<plain.size(); i++)
1484         {
1485                 writeU16((u8*)buf, plain[i]);
1486                 s.append(buf, 2);
1487         }
1488         return s;
1489 }
1490
1491 // Reads a string with the length as the first two bytes
1492 inline std::string deSerializeString(std::istream &is)
1493 {
1494         char buf[2];
1495         is.read(buf, 2);
1496         if(is.gcount() != 2)
1497                 throw SerializationError("deSerializeString: size not read");
1498         u16 s_size = readU16((u8*)buf);
1499         if(s_size == 0)
1500                 return "";
1501         Buffer<char> buf2(s_size);
1502         is.read(&buf2[0], s_size);
1503         std::string s;
1504         s.reserve(s_size);
1505         s.append(&buf2[0], s_size);
1506         return s;
1507 }
1508
1509 // Reads a wide string with the length as the first two bytes
1510 inline std::wstring deSerializeWideString(std::istream &is)
1511 {
1512         char buf[2];
1513         is.read(buf, 2);
1514         if(is.gcount() != 2)
1515                 throw SerializationError("deSerializeString: size not read");
1516         u16 s_size = readU16((u8*)buf);
1517         if(s_size == 0)
1518                 return L"";
1519         std::wstring s;
1520         s.reserve(s_size);
1521         for(u32 i=0; i<s_size; i++)
1522         {
1523                 is.read(&buf[0], 2);
1524                 wchar_t c16 = readU16((u8*)buf);
1525                 s.append(&c16, 1);
1526         }
1527         return s;
1528 }
1529
1530 // Creates a string with the length as the first four bytes
1531 inline std::string serializeLongString(const std::string &plain)
1532 {
1533         char buf[4];
1534         writeU32((u8*)&buf[0], plain.size());
1535         std::string s;
1536         s.append(buf, 4);
1537         s.append(plain);
1538         return s;
1539 }
1540
1541 // Reads a string with the length as the first four bytes
1542 inline std::string deSerializeLongString(std::istream &is)
1543 {
1544         char buf[4];
1545         is.read(buf, 4);
1546         if(is.gcount() != 4)
1547                 throw SerializationError("deSerializeLongString: size not read");
1548         u32 s_size = readU32((u8*)buf);
1549         if(s_size == 0)
1550                 return "";
1551         Buffer<char> buf2(s_size);
1552         is.read(&buf2[0], s_size);
1553         std::string s;
1554         s.reserve(s_size);
1555         s.append(&buf2[0], s_size);
1556         return s;
1557 }
1558
1559 //
1560
1561 inline u32 time_to_daynight_ratio(u32 time_of_day)
1562 {
1563         const s32 daylength = 16;
1564         const s32 nightlength = 6;
1565         const s32 daytimelength = 8;
1566         s32 d = daylength;
1567         s32 t = (((time_of_day)%24000)/(24000/d));
1568         if(t < nightlength/2 || t >= d - nightlength/2)
1569                 //return 300;
1570                 return 350;
1571         else if(t >= d/2 - daytimelength/2 && t < d/2 + daytimelength/2)
1572                 return 1000;
1573         else
1574                 return 750;
1575 }
1576
1577 // Random helper. Usually d=BS
1578 inline core::aabbox3d<f32> getNodeBox(v3s16 p, float d)
1579 {
1580         return core::aabbox3d<f32>(
1581                 (float)p.X * d - 0.5*d,
1582                 (float)p.Y * d - 0.5*d,
1583                 (float)p.Z * d - 0.5*d,
1584                 (float)p.X * d + 0.5*d,
1585                 (float)p.Y * d + 0.5*d,
1586                 (float)p.Z * d + 0.5*d
1587         );
1588 }
1589         
1590 class IntervalLimiter
1591 {
1592 public:
1593         IntervalLimiter():
1594                 m_accumulator(0)
1595         {
1596         }
1597         /*
1598                 dtime: time from last call to this method
1599                 wanted_interval: interval wanted
1600                 return value:
1601                         true: action should be skipped
1602                         false: action should be done
1603         */
1604         bool step(float dtime, float wanted_interval)
1605         {
1606                 m_accumulator += dtime;
1607                 if(m_accumulator < wanted_interval)
1608                         return false;
1609                 m_accumulator -= wanted_interval;
1610                 return true;
1611         }
1612 protected:
1613         float m_accumulator;
1614 };
1615
1616 std::string translatePassword(std::string playername, std::wstring password);
1617
1618 #endif
1619