summaryrefslogtreecommitdiff
path: root/src/utility.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/utility.h')
-rw-r--r--src/utility.h607
1 files changed, 607 insertions, 0 deletions
diff --git a/src/utility.h b/src/utility.h
new file mode 100644
index 000000000..4178e9d95
--- /dev/null
+++ b/src/utility.h
@@ -0,0 +1,607 @@
+/*
+(c) 2010 Perttu Ahola <celeron55@gmail.com>
+*/
+
+#ifndef UTILITY_HEADER
+#define UTILITY_HEADER
+
+#include "common_irrlicht.h"
+#include "debug.h"
+#include "strfnd.h"
+#include <iostream>
+#include <string>
+
+extern const v3s16 g_26dirs[26];
+
+inline void writeU32(u8 *data, u32 i)
+{
+ data[0] = ((i>>24)&0xff);
+ data[1] = ((i>>16)&0xff);
+ data[2] = ((i>> 8)&0xff);
+ data[3] = ((i>> 0)&0xff);
+}
+
+inline void writeU16(u8 *data, u16 i)
+{
+ data[0] = ((i>> 8)&0xff);
+ data[1] = ((i>> 0)&0xff);
+}
+
+inline void writeU8(u8 *data, u8 i)
+{
+ data[0] = ((i>> 0)&0xff);
+}
+
+inline u32 readU32(u8 *data)
+{
+ return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);
+}
+
+inline u16 readU16(u8 *data)
+{
+ return (data[0]<<8) | (data[1]<<0);
+}
+
+inline u8 readU8(u8 *data)
+{
+ return (data[0]<<0);
+}
+
+// Signed variants of the above
+
+inline void writeS32(u8 *data, s32 i){
+ writeU32(data, (u32)i);
+}
+inline s32 readS32(u8 *data){
+ return (s32)readU32(data);
+}
+
+inline void writeS16(u8 *data, s16 i){
+ writeU16(data, (u16)i);
+}
+inline s16 readS16(u8 *data){
+ return (s16)readU16(data);
+}
+
+inline void writeV3S32(u8 *data, v3s32 p)
+{
+ writeS32(&data[0], p.X);
+ writeS32(&data[4], p.Y);
+ writeS32(&data[8], p.Z);
+}
+
+inline v3s32 readV3S32(u8 *data)
+{
+ v3s32 p;
+ p.X = readS32(&data[0]);
+ p.Y = readS32(&data[4]);
+ p.Z = readS32(&data[8]);
+ return p;
+}
+
+inline void writeV2S16(u8 *data, v2s16 p)
+{
+ writeS16(&data[0], p.X);
+ writeS16(&data[2], p.Y);
+}
+
+inline v2s16 readV2S16(u8 *data)
+{
+ v2s16 p;
+ p.X = readS16(&data[0]);
+ p.Y = readS16(&data[2]);
+ return p;
+}
+
+inline void writeV2S32(u8 *data, v2s32 p)
+{
+ writeS32(&data[0], p.X);
+ writeS32(&data[2], p.Y);
+}
+
+inline v2s32 readV2S32(u8 *data)
+{
+ v2s32 p;
+ p.X = readS32(&data[0]);
+ p.Y = readS32(&data[2]);
+ return p;
+}
+
+inline void writeV3S16(u8 *data, v3s16 p)
+{
+ writeS16(&data[0], p.X);
+ writeS16(&data[2], p.Y);
+ writeS16(&data[4], p.Z);
+}
+
+inline v3s16 readV3S16(u8 *data)
+{
+ v3s16 p;
+ p.X = readS16(&data[0]);
+ p.Y = readS16(&data[2]);
+ p.Z = readS16(&data[4]);
+ return p;
+}
+
+/*
+ None of these are used at the moment
+*/
+
+template <typename T>
+class SharedPtr
+{
+public:
+ SharedPtr(T *t=NULL)
+ {
+ refcount = new int;
+ *refcount = 1;
+ ptr = t;
+ }
+ SharedPtr(SharedPtr<T> &t)
+ {
+ //*this = t;
+ drop();
+ refcount = t.refcount;
+ (*refcount)++;
+ ptr = t.ptr;
+ }
+ ~SharedPtr()
+ {
+ drop();
+ }
+ SharedPtr<T> & operator=(T *t)
+ {
+ drop();
+ refcount = new int;
+ *refcount = 1;
+ ptr = t;
+ return *this;
+ }
+ SharedPtr<T> & operator=(SharedPtr<T> &t)
+ {
+ drop();
+ refcount = t.refcount;
+ (*refcount)++;
+ ptr = t.ptr;
+ return *this;
+ }
+ T* operator->()
+ {
+ return ptr;
+ }
+ T & operator*()
+ {
+ return *ptr;
+ }
+ bool operator!=(T *t)
+ {
+ return ptr != t;
+ }
+ bool operator==(T *t)
+ {
+ return ptr == t;
+ }
+private:
+ void drop()
+ {
+ assert((*refcount) > 0);
+ (*refcount)--;
+ if(*refcount == 0)
+ {
+ delete refcount;
+ if(ptr != NULL)
+ delete ptr;
+ }
+ }
+ T *ptr;
+ int *refcount;
+};
+
+template <typename T>
+class Buffer
+{
+public:
+ Buffer(unsigned int size)
+ {
+ m_size = size;
+ data = new T[size];
+ }
+ Buffer(const Buffer &buffer)
+ {
+ m_size = buffer.m_size;
+ data = new T[buffer.m_size];
+ memcpy(data, buffer.data, buffer.m_size);
+ }
+ Buffer(T *t, unsigned int size)
+ {
+ m_size = size;
+ data = new T[size];
+ memcpy(data, t, size);
+ }
+ ~Buffer()
+ {
+ delete[] data;
+ }
+ T & operator[](unsigned int i) const
+ {
+ return data[i];
+ }
+ T * operator*() const
+ {
+ return data;
+ }
+ unsigned int getSize() const
+ {
+ return m_size;
+ }
+private:
+ T *data;
+ unsigned int m_size;
+};
+
+template <typename T>
+class SharedBuffer
+{
+public:
+ SharedBuffer(unsigned int size)
+ {
+ m_size = size;
+ data = new T[size];
+ refcount = new unsigned int;
+ (*refcount) = 1;
+ }
+ SharedBuffer(const SharedBuffer &buffer)
+ {
+ //std::cout<<"SharedBuffer(const SharedBuffer &buffer)"<<std::endl;
+ m_size = buffer.m_size;
+ data = buffer.data;
+ refcount = buffer.refcount;
+ (*refcount)++;
+ }
+ SharedBuffer & operator=(const SharedBuffer & buffer)
+ {
+ //std::cout<<"SharedBuffer & operator=(const SharedBuffer & buffer)"<<std::endl;
+ if(this == &buffer)
+ return *this;
+ drop();
+ m_size = buffer.m_size;
+ data = buffer.data;
+ refcount = buffer.refcount;
+ (*refcount)++;
+ return *this;
+ }
+ /*
+ Copies whole buffer
+ */
+ SharedBuffer(T *t, unsigned int size)
+ {
+ m_size = size;
+ data = new T[size];
+ memcpy(data, t, size);
+ refcount = new unsigned int;
+ (*refcount) = 1;
+ }
+ /*
+ Copies whole buffer
+ */
+ SharedBuffer(const Buffer<T> &buffer)
+ {
+ m_size = buffer.m_size;
+ data = new T[buffer.getSize()];
+ memcpy(data, *buffer, buffer.getSize());
+ refcount = new unsigned int;
+ (*refcount) = 1;
+ }
+ ~SharedBuffer()
+ {
+ drop();
+ }
+ T & operator[](unsigned int i) const
+ {
+ return data[i];
+ }
+ T * operator*() const
+ {
+ return data;
+ }
+ unsigned int getSize() const
+ {
+ return m_size;
+ }
+private:
+ void drop()
+ {
+ assert((*refcount) > 0);
+ (*refcount)--;
+ if(*refcount == 0)
+ {
+ delete[] data;
+ delete refcount;
+ }
+ }
+ T *data;
+ unsigned int m_size;
+ unsigned int *refcount;
+};
+
+inline SharedBuffer<u8> SharedBufferFromString(const char *string)
+{
+ SharedBuffer<u8> b((u8*)string, strlen(string)+1);
+ return b;
+}
+
+template<typename T>
+class MutexedVariable
+{
+public:
+ MutexedVariable(T value):
+ m_value(value)
+ {
+ m_mutex.Init();
+ }
+
+ T get()
+ {
+ JMutexAutoLock lock(m_mutex);
+ return m_value;
+ }
+
+ void set(T value)
+ {
+ JMutexAutoLock lock(m_mutex);
+ m_value = value;
+ }
+
+ // You'll want to grab this in a SharedPtr
+ JMutexAutoLock * getLock()
+ {
+ return new JMutexAutoLock(m_mutex);
+ }
+
+ // You pretty surely want to grab the lock when accessing this
+ T m_value;
+
+private:
+ JMutex m_mutex;
+};
+
+/*
+ TimeTaker
+*/
+
+class TimeTaker
+{
+public:
+ TimeTaker(const char *name, IrrlichtDevice *dev)
+ {
+ m_name = name;
+ m_dev = dev;
+ m_time1 = m_dev->getTimer()->getRealTime();
+ m_running = true;
+ }
+ ~TimeTaker()
+ {
+ stop();
+ }
+ u32 stop(bool quiet=false)
+ {
+ if(m_running)
+ {
+ u32 time2 = m_dev->getTimer()->getRealTime();
+ u32 dtime = time2 - m_time1;
+ if(quiet == false)
+ std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
+ m_running = false;
+ return dtime;
+ }
+ return 0;
+ }
+private:
+ const char *m_name;
+ IrrlichtDevice *m_dev;
+ u32 m_time1;
+ bool m_running;
+};
+
+// Calculates the borders of a "d-radius" cube
+inline void getFacePositions(core::list<v3s16> &list, u16 d)
+{
+ if(d == 0)
+ {
+ list.push_back(v3s16(0,0,0));
+ return;
+ }
+ if(d == 1)
+ {
+ /*
+ This is an optimized sequence of coordinates.
+ */
+ list.push_back(v3s16( 0, 0, 1)); // back
+ list.push_back(v3s16(-1, 0, 0)); // left
+ list.push_back(v3s16( 1, 0, 0)); // right
+ list.push_back(v3s16( 0, 0,-1)); // front
+ list.push_back(v3s16( 0,-1, 0)); // bottom
+ list.push_back(v3s16( 0, 1, 0)); // top
+ // 6
+ list.push_back(v3s16(-1, 0, 1)); // back left
+ list.push_back(v3s16( 1, 0, 1)); // back right
+ list.push_back(v3s16(-1, 0,-1)); // front left
+ list.push_back(v3s16( 1, 0,-1)); // front right
+ list.push_back(v3s16(-1,-1, 0)); // bottom left
+ list.push_back(v3s16( 1,-1, 0)); // bottom right
+ list.push_back(v3s16( 0,-1, 1)); // bottom back
+ list.push_back(v3s16( 0,-1,-1)); // bottom front
+ list.push_back(v3s16(-1, 1, 0)); // top left
+ list.push_back(v3s16( 1, 1, 0)); // top right
+ list.push_back(v3s16( 0, 1, 1)); // top back
+ list.push_back(v3s16( 0, 1,-1)); // top front
+ // 18
+ list.push_back(v3s16(-1, 1, 1)); // top back-left
+ list.push_back(v3s16( 1, 1, 1)); // top back-right
+ list.push_back(v3s16(-1, 1,-1)); // top front-left
+ list.push_back(v3s16( 1, 1,-1)); // top front-right
+ list.push_back(v3s16(-1,-1, 1)); // bottom back-left
+ list.push_back(v3s16( 1,-1, 1)); // bottom back-right
+ list.push_back(v3s16(-1,-1,-1)); // bottom front-left
+ list.push_back(v3s16( 1,-1,-1)); // bottom front-right
+ // 26
+ return;
+ }
+
+ // Take blocks in all sides, starting from y=0 and going +-y
+ for(s16 y=0; y<=d-1; y++)
+ {
+ // Left and right side, including borders
+ for(s16 z=-d; z<=d; z++)
+ {
+ list.push_back(v3s16(d,y,z));
+ list.push_back(v3s16(-d,y,z));
+ if(y != 0)
+ {
+ list.push_back(v3s16(d,-y,z));
+ list.push_back(v3s16(-d,-y,z));
+ }
+ }
+ // Back and front side, excluding borders
+ for(s16 x=-d+1; x<=d-1; x++)
+ {
+ list.push_back(v3s16(x,y,d));
+ list.push_back(v3s16(x,y,-d));
+ if(y != 0)
+ {
+ list.push_back(v3s16(x,-y,d));
+ list.push_back(v3s16(x,-y,-d));
+ }
+ }
+ }
+
+ // Take the bottom and top face with borders
+ // -d<x<d, y=+-d, -d<z<d
+ for(s16 x=-d; x<=d; x++)
+ for(s16 z=-d; z<=d; z++)
+ {
+ list.push_back(v3s16(x,-d,z));
+ list.push_back(v3s16(x,d,z));
+ }
+}
+
+class IndentationRaiser
+{
+public:
+ IndentationRaiser(u16 *indentation)
+ {
+ m_indentation = indentation;
+ (*m_indentation)++;
+ }
+ ~IndentationRaiser()
+ {
+ (*m_indentation)--;
+ }
+private:
+ u16 *m_indentation;
+};
+
+inline s16 getContainerPos(s16 p, s16 d)
+{
+ return (p>=0 ? p : p-d+1) / d;
+}
+
+inline v2s16 getContainerPos(v2s16 p, s16 d)
+{
+ return v2s16(
+ getContainerPos(p.X, d),
+ getContainerPos(p.Y, d)
+ );
+}
+
+inline v3s16 getContainerPos(v3s16 p, s16 d)
+{
+ return v3s16(
+ getContainerPos(p.X, d),
+ getContainerPos(p.Y, d),
+ getContainerPos(p.Z, d)
+ );
+}
+
+inline bool isInArea(v3s16 p, s16 d)
+{
+ return (
+ p.X >= 0 && p.X < d &&
+ p.Y >= 0 && p.Y < d &&
+ p.Z >= 0 && p.Z < d
+ );
+}
+
+inline bool isInArea(v2s16 p, s16 d)
+{
+ return (
+ p.X >= 0 && p.X < d &&
+ p.Y >= 0 && p.Y < d
+ );
+}
+
+inline std::wstring narrow_to_wide(const std::string& mbs)
+{
+ size_t wcl = mbs.size();
+ SharedBuffer<wchar_t> wcs(wcl+1);
+ size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
+ wcs[l] = 0;
+ return *wcs;
+}
+
+inline std::string wide_to_narrow(const std::wstring& wcs)
+{
+ size_t mbl = wcs.size()*4;
+ SharedBuffer<char> mbs(mbl+1);
+ size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
+ if((int)l == -1)
+ mbs[0] = 0;
+ else
+ mbs[l] = 0;
+ return *mbs;
+}
+
+/*
+ See test.cpp for example cases.
+ wraps degrees to the range of -360...360
+ NOTE: Wrapping to 0...360 is not used because pitch needs negative values.
+*/
+inline float wrapDegrees(float f)
+{
+ // Take examples of f=10, f=720.5, f=-0.5, f=-360.5
+ // This results in
+ // 10, 720, -1, -361
+ int i = floor(f);
+ // 0, 2, 0, -1
+ int l = i / 360;
+ // NOTE: This would be used for wrapping to 0...360
+ // 0, 2, -1, -2
+ /*if(i < 0)
+ l -= 1;*/
+ // 0, 720, 0, -360
+ int k = l * 360;
+ // 10, 0.5, -0.5, -0.5
+ f -= float(k);
+ return f;
+}
+
+inline std::string lowercase(std::string s)
+{
+ for(size_t i=0; i<s.size(); i++)
+ {
+ if(s[i] >= 'A' && s[i] <= 'Z')
+ s[i] -= 'A' - 'a';
+ }
+ return s;
+}
+
+inline bool is_yes(std::string s)
+{
+ s = lowercase(trim(s));
+ if(s == "y" || s == "yes" || s == "true")
+ return true;
+ return false;
+}
+
+#endif
+