Footsteps: Fix offset footstep and shallow water sound bugs
[oweals/minetest.git] / src / util / serialize.cpp
index 0d38b960866c157fc1ac01683e4a27a6058300a6..61d369bc487f3a5ae8099c228cb09568237bc47d 100644 (file)
@@ -28,6 +28,77 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iomanip>
 #include <vector>
 
+SerializationError eof_ser_err("Attempted read past end of data");
+
+////
+//// BufReader
+////
+
+bool BufReader::getStringNoEx(std::string *val)
+{
+       u16 num_chars;
+       if (!getU16NoEx(&num_chars))
+               return false;
+
+       if (pos + num_chars > size) {
+               pos -= sizeof(num_chars);
+               return false;
+       }
+
+       val->assign((const char *)data + pos, num_chars);
+       pos += num_chars;
+
+       return true;
+}
+
+bool BufReader::getWideStringNoEx(std::wstring *val)
+{
+       u16 num_chars;
+       if (!getU16NoEx(&num_chars))
+               return false;
+
+       if (pos + num_chars * 2 > size) {
+               pos -= sizeof(num_chars);
+               return false;
+       }
+
+       for (size_t i = 0; i != num_chars; i++) {
+               val->push_back(readU16(data + pos));
+               pos += 2;
+       }
+
+       return true;
+}
+
+bool BufReader::getLongStringNoEx(std::string *val)
+{
+       u32 num_chars;
+       if (!getU32NoEx(&num_chars))
+               return false;
+
+       if (pos + num_chars > size) {
+               pos -= sizeof(num_chars);
+               return false;
+       }
+
+       val->assign((const char *)data + pos, num_chars);
+       pos += num_chars;
+
+       return true;
+}
+
+bool BufReader::getRawDataNoEx(void *val, size_t len)
+{
+       if (pos + len > size)
+               return false;
+
+       memcpy(val, data + pos, len);
+       pos += len;
+
+       return true;
+}
+
+
 ////
 //// String
 ////
@@ -37,7 +108,7 @@ std::string serializeString(const std::string &plain)
        std::string s;
        char buf[2];
 
-       if (plain.size() > 65535)
+       if (plain.size() > STRING_MAX_LEN)
                throw SerializationError("String too long for serializeString");
 
        writeU16((u8 *)&buf[0], plain.size());
@@ -79,8 +150,8 @@ std::string serializeWideString(const std::wstring &plain)
        std::string s;
        char buf[2];
 
-       if (plain.size() > 65535)
-               throw SerializationError("String too long for serializeString");
+       if (plain.size() > WIDE_STRING_MAX_LEN)
+               throw SerializationError("String too long for serializeWideString");
 
        writeU16((u8 *)buf, plain.size());
        s.append(buf, 2);
@@ -99,7 +170,7 @@ std::wstring deSerializeWideString(std::istream &is)
 
        is.read(buf, 2);
        if (is.gcount() != 2)
-               throw SerializationError("deSerializeString: size not read");
+               throw SerializationError("deSerializeWideString: size not read");
 
        u16 s_size = readU16((u8 *)buf);
        if (s_size == 0)
@@ -127,7 +198,7 @@ std::string serializeLongString(const std::string &plain)
 {
        char buf[4];
 
-       if (plain.size() > LONG_STRING_MAX)
+       if (plain.size() > LONG_STRING_MAX_LEN)
                throw SerializationError("String too long for serializeLongString");
 
        writeU32((u8*)&buf[0], plain.size());
@@ -151,15 +222,15 @@ std::string deSerializeLongString(std::istream &is)
                return s;
 
        // We don't really want a remote attacker to force us to allocate 4GB...
-       if (s_size > LONG_STRING_MAX) {
+       if (s_size > LONG_STRING_MAX_LEN) {
                throw SerializationError("deSerializeLongString: "
                        "string too long: " + itos(s_size) + " bytes");
        }
 
        Buffer<char> buf2(s_size);
        is.read(&buf2[0], s_size);
-       if (is.gcount() != s_size)
-               throw SerializationError("deSerializeString: couldn't read all chars");
+       if ((u32)is.gcount() != s_size)
+               throw SerializationError("deSerializeLongString: couldn't read all chars");
 
        s.reserve(s_size);
        s.append(&buf2[0], s_size);
@@ -283,6 +354,55 @@ std::string deSerializeJsonString(std::istream &is)
        return os.str();
 }
 
+std::string serializeJsonStringIfNeeded(const std::string &s)
+{
+       for (size_t i = 0; i < s.size(); ++i) {
+               if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
+                       return serializeJsonString(s);
+       }
+       return s;
+}
+
+std::string deSerializeJsonStringIfNeeded(std::istream &is)
+{
+       std::ostringstream tmp_os;
+       bool expect_initial_quote = true;
+       bool is_json = false;
+       bool was_backslash = false;
+       for (;;) {
+               char c = is.get();
+               if (is.eof())
+                       break;
+
+               if (expect_initial_quote && c == '"') {
+                       tmp_os << c;
+                       is_json = true;
+               } else if(is_json) {
+                       tmp_os << c;
+                       if (was_backslash)
+                               was_backslash = false;
+                       else if (c == '\\')
+                               was_backslash = true;
+                       else if (c == '"')
+                               break; // Found end of string
+               } else {
+                       if (c == ' ') {
+                               // Found end of word
+                               is.unget();
+                               break;
+                       } else {
+                               tmp_os << c;
+                       }
+               }
+               expect_initial_quote = false;
+       }
+       if (is_json) {
+               std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
+               return deSerializeJsonString(tmp_is);
+       } else
+               return tmp_os.str();
+}
+
 ////
 //// String/Struct conversions
 ////