Made dungeons a bit rarer
[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 <jthread.h>
28 #include <jmutex.h>
29 #include <jmutexautolock.h>
30
31 #include "common_irrlicht.h"
32 #include "debug.h"
33 #include "strfnd.h"
34 #include "exceptions.h"
35 #include "porting.h"
36
37 extern const v3s16 g_26dirs[26];
38
39 inline void writeU32(u8 *data, u32 i)
40 {
41         data[0] = ((i>>24)&0xff);
42         data[1] = ((i>>16)&0xff);
43         data[2] = ((i>> 8)&0xff);
44         data[3] = ((i>> 0)&0xff);
45 }
46
47 inline void writeU16(u8 *data, u16 i)
48 {
49         data[0] = ((i>> 8)&0xff);
50         data[1] = ((i>> 0)&0xff);
51 }
52
53 inline void writeU8(u8 *data, u8 i)
54 {
55         data[0] = ((i>> 0)&0xff);
56 }
57
58 inline u32 readU32(u8 *data)
59 {
60         return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
61 }
62
63 inline u16 readU16(u8 *data)
64 {
65         return (data[0]<<8) | (data[1]<<0);
66 }
67
68 inline u8 readU8(u8 *data)
69 {
70         return (data[0]<<0);
71 }
72
73 // Signed variants of the above
74
75 inline void writeS32(u8 *data, s32 i){
76         writeU32(data, (u32)i);
77 }
78 inline s32 readS32(u8 *data){
79         return (s32)readU32(data);
80 }
81
82 inline void writeS16(u8 *data, s16 i){
83         writeU16(data, (u16)i);
84 }
85 inline s16 readS16(u8 *data){
86         return (s16)readU16(data);
87 }
88
89 inline void writeV3S32(u8 *data, v3s32 p)
90 {
91         writeS32(&data[0], p.X);
92         writeS32(&data[4], p.Y);
93         writeS32(&data[8], p.Z);
94 }
95
96 inline v3s32 readV3S32(u8 *data)
97 {
98         v3s32 p;
99         p.X = readS32(&data[0]);
100         p.Y = readS32(&data[4]);
101         p.Z = readS32(&data[8]);
102         return p;
103 }
104
105 inline void writeV2S16(u8 *data, v2s16 p)
106 {
107         writeS16(&data[0], p.X);
108         writeS16(&data[2], p.Y);
109 }
110
111 inline v2s16 readV2S16(u8 *data)
112 {
113         v2s16 p;
114         p.X = readS16(&data[0]);
115         p.Y = readS16(&data[2]);
116         return p;
117 }
118
119 inline void writeV2S32(u8 *data, v2s32 p)
120 {
121         writeS32(&data[0], p.X);
122         writeS32(&data[2], p.Y);
123 }
124
125 inline v2s32 readV2S32(u8 *data)
126 {
127         v2s32 p;
128         p.X = readS32(&data[0]);
129         p.Y = readS32(&data[2]);
130         return p;
131 }
132
133 inline void writeV3S16(u8 *data, v3s16 p)
134 {
135         writeS16(&data[0], p.X);
136         writeS16(&data[2], p.Y);
137         writeS16(&data[4], p.Z);
138 }
139
140 inline v3s16 readV3S16(u8 *data)
141 {
142         v3s16 p;
143         p.X = readS16(&data[0]);
144         p.Y = readS16(&data[2]);
145         p.Z = readS16(&data[4]);
146         return p;
147 }
148
149 /*
150         None of these are used at the moment
151 */
152
153 template <typename T>
154 class SharedPtr
155 {
156 public:
157         SharedPtr(T *t=NULL)
158         {
159                 refcount = new int;
160                 *refcount = 1;
161                 ptr = t;
162         }
163         SharedPtr(SharedPtr<T> &t)
164         {
165                 //*this = t;
166                 drop();
167                 refcount = t.refcount;
168                 (*refcount)++;
169                 ptr = t.ptr;
170         }
171         ~SharedPtr()
172         {
173                 drop();
174         }
175         SharedPtr<T> & operator=(T *t)
176         {
177                 drop();
178                 refcount = new int;
179                 *refcount = 1;
180                 ptr = t;
181                 return *this;
182         }
183         SharedPtr<T> & operator=(SharedPtr<T> &t)
184         {
185                 drop();
186                 refcount = t.refcount;
187                 (*refcount)++;
188                 ptr = t.ptr;
189                 return *this;
190         }
191         T* operator->()
192         {
193                 return ptr;
194         }
195         T & operator*()
196         {
197                 return *ptr;
198         }
199         bool operator!=(T *t)
200         {
201                 return ptr != t;
202         }
203         bool operator==(T *t)
204         {
205                 return ptr == t;
206         }
207 private:
208         void drop()
209         {
210                 assert((*refcount) > 0);
211                 (*refcount)--;
212                 if(*refcount == 0)
213                 {
214                         delete refcount;
215                         if(ptr != NULL)
216                                 delete ptr;
217                 }
218         }
219         T *ptr;
220         int *refcount;
221 };
222
223 template <typename T>
224 class Buffer
225 {
226 public:
227         Buffer(unsigned int size)
228         {
229                 m_size = size;
230                 data = new T[size];
231         }
232         Buffer(const Buffer &buffer)
233         {
234                 m_size = buffer.m_size;
235                 data = new T[buffer.m_size];
236                 memcpy(data, buffer.data, buffer.m_size);
237         }
238         Buffer(T *t, unsigned int size)
239         {
240                 m_size = size;
241                 data = new T[size];
242                 memcpy(data, t, size);
243         }
244         ~Buffer()
245         {
246                 delete[] data;
247         }
248         T & operator[](unsigned int i) const
249         {
250                 return data[i];
251         }
252         T * operator*() const
253         {
254                 return data;
255         }
256         unsigned int getSize() const
257         {
258                 return m_size;
259         }
260 private:
261         T *data;
262         unsigned int m_size;
263 };
264
265 template <typename T>
266 class SharedBuffer
267 {
268 public:
269         SharedBuffer(unsigned int size)
270         {
271                 m_size = size;
272                 data = new T[size];
273                 refcount = new unsigned int;
274                 (*refcount) = 1;
275         }
276         SharedBuffer(const SharedBuffer &buffer)
277         {
278                 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
279                 m_size = buffer.m_size;
280                 data = buffer.data;
281                 refcount = buffer.refcount;
282                 (*refcount)++;
283         }
284         SharedBuffer & operator=(const SharedBuffer & buffer)
285         {
286                 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
287                 if(this == &buffer)
288                         return *this;
289                 drop();
290                 m_size = buffer.m_size;
291                 data = buffer.data;
292                 refcount = buffer.refcount;
293                 (*refcount)++;
294                 return *this;
295         }
296         /*
297                 Copies whole buffer
298         */
299         SharedBuffer(T *t, unsigned int size)
300         {
301                 m_size = size;
302                 data = new T[size];
303                 memcpy(data, t, size);
304                 refcount = new unsigned int;
305                 (*refcount) = 1;
306         }
307         /*
308                 Copies whole buffer
309         */
310         SharedBuffer(const Buffer<T> &buffer)
311         {
312                 m_size = buffer.m_size;
313                 data = new T[buffer.getSize()];
314                 memcpy(data, *buffer, buffer.getSize());
315                 refcount = new unsigned int;
316                 (*refcount) = 1;
317         }
318         ~SharedBuffer()
319         {
320                 drop();
321         }
322         T & operator[](unsigned int i) const
323         {
324                 return data[i];
325         }
326         T * operator*() const
327         {
328                 return data;
329         }
330         unsigned int getSize() const
331         {
332                 return m_size;
333         }
334 private:
335         void drop()
336         {
337                 assert((*refcount) > 0);
338                 (*refcount)--;
339                 if(*refcount == 0)
340                 {
341                         delete[] data;
342                         delete refcount;
343                 }
344         }
345         T *data;
346         unsigned int m_size;
347         unsigned int *refcount;
348 };
349
350 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
351 {
352         SharedBuffer<u8> b((u8*)string, strlen(string)+1);
353         return b;
354 }
355
356 template<typename T>
357 class MutexedVariable
358 {
359 public:
360         MutexedVariable(T value):
361                 m_value(value)
362         {
363                 m_mutex.Init();
364         }
365
366         T get()
367         {
368                 JMutexAutoLock lock(m_mutex);
369                 return m_value;
370         }
371
372         void set(T value)
373         {
374                 JMutexAutoLock lock(m_mutex);
375                 m_value = value;
376         }
377         
378         // You'll want to grab this in a SharedPtr
379         JMutexAutoLock * getLock()
380         {
381                 return new JMutexAutoLock(m_mutex);
382         }
383         
384         // You pretty surely want to grab the lock when accessing this
385         T m_value;
386
387 private:
388         JMutex m_mutex;
389 };
390
391 /*
392         TimeTaker
393 */
394
395 class IrrlichtWrapper;
396
397 class TimeTaker
398 {
399 public:
400         TimeTaker(const char *name, u32 *result=NULL);
401
402         ~TimeTaker()
403         {
404                 stop();
405         }
406
407         u32 stop(bool quiet=false);
408
409 private:
410         const char *m_name;
411         u32 m_time1;
412         bool m_running;
413         u32 *m_result;
414 };
415
416 // Calculates the borders of a "d-radius" cube
417 inline void getFacePositions(core::list<v3s16> &list, u16 d)
418 {
419         if(d == 0)
420         {
421                 list.push_back(v3s16(0,0,0));
422                 return;
423         }
424         if(d == 1)
425         {
426                 /*
427                         This is an optimized sequence of coordinates.
428                 */
429                 list.push_back(v3s16( 0, 1, 0)); // top
430                 list.push_back(v3s16( 0, 0, 1)); // back
431                 list.push_back(v3s16(-1, 0, 0)); // left
432                 list.push_back(v3s16( 1, 0, 0)); // right
433                 list.push_back(v3s16( 0, 0,-1)); // front
434                 list.push_back(v3s16( 0,-1, 0)); // bottom
435                 // 6
436                 list.push_back(v3s16(-1, 0, 1)); // back left
437                 list.push_back(v3s16( 1, 0, 1)); // back right
438                 list.push_back(v3s16(-1, 0,-1)); // front left
439                 list.push_back(v3s16( 1, 0,-1)); // front right
440                 list.push_back(v3s16(-1,-1, 0)); // bottom left
441                 list.push_back(v3s16( 1,-1, 0)); // bottom right
442                 list.push_back(v3s16( 0,-1, 1)); // bottom back
443                 list.push_back(v3s16( 0,-1,-1)); // bottom front
444                 list.push_back(v3s16(-1, 1, 0)); // top left
445                 list.push_back(v3s16( 1, 1, 0)); // top right
446                 list.push_back(v3s16( 0, 1, 1)); // top back
447                 list.push_back(v3s16( 0, 1,-1)); // top front
448                 // 18
449                 list.push_back(v3s16(-1, 1, 1)); // top back-left
450                 list.push_back(v3s16( 1, 1, 1)); // top back-right
451                 list.push_back(v3s16(-1, 1,-1)); // top front-left
452                 list.push_back(v3s16( 1, 1,-1)); // top front-right
453                 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
454                 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
455                 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
456                 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
457                 // 26
458                 return;
459         }
460
461         // Take blocks in all sides, starting from y=0 and going +-y
462         for(s16 y=0; y<=d-1; y++)
463         {
464                 // Left and right side, including borders
465                 for(s16 z=-d; z<=d; z++)
466                 {
467                         list.push_back(v3s16(d,y,z));
468                         list.push_back(v3s16(-d,y,z));
469                         if(y != 0)
470                         {
471                                 list.push_back(v3s16(d,-y,z));
472                                 list.push_back(v3s16(-d,-y,z));
473                         }
474                 }
475                 // Back and front side, excluding borders
476                 for(s16 x=-d+1; x<=d-1; x++)
477                 {
478                         list.push_back(v3s16(x,y,d));
479                         list.push_back(v3s16(x,y,-d));
480                         if(y != 0)
481                         {
482                                 list.push_back(v3s16(x,-y,d));
483                                 list.push_back(v3s16(x,-y,-d));
484                         }
485                 }
486         }
487
488         // Take the bottom and top face with borders
489         // -d<x<d, y=+-d, -d<z<d
490         for(s16 x=-d; x<=d; x++)
491         for(s16 z=-d; z<=d; z++)
492         {
493                 list.push_back(v3s16(x,-d,z));
494                 list.push_back(v3s16(x,d,z));
495         }
496 }
497
498 class IndentationRaiser
499 {
500 public:
501         IndentationRaiser(u16 *indentation)
502         {
503                 m_indentation = indentation;
504                 (*m_indentation)++;
505         }
506         ~IndentationRaiser()
507         {
508                 (*m_indentation)--;
509         }
510 private:
511         u16 *m_indentation;
512 };
513
514 inline s16 getContainerPos(s16 p, s16 d)
515 {
516         return (p>=0 ? p : p-d+1) / d;
517 }
518
519 inline v2s16 getContainerPos(v2s16 p, s16 d)
520 {
521         return v2s16(
522                 getContainerPos(p.X, d),
523                 getContainerPos(p.Y, d)
524         );
525 }
526
527 inline v3s16 getContainerPos(v3s16 p, s16 d)
528 {
529         return v3s16(
530                 getContainerPos(p.X, d),
531                 getContainerPos(p.Y, d),
532                 getContainerPos(p.Z, d)
533         );
534 }
535
536 inline bool isInArea(v3s16 p, s16 d)
537 {
538         return (
539                 p.X >= 0 && p.X < d &&
540                 p.Y >= 0 && p.Y < d &&
541                 p.Z >= 0 && p.Z < d
542         );
543 }
544
545 inline bool isInArea(v2s16 p, s16 d)
546 {
547         return (
548                 p.X >= 0 && p.X < d &&
549                 p.Y >= 0 && p.Y < d
550         );
551 }
552
553 inline s16 rangelim(s16 i, s16 min, s16 max)
554 {
555         if(i < min)
556                 return min;
557         if(i > max)
558                 return max;
559         return i;
560 }
561
562 inline s16 rangelim(s16 i, s16 max)
563 {
564         if(i < 0)
565                 return 0;
566         if(i > max)
567                 return max;
568         return i;
569 }
570
571 inline v3s16 arealim(v3s16 p, s16 d)
572 {
573         if(p.X < 0)
574                 p.X = 0;
575         if(p.Y < 0)
576                 p.Y = 0;
577         if(p.Z < 0)
578                 p.Z = 0;
579         if(p.X > d-1)
580                 p.X = d-1;
581         if(p.Y > d-1)
582                 p.Y = d-1;
583         if(p.Z > d-1)
584                 p.Z = d-1;
585         return p;
586 }
587
588 inline std::wstring narrow_to_wide(const std::string& mbs)
589 {
590         size_t wcl = mbs.size();
591         SharedBuffer<wchar_t> wcs(wcl+1);
592         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
593         wcs[l] = 0;
594         return *wcs;
595 }
596
597 inline std::string wide_to_narrow(const std::wstring& wcs)
598 {
599         size_t mbl = wcs.size()*4;
600         SharedBuffer<char> mbs(mbl+1);
601         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
602         if((int)l == -1)
603                 mbs[0] = 0;
604         else
605                 mbs[l] = 0;
606         return *mbs;
607 }
608
609 /*
610         See test.cpp for example cases.
611         wraps degrees to the range of -360...360
612         NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
613 */
614 inline float wrapDegrees(float f)
615 {
616         // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
617         // This results in
618         // 10, 720, -1, -361
619         int i = floor(f);
620         // 0, 2, 0, -1
621         int l = i / 360;
622         // NOTE: This would be used for wrapping to 0...360
623         // 0, 2, -1, -2
624         /*if(i < 0)
625                 l -= 1;*/
626         // 0, 720, 0, -360
627         int k = l * 360;
628         // 10, 0.5, -0.5, -0.5
629         f -= float(k);
630         return f;
631 }
632
633 inline std::string lowercase(const std::string &s)
634 {
635         std::string s2;
636         for(size_t i=0; i<s.size(); i++)
637         {
638                 char c = s[i];
639                 if(c >= 'A' && c <= 'Z')
640                         c -= 'A' - 'a';
641                 s2 += c;
642         }
643         return s2;
644 }
645
646 inline bool is_yes(const std::string &s)
647 {
648         std::string s2 = lowercase(trim(s));
649         if(s2 == "y" || s2 == "yes" || s2 == "true")
650                 return true;
651         return false;
652 }
653
654 inline s32 stoi(const std::string &s, s32 min, s32 max)
655 {
656         s32 i = atoi(s.c_str());
657         if(i < min)
658                 i = min;
659         if(i > max)
660                 i = max;
661         return i;
662 }
663
664 inline s32 stoi(std::string s)
665 {
666         return atoi(s.c_str());
667 }
668
669 /*
670         A base class for simple background thread implementation
671 */
672
673 class SimpleThread : public JThread
674 {
675         bool run;
676         JMutex run_mutex;
677
678 public:
679
680         SimpleThread():
681                 JThread(),
682                 run(true)
683         {
684                 run_mutex.Init();
685         }
686
687         virtual ~SimpleThread()
688         {}
689
690         virtual void * Thread() = 0;
691
692         bool getRun()
693         {
694                 JMutexAutoLock lock(run_mutex);
695                 return run;
696         }
697         void setRun(bool a_run)
698         {
699                 JMutexAutoLock lock(run_mutex);
700                 run = a_run;
701         }
702
703         void stop()
704         {
705                 setRun(false);
706                 while(IsRunning())
707                         sleep_ms(100);
708         }
709 };
710
711 /*
712         Config stuff
713 */
714
715 enum ValueType
716 {
717         VALUETYPE_STRING,
718         VALUETYPE_FLAG // Doesn't take any arguments
719 };
720
721 struct ValueSpec
722 {
723         ValueSpec(ValueType a_type, const char *a_help=NULL)
724         {
725                 type = a_type;
726                 help = a_help;
727         }
728         ValueType type;
729         const char *help;
730 };
731
732 class Settings
733 {
734 public:
735
736         // Returns false on EOF
737         bool parseConfigObject(std::istream &is)
738         {
739                 if(is.eof())
740                         return false;
741                 
742                 // NOTE: This function will be expanded to allow multi-line settings
743                 std::string line;
744                 std::getline(is, line);
745                 //dstream<<"got line: \""<<line<<"\""<<std::endl;
746
747                 std::string trimmedline = trim(line);
748                 
749                 // Ignore comments
750                 if(trimmedline[0] == '#')
751                         return true;
752
753                 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
754
755                 Strfnd sf(trim(line));
756
757                 std::string name = sf.next("=");
758                 name = trim(name);
759
760                 if(name == "")
761                         return true;
762                 
763                 std::string value = sf.next("\n");
764                 value = trim(value);
765
766                 dstream<<"Config name=\""<<name<<"\" value=\""
767                                 <<value<<"\""<<std::endl;
768                 
769                 m_settings[name] = value;
770                 
771                 return true;
772         }
773
774         /*
775                 Read configuration file
776
777                 Returns true on success
778         */
779         bool readConfigFile(const char *filename)
780         {
781                 std::ifstream is(filename);
782                 if(is.good() == false)
783                 {
784                         dstream<<"Error opening configuration file \""
785                                         <<filename<<"\""<<std::endl;
786                         return false;
787                 }
788
789                 dstream<<"Parsing configuration file: \""
790                                 <<filename<<"\""<<std::endl;
791                                 
792                 while(parseConfigObject(is));
793                 
794                 return true;
795         }
796
797         /*
798                 Reads a configuration object from stream (usually a single line)
799                 and adds it to dst.
800                 
801                 Preserves comments and empty lines.
802
803                 Settings that were added to dst are also added to updated.
804                 key of updated is setting name, value of updated is dummy.
805
806                 Returns false on EOF
807         */
808         bool getUpdatedConfigObject(std::istream &is,
809                         core::list<std::string> &dst,
810                         core::map<std::string, bool> &updated)
811         {
812                 if(is.eof())
813                         return false;
814                 
815                 // NOTE: This function will be expanded to allow multi-line settings
816                 std::string line;
817                 std::getline(is, line);
818
819                 std::string trimmedline = trim(line);
820
821                 std::string line_end = "";
822                 if(is.eof() == false)
823                         line_end = "\n";
824                 
825                 // Ignore comments
826                 if(trimmedline[0] == '#')
827                 {
828                         dst.push_back(line+line_end);
829                         return true;
830                 }
831
832                 Strfnd sf(trim(line));
833
834                 std::string name = sf.next("=");
835                 name = trim(name);
836
837                 if(name == "")
838                 {
839                         dst.push_back(line+line_end);
840                         return true;
841                 }
842                 
843                 std::string value = sf.next("\n");
844                 value = trim(value);
845                 
846                 if(m_settings.find(name))
847                 {
848                         std::string newvalue = m_settings[name];
849                         
850                         if(newvalue != value)
851                         {
852                                 dstream<<"Changing value of \""<<name<<"\" = \""
853                                                 <<value<<"\" -> \""<<newvalue<<"\""
854                                                 <<std::endl;
855                         }
856
857                         dst.push_back(name + " = " + newvalue + line_end);
858
859                         updated[name] = true;
860                 }
861                 
862                 return true;
863         }
864
865         /*
866                 Updates configuration file
867
868                 Returns true on success
869         */
870         bool updateConfigFile(const char *filename)
871         {
872                 dstream<<"Updating configuration file: \""
873                                 <<filename<<"\""<<std::endl;
874                 
875                 core::list<std::string> objects;
876                 core::map<std::string, bool> updated;
877                 
878                 // Read and modify stuff
879                 {
880                         std::ifstream is(filename);
881                         if(is.good() == false)
882                         {
883                                 dstream<<"Error opening configuration file"
884                                                 " for reading: \""
885                                                 <<filename<<"\""<<std::endl;
886                                 return false;
887                         }
888
889                         while(getUpdatedConfigObject(is, objects, updated));
890                 }
891                 
892                 // Write stuff back
893                 {
894                         std::ofstream os(filename);
895                         if(os.good() == false)
896                         {
897                                 dstream<<"Error opening configuration file"
898                                                 " for writing: \""
899                                                 <<filename<<"\""<<std::endl;
900                                 return false;
901                         }
902                         
903                         /*
904                                 Write updated stuff
905                         */
906                         for(core::list<std::string>::Iterator
907                                         i = objects.begin();
908                                         i != objects.end(); i++)
909                         {
910                                 os<<(*i);
911                         }
912
913                         /*
914                                 Write stuff that was not already in the file
915                         */
916                         for(core::map<std::string, std::string>::Iterator
917                                         i = m_settings.getIterator();
918                                         i.atEnd() == false; i++)
919                         {
920                                 if(updated.find(i.getNode()->getKey()))
921                                         continue;
922                                 std::string name = i.getNode()->getKey();
923                                 std::string value = i.getNode()->getValue();
924                                 dstream<<"Adding \""<<name<<"\" = \""<<value<<"\""
925                                                 <<std::endl;
926                                 os<<name<<" = "<<value<<"\n";
927                         }
928                 }
929                 
930                 return true;
931         }
932
933         /*
934                 NOTE: Types of allowed_options are ignored
935
936                 returns true on success
937         */
938         bool parseCommandLine(int argc, char *argv[],
939                         core::map<std::string, ValueSpec> &allowed_options)
940         {
941                 int i=1;
942                 for(;;)
943                 {
944                         if(i >= argc)
945                                 break;
946                         std::string argname = argv[i];
947                         if(argname.substr(0, 2) != "--")
948                         {
949                                 dstream<<"Invalid command-line parameter \""
950                                                 <<argname<<"\": --<option> expected."<<std::endl;
951                                 return false;
952                         }
953                         i++;
954
955                         std::string name = argname.substr(2);
956
957                         core::map<std::string, ValueSpec>::Node *n;
958                         n = allowed_options.find(name);
959                         if(n == NULL)
960                         {
961                                 dstream<<"Unknown command-line parameter \""
962                                                 <<argname<<"\""<<std::endl;
963                                 return false;
964                         }
965
966                         ValueType type = n->getValue().type;
967
968                         std::string value = "";
969                         
970                         if(type == VALUETYPE_FLAG)
971                         {
972                                 value = "true";
973                         }
974                         else
975                         {
976                                 if(i >= argc)
977                                 {
978                                         dstream<<"Invalid command-line parameter \""
979                                                         <<name<<"\": missing value"<<std::endl;
980                                         return false;
981                                 }
982                                 value = argv[i];
983                                 i++;
984                         }
985                         
986
987                         dstream<<"Valid command-line parameter: \""
988                                         <<name<<"\" = \""<<value<<"\""
989                                         <<std::endl;
990                         set(name, value);
991                 }
992
993                 return true;
994         }
995
996         void set(std::string name, std::string value)
997         {
998                 m_settings[name] = value;
999         }
1000
1001         void setDefault(std::string name, std::string value)
1002         {
1003                 m_defaults[name] = value;
1004         }
1005
1006         bool exists(std::string name)
1007         {
1008                 return (m_settings.find(name) || m_defaults.find(name));
1009         }
1010
1011         std::string get(std::string name)
1012         {
1013                 core::map<std::string, std::string>::Node *n;
1014                 n = m_settings.find(name);
1015                 if(n == NULL)
1016                 {
1017                         n = m_defaults.find(name);
1018                         if(n == NULL)
1019                         {
1020                                 throw SettingNotFoundException("Setting not found");
1021                         }
1022                 }
1023
1024                 return n->getValue();
1025         }
1026
1027         bool getBool(std::string name)
1028         {
1029                 return is_yes(get(name));
1030         }
1031         
1032         bool getFlag(std::string name)
1033         {
1034                 try
1035                 {
1036                         return getBool(name);
1037                 }
1038                 catch(SettingNotFoundException &e)
1039                 {
1040                         return false;
1041                 }
1042         }
1043
1044         // Asks if empty
1045         bool getBoolAsk(std::string name, std::string question, bool def)
1046         {
1047                 // If it is in settings
1048                 if(m_settings.find(name))
1049                         return getBool(name);
1050                 
1051                 std::string s;
1052                 char templine[10];
1053                 std::cout<<question<<" [y/N]: ";
1054                 std::cin.getline(templine, 10);
1055                 s = templine;
1056
1057                 if(s == "")
1058                         return def;
1059
1060                 return is_yes(s);
1061         }
1062
1063         float getFloat(std::string name)
1064         {
1065                 float f;
1066                 std::istringstream vis(get(name));
1067                 vis>>f;
1068                 return f;
1069         }
1070
1071         u16 getU16(std::string name)
1072         {
1073                 return stoi(get(name), 0, 65535);
1074         }
1075
1076         u16 getU16Ask(std::string name, std::string question, u16 def)
1077         {
1078                 // If it is in settings
1079                 if(m_settings.find(name))
1080                         return getU16(name);
1081                 
1082                 std::string s;
1083                 char templine[10];
1084                 std::cout<<question<<" ["<<def<<"]: ";
1085                 std::cin.getline(templine, 10);
1086                 s = templine;
1087
1088                 if(s == "")
1089                         return def;
1090
1091                 return stoi(s, 0, 65535);
1092         }
1093
1094         s16 getS16(std::string name)
1095         {
1096                 return stoi(get(name), -32768, 32767);
1097         }
1098
1099         s32 getS32(std::string name)
1100         {
1101                 return stoi(get(name));
1102         }
1103
1104 private:
1105         core::map<std::string, std::string> m_settings;
1106         core::map<std::string, std::string> m_defaults;
1107 };
1108
1109 /*
1110         FIFO queue
1111 */
1112 template<typename T>
1113 class Queue
1114 {
1115 public:
1116         void push_back(T t)
1117         {
1118                 m_list.push_back(t);
1119         }
1120         
1121         T pop_front()
1122         {
1123                 if(m_list.size() == 0)
1124                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1125
1126                 typename core::list<T>::Iterator begin = m_list.begin();
1127                 T t = *begin;
1128                 m_list.erase(begin);
1129                 return t;
1130         }
1131
1132         u32 size()
1133         {
1134                 return m_list.size();
1135         }
1136
1137 protected:
1138         core::list<T> m_list;
1139 };
1140
1141 /*
1142         Thread-safe FIFO queue
1143 */
1144
1145 template<typename T>
1146 class MutexedQueue
1147 {
1148 public:
1149         MutexedQueue()
1150         {
1151                 m_mutex.Init();
1152         }
1153         u32 size()
1154         {
1155                 return m_list.size();
1156         }
1157         void push_back(T t)
1158         {
1159                 JMutexAutoLock lock(m_mutex);
1160                 m_list.push_back(t);
1161         }
1162         T pop_front(u32 wait_time_max_ms=0)
1163         {
1164                 u32 wait_time_ms = 0;
1165
1166                 for(;;)
1167                 {
1168                         {
1169                                 JMutexAutoLock lock(m_mutex);
1170
1171                                 if(m_list.size() > 0)
1172                                 {
1173                                         typename core::list<T>::Iterator begin = m_list.begin();
1174                                         T t = *begin;
1175                                         m_list.erase(begin);
1176                                         return t;
1177                                 }
1178
1179                                 if(wait_time_ms >= wait_time_max_ms)
1180                                         throw ItemNotFoundException("MutexedQueue: queue is empty");
1181                         }
1182
1183                         // Wait a while before trying again
1184                         sleep_ms(10);
1185                         wait_time_ms += 10;
1186                 }
1187         }
1188
1189         JMutex & getMutex()
1190         {
1191                 return m_mutex;
1192         }
1193
1194         core::list<T> & getList()
1195         {
1196                 return m_list;
1197         }
1198
1199 protected:
1200         JMutex m_mutex;
1201         core::list<T> m_list;
1202 };
1203
1204 template<typename Caller, typename Data>
1205 class CallerInfo
1206 {
1207 public:
1208         Caller caller;
1209         Data data;
1210 };
1211
1212 template<typename Key, typename T, typename Caller, typename CallerData>
1213 class GetResult
1214 {
1215 public:
1216         Key key;
1217         T item;
1218         core::list<CallerInfo<Caller, CallerData> > callers;
1219 };
1220
1221 template<typename Key, typename T, typename Caller, typename CallerData>
1222 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
1223 {
1224 };
1225
1226 template<typename Key, typename T, typename Caller, typename CallerData>
1227 class GetRequest
1228 {
1229 public:
1230         GetRequest()
1231         {
1232                 dest = NULL;
1233         }
1234         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
1235         {
1236                 dest = a_dest;
1237         }
1238         GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
1239                         Key a_key)
1240         {
1241                 dest = a_dest;
1242                 key = a_key;
1243         }
1244         ~GetRequest()
1245         {
1246         }
1247         
1248         Key key;
1249         ResultQueue<Key, T, Caller, CallerData> *dest;
1250         core::list<CallerInfo<Caller, CallerData> > callers;
1251 };
1252
1253 /*
1254         Quickhands for typical request-result queues.
1255         Used for distributing work between threads.
1256 */
1257
1258 template<typename Key, typename T, typename Caller, typename CallerData>
1259 class RequestQueue
1260 {
1261 public:
1262         u32 size()
1263         {
1264                 return m_queue.size();
1265         }
1266
1267         void add(Key key, Caller caller, CallerData callerdata,
1268                         ResultQueue<Key, T, Caller, CallerData> *dest)
1269         {
1270                 JMutexAutoLock lock(m_queue.getMutex());
1271                 
1272                 /*
1273                         If the caller is already on the list, only update CallerData
1274                 */
1275                 for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
1276                                 i = m_queue.getList().begin();
1277                                 i != m_queue.getList().end(); i++)
1278                 {
1279                         GetRequest<Key, T, Caller, CallerData> &request = *i;
1280
1281                         if(request.key == key)
1282                         {
1283                                 for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
1284                                                 i = request.callers.begin();
1285                                                 i != request.callers.end(); i++)
1286                                 {
1287                                         CallerInfo<Caller, CallerData> &ca = *i;
1288                                         if(ca.caller == caller)
1289                                         {
1290                                                 ca.data = callerdata;
1291                                                 return;
1292                                         }
1293                                 }
1294                                 CallerInfo<Caller, CallerData> ca;
1295                                 ca.caller = caller;
1296                                 ca.data = callerdata;
1297                                 request.callers.push_back(ca);
1298                                 return;
1299                         }
1300                 }
1301
1302                 /*
1303                         Else add a new request to the queue
1304                 */
1305
1306                 GetRequest<Key, T, Caller, CallerData> request;
1307                 request.key = key;
1308                 CallerInfo<Caller, CallerData> ca;
1309                 ca.caller = caller;
1310                 ca.data = callerdata;
1311                 request.callers.push_back(ca);
1312                 request.dest = dest;
1313                 
1314                 m_queue.getList().push_back(request);
1315         }
1316
1317         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
1318         {
1319                 return m_queue.pop_front(wait_if_empty);
1320         }
1321
1322 private:
1323         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
1324 };
1325
1326 // Pseudo-random (VC++ rand() sucks)
1327 int myrand(void);
1328 void mysrand(unsigned seed);
1329 #define MYRAND_MAX 32767
1330
1331 #endif
1332