aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api/l_nodetimer.h
blob: 9f8dd21c8ccbfb42be883be7c15861fd3e488c7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef L_NODETIMER_H_
#define L_NODETIMER_H_

#include "lua_api/l_base.h"
#include "irr_v3d.h"

class ServerEnvironment;

class NodeTimerRef : public ModApiBase {
private:
	v3s16 m_p;
	ServerEnvironment *m_env;

	static const char className[];
	static const luaL_reg methods[];

	static int gc_object(lua_State *L);

	static NodeTimerRef *checkobject(lua_State *L, int narg);

	static int l_set(lua_State *L);

	static int l_start(lua_State *L);

	static int l_stop(lua_State *L);

	static int l_is_started(lua_State *L);

	static int l_get_timeout(lua_State *L);

	static int l_get_elapsed(lua_State *L);

public:
	NodeTimerRef(v3s16 p, ServerEnvironment *env);
	~NodeTimerRef();

	// Creates an NodeTimerRef and leaves it on top of stack
	// Not callable from Lua; all references are created on the C side.
	static void create(lua_State *L, v3s16 p, ServerEnvironment *env);

	static void set_null(lua_State *L);

	static void Register(lua_State *L);
};



#endif /* L_NODETIMER_H_ */
> 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
/*
Minetest
Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "serialize.h"
#include "pointer.h"
#include "porting.h"
#include "util/string.h"
#include "exceptions.h"
#include "irrlichttypes.h"

#include <sstream>
#include <iomanip>
#include <vector>

FloatType g_serialize_f32_type = FLOATTYPE_UNKNOWN;


////
//// String
////

std::string serializeString16(const std::string &plain)
{
	std::string s;
	char buf[2];

	if (plain.size() > STRING_MAX_LEN)
		throw SerializationError("String too long for serializeString16");
	s.reserve(2 + plain.size());

	writeU16((u8 *)&buf[0], plain.size());
	s.append(buf, 2);

	s.append(plain);
	return s;
}

std::string deSerializeString16(std::istream &is)
{
	std::string s;
	char buf[2];

	is.read(buf, 2);
	if (is.gcount() != 2)
		throw SerializationError("deSerializeString16: size not read");

	u16 s_size = readU16((u8 *)buf);
	if (s_size == 0)
		return s;

	s.resize(s_size);
	is.read(&s[0], s_size);
	if (is.gcount() != s_size)
		throw SerializationError("deSerializeString16: couldn't read all chars");

	return s;
}


////
//// Long String
////

std::string serializeString32(const std::string &plain)
{
	std::string s;
	char buf[4];

	if (plain.size() > LONG_STRING_MAX_LEN)
		throw SerializationError("String too long for serializeLongString");
	s.reserve(4 + plain.size());

	writeU32((u8*)&buf[0], plain.size());
	s.append(buf, 4);
	s.append(plain);
	return s;
}

std::string deSerializeString32(std::istream &is)
{
	std::string s;
	char buf[4];

	is.read(buf, 4);
	if (is.gcount() != 4)
		throw SerializationError("deSerializeLongString: size not read");

	u32 s_size = readU32((u8 *)buf);
	if (s_size == 0)
		return s;

	// We don't really want a remote attacker to force us to allocate 4GB...
	if (s_size > LONG_STRING_MAX_LEN) {
		throw SerializationError("deSerializeLongString: "
			"string too long: " + itos(s_size) + " bytes");
	}

	s.resize(s_size);
	is.read(&s[0], s_size);
	if ((u32)is.gcount() != s_size)
		throw SerializationError("deSerializeLongString: couldn't read all chars");

	return s;
}

////
//// JSON
////

std::string serializeJsonString(const std::string &plain)
{
	std::ostringstream os(std::ios::binary);
	os << "\"";

	for (char c : plain) {
		switch (c) {
			case '"':
				os << "\\\"";
				break;
			case '\\':
				os << "\\\\";
				break;
			case '/':
				os << "\\/";
				break;
			case '\b':
				os << "\\b";
				break;
			case '\f':
				os << "\\f";
				break;
			case '\n':
				os << "\\n";
				break;
			case '\r':
				os << "\\r";
				break;
			case '\t':
				os << "\\t";
				break;
			default: {
				if (c >= 32 && c <= 126) {
					os << c;
				} else {
					u32 cnum = (u8)c;
					os << "\\u" << std::hex << std::setw(4)
						<< std::setfill('0') << cnum;
				}
				break;
			}
		}
	}

	os << "\"";
	return os.str();
}

std::string deSerializeJsonString(std::istream &is)
{
	std::ostringstream os(std::ios::binary);
	char c, c2;

	// Parse initial doublequote
	is >> c;
	if (c != '"')
		throw SerializationError("JSON string must start with doublequote");

	// Parse characters
	for (;;) {
		c = is.get();
		if (is.eof())
			throw SerializationError("JSON string ended prematurely");

		if (c == '"') {
			return os.str();
		}

		if (c == '\\') {
			c2 = is.get();
			if (is.eof())
				throw SerializationError("JSON string ended prematurely");
			switch (c2) {
				case 'b':
					os << '\b';
					break;
				case 'f':
					os << '\f';
					break;
				case 'n':
					os << '\n';
					break;
				case 'r':
					os << '\r';
					break;
				case 't':
					os << '\t';
					break;
				case 'u': {
					int hexnumber;
					char hexdigits[4 + 1];

					is.read(hexdigits, 4);
					if (is.eof())
						throw SerializationError("JSON string ended prematurely");
					hexdigits[4] = 0;

					std::istringstream tmp_is(hexdigits, std::ios::binary);
					tmp_is >> std::hex >> hexnumber;
					os << (char)hexnumber;
					break;
				}
				default:
					os << c2;
					break;
			}
		} else {
			os << c;
		}
	}

	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;
			}

			tmp_os << c;
		}
		expect_initial_quote = false;
	}
	if (is_json) {
		std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
		return deSerializeJsonString(tmp_is);
	}

	return tmp_os.str();
}