예제 #1
0
void
eos_shard_writer_v1_write_to_fd (EosShardWriterV1 *self, int fd)
{
  GVariant *variant;

  /* Sort our records to allow for binary searches on retrieval. */
  g_array_sort (self->entries, &compare_records);

  variant = header_entry_variant (self->entries);
  uint64_t header_size = g_variant_get_size (variant);
  header_size = GUINT64_TO_LE (header_size);
  g_variant_unref (variant);

  lseek (fd, ALIGN (sizeof (header_size) + header_size), SEEK_SET);

  int i;
  for (i = 0; i < self->entries->len; i++) {
    struct eos_shard_writer_v1_record_entry *e = &g_array_index (self->entries, struct eos_shard_writer_v1_record_entry, i);

    write_blob (fd, &e->metadata);
    write_blob (fd, &e->data);
  }

  lseek (fd, 0, SEEK_SET);
  g_assert (write (fd, &header_size, sizeof (header_size)) >= 0);
  variant = header_entry_variant (self->entries);
  write_variant (fd, variant);
  g_variant_unref (variant);
}
예제 #2
0
    void xml_writer_impl::write_element(const variant& element)
    {
        try
        {
            if (element.is<variant::Collection>() && element.empty() && element.type() != variant::DataTable)
            {
                write_empty_element();
                return;
            }

            switch(element.type())
            {
            case variant::None:
            {
                write_empty_element();
                break;
            }
            case variant::Any:
            case variant::String:
            {
                if (element.as<std::string>().empty())
                {
                    write_empty_element();
                    break;
                }
            }
            case variant::Float:
            case variant::Double:
            case variant::Int32:
            case variant::UInt32:
            case variant::Int64:
            case variant::UInt64:
            case variant::Boolean:
            case variant::Date:
            case variant::Time:
            case variant::DateTime:
            {
                m_os << start_tag();
                write_text(element);
                m_os << end_tag();
                break;
            }
            case variant::Dictionary:
            case variant::Bag:
            {
                if ((m_mode & xml_mode::Preserve)!=0)
                {
                    if (element.has_key(xml_attributes))
                    {
                        m_stack.top().m_attributes = element[xml_attributes];

                        if (element.size()==1)
                        {
                            write_empty_element();
                            break;
                        }
                    }

                    m_os << start_tag();

                    bool prev_is_text = false;
                    variant::const_iterator it, end(element.end());
                    for (it=element.begin(); it!=end; ++it)
                    {
                        if (it.key()==xml_attributes)
                        {
                            continue;
                        }
                        else if (it.key()==xml_text)
                        {
                            write_text(it.value());
                            prev_is_text = true;
                        }
                        else if (it.key()==xml_instruction)
                        {
                            push(it.key());

                            if (!prev_is_text)
                            {
                                m_os << indent();
                            }

                            write_instruction(it.value());

                            prev_is_text = false;

                            pop();
                        }
                        else if (it.key()==xml_comment)
                        {
                            push(it.key());

                            if (!prev_is_text)
                            {
                                m_os << indent();
                            }

                            write_comment(it.value());

                            prev_is_text = false;

                            pop();
                        }
                        else
                        {
                            push(it.key());

                            if (!prev_is_text)
                            {
                                m_os << indent();
                            }

                            write_element(it.value());

                            prev_is_text = false;

                            pop();
                        }
                    }

                    if (!prev_is_text)
                    {
                        m_os << indent();
                    }

                    m_os << end_tag();
                }
                else
                {
                    m_os << start_tag();

                    variant::const_iterator it, end(element.end());
                    for (it=element.begin(); it!=end; ++it)
                    {
                        push(it.key());

                        m_os << indent();
                        write_variant(it.value());

                        pop();
                    }

                    m_os << indent() << end_tag();
                }

                break;
            }
            case variant::List:
            {
                m_os << start_tag();

                BOOST_FOREACH(const variant& item, element)
                {
                    push();
                    m_os << indent();
                    write_variant(item);
                    pop();
                }

                m_os << indent();
                m_os << end_tag();

                break;
            }
            case variant::Tuple:
            {
                m_stack.top().m_attributes.insert("size", variant(element.size()));
                m_os << start_tag();

                BOOST_FOREACH(const variant& item, element)
                {
                    push();
                    m_os << indent();
                    write_variant(item);
                    pop();
                }

                m_os << indent();
                m_os << end_tag();
                break;
            }
            case variant::TimeSeries:
            {
                m_os << start_tag();

                variant::const_iterator it, end = element.end();
                for (it=element.begin(); it!=end; ++it)
                {
                    push().insert("time", variant(it.time()));
                    m_os << indent();
                    write_variant(it.value());
                    pop();
                }

                m_os << indent();
                m_os << end_tag();
                break;
            }
            case variant::DataTable:
            {
                const data_table& dt = element.m_value.get<variant::DataTable>();

                m_stack.top().m_attributes
                    .insert("rows",    variant(dt.size()))
                    .insert("columns", variant(dt.columns().size()));
                m_os << start_tag();

                if (!dt.columns().empty())
                {
                    push("Columns");
                    m_os << indent() << start_tag();

                    for (data_table::column_container_type::const_iterator column_iter = dt.columns().begin()
                           ; column_iter != dt.columns().end()
                           ; ++column_iter)
                    {
                        push("Column")
                            .insert("name", variant(column_iter->name()))
                            .insert("type", variant(variant::enum_to_string(column_iter->type())));
                        m_os << indent();
                        write_empty_element();
                        pop();
                    }

                    m_os << indent() << end_tag();
                    pop();
                }

                for (data_table::column_container_type::const_iterator column_iter = dt.columns().begin()
                       ; column_iter != dt.columns().end()
                       ; ++column_iter)
                {
                    push("Column").insert("name", variant(column_iter->name()));
                    m_os << indent() << start_tag();

                    if (column_iter->type() & variant_base::Primitive)
                    {
                        boost::scoped_ptr<data_table_column_writer> column_writer(
                            make_data_table_column_stream_writer(*column_iter, m_os)
                        );

                        while (column_writer->has_next())
                        {
                            push("V");
                            m_os << indent() << start_tag();
                            column_writer->write();
                            m_os << end_tag();
                            pop();

                            column_writer->advance();
                        }
                    }
                    else
                    {
                        variant::const_iterator iter(column_iter->begin());
                        variant::const_iterator end(column_iter->end());
                        while (iter != end)
                        {
                            push("V");
                            m_os << indent();
                            write_variant(*(iter++));
                            pop();
                        }
                    }

                    m_os << indent() << end_tag();
                    pop();
                }

                m_os << indent();
                m_os << end_tag();

                break;
            }
            case variant::Buffer:
            {
                m_os << start_tag();
                const void *data = element.as<void*>();
                size_t size = element.size();
                if (data!=nullptr && size>0)
                {
                    unsigned int n = 0;
                    boost::scoped_ptr<char> b64(detail::b64_encode((const char*)data, (unsigned int)size, &n));
                    if (!b64.get())
                    {
                        boost::throw_exception(variant_error("Unable to base64 encode data"));
                    }
                    m_os << b64.get();
                }
                m_os << end_tag();
                break;
            }
            case variant::Object:
            {
                const object& obj(element.as<object>());

                // write class name
                m_stack.top().m_attributes
                    .insert("class", variant(obj.name()))
                    .insert("version", variant(obj.version()));

                m_os << start_tag();

                // write parameter dictionary
                variant params;
                obj.deflate(params);
                push("params");
                m_os << indent();
                write_variant(params);
                pop();

                m_os << indent();
                m_os << end_tag();

                break;
            }
            case variant::Exception:
            {
                m_os << start_tag();

                exception_data e(element.as<exception_data>());

                push("type");
                m_os << indent();
                write_element(variant(e.type()));
                pop();
                
                push("message");
                m_os << indent();
                write_element(variant(e.message()));
                pop();

                if (!e.source().empty())
                {
                    push("source");
                    m_os << indent();
                    write_element(variant(e.source()));
                    pop();
                }

                if (!e.stack().empty())
                {
                    push("stack");
                    m_os << indent();
                    write_element(variant(e.stack()));
                    pop();
                }

                m_os << indent();
                m_os << end_tag();
                break;
            }
            case variant::Array:
            {
                const typed_array& a(element.as<typed_array>());
                m_stack.top().m_attributes
                    .insert("size", variant(a.size()))
                    .insert("type", variant(variant::enum_to_string(a.type())));
                
                m_os << start_tag();

                for (size_t i=0; i<a.size(); ++i)
                {
                    push();
                    m_os << indent();
                    write_element(variant(a[i]));
                    pop();
                }

                m_os << indent();
                m_os << end_tag();
                break;
            }
            default:
                 boost::throw_exception(variant_error("Case exhaustion: " + variant::enum_to_string(element.type()))); 
            }
예제 #3
0
Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_resource,uint32_t p_flags) {

	Error err;
	if (p_flags&ResourceSaver::FLAG_COMPRESS) {
		FileAccessCompressed *fac = memnew( FileAccessCompressed );
		fac->configure("RSCC");
		f=fac;
		err = fac->_open(p_path,FileAccess::WRITE);
		if (err)
			memdelete(f);

	} else {
		f=FileAccess::open(p_path,FileAccess::WRITE,&err);
	}


	ERR_FAIL_COND_V(err,err);
	FileAccessRef _fref(f);


	relative_paths=p_flags&ResourceSaver::FLAG_RELATIVE_PATHS;
	skip_editor=p_flags&ResourceSaver::FLAG_OMIT_EDITOR_PROPERTIES;
	bundle_resources=p_flags&ResourceSaver::FLAG_BUNDLE_RESOURCES;
	big_endian=p_flags&ResourceSaver::FLAG_SAVE_BIG_ENDIAN;
	no_extensions=p_flags&ResourceSaver::FLAG_NO_EXTENSION;

	local_path=p_path.get_base_dir();
	//bin_meta_idx = get_string_index("__bin_meta__"); //is often used, so create

	_find_resources(p_resource,true);

	if (!(p_flags&ResourceSaver::FLAG_COMPRESS)) {
		//save header compressed
		static const uint8_t header[4]={'R','S','R','C'};
		f->store_buffer(header,4);
	}

	if (big_endian) {
		f->store_32(1);
		f->set_endian_swap(true);
	} else
		f->store_32(0);

	f->store_32(0); //64 bits file, false for now
	f->store_32(VERSION_MAJOR);
	f->store_32(VERSION_MINOR);
	f->store_32(FORMAT_VERSION);

	//f->store_32(saved_resources.size()+external_resources.size()); // load steps -not needed
	save_unicode_string(p_resource->get_type());
	uint64_t md_at = f->get_pos();
	f->store_64(0); //offset to impoty metadata
	for(int i=0;i<14;i++)
		f->store_32(0); // reserved


	List<ResourceData> resources;


	{


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


			ResourceData &rd = resources.push_back(ResourceData())->get();
			rd.type=E->get()->get_type();

			List<PropertyInfo> property_list;
			E->get()->get_property_list( &property_list );

			for(List<PropertyInfo>::Element *F=property_list.front();F;F=F->next()) {

				if (skip_editor && F->get().name.begins_with("__editor"))
					continue;
				if (F->get().usage&PROPERTY_USAGE_STORAGE || (bundle_resources && F->get().usage&PROPERTY_USAGE_BUNDLE)) {
					Property p;
					p.name_idx=get_string_index(F->get().name);
					p.value=E->get()->get(F->get().name);
					if (F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero())
						continue;
					p.pi=F->get();										

					rd.properties.push_back(p);

				}
			}



		}
	}


	f->store_32(strings.size()); //string table size
	for(int i=0;i<strings.size();i++) {
		//print_bl("saving string: "+strings[i]);
		save_unicode_string(strings[i]);
	}

	// save external resource table
	f->store_32(external_resources.size()); //amount of external resources
	for(Set<RES>::Element *E=external_resources.front();E;E=E->next()) {

		save_unicode_string(E->get()->get_save_type());
		String path = E->get()->get_path();
		if (no_extensions)
			path=path.basename()+".*";
		save_unicode_string(path);
	}
	// save internal resource table
	f->store_32(saved_resources.size()); //amount of internal resources
	Vector<uint64_t> ofs_pos;
	for(List<RES>::Element *E=saved_resources.front();E;E=E->next()) {

		RES r = E->get();
		if (r->get_path()=="" || r->get_path().find("::")!=-1)
			save_unicode_string("local://"+itos(ofs_pos.size()));
		else
			save_unicode_string(r->get_path()); //actual external
		ofs_pos.push_back(f->get_pos());
		f->store_64(0); //offset in 64 bits
	}

	Vector<uint64_t> ofs_table;
//	int saved_idx=0;
	//now actually save the resources

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

		ResourceData & rd = E->get();

		ofs_table.push_back(f->get_pos());
		save_unicode_string(rd.type);
		f->store_32(rd.properties.size());

		for (List<Property>::Element *F=rd.properties.front();F;F=F->next()) {

			Property &p=F->get();
			f->store_32(p.name_idx);
			write_variant(p.value,F->get().pi);
		}

	}

	for(int i=0;i<ofs_table.size();i++) {
		f->seek(ofs_pos[i]);
		f->store_64(ofs_table[i]);
	}

	f->seek_end();
	if (p_resource->get_import_metadata().is_valid()) {
		uint64_t md_pos = f->get_pos();
		Ref<ResourceImportMetadata> imd=p_resource->get_import_metadata();
		save_unicode_string(imd->get_editor());
		f->store_32(imd->get_source_count());
		for(int i=0;i<imd->get_source_count();i++) {
			save_unicode_string(imd->get_source_path(i));
			save_unicode_string(imd->get_source_md5(i));
		}
		List<String> options;
		imd->get_options(&options);
		f->store_32(options.size());
		for(List<String>::Element *E=options.front();E;E=E->next()) {
			save_unicode_string(E->get());
			write_variant(imd->get_option(E->get()));
		}

		f->seek(md_at);
		f->store_64(md_pos);
		f->seek_end();
	}


	f->store_buffer((const uint8_t*)"RSRC",4); //magic at end

	f->close();


	return OK;
}
예제 #4
0
    void xml_writer_impl::write_document(const variant& document)
    {
        try
        {
            if ((m_mode & xml_mode::NoHeader)==0)
            {
                // output the XML header
                write_header();
            }

            if ((m_mode & xml_mode::Preserve)!=0)
            {
                bool first(true);
                if (document.is<variant::Mapping>())
                {
                    std::string element_name;
                    variant::const_iterator it, end(document.end());
                    for (it=document.begin(); it!=end; ++it)
                    {
                        if (it.key()==xml_text)
                        {
                            boost::throw_exception(variant_error("Encountered text in document node"));
                        }
                        else if (it.key()==xml_attributes)
                        {
                            boost::throw_exception(variant_error("Encountered attributes in document node"));
                        }
                        else if (it.key()==xml_instruction)
                        {
                            if (!first)
                            {
                                m_os << indent();
                            }
                            write_instruction(it.value());
                        }
                        else if (it.key()==xml_comment)
                        {
                            if (!first)
                            {
                                m_os << indent();
                            }
                            write_comment(it.value());
                        }
                        else
                        {
                            if (element_name.empty())
                            {
                                element_name = it.key();
                            }
                            else
                            {
                                boost::throw_exception(variant_error((boost::format("Illegal element %s encountered in document, expecting single element %s at root") % it.key() % element_name).str()));
                            }

                            push(it.key());
                            if (!first)
                            {
                                m_os << indent();
                            }
                            write_element(it.value());
                            pop();
                        }
                        first = false;
                    }
                }
                else
                {
                    boost::throw_exception(variant_error("Invalid document structure, root node must be a Dictionary or Bag"));
                }
            }
            else
            {
                push();
                write_variant(document);
                pop();
            }
        }
        catch (const std::exception &e)
        {
            boost::throw_exception(variant_error(e.what()));
        }
        catch (...)
        {
            boost::throw_exception(variant_error("Unhandled Exception"));
        }
    }
예제 #5
0
void ResourceFormatSaverBinaryInstance::write_variant(const Variant& p_property,const PropertyInfo& p_hint) {

	switch(p_property.get_type()) {

		case Variant::NIL: {

			f->store_32(VARIANT_NIL);
			// don't store anything
		} break;
		case Variant::BOOL: {

			f->store_32(VARIANT_BOOL);
			bool val=p_property;
			f->store_32(val);
		} break;
		case Variant::INT: {

			f->store_32(VARIANT_INT);
			int val=p_property;
			f->store_32(val);
		} break;
		case Variant::REAL: {

			f->store_32(VARIANT_REAL);
			real_t val=p_property;
			f->store_real(val);

		} break;
		case Variant::STRING: {

			f->store_32(VARIANT_STRING);
			String val=p_property;
			save_unicode_string(val);

		} break;
		case Variant::VECTOR2: {

			f->store_32(VARIANT_VECTOR2);
			Vector2 val=p_property;
			f->store_real(val.x);
			f->store_real(val.y);

		} break;
		case Variant::RECT2: {

			f->store_32(VARIANT_RECT2);
			Rect2 val=p_property;
			f->store_real(val.pos.x);
			f->store_real(val.pos.y);
			f->store_real(val.size.x);
			f->store_real(val.size.y);

		} break;
		case Variant::VECTOR3: {

			f->store_32(VARIANT_VECTOR3);
			Vector3 val=p_property;
			f->store_real(val.x);
			f->store_real(val.y);
			f->store_real(val.z);

		} break;
		case Variant::PLANE: {

			f->store_32(VARIANT_PLANE);
			Plane val=p_property;
			f->store_real(val.normal.x);
			f->store_real(val.normal.y);
			f->store_real(val.normal.z);
			f->store_real(val.d);

		} break;
		case Variant::QUAT: {

			f->store_32(VARIANT_QUAT);
			Quat val=p_property;
			f->store_real(val.x);
			f->store_real(val.y);
			f->store_real(val.z);
			f->store_real(val.w);

		} break;
		case Variant::_AABB: {

			f->store_32(VARIANT_AABB);
			AABB val=p_property;
			f->store_real(val.pos.x);
			f->store_real(val.pos.y);
			f->store_real(val.pos.z);
			f->store_real(val.size.x);
			f->store_real(val.size.y);
			f->store_real(val.size.z);

		} break;
		case Variant::MATRIX32: {

			f->store_32(VARIANT_MATRIX32);
			Matrix32 val=p_property;
			f->store_real(val.elements[0].x);
			f->store_real(val.elements[0].y);
			f->store_real(val.elements[1].x);
			f->store_real(val.elements[1].y);
			f->store_real(val.elements[2].x);
			f->store_real(val.elements[2].y);

		} break;
		case Variant::MATRIX3: {

			f->store_32(VARIANT_MATRIX3);
			Matrix3 val=p_property;
			f->store_real(val.elements[0].x);
			f->store_real(val.elements[0].y);
			f->store_real(val.elements[0].z);
			f->store_real(val.elements[1].x);
			f->store_real(val.elements[1].y);
			f->store_real(val.elements[1].z);
			f->store_real(val.elements[2].x);
			f->store_real(val.elements[2].y);
			f->store_real(val.elements[2].z);

		} break;
		case Variant::TRANSFORM: {

			f->store_32(VARIANT_TRANSFORM);
			Transform val=p_property;
			f->store_real(val.basis.elements[0].x);
			f->store_real(val.basis.elements[0].y);
			f->store_real(val.basis.elements[0].z);
			f->store_real(val.basis.elements[1].x);
			f->store_real(val.basis.elements[1].y);
			f->store_real(val.basis.elements[1].z);
			f->store_real(val.basis.elements[2].x);
			f->store_real(val.basis.elements[2].y);
			f->store_real(val.basis.elements[2].z);
			f->store_real(val.origin.x);
			f->store_real(val.origin.y);
			f->store_real(val.origin.z);

		} break;
		case Variant::COLOR: {

			f->store_32(VARIANT_COLOR);
			Color val=p_property;
			f->store_real(val.r);
			f->store_real(val.g);
			f->store_real(val.b);
			f->store_real(val.a);

		} break;
		case Variant::IMAGE: {

			f->store_32(VARIANT_IMAGE);
			Image val =p_property;
			if (val.empty()) {
				f->store_32(IMAGE_ENCODING_EMPTY);
				break;
			}

			int encoding=IMAGE_ENCODING_RAW;
			float quality=0.7;

			if (val.get_format() <= Image::FORMAT_INDEXED_ALPHA) {
				//can only compress uncompressed stuff

				if (p_hint.hint==PROPERTY_HINT_IMAGE_COMPRESS_LOSSY && Image::lossy_packer) {
					encoding=IMAGE_ENCODING_LOSSY;
					float qs=p_hint.hint_string.to_double();
					if (qs!=0.0)
						quality=qs;

				} else if (p_hint.hint==PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS && Image::lossless_packer) {
					encoding=IMAGE_ENCODING_LOSSLESS;

				}
			}

			f->store_32(encoding); //raw encoding

			if (encoding==IMAGE_ENCODING_RAW) {


				f->store_32(val.get_width());
				f->store_32(val.get_height());
				f->store_32(val.get_mipmaps());
				switch(val.get_format()) {

					case Image::FORMAT_GRAYSCALE: f->store_32(IMAGE_FORMAT_GRAYSCALE ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255
					case Image::FORMAT_INTENSITY: f->store_32(IMAGE_FORMAT_INTENSITY ); break; ///< one byte per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255
					case Image::FORMAT_GRAYSCALE_ALPHA: f->store_32(IMAGE_FORMAT_GRAYSCALE_ALPHA ); break; ///< two bytes per pixel: f->store_32(IMAGE_FORMAT_ ); break; 0-255. alpha 0-255
					case Image::FORMAT_RGB: f->store_32(IMAGE_FORMAT_RGB ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B
					case Image::FORMAT_RGBA: f->store_32(IMAGE_FORMAT_RGBA ); break; ///< one byte R: f->store_32(IMAGE_FORMAT_ ); break; one byte G: f->store_32(IMAGE_FORMAT_ ); break; one byte B: f->store_32(IMAGE_FORMAT_ ); break; one byte A
					case Image::FORMAT_INDEXED: f->store_32(IMAGE_FORMAT_INDEXED ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*3 bytes of palette
					case Image::FORMAT_INDEXED_ALPHA: f->store_32(IMAGE_FORMAT_INDEXED_ALPHA ); break; ///< index byte 0-256: f->store_32(IMAGE_FORMAT_ ); break; and after image end: f->store_32(IMAGE_FORMAT_ ); break; 256*4 bytes of palette (alpha)
					case Image::FORMAT_BC1: f->store_32(IMAGE_FORMAT_BC1 ); break; // DXT1
					case Image::FORMAT_BC2: f->store_32(IMAGE_FORMAT_BC2 ); break; // DXT3
					case Image::FORMAT_BC3: f->store_32(IMAGE_FORMAT_BC3 ); break; // DXT5
					case Image::FORMAT_BC4: f->store_32(IMAGE_FORMAT_BC4 ); break; // ATI1
					case Image::FORMAT_BC5: f->store_32(IMAGE_FORMAT_BC5 ); break; // ATI2
					case Image::FORMAT_PVRTC2: f->store_32(IMAGE_FORMAT_PVRTC2 ); break;
					case Image::FORMAT_PVRTC2_ALPHA: f->store_32(IMAGE_FORMAT_PVRTC2_ALPHA ); break;
					case Image::FORMAT_PVRTC4: f->store_32(IMAGE_FORMAT_PVRTC4 ); break;
					case Image::FORMAT_PVRTC4_ALPHA: f->store_32(IMAGE_FORMAT_PVRTC4_ALPHA ); break;
					case Image::FORMAT_ETC: f->store_32(IMAGE_FORMAT_ETC); break;
					case Image::FORMAT_CUSTOM: f->store_32(IMAGE_FORMAT_CUSTOM ); break;
					default: {}

				}

				int dlen = val.get_data().size();
				f->store_32(dlen);
				DVector<uint8_t>::Read r = val.get_data().read();
				f->store_buffer(r.ptr(),dlen);
				_pad_buffer(dlen);
			} else {

				DVector<uint8_t> data;
				if (encoding==IMAGE_ENCODING_LOSSY) {
					data=Image::lossy_packer(val,quality);

				} else if (encoding==IMAGE_ENCODING_LOSSLESS) {
					data=Image::lossless_packer(val);

				}

				int ds=data.size();
				f->store_32(ds);
				if (ds>0) {
					DVector<uint8_t>::Read r = data.read();
					f->store_buffer(r.ptr(),ds);

					_pad_buffer(ds);

				}
			}

		} break;
		case Variant::NODE_PATH: {
			f->store_32(VARIANT_NODE_PATH);
			NodePath np=p_property;
			f->store_16(np.get_name_count());
			uint16_t snc = np.get_subname_count();
			if (np.is_absolute())
				snc|=0x8000;
			f->store_16(snc);
			for(int i=0;i<np.get_name_count();i++)
				f->store_32(get_string_index(np.get_name(i)));
			for(int i=0;i<np.get_subname_count();i++)
				f->store_32(get_string_index(np.get_subname(i)));
			f->store_32(get_string_index(np.get_property()));

		} break;
		case Variant::_RID: {

			f->store_32(VARIANT_RID);
			WARN_PRINT("Can't save RIDs");
			RID val = p_property;
			f->store_32(val.get_id());
		} break;
		case Variant::OBJECT: {

			f->store_32(VARIANT_OBJECT);
			RES res = p_property;
			if (res.is_null()) {
				f->store_32(OBJECT_EMPTY);
				return; // don't save it
			}

			if (res->get_path().length() && res->get_path().find("::")==-1) {
				f->store_32(OBJECT_EXTERNAL_RESOURCE);
				save_unicode_string(res->get_save_type());
				String path=relative_paths?local_path.path_to_file(res->get_path()):res->get_path();
				if (no_extensions)
					path=path.basename()+".*";
				save_unicode_string(path);
			} else {

				if (!resource_map.has(res)) {
					f->store_32(OBJECT_EMPTY);
					ERR_EXPLAIN("Resource was not pre cached for the resource section, bug?");
					ERR_FAIL();
				}

				f->store_32(OBJECT_INTERNAL_RESOURCE);
				f->store_32(resource_map[res]);
				//internal resource
			}


		} break;
		case Variant::INPUT_EVENT: {

			f->store_32(VARIANT_INPUT_EVENT);
			WARN_PRINT("Can't save InputEvent (maybe it could..)");
		} break;
		case Variant::DICTIONARY: {

			f->store_32(VARIANT_DICTIONARY);
			Dictionary d = p_property;
            f->store_32(uint32_t(d.size())|(d.is_shared()?0x80000000:0));

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

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

				//if (!_check_type(dict[E->get()]))
				//	continue;

				write_variant(E->get());
				write_variant(d[E->get()]);
			}


		} break;
		case Variant::ARRAY: {

			f->store_32(VARIANT_ARRAY);
			Array a=p_property;
			f->store_32(uint32_t(a.size())|(a.is_shared()?0x80000000:0));
			for(int i=0;i<a.size();i++) {

				write_variant(a[i]);
			}

		} break;
		case Variant::RAW_ARRAY: {

			f->store_32(VARIANT_RAW_ARRAY);
			DVector<uint8_t> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<uint8_t>::Read r = arr.read();
			f->store_buffer(r.ptr(),len);
			_pad_buffer(len);

		} break;
		case Variant::INT_ARRAY: {

			f->store_32(VARIANT_INT_ARRAY);
			DVector<int> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<int>::Read r = arr.read();
			for(int i=0;i<len;i++)
				f->store_32(r[i]);

		} break;
		case Variant::REAL_ARRAY: {

			f->store_32(VARIANT_REAL_ARRAY);
			DVector<real_t> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<real_t>::Read r = arr.read();
			for(int i=0;i<len;i++) {
				f->store_real(r[i]);
			}

		} break;
		case Variant::STRING_ARRAY: {

			f->store_32(VARIANT_STRING_ARRAY);
			DVector<String> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<String>::Read r = arr.read();
			for(int i=0;i<len;i++) {
				save_unicode_string(r[i]);
			}

		} break;
		case Variant::VECTOR3_ARRAY: {

			f->store_32(VARIANT_VECTOR3_ARRAY);
			DVector<Vector3> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<Vector3>::Read r = arr.read();
			for(int i=0;i<len;i++) {
				f->store_real(r[i].x);
				f->store_real(r[i].y);
				f->store_real(r[i].z);
			}

		} break;
		case Variant::VECTOR2_ARRAY: {

			f->store_32(VARIANT_VECTOR2_ARRAY);
			DVector<Vector2> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<Vector2>::Read r = arr.read();
			for(int i=0;i<len;i++) {
				f->store_real(r[i].x);
				f->store_real(r[i].y);
			}

		} break;
		case Variant::COLOR_ARRAY: {

			f->store_32(VARIANT_COLOR_ARRAY);
			DVector<Color> arr = p_property;
			int len=arr.size();
			f->store_32(len);
			DVector<Color>::Read r = arr.read();
			for(int i=0;i<len;i++) {
				f->store_real(r[i].r);
				f->store_real(r[i].g);
				f->store_real(r[i].b);
				f->store_real(r[i].a);
			}

		} break;
		default: {

			ERR_EXPLAIN("Invalid variant");
			ERR_FAIL();
		}
	}
}