3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
24 #ifndef UTILITY_HEADER
25 #define UTILITY_HEADER
27 #include "common_irrlicht.h"
30 #include "exceptions.h"
36 extern const v3s16 g_26dirs[26];
38 inline void writeU32(u8 *data, u32 i)
40 data[0] = ((i>>24)&0xff);
41 data[1] = ((i>>16)&0xff);
42 data[2] = ((i>> 8)&0xff);
43 data[3] = ((i>> 0)&0xff);
46 inline void writeU16(u8 *data, u16 i)
48 data[0] = ((i>> 8)&0xff);
49 data[1] = ((i>> 0)&0xff);
52 inline void writeU8(u8 *data, u8 i)
54 data[0] = ((i>> 0)&0xff);
57 inline u32 readU32(u8 *data)
59 return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
62 inline u16 readU16(u8 *data)
64 return (data[0]<<8) | (data[1]<<0);
67 inline u8 readU8(u8 *data)
72 // Signed variants of the above
74 inline void writeS32(u8 *data, s32 i){
75 writeU32(data, (u32)i);
77 inline s32 readS32(u8 *data){
78 return (s32)readU32(data);
81 inline void writeS16(u8 *data, s16 i){
82 writeU16(data, (u16)i);
84 inline s16 readS16(u8 *data){
85 return (s16)readU16(data);
88 inline void writeV3S32(u8 *data, v3s32 p)
90 writeS32(&data[0], p.X);
91 writeS32(&data[4], p.Y);
92 writeS32(&data[8], p.Z);
95 inline v3s32 readV3S32(u8 *data)
98 p.X = readS32(&data[0]);
99 p.Y = readS32(&data[4]);
100 p.Z = readS32(&data[8]);
104 inline void writeV2S16(u8 *data, v2s16 p)
106 writeS16(&data[0], p.X);
107 writeS16(&data[2], p.Y);
110 inline v2s16 readV2S16(u8 *data)
113 p.X = readS16(&data[0]);
114 p.Y = readS16(&data[2]);
118 inline void writeV2S32(u8 *data, v2s32 p)
120 writeS32(&data[0], p.X);
121 writeS32(&data[2], p.Y);
124 inline v2s32 readV2S32(u8 *data)
127 p.X = readS32(&data[0]);
128 p.Y = readS32(&data[2]);
132 inline void writeV3S16(u8 *data, v3s16 p)
134 writeS16(&data[0], p.X);
135 writeS16(&data[2], p.Y);
136 writeS16(&data[4], p.Z);
139 inline v3s16 readV3S16(u8 *data)
142 p.X = readS16(&data[0]);
143 p.Y = readS16(&data[2]);
144 p.Z = readS16(&data[4]);
149 None of these are used at the moment
152 template <typename T>
162 SharedPtr(SharedPtr<T> &t)
166 refcount = t.refcount;
174 SharedPtr<T> & operator=(T *t)
182 SharedPtr<T> & operator=(SharedPtr<T> &t)
185 refcount = t.refcount;
198 bool operator!=(T *t)
202 bool operator==(T *t)
209 assert((*refcount) > 0);
222 template <typename T>
226 Buffer(unsigned int size)
231 Buffer(const Buffer &buffer)
233 m_size = buffer.m_size;
234 data = new T[buffer.m_size];
235 memcpy(data, buffer.data, buffer.m_size);
237 Buffer(T *t, unsigned int size)
241 memcpy(data, t, size);
247 T & operator[](unsigned int i) const
251 T * operator*() const
255 unsigned int getSize() const
264 template <typename T>
268 SharedBuffer(unsigned int size)
272 refcount = new unsigned int;
275 SharedBuffer(const SharedBuffer &buffer)
277 //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
278 m_size = buffer.m_size;
280 refcount = buffer.refcount;
283 SharedBuffer & operator=(const SharedBuffer & buffer)
285 //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
289 m_size = buffer.m_size;
291 refcount = buffer.refcount;
298 SharedBuffer(T *t, unsigned int size)
302 memcpy(data, t, size);
303 refcount = new unsigned int;
309 SharedBuffer(const Buffer<T> &buffer)
311 m_size = buffer.m_size;
312 data = new T[buffer.getSize()];
313 memcpy(data, *buffer, buffer.getSize());
314 refcount = new unsigned int;
321 T & operator[](unsigned int i) const
325 T * operator*() const
329 unsigned int getSize() const
336 assert((*refcount) > 0);
346 unsigned int *refcount;
349 inline SharedBuffer<u8> SharedBufferFromString(const char *string)
351 SharedBuffer<u8> b((u8*)string, strlen(string)+1);
356 class MutexedVariable
359 MutexedVariable(T value):
367 JMutexAutoLock lock(m_mutex);
373 JMutexAutoLock lock(m_mutex);
377 // You'll want to grab this in a SharedPtr
378 JMutexAutoLock * getLock()
380 return new JMutexAutoLock(m_mutex);
383 // You pretty surely want to grab the lock when accessing this
397 TimeTaker(const char *name, IrrlichtDevice *dev)
401 m_time1 = m_dev->getTimer()->getRealTime();
408 u32 stop(bool quiet=false)
412 u32 time2 = m_dev->getTimer()->getRealTime();
413 u32 dtime = time2 - m_time1;
415 std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
423 IrrlichtDevice *m_dev;
428 // Calculates the borders of a "d-radius" cube
429 inline void getFacePositions(core::list<v3s16> &list, u16 d)
433 list.push_back(v3s16(0,0,0));
439 This is an optimized sequence of coordinates.
441 list.push_back(v3s16( 0, 0, 1)); // back
442 list.push_back(v3s16(-1, 0, 0)); // left
443 list.push_back(v3s16( 1, 0, 0)); // right
444 list.push_back(v3s16( 0, 0,-1)); // front
445 list.push_back(v3s16( 0,-1, 0)); // bottom
446 list.push_back(v3s16( 0, 1, 0)); // top
448 list.push_back(v3s16(-1, 0, 1)); // back left
449 list.push_back(v3s16( 1, 0, 1)); // back right
450 list.push_back(v3s16(-1, 0,-1)); // front left
451 list.push_back(v3s16( 1, 0,-1)); // front right
452 list.push_back(v3s16(-1,-1, 0)); // bottom left
453 list.push_back(v3s16( 1,-1, 0)); // bottom right
454 list.push_back(v3s16( 0,-1, 1)); // bottom back
455 list.push_back(v3s16( 0,-1,-1)); // bottom front
456 list.push_back(v3s16(-1, 1, 0)); // top left
457 list.push_back(v3s16( 1, 1, 0)); // top right
458 list.push_back(v3s16( 0, 1, 1)); // top back
459 list.push_back(v3s16( 0, 1,-1)); // top front
461 list.push_back(v3s16(-1, 1, 1)); // top back-left
462 list.push_back(v3s16( 1, 1, 1)); // top back-right
463 list.push_back(v3s16(-1, 1,-1)); // top front-left
464 list.push_back(v3s16( 1, 1,-1)); // top front-right
465 list.push_back(v3s16(-1,-1, 1)); // bottom back-left
466 list.push_back(v3s16( 1,-1, 1)); // bottom back-right
467 list.push_back(v3s16(-1,-1,-1)); // bottom front-left
468 list.push_back(v3s16( 1,-1,-1)); // bottom front-right
473 // Take blocks in all sides, starting from y=0 and going +-y
474 for(s16 y=0; y<=d-1; y++)
476 // Left and right side, including borders
477 for(s16 z=-d; z<=d; z++)
479 list.push_back(v3s16(d,y,z));
480 list.push_back(v3s16(-d,y,z));
483 list.push_back(v3s16(d,-y,z));
484 list.push_back(v3s16(-d,-y,z));
487 // Back and front side, excluding borders
488 for(s16 x=-d+1; x<=d-1; x++)
490 list.push_back(v3s16(x,y,d));
491 list.push_back(v3s16(x,y,-d));
494 list.push_back(v3s16(x,-y,d));
495 list.push_back(v3s16(x,-y,-d));
500 // Take the bottom and top face with borders
501 // -d<x<d, y=+-d, -d<z<d
502 for(s16 x=-d; x<=d; x++)
503 for(s16 z=-d; z<=d; z++)
505 list.push_back(v3s16(x,-d,z));
506 list.push_back(v3s16(x,d,z));
510 class IndentationRaiser
513 IndentationRaiser(u16 *indentation)
515 m_indentation = indentation;
526 inline s16 getContainerPos(s16 p, s16 d)
528 return (p>=0 ? p : p-d+1) / d;
531 inline v2s16 getContainerPos(v2s16 p, s16 d)
534 getContainerPos(p.X, d),
535 getContainerPos(p.Y, d)
539 inline v3s16 getContainerPos(v3s16 p, s16 d)
542 getContainerPos(p.X, d),
543 getContainerPos(p.Y, d),
544 getContainerPos(p.Z, d)
548 inline bool isInArea(v3s16 p, s16 d)
551 p.X >= 0 && p.X < d &&
552 p.Y >= 0 && p.Y < d &&
557 inline bool isInArea(v2s16 p, s16 d)
560 p.X >= 0 && p.X < d &&
565 inline std::wstring narrow_to_wide(const std::string& mbs)
567 size_t wcl = mbs.size();
568 SharedBuffer<wchar_t> wcs(wcl+1);
569 size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
574 inline std::string wide_to_narrow(const std::wstring& wcs)
576 size_t mbl = wcs.size()*4;
577 SharedBuffer<char> mbs(mbl+1);
578 size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
587 See test.cpp for example cases.
588 wraps degrees to the range of -360...360
589 NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
591 inline float wrapDegrees(float f)
593 // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
599 // NOTE: This would be used for wrapping to 0...360
605 // 10, 0.5, -0.5, -0.5
610 inline std::string lowercase(std::string s)
612 for(size_t i=0; i<s.size(); i++)
614 if(s[i] >= 'A' && s[i] <= 'Z')
620 inline bool is_yes(std::string s)
622 s = lowercase(trim(s));
623 if(s == "y" || s == "yes" || s == "true")
628 inline s32 stoi(std::string s, s32 min, s32 max)
630 s32 i = atoi(s.c_str());
638 inline s32 stoi(std::string s)
640 return atoi(s.c_str());
651 // Returns false on EOF
652 bool parseConfigObject(std::istream &is)
657 // NOTE: This function will be expanded to allow multi-line settings
659 std::getline(is, line);
660 //dstream<<"got line: \""<<line<<"\""<<std::endl;
662 std::string trimmedline = trim(line);
665 if(trimmedline[0] == '#')
668 //dstream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
670 Strfnd sf(trim(line));
672 std::string name = sf.next("=");
678 std::string value = sf.next("\n");
681 dstream<<"Config name=\""<<name<<"\" value=\""
682 <<value<<"\""<<std::endl;
684 m_settings[name] = value;
689 // Returns true on success
690 bool readConfigFile(const char *filename)
692 std::ifstream is(filename);
693 if(is.good() == false)
695 dstream<<"Error opening configuration file: "
696 <<filename<<std::endl;
700 dstream<<"Parsing configuration file: "
701 <<filename<<std::endl;
703 while(parseConfigObject(is));
708 void set(std::string name, std::string value)
710 m_settings[name] = value;
713 std::string get(std::string name)
715 core::map<std::string, std::string>::Node *n;
716 n = m_settings.find(name);
718 throw SettingNotFoundException("Setting not found");
720 return n->getValue();
723 bool getBool(std::string name)
725 return is_yes(get(name));
729 bool getBoolAsk(std::string name, std::string question, bool def)
731 std::string s = get(name);
736 std::cout<<question<<" [y/N]: ";
737 std::cin.getline(templine, 10);
746 float getFloat(std::string name)
749 std::istringstream vis(get(name));
754 u16 getU16(std::string name)
756 return stoi(get(name), 0, 65535);
759 u16 getU16Ask(std::string name, std::string question, u16 def)
761 std::string s = get(name);
763 return stoi(s, 0, 65535);
766 std::cout<<question<<" ["<<def<<"]: ";
767 std::cin.getline(templine, 10);
773 return stoi(s, 0, 65535);
776 s16 getS16(std::string name)
778 return stoi(get(name), -32768, 32767);
781 s32 getS32(std::string name)
783 return stoi(get(name));
787 core::map<std::string, std::string> m_settings;