Merge branch 'develop' of https://github.com/fougue/gmio into develop
This commit is contained in:
commit
579989484c
@ -632,7 +632,8 @@ static size_t gmio_amf_ostringstream_write_zlib(
|
|||||||
int z_retcode = Z_OK;
|
int z_retcode = Z_OK;
|
||||||
|
|
||||||
context->z_uncompressed_size += len;
|
context->z_uncompressed_size += len;
|
||||||
context->z_crc32 = crc32(context->z_crc32, (const Bytef*)ptr, len);
|
context->z_crc32 =
|
||||||
|
gmio_zlib_crc32_update(context->z_crc32, (const uint8_t*)ptr, len);
|
||||||
|
|
||||||
z_stream->next_in = (z_const Bytef*)ptr;
|
z_stream->next_in = (z_const Bytef*)ptr;
|
||||||
z_stream->avail_in = len;
|
z_stream->avail_in = len;
|
||||||
@ -866,7 +867,7 @@ int gmio_amf_write(
|
|||||||
(uint8_t*)memblock->ptr + mblock_halfsize,
|
(uint8_t*)memblock->ptr + mblock_halfsize,
|
||||||
mblock_halfsize,
|
mblock_halfsize,
|
||||||
NULL);
|
NULL);
|
||||||
context.z_crc32 = crc32(0, NULL, 0);
|
context.z_crc32 = gmio_zlib_crc32_initial();
|
||||||
context.error =
|
context.error =
|
||||||
gmio_zlib_compress_init(
|
gmio_zlib_compress_init(
|
||||||
&context.z_stream, &opts->z_compress_options);
|
&context.z_stream, &opts->z_compress_options);
|
||||||
|
@ -75,14 +75,21 @@ static const struct tm* gmio_nonnull_datetime(const struct tm* datetime)
|
|||||||
return datetime;
|
return datetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GMIO_HAVE_INT64_TYPE
|
/* Reads 16b uint from memory (little-endian) and advances buffer pos */
|
||||||
/* Encodes little-endian 64b val in buffer and returns advanced buffer pos */
|
static uint16_t gmio_adv_decode_uint16_le(const uint8_t** bytes)
|
||||||
static uint8_t* gmio_adv_encode_uint64_le(uint64_t val, uint8_t* bytes)
|
|
||||||
{
|
{
|
||||||
gmio_encode_uint64_le(val, bytes);
|
const uint16_t val = gmio_decode_uint16_le(*bytes);
|
||||||
return bytes + 8;
|
*bytes += 2;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads 32b uint from memory (little-endian) and advances buffer pos */
|
||||||
|
static uint32_t gmio_adv_decode_uint32_le(const uint8_t** bytes)
|
||||||
|
{
|
||||||
|
const uint32_t val = gmio_decode_uint32_le(*bytes);
|
||||||
|
*bytes += 4;
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Encodes little-endian 32b val in buffer and returns advanced buffer pos */
|
/* Encodes little-endian 32b val in buffer and returns advanced buffer pos */
|
||||||
static uint8_t* gmio_adv_encode_uint32_le(uint32_t val, uint8_t* bytes)
|
static uint8_t* gmio_adv_encode_uint32_le(uint32_t val, uint8_t* bytes)
|
||||||
@ -98,25 +105,251 @@ static uint8_t* gmio_adv_encode_uint16_le(uint16_t val, uint8_t* bytes)
|
|||||||
return bytes + 2;
|
return bytes + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GMIO_HAVE_INT64_TYPE
|
||||||
|
/* Reads 64b uint from memory (little-endian) and advances buffer pos */
|
||||||
|
static uint64_t gmio_adv_decode_uint64_le(const uint8_t** bytes)
|
||||||
|
{
|
||||||
|
const uint64_t val = gmio_decode_uint64_le(*bytes);
|
||||||
|
*bytes += 8;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encodes little-endian 64b val in buffer and returns advanced buffer pos */
|
||||||
|
static uint8_t* gmio_adv_encode_uint64_le(uint64_t val, uint8_t* bytes)
|
||||||
|
{
|
||||||
|
gmio_encode_uint64_le(val, bytes);
|
||||||
|
return bytes + 8;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Helper to facilitate return from gmio_zip_write_xxx() API functions */
|
/* Helper to facilitate return from gmio_zip_write_xxx() API functions */
|
||||||
static size_t gmio_zip_write_returnhelper(
|
static size_t gmio_zip_write_returnhelper(
|
||||||
struct gmio_stream* stream, size_t written, size_t expected, int* error)
|
struct gmio_stream* stream,
|
||||||
|
size_t written,
|
||||||
|
size_t expected,
|
||||||
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
if (error != NULL) {
|
if (ptr_error != NULL) {
|
||||||
const bool no_error = written == expected && !gmio_stream_error(stream);
|
const bool no_error = written == expected && !gmio_stream_error(stream);
|
||||||
*error = no_error ? GMIO_ERROR_OK : GMIO_ERROR_STREAM;
|
*ptr_error = no_error ? GMIO_ERROR_OK : GMIO_ERROR_STREAM;
|
||||||
}
|
}
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool gmio_zip_read_checkhelper(
|
||||||
|
struct gmio_stream* stream, size_t read, size_t expected)
|
||||||
|
{
|
||||||
|
return read == expected && !gmio_stream_error(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to facilitate return from gmio_zip_read_xxx() and gmio_zip_write_xxx()
|
||||||
|
* API functions */
|
||||||
|
static size_t gmio_zip_io_returnerr(size_t io_len, int error, int* ptr_error)
|
||||||
|
{
|
||||||
|
if (ptr_error != NULL)
|
||||||
|
*ptr_error = error;
|
||||||
|
return io_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* API functions
|
* API functions
|
||||||
* ---------- */
|
* ---------- */
|
||||||
|
|
||||||
|
size_t gmio_zip_read_local_file_header(
|
||||||
|
struct gmio_stream *stream,
|
||||||
|
struct gmio_zip_local_file_header *info,
|
||||||
|
int *ptr_error)
|
||||||
|
{
|
||||||
|
uint8_t buff[GMIO_ZIP_SIZE_LOCAL_FILE_HEADER];
|
||||||
|
uint8_t* buffit = buff;
|
||||||
|
|
||||||
|
const size_t read_len = gmio_stream_read_bytes(stream, buff, sizeof(buff));
|
||||||
|
if (!gmio_zip_read_checkhelper(stream, read_len, sizeof(buff)))
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_STREAM, ptr_error);
|
||||||
|
|
||||||
|
/* 4-bytes magic */
|
||||||
|
if (gmio_adv_decode_uint32_le(&buffit) != 0x04034b50) {
|
||||||
|
return gmio_zip_io_returnerr(
|
||||||
|
read_len, GMIO_ZIP_UTILS_ERROR_BAD_MAGIC, ptr_error);
|
||||||
|
}
|
||||||
|
/* 2-bytes version needed to extract */
|
||||||
|
info->version_needed_to_extract = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes general purpose bit flag */
|
||||||
|
info->general_purpose_flags = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes compression method */
|
||||||
|
info->compress_method = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes last mod file time */
|
||||||
|
/* 2-bytes last mod file date */
|
||||||
|
/* TODO: convert DOS datetime to struct tm */
|
||||||
|
const uint32_t dos_datetime = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
GMIO_UNUSED(dos_datetime);
|
||||||
|
info->lastmod_datetime = NULL;
|
||||||
|
/* 4-bytes crc-32 */
|
||||||
|
info->crc32 = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes compressed size */
|
||||||
|
info->compressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes uncompressed size */
|
||||||
|
info->uncompressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 2-bytes file name length */
|
||||||
|
info->filename_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes extra field length */
|
||||||
|
info->extrafield_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
|
||||||
|
info->filename = NULL;
|
||||||
|
info->extrafield = NULL;
|
||||||
|
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_OK, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gmio_zip_write_data_descriptor(
|
||||||
|
struct gmio_stream *stream,
|
||||||
|
const struct gmio_zip_data_descriptor *info,
|
||||||
|
int* ptr_error)
|
||||||
|
{
|
||||||
|
const size_t fixed_data_len =
|
||||||
|
info->use_zip64 ?
|
||||||
|
GMIO_ZIP64_SIZE_DATA_DESCRIPTOR :
|
||||||
|
GMIO_ZIP_SIZE_DATA_DESCRIPTOR;
|
||||||
|
uint8_t fixed_data[GMIO_ZIP64_SIZE_DATA_DESCRIPTOR];
|
||||||
|
uint8_t* buff = fixed_data;
|
||||||
|
|
||||||
|
/* 4-bytes crc-32 */
|
||||||
|
buff = gmio_adv_encode_uint32_le(info->crc32, buff);
|
||||||
|
/* Compressed size and uncompressed size (4 or 8 bytes) */
|
||||||
|
if (info->use_zip64) {
|
||||||
|
#ifdef GMIO_HAVE_INT64_TYPE
|
||||||
|
buff = gmio_adv_encode_uint64_le(info->compressed_size, buff);
|
||||||
|
buff = gmio_adv_encode_uint64_le(info->uncompressed_size, buff);
|
||||||
|
#else
|
||||||
|
/* TODO: error code */
|
||||||
|
return gmio_zip_io_returnerr(0, GMIO_ERROR_UNKNOWN, ptr_error);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (info->compressed_size <= UINT32_MAX
|
||||||
|
&& info->uncompressed_size <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
buff = gmio_adv_encode_uint32_le((uint32_t)info->compressed_size, buff);
|
||||||
|
buff = gmio_adv_encode_uint32_le((uint32_t)info->uncompressed_size, buff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* TODO: error code */
|
||||||
|
return gmio_zip_io_returnerr(0, GMIO_ERROR_UNKNOWN, ptr_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to stream */
|
||||||
|
const size_t written_len =
|
||||||
|
gmio_stream_write_bytes(stream, fixed_data, fixed_data_len);
|
||||||
|
return gmio_zip_write_returnhelper(
|
||||||
|
stream, written_len, fixed_data_len, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gmio_zip_read_central_directory_header(
|
||||||
|
struct gmio_stream *stream,
|
||||||
|
struct gmio_zip_central_directory_header *info,
|
||||||
|
int *ptr_error)
|
||||||
|
{
|
||||||
|
uint8_t buff[GMIO_ZIP_SIZE_CENTRAL_DIRECTORY_HEADER];
|
||||||
|
uint8_t* buffit = buff;
|
||||||
|
|
||||||
|
const size_t read_len = gmio_stream_read_bytes(stream, buff, sizeof(buff));
|
||||||
|
if (!gmio_zip_read_checkhelper(stream, read_len, sizeof(buff)))
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_STREAM, ptr_error);
|
||||||
|
|
||||||
|
/* 4-bytes magic */
|
||||||
|
if (gmio_adv_decode_uint32_le(&buffit) != 0x02014b50) {
|
||||||
|
return gmio_zip_io_returnerr(
|
||||||
|
read_len, GMIO_ZIP_UTILS_ERROR_BAD_MAGIC, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2-bytes version made by */
|
||||||
|
info->version_made_by = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes version needed to extract */
|
||||||
|
info->version_needed_to_extract = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes general purpose bit flag */
|
||||||
|
info->general_purpose_flags = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes compression method */
|
||||||
|
info->compress_method = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes last mod file time */
|
||||||
|
/* 2-bytes last mod file date */
|
||||||
|
/* TODO: convert DOS datetime to struct tm */
|
||||||
|
const uint32_t dos_datetime = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
GMIO_UNUSED(dos_datetime);
|
||||||
|
info->lastmod_datetime = NULL;
|
||||||
|
/* 4-bytes crc-32 */
|
||||||
|
info->crc32 = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes compressed size */
|
||||||
|
info->compressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes uncompressed size */
|
||||||
|
info->uncompressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 2-bytes file name length */
|
||||||
|
info->filename_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes extra field length */
|
||||||
|
info->extrafield_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes file comment length */
|
||||||
|
info->filecomment_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes disk number start */
|
||||||
|
info->disk_nb_start = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes internal file attributes */
|
||||||
|
info->internal_file_attrs = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 4-bytes external file attributes */
|
||||||
|
info->external_file_attrs = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes relative offset of local header */
|
||||||
|
info->relative_offset_local_header = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
|
||||||
|
info->filename = NULL;
|
||||||
|
info->extrafield = NULL;
|
||||||
|
info->filecomment = NULL;
|
||||||
|
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_OK, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gmio_zip_read_end_of_central_directory_record(
|
||||||
|
struct gmio_stream *stream,
|
||||||
|
struct gmio_zip_end_of_central_directory_record *info,
|
||||||
|
int *ptr_error)
|
||||||
|
{
|
||||||
|
uint8_t buff[GMIO_ZIP_SIZE_END_OF_CENTRAL_DIRECTORY_RECORD];
|
||||||
|
uint8_t* buffit = buff;
|
||||||
|
|
||||||
|
const size_t read_len = gmio_stream_read_bytes(stream, buff, sizeof(buff));
|
||||||
|
if (!gmio_zip_read_checkhelper(stream, read_len, sizeof(buff)))
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_STREAM, ptr_error);
|
||||||
|
|
||||||
|
/* 4-bytes magic */
|
||||||
|
if (gmio_adv_decode_uint32_le(&buffit) != 0x06054b50) {
|
||||||
|
return gmio_zip_io_returnerr(
|
||||||
|
read_len, GMIO_ZIP_UTILS_ERROR_BAD_MAGIC, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2-bytes number of this disk */
|
||||||
|
info->disk_nb = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes number of the disk with the start of the central directory */
|
||||||
|
info->disk_nb_with_start_of_central_dir = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes total number of entries in the central directory on this disk */
|
||||||
|
info->total_entry_count_in_central_dir_on_disk =
|
||||||
|
gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 2-bytes total number of entries in the central directory */
|
||||||
|
info->total_entry_count_in_central_dir = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
/* 4-bytes size of the central directory */
|
||||||
|
info->central_dir_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 4-bytes offset of start of central directory with respect to the starting
|
||||||
|
* disk number */
|
||||||
|
info->start_offset_central_dir_from_disk_start_nb =
|
||||||
|
gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 2-bytes .ZIP file comment length */
|
||||||
|
info->filecomment_len = gmio_adv_decode_uint16_le(&buffit);
|
||||||
|
|
||||||
|
info->filecomment = NULL;
|
||||||
|
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_OK, ptr_error);
|
||||||
|
}
|
||||||
|
|
||||||
size_t gmio_zip_write_local_file_header(
|
size_t gmio_zip_write_local_file_header(
|
||||||
struct gmio_stream* stream,
|
struct gmio_stream* stream,
|
||||||
const struct gmio_zip_local_file_header* info,
|
const struct gmio_zip_local_file_header* info,
|
||||||
int* error)
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
uint8_t fixed_data[GMIO_ZIP_SIZE_LOCAL_FILE_HEADER];
|
uint8_t fixed_data[GMIO_ZIP_SIZE_LOCAL_FILE_HEADER];
|
||||||
uint8_t* buff = fixed_data;
|
uint8_t* buff = fixed_data;
|
||||||
@ -162,55 +395,62 @@ size_t gmio_zip_write_local_file_header(
|
|||||||
written_len +=
|
written_len +=
|
||||||
gmio_stream_write_bytes(stream, info->extrafield, info->extrafield_len);
|
gmio_stream_write_bytes(stream, info->extrafield, info->extrafield_len);
|
||||||
return gmio_zip_write_returnhelper(
|
return gmio_zip_write_returnhelper(
|
||||||
stream, written_len, expected_written_len, error);
|
stream, written_len, expected_written_len, ptr_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gmio_zip_write_data_descriptor(
|
size_t gmio_zip_read_data_descriptor(
|
||||||
struct gmio_stream *stream,
|
struct gmio_stream *stream,
|
||||||
const struct gmio_zip_data_descriptor *info,
|
struct gmio_zip_data_descriptor *info,
|
||||||
int* error)
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
const size_t fixed_data_len =
|
uint8_t buff[GMIO_ZIP_SIZE_DATA_DESCRIPTOR];
|
||||||
info->use_zip64 ?
|
uint8_t* buffit = buff;
|
||||||
GMIO_ZIP64_SIZE_DATA_DESCRIPTOR :
|
|
||||||
GMIO_ZIP_SIZE_DATA_DESCRIPTOR;
|
const size_t read_len = gmio_stream_read_bytes(stream, buff, sizeof(buff));
|
||||||
uint8_t fixed_data[GMIO_ZIP64_SIZE_DATA_DESCRIPTOR];
|
if (!gmio_zip_read_checkhelper(stream, read_len, sizeof(buff)))
|
||||||
uint8_t* buff = fixed_data;
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_STREAM, ptr_error);
|
||||||
|
|
||||||
/* 4-bytes crc-32 */
|
/* 4-bytes crc-32 */
|
||||||
buff = gmio_adv_encode_uint32_le(info->crc32, buff);
|
info->crc32 = gmio_adv_decode_uint32_le(&buffit);
|
||||||
/* Compressed size and uncompressed size (4 or 8 bytes) */
|
/* 4-bytes compressed size */
|
||||||
if (info->use_zip64) {
|
info->compressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
#ifdef GMIO_HAVE_INT64_TYPE
|
/* 4-bytes uncompressed size */
|
||||||
buff = gmio_adv_encode_uint64_le(info->compressed_size, buff);
|
info->uncompressed_size = gmio_adv_decode_uint32_le(&buffit);
|
||||||
buff = gmio_adv_encode_uint64_le(info->uncompressed_size, buff);
|
|
||||||
#else
|
|
||||||
return GMIO_ERROR_UNKNOWN; /* TODO: error code */
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (info->compressed_size <= UINT32_MAX
|
|
||||||
&& info->uncompressed_size <= UINT32_MAX)
|
|
||||||
{
|
|
||||||
buff = gmio_adv_encode_uint32_le((uint32_t)info->compressed_size, buff);
|
|
||||||
buff = gmio_adv_encode_uint32_le((uint32_t)info->uncompressed_size, buff);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return GMIO_ERROR_UNKNOWN; /* TODO: error code */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write to stream */
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_OK, ptr_error);
|
||||||
const size_t written_len =
|
}
|
||||||
gmio_stream_write_bytes(stream, fixed_data, fixed_data_len);
|
|
||||||
return gmio_zip_write_returnhelper(
|
size_t gmio_zip64_read_data_descriptor(
|
||||||
stream, written_len, fixed_data_len, error);
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_data_descriptor* info,
|
||||||
|
int* ptr_error)
|
||||||
|
{
|
||||||
|
#ifdef GMIO_HAVE_INT64_TYPE
|
||||||
|
uint8_t buff[GMIO_ZIP64_SIZE_DATA_DESCRIPTOR];
|
||||||
|
uint8_t* buffit = buff;
|
||||||
|
|
||||||
|
const size_t read_len = gmio_stream_read_bytes(stream, buff, sizeof(buff));
|
||||||
|
if (!gmio_zip_read_checkhelper(stream, read_len, sizeof(buff)))
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_STREAM, ptr_error);
|
||||||
|
|
||||||
|
/* 4-bytes crc-32 */
|
||||||
|
info->crc32 = gmio_adv_decode_uint32_le(&buffit);
|
||||||
|
/* 8-bytes compressed size */
|
||||||
|
info->compressed_size = gmio_adv_decode_uint64_le(&buffit);
|
||||||
|
/* 8-bytes uncompressed size */
|
||||||
|
info->uncompressed_size = gmio_adv_decode_uint64_le(&buffit);
|
||||||
|
|
||||||
|
return gmio_zip_io_returnerr(read_len, GMIO_ERROR_OK, ptr_error);
|
||||||
|
#else
|
||||||
|
/* TODO: error code */
|
||||||
|
return gmio_zip_io_returnerr(0, GMIO_ERROR_UNKNOWN, ptr_error);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gmio_zip_write_central_directory_header(
|
size_t gmio_zip_write_central_directory_header(
|
||||||
struct gmio_stream *stream,
|
struct gmio_stream *stream,
|
||||||
const struct gmio_zip_central_directory_header *info,
|
const struct gmio_zip_central_directory_header *info,
|
||||||
int* error)
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
uint8_t fixed_data[GMIO_ZIP_SIZE_CENTRAL_DIRECTORY_HEADER];
|
uint8_t fixed_data[GMIO_ZIP_SIZE_CENTRAL_DIRECTORY_HEADER];
|
||||||
uint8_t* buff = fixed_data;
|
uint8_t* buff = fixed_data;
|
||||||
@ -270,18 +510,18 @@ size_t gmio_zip_write_central_directory_header(
|
|||||||
written_len +=
|
written_len +=
|
||||||
gmio_stream_write_bytes(stream, info->filecomment, info->filecomment_len);
|
gmio_stream_write_bytes(stream, info->filecomment, info->filecomment_len);
|
||||||
return gmio_zip_write_returnhelper(
|
return gmio_zip_write_returnhelper(
|
||||||
stream, written_len, expected_written_len, error);
|
stream, written_len, expected_written_len, ptr_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gmio_zip64_write_extrafield_extended_info(
|
size_t gmio_zip64_write_extrafield_extended_info(
|
||||||
uint8_t *buff,
|
uint8_t *buff,
|
||||||
size_t buff_capacity,
|
size_t buff_capacity,
|
||||||
const struct gmio_zip64_extrablock_extended_info *info,
|
const struct gmio_zip64_extrablock_extended_info *info,
|
||||||
int* error)
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
if (buff_capacity < GMIO_ZIP64_SIZE_EXTRAFIELD_EXTENDED_INFO) {
|
if (buff_capacity < GMIO_ZIP64_SIZE_EXTRAFIELD_EXTENDED_INFO) {
|
||||||
*error = GMIO_ERROR_INVALID_MEMBLOCK_SIZE;
|
return gmio_zip_io_returnerr(
|
||||||
return 0;
|
0, GMIO_ERROR_INVALID_MEMBLOCK_SIZE, ptr_error);
|
||||||
}
|
}
|
||||||
#ifdef GMIO_HAVE_INT64_TYPE
|
#ifdef GMIO_HAVE_INT64_TYPE
|
||||||
/* Tag */
|
/* Tag */
|
||||||
@ -297,18 +537,20 @@ size_t gmio_zip64_write_extrafield_extended_info(
|
|||||||
buff = gmio_adv_encode_uint64_le(info->relative_offset_local_header, buff);
|
buff = gmio_adv_encode_uint64_le(info->relative_offset_local_header, buff);
|
||||||
/* Number of the disk on which this file starts */
|
/* Number of the disk on which this file starts */
|
||||||
buff = gmio_adv_encode_uint32_le(info->disk_nb_start, buff);
|
buff = gmio_adv_encode_uint32_le(info->disk_nb_start, buff);
|
||||||
*error = GMIO_ERROR_OK;
|
return gmio_zip_io_returnerr(
|
||||||
return GMIO_ZIP64_SIZE_EXTRAFIELD_EXTENDED_INFO;
|
GMIO_ZIP64_SIZE_EXTRAFIELD_EXTENDED_INFO,
|
||||||
|
GMIO_ERROR_OK,
|
||||||
|
ptr_error);
|
||||||
#else
|
#else
|
||||||
*error = GMIO_ERROR_UNKNOWN; /* TODO: error code */
|
/* TODO: error code */
|
||||||
return 0;
|
return gmio_zip_io_returnerr(0, GMIO_ERROR_UNKNOWN, error);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t gmio_zip_write_end_of_central_directory_record(
|
size_t gmio_zip_write_end_of_central_directory_record(
|
||||||
struct gmio_stream *stream,
|
struct gmio_stream *stream,
|
||||||
const struct gmio_zip_end_of_central_directory_record *info,
|
const struct gmio_zip_end_of_central_directory_record *info,
|
||||||
int* error)
|
int* ptr_error)
|
||||||
{
|
{
|
||||||
uint8_t fixed_data[GMIO_ZIP_SIZE_END_OF_CENTRAL_DIRECTORY_RECORD];
|
uint8_t fixed_data[GMIO_ZIP_SIZE_END_OF_CENTRAL_DIRECTORY_RECORD];
|
||||||
uint8_t* buff = fixed_data;
|
uint8_t* buff = fixed_data;
|
||||||
@ -322,17 +564,24 @@ size_t gmio_zip_write_end_of_central_directory_record(
|
|||||||
|
|
||||||
/* 2-bytes number of the disk with the start of the central directory */
|
/* 2-bytes number of the disk with the start of the central directory */
|
||||||
const uint16_t disk_nb_with_start_of_central_dir =
|
const uint16_t disk_nb_with_start_of_central_dir =
|
||||||
info->use_zip64 ? UINT16_MAX : info->disk_nb_with_start_of_central_dir;
|
info->use_zip64 ?
|
||||||
|
UINT16_MAX :
|
||||||
|
info->disk_nb_with_start_of_central_dir;
|
||||||
buff = gmio_adv_encode_uint16_le(disk_nb_with_start_of_central_dir, buff);
|
buff = gmio_adv_encode_uint16_le(disk_nb_with_start_of_central_dir, buff);
|
||||||
|
|
||||||
/* 2-bytes total number of entries in the central directory on this disk */
|
/* 2-bytes total number of entries in the central directory on this disk */
|
||||||
const uint16_t total_entry_count_in_central_dir_on_disk =
|
const uint16_t total_entry_count_in_central_dir_on_disk =
|
||||||
info->use_zip64 ? UINT16_MAX : info->total_entry_count_in_central_dir_on_disk;
|
info->use_zip64 ?
|
||||||
buff = gmio_adv_encode_uint16_le(total_entry_count_in_central_dir_on_disk, buff);
|
UINT16_MAX :
|
||||||
|
info->total_entry_count_in_central_dir_on_disk;
|
||||||
|
buff = gmio_adv_encode_uint16_le(
|
||||||
|
total_entry_count_in_central_dir_on_disk, buff);
|
||||||
|
|
||||||
/* 2-bytes total number of entries in the central directory */
|
/* 2-bytes total number of entries in the central directory */
|
||||||
const uint16_t total_entry_count_in_central_dir =
|
const uint16_t total_entry_count_in_central_dir =
|
||||||
info->use_zip64 ? UINT16_MAX : info->total_entry_count_in_central_dir;
|
info->use_zip64 ?
|
||||||
|
UINT16_MAX :
|
||||||
|
info->total_entry_count_in_central_dir;
|
||||||
buff = gmio_adv_encode_uint16_le(total_entry_count_in_central_dir, buff);
|
buff = gmio_adv_encode_uint16_le(total_entry_count_in_central_dir, buff);
|
||||||
|
|
||||||
/* 4-bytes size of the central directory */
|
/* 4-bytes size of the central directory */
|
||||||
@ -343,8 +592,11 @@ size_t gmio_zip_write_end_of_central_directory_record(
|
|||||||
/* 4-bytes offset of start of central directory with respect to the starting
|
/* 4-bytes offset of start of central directory with respect to the starting
|
||||||
* disk number */
|
* disk number */
|
||||||
const uint32_t start_offset_central_dir_from_disk_start_nb =
|
const uint32_t start_offset_central_dir_from_disk_start_nb =
|
||||||
info->use_zip64 ? UINT32_MAX : info->start_offset_central_dir_from_disk_start_nb;
|
info->use_zip64 ?
|
||||||
buff = gmio_adv_encode_uint32_le(start_offset_central_dir_from_disk_start_nb, buff);
|
UINT32_MAX :
|
||||||
|
info->start_offset_central_dir_from_disk_start_nb;
|
||||||
|
buff = gmio_adv_encode_uint32_le(
|
||||||
|
start_offset_central_dir_from_disk_start_nb, buff);
|
||||||
|
|
||||||
/* 2-bytes .ZIP file comment length */
|
/* 2-bytes .ZIP file comment length */
|
||||||
buff = gmio_adv_encode_uint16_le(info->filecomment_len, buff);
|
buff = gmio_adv_encode_uint16_le(info->filecomment_len, buff);
|
||||||
@ -358,5 +610,5 @@ size_t gmio_zip_write_end_of_central_directory_record(
|
|||||||
written_len +=
|
written_len +=
|
||||||
gmio_stream_write_bytes(stream, info->filecomment, info->filecomment_len);
|
gmio_stream_write_bytes(stream, info->filecomment, info->filecomment_len);
|
||||||
return gmio_zip_write_returnhelper(
|
return gmio_zip_write_returnhelper(
|
||||||
stream, written_len, expected_written_len, error);
|
stream, written_len, expected_written_len, ptr_error);
|
||||||
}
|
}
|
||||||
|
@ -165,10 +165,10 @@ struct gmio_zip_local_file_header {
|
|||||||
uint32_t crc32;
|
uint32_t crc32;
|
||||||
uint32_t compressed_size;
|
uint32_t compressed_size;
|
||||||
uint32_t uncompressed_size;
|
uint32_t uncompressed_size;
|
||||||
const char* filename;
|
|
||||||
const uint8_t* extrafield;
|
|
||||||
uint16_t filename_len;
|
uint16_t filename_len;
|
||||||
uint16_t extrafield_len;
|
uint16_t extrafield_len;
|
||||||
|
const char* filename;
|
||||||
|
const uint8_t* extrafield;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Zip data descriptor */
|
/*! Zip data descriptor */
|
||||||
@ -246,23 +246,58 @@ struct gmio_zip_write_result {
|
|||||||
size_t written_len;
|
size_t written_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { GMIO_ZIP_UTILS_ERROR_TAG = 0xAA000000 };
|
||||||
|
enum gmio_zip_utils_error {
|
||||||
|
GMIO_ZIP_UTILS_ERROR_BAD_MAGIC = GMIO_ZIP_UTILS_ERROR_TAG + 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! Reads ZIP local file header from \p stream */
|
||||||
|
size_t gmio_zip_read_local_file_header(
|
||||||
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_local_file_header* info,
|
||||||
|
int* ptr_error);
|
||||||
|
|
||||||
|
/*! Reads ZIP data descriptor from \p stream */
|
||||||
|
size_t gmio_zip_read_data_descriptor(
|
||||||
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_data_descriptor* info,
|
||||||
|
int* ptr_error);
|
||||||
|
|
||||||
|
/*! Reads Zip64 data descriptor from \p stream */
|
||||||
|
size_t gmio_zip64_read_data_descriptor(
|
||||||
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_data_descriptor* info,
|
||||||
|
int* ptr_error);
|
||||||
|
|
||||||
|
/*! Reads ZIP central directory header from \p stream */
|
||||||
|
size_t gmio_zip_read_central_directory_header(
|
||||||
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_central_directory_header* info,
|
||||||
|
int* ptr_error);
|
||||||
|
|
||||||
|
/*! Reads ZIP end of central directory record from \p stream */
|
||||||
|
size_t gmio_zip_read_end_of_central_directory_record(
|
||||||
|
struct gmio_stream* stream,
|
||||||
|
struct gmio_zip_end_of_central_directory_record* info,
|
||||||
|
int* ptr_error);
|
||||||
|
|
||||||
/*! Writes ZIP local file header to \p stream */
|
/*! Writes ZIP local file header to \p stream */
|
||||||
size_t gmio_zip_write_local_file_header(
|
size_t gmio_zip_write_local_file_header(
|
||||||
struct gmio_stream* stream,
|
struct gmio_stream* stream,
|
||||||
const struct gmio_zip_local_file_header* info,
|
const struct gmio_zip_local_file_header* info,
|
||||||
int* error);
|
int* ptr_error);
|
||||||
|
|
||||||
/*! Writes ZIP data descriptor to \p stream */
|
/*! Writes ZIP data descriptor to \p stream */
|
||||||
size_t gmio_zip_write_data_descriptor(
|
size_t gmio_zip_write_data_descriptor(
|
||||||
struct gmio_stream* stream,
|
struct gmio_stream* stream,
|
||||||
const struct gmio_zip_data_descriptor* info,
|
const struct gmio_zip_data_descriptor* info,
|
||||||
int* error);
|
int* ptr_error);
|
||||||
|
|
||||||
/*! Writes ZIP central directory header to \p stream */
|
/*! Writes ZIP central directory header to \p stream */
|
||||||
size_t gmio_zip_write_central_directory_header(
|
size_t gmio_zip_write_central_directory_header(
|
||||||
struct gmio_stream* stream,
|
struct gmio_stream* stream,
|
||||||
const struct gmio_zip_central_directory_header* info,
|
const struct gmio_zip_central_directory_header* info,
|
||||||
int* error);
|
int* ptr_error);
|
||||||
|
|
||||||
/*! Writes ZIP local file header to \p buff
|
/*! Writes ZIP local file header to \p buff
|
||||||
*
|
*
|
||||||
@ -273,12 +308,12 @@ size_t gmio_zip64_write_extrafield_extended_info(
|
|||||||
uint8_t* buff,
|
uint8_t* buff,
|
||||||
size_t buff_capacity,
|
size_t buff_capacity,
|
||||||
const struct gmio_zip64_extrablock_extended_info* info,
|
const struct gmio_zip64_extrablock_extended_info* info,
|
||||||
int* error);
|
int* ptr_error);
|
||||||
|
|
||||||
/*! Writes ZIP end of central directory record \p stream */
|
/*! Writes ZIP end of central directory record to \p stream */
|
||||||
size_t gmio_zip_write_end_of_central_directory_record(
|
size_t gmio_zip_write_end_of_central_directory_record(
|
||||||
struct gmio_stream* stream,
|
struct gmio_stream* stream,
|
||||||
const struct gmio_zip_end_of_central_directory_record* info,
|
const struct gmio_zip_end_of_central_directory_record* info,
|
||||||
int* error);
|
int* ptr_error);
|
||||||
|
|
||||||
#endif /* GMIO_INTERNAL_ZIP_UTILS_H */
|
#endif /* GMIO_INTERNAL_ZIP_UTILS_H */
|
||||||
|
@ -30,6 +30,18 @@
|
|||||||
#include "zlib_utils.h"
|
#include "zlib_utils.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
|
||||||
|
/* 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_for_no_zlib_wrapper = -15;
|
||||||
|
|
||||||
static int gmio_to_zlib_compress_level(int gmio_compress_level)
|
static int gmio_to_zlib_compress_level(int gmio_compress_level)
|
||||||
{
|
{
|
||||||
if (gmio_compress_level == GMIO_ZLIB_COMPRESS_LEVEL_DEFAULT)
|
if (gmio_compress_level == GMIO_ZLIB_COMPRESS_LEVEL_DEFAULT)
|
||||||
@ -69,23 +81,12 @@ int gmio_zlib_compress_init(
|
|||||||
gmio_to_zlib_compress_level(z_opts->level);
|
gmio_to_zlib_compress_level(z_opts->level);
|
||||||
const int zlib_compress_memusage =
|
const int zlib_compress_memusage =
|
||||||
gmio_to_zlib_compress_memusage(z_opts->memory_usage);
|
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 =
|
const int z_init_error =
|
||||||
deflateInit2_(
|
deflateInit2_(
|
||||||
z_stream,
|
z_stream,
|
||||||
zlib_compress_level,
|
zlib_compress_level,
|
||||||
Z_DEFLATED, /* Method */
|
Z_DEFLATED, /* Method */
|
||||||
z_window_bits,
|
z_window_bits_for_no_zlib_wrapper,
|
||||||
zlib_compress_memusage,
|
zlib_compress_memusage,
|
||||||
z_opts->strategy,
|
z_opts->strategy,
|
||||||
ZLIB_VERSION,
|
ZLIB_VERSION,
|
||||||
@ -104,3 +105,60 @@ bool gmio_check_zlib_compress_options(
|
|||||||
}
|
}
|
||||||
return gmio_no_error(*error);
|
return gmio_no_error(*error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gmio_zlib_uncompress_buffer(
|
||||||
|
uint8_t* dest, size_t* dest_len, const uint8_t* src, size_t src_len)
|
||||||
|
{
|
||||||
|
z_stream stream;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
stream.next_in = (z_const Bytef *)src;
|
||||||
|
stream.avail_in = (uInt)src_len;
|
||||||
|
/* Check for source > 64K on 16-bit machine: */
|
||||||
|
if ((uLong)stream.avail_in != src_len)
|
||||||
|
return GMIO_ERROR_ZLIB_BUF;
|
||||||
|
|
||||||
|
stream.next_out = dest;
|
||||||
|
stream.avail_out = (uInt)*dest_len;
|
||||||
|
if ((uLong)stream.avail_out != *dest_len)
|
||||||
|
return GMIO_ERROR_ZLIB_BUF;
|
||||||
|
|
||||||
|
stream.zalloc = (alloc_func)NULL;
|
||||||
|
stream.zfree = (free_func)NULL;
|
||||||
|
|
||||||
|
err = inflateInit2_(
|
||||||
|
&stream,
|
||||||
|
z_window_bits_for_no_zlib_wrapper,
|
||||||
|
ZLIB_VERSION,
|
||||||
|
sizeof(z_stream));
|
||||||
|
if (err != Z_OK)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = inflate(&stream, Z_FINISH);
|
||||||
|
if (err != Z_STREAM_END) {
|
||||||
|
inflateEnd(&stream);
|
||||||
|
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
|
||||||
|
return GMIO_ERROR_ZLIB_DATA;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
*dest_len = stream.total_out;
|
||||||
|
|
||||||
|
err = inflateEnd(&stream);
|
||||||
|
return zlib_error_to_gmio_error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t gmio_zlib_crc32(const uint8_t *buff, size_t buff_len)
|
||||||
|
{
|
||||||
|
return gmio_zlib_crc32_update(gmio_zlib_crc32_initial(), buff, buff_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t gmio_zlib_crc32_update(
|
||||||
|
uint32_t crc, const uint8_t *buff, size_t buff_len)
|
||||||
|
{
|
||||||
|
return crc32(crc, (const Bytef*)buff, (uInt)buff_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t gmio_zlib_crc32_initial()
|
||||||
|
{
|
||||||
|
return crc32(0, NULL, 0);
|
||||||
|
}
|
||||||
|
@ -46,4 +46,24 @@ int gmio_zlib_compress_init(
|
|||||||
bool gmio_check_zlib_compress_options(
|
bool gmio_check_zlib_compress_options(
|
||||||
int* error, const struct gmio_zlib_compress_options* z_opts);
|
int* error, const struct gmio_zlib_compress_options* z_opts);
|
||||||
|
|
||||||
|
/* Decompresses the source buffer into the destination buffer.
|
||||||
|
*
|
||||||
|
* \p sourceLen is the byte length of the source buffer. Upon entry, \p destLen
|
||||||
|
* is the total size of the destination buffer, which must be large enough to
|
||||||
|
* hold the entire uncompressed data.
|
||||||
|
* Upon exit, destLen is the actual size of the compressed buffer.
|
||||||
|
*/
|
||||||
|
int gmio_zlib_uncompress_buffer(
|
||||||
|
uint8_t* dest, size_t* dest_len, const uint8_t* src, size_t src_len);
|
||||||
|
|
||||||
|
/* Computes the CRC-32 value with the bytes buff[0..buff_len-1] */
|
||||||
|
uint32_t gmio_zlib_crc32(const uint8_t* buff, size_t buff_len);
|
||||||
|
|
||||||
|
/* Returns the required initial value for the gmio_zlib_crc32_update() */
|
||||||
|
uint32_t gmio_zlib_crc32_initial();
|
||||||
|
|
||||||
|
/* Updates a running CRC-32 with the bytes buff[0..buff_len-1] */
|
||||||
|
uint32_t gmio_zlib_crc32_update(
|
||||||
|
uint32_t crc, const uint8_t* buff, size_t buff_len);
|
||||||
|
|
||||||
#endif /* GMIO_INTERNAL_ZLIB_UTILS_H */
|
#endif /* GMIO_INTERNAL_ZLIB_UTILS_H */
|
||||||
|
@ -48,7 +48,8 @@ const char* all_tests()
|
|||||||
|
|
||||||
gmio_memblock_set_default_constructor(gmio_memblock_for_tests);
|
gmio_memblock_set_default_constructor(gmio_memblock_for_tests);
|
||||||
|
|
||||||
UTEST_RUN(test_amf_write);
|
UTEST_RUN(test_amf_write_doc_null);
|
||||||
|
UTEST_RUN(test_amf_write_doc_1);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "../src/gmio_core/internal/byte_codec.h"
|
#include "../src/gmio_core/internal/byte_codec.h"
|
||||||
#include "../src/gmio_core/internal/helper_stream.h"
|
#include "../src/gmio_core/internal/helper_stream.h"
|
||||||
#include "../src/gmio_core/internal/zip_utils.h"
|
#include "../src/gmio_core/internal/zip_utils.h"
|
||||||
|
#include "../src/gmio_core/internal/zlib_utils.h"
|
||||||
#include "../src/gmio_amf/amf_error.h"
|
#include "../src/gmio_amf/amf_error.h"
|
||||||
#include "../src/gmio_amf/amf_io.h"
|
#include "../src/gmio_amf/amf_io.h"
|
||||||
|
|
||||||
@ -178,97 +179,105 @@ static void __tamf__skip_zip_local_file_header()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* test_amf_write()
|
static const char* test_amf_write_doc_null()
|
||||||
{
|
{
|
||||||
|
struct gmio_stream stream = {0};
|
||||||
|
struct gmio_amf_document doc = {0};
|
||||||
|
const int error = gmio_amf_write(&stream, &doc, NULL);
|
||||||
|
UTEST_ASSERT(gmio_error(error));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* test_amf_write_doc_1()
|
||||||
|
{
|
||||||
|
static const size_t wbuffsize = 8192;
|
||||||
|
struct gmio_rw_buffer wbuff = {0};
|
||||||
|
struct gmio_amf_document doc = {0};
|
||||||
|
|
||||||
|
const struct __tamf__material testmaterials[] = {
|
||||||
|
{ { 1., 0., 0. }, "red" },
|
||||||
|
{ { 0., 1., 0. }, "green" },
|
||||||
|
{ { 0., 0., 1. }, "blue" },
|
||||||
|
{ { 1., 1., 1. }, "white" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct gmio_vec3d testvertices[] = {
|
||||||
|
{ 0., 0., 0.},
|
||||||
|
{ 1., 0., 0.},
|
||||||
|
{ 1., -1., 0.},
|
||||||
|
{ 0., -1., 0.},
|
||||||
|
{ 1., 0., 1.},
|
||||||
|
{ 1., -1., 1.},
|
||||||
|
{ 0., 0., 1.},
|
||||||
|
{ 0., -1., 1.}
|
||||||
|
};
|
||||||
|
const struct __tamf__triangle testtriangles[] = {
|
||||||
|
{ 0, 1, 2},
|
||||||
|
{ 0, 2, 3},
|
||||||
|
{ 1, 5, 2},
|
||||||
|
{ 1, 4, 5},
|
||||||
|
{ 6, 5, 7},
|
||||||
|
{ 6, 4, 5},
|
||||||
|
{ 0, 6, 7},
|
||||||
|
{ 0, 7, 3},
|
||||||
|
{ 0, 6, 4},
|
||||||
|
{ 0, 4, 1},
|
||||||
|
{ 3, 7, 5},
|
||||||
|
{ 3, 5, 2}
|
||||||
|
};
|
||||||
|
struct __tamf__document testdoc = {0};
|
||||||
|
|
||||||
|
wbuff.ptr = calloc(wbuffsize, 1);
|
||||||
|
wbuff.len = wbuffsize;
|
||||||
|
|
||||||
|
testdoc.vec_material = testmaterials;
|
||||||
|
testdoc.mesh.vec_vertex = testvertices;
|
||||||
|
testdoc.mesh.vertex_count = GMIO_ARRAY_SIZE(testvertices);
|
||||||
|
testdoc.mesh.vec_triangle = testtriangles;
|
||||||
|
testdoc.mesh.triangle_count = GMIO_ARRAY_SIZE(testtriangles);
|
||||||
|
|
||||||
|
doc.cookie = &testdoc;
|
||||||
|
doc.unit = GMIO_AMF_UNIT_MILLIMETER;
|
||||||
|
doc.func_get_document_element = &__tamf__get_document_element;
|
||||||
|
doc.func_get_object_mesh = &__tamf__get_object_mesh;
|
||||||
|
doc.func_get_object_mesh_element = &__tamf__get_object_mesh_element;
|
||||||
|
doc.func_get_object_mesh_volume_triangle =
|
||||||
|
&__tamf__get_object_mesh_volume_triangle;
|
||||||
|
doc.func_get_document_element_metadata =
|
||||||
|
&__tamf__get_document_element_metadata;
|
||||||
|
doc.object_count = 1;
|
||||||
|
doc.material_count = GMIO_ARRAY_SIZE(testmaterials);
|
||||||
|
|
||||||
|
/* Write as raw contents(uncompressed) */
|
||||||
{
|
{
|
||||||
struct gmio_stream stream = {0};
|
struct gmio_stream stream = gmio_stream_buffer(&wbuff);
|
||||||
struct gmio_amf_document doc = {0};
|
struct gmio_amf_write_options options = {0};
|
||||||
const int error = gmio_amf_write(&stream, &doc, NULL);
|
options.float64_prec = 9;
|
||||||
UTEST_ASSERT(gmio_error(error));
|
const int error = gmio_amf_write(&stream, &doc, &options);
|
||||||
|
if (gmio_error(error))
|
||||||
|
printf("\n0x%x\n", error);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
/* printf("%s\n", wbuff.ptr); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write compressed ZIP */
|
||||||
{
|
{
|
||||||
static const size_t wbuffsize = 8192;
|
const size_t source_len = wbuff.pos;
|
||||||
struct gmio_rw_buffer wbuff = {0};
|
const uint32_t crc32_amf_data = gmio_zlib_crc32(wbuff.ptr, source_len);
|
||||||
struct gmio_stream stream = gmio_stream_buffer(&wbuff);
|
uint8_t* source = calloc(source_len, 1);
|
||||||
struct gmio_amf_document doc = {0};
|
memcpy(source, wbuff.ptr, source_len);
|
||||||
struct gmio_amf_write_options options = {0};
|
|
||||||
|
|
||||||
const struct __tamf__material testmaterials[] = {
|
static const char zip_entry_filename[] = "test.amf";
|
||||||
{ { 1., 0., 0. }, "red" },
|
static const uint16_t zip_entry_filename_len =
|
||||||
{ { 0., 1., 0. }, "green" },
|
sizeof(zip_entry_filename) - 1;
|
||||||
{ { 0., 0., 1. }, "blue" },
|
|
||||||
{ { 1., 1., 1. }, "white" }
|
|
||||||
};
|
|
||||||
const struct gmio_vec3d testvertices[] = {
|
|
||||||
{ 0., 0., 0.},
|
|
||||||
{ 1., 0., 0.},
|
|
||||||
{ 1., -1., 0.},
|
|
||||||
{ 0., -1., 0.},
|
|
||||||
{ 1., 0., 1.},
|
|
||||||
{ 1., -1., 1.},
|
|
||||||
{ 0., 0., 1.},
|
|
||||||
{ 0., -1., 1.}
|
|
||||||
};
|
|
||||||
const struct __tamf__triangle testtriangles[] = {
|
|
||||||
{ 0, 1, 2},
|
|
||||||
{ 0, 2, 3},
|
|
||||||
{ 1, 5, 2},
|
|
||||||
{ 1, 4, 5},
|
|
||||||
{ 6, 5, 7},
|
|
||||||
{ 6, 4, 5},
|
|
||||||
{ 0, 6, 7},
|
|
||||||
{ 0, 7, 3},
|
|
||||||
{ 0, 6, 4},
|
|
||||||
{ 0, 4, 1},
|
|
||||||
{ 3, 7, 5},
|
|
||||||
{ 3, 5, 2}
|
|
||||||
};
|
|
||||||
struct __tamf__document testdoc = {0};
|
|
||||||
|
|
||||||
wbuff.ptr = calloc(wbuffsize, 1);
|
|
||||||
wbuff.len = wbuffsize;
|
|
||||||
|
|
||||||
testdoc.vec_material = testmaterials;
|
|
||||||
testdoc.mesh.vec_vertex = testvertices;
|
|
||||||
testdoc.mesh.vertex_count = GMIO_ARRAY_SIZE(testvertices);
|
|
||||||
testdoc.mesh.vec_triangle = testtriangles;
|
|
||||||
testdoc.mesh.triangle_count = GMIO_ARRAY_SIZE(testtriangles);
|
|
||||||
|
|
||||||
doc.cookie = &testdoc;
|
|
||||||
doc.unit = GMIO_AMF_UNIT_MILLIMETER;
|
|
||||||
doc.func_get_document_element = &__tamf__get_document_element;
|
|
||||||
doc.func_get_object_mesh = &__tamf__get_object_mesh;
|
|
||||||
doc.func_get_object_mesh_element = &__tamf__get_object_mesh_element;
|
|
||||||
doc.func_get_object_mesh_volume_triangle =
|
|
||||||
&__tamf__get_object_mesh_volume_triangle;
|
|
||||||
doc.func_get_document_element_metadata =
|
|
||||||
&__tamf__get_document_element_metadata;
|
|
||||||
doc.object_count = 1;
|
|
||||||
doc.material_count = GMIO_ARRAY_SIZE(testmaterials);
|
|
||||||
|
|
||||||
options.float64_prec = 9;
|
|
||||||
|
|
||||||
/* Write as raw contents(uncompressed) */
|
|
||||||
{
|
{
|
||||||
const int error = gmio_amf_write(&stream, &doc, &options);
|
|
||||||
if (gmio_error(error))
|
|
||||||
printf("\n0x%x\n", error);
|
|
||||||
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
|
||||||
/* printf("%s\n", wbuff.ptr); */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write compressed ZIP */
|
|
||||||
{
|
|
||||||
const size_t source_len = wbuff.pos;
|
|
||||||
uint8_t* source = calloc(source_len, 1);
|
|
||||||
|
|
||||||
memcpy(source, wbuff.ptr, source_len);
|
|
||||||
wbuff.pos = 0;
|
wbuff.pos = 0;
|
||||||
|
struct gmio_stream stream = gmio_stream_buffer(&wbuff);
|
||||||
|
struct gmio_amf_write_options options = {0};
|
||||||
|
options.float64_prec = 9;
|
||||||
options.compress = true;
|
options.compress = true;
|
||||||
static const char zip_entry_filename[] = "test.amf";
|
|
||||||
options.zip_entry_filename = zip_entry_filename;
|
options.zip_entry_filename = zip_entry_filename;
|
||||||
options.zip_entry_filename_len = sizeof(zip_entry_filename) - 1;
|
options.zip_entry_filename_len = zip_entry_filename_len;
|
||||||
const int error = gmio_amf_write(&stream, &doc, &options);
|
const int error = gmio_amf_write(&stream, &doc, &options);
|
||||||
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
#if 0
|
#if 0
|
||||||
@ -276,52 +285,108 @@ static const char* test_amf_write()
|
|||||||
fwrite(wbuff.ptr, 1, wbuff.pos, file);
|
fwrite(wbuff.ptr, 1, wbuff.pos, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
#endif
|
#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);
|
/* Unzip and compare with source data */
|
||||||
|
{
|
||||||
|
/* Total size in bytes of the ZIP archive */
|
||||||
|
const uintmax_t zip_archive_len = wbuff.pos;
|
||||||
|
wbuff.pos = 0;
|
||||||
|
struct gmio_stream stream = gmio_stream_buffer(&wbuff);
|
||||||
|
int error = GMIO_ERROR_OK;
|
||||||
|
/* -- Read ZIP local file header */
|
||||||
|
struct gmio_zip_local_file_header zip_lfh = {0};
|
||||||
|
const size_t lfh_read_len =
|
||||||
|
gmio_zip_read_local_file_header(&stream, &zip_lfh, &error);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_lfh.compress_method,
|
||||||
|
GMIO_ZIP_COMPRESS_METHOD_DEFLATE);
|
||||||
|
UTEST_ASSERT(
|
||||||
|
(zip_lfh.general_purpose_flags &
|
||||||
|
GMIO_ZIP_GENERAL_PURPOSE_FLAG_USE_DATA_DESCRIPTOR)
|
||||||
|
!= 0);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_lfh.filename_len,
|
||||||
|
sizeof(zip_entry_filename) - 1);
|
||||||
|
UTEST_ASSERT(strncmp(
|
||||||
|
(const char*)wbuff.ptr + wbuff.pos,
|
||||||
|
zip_entry_filename,
|
||||||
|
zip_entry_filename_len)
|
||||||
|
== 0);
|
||||||
|
/* -- Read ZIP end of central directory record */
|
||||||
|
static const size_t end_of_central_dir_record_len = 22;
|
||||||
|
wbuff.pos = zip_archive_len - end_of_central_dir_record_len;;
|
||||||
|
struct gmio_zip_end_of_central_directory_record zip_eocdr = {0};
|
||||||
|
gmio_zip_read_end_of_central_directory_record(
|
||||||
|
&stream, &zip_eocdr, &error);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
UTEST_COMPARE_UINT(zip_eocdr.disk_nb, 0);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_eocdr.disk_nb_with_start_of_central_dir, 0);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_eocdr.total_entry_count_in_central_dir_on_disk, 1);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_eocdr.total_entry_count_in_central_dir, 1);
|
||||||
|
/* -- Read ZIP central directory */
|
||||||
|
wbuff.pos = zip_eocdr.start_offset_central_dir_from_disk_start_nb;
|
||||||
|
struct gmio_zip_central_directory_header zip_cdh = {0};
|
||||||
|
gmio_zip_read_central_directory_header(&stream, &zip_cdh, &error);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_cdh.compress_method,
|
||||||
|
GMIO_ZIP_COMPRESS_METHOD_DEFLATE);
|
||||||
|
UTEST_ASSERT(
|
||||||
|
(zip_cdh.general_purpose_flags &
|
||||||
|
GMIO_ZIP_GENERAL_PURPOSE_FLAG_USE_DATA_DESCRIPTOR)
|
||||||
|
!= 0);
|
||||||
|
UTEST_COMPARE_UINT(crc32_amf_data, zip_cdh.crc32);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_cdh.filename_len, zip_entry_filename_len);
|
||||||
|
UTEST_ASSERT(strncmp(
|
||||||
|
(const char*)wbuff.ptr + wbuff.pos,
|
||||||
|
zip_entry_filename,
|
||||||
|
zip_entry_filename_len)
|
||||||
|
== 0);
|
||||||
|
/* -- Read compressed AMF data */
|
||||||
|
const size_t pos_start_amf_data =
|
||||||
|
lfh_read_len + zip_lfh.filename_len + zip_lfh.extrafield_len;
|
||||||
|
wbuff.pos = pos_start_amf_data;
|
||||||
|
{
|
||||||
|
uint8_t* dest = calloc(zip_cdh.uncompressed_size, 1);
|
||||||
|
size_t dest_len = zip_cdh.uncompressed_size;
|
||||||
|
const int error =
|
||||||
|
gmio_zlib_uncompress_buffer(
|
||||||
|
dest,
|
||||||
|
&dest_len,
|
||||||
|
(const uint8_t*)wbuff.ptr + wbuff.pos,
|
||||||
|
zip_cdh.compressed_size);
|
||||||
|
printf("\n-- Info: z_len=%i src_len=%i\n",
|
||||||
|
zip_cdh.compressed_size, source_len);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
UTEST_COMPARE_UINT(source_len, dest_len);
|
||||||
|
UTEST_COMPARE_UINT(dest_len, zip_cdh.uncompressed_size);
|
||||||
|
UTEST_COMPARE_INT(memcmp(dest, source, source_len), 0);
|
||||||
|
const uint32_t crc32_uncomp = gmio_zlib_crc32(dest, dest_len);
|
||||||
|
UTEST_COMPARE_UINT(crc32_amf_data, crc32_uncomp);
|
||||||
|
free(dest);
|
||||||
|
}
|
||||||
|
/* -- Read ZIP data descriptor */
|
||||||
|
wbuff.pos = pos_start_amf_data + zip_cdh.compressed_size;
|
||||||
|
struct gmio_zip_data_descriptor zip_dd = {0};
|
||||||
|
gmio_zip_read_data_descriptor(&stream, &zip_dd, &error);
|
||||||
|
UTEST_COMPARE_INT(error, GMIO_ERROR_OK);
|
||||||
|
UTEST_COMPARE_UINT(zip_dd.crc32, crc32_amf_data);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_dd.compressed_size, zip_cdh.compressed_size);
|
||||||
|
UTEST_COMPARE_UINT(
|
||||||
|
zip_dd.uncompressed_size, zip_cdh.uncompressed_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(wbuff.ptr);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user