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