From a53539f9af3f3a4237e6400b5cbb3fd6d85e40ca Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 28 Aug 2019 16:03:26 +0200 Subject: [PATCH] Fixed import of .3mf and .amf files. Parse contained XML model file by chunch instead that as a whole --- src/libslic3r/Format/3mf.cpp | 42 +++++++++++++++++++++++++----------- src/libslic3r/Format/AMF.cpp | 41 ++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 5e0878884..2a8b4d1d3 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -705,25 +705,41 @@ namespace Slic3r { XML_SetElementHandler(m_xml_parser, _3MF_Importer::_handle_start_model_xml_element, _3MF_Importer::_handle_end_model_xml_element); XML_SetCharacterDataHandler(m_xml_parser, _3MF_Importer::_handle_model_xml_characters); - void* parser_buffer = XML_GetBuffer(m_xml_parser, (int)stat.m_uncomp_size); - if (parser_buffer == nullptr) + struct CallbackData { - add_error("Unable to create buffer"); + XML_Parser& parser; + const mz_zip_archive_file_stat& stat; + + CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {} + }; + + CallbackData data(m_xml_parser, stat); + + mz_bool res = 0; + + try + { + res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t { + CallbackData* data = (CallbackData*)pOpaque; + if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0)) + { + char error_buf[1024]; + ::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser)); + throw std::runtime_error(error_buf); + } + + return n; + }, &data, 0); + } + catch (std::exception& e) + { + add_error(e.what()); return false; } - mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0); if (res == 0) { - add_error("Error while reading model data to buffer"); - return false; - } - - if (!XML_ParseBuffer(m_xml_parser, (int)stat.m_uncomp_size, 1)) - { - char error_buf[1024]; - ::sprintf(error_buf, "Error (%s) while parsing xml file at line %d", XML_ErrorString(XML_GetErrorCode(m_xml_parser)), (int)XML_GetCurrentLineNumber(m_xml_parser)); - add_error(error_buf); + add_error("Error while extracting model data from zip archive"); return false; } diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 033e64aa0..7850c17fd 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -783,25 +783,42 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi XML_SetElementHandler(parser, AMFParserContext::startElement, AMFParserContext::endElement); XML_SetCharacterDataHandler(parser, AMFParserContext::characters); - void* parser_buffer = XML_GetBuffer(parser, (int)stat.m_uncomp_size); - if (parser_buffer == nullptr) + struct CallbackData { - printf("Unable to create buffer\n"); + XML_Parser& parser; + const mz_zip_archive_file_stat& stat; + + CallbackData(XML_Parser& parser, const mz_zip_archive_file_stat& stat) : parser(parser), stat(stat) {} + }; + + CallbackData data(parser, stat); + + mz_bool res = 0; + + try + { + res = mz_zip_reader_extract_file_to_callback(&archive, stat.m_filename, [](void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)->size_t { + CallbackData* data = (CallbackData*)pOpaque; + if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0)) + { + char error_buf[1024]; + ::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser)); + throw std::runtime_error(error_buf); + } + + return n; + }, &data, 0); + } + catch (std::exception& e) + { + printf("%s\n", e.what()); close_zip_reader(&archive); return false; } - mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0); if (res == 0) { - printf("Error while reading model data to buffer\n"); - close_zip_reader(&archive); - return false; - } - - if (!XML_ParseBuffer(parser, (int)stat.m_uncomp_size, 1)) - { - printf("Error (%s) while parsing xml file at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)), (int)XML_GetCurrentLineNumber(parser)); + printf("Error while extracting model data from zip archive"); close_zip_reader(&archive); return false; }