gmio_amf: add ZIP archiving (Zip64 format to be further supported)
This commit is contained in:
parent
73eb7a522e
commit
a2ad3b9d4b
@ -47,16 +47,16 @@
|
||||
|
||||
struct gmio_amf_metadata
|
||||
{
|
||||
const char* type; /* UTF8-encoded */
|
||||
const char* data; /* UTF8-encoded */
|
||||
const char* type; /*!< UTF8-encoded */
|
||||
const char* data; /*!< UTF8-encoded */
|
||||
};
|
||||
|
||||
struct gmio_amf_color
|
||||
{
|
||||
double r; /* in [0,1] */
|
||||
double g; /* in [0,1] */
|
||||
double b; /* in [0,1] */
|
||||
double a; /* in [0,1] optional */
|
||||
double r; /*!< Red channel in [0,1] */
|
||||
double g; /*!< Green channel in [0,1] */
|
||||
double b; /*!< Blue channel in [0,1] */
|
||||
double a; /*!< Optional alpha(transparency) channel in [0,1] */
|
||||
const char* r_formula;
|
||||
const char* g_formula;
|
||||
const char* b_formula;
|
||||
@ -71,13 +71,19 @@ struct gmio_amf_material
|
||||
uint32_t metadata_count;
|
||||
};
|
||||
|
||||
/*! Proportion of the composition of another material
|
||||
*
|
||||
* The proportion can be specified as a formula(with \c value_formula) or as a
|
||||
* constant mixing(with \c value).
|
||||
*/
|
||||
struct gmio_amf_composite
|
||||
{
|
||||
uint32_t materialid; /* XML:nonNegativeInteger, required */
|
||||
double value; /* governs the percent of material */
|
||||
double value; /*!< governs the percent of material */
|
||||
const char* value_formula;
|
||||
};
|
||||
|
||||
/*! Vertex within an AMF mesh */
|
||||
struct gmio_amf_vertex
|
||||
{
|
||||
struct gmio_vec3d coords;
|
||||
@ -88,6 +94,7 @@ struct gmio_amf_vertex
|
||||
uint32_t metadata_count;
|
||||
};
|
||||
|
||||
/*! Edge within an AMF mesh, for curved triangles */
|
||||
struct gmio_amf_edge
|
||||
{
|
||||
uint32_t v1; /* XML:nonNegativeInteger */
|
||||
@ -126,11 +133,12 @@ enum gmio_amf_volume_type
|
||||
GMIO_AMF_VOLUME_TYPE_SUPPORT
|
||||
};
|
||||
|
||||
/*! Volume within an AMF mesh */
|
||||
struct gmio_amf_volume
|
||||
{
|
||||
uint32_t materialid; /* XML:nonNegativeInteger */
|
||||
enum gmio_amf_volume_type type;
|
||||
uint32_t triangle_count; /* Should be >= 4 */
|
||||
uint32_t triangle_count; /*!< Should be >= 4 */
|
||||
uint32_t metadata_count;
|
||||
bool has_color;
|
||||
struct gmio_amf_color color; /* XML:Color */
|
||||
@ -155,10 +163,11 @@ struct gmio_amf_object
|
||||
struct gmio_amf_constellation
|
||||
{
|
||||
uint32_t id; /* XML:integer */
|
||||
uint32_t instance_count; /* Should be >= 2 */
|
||||
uint32_t instance_count; /*!< Should be >= 2 */
|
||||
uint32_t metadata_count;
|
||||
};
|
||||
|
||||
/*! Instance within an AMF constellation */
|
||||
struct gmio_amf_instance
|
||||
{
|
||||
uint32_t objectid; /* XML:nonNegativeInteger */
|
||||
@ -179,9 +188,10 @@ struct gmio_amf_texture
|
||||
uint32_t depth; /* XML:nonNegativeInteger */
|
||||
bool tiled;
|
||||
enum gmio_amf_texture_type type;
|
||||
struct gmio_memblock binary_data; /* Will be converted to base64 */
|
||||
struct gmio_memblock binary_data; /*!< Will be converted to base64 */
|
||||
};
|
||||
|
||||
/*! Units supported by AMF */
|
||||
enum gmio_amf_unit
|
||||
{
|
||||
GMIO_AMF_UNIT_UNKNOWN,
|
||||
@ -192,6 +202,7 @@ enum gmio_amf_unit
|
||||
GMIO_AMF_UNIT_MICRON
|
||||
};
|
||||
|
||||
/*! The direct elements of an AMF document(ie. inside <tt><amf>...</amf></tt>) */
|
||||
enum gmio_amf_document_element
|
||||
{
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_OBJECT,
|
||||
@ -201,6 +212,7 @@ enum gmio_amf_document_element
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_METADATA
|
||||
};
|
||||
|
||||
/*! The direct elements of an AMF mesh(ie. inside <tt><mesh>...</mesh></tt>) */
|
||||
enum gmio_amf_mesh_element
|
||||
{
|
||||
GMIO_AMF_MESH_ELEMENT_VERTEX,
|
||||
@ -223,7 +235,7 @@ struct gmio_amf_document
|
||||
const void* cookie;
|
||||
|
||||
enum gmio_amf_unit unit;
|
||||
uint32_t object_count; /* Must be >= 1 */
|
||||
uint32_t object_count; /*!< Must be >= 1 */
|
||||
uint32_t material_count;
|
||||
uint32_t texture_count;
|
||||
uint32_t constellation_count;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../gmio_core/internal/helper_stream.h"
|
||||
#include "../gmio_core/internal/helper_task_iface.h"
|
||||
#include "../gmio_core/internal/ostringstream.h"
|
||||
#include "../gmio_core/internal/zip_utils.h"
|
||||
#include "../gmio_core/internal/zlib_utils.h"
|
||||
|
||||
#include <stddef.h>
|
||||
@ -58,8 +59,12 @@ struct gmio_amf_wcontext
|
||||
struct gmio_memblock z_memblock;
|
||||
struct z_stream_s z_stream;
|
||||
int z_flush;
|
||||
uintmax_t z_compressed_size;
|
||||
uintmax_t z_uncompressed_size;
|
||||
uint32_t z_crc32;
|
||||
};
|
||||
|
||||
/* Helper to set error code of the writing context */
|
||||
GMIO_INLINE bool gmio_amf_wcontext_set_error(
|
||||
struct gmio_amf_wcontext* context, int error)
|
||||
{
|
||||
@ -67,6 +72,7 @@ GMIO_INLINE bool gmio_amf_wcontext_set_error(
|
||||
return gmio_no_error(error);
|
||||
}
|
||||
|
||||
/* Helper to increment the current task progress of the writing context */
|
||||
GMIO_INLINE void gmio_amf_wcontext_incr_task_progress(
|
||||
struct gmio_amf_wcontext* context)
|
||||
{
|
||||
@ -163,13 +169,11 @@ static void gmio_amf_write_amf_begin(
|
||||
}
|
||||
|
||||
/* Writes document metadata to stream */
|
||||
static bool gmio_amf_write_root_metadata(
|
||||
struct gmio_amf_wcontext* context)
|
||||
static bool gmio_amf_write_root_metadata(struct gmio_amf_wcontext* context)
|
||||
{
|
||||
const struct gmio_amf_document* doc = context->document;
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
uint32_t imeta;
|
||||
for (imeta = 0; imeta < doc->metadata_count; ++imeta) {
|
||||
for (uint32_t imeta = 0; imeta < doc->metadata_count; ++imeta) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_METADATA, imeta, &metadata);
|
||||
@ -180,31 +184,27 @@ static bool gmio_amf_write_root_metadata(
|
||||
}
|
||||
|
||||
/* Writes document materials to stream */
|
||||
static bool gmio_amf_write_root_materials(
|
||||
struct gmio_amf_wcontext* context)
|
||||
static bool gmio_amf_write_root_materials(struct gmio_amf_wcontext* context)
|
||||
{
|
||||
const struct gmio_amf_document* doc = context->document;
|
||||
struct gmio_ostringstream* sstream = context->sstream;
|
||||
struct gmio_amf_material material = {0};
|
||||
uint32_t imat;
|
||||
for (imat = 0; imat < doc->material_count; ++imat) {
|
||||
for (uint32_t imat = 0; imat < doc->material_count; ++imat) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_MATERIAL, imat, &material);
|
||||
gmio_ostringstream_write_chararray(sstream, "<material");
|
||||
gmio_ostringstream_write_xmlattr_u32(sstream, "id", material.id);
|
||||
gmio_ostringstream_write_char(sstream, '>');
|
||||
gmio_ostringstream_write_chararray(sstream, ">\n");
|
||||
/* Write material <metadata> elements */
|
||||
if (material.metadata_count > 0) {
|
||||
uint32_t imeta;
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
/* Check function pointer is defined */
|
||||
if (doc->func_get_document_element_metadata == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_DOCUMENT_ELEMENT_METADATA);
|
||||
}
|
||||
for (imeta = 0; imeta < material.metadata_count; ++imeta) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
for (uint32_t imeta = 0; imeta < material.metadata_count; ++imeta) {
|
||||
doc->func_get_document_element_metadata(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_MATERIAL,
|
||||
@ -218,15 +218,13 @@ static bool gmio_amf_write_root_materials(
|
||||
gmio_amf_write_color(context, &material.color);
|
||||
/* Write material <composite> elements */
|
||||
if (material.composite_count > 0) {
|
||||
struct gmio_amf_composite composite = {0};
|
||||
uint32_t icomp;
|
||||
/* Check function pointer is defined */
|
||||
if (doc->func_get_material_composite == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_MATERIAL_COMPOSITE);
|
||||
}
|
||||
for (icomp = 0; icomp < material.composite_count; ++icomp) {
|
||||
struct gmio_amf_composite composite = {0};
|
||||
for (uint32_t icomp = 0; icomp < material.composite_count; ++icomp) {
|
||||
doc->func_get_material_composite(
|
||||
doc->cookie, imat, icomp, &composite);
|
||||
gmio_ostringstream_write_chararray(sstream, "<composite");
|
||||
@ -287,11 +285,10 @@ static bool gmio_amf_write_mesh(
|
||||
*base_mesh_element_index;
|
||||
const struct gmio_ostringstream_format_float* f64_format =
|
||||
&context->f64_format;
|
||||
struct gmio_amf_vertex vertex = {0};
|
||||
uint32_t ivert;
|
||||
/* Write mesh <vertices> element */
|
||||
gmio_ostringstream_write_chararray(sstream, "<mesh>\n<vertices>");
|
||||
for (ivert = 0; ivert < mesh->vertex_count; ++ivert) {
|
||||
struct gmio_amf_vertex vertex = {0};
|
||||
gmio_ostringstream_write_chararray(sstream, "<mesh>\n<vertices>\n");
|
||||
for (uint32_t ivert = 0; ivert < mesh->vertex_count; ++ivert) {
|
||||
mesh_elt_index.value = ivert;
|
||||
doc->func_get_object_mesh_element(
|
||||
doc->cookie,
|
||||
@ -320,15 +317,13 @@ static bool gmio_amf_write_mesh(
|
||||
}
|
||||
/* Write <metadata> elements */
|
||||
if (vertex.metadata_count > 0) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
uint32_t imeta;
|
||||
/* Check function pointer */
|
||||
if (doc->func_get_object_mesh_vertex_metadata == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_OBJECT_MESH_VERTEX_METADATA);
|
||||
}
|
||||
for (imeta = 0; imeta < vertex.metadata_count; ++imeta) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
for (uint32_t imeta = 0; imeta < vertex.metadata_count; ++imeta) {
|
||||
doc->func_get_object_mesh_vertex_metadata(
|
||||
doc->cookie, &mesh_elt_index, imeta, &metadata);
|
||||
gmio_amf_write_metadata(sstream, &metadata);
|
||||
@ -342,8 +337,7 @@ static bool gmio_amf_write_mesh(
|
||||
/* Write mesh vertices <edge> elements */
|
||||
if (mesh->edge_count > 0) {
|
||||
struct gmio_amf_edge edge = {0};
|
||||
uint32_t iedge;
|
||||
for (iedge = 0; iedge < mesh->edge_count; ++iedge) {
|
||||
for (uint32_t iedge = 0; iedge < mesh->edge_count; ++iedge) {
|
||||
mesh_elt_index.value = iedge;
|
||||
doc->func_get_object_mesh_element(
|
||||
doc->cookie,
|
||||
@ -374,9 +368,7 @@ static bool gmio_amf_write_mesh(
|
||||
/* Write mesh <volume> elements */
|
||||
if (mesh->volume_count > 0) {
|
||||
struct gmio_amf_volume volume = {0};
|
||||
uint32_t ivol;
|
||||
for (ivol = 0; ivol < mesh->volume_count; ++ivol) {
|
||||
const char* str_volume_type = "";
|
||||
for (uint32_t ivol = 0; ivol < mesh->volume_count; ++ivol) {
|
||||
mesh_elt_index.value = ivol;
|
||||
doc->func_get_object_mesh_element(
|
||||
doc->cookie,
|
||||
@ -385,6 +377,7 @@ static bool gmio_amf_write_mesh(
|
||||
gmio_ostringstream_write_chararray(sstream, "<volume");
|
||||
gmio_ostringstream_write_xmlattr_u32(
|
||||
sstream, "materialid", volume.materialid);
|
||||
const char* str_volume_type = "";
|
||||
switch (volume.type) {
|
||||
case GMIO_AMF_VOLUME_TYPE_OBJECT:
|
||||
str_volume_type = "object"; break;
|
||||
@ -392,18 +385,16 @@ static bool gmio_amf_write_mesh(
|
||||
str_volume_type = "support"; break;
|
||||
}
|
||||
gmio_ostringstream_write_xmlattr_str(sstream, "type", str_volume_type);
|
||||
gmio_ostringstream_write_char(sstream, '>');
|
||||
gmio_ostringstream_write_chararray(sstream, ">\n");
|
||||
/* Write volume <metadata> elements */
|
||||
if (volume.metadata_count > 0) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
uint32_t imeta;
|
||||
/* Check function pointer */
|
||||
if (doc->func_get_object_mesh_volume_metadata == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_OBJECT_MESH_VOLUME_METADATA);
|
||||
}
|
||||
for (imeta = 0; imeta < volume.metadata_count; ++imeta) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
for (uint32_t imeta = 0; imeta < volume.metadata_count; ++imeta) {
|
||||
doc->func_get_object_mesh_volume_metadata(
|
||||
doc->cookie, &mesh_elt_index, imeta, &metadata);
|
||||
gmio_amf_write_metadata(sstream, &metadata);
|
||||
@ -415,8 +406,7 @@ static bool gmio_amf_write_mesh(
|
||||
/* Write <triangle> elements */
|
||||
if (volume.triangle_count > 0) {
|
||||
struct gmio_amf_triangle triangle = {0};
|
||||
uint32_t itri;
|
||||
for (itri = 0; itri < volume.triangle_count; ++itri) {
|
||||
for (uint32_t itri = 0; itri < volume.triangle_count; ++itri) {
|
||||
doc->func_get_object_mesh_volume_triangle(
|
||||
doc->cookie, &mesh_elt_index, itri, &triangle);
|
||||
gmio_ostringstream_write_chararray(sstream, "<triangle>");
|
||||
@ -453,26 +443,23 @@ static bool gmio_amf_write_root_objects(struct gmio_amf_wcontext* context)
|
||||
const struct gmio_amf_document* doc = context->document;
|
||||
struct gmio_ostringstream* sstream = context->sstream;
|
||||
struct gmio_amf_object object = {0};
|
||||
uint32_t iobj;
|
||||
for (iobj = 0; iobj < doc->object_count; ++iobj) {
|
||||
for (uint32_t iobj = 0; iobj < doc->object_count; ++iobj) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_OBJECT, iobj, &object);
|
||||
/* Open object element */
|
||||
gmio_ostringstream_write_chararray(sstream, "<object");
|
||||
gmio_ostringstream_write_xmlattr_u32(sstream, "id", object.id);
|
||||
gmio_ostringstream_write_char(sstream, '>');
|
||||
gmio_ostringstream_write_chararray(sstream, ">\n");
|
||||
/* Write metadata elements */
|
||||
if (object.metadata_count > 0) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
uint32_t imeta;
|
||||
/* Check function pointer */
|
||||
if (doc->func_get_document_element_metadata == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_DOCUMENT_ELEMENT_METADATA);
|
||||
}
|
||||
for (imeta = 0; imeta < object.metadata_count; ++imeta) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
for (uint32_t imeta = 0; imeta < object.metadata_count; ++imeta) {
|
||||
doc->func_get_document_element_metadata(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_OBJECT,
|
||||
@ -488,8 +475,7 @@ static bool gmio_amf_write_root_objects(struct gmio_amf_wcontext* context)
|
||||
/* Write mesh elements */
|
||||
if (object.mesh_count > 0) {
|
||||
struct gmio_amf_mesh mesh = {0};
|
||||
uint32_t imesh;
|
||||
for (imesh = 0; imesh < object.mesh_count; ++imesh) {
|
||||
for (uint32_t imesh = 0; imesh < object.mesh_count; ++imesh) {
|
||||
struct gmio_amf_object_mesh_element_index base_mesh_elt_index;
|
||||
doc->func_get_object_mesh(doc->cookie, iobj, imesh, &mesh);
|
||||
base_mesh_elt_index.object_index = iobj;
|
||||
@ -512,9 +498,7 @@ static bool gmio_amf_write_root_textures(struct gmio_amf_wcontext* context)
|
||||
const struct gmio_amf_document* doc = context->document;
|
||||
struct gmio_ostringstream* sstream = context->sstream;
|
||||
struct gmio_amf_texture texture = {0};
|
||||
uint32_t itex;
|
||||
for (itex = 0; itex < doc->texture_count; ++itex) {
|
||||
const char* str_texture_type = "";
|
||||
for (uint32_t itex = 0; itex < doc->texture_count; ++itex) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_TEXTURE, itex, &texture);
|
||||
@ -525,6 +509,7 @@ static bool gmio_amf_write_root_textures(struct gmio_amf_wcontext* context)
|
||||
gmio_ostringstream_write_xmlattr_u32(sstream, "depth", texture.depth);
|
||||
gmio_ostringstream_write_xmlattr_str(
|
||||
sstream, "tiled", texture.tiled ? "true" : "false");
|
||||
const char* str_texture_type = "";
|
||||
switch (texture.type) {
|
||||
case GMIO_AMF_TEXTURE_TYPE_GRAYSCALE:
|
||||
str_texture_type = "grayscale"; break;
|
||||
@ -544,31 +529,27 @@ static bool gmio_amf_write_root_textures(struct gmio_amf_wcontext* context)
|
||||
}
|
||||
|
||||
/* Writes document constellations to stream */
|
||||
static bool gmio_amf_write_root_constellations(
|
||||
struct gmio_amf_wcontext* context)
|
||||
static bool gmio_amf_write_root_constellations(struct gmio_amf_wcontext* context)
|
||||
{
|
||||
const struct gmio_amf_document* doc = context->document;
|
||||
struct gmio_ostringstream* sstream = context->sstream;
|
||||
struct gmio_amf_constellation constellation = {0};
|
||||
uint32_t icons;
|
||||
for (icons = 0; icons < doc->constellation_count; ++icons) {
|
||||
for (uint32_t icons = 0; icons < doc->constellation_count; ++icons) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_CONSTELLATION, icons, &constellation);
|
||||
gmio_ostringstream_write_chararray(sstream, "<constellation");
|
||||
gmio_ostringstream_write_xmlattr_u32(sstream, "id", constellation.id);
|
||||
gmio_ostringstream_write_char(sstream, '>');
|
||||
gmio_ostringstream_write_chararray(sstream, ">\n");
|
||||
/* Write constellation <metadata> elements */
|
||||
if (constellation.metadata_count > 0) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
uint32_t imeta;
|
||||
/* Check function pointer */
|
||||
if (doc->func_get_document_element_metadata == NULL) {
|
||||
return gmio_amf_wcontext_set_error(
|
||||
context,
|
||||
GMIO_AMF_ERROR_NULL_FUNC_GET_DOCUMENT_ELEMENT_METADATA);
|
||||
}
|
||||
for (imeta = 0; imeta < constellation.metadata_count; ++imeta) {
|
||||
struct gmio_amf_metadata metadata = {0};
|
||||
for (uint32_t imeta = 0; imeta < constellation.metadata_count; ++imeta) {
|
||||
doc->func_get_document_element_metadata(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_CONSTELLATION,
|
||||
@ -581,8 +562,7 @@ static bool gmio_amf_write_root_constellations(
|
||||
/* Write constellation <instance> elements */
|
||||
if (constellation.instance_count > 0) {
|
||||
struct gmio_amf_instance instance = {0};
|
||||
uint32_t iinst;
|
||||
for (iinst = 0; iinst < constellation.instance_count; ++iinst) {
|
||||
for (uint32_t iinst = 0; iinst < constellation.instance_count; ++iinst) {
|
||||
doc->func_get_constellation_instance(
|
||||
doc->cookie, icons, iinst, &instance);
|
||||
gmio_ostringstream_write_chararray(sstream, "<instance");
|
||||
@ -613,7 +593,7 @@ static bool gmio_amf_write_root_constellations(
|
||||
}
|
||||
|
||||
/* Returns true if internal document data are roughly accessible */
|
||||
static bool gmio_amf_check_error(
|
||||
static bool gmio_amf_check_document(
|
||||
int* error, const struct gmio_amf_document* doc)
|
||||
{
|
||||
if (doc == NULL) {
|
||||
@ -650,8 +630,12 @@ static size_t gmio_amf_ostringstream_write_zlib(
|
||||
struct z_stream_s* z_stream = &context->z_stream;
|
||||
size_t total_written_len = 0;
|
||||
int z_retcode = Z_OK;
|
||||
|
||||
context->z_uncompressed_size += len;
|
||||
context->z_crc32 = crc32(context->z_crc32, (const Bytef*)ptr, len);
|
||||
|
||||
z_stream->next_in = (z_const Bytef*)ptr;
|
||||
z_stream->avail_in = len; /* TODO: use better cast */
|
||||
z_stream->avail_in = len;
|
||||
/* Run zlib deflate() on input until output buffer not full
|
||||
* Finish compression when zflush == Z_FINISH */
|
||||
do {
|
||||
@ -688,10 +672,16 @@ static size_t gmio_amf_ostringstream_write_zlib(
|
||||
context->error = GMIO_ERROR_UNKNOWN;
|
||||
return total_written_len;
|
||||
}
|
||||
context->z_compressed_size += total_written_len;
|
||||
return total_written_len;
|
||||
|
||||
/* zlib official "howto" from http://zlib.net/zlib_how.html */
|
||||
#if 0
|
||||
int ret, flush;
|
||||
unsigned have;
|
||||
z_stream strm;
|
||||
unsigned char in[CHUNK];
|
||||
unsigned char out[CHUNK];
|
||||
/* compress until end of file */
|
||||
do {
|
||||
strm.avail_in = fread(in, 1, CHUNK, source);
|
||||
@ -702,7 +692,7 @@ static size_t gmio_amf_ostringstream_write_zlib(
|
||||
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
|
||||
strm.next_in = in;
|
||||
/* run deflate() on input until output buffer not full, finish
|
||||
compression if all of source has been read in */
|
||||
* compression if all of source has been read in */
|
||||
do {
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
@ -763,120 +753,145 @@ static intmax_t gmio_amf_task_progress_max(const struct gmio_amf_document* doc)
|
||||
progress_max += doc->material_count;
|
||||
progress_max += doc->texture_count;
|
||||
/* Add total object(vertex_count + edge_count + triangle_count) */
|
||||
{
|
||||
struct gmio_amf_object object = {0};
|
||||
uint32_t iobj;
|
||||
for (iobj = 0; iobj < doc->object_count; ++iobj) {
|
||||
struct gmio_amf_mesh mesh = {0};
|
||||
uint32_t imesh;
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_OBJECT, iobj, &object);
|
||||
for (imesh = 0; imesh < object.mesh_count; ++imesh) {
|
||||
doc->func_get_object_mesh(doc->cookie, iobj, imesh, &mesh);
|
||||
progress_max += mesh.vertex_count;
|
||||
progress_max += mesh.edge_count;
|
||||
{
|
||||
struct gmio_amf_object_mesh_element_index mesh_elt_index;
|
||||
uint32_t ivol;
|
||||
mesh_elt_index.object_index = iobj;
|
||||
mesh_elt_index.mesh_index = imesh;
|
||||
mesh_elt_index.value = 0;
|
||||
for (ivol = 0; ivol < mesh.volume_count; ++ivol) {
|
||||
struct gmio_amf_volume volume = {0};
|
||||
mesh_elt_index.value = ivol;
|
||||
doc->func_get_object_mesh_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_MESH_ELEMENT_VOLUME,
|
||||
&mesh_elt_index,
|
||||
&volume);
|
||||
progress_max += volume.triangle_count;
|
||||
}
|
||||
}
|
||||
struct gmio_amf_object object = {0};
|
||||
for (uint32_t iobj = 0; iobj < doc->object_count; ++iobj) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_OBJECT, iobj, &object);
|
||||
struct gmio_amf_mesh mesh = {0};
|
||||
for (uint32_t imesh = 0; imesh < object.mesh_count; ++imesh) {
|
||||
doc->func_get_object_mesh(doc->cookie, iobj, imesh, &mesh);
|
||||
progress_max += mesh.vertex_count;
|
||||
progress_max += mesh.edge_count;
|
||||
struct gmio_amf_object_mesh_element_index mesh_elt_index;
|
||||
mesh_elt_index.object_index = iobj;
|
||||
mesh_elt_index.mesh_index = imesh;
|
||||
mesh_elt_index.value = 0;
|
||||
for (uint32_t ivol = 0; ivol < mesh.volume_count; ++ivol) {
|
||||
struct gmio_amf_volume volume = {0};
|
||||
mesh_elt_index.value = ivol;
|
||||
doc->func_get_object_mesh_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_MESH_ELEMENT_VOLUME,
|
||||
&mesh_elt_index,
|
||||
&volume);
|
||||
progress_max += volume.triangle_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Add total constellation(instance_count) */
|
||||
{
|
||||
struct gmio_amf_constellation constellation = {0};
|
||||
uint32_t icons;
|
||||
for (icons = 0; icons < doc->constellation_count; ++icons) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_CONSTELLATION,
|
||||
icons,
|
||||
&constellation);
|
||||
progress_max += constellation.instance_count;
|
||||
}
|
||||
struct gmio_amf_constellation constellation = {0};
|
||||
for (uint32_t icons = 0; icons < doc->constellation_count; ++icons) {
|
||||
doc->func_get_document_element(
|
||||
doc->cookie,
|
||||
GMIO_AMF_DOCUMENT_ELEMENT_CONSTELLATION,
|
||||
icons,
|
||||
&constellation);
|
||||
progress_max += constellation.instance_count;
|
||||
}
|
||||
return progress_max;
|
||||
}
|
||||
|
||||
struct gmio_zip_entry_filename {
|
||||
const char* ptr;
|
||||
uint16_t len;
|
||||
};
|
||||
|
||||
/* Returns a non-null C string for the ZIP entry filename in options */
|
||||
static struct gmio_zip_entry_filename gmio_amf_zip_entry_filename(
|
||||
const struct gmio_amf_write_options* options)
|
||||
{
|
||||
static const char default_filename[] = "geometry.amf";
|
||||
const char* filename = options->zip_entry_filename;
|
||||
const bool is_empty_filename = filename == NULL || *filename == '\0';
|
||||
struct gmio_zip_entry_filename zip_filename;
|
||||
zip_filename.ptr = is_empty_filename ? default_filename : filename;
|
||||
zip_filename.len =
|
||||
is_empty_filename ?
|
||||
sizeof(default_filename) - 1 :
|
||||
options->zip_entry_filename_len;
|
||||
return zip_filename;
|
||||
}
|
||||
|
||||
int gmio_amf_write(
|
||||
struct gmio_stream* stream,
|
||||
const struct gmio_amf_document* doc,
|
||||
const struct gmio_amf_write_options* opts)
|
||||
{
|
||||
/* Constants */
|
||||
static const struct gmio_amf_write_options default_write_opts = {0};
|
||||
opts = opts != NULL ? opts : &default_write_opts;
|
||||
|
||||
/* Constants */
|
||||
struct gmio_memblock_helper mblock_helper =
|
||||
gmio_memblock_helper(opts != NULL ? &opts->stream_memblock : NULL);
|
||||
const struct gmio_memblock* memblock = &mblock_helper.memblock;
|
||||
const struct gmio_zip_entry_filename zip_entry_filename =
|
||||
gmio_amf_zip_entry_filename(opts);
|
||||
|
||||
/* Variables */
|
||||
struct gmio_amf_wcontext context = {0};
|
||||
struct gmio_ostringstream sstream =
|
||||
gmio_ostringstream(
|
||||
*stream, gmio_string(memblock->ptr, 0, memblock->size));
|
||||
|
||||
opts = opts != NULL ? opts : &default_write_opts;
|
||||
uintmax_t zip_write_pos = 0;
|
||||
|
||||
/* Check validity of input parameters */
|
||||
context.error = GMIO_ERROR_OK;
|
||||
/* TODO: check stream function pointers */
|
||||
if (!gmio_check_memblock(&context.error, memblock))
|
||||
goto label_end;
|
||||
if (!gmio_amf_check_error(&context.error, doc))
|
||||
if (!gmio_amf_check_document(&context.error, doc))
|
||||
goto label_end;
|
||||
|
||||
/* Initialize writing context */
|
||||
{
|
||||
const struct gmio_string_16 f64_stdio_format =
|
||||
gmio_to_stdio_float_format(
|
||||
opts->float64_format, opts->float64_prec);
|
||||
context.options = opts;
|
||||
context.sstream = &sstream;
|
||||
context.document = doc;
|
||||
context.task_iface = &opts->task_iface;
|
||||
context.task_progress_current = 0;
|
||||
if (context.task_iface->func_handle_progress != NULL)
|
||||
context.task_progress_max += gmio_amf_task_progress_max(doc);
|
||||
context.f64_format.printf_format = f64_stdio_format.array;
|
||||
context.f64_format.text_format = opts->float64_format;
|
||||
context.f64_format.precision =
|
||||
opts->float64_prec != 0 ? opts->float64_prec : 16;
|
||||
|
||||
const struct gmio_string_16 f64_stdio_format =
|
||||
gmio_to_stdio_float_format(opts->float64_format, opts->float64_prec);
|
||||
context.options = opts;
|
||||
context.sstream = &sstream;
|
||||
context.document = doc;
|
||||
context.task_iface = &opts->task_iface;
|
||||
context.task_progress_current = 0;
|
||||
if (context.task_iface->func_handle_progress != NULL)
|
||||
context.task_progress_max += gmio_amf_task_progress_max(doc);
|
||||
context.f64_format.printf_format = f64_stdio_format.array;
|
||||
context.f64_format.text_format = opts->float64_format;
|
||||
context.f64_format.precision =
|
||||
opts->float64_prec != 0 ? opts->float64_prec : 16;
|
||||
if (opts->compress) {
|
||||
/* Initialize internal zlib stream for compression */
|
||||
if (opts->compress) {
|
||||
const size_t mblock_halfsize = memblock->size / 2;
|
||||
context.sstream->strbuff.capacity = mblock_halfsize;
|
||||
context.z_memblock =
|
||||
gmio_memblock(
|
||||
(uint8_t*)memblock->ptr + mblock_halfsize,
|
||||
mblock_halfsize,
|
||||
NULL);
|
||||
context.error =
|
||||
gmio_zlib_compress_init(
|
||||
&context.z_stream, &opts->z_compress_options);
|
||||
if (gmio_error(context.error))
|
||||
goto label_end;
|
||||
context.z_flush = Z_NO_FLUSH;
|
||||
}
|
||||
const size_t mblock_halfsize = memblock->size / 2;
|
||||
context.sstream->strbuff.capacity = mblock_halfsize;
|
||||
context.z_memblock =
|
||||
gmio_memblock(
|
||||
(uint8_t*)memblock->ptr + mblock_halfsize,
|
||||
mblock_halfsize,
|
||||
NULL);
|
||||
context.z_crc32 = crc32(0, NULL, 0);
|
||||
context.error =
|
||||
gmio_zlib_compress_init(
|
||||
&context.z_stream, &opts->z_compress_options);
|
||||
if (gmio_error(context.error))
|
||||
goto label_end;
|
||||
context.z_flush = Z_NO_FLUSH;
|
||||
}
|
||||
|
||||
sstream.cookie = &context;
|
||||
sstream.func_stream_write = &gmio_amf_ostringstream_write;
|
||||
|
||||
/* If compression enabled, write ZIP local file header */
|
||||
if (opts->compress) {
|
||||
struct gmio_zip_local_file_header info = {0};
|
||||
info.general_purpose_flags =
|
||||
GMIO_ZIP_GENERAL_PURPOSE_FLAG_USE_DATA_DESCRIPTOR;
|
||||
info.compress_method = GMIO_ZIP_COMPRESS_METHOD_DEFLATE;
|
||||
info.filename = zip_entry_filename.ptr;
|
||||
info.filename_len = zip_entry_filename.len;
|
||||
zip_write_pos +=
|
||||
gmio_zip_write_local_file_header(stream, &info, &context.error);
|
||||
if (gmio_error(context.error))
|
||||
goto label_end;
|
||||
}
|
||||
|
||||
gmio_amf_write_amf_begin(&sstream, doc);
|
||||
if (!gmio_amf_write_root_metadata(&context))
|
||||
goto label_end;
|
||||
@ -896,6 +911,49 @@ int gmio_amf_write(
|
||||
gmio_ostringstream_write_chararray(&sstream, "</amf>\n");
|
||||
gmio_ostringstream_flush(&sstream);
|
||||
|
||||
/* Write ending ZIP archive data */
|
||||
if (opts->compress && gmio_no_error(context.error)) {
|
||||
zip_write_pos += context.z_compressed_size;
|
||||
/* Write data descriptor */
|
||||
struct gmio_zip_data_descriptor dd = {0};
|
||||
dd.crc32 = context.z_crc32;
|
||||
dd.compressed_size = context.z_compressed_size;
|
||||
dd.uncompressed_size = context.z_uncompressed_size;
|
||||
zip_write_pos +=
|
||||
gmio_zip_write_data_descriptor(stream, &dd, &context.error);
|
||||
if (gmio_error(context.error))
|
||||
goto label_end;
|
||||
/* Write central directory header */
|
||||
struct gmio_zip_central_directory_header cdh = {0};
|
||||
cdh.version_needed_to_extract =
|
||||
GMIO_ZIP_FEATURE_VERSION_FILE_COMPRESSED_DEFLATE;
|
||||
cdh.general_purpose_flags =
|
||||
GMIO_ZIP_GENERAL_PURPOSE_FLAG_USE_DATA_DESCRIPTOR;
|
||||
cdh.compress_method = GMIO_ZIP_COMPRESS_METHOD_DEFLATE;
|
||||
cdh.crc32 = context.z_crc32;
|
||||
cdh.compressed_size = (uint32_t)context.z_compressed_size;
|
||||
cdh.uncompressed_size = (uint32_t)context.z_uncompressed_size;
|
||||
cdh.filename = zip_entry_filename.ptr;
|
||||
cdh.filename_len = zip_entry_filename.len;
|
||||
const uintmax_t central_dir_startpos = zip_write_pos;
|
||||
const size_t central_dir_size =
|
||||
gmio_zip_write_central_directory_header(
|
||||
stream, &cdh, &context.error);
|
||||
zip_write_pos += central_dir_size;
|
||||
if (gmio_error(context.error))
|
||||
goto label_end;
|
||||
/* Write end of central directory record */
|
||||
struct gmio_zip_end_of_central_directory_record eocdr = {0};
|
||||
eocdr.total_entry_count_in_central_dir_on_disk = 1;
|
||||
eocdr.total_entry_count_in_central_dir = 1;
|
||||
eocdr.central_dir_size = (uint32_t)central_dir_size;
|
||||
eocdr.start_offset_central_dir_from_disk_start_nb =
|
||||
(uint32_t)central_dir_startpos;
|
||||
zip_write_pos +=
|
||||
gmio_zip_write_end_of_central_directory_record(
|
||||
stream, &eocdr, &context.error);
|
||||
}
|
||||
|
||||
label_end:
|
||||
if (opts->compress)
|
||||
deflateEnd(&context.z_stream);
|
||||
@ -911,6 +969,8 @@ int gmio_amf_write_file(
|
||||
const bool compress = opts != NULL ? opts->compress : false;
|
||||
FILE* file = fopen(filepath, compress ? "wb" : "w");
|
||||
if (file != NULL) {
|
||||
/* TODO: if opts->zip_entry_filename is empty then try to take the
|
||||
* filename part of filepath */
|
||||
struct gmio_stream stream = gmio_stream_stdio(file);
|
||||
const int error = gmio_amf_write(&stream, doc, opts);
|
||||
fclose(file);
|
||||
|
@ -76,10 +76,12 @@ struct gmio_amf_write_options
|
||||
*/
|
||||
uint8_t float64_prec;
|
||||
|
||||
/* ZIP compression */
|
||||
/* ZIP/Deflate compression */
|
||||
|
||||
bool compress;
|
||||
struct gmio_zlib_compress_options z_compress_options;
|
||||
const char* zip_entry_filename;
|
||||
uint16_t zip_entry_filename_len;
|
||||
};
|
||||
|
||||
#endif /* GMIO_AMF_IO_OPTIONS_H */
|
||||
|
@ -139,6 +139,11 @@ typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
# endif
|
||||
|
||||
# define INT16_MAX 0x7FFF
|
||||
# define UINT16_MAX 0xFFFF
|
||||
# define INT32_MAX 0x7FFFFFFF
|
||||
# define UINT32_MAX 0xFFFFFFFF
|
||||
|
||||
#endif
|
||||
|
||||
/* GMIO_HAVE_STDBOOL_H */
|
||||
|
@ -30,21 +30,6 @@
|
||||
#include "zlib_utils.h"
|
||||
#include "../error.h"
|
||||
|
||||
/* Converts zlib error to gmio "zlib-specific" error */
|
||||
int zlib_error_to_gmio_error(int z_error)
|
||||
{
|
||||
switch (z_error) {
|
||||
case Z_OK: return GMIO_ERROR_OK;
|
||||
case Z_ERRNO: return GMIO_ERROR_ZLIB_ERRNO;
|
||||
case Z_STREAM_ERROR: return GMIO_ERROR_ZLIB_STREAM;
|
||||
case Z_DATA_ERROR: return GMIO_ERROR_ZLIB_DATA;
|
||||
case Z_MEM_ERROR: return GMIO_ERROR_ZLIB_MEM;
|
||||
case Z_BUF_ERROR: return GMIO_ERROR_ZLIB_BUF;
|
||||
case Z_VERSION_ERROR: return GMIO_ERROR_ZLIB_VERSION;
|
||||
}
|
||||
return GMIO_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
static int gmio_to_zlib_compress_level(int gmio_compress_level)
|
||||
{
|
||||
if (gmio_compress_level == GMIO_ZLIB_COMPRESS_LEVEL_DEFAULT)
|
||||
@ -61,6 +46,21 @@ static int gmio_to_zlib_compress_memusage(int gmio_compress_memusage)
|
||||
return gmio_compress_memusage;
|
||||
}
|
||||
|
||||
/* Converts zlib error to gmio "zlib-specific" error */
|
||||
int zlib_error_to_gmio_error(int z_error)
|
||||
{
|
||||
switch (z_error) {
|
||||
case Z_OK: return GMIO_ERROR_OK;
|
||||
case Z_ERRNO: return GMIO_ERROR_ZLIB_ERRNO;
|
||||
case Z_STREAM_ERROR: return GMIO_ERROR_ZLIB_STREAM;
|
||||
case Z_DATA_ERROR: return GMIO_ERROR_ZLIB_DATA;
|
||||
case Z_MEM_ERROR: return GMIO_ERROR_ZLIB_MEM;
|
||||
case Z_BUF_ERROR: return GMIO_ERROR_ZLIB_BUF;
|
||||
case Z_VERSION_ERROR: return GMIO_ERROR_ZLIB_VERSION;
|
||||
}
|
||||
return GMIO_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
int gmio_zlib_compress_init(
|
||||
struct z_stream_s* z_stream,
|
||||
const struct gmio_zlib_compress_options* z_opts)
|
||||
@ -69,12 +69,23 @@ int gmio_zlib_compress_init(
|
||||
gmio_to_zlib_compress_level(z_opts->level);
|
||||
const int zlib_compress_memusage =
|
||||
gmio_to_zlib_compress_memusage(z_opts->memory_usage);
|
||||
/* zlib doc:
|
||||
* the windowBits parameter is the base two logarithm of the window size
|
||||
* (the size of the history buffer). It should be in the range 8..15 for
|
||||
* this version of the library. Larger values of this parameter result in
|
||||
* better compression at the expense of memory usage. The default value is
|
||||
* 15 if deflateInit is used instead.
|
||||
* windowBits can also be –8..–15 for raw deflate. In this case, -windowBits
|
||||
* determines the window size. deflate() will then generate raw deflate
|
||||
* data with no zlib header or trailer, and will not compute an adler32
|
||||
* check value. */
|
||||
static const int z_window_bits = -15;
|
||||
const int z_init_error =
|
||||
deflateInit2_(
|
||||
z_stream,
|
||||
zlib_compress_level,
|
||||
Z_DEFLATED, /* Method */
|
||||
15, /* Window bits(default value) */
|
||||
z_window_bits,
|
||||
zlib_compress_memusage,
|
||||
z_opts->strategy,
|
||||
ZLIB_VERSION,
|
||||
|
@ -33,12 +33,15 @@
|
||||
#include "stream_buffer.h"
|
||||
|
||||
#include "../src/gmio_core/error.h"
|
||||
#include "../src/gmio_core/internal/byte_codec.h"
|
||||
#include "../src/gmio_core/internal/helper_stream.h"
|
||||
#include "../src/gmio_core/internal/zip_utils.h"
|
||||
#include "../src/gmio_amf/amf_error.h"
|
||||
#include "../src/gmio_amf/amf_io.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
struct __tamf__material
|
||||
@ -108,10 +111,10 @@ static void __tamf__get_object_mesh(
|
||||
uint32_t mesh_index,
|
||||
struct gmio_amf_mesh* ptr_mesh)
|
||||
{
|
||||
const struct __tamf__document* doc =
|
||||
(const struct __tamf__document*)cookie;
|
||||
GMIO_UNUSED(object_index);
|
||||
GMIO_UNUSED(mesh_index);
|
||||
const struct __tamf__document* doc =
|
||||
(const struct __tamf__document*)cookie;
|
||||
ptr_mesh->vertex_count = doc->mesh.vertex_count;
|
||||
ptr_mesh->edge_count = 0;
|
||||
ptr_mesh->volume_count = 1;
|
||||
@ -147,9 +150,9 @@ static void __tamf__get_object_mesh_volume_triangle(
|
||||
uint32_t triangle_index,
|
||||
struct gmio_amf_triangle* ptr_triangle)
|
||||
{
|
||||
GMIO_UNUSED(volume_index);
|
||||
const struct __tamf__document* doc = (const struct __tamf__document*)cookie;
|
||||
const struct __tamf__triangle* tri = &doc->mesh.vec_triangle[triangle_index];
|
||||
GMIO_UNUSED(volume_index);
|
||||
ptr_triangle->v1 = tri->vertex[0];
|
||||
ptr_triangle->v2 = tri->vertex[1];
|
||||
ptr_triangle->v3 = tri->vertex[2];
|
||||
@ -162,14 +165,19 @@ static void __tamf__get_document_element_metadata(
|
||||
uint32_t metadata_index,
|
||||
struct gmio_amf_metadata* ptr_metadata)
|
||||
{
|
||||
const struct __tamf__document* doc = (const struct __tamf__document*)cookie;
|
||||
GMIO_UNUSED(metadata_index);
|
||||
const struct __tamf__document* doc = (const struct __tamf__document*)cookie;
|
||||
if (element == GMIO_AMF_DOCUMENT_ELEMENT_MATERIAL) {
|
||||
ptr_metadata->type = "name";
|
||||
ptr_metadata->data = doc->vec_material[element_index].name;
|
||||
}
|
||||
}
|
||||
|
||||
static void __tamf__skip_zip_local_file_header()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const char* test_amf_write()
|
||||
{
|
||||
{
|
||||
@ -247,20 +255,71 @@ static const char* test_amf_write()
|
||||
if (gmio_error(error))
|
||||
printf("\n0x%x\n", error);
|
||||
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||
printf("%s\n", wbuff.ptr);
|
||||
/* printf("%s\n", wbuff.ptr); */
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Write compressed */
|
||||
/* Write compressed ZIP */
|
||||
{
|
||||
int error = GMIO_ERROR_OK;
|
||||
const size_t source_len = wbuff.pos;
|
||||
uint8_t* source = calloc(source_len, 1);
|
||||
|
||||
memcpy(source, wbuff.ptr, source_len);
|
||||
wbuff.pos = 0;
|
||||
options.compress = true;
|
||||
error = gmio_amf_write(&stream, &doc, &options);
|
||||
static const char zip_entry_filename[] = "test.amf";
|
||||
options.zip_entry_filename = zip_entry_filename;
|
||||
options.zip_entry_filename_len = sizeof(zip_entry_filename) - 1;
|
||||
const int error = gmio_amf_write(&stream, &doc, &options);
|
||||
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||
}
|
||||
#if 0
|
||||
FILE* file = fopen("output.zip", "wb");
|
||||
fwrite(wbuff.ptr, 1, wbuff.pos, file);
|
||||
fclose(file);
|
||||
#endif
|
||||
|
||||
/* Unzip and compare with source data */
|
||||
uint8_t* rbuff = wbuff.ptr;
|
||||
/* -- Read local file header */
|
||||
UTEST_COMPARE_UINT(gmio_decode_uint32_le(rbuff), 0x04034b50);
|
||||
rbuff += 8;
|
||||
/* -- Read compression method */
|
||||
UTEST_COMPARE_UINT(
|
||||
gmio_decode_uint16_le(rbuff),
|
||||
GMIO_ZIP_COMPRESS_METHOD_DEFLATE);
|
||||
rbuff += 18;
|
||||
/* -- Read filename length */
|
||||
UTEST_COMPARE_UINT(
|
||||
gmio_decode_uint16_le(rbuff),
|
||||
options.zip_entry_filename_len);
|
||||
rbuff += 2;
|
||||
/* -- Read extrafield length */
|
||||
const uint16_t zip_extrafield_len = gmio_decode_uint16_le(rbuff);
|
||||
rbuff += 2;
|
||||
/* -- Read filename */
|
||||
UTEST_ASSERT(strncmp(
|
||||
(const char*)rbuff,
|
||||
options.zip_entry_filename,
|
||||
options.zip_entry_filename_len)
|
||||
== 0);
|
||||
rbuff += options.zip_entry_filename_len;
|
||||
/* -- Skip extrafield */
|
||||
rbuff += zip_extrafield_len;
|
||||
|
||||
#if 0 /* TODO: check other ZIP records, and uncompress file */
|
||||
uint8_t* dest = calloc(wbuffsize, 1);
|
||||
unsigned long dest_len = (unsigned long)wbuffsize;
|
||||
const unsigned long z_len = wbuff.pos;
|
||||
const int zerr = uncompress(dest, &dest_len, wbuff.ptr, z_len);
|
||||
printf("\n-- Info: z_len=%i src_len=%i\n", z_len, source_len);
|
||||
UTEST_COMPARE_INT(zerr, Z_OK);
|
||||
UTEST_COMPARE_UINT(source_len, dest_len);
|
||||
UTEST_COMPARE_INT(memcmp(dest, source, source_len), 0);
|
||||
free(dest);
|
||||
#endif
|
||||
|
||||
free(source);
|
||||
}
|
||||
|
||||
free(wbuff.ptr);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user