X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futility.h;h=aa64c28bb601ceb3be158917d939c461c60a89ed;hb=45f78bdf40e273de7598f74c66411d5f42a347fa;hp=497f79fa0dfed76ca441ec5e11824feb5b90a4d0;hpb=aed9e809a19bffdf911f75dd9d718efb8decd2c1;p=dragonfireclient.git diff --git a/src/utility.h b/src/utility.h index 497f79fa0..aa64c28bb 100644 --- a/src/utility.h +++ b/src/utility.h @@ -28,12 +28,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include "common_irrlicht.h" #include "debug.h" -#include "strfnd.h" #include "exceptions.h" #include "porting.h" +#include "strfnd.h" // For trim() extern const v3s16 g_6dirs[6]; @@ -103,13 +104,6 @@ inline s32 readS32(u8 *data){ return (s32)readU32(data); } -inline void writeF1000(u8 *data, f32 i){ - writeS32(data, i*1000); -} -inline f32 readF1000(u8 *data){ - return (f32)readS32(data)/1000.; -} - inline void writeS16(u8 *data, s16 i){ writeU16(data, (u16)i); } @@ -117,6 +111,20 @@ inline s16 readS16(u8 *data){ return (s16)readU16(data); } +inline void writeS8(u8 *data, s8 i){ + writeU8(data, (u8)i); +} +inline s8 readS8(u8 *data){ + return (s8)readU8(data); +} + +inline void writeF1000(u8 *data, f32 i){ + writeS32(data, i*1000); +} +inline f32 readF1000(u8 *data){ + return (f32)readS32(data)/1000.; +} + inline void writeV3S32(u8 *data, v3s32 p) { writeS32(&data[0], p.X); @@ -147,6 +155,19 @@ inline v3f readV3F1000(u8 *data) return p; } +inline void writeV2F1000(u8 *data, v2f p) +{ + writeF1000(&data[0], p.X); + writeF1000(&data[4], p.Y); +} +inline v2f readV2F1000(u8 *data) +{ + v2f p; + p.X = (float)readF1000(&data[0]); + p.Y = (float)readF1000(&data[4]); + return p; +} + inline void writeV2S16(u8 *data, v2s16 p) { writeS16(&data[0], p.X); @@ -221,32 +242,68 @@ inline u16 readU16(std::istream &is) return readU16((u8*)buf); } -inline void writeU32(std::ostream &os, u16 p) +inline void writeU32(std::ostream &os, u32 p) { char buf[4]; - writeU16((u8*)buf, p); + writeU32((u8*)buf, p); os.write(buf, 4); } -inline u16 readU32(std::istream &is) +inline u32 readU32(std::istream &is) { char buf[4]; is.read(buf, 4); return readU32((u8*)buf); } -inline void writeF1000(std::ostream &os, f32 p) +inline void writeS32(std::ostream &os, s32 p) +{ + char buf[4]; + writeS32((u8*)buf, p); + os.write(buf, 4); +} +inline s32 readS32(std::istream &is) +{ + char buf[4]; + is.read(buf, 4); + return readS32((u8*)buf); +} + +inline void writeS16(std::ostream &os, s16 p) { char buf[2]; - writeF1000((u8*)buf, p); + writeS16((u8*)buf, p); os.write(buf, 2); } -inline f32 readF1000(std::istream &is) +inline s16 readS16(std::istream &is) { char buf[2]; is.read(buf, 2); - // TODO: verify if this gets rid of the valgrind warning - //if(is.gcount() != 2) - // return 0; + return readS16((u8*)buf); +} + +inline void writeS8(std::ostream &os, s8 p) +{ + char buf[1]; + writeS8((u8*)buf, p); + os.write(buf, 1); +} +inline s8 readS8(std::istream &is) +{ + char buf[1]; + is.read(buf, 1); + return readS8((u8*)buf); +} + +inline void writeF1000(std::ostream &os, f32 p) +{ + char buf[4]; + writeF1000((u8*)buf, p); + os.write(buf, 4); +} +inline f32 readF1000(std::istream &is) +{ + char buf[4]; + is.read(buf, 4); return readF1000((u8*)buf); } @@ -263,6 +320,45 @@ inline v3f readV3F1000(std::istream &is) return readV3F1000((u8*)buf); } +inline void writeV2F1000(std::ostream &os, v2f p) +{ + char buf[8]; + writeV2F1000((u8*)buf, p); + os.write(buf, 8); +} +inline v2f readV2F1000(std::istream &is) +{ + char buf[8]; + is.read(buf, 8); + return readV2F1000((u8*)buf); +} + +inline void writeV2S16(std::ostream &os, v2s16 p) +{ + char buf[4]; + writeV2S16((u8*)buf, p); + os.write(buf, 4); +} +inline v2s16 readV2S16(std::istream &is) +{ + char buf[4]; + is.read(buf, 4); + return readV2S16((u8*)buf); +} + +inline void writeV3S16(std::ostream &os, v3s16 p) +{ + char buf[6]; + writeV3S16((u8*)buf, p); + os.write(buf, 6); +} +inline v3s16 readV3S16(std::istream &is) +{ + char buf[6]; + is.read(buf, 6); + return readV3S16((u8*)buf); +} + /* None of these are used at the moment */ @@ -345,26 +441,59 @@ template class Buffer { public: + Buffer() + { + m_size = 0; + data = NULL; + } Buffer(unsigned int size) { m_size = size; - data = new T[size]; + if(size != 0) + data = new T[size]; + else + data = NULL; } Buffer(const Buffer &buffer) { m_size = buffer.m_size; - data = new T[buffer.m_size]; - memcpy(data, buffer.data, buffer.m_size); + if(m_size != 0) + { + data = new T[buffer.m_size]; + memcpy(data, buffer.data, buffer.m_size); + } + else + data = NULL; } - Buffer(T *t, unsigned int size) + Buffer(const T *t, unsigned int size) { m_size = size; - data = new T[size]; - memcpy(data, t, size); + if(size != 0) + { + data = new T[size]; + memcpy(data, t, size); + } + else + data = NULL; } ~Buffer() { - delete[] data; + drop(); + } + Buffer& operator=(const Buffer &buffer) + { + if(this == &buffer) + return *this; + drop(); + m_size = buffer.m_size; + if(m_size != 0) + { + data = new T[buffer.m_size]; + memcpy(data, buffer.data, buffer.m_size); + } + else + data = NULL; + return *this; } T & operator[](unsigned int i) const { @@ -379,6 +508,11 @@ class Buffer return m_size; } private: + void drop() + { + if(data) + delete[] data; + } T *data; unsigned int m_size; }; @@ -473,6 +607,10 @@ class SharedBuffer { return m_size; } + operator Buffer() const + { + return Buffer(data, m_size); + } private: void drop() { @@ -556,6 +694,46 @@ class TimeTaker u32 *m_result; }; +// Tests if two strings are equal, optionally case insensitive +inline bool str_equal(const std::wstring& s1, const std::wstring& s2, + bool case_insensitive = false) +{ + if(case_insensitive) + { + if(s1.size() != s2.size()) + return false; + for(size_t i = 0; i < s1.size(); ++i) + if(tolower(s1[i]) != tolower(s2[i])) + return false; + return true; + } + else + { + return s1 == s2; + } +} + +// Tests if the second string is a prefix of the first, optionally case insensitive +inline bool str_starts_with(const std::wstring& str, const std::wstring& prefix, + bool case_insensitive = false) +{ + if(str.size() < prefix.size()) + return false; + if(case_insensitive) + { + for(size_t i = 0; i < prefix.size(); ++i) + if(tolower(str[i]) != tolower(prefix[i])) + return false; + } + else + { + for(size_t i = 0; i < prefix.size(); ++i) + if(str[i] != prefix[i]) + return false; + } + return true; +} + // Calculates the borders of a "d-radius" cube inline void getFacePositions(core::list &list, u16 d) { @@ -807,6 +985,35 @@ inline float wrapDegrees(float f) return f; } +/* Wrap to 0...360 */ +inline float wrapDegrees_0_360(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; + // Wrap 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; +} + +/* Wrap to -180...180 */ +inline float wrapDegrees_180(float f) +{ + f += 180; + f = wrapDegrees_0_360(f); + f -= 180; + return f; +} + inline std::string lowercase(const std::string &s) { std::string s2; @@ -828,7 +1035,7 @@ inline bool is_yes(const std::string &s) return false; } -inline s32 stoi(const std::string &s, s32 min, s32 max) +inline s32 mystoi(const std::string &s, s32 min, s32 max) { s32 i = atoi(s.c_str()); if(i < min) @@ -840,19 +1047,19 @@ inline s32 stoi(const std::string &s, s32 min, s32 max) // MSVC2010 includes it's own versions of these -#if !defined(_MSC_VER) || _MSC_VER < 1600 +//#if !defined(_MSC_VER) || _MSC_VER < 1600 -inline s32 stoi(std::string s) +inline s32 mystoi(std::string s) { return atoi(s.c_str()); } -inline s32 stoi(std::wstring s) +inline s32 mystoi(std::wstring s) { return atoi(wide_to_narrow(s).c_str()); } -inline float stof(std::string s) +inline float mystof(std::string s) { float f; std::istringstream ss(s); @@ -860,7 +1067,10 @@ inline float stof(std::string s) return f; } -#endif +//#endif + +#define stoi mystoi +#define stof mystof inline std::string itos(s32 i) { @@ -938,547 +1148,6 @@ class SimpleThread : public JThread } }; -/* - Config stuff -*/ - -enum ValueType -{ - VALUETYPE_STRING, - VALUETYPE_FLAG // Doesn't take any arguments -}; - -struct ValueSpec -{ - ValueSpec(ValueType a_type, const char *a_help=NULL) - { - type = a_type; - help = a_help; - } - ValueType type; - const char *help; -}; - -class Settings -{ -public: - Settings() - { - m_mutex.Init(); - } - - void writeLines(std::ostream &os) - { - JMutexAutoLock lock(m_mutex); - - for(core::map::Iterator - i = m_settings.getIterator(); - i.atEnd() == false; i++) - { - std::string name = i.getNode()->getKey(); - std::string value = i.getNode()->getValue(); - os< &dst, - core::map &updated) - { - JMutexAutoLock lock(m_mutex); - - if(is.eof()) - return false; - - // NOTE: This function will be expanded to allow multi-line settings - std::string line; - std::getline(is, line); - - std::string trimmedline = trim(line); - - std::string line_end = ""; - if(is.eof() == false) - line_end = "\n"; - - // Ignore comments - if(trimmedline[0] == '#') - { - dst.push_back(line+line_end); - return true; - } - - Strfnd sf(trim(line)); - - std::string name = sf.next("="); - name = trim(name); - - if(name == "") - { - dst.push_back(line+line_end); - return true; - } - - std::string value = sf.next("\n"); - value = trim(value); - - if(m_settings.find(name)) - { - std::string newvalue = m_settings[name]; - - if(newvalue != value) - { - dstream<<"Changing value of \""< \""< objects; - core::map updated; - - // Read and modify stuff - { - std::ifstream is(filename); - if(is.good() == false) - { - dstream<<"INFO: updateConfigFile():" - " Error opening configuration file" - " for reading: \"" - <::Iterator - i = objects.begin(); - i != objects.end(); i++) - { - os<<(*i); - } - - /* - Write stuff that was not already in the file - */ - for(core::map::Iterator - i = m_settings.getIterator(); - i.atEnd() == false; i++) - { - if(updated.find(i.getNode()->getKey())) - continue; - std::string name = i.getNode()->getKey(); - std::string value = i.getNode()->getValue(); - dstream<<"Adding \""< &allowed_options) - { - int i=1; - for(;;) - { - if(i >= argc) - break; - std::string argname = argv[i]; - if(argname.substr(0, 2) != "--") - { - dstream<<"Invalid command-line parameter \"" - < expected."<::Node *n; - n = allowed_options.find(name); - if(n == NULL) - { - dstream<<"Unknown command-line parameter \"" - <getValue().type; - - std::string value = ""; - - if(type == VALUETYPE_FLAG) - { - value = "true"; - } - else - { - if(i >= argc) - { - dstream<<"Invalid command-line parameter \"" - <::Node *n; - n = m_settings.find(name); - if(n == NULL) - { - n = m_defaults.find(name); - if(n == NULL) - { - dstream<<"INFO: Settings: Setting not found: \"" - <getValue(); - } - - bool getBool(std::string name) - { - return is_yes(get(name)); - } - - bool getFlag(std::string name) - { - try - { - return getBool(name); - } - catch(SettingNotFoundException &e) - { - return false; - } - } - - // Asks if empty - bool getBoolAsk(std::string name, std::string question, bool def) - { - // If it is in settings - if(exists(name)) - return getBool(name); - - std::string s; - char templine[10]; - std::cout<>value; - return value; - } - - void setBool(std::string name, bool value) - { - if(value) - set(name, "true"); - else - set(name, "false"); - } - - void setS32(std::string name, s32 value) - { - set(name, itos(value)); - } - - void setFloat(std::string name, float value) - { - set(name, ftos(value)); - } - - void setV3F(std::string name, v3f value) - { - std::ostringstream os; - os<<"("<::Iterator - i = other.m_settings.getIterator(); - i.atEnd() == false; i++) - { - m_settings.insert(i.getNode()->getKey(), - i.getNode()->getValue()); - } - - for(core::map::Iterator - i = other.m_defaults.getIterator(); - i.atEnd() == false; i++) - { - m_defaults.insert(i.getNode()->getKey(), - i.getNode()->getValue()); - } - - } - - Settings & operator=(Settings &other) - { - JMutexAutoLock lock(m_mutex); - JMutexAutoLock lock2(other.m_mutex); - - if(&other == this) - return *this; - - clear(); - (*this) += other; - - return *this; - } - -private: - core::map m_settings; - core::map m_defaults; - // All methods that access m_settings/m_defaults directly should lock this. - JMutex m_mutex; -}; - /* FIFO queue (well, actually a FILO also) */ @@ -1739,27 +1408,14 @@ int myrand(void); void mysrand(unsigned seed); #define MYRAND_MAX 32767 -inline int myrand_range(int min, int max) -{ - if(max-min > MYRAND_MAX) - { - dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"< max) - { - assert(0); - return max; - } - return (myrand()%(max-min+1))+min; -} +int myrand_range(int min, int max); /* Miscellaneous functions */ -bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, f32 range, - f32 *distance_ptr=NULL); +bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, + f32 camera_fov, f32 range, f32 *distance_ptr=NULL); /* Queue with unique values with fast checking of value existence @@ -1949,6 +1605,15 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen) #define MYMIN(a,b) ((a)<(b)?(a):(b)) #define MYMAX(a,b) ((a)>(b)?(a):(b)) +/* + Returns nearest 32-bit integer for given floating point number. + and in VC++ don't provide round(). +*/ +inline s32 myround(f32 f) +{ + return floor(f + 0.5); +} + /* Returns integer position of node in given floating point position */ @@ -2078,6 +1743,12 @@ inline std::string deSerializeLongString(std::istream &is) return s; } +// Creates a string encoded in JSON format (almost equivalent to a C string literal) +std::string serializeJsonString(const std::string &plain); + +// Reads a string encoded in JSON format +std::string deSerializeJsonString(std::istream &is); + // inline u32 time_to_daynight_ratio(u32 time_of_day) @@ -2135,7 +1806,73 @@ class IntervalLimiter float m_accumulator; }; +/* + Splits a list into "pages". For example, the list [1,2,3,4,5] split + into two pages would be [1,2,3],[4,5]. This function computes the + minimum and maximum indices of a single page. + + length: Length of the list that should be split + page: Page number, 1 <= page <= pagecount + pagecount: The number of pages, >= 1 + minindex: Receives the minimum index (inclusive). + maxindex: Receives the maximum index (exclusive). + + Ensures 0 <= minindex <= maxindex <= length. +*/ +inline void paging(u32 length, u32 page, u32 pagecount, u32 &minindex, u32 &maxindex) +{ + if(length < 1 || pagecount < 1 || page < 1 || page > pagecount) + { + // Special cases or invalid parameters + minindex = maxindex = 0; + } + else if(pagecount <= length) + { + // Less pages than entries in the list: + // Each page contains at least one entry + minindex = (length * (page-1) + (pagecount-1)) / pagecount; + maxindex = (length * page + (pagecount-1)) / pagecount; + } + else + { + // More pages than entries in the list: + // Make sure the empty pages are at the end + if(page < length) + { + minindex = page-1; + maxindex = page; + } + else + { + minindex = 0; + maxindex = 0; + } + } +} + std::string translatePassword(std::string playername, std::wstring password); +enum PointedThingType +{ + POINTEDTHING_NOTHING, + POINTEDTHING_NODE, + POINTEDTHING_OBJECT +}; + +struct PointedThing +{ + PointedThingType type; + v3s16 node_undersurface; + v3s16 node_abovesurface; + s16 object_id; + + PointedThing(); + std::string dump() const; + void serialize(std::ostream &os) const; + void deSerialize(std::istream &is); + bool operator==(const PointedThing &pt2) const; + bool operator!=(const PointedThing &pt2) const; +}; + #endif