Пример #1
0
void StreamPeer::put_double(double p_val) {

	uint8_t buf[8];
	encode_double(p_val, buf);
	if (big_endian) {
		uint64_t *p64 = (uint64_t *)buf;
		*p64 = BSWAP64(*p64);
	}
	put_data(buf, 8);
}
Пример #2
0
/* Returns LUAAMF_ESUCCESS on success, error code on failure */
static int save_value(
    luaamf_SaveBuffer * sb,
    lua_State * L,
    int index,
    int use_code
  )
{
  int result = LUAAMF_EFAILURE;

  switch (lua_type(L, index))
  {
  case LUA_TNIL:
    sb_writechar(sb, LUAAMF_NULL);
    result = LUAAMF_ESUCCESS;
    break;

  case LUA_TBOOLEAN:
    sb_writechar(sb, lua_toboolean(L, index) ? LUAAMF_TRUE : LUAAMF_FALSE);
    result = LUAAMF_ESUCCESS;
    break;

  case LUA_TNUMBER:
    result = encode_double(sb, lua_tonumber(L, index));
    break;

  case LUA_TSTRING:
    {
      size_t len;
      const char * buf = lua_tolstring(L, index, &len);
      if(use_code)
      {
        sb_writechar(sb, LUAAMF_STRING);
      }
      result = encode_string(sb, buf, len);
      break;
    }

  case LUA_TTABLE:
    result = save_table(L, sb, index);
    break;

  case LUA_TNONE:
  case LUA_TFUNCTION:
  case LUA_TTHREAD:
  case LUA_TUSERDATA:
  default:
    result = LUAAMF_EBADTYPE;
  }

  return result;
}
int encode_field_value(lua_sandbox* lsb, output_data* d, int first,
                       const char* representation)
{
  int result = 1;
  size_t len;
  const char* s;

  int t = lua_type(lsb->lua, -1);
  switch (t) {
  case LUA_TSTRING:
    if (first && representation) { // this uglyness keeps the protobuf
                                   // fields in order without additional
                                   // lookups
      if (pb_write_string(d, 3, representation, strlen(representation))) {
        return 1;
      }
    }
    s = lua_tolstring(lsb->lua, -1, &len);
    result = pb_write_string(d, 4, s, len);
    break;
  case LUA_TNUMBER:
    if (first) {
      if (pb_write_tag(d, 2, 0)) return 1;
      if (pb_write_varint(d, 3)) return 1;
      if (representation) {
        if (pb_write_string(d, 3, representation,
                            strlen(representation))) {
          return 1;
        }
      }
    }
    result = encode_double(lsb, d, 7);
    break;
  case LUA_TBOOLEAN:
    if (first) {
      if (pb_write_tag(d, 2, 0)) return 1;
      if (pb_write_varint(d, 4)) return 1;
      if (representation) {
        if (pb_write_string(d, 3, representation,
                            strlen(representation))) {
          return 1;
        }
      }
    }
    if (pb_write_tag(d, 8, 0)) return 1;
    result = pb_write_bool(d, lua_toboolean(lsb->lua, -1));
    break;
  case LUA_TTABLE:
    {
      lua_rawgeti(lsb->lua, -1, 1);
      int t = lua_type(lsb->lua, -1);
      lua_pop(lsb->lua, 1); // remove the array test value
      if (LUA_TNIL == t) {
        result = encode_field_object(lsb, d);
      } else {
        result = encode_field_array(lsb, d, t, representation);
      }
    }
    break;
  default:
    snprintf(lsb->error_message, LSB_ERROR_SIZE, "unsupported type %d", t);
    result = 1;
  }
  return result;
}
Пример #4
0
Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) {

	uint8_t *buf = r_buffer;

	r_len = 0;

	uint32_t flags = 0;

	switch (p_variant.get_type()) {

		case Variant::INT: {
			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				flags |= ENCODE_FLAG_64;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				flags |= ENCODE_FLAG_64; //always encode real as double
			}
		} break;
	}

	if (buf) {
		encode_uint32(p_variant.get_type() | flags, buf);
		buf += 4;
	}
	r_len += 4;

	switch (p_variant.get_type()) {

		case Variant::NIL: {

			//nothing to do
		} break;
		case Variant::BOOL: {

			if (buf) {
				encode_uint32(p_variant.operator bool(), buf);
			}

			r_len += 4;

		} break;
		case Variant::INT: {

			int64_t val = p_variant;
			if (val > 0x7FFFFFFF || val < -0x80000000) {
				//64 bits
				if (buf) {
					encode_uint64(val, buf);
				}

				r_len += 8;
			} else {
				if (buf) {
					encode_uint32(int32_t(val), buf);
				}

				r_len += 4;
			}
		} break;
		case Variant::REAL: {

			double d = p_variant;
			float f = d;
			if (double(f) != d) {
				if (buf) {
					encode_double(p_variant.operator double(), buf);
				}

				r_len += 8;

			} else {

				if (buf) {
					encode_float(p_variant.operator float(), buf);
				}

				r_len += 4;
			}

		} break;
		case Variant::NODE_PATH: {

			NodePath np = p_variant;
			if (buf) {
				encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format
				encode_uint32(np.get_subname_count(), buf + 4);
				uint32_t flags = 0;
				if (np.is_absolute())
					flags |= 1;
				if (np.get_property() != StringName())
					flags |= 2;

				encode_uint32(flags, buf + 8);

				buf += 12;
			}

			r_len += 12;

			int total = np.get_name_count() + np.get_subname_count();
			if (np.get_property() != StringName())
				total++;

			for (int i = 0; i < total; i++) {

				String str;

				if (i < np.get_name_count())
					str = np.get_name(i);
				else if (i < np.get_name_count() + np.get_subname_count())
					str = np.get_subname(i - np.get_subname_count());
				else
					str = np.get_property();

				CharString utf8 = str.utf8();

				int pad = 0;

				if (utf8.length() % 4)
					pad = 4 - utf8.length() % 4;

				if (buf) {
					encode_uint32(utf8.length(), buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length());
					buf += pad + utf8.length();
				}

				r_len += 4 + utf8.length() + pad;
			}

		} break;
		case Variant::STRING: {

			CharString utf8 = p_variant.operator String().utf8();

			if (buf) {
				encode_uint32(utf8.length(), buf);
				buf += 4;
				copymem(buf, utf8.get_data(), utf8.length());
			}

			r_len += 4 + utf8.length();
			while (r_len % 4)
				r_len++; //pad

		} break;
		// math types

		case Variant::VECTOR2: {

			if (buf) {
				Vector2 v2 = p_variant;
				encode_float(v2.x, &buf[0]);
				encode_float(v2.y, &buf[4]);
			}

			r_len += 2 * 4;

		} break; // 5
		case Variant::RECT2: {

			if (buf) {
				Rect2 r2 = p_variant;
				encode_float(r2.position.x, &buf[0]);
				encode_float(r2.position.y, &buf[4]);
				encode_float(r2.size.x, &buf[8]);
				encode_float(r2.size.y, &buf[12]);
			}
			r_len += 4 * 4;

		} break;
		case Variant::VECTOR3: {

			if (buf) {
				Vector3 v3 = p_variant;
				encode_float(v3.x, &buf[0]);
				encode_float(v3.y, &buf[4]);
				encode_float(v3.z, &buf[8]);
			}

			r_len += 3 * 4;

		} break;
		case Variant::TRANSFORM2D: {

			if (buf) {
				Transform2D val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 2; j++) {

						copymem(&buf[(i * 2 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 6 * 4;

		} break;
		case Variant::PLANE: {

			if (buf) {
				Plane p = p_variant;
				encode_float(p.normal.x, &buf[0]);
				encode_float(p.normal.y, &buf[4]);
				encode_float(p.normal.z, &buf[8]);
				encode_float(p.d, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::QUAT: {

			if (buf) {
				Quat q = p_variant;
				encode_float(q.x, &buf[0]);
				encode_float(q.y, &buf[4]);
				encode_float(q.z, &buf[8]);
				encode_float(q.w, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		case Variant::RECT3: {

			if (buf) {
				Rect3 aabb = p_variant;
				encode_float(aabb.position.x, &buf[0]);
				encode_float(aabb.position.y, &buf[4]);
				encode_float(aabb.position.z, &buf[8]);
				encode_float(aabb.size.x, &buf[12]);
				encode_float(aabb.size.y, &buf[16]);
				encode_float(aabb.size.z, &buf[20]);
			}

			r_len += 6 * 4;

		} break;
		case Variant::BASIS: {

			if (buf) {
				Basis val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.elements[i][j], sizeof(float));
					}
				}
			}

			r_len += 9 * 4;

		} break;
		case Variant::TRANSFORM: {

			if (buf) {
				Transform val = p_variant;
				for (int i = 0; i < 3; i++) {
					for (int j = 0; j < 3; j++) {

						copymem(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float));
					}
				}

				encode_float(val.origin.x, &buf[36]);
				encode_float(val.origin.y, &buf[40]);
				encode_float(val.origin.z, &buf[44]);
			}

			r_len += 12 * 4;

		} break;

		// misc types
		case Variant::COLOR: {

			if (buf) {
				Color c = p_variant;
				encode_float(c.r, &buf[0]);
				encode_float(c.g, &buf[4]);
				encode_float(c.b, &buf[8]);
				encode_float(c.a, &buf[12]);
			}

			r_len += 4 * 4;

		} break;
		/*case Variant::RESOURCE: {

			ERR_EXPLAIN("Can't marshallize resources");
			ERR_FAIL_V(ERR_INVALID_DATA); //no, i'm sorry, no go
		} break;*/
		case Variant::_RID:
		case Variant::OBJECT: {

		} break;
		case Variant::DICTIONARY: {

			Dictionary d = p_variant;

			if (buf) {
				encode_uint32(uint32_t(d.size()), buf);
				buf += 4;
			}
			r_len += 4;

			List<Variant> keys;
			d.get_key_list(&keys);

			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {

				/*
				CharString utf8 = E->->utf8();

				if (buf) {
					encode_uint32(utf8.length()+1,buf);
					buf+=4;
					copymem(buf,utf8.get_data(),utf8.length()+1);
				}

				r_len+=4+utf8.length()+1;
				while (r_len%4)
					r_len++; //pad
				*/
				int len;
				encode_variant(E->get(), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
				encode_variant(d[E->get()], buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		case Variant::ARRAY: {

			Array v = p_variant;

			if (buf) {
				encode_uint32(uint32_t(v.size()), buf);
				buf += 4;
			}

			r_len += 4;

			for (int i = 0; i < v.size(); i++) {

				int len;
				encode_variant(v.get(i), buf, len);
				ERR_FAIL_COND_V(len % 4, ERR_BUG);
				r_len += len;
				if (buf)
					buf += len;
			}

		} break;
		// arrays
		case Variant::POOL_BYTE_ARRAY: {

			PoolVector<uint8_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(uint8_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<uint8_t>::Read r = data.read();
				copymem(buf, &r[0], datalen * datasize);
			}

			r_len += 4 + datalen * datasize;
			while (r_len % 4)
				r_len++;

		} break;
		case Variant::POOL_INT_ARRAY: {

			PoolVector<int> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(int32_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<int>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_uint32(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_REAL_ARRAY: {

			PoolVector<real_t> data = p_variant;
			int datalen = data.size();
			int datasize = sizeof(real_t);

			if (buf) {
				encode_uint32(datalen, buf);
				buf += 4;
				PoolVector<real_t>::Read r = data.read();
				for (int i = 0; i < datalen; i++)
					encode_float(r[i], &buf[i * datasize]);
			}

			r_len += 4 + datalen * datasize;

		} break;
		case Variant::POOL_STRING_ARRAY: {

			PoolVector<String> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			for (int i = 0; i < len; i++) {

				CharString utf8 = data.get(i).utf8();

				if (buf) {
					encode_uint32(utf8.length() + 1, buf);
					buf += 4;
					copymem(buf, utf8.get_data(), utf8.length() + 1);
					buf += utf8.length() + 1;
				}

				r_len += 4 + utf8.length() + 1;
				while (r_len % 4) {
					r_len++; //pad
					if (buf)
						buf++;
				}
			}

		} break;
		case Variant::POOL_VECTOR2_ARRAY: {

			PoolVector<Vector2> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Vector2 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					buf += 4 * 2;
				}
			}

			r_len += 4 * 2 * len;

		} break;
		case Variant::POOL_VECTOR3_ARRAY: {

			PoolVector<Vector3> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Vector3 v = data.get(i);

					encode_float(v.x, &buf[0]);
					encode_float(v.y, &buf[4]);
					encode_float(v.z, &buf[8]);
					buf += 4 * 3;
				}
			}

			r_len += 4 * 3 * len;

		} break;
		case Variant::POOL_COLOR_ARRAY: {

			PoolVector<Color> data = p_variant;
			int len = data.size();

			if (buf) {
				encode_uint32(len, buf);
				buf += 4;
			}

			r_len += 4;

			if (buf) {

				for (int i = 0; i < len; i++) {

					Color c = data.get(i);

					encode_float(c.r, &buf[0]);
					encode_float(c.g, &buf[4]);
					encode_float(c.b, &buf[8]);
					encode_float(c.a, &buf[12]);
					buf += 4 * 4;
				}
			}

			r_len += 4 * 4 * len;

		} break;
		default: { ERR_FAIL_V(ERR_BUG); }
	}

	return OK;
}