Merge branch 'dev' into dev

This commit is contained in:
Thomas Fussell 2017-09-08 23:15:06 -04:00 committed by GitHub
commit 299fc7d572
49 changed files with 3466 additions and 656 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ Win32/
*.pyd *.pyd
python/record.txt python/record.txt
python/xlntpyarrow.egg-info/ python/xlntpyarrow.egg-info/
/x64/

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(xlnt_all) project(xlnt_all)
# This indicates to CMakeLists in subdirectories that they are part of a larger project # This indicates to CMakeLists in subdirectories that they are part of a larger project
@ -11,28 +11,28 @@ option(STATIC "Set to ON to build xlnt as a static library instead of a shared l
option(TESTS "Set to OFF to skip building test executable (in ./tests)" ON) option(TESTS "Set to OFF to skip building test executable (in ./tests)" ON)
option(SAMPLES "Set to ON to build executable code samples (in ./samples)" OFF) option(SAMPLES "Set to ON to build executable code samples (in ./samples)" OFF)
option(BENCHMARKS "Set to ON to build performance benchmarks (in ./benchmarks)" OFF) option(BENCHMARKS "Set to ON to build performance benchmarks (in ./benchmarks)" OFF)
option(ARROW "Set to ON to build Arrow conversion functions (in ./contrib/xlntarrow)" OFF) option(PYTHON "Set to ON to build Arrow conversion functions (in ./python)" OFF)
# Platform specific options # Platform specific options
if(NOT MSVC) if(NOT MSVC)
option(COVERAGE "Generate coverage data using gcov" OFF) option(COVERAGE "Generate coverage data using gcov" OFF)
endif() endif()
# Add components according to selected options # Add components according to selected options
if(SAMPLES) if(SAMPLES)
add_subdirectory(samples) add_subdirectory(samples)
endif() endif()
if(BENCHMARKS) if(BENCHMARKS)
add_subdirectory(benchmarks) add_subdirectory(benchmarks)
endif() endif()
if(TESTS) if(TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
if(PYTHON) if(PYTHON)
add_subdirectory(python) add_subdirectory(python)
endif() endif()
add_subdirectory(source) add_subdirectory(source)

46
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at thomas.fussell@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View File

@ -26,6 +26,37 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
``` ```
# Dependency Licences
## [utfcpp](https://github.com/nemtrif/utfcpp)
>[Boost Software License - Version 1.0](https://github.com/nemtrif/utfcpp/blob/master/source/utf8.h)
```
Copyright 2006 Nemanja Trifunovic
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
## [POLE](http://www.dimin.net/software/pole/) ## [POLE](http://www.dimin.net/software/pole/)
>[BSD 2-Clause License](https://bitbucket.org/dimin/pole/src/c15e513bdce4c3a52b3dbc925d4d2bb520dc71d8/pole/LICENSE) >[BSD 2-Clause License](https://bitbucket.org/dimin/pole/src/c15e513bdce4c3a52b3dbc925d4d2bb520dc71d8/pole/LICENSE)
@ -92,6 +123,204 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
``` ```
## [PartIO](https://www.disneyanimation.com/technology/partio.html)
>[BSD 3-Clause License (with specific non-attribution clause)](https://github.com/wdas/partio/blob/master/src/lib/io/ZIP.h)
```
Copyright 2010 Disney Enterprises, Inc. All rights reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
Studios" or the names of its contributors may NOT be used to
endorse or promote products derived from this software without
specific prior written permission from Walt Disney Pictures.
Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
```
## [miniz](https://github.com/richgel999/miniz)
>[Public Domain/MIT License](https://github.com/richgel999/miniz/blob/master/LICENSE)
```
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
Copyright 2013-2014 RAD Game Tools and Valve Software
Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
## [SHA-512 hash in C](https://www.nayuki.io/page/fast-sha2-hashes-in-x86-assembly)
>[MIT License](https://www.nayuki.io/res/fast-sha2-hashes-in-x86-assembly/sha512.c)
```
Copyright (c) 2016 Project Nayuki
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## [SHA-1 hash in C](https://www.nayuki.io/page/fast-sha1-hash-implementation-in-x86-assembly)
>[MIT License](https://www.nayuki.io/res/fast-sha1-hash-implementation-in-x86-assembly/sha1-fast.c)
```
Copyright (c) 2014 Project Nayuki
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
```
## [LibTomCrypt](http://www.libtom.net/)
>[Public Domain](https://github.com/libtom/libtomcrypt/blob/develop/LICENSE)
```
LibTomCrypt is public domain. As should all quality software be.
Tom St Denis
```
# Dependency Licences (Python Module)
## [pybind11](https://github.com/pybind/pybind11)
>[BSD 3-Clause License](https://github.com/pybind/pybind11/blob/master/LICENSE)
```
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You are under no obligation whatsoever to provide any bug fixes, patches, or
upgrades to the features, functionality or performance of the source code
("Enhancements") to anyone; however, if you choose to make your Enhancements
available either publicly, or directly to the author of this software, without
imposing a separate written license agreement for such Enhancements, then you
hereby grant the following license: a non-exclusive, royalty-free perpetual
license to install, use, modify, prepare derivative works, incorporate into
other computer software, distribute, and sublicense such enhancements or
derivative works thereof, in binary and source code form.
```
# Dependency Licences (Testing Only)
## [CxxTest](http://cxxtest.com/) ## [CxxTest](http://cxxtest.com/)
>[LGPL License](https://github.com/CxxTest/cxxtest/blob/master/COPYING) >[LGPL License](https://github.com/CxxTest/cxxtest/blob/master/COPYING)
@ -262,92 +491,3 @@ apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the permanent authorization for you to choose that version for the
Library. Library.
``` ```
## [PartIO](https://www.disneyanimation.com/technology/partio.html)
>[BSD 3-Clause License (with specific non-attribution clause)](https://github.com/wdas/partio/blob/master/src/lib/io/ZIP.h)
```
Copyright 2010 Disney Enterprises, Inc. All rights reserved
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
Studios" or the names of its contributors may NOT be used to
endorse or promote products derived from this software without
specific prior written permission from Walt Disney Pictures.
Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
```
## [miniz](https://github.com/richgel999/miniz)
>[Public Domain/MIT License](https://github.com/richgel999/miniz/blob/master/LICENSE)
```
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
Copyright 2013-2014 RAD Game Tools and Valve Software
Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```

View File

@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(xlnt.benchmarks) project(xlnt.benchmarks)
set(CMAKE_CXX_STANDARD 14) # Require C++11 compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT COMBINED_PROJECT) if(NOT COMBINED_PROJECT)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) # Include xlnt library
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source)
endif()
if(MSVC AND STATIC)
# Link with static C runtime
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ucm.cmake)
ucm_set_runtime(STATIC)
endif() endif()
set(XLNT_BENCHMARK_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) set(XLNT_BENCHMARK_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
@ -13,20 +21,24 @@ set(XLNT_BENCHMARK_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
file(GLOB BENCHMARK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file(GLOB BENCHMARK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(BENCHMARK_SOURCE IN ITEMS ${BENCHMARK_SOURCES}) foreach(BENCHMARK_SOURCE IN ITEMS ${BENCHMARK_SOURCES})
get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE) # Convert <name>.cpp to benchmark-<name>
set(BENCHMARK_EXECUTABLE benchmark-${BENCHMARK_NAME}) get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE)
set(BENCHMARK_EXECUTABLE benchmark-${BENCHMARK_NAME})
add_executable(${BENCHMARK_EXECUTABLE} ${BENCHMARK_SOURCE}) add_executable(${BENCHMARK_EXECUTABLE} ${BENCHMARK_SOURCE})
target_link_libraries(${BENCHMARK_EXECUTABLE} PRIVATE xlnt) target_link_libraries(${BENCHMARK_EXECUTABLE} PRIVATE xlnt)
target_include_directories(${BENCHMARK_EXECUTABLE} # Need to use some test helpers
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests) target_include_directories(${BENCHMARK_EXECUTABLE}
target_compile_definitions(${BENCHMARK_EXECUTABLE} PRIVATE XLNT_BENCHMARK_DATA_DIR=${XLNT_BENCHMARK_DATA_DIR}) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests)
target_compile_definitions(${BENCHMARK_EXECUTABLE}
PRIVATE XLNT_BENCHMARK_DATA_DIR=${XLNT_BENCHMARK_DATA_DIR})
if(MSVC AND NOT STATIC) if(MSVC AND NOT STATIC)
add_custom_command(TARGET ${BENCHMARK_EXECUTABLE} POST_BUILD # Copy xlnt DLL into benchmarks directory
COMMAND ${CMAKE_COMMAND} -E copy_if_different add_custom_command(TARGET ${BENCHMARK_EXECUTABLE} POST_BUILD
$<TARGET_FILE:xlnt> COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE_DIR:${BENCHMARK_EXECUTABLE}>) $<TARGET_FILE:xlnt>
endif() $<TARGET_FILE_DIR:${BENCHMARK_EXECUTABLE}>)
endif()
endforeach() endforeach()

10
book.json Normal file
View File

@ -0,0 +1,10 @@
{
"plugins": ["build"],
"pluginsConfig": {
"build": {
"template": "docs/template.ejs",
"format": "man",
"output": "docs/xlnt.3"
}
}
}

634
cmake/ucm.cmake Normal file
View File

@ -0,0 +1,634 @@
#
# ucm.cmake - useful cmake macros
#
# Copyright (c) 2016 Viktor Kirilov
#
# Distributed under the MIT Software License
# See accompanying file LICENSE.txt or copy at
# https://opensource.org/licenses/MIT
#
# The documentation can be found at the library's page:
# https://github.com/onqtam/ucm
cmake_minimum_required(VERSION 2.8.12)
include(CMakeParseArguments)
# optionally include cotire - the git submodule might not be inited (or the user might have already included it)
if(NOT COMMAND cotire)
include(${CMAKE_CURRENT_LIST_DIR}/../cotire/CMake/cotire.cmake OPTIONAL)
endif()
if(COMMAND cotire AND "1.7.9" VERSION_LESS "${COTIRE_CMAKE_MODULE_VERSION}")
set(ucm_with_cotire 1)
else()
set(ucm_with_cotire 0)
endif()
option(UCM_UNITY_BUILD "Enable unity build for targets registered with the ucm_add_target() macro" OFF)
option(UCM_NO_COTIRE_FOLDER "Do not use a cotire folder in the solution explorer for all unity and cotire related targets" ON)
# ucm_add_flags
# Adds compiler flags to CMAKE_<LANG>_FLAGS or to a specific config
macro(ucm_add_flags)
cmake_parse_arguments(ARG "C;CXX;CLEAR_OLD" "" "CONFIG" ${ARGN})
if(NOT ARG_CONFIG)
set(ARG_CONFIG " ")
endif()
foreach(CONFIG ${ARG_CONFIG})
# determine to which flags to add
if(NOT ${CONFIG} STREQUAL " ")
string(TOUPPER ${CONFIG} CONFIG)
set(CXX_FLAGS CMAKE_CXX_FLAGS_${CONFIG})
set(C_FLAGS CMAKE_C_FLAGS_${CONFIG})
else()
set(CXX_FLAGS CMAKE_CXX_FLAGS)
set(C_FLAGS CMAKE_C_FLAGS)
endif()
# clear the old flags
if(${ARG_CLEAR_OLD})
if("${ARG_CXX}" OR NOT "${ARG_C}")
set(${CXX_FLAGS} "")
endif()
if("${ARG_C}" OR NOT "${ARG_CXX}")
set(${C_FLAGS} "")
endif()
endif()
# add all the passed flags
foreach(flag ${ARG_UNPARSED_ARGUMENTS})
if("${ARG_CXX}" OR NOT "${ARG_C}")
set(${CXX_FLAGS} "${${CXX_FLAGS}} ${flag}")
endif()
if("${ARG_C}" OR NOT "${ARG_CXX}")
set(${C_FLAGS} "${${C_FLAGS}} ${flag}")
endif()
endforeach()
endforeach()
endmacro()
# ucm_set_flags
# Sets the CMAKE_<LANG>_FLAGS compiler flags or for a specific config
macro(ucm_set_flags)
ucm_add_flags(CLEAR_OLD ${ARGN})
endmacro()
# ucm_add_linker_flags
# Adds linker flags to CMAKE_<TYPE>_LINKER_FLAGS or to a specific config
macro(ucm_add_linker_flags)
cmake_parse_arguments(ARG "CLEAR_OLD;EXE;MODULE;SHARED;STATIC" "" "CONFIG" ${ARGN})
if(NOT ARG_CONFIG)
set(ARG_CONFIG " ")
endif()
foreach(CONFIG ${ARG_CONFIG})
string(TOUPPER "${CONFIG}" CONFIG)
if(NOT ${ARG_EXE} AND NOT ${ARG_MODULE} AND NOT ${ARG_SHARED} AND NOT ${ARG_STATIC})
set(ARG_EXE 1)
set(ARG_MODULE 1)
set(ARG_SHARED 1)
set(ARG_STATIC 1)
endif()
set(flags_configs "")
if(${ARG_EXE})
if(NOT "${CONFIG}" STREQUAL " ")
list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS_${CONFIG})
else()
list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS)
endif()
endif()
if(${ARG_MODULE})
if(NOT "${CONFIG}" STREQUAL " ")
list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS_${CONFIG})
else()
list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS)
endif()
endif()
if(${ARG_SHARED})
if(NOT "${CONFIG}" STREQUAL " ")
list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS_${CONFIG})
else()
list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS)
endif()
endif()
if(${ARG_STATIC})
if(NOT "${CONFIG}" STREQUAL " ")
list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS_${CONFIG})
else()
list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS)
endif()
endif()
# clear the old flags
if(${ARG_CLEAR_OLD})
foreach(flags ${flags_configs})
set(${flags} "")
endforeach()
endif()
# add all the passed flags
foreach(flag ${ARG_UNPARSED_ARGUMENTS})
foreach(flags ${flags_configs})
set(${flags} "${${flags}} ${flag}")
endforeach()
endforeach()
endforeach()
endmacro()
# ucm_set_linker_flags
# Sets the CMAKE_<TYPE>_LINKER_FLAGS linker flags or for a specific config
macro(ucm_set_linker_flags)
ucm_add_linker_flags(CLEAR_OLD ${ARGN})
endmacro()
# ucm_gather_flags
# Gathers all lists of flags for printing or manipulation
macro(ucm_gather_flags with_linker result)
set(${result} "")
# add the main flags without a config
list(APPEND ${result} CMAKE_C_FLAGS)
list(APPEND ${result} CMAKE_CXX_FLAGS)
if(${with_linker})
list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS)
list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS)
list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS)
list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS)
endif()
if("${CMAKE_CONFIGURATION_TYPES}" STREQUAL "" AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "")
# handle single config generators - like makefiles/ninja - when CMAKE_BUILD_TYPE is set
string(TOUPPER ${CMAKE_BUILD_TYPE} config)
list(APPEND ${result} CMAKE_C_FLAGS_${config})
list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
if(${with_linker})
list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
endif()
else()
# handle multi config generators (like msvc, xcode)
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
list(APPEND ${result} CMAKE_C_FLAGS_${config})
list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
if(${with_linker})
list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
endif()
endforeach()
endif()
endmacro()
# ucm_set_runtime
# Sets the runtime (static/dynamic) for msvc/gcc
macro(ucm_set_runtime)
cmake_parse_arguments(ARG "STATIC;DYNAMIC" "" "" ${ARGN})
if(ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" STREQUAL "")
message(AUTHOR_WARNING "ucm_set_runtime() does not support clang yet!")
endif()
ucm_gather_flags(0 flags_configs)
# add/replace the flags
# note that if the user has messed with the flags directly this function might fail
# - for example if with MSVC and the user has removed the flags - here we just switch/replace them
if("${ARG_STATIC}")
foreach(flags ${flags_configs})
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(NOT ${flags} MATCHES "-static-libstdc\\+\\+")
set(${flags} "${${flags}} -static-libstdc++")
endif()
if(NOT ${flags} MATCHES "-static-libgcc")
set(${flags} "${${flags}} -static-libgcc")
endif()
elseif(MSVC)
if(${flags} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flags} "${${flags}}")
endif()
endif()
endforeach()
elseif("${ARG_DYNAMIC}")
foreach(flags ${flags_configs})
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(${flags} MATCHES "-static-libstdc\\+\\+")
string(REGEX REPLACE "-static-libstdc\\+\\+" "" ${flags} "${${flags}}")
endif()
if(${flags} MATCHES "-static-libgcc")
string(REGEX REPLACE "-static-libgcc" "" ${flags} "${${flags}}")
endif()
elseif(MSVC)
if(${flags} MATCHES "/MT")
string(REGEX REPLACE "/MT" "/MD" ${flags} "${${flags}}")
endif()
endif()
endforeach()
endif()
endmacro()
# ucm_print_flags
# Prints all compiler flags for all configurations
macro(ucm_print_flags)
ucm_gather_flags(1 flags_configs)
message("")
foreach(flags ${flags_configs})
message("${flags}: ${${flags}}")
endforeach()
message("")
endmacro()
# ucm_count_sources
# Counts the number of source files
macro(ucm_count_sources)
cmake_parse_arguments(ARG "" "RESULT" "" ${ARGN})
if(${ARG_RESULT} STREQUAL "")
message(FATAL_ERROR "Need to pass RESULT and a variable name to ucm_count_sources()")
endif()
set(result 0)
foreach(SOURCE_FILE ${ARG_UNPARSED_ARGUMENTS})
if("${SOURCE_FILE}" MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx|i|ii\)$)
math(EXPR result "${result} + 1")
endif()
endforeach()
set(${ARG_RESULT} ${result})
endmacro()
# ucm_include_file_in_sources
# Includes the file to the source with compiler flags
macro(ucm_include_file_in_sources)
cmake_parse_arguments(ARG "" "HEADER" "" ${ARGN})
if(${ARG_HEADER} STREQUAL "")
message(FATAL_ERROR "Need to pass HEADER and a header file to ucm_include_file_in_sources()")
endif()
foreach(src ${ARG_UNPARSED_ARGUMENTS})
if(${src} MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
# get old flags
get_source_file_property(old_compile_flags ${src} COMPILE_FLAGS)
if(old_compile_flags STREQUAL "NOTFOUND")
set(old_compile_flags "")
endif()
# update flags
if(MSVC)
set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
"${old_compile_flags} /FI\"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
else()
set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
"${old_compile_flags} -include \"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
endif()
endif()
endforeach()
endmacro()
# ucm_dir_list
# Returns a list of subdirectories for a given directory
macro(ucm_dir_list thedir result)
file(GLOB sub-dir "${thedir}/*")
set(list_of_dirs "")
foreach(dir ${sub-dir})
if(IS_DIRECTORY ${dir})
get_filename_component(DIRNAME ${dir} NAME)
LIST(APPEND list_of_dirs ${DIRNAME})
endif()
endforeach()
set(${result} ${list_of_dirs})
endmacro()
# ucm_trim_front_words
# Trims X times the front word from a string separated with "/" and removes
# the front "/" characters after that (used for filters for visual studio)
macro(ucm_trim_front_words source out num_filter_trims)
set(result "${source}")
set(counter 0)
while(${counter} LESS ${num_filter_trims})
MATH(EXPR counter "${counter} + 1")
# removes everything at the front up to a "/" character
string(REGEX REPLACE "^([^/]+)" "" result "${result}")
# removes all consecutive "/" characters from the front
string(REGEX REPLACE "^(/+)" "" result "${result}")
endwhile()
set(${out} ${result})
endmacro()
# ucm_remove_files
# Removes source files from a list of sources (path is the relative path for it to be found)
macro(ucm_remove_files)
cmake_parse_arguments(ARG "" "FROM" "" ${ARGN})
if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(FATAL_ERROR "Need to pass some relative files to ucm_remove_files()")
endif()
if(${ARG_FROM} STREQUAL "")
message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_files()")
endif()
foreach(cur_file ${ARG_UNPARSED_ARGUMENTS})
list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
endforeach()
endmacro()
# ucm_remove_directories
# Removes all source files from the given directories from the sources list
macro(ucm_remove_directories)
cmake_parse_arguments(ARG "" "FROM" "MATCHES" ${ARGN})
if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(FATAL_ERROR "Need to pass some relative directories to ucm_remove_directories()")
endif()
if(${ARG_FROM} STREQUAL "")
message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_directories()")
endif()
foreach(cur_dir ${ARG_UNPARSED_ARGUMENTS})
foreach(cur_file ${${ARG_FROM}})
string(REGEX MATCH ${cur_dir} res ${cur_file})
if(NOT "${res}" STREQUAL "")
if("${ARG_MATCHES}" STREQUAL "")
list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
else()
foreach(curr_ptrn ${ARG_MATCHES})
string(REGEX MATCH ${curr_ptrn} res ${cur_file})
if(NOT "${res}" STREQUAL "")
list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
break()
endif()
endforeach()
endif()
endif()
endforeach()
endforeach()
endmacro()
# ucm_add_files_impl
macro(ucm_add_files_impl result trim files)
foreach(cur_file ${files})
SET(${result} ${${result}} ${cur_file})
get_filename_component(FILEPATH ${cur_file} PATH)
ucm_trim_front_words("${FILEPATH}" FILEPATH "${trim}")
# replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
STRING(REPLACE "/" "\\" FILTERS "${FILEPATH}")
SOURCE_GROUP("${FILTERS}" FILES ${cur_file})
endforeach()
endmacro()
# ucm_add_files
# Adds files to a list of sources
macro(ucm_add_files)
cmake_parse_arguments(ARG "" "TO;FILTER_POP" "" ${ARGN})
if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(FATAL_ERROR "Need to pass some relative files to ucm_add_files()")
endif()
if(${ARG_TO} STREQUAL "")
message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_files()")
endif()
if("${ARG_FILTER_POP}" STREQUAL "")
set(ARG_FILTER_POP 0)
endif()
ucm_add_files_impl(${ARG_TO} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}")
endmacro()
# ucm_add_dir_impl
macro(ucm_add_dir_impl result rec trim dirs_in additional_ext)
set(dirs "${dirs_in}")
# handle the "" and "." cases
if("${dirs}" STREQUAL "" OR "${dirs}" STREQUAL ".")
set(dirs "./")
endif()
foreach(cur_dir ${dirs})
# to circumvent some linux/cmake/path issues - barely made it work...
if(cur_dir STREQUAL "./")
set(cur_dir "")
else()
set(cur_dir "${cur_dir}/")
endif()
# since unix is case sensitive - add these valid extensions too
# we don't use "UNIX" but instead "CMAKE_HOST_UNIX" because we might be cross
# compiling (for example emscripten) under windows and UNIX may be set to 1
# Also OSX is case insensitive like windows...
set(additional_file_extensions "")
if(CMAKE_HOST_UNIX AND NOT APPLE)
set(additional_file_extensions
"${cur_dir}*.CPP"
"${cur_dir}*.C"
"${cur_dir}*.H"
"${cur_dir}*.HPP"
)
endif()
foreach(ext ${additional_ext})
list(APPEND additional_file_extensions "${cur_dir}*.${ext}")
endforeach()
# find all sources and set them as result
FILE(GLOB found_sources RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
# https://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Overall-Options.html#index-file-name-suffix-71
# sources
"${cur_dir}*.cpp"
"${cur_dir}*.cxx"
"${cur_dir}*.c++"
"${cur_dir}*.cc"
"${cur_dir}*.cp"
"${cur_dir}*.c"
"${cur_dir}*.i"
"${cur_dir}*.ii"
# headers
"${cur_dir}*.h"
"${cur_dir}*.h++"
"${cur_dir}*.hpp"
"${cur_dir}*.hxx"
"${cur_dir}*.hh"
"${cur_dir}*.inl"
"${cur_dir}*.inc"
"${cur_dir}*.ipp"
"${cur_dir}*.ixx"
"${cur_dir}*.txx"
"${cur_dir}*.tpp"
"${cur_dir}*.tcc"
"${cur_dir}*.tpl"
${additional_file_extensions})
SET(${result} ${${result}} ${found_sources})
# set the proper filters
ucm_trim_front_words("${cur_dir}" cur_dir "${trim}")
# replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
STRING(REPLACE "/" "\\" FILTERS "${cur_dir}")
SOURCE_GROUP("${FILTERS}" FILES ${found_sources})
endforeach()
if(${rec})
foreach(cur_dir ${dirs})
ucm_dir_list("${cur_dir}" subdirs)
foreach(subdir ${subdirs})
ucm_add_dir_impl(${result} ${rec} ${trim} "${cur_dir}/${subdir}" "${additional_ext}")
endforeach()
endforeach()
endif()
endmacro()
# ucm_add_dirs
# Adds all files from directories traversing them recursively to a list of sources
# and generates filters according to their location (accepts relative paths only).
# Also this macro trims X times the front word from the filter string for visual studio filters.
macro(ucm_add_dirs)
cmake_parse_arguments(ARG "RECURSIVE" "TO;FILTER_POP" "ADDITIONAL_EXT" ${ARGN})
if(${ARG_TO} STREQUAL "")
message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_dirs()")
endif()
if("${ARG_FILTER_POP}" STREQUAL "")
set(ARG_FILTER_POP 0)
endif()
ucm_add_dir_impl(${ARG_TO} ${ARG_RECURSIVE} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}" "${ARG_ADDITIONAL_EXT}")
endmacro()
# ucm_add_target
# Adds a target eligible for cotiring - unity build and/or precompiled header
macro(ucm_add_target)
cmake_parse_arguments(ARG "UNITY" "NAME;TYPE;PCH_FILE;CPP_PER_UNITY" "UNITY_EXCLUDED;SOURCES" ${ARGN})
if(NOT "${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
message(FATAL_ERROR "Unrecognized options passed to ucm_add_target()")
endif()
if("${ARG_NAME}" STREQUAL "")
message(FATAL_ERROR "Need to pass NAME and a name for the target to ucm_add_target()")
endif()
set(valid_types EXECUTABLE STATIC SHARED MODULE)
list(FIND valid_types "${ARG_TYPE}" is_type_valid)
if(${is_type_valid} STREQUAL "-1")
message(FATAL_ERROR "Need to pass TYPE and the type for the target [EXECUTABLE/STATIC/SHARED/MODULE] to ucm_add_target()")
endif()
if("${ARG_SOURCES}" STREQUAL "")
message(FATAL_ERROR "Need to pass SOURCES and a list of source files to ucm_add_target()")
endif()
# init with the global unity flag
set(do_unity ${UCM_UNITY_BUILD})
# check the UNITY argument
if(NOT ARG_UNITY)
set(do_unity FALSE)
endif()
# if target is excluded through the exclusion list
list(FIND UCM_UNITY_BUILD_EXCLUDE_TARGETS ${ARG_NAME} is_target_excluded)
if(NOT ${is_target_excluded} STREQUAL "-1")
set(do_unity FALSE)
endif()
# unity build only for targets with > 1 source file (otherwise there will be an additional unnecessary target)
if(do_unity) # optimization
ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
if(${num_sources} LESS 2)
set(do_unity FALSE)
endif()
endif()
set(wanted_cotire ${do_unity})
# if cotire cannot be used
if(do_unity AND NOT ucm_with_cotire)
set(do_unity FALSE)
endif()
# inform the developer that the current target might benefit from a unity build
if(NOT ARG_UNITY AND ${UCM_UNITY_BUILD})
ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
if(${num_sources} GREATER 1)
message(AUTHOR_WARNING "Target '${ARG_NAME}' may benefit from a unity build.\nIt has ${num_sources} sources - enable with UNITY flag")
endif()
endif()
# prepare for the unity build
set(orig_target ${ARG_NAME})
if(do_unity)
# the original target will be added with a different name than the requested
set(orig_target ${ARG_NAME}_ORIGINAL)
# exclude requested files from unity build of the current target
foreach(excluded_file "${ARG_UNITY_EXCLUDED}")
set_source_files_properties(${excluded_file} PROPERTIES COTIRE_EXCLUDED TRUE)
endforeach()
endif()
# add the original target
if(${ARG_TYPE} STREQUAL "EXECUTABLE")
add_executable(${orig_target} ${ARG_SOURCES})
else()
add_library(${orig_target} ${ARG_TYPE} ${ARG_SOURCES})
endif()
if(do_unity)
# set the number of unity cpp files to be used for the unity target
if(NOT "${ARG_CPP_PER_UNITY}" STREQUAL "")
set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${ARG_CPP_PER_UNITY}")
else()
set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "100")
endif()
if(NOT "${ARG_PCH_FILE}" STREQUAL "")
set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
else()
set_target_properties(${orig_target} PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER FALSE)
endif()
# add a unity target for the original one with the name intended for the original
set_target_properties(${orig_target} PROPERTIES COTIRE_UNITY_TARGET_NAME ${ARG_NAME})
# this is the library call that does the magic
cotire(${orig_target})
set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
# disable the original target and enable the unity one
get_target_property(unity_target_name ${orig_target} COTIRE_UNITY_TARGET_NAME)
set_target_properties(${orig_target} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
set_target_properties(${unity_target_name} PROPERTIES EXCLUDE_FROM_ALL 0 EXCLUDE_FROM_DEFAULT_BUILD 0)
# also set the name of the target output as the original one
set_target_properties(${unity_target_name} PROPERTIES OUTPUT_NAME ${ARG_NAME})
if(UCM_NO_COTIRE_FOLDER)
# reset the folder property so all unity targets dont end up in a single folder in the solution explorer of VS
set_target_properties(${unity_target_name} PROPERTIES FOLDER "")
endif()
set_target_properties(all_unity PROPERTIES FOLDER "CMakePredefinedTargets")
elseif(NOT "${ARG_PCH_FILE}" STREQUAL "")
set(wanted_cotire TRUE)
if(ucm_with_cotire)
set_target_properties(${orig_target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
cotire(${orig_target})
set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
endif()
endif()
# print a message if the target was requested to be cotired but it couldn't
if(wanted_cotire AND NOT ucm_with_cotire)
if(NOT COMMAND cotire)
message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire isn't loaded")
else()
message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire is older than the required version")
endif()
endif()
endmacro()

3
docs/template.ejs Normal file
View File

@ -0,0 +1,3 @@
<% for(var i = 0; i < summary.length; i++) {%>
<%- summary[i].content %>
<% } %>

1859
docs/xlnt.3 Normal file

File diff suppressed because it is too large Load Diff

View File

@ -156,11 +156,6 @@ public:
/// </summary> /// </summary>
void value(double float_value); void value(double float_value);
/// <summary>
/// Sets the value of this cell to the given value.
/// </summary>
void value(long double float_value);
/// <summary> /// <summary>
/// Sets the value of this cell to the given value. /// Sets the value of this cell to the given value.
/// </summary> /// </summary>
@ -671,9 +666,6 @@ float cell::value<float>() const;
template<> template<>
double cell::value<double>() const; double cell::value<double>() const;
template<>
long double cell::value<long double>() const;
template<> template<>
date cell::value<date>() const; date cell::value<date>() const;

View File

@ -242,7 +242,7 @@ public:
/// Returns number formatted according to this number format's format code /// Returns number formatted according to this number format's format code
/// with the given base date. /// with the given base date.
/// </summary> /// </summary>
std::string format(long double number, calendar base_date) const; std::string format(double number, calendar base_date) const;
/// <summary> /// <summary>
/// Returns true if this format code returns a number formatted as a date. /// Returns true if this format code returns a number formatted as a date.

View File

@ -54,7 +54,7 @@ struct XLNT_API datetime
/// a date and the fractional part into a time according to date::from_number /// a date and the fractional part into a time according to date::from_number
/// and time::from_number. /// and time::from_number.
/// </summary> /// </summary>
static datetime from_number(long double number, calendar base_date); static datetime from_number(double number, calendar base_date);
/// <summary> /// <summary>
/// Returns a datetime equivalent to the ISO-formatted string iso_string. /// Returns a datetime equivalent to the ISO-formatted string iso_string.
@ -84,7 +84,7 @@ struct XLNT_API datetime
/// <summary> /// <summary>
/// Returns this datetime as a number of seconds since 1900 or 1904 (depending on base_date provided). /// Returns this datetime as a number of seconds since 1900 or 1904 (depending on base_date provided).
/// </summary> /// </summary>
long double to_number(calendar base_date) const; double to_number(calendar base_date) const;
/// <summary> /// <summary>
/// Returns true if this datetime is equivalent to comparand. /// Returns true if this datetime is equivalent to comparand.

View File

@ -46,7 +46,7 @@ struct XLNT_API time
/// The integer part of number will be ignored. /// The integer part of number will be ignored.
/// 0.5 would return time(12, 0, 0, 0) or noon, halfway through the day. /// 0.5 would return time(12, 0, 0, 0) or noon, halfway through the day.
/// </summary> /// </summary>
static time from_number(long double number); static time from_number(double number);
/// <summary> /// <summary>
/// Constructs a time object from an optional hour, minute, second, and microsecond. /// Constructs a time object from an optional hour, minute, second, and microsecond.
@ -62,7 +62,7 @@ struct XLNT_API time
/// Returns a numeric representation of the time in the range 0-1 where the value /// Returns a numeric representation of the time in the range 0-1 where the value
/// is equal to the fraction of the day elapsed. /// is equal to the fraction of the day elapsed.
/// </summary> /// </summary>
long double to_number() const; double to_number() const;
/// <summary> /// <summary>
/// Returns true if this time is equivalent to comparand. /// Returns true if this time is equivalent to comparand.

View File

@ -38,7 +38,7 @@ struct XLNT_API timedelta
/// <summary> /// <summary>
/// Returns a timedelta from a number representing the factional number of days elapsed. /// Returns a timedelta from a number representing the factional number of days elapsed.
/// </summary> /// </summary>
static timedelta from_number(long double number); static timedelta from_number(double number);
/// <summary> /// <summary>
/// Constructs a timedelta equal to zero. /// Constructs a timedelta equal to zero.
@ -53,7 +53,7 @@ struct XLNT_API timedelta
/// <summary> /// <summary>
/// Returns a numeric representation of this timedelta as a fractional number of days. /// Returns a numeric representation of this timedelta as a fractional number of days.
/// </summary> /// </summary>
long double to_number() const; double to_number() const;
/// <summary> /// <summary>
/// The days /// The days

View File

@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(xlnt.samples) project(xlnt.samples)
set(CMAKE_CXX_STANDARD 14) # Require C++11 compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT COMBINED_PROJECT) if(NOT COMBINED_PROJECT)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) # Include xlnt library
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source)
endif()
if(MSVC AND STATIC)
# Link with static C runtime
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ucm.cmake)
ucm_set_runtime(STATIC)
endif() endif()
set(XLNT_SAMPLE_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) set(XLNT_SAMPLE_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
@ -13,20 +21,24 @@ set(XLNT_SAMPLE_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
file(GLOB SAMPLE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) file(GLOB SAMPLE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(SAMPLE_SOURCE IN ITEMS ${SAMPLE_SOURCES}) foreach(SAMPLE_SOURCE IN ITEMS ${SAMPLE_SOURCES})
get_filename_component(SAMPLE_NAME ${SAMPLE_SOURCE} NAME_WE) # Convert <name>.cpp to sample-<name>
set(SAMPLE_EXECUTABLE sample-${SAMPLE_NAME}) get_filename_component(SAMPLE_NAME ${SAMPLE_SOURCE} NAME_WE)
set(SAMPLE_EXECUTABLE sample-${SAMPLE_NAME})
add_executable(${SAMPLE_EXECUTABLE} ${SAMPLE_SOURCE}) add_executable(${SAMPLE_EXECUTABLE} ${SAMPLE_SOURCE})
target_link_libraries(${SAMPLE_EXECUTABLE} PRIVATE xlnt) target_link_libraries(${SAMPLE_EXECUTABLE} PRIVATE xlnt)
target_include_directories(${SAMPLE_EXECUTABLE} # Need to use some test helpers
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests) target_include_directories(${SAMPLE_EXECUTABLE}
target_compile_definitions(${SAMPLE_EXECUTABLE} PRIVATE XLNT_SAMPLE_DATA_DIR=${XLNT_SAMPLE_DATA_DIR}) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../tests)
target_compile_definitions(${SAMPLE_EXECUTABLE}
PRIVATE XLNT_SAMPLE_DATA_DIR=${XLNT_SAMPLE_DATA_DIR})
if(MSVC AND NOT STATIC) if(MSVC AND NOT STATIC)
add_custom_command(TARGET ${SAMPLE_EXECUTABLE} POST_BUILD # Copy xlnt DLL into samples directory
COMMAND ${CMAKE_COMMAND} -E copy_if_different add_custom_command(TARGET ${SAMPLE_EXECUTABLE} POST_BUILD
$<TARGET_FILE:xlnt> COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE_DIR:${SAMPLE_EXECUTABLE}>) $<TARGET_FILE:xlnt>
endif() $<TARGET_FILE_DIR:${SAMPLE_EXECUTABLE}>)
endif()
endforeach() endforeach()

View File

@ -1,44 +1,61 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(xlnt VERSION 1.1) project(xlnt VERSION 1.2)
set(CMAKE_CXX_STANDARD 14) # Require C99 and C++11 compilers
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Project metadata
set(PROJECT_VENDOR "Thomas Fussell") set(PROJECT_VENDOR "Thomas Fussell")
set(PROJECT_CONTACT "thomas.fussell@gmail.com") set(PROJECT_CONTACT "thomas.fussell@gmail.com")
set(PROJECT_URL "https://github.com/tfussell/xlnt") set(PROJECT_URL "https://github.com/tfussell/xlnt")
set(PROJECT_DESCRIPTION "cross-platform user-friendly xlsx library for C++14") set(PROJECT_DESCRIPTION "cross-platform user-friendly xlsx library for C++11")
if(APPLE)
option(FRAMEWORK "Set to ON to package dylib and headers into a .framework, OSX only" OFF)
endif()
# Commonly used project directories
set(XLNT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..) set(XLNT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
set(XLNT_INCLUDE_DIR ${XLNT_ROOT_DIR}/include) set(XLNT_INCLUDE_DIR ${XLNT_ROOT_DIR}/include)
set(XLNT_SOURCE_DIR ${XLNT_ROOT_DIR}/source) set(XLNT_SOURCE_DIR ${XLNT_ROOT_DIR}/source)
set(THIRD_PARTY_DIR ${XLNT_ROOT_DIR}/third-party) set(THIRD_PARTY_DIR ${XLNT_ROOT_DIR}/third-party)
add_subdirectory(${THIRD_PARTY_DIR}/libstudxml ${CMAKE_CURRENT_BINARY_DIR}/third-party/libstudxml) # Include libstudxml library
add_subdirectory(${THIRD_PARTY_DIR}/libstudxml
${CMAKE_CURRENT_BINARY_DIR}/third-party/libstudxml)
if(COVERAGE) if(COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
endif() endif()
# Non-target-specific compiler settings
if(MSVC) if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") # level 4 warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") # multi-processor compilation
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # all warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unknown-pragmas") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") # extra warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") # ignore MSVC and Clang pragmas
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Werror -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Wno-documentation-unknown-command -Wno-unknown-pragmas") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything") # all warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") # warnings are errors
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++98-compat") # ignore warnings about C++98 compatibility
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++98-compat-pedantic") # ignore pedantic warnings about C++98 compatibility
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-padded") # ignore padding warnings
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-documentation-unknown-command") # ignore unknown commands in Javadoc-style comments
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") # ignore Windows and GCC pragmas
endif()
if(MSVC AND STATIC)
# Link with static C runtime
include(${XLNT_ROOT_DIR}/cmake/ucm.cmake)
ucm_set_runtime(STATIC)
endif() endif()
if(APPLE) if(APPLE)
# Prevent a warning about deployment target not being set # Prevent a warning about deployment target not being set by setting it to current OSX version
execute_process(COMMAND "sw_vers -productVersion | awk -F'.' '{print $1\".\"$2}'" execute_process(COMMAND "sw_vers -productVersion | awk -F'.' '{print $1\".\"$2}'"
OUTPUT_VARIABLE OSX_VERSION) OUTPUT_VARIABLE OSX_VERSION)
set(CMAKE_OSX_DEPLOYMENT_TARGET ${OSX_VERSION}) set(CMAKE_OSX_DEPLOYMENT_TARGET ${OSX_VERSION})
endif() endif()
file(GLOB ROOT_HEADERS ${XLNT_INCLUDE_DIR}/xlnt/*.hpp) file(GLOB ROOT_HEADERS ${XLNT_INCLUDE_DIR}/xlnt/*.hpp)
@ -78,99 +95,105 @@ file(GLOB DETAIL_SERIALIZATION_HEADERS ${XLNT_SOURCE_DIR}/detail/serialization/*
file(GLOB DETAIL_SERIALIZATION_SOURCES ${XLNT_SOURCE_DIR}/detail/serialization/*.cpp) file(GLOB DETAIL_SERIALIZATION_SOURCES ${XLNT_SOURCE_DIR}/detail/serialization/*.cpp)
set(DETAIL_HEADERS ${DETAIL_ROOT_HEADERS} ${DETAIL_CRYPTOGRAPHY_HEADERS} set(DETAIL_HEADERS ${DETAIL_ROOT_HEADERS} ${DETAIL_CRYPTOGRAPHY_HEADERS}
${DETAIL_EXTERNAL_HEADERS} ${DETAIL_HEADER_FOOTER_HEADERS} ${DETAIL_EXTERNAL_HEADERS} ${DETAIL_HEADER_FOOTER_HEADERS}
${DETAIL_IMPLEMENTATIONS_HEADERS} ${DETAIL_NUMBER_FORMAT_HEADERS} ${DETAIL_IMPLEMENTATIONS_HEADERS} ${DETAIL_NUMBER_FORMAT_HEADERS}
${DETAIL_SERIALIZATION_HEADERS}) ${DETAIL_SERIALIZATION_HEADERS})
set(DETAIL_SOURCES ${DETAIL_ROOT_SOURCES} ${DETAIL_CRYPTOGRAPHY_SOURCES} set(DETAIL_SOURCES ${DETAIL_ROOT_SOURCES} ${DETAIL_CRYPTOGRAPHY_SOURCES}
${DETAIL_EXTERNAL_SOURCES} ${DETAIL_HEADER_FOOTER_SOURCES} ${DETAIL_EXTERNAL_SOURCES} ${DETAIL_HEADER_FOOTER_SOURCES}
${DETAIL_IMPLEMENTATIONS_SOURCES} ${DETAIL_NUMBER_FORMAT_SOURCES} ${DETAIL_IMPLEMENTATIONS_SOURCES} ${DETAIL_NUMBER_FORMAT_SOURCES}
${DETAIL_SERIALIZATION_SOURCES}) ${DETAIL_SERIALIZATION_SOURCES})
set(XLNT_HEADERS ${ROOT_HEADERS} ${CELL_HEADERS} ${CHARTS_HEADERS} set(XLNT_HEADERS ${ROOT_HEADERS} ${CELL_HEADERS} ${CHARTS_HEADERS}
${CHARTSHEET_HEADERS} ${DRAWING_HEADERS} ${FORMULA_HEADERS} ${CHARTSHEET_HEADERS} ${DRAWING_HEADERS} ${FORMULA_HEADERS}
${PACKAGING_HEADERS} ${STYLES_HEADERS} ${UTILS_HEADERS} ${PACKAGING_HEADERS} ${STYLES_HEADERS} ${UTILS_HEADERS}
${WORKBOOK_HEADERS} ${WORKSHEET_HEADERS} ${DETAIL_HEADERS} ${DETAIL_CRYPTO_HEADERS}) ${WORKBOOK_HEADERS} ${WORKSHEET_HEADERS} ${DETAIL_HEADERS} ${DETAIL_CRYPTO_HEADERS})
set(XLNT_SOURCES ${CELL_SOURCES} ${CHARTS_SOURCES} ${CHARTSHEET_SOURCES} set(XLNT_SOURCES ${CELL_SOURCES} ${CHARTS_SOURCES} ${CHARTSHEET_SOURCES}
${DRAWING_SOURCES} ${FORMULA_SOURCES} ${PACKAGING_SOURCES} ${DRAWING_SOURCES} ${FORMULA_SOURCES} ${PACKAGING_SOURCES}
${STYLES_SOURCES} ${UTILS_SOURCES} ${WORKBOOK_SOURCES} ${STYLES_SOURCES} ${UTILS_SOURCES} ${WORKBOOK_SOURCES}
${WORKSHEET_SOURCES} ${DETAIL_SOURCES} ${DETAIL_CRYPTO_SOURCES}) ${WORKSHEET_SOURCES} ${DETAIL_SOURCES} ${DETAIL_CRYPTO_SOURCES})
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
if(MSVC) # Set a default CMAKE_INSTALL_PREFIX if one wasn't specified
set(DEFAULT_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/installed")
else()
set(DEFAULT_INSTALL_PREFIX "/usr/local")
endif()
set(CMAKE_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX} if(MSVC)
CACHE PATH "default install path" FORCE) # No good place to install on Windows so just install to cmake build directory in /installed
set(DEFAULT_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/installed")
else()
# Install to /usr/local on other platforms
set(DEFAULT_INSTALL_PREFIX "/usr/local")
endif()
# Apply the variable and save to cache
set(CMAKE_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX}
CACHE PATH "default install path" FORCE)
endif() endif()
if(NOT INC_DEST_DIR) # Append "d" to the name of the compiled library
set(INC_DEST_DIR ${CMAKE_INSTALL_PREFIX}/include) set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix")
endif()
if(NOT LIB_DEST_DIR)
set(LIB_DEST_DIR ${CMAKE_INSTALL_PREFIX}/lib)
endif()
if(NOT BIN_DEST_DIR)
set(BIN_DEST_DIR ${CMAKE_INSTALL_PREFIX}/bin)
endif()
if(NOT STATIC) if(NOT STATIC)
add_library(xlnt SHARED ${XLNT_HEADERS} ${XLNT_SOURCES} $<TARGET_OBJECTS:libstudxml>) # Compile shared library
target_compile_definitions(xlnt PRIVATE XLNT_SHARED=1) add_library(xlnt SHARED
${XLNT_HEADERS}
${XLNT_SOURCES}
$<TARGET_OBJECTS:libstudxml>)
if(MSVC) target_compile_definitions(xlnt PRIVATE XLNT_SHARED=1)
target_compile_definitions(xlnt PRIVATE XLNT_EXPORT=1 _CRT_SECURE_NO_WARNINGS=1)
endif()
set_target_properties(xlnt # Set SO version (for symbolic links like libxlnt.so.1.2 and libxlnt.so.1)
PROPERTIES set_target_properties(xlnt
VERSION ${PROJECT_VERSION} PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} VERSION ${PROJECT_VERSION}
INSTALL_NAME_DIR "${LIB_DEST_DIR}") SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
INSTALL_NAME_DIR "${LIB_DEST_DIR}")
if(FRAMEWORK)
add_custom_command(TARGET xlnt
POST_BUILD
COMMAND mkdir -p "${CMAKE_CURRENT_BINARY_DIR}/xlnt.framework/Versions/${PROJECT_VERSION_FULL}/Headers"
COMMAND cp -R ${XLNT_INCLUDE_DIR}/xlnt/* "${CMAKE_CURRENT_BINARY_DIR}/xlnt.framework/Versions/${PROJECT_VERSION_FULL}/Headers"
COMMAND cp "lib/lib${PROJECT_NAME}.${PROJECT_VERSION_FULL}.dylib" "${CMAKE_CURRENT_BINARY_DIR}/xlnt.framework/Versions/${PROJECT_VERSION_FULL}/xlnt"
COMMAND cd "${CMAKE_CURRENT_BINARY_DIR}/xlnt.framework/Versions" && ln -s "${PROJECT_VERSION_FULL}" Current
COMMAND cd "${CMAKE_CURRENT_BINARY_DIR}/xlnt.framework" && ln -s Versions/Current/* ./
)
endif()
else() else()
add_library(xlnt STATIC ${XLNT_HEADERS} ${XLNT_SOURCES} $<TARGET_OBJECTS:libstudxml>) # Compile static library
target_compile_definitions(xlnt PUBLIC XLNT_STATIC=1) add_library(xlnt STATIC ${XLNT_HEADERS} ${XLNT_SOURCES} $<TARGET_OBJECTS:libstudxml>)
target_compile_definitions(xlnt PUBLIC XLNT_STATIC=1)
if(MSVC)
target_compile_definitions(xlnt PRIVATE _CRT_SECURE_NO_WARNINGS=1)
endif()
endif() endif()
# Includes
target_include_directories(xlnt PUBLIC ${XLNT_INCLUDE_DIR}) target_include_directories(xlnt PUBLIC ${XLNT_INCLUDE_DIR})
target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}) target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR})
target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}/../third-party/libstudxml) target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}/../third-party/libstudxml)
target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}/../third-party/utfcpp) target_include_directories(xlnt PRIVATE ${XLNT_SOURCE_DIR}/../third-party/utfcpp)
# Platform- and file-specific settings, MSVC
if(MSVC) if(MSVC)
set_target_properties(xlnt PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\" /wd\"4068\" /MP") target_compile_definitions(xlnt PRIVATE _CRT_SECURE_NO_WARNINGS=1)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp PROPERTIES COMPILE_FLAGS "/wd\"4244\" /wd\"4334\" /wd\"4127\"")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/cryptography/aes.cpp PROPERTIES COMPILE_FLAGS "/wd\"4996\"") if(NOT STATIC)
target_compile_definitions(xlnt PRIVATE XLNT_EXPORT=1)
endif()
set_target_properties(xlnt PROPERTIES
COMPILE_FLAGS "/wd\"4251\" /wd\"4275\" /wd\"4068\"")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp
PROPERTIES
COMPILE_FLAGS "/wd\"4244\" /wd\"4334\" /wd\"4127\"")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/cryptography/aes.cpp
PROPERTIES
COMPILE_FLAGS "/wd\"4996\"")
endif() endif()
# Platform- and file-specific settings, Clang
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp PROPERTIES COMPILE_FLAGS "-Wno-undef") set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/zstream.cpp PROPERTIES COMPILE_FLAGS "-Wno-undef -Wno-shorten-64-to-32") PROPERTIES
COMPILE_FLAGS "-Wno-undef")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/zstream.cpp
PROPERTIES
COMPILE_FLAGS "-Wno-undef -Wno-shorten-64-to-32")
endif() endif()
# Platform- and file-specific settings, GCC
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp PROPERTIES COMPILE_FLAGS "-Wno-strict-aliasing") set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/detail/serialization/miniz.cpp
PROPERTIES
COMPILE_FLAGS "-Wno-strict-aliasing")
endif() endif()
# Group files into pseudo-folders in IDEs
source_group(xlnt FILES ${ROOT_HEADERS}) source_group(xlnt FILES ${ROOT_HEADERS})
source_group(cell FILES ${CELL_HEADERS} ${CELL_SOURCES}) source_group(cell FILES ${CELL_HEADERS} ${CELL_SOURCES})
source_group(detail FILES ${DETAIL_ROOT_HEADERS} ${DETAIL_ROOT_SOURCES}) source_group(detail FILES ${DETAIL_ROOT_HEADERS} ${DETAIL_ROOT_SOURCES})
@ -186,31 +209,63 @@ source_group(utils FILES ${UTILS_HEADERS} ${UTILS_SOURCES})
source_group(workbook FILES ${WORKBOOK_HEADERS} ${WORKBOOK_SOURCES}) source_group(workbook FILES ${WORKBOOK_HEADERS} ${WORKBOOK_SOURCES})
source_group(worksheet FILES ${WORKSHEET_HEADERS} ${WORKSHEET_SOURCES}) source_group(worksheet FILES ${WORKSHEET_HEADERS} ${WORKSHEET_SOURCES})
set(PKG_CONFIG_LIBDIR ${LIB_DEST_DIR}) if(NOT INC_DEST_DIR)
set(PKG_CONFIG_INCLUDEDIR ${INC_DEST_DIR}) # Default location to install include files
set(PKG_CONFIG_LIBS "-L\${libdir} -lxlnt") set(INC_DEST_DIR ${CMAKE_INSTALL_PREFIX}/include)
set(PKG_CONFIG_CFLAGS "-I\${includedir}")
install(TARGETS xlnt
LIBRARY DESTINATION ${LIB_DEST_DIR}
ARCHIVE DESTINATION ${LIB_DEST_DIR}
RUNTIME DESTINATION ${BIN_DEST_DIR})
if(NOT MSVC)
configure_file("${XLNT_ROOT_DIR}/cmake/pkg-config.pc.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/xlnt.pc")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/xlnt.pc"
DESTINATION ${LIB_DEST_DIR}/pkgconfig)
endif() endif()
if(NOT LIB_DEST_DIR)
# Default location to install library files
set(LIB_DEST_DIR ${CMAKE_INSTALL_PREFIX}/lib)
endif()
if(NOT BIN_DEST_DIR)
# Default location to install runtime files
set(BIN_DEST_DIR ${CMAKE_INSTALL_PREFIX}/bin)
endif()
if(NOT MAN_DEST_DIR)
# Default location to install runtime files
set(MAN_DEST_DIR ${CMAKE_INSTALL_PREFIX}/share/man)
endif()
# Install library
install(TARGETS xlnt
LIBRARY DESTINATION ${LIB_DEST_DIR}
ARCHIVE DESTINATION ${LIB_DEST_DIR}
RUNTIME DESTINATION ${BIN_DEST_DIR})
# Install include directory
install(DIRECTORY ${XLNT_INCLUDE_DIR}/xlnt install(DIRECTORY ${XLNT_INCLUDE_DIR}/xlnt
DESTINATION include DESTINATION include
PATTERN ".DS_Store" EXCLUDE) PATTERN ".DS_Store" EXCLUDE)
# Install LICENSE.md
install(FILES ${XLNT_ROOT_DIR}/docs/xlnt.3
DESTINATION ${MAN_DEST_DIR}/man3)
# Configure uninstall
configure_file("${XLNT_ROOT_DIR}/cmake/cmake_uninstall.cmake.in" configure_file("${XLNT_ROOT_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY) IMMEDIATE @ONLY)
# Add uninstall target
add_custom_target(uninstall add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
if(NOT MSVC)
# Set pkg-config variables
set(PKG_CONFIG_LIBDIR ${LIB_DEST_DIR})
set(PKG_CONFIG_INCLUDEDIR ${INC_DEST_DIR})
set(PKG_CONFIG_LIBS "-L\${libdir} -lxlnt")
set(PKG_CONFIG_CFLAGS "-I\${includedir}")
# Replace variables in pkg-config template
configure_file("${XLNT_ROOT_DIR}/cmake/pkg-config.pc.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/xlnt.pc")
# pkg-config install
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/xlnt.pc"
DESTINATION ${LIB_DEST_DIR}/pkgconfig)
endif()

View File

@ -29,6 +29,7 @@
#include <detail/implementations/cell_impl.hpp> #include <detail/implementations/cell_impl.hpp>
#include <detail/implementations/format_impl.hpp> #include <detail/implementations/format_impl.hpp>
#include <detail/implementations/stylesheet.hpp> #include <detail/implementations/stylesheet.hpp>
#include <detail/implementations/worksheet_impl.hpp>
#include <xlnt/cell/cell.hpp> #include <xlnt/cell/cell.hpp>
#include <xlnt/cell/cell_reference.hpp> #include <xlnt/cell/cell_reference.hpp>
#include <xlnt/cell/comment.hpp> #include <xlnt/cell/comment.hpp>
@ -55,17 +56,17 @@
namespace { namespace {
std::pair<bool, long double> cast_numeric(const std::string &s) std::pair<bool, double> cast_numeric(const std::string &s)
{ {
auto str_end = static_cast<char *>(nullptr); auto str_end = static_cast<char *>(nullptr);
auto result = std::strtold(s.c_str(), &str_end); auto result = std::strtod(s.c_str(), &str_end);
return (str_end != s.c_str() + s.size()) return (str_end != s.c_str() + s.size())
? std::make_pair(false, 0.0L) ? std::make_pair(false, 0.0)
: std::make_pair(true, result); : std::make_pair(true, result);
} }
std::pair<bool, long double> cast_percentage(const std::string &s) std::pair<bool, double> cast_percentage(const std::string &s)
{ {
if (s.back() == '%') if (s.back() == '%')
{ {
@ -77,7 +78,7 @@ std::pair<bool, long double> cast_percentage(const std::string &s)
} }
} }
return {false, 0}; return {false, 0.0};
} }
std::pair<bool, xlnt::time> cast_time(const std::string &s) std::pair<bool, xlnt::time> cast_time(const std::string &s)
@ -205,48 +206,42 @@ void cell::value(std::nullptr_t)
void cell::value(bool boolean_value) void cell::value(bool boolean_value)
{ {
d_->type_ = type::boolean; d_->type_ = type::boolean;
d_->value_numeric_ = boolean_value ? 1.0L : 0.0L; d_->value_numeric_ = boolean_value ? 1.0 : 0.0;
} }
void cell::value(int int_value) void cell::value(int int_value)
{ {
d_->value_numeric_ = static_cast<long double>(int_value); d_->value_numeric_ = static_cast<double>(int_value);
d_->type_ = type::number; d_->type_ = type::number;
} }
void cell::value(unsigned int int_value) void cell::value(unsigned int int_value)
{ {
d_->value_numeric_ = static_cast<long double>(int_value); d_->value_numeric_ = static_cast<double>(int_value);
d_->type_ = type::number; d_->type_ = type::number;
} }
void cell::value(long long int int_value) void cell::value(long long int int_value)
{ {
d_->value_numeric_ = static_cast<long double>(int_value); d_->value_numeric_ = static_cast<double>(int_value);
d_->type_ = type::number; d_->type_ = type::number;
} }
void cell::value(unsigned long long int int_value) void cell::value(unsigned long long int int_value)
{ {
d_->value_numeric_ = static_cast<long double>(int_value); d_->value_numeric_ = static_cast<double>(int_value);
d_->type_ = type::number; d_->type_ = type::number;
} }
void cell::value(float float_value) void cell::value(float float_value)
{ {
d_->value_numeric_ = static_cast<long double>(float_value); d_->value_numeric_ = static_cast<double>(float_value);
d_->type_ = type::number; d_->type_ = type::number;
} }
void cell::value(double float_value) void cell::value(double float_value)
{ {
d_->value_numeric_ = static_cast<long double>(float_value); d_->value_numeric_ = static_cast<double>(float_value);
d_->type_ = type::number;
}
void cell::value(long double d)
{
d_->value_numeric_ = d;
d_->type_ = type::number; d_->type_ = type::number;
} }
@ -260,7 +255,7 @@ void cell::value(const rich_text &text)
check_string(text.plain_text()); check_string(text.plain_text());
d_->type_ = type::shared_string; d_->type_ = type::shared_string;
d_->value_numeric_ = static_cast<long double>(workbook().add_shared_string(text)); d_->value_numeric_ = static_cast<double>(workbook().add_shared_string(text));
} }
void cell::value(const char *c) void cell::value(const char *c)
@ -534,7 +529,7 @@ void cell::clear_value()
template <> template <>
XLNT_API bool cell::value() const XLNT_API bool cell::value() const
{ {
return d_->value_numeric_ != 0.L; return d_->value_numeric_ != 0.0;
} }
template <> template <>
@ -573,12 +568,6 @@ XLNT_API double cell::value() const
return static_cast<double>(d_->value_numeric_); return static_cast<double>(d_->value_numeric_);
} }
template <>
XLNT_API long double cell::value() const
{
return d_->value_numeric_;
}
template <> template <>
XLNT_API time cell::value() const XLNT_API time cell::value() const
{ {
@ -671,14 +660,14 @@ std::string cell::to_string() const
return ""; return "";
case cell::type::date: case cell::type::date:
case cell::type::number: case cell::type::number:
return nf.format(value<long double>(), base_date()); return nf.format(value<double>(), base_date());
case cell::type::inline_string: case cell::type::inline_string:
case cell::type::shared_string: case cell::type::shared_string:
case cell::type::formula_string: case cell::type::formula_string:
case cell::type::error: case cell::type::error:
return nf.format(value<std::string>()); return nf.format(value<std::string>());
case cell::type::boolean: case cell::type::boolean:
return value<long double>() == 0.L ? "FALSE" : "TRUE"; return value<double>() == 0.0 ? "FALSE" : "TRUE";
} }
return ""; return "";
@ -878,7 +867,11 @@ bool cell::has_comment()
void cell::clear_comment() void cell::clear_comment()
{ {
d_->comment_.clear(); if (has_comment())
{
d_->parent_->comments_.erase(reference().to_string());
d_->comment_.clear();
}
} }
class comment cell::comment() class comment cell::comment()
@ -888,7 +881,7 @@ class comment cell::comment()
throw xlnt::exception("cell has no comment"); throw xlnt::exception("cell has no comment");
} }
return d_->comment_.get(); return *d_->comment_.get();
} }
void cell::comment(const std::string &text, const std::string &author) void cell::comment(const std::string &text, const std::string &author)
@ -904,15 +897,23 @@ void cell::comment(const std::string &text, const class font &comment_font, cons
void cell::comment(const class comment &new_comment) void cell::comment(const class comment &new_comment)
{ {
d_->comment_.set(new_comment); if (has_comment())
{
*d_->comment_.get() = new_comment;
}
else
{
d_->parent_->comments_[reference().to_string()] = new_comment;
d_->comment_.set(&d_->parent_->comments_[reference().to_string()]);
}
// offset comment 5 pixels down and 5 pixels right of the top right corner of the cell // offset comment 5 pixels down and 5 pixels right of the top right corner of the cell
auto cell_position = anchor(); auto cell_position = anchor();
cell_position.first += static_cast<int>(width()) + 5; cell_position.first += static_cast<int>(width()) + 5;
cell_position.second += 5; cell_position.second += 5;
d_->comment_.get().position(cell_position.first, cell_position.second); d_->comment_.get()->position(cell_position.first, cell_position.second);
d_->comment_.get().size(200, 100); d_->comment_.get()->size(200, 100);
worksheet().register_comments_in_manifest(); worksheet().register_comments_in_manifest();
} }

View File

@ -122,7 +122,7 @@ std::pair<std::string, row_t> cell_reference::split_reference(
for (auto character : reference_string) for (auto character : reference_string)
{ {
char upper = std::toupper(character); auto upper = static_cast<char>(std::toupper(static_cast<std::uint8_t>(character)));
if (std::isalpha(character)) if (std::isalpha(character))
{ {

View File

@ -21,6 +21,10 @@
// @license: http://www.opensource.org/licenses/mit-license.php // @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file // @author: see AUTHORS file
// Adapted from LibTomCrypt AES implementation
// https://github.com/libtom/libtomcrypt/blob/develop/src/ciphers/aes/aes_tab.c
// https://github.com/libtom/libtomcrypt/blob/develop/src/ciphers/aes/aes.c
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <assert.h> #include <assert.h>

View File

@ -113,7 +113,7 @@ public:
compound_document_istreambuf(const compound_document_istreambuf &) = delete; compound_document_istreambuf(const compound_document_istreambuf &) = delete;
compound_document_istreambuf &operator=(const compound_document_istreambuf &) = delete; compound_document_istreambuf &operator=(const compound_document_istreambuf &) = delete;
virtual ~compound_document_istreambuf(); ~compound_document_istreambuf() override;
private: private:
std::streamsize xsgetn(char *c, std::streamsize count) override std::streamsize xsgetn(char *c, std::streamsize count) override
@ -326,7 +326,7 @@ public:
compound_document_ostreambuf(const compound_document_ostreambuf &) = delete; compound_document_ostreambuf(const compound_document_ostreambuf &) = delete;
compound_document_ostreambuf &operator=(const compound_document_ostreambuf &) = delete; compound_document_ostreambuf &operator=(const compound_document_ostreambuf &) = delete;
virtual ~compound_document_ostreambuf(); ~compound_document_ostreambuf() override;
private: private:
int sync() override int sync() override

View File

@ -283,18 +283,18 @@ encryption_info read_encryption_info(std::istream &info_stream, const std::u16st
throw xlnt::exception("unsupported encryption version"); throw xlnt::exception("unsupported encryption version");
} }
if ((encryption_flags & 0b00000011) != 0) // Reserved1 and Reserved2, MUST be 0 if ((encryption_flags & 0x03) != 0) // Reserved1 and Reserved2, MUST be 0
{ {
throw xlnt::exception("bad header"); throw xlnt::exception("bad header");
} }
if ((encryption_flags & 0b00000100) == 0 // fCryptoAPI if ((encryption_flags & 0x04) == 0 // fCryptoAPI
|| (encryption_flags & 0b00010000) != 0) // fExternal || (encryption_flags & 0x10) != 0) // fExternal
{ {
throw xlnt::exception("extensible encryption is not supported"); throw xlnt::exception("extensible encryption is not supported");
} }
if ((encryption_flags & 0b00100000) == 0) // fAES if ((encryption_flags & 0x20) == 0) // fAES
{ {
throw xlnt::exception("not an OOXML document"); throw xlnt::exception("not an OOXML document");
} }

View File

@ -181,7 +181,7 @@ void write_standard_encryption_info(const encryption_info &info, std::ostream &i
const auto version_major = std::uint16_t(4); const auto version_major = std::uint16_t(4);
const auto version_minor = std::uint16_t(2); const auto version_minor = std::uint16_t(2);
const auto encryption_flags = std::uint32_t(0b00010000 & 0b00100000); const auto encryption_flags = std::uint32_t(0x10 & 0x20);
writer.write(version_major); writer.write(version_major);
writer.write(version_minor); writer.write(version_minor);

View File

@ -51,12 +51,12 @@ struct cell_impl
bool is_merged_; bool is_merged_;
rich_text value_text_; rich_text value_text_;
long double value_numeric_; double value_numeric_;
optional<std::string> formula_; optional<std::string> formula_;
optional<std::string> hyperlink_; optional<std::string> hyperlink_;
optional<format_impl *> format_; optional<format_impl *> format_;
optional<comment> comment_; optional<comment *> comment_;
}; };
} // namespace detail } // namespace detail

View File

@ -115,6 +115,8 @@ struct worksheet_impl
std::vector<column_t> column_breaks_; std::vector<column_t> column_breaks_;
std::vector<row_t> row_breaks_; std::vector<row_t> row_breaks_;
std::unordered_map<std::string, comment> comments_;
}; };
} // namespace detail } // namespace detail

View File

@ -83,7 +83,7 @@ void unhandled_case(bool error)
namespace xlnt { namespace xlnt {
namespace detail { namespace detail {
bool format_condition::satisfied_by(long double number) const bool format_condition::satisfied_by(double number) const
{ {
switch (type) switch (type)
{ {
@ -96,9 +96,9 @@ bool format_condition::satisfied_by(long double number) const
case condition_type::less_than: case condition_type::less_than:
return number < value; return number < value;
case condition_type::not_equal: case condition_type::not_equal:
return std::fabs(number - value) != 0.0L; return std::fabs(number - value) != 0.0;
case condition_type::equal: case condition_type::equal:
return std::fabs(number - value) == 0.0L; return std::fabs(number - value) == 0.0;
} }
default_case(false); default_case(false);
@ -221,7 +221,7 @@ void number_format_parser::parse()
value = token.string.substr(1); value = token.string.substr(1);
} }
section.condition.value = std::stold(value); section.condition.value = std::stod(value);
break; break;
} }
@ -1075,7 +1075,7 @@ number_formatter::number_formatter(const std::string &format_string, xlnt::calen
format_ = parser_.result(); format_ = parser_.result();
} }
std::string number_formatter::format_number(long double number) std::string number_formatter::format_number(double number)
{ {
if (format_[0].has_condition) if (format_[0].has_condition)
{ {
@ -1154,7 +1154,7 @@ std::string number_formatter::format_text(const std::string &text)
return format_text(format_[3], text); return format_text(format_[3], text);
} }
std::string number_formatter::fill_placeholders(const format_placeholders &p, long double number) std::string number_formatter::fill_placeholders(const format_placeholders &p, double number)
{ {
std::string result; std::string result;
@ -1230,7 +1230,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
else if (p.type == format_placeholders::placeholders_type::fractional_part) else if (p.type == format_placeholders::placeholders_type::fractional_part)
{ {
auto fractional_part = number - integer_part; auto fractional_part = number - integer_part;
result = std::fabs(fractional_part) < std::numeric_limits<long double>::min() result = std::fabs(fractional_part) < std::numeric_limits<double>::min()
? std::string(".") ? std::string(".")
: std::to_string(fractional_part).substr(1); : std::to_string(fractional_part).substr(1);
@ -1259,11 +1259,11 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
} }
std::string number_formatter::fill_scientific_placeholders(const format_placeholders &integer_part, std::string number_formatter::fill_scientific_placeholders(const format_placeholders &integer_part,
const format_placeholders &fractional_part, const format_placeholders &exponent_part, long double number) const format_placeholders &fractional_part, const format_placeholders &exponent_part, double number)
{ {
std::size_t logarithm = 0; std::size_t logarithm = 0;
if (number != 0.L) if (number != 0.0)
{ {
logarithm = static_cast<std::size_t>(std::log10(number)); logarithm = static_cast<std::size_t>(std::log10(number));
@ -1280,7 +1280,7 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol
std::string integer_string = std::to_string(integer); std::string integer_string = std::to_string(integer);
if (number == 0.L) if (number == 0.0)
{ {
integer_string = std::string(integer_part.num_zeros + integer_part.num_optionals, '0'); integer_string = std::string(integer_part.num_zeros + integer_part.num_optionals, '0');
} }
@ -1312,14 +1312,14 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol
} }
std::string number_formatter::fill_fraction_placeholders(const format_placeholders & /*numerator*/, std::string number_formatter::fill_fraction_placeholders(const format_placeholders & /*numerator*/,
const format_placeholders &denominator, long double number, bool /*improper*/) const format_placeholders &denominator, double number, bool /*improper*/)
{ {
auto fractional_part = number - static_cast<int>(number); auto fractional_part = number - static_cast<int>(number);
auto original_fractional_part = fractional_part; auto original_fractional_part = fractional_part;
fractional_part *= 10; fractional_part *= 10;
while (std::abs(fractional_part - static_cast<int>(fractional_part)) > 0.000001L while (std::abs(fractional_part - static_cast<int>(fractional_part)) > 0.000001
&& std::abs(fractional_part - static_cast<int>(fractional_part)) < 0.999999L) && std::abs(fractional_part - static_cast<int>(fractional_part)) < 0.999999)
{ {
fractional_part *= 10; fractional_part *= 10;
} }
@ -1331,13 +1331,13 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde
auto lower = static_cast<int>(std::pow(10, denominator_digits - 1)); auto lower = static_cast<int>(std::pow(10, denominator_digits - 1));
auto upper = static_cast<int>(std::pow(10, denominator_digits)); auto upper = static_cast<int>(std::pow(10, denominator_digits));
auto best_denominator = lower; auto best_denominator = lower;
auto best_difference = 1000.0L; auto best_difference = 1000.0;
for (int i = lower; i < upper; ++i) for (int i = lower; i < upper; ++i)
{ {
auto numerator_full = original_fractional_part * i; auto numerator_full = original_fractional_part * i;
auto numerator_rounded = static_cast<int>(std::round(numerator_full)); auto numerator_rounded = static_cast<int>(std::round(numerator_full));
auto difference = std::fabs(original_fractional_part - (numerator_rounded / static_cast<long double>(i))); auto difference = std::fabs(original_fractional_part - (numerator_rounded / static_cast<double>(i)));
if (difference < best_difference) if (difference < best_difference)
{ {
@ -1350,7 +1350,7 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde
return std::to_string(numerator_rounded) + "/" + std::to_string(best_denominator); return std::to_string(numerator_rounded) + "/" + std::to_string(best_denominator);
} }
std::string number_formatter::format_number(const format_code &format, long double number) std::string number_formatter::format_number(const format_code &format, double number)
{ {
static const std::vector<std::string> *month_names = new std::vector<std::string>{"January", "February", "March", static const std::vector<std::string> *month_names = new std::vector<std::string>{"January", "February", "March",
"April", "May", "June", "July", "August", "September", "October", "November", "December"}; "April", "May", "June", "July", "August", "September", "October", "November", "December"};
@ -1377,7 +1377,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
if (format.is_datetime) if (format.is_datetime)
{ {
if (number != 0.L) if (number != 0.0)
{ {
dt = xlnt::datetime::from_number(number, calendar_); dt = xlnt::datetime::from_number(number, calendar_);
} }
@ -1434,7 +1434,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
auto digits = std::min( auto digits = std::min(
static_cast<std::size_t>(6), part.placeholders.num_zeros + part.placeholders.num_optionals); static_cast<std::size_t>(6), part.placeholders.num_zeros + part.placeholders.num_optionals);
auto denominator = static_cast<int>(std::pow(10.0, digits)); auto denominator = static_cast<int>(std::pow(10.0, digits));
auto fractional_seconds = dt.microsecond / 1.0E6L * denominator; auto fractional_seconds = dt.microsecond / 1.0E6 * denominator;
fractional_seconds = std::round(fractional_seconds) / denominator; fractional_seconds = std::round(fractional_seconds) / denominator;
result.append(fill_placeholders(part.placeholders, fractional_seconds)); result.append(fill_placeholders(part.placeholders, fractional_seconds));
break; break;
@ -1449,7 +1449,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
{ {
i += 2; i += 2;
if (number == 0.L) if (number == 0.0)
{ {
result.pop_back(); result.pop_back();
break; break;

View File

@ -222,9 +222,9 @@ struct XLNT_API format_condition
greater_or_equal greater_or_equal
} type = condition_type::not_equal; } type = condition_type::not_equal;
long double value = 0; double value = 0.0;
bool satisfied_by(long double number) const; bool satisfied_by(double number) const;
}; };
struct format_placeholders struct format_placeholders
@ -352,17 +352,17 @@ class XLNT_API number_formatter
{ {
public: public:
number_formatter(const std::string &format_string, xlnt::calendar calendar); number_formatter(const std::string &format_string, xlnt::calendar calendar);
std::string format_number(long double number); std::string format_number(double number);
std::string format_text(const std::string &text); std::string format_text(const std::string &text);
private: private:
std::string fill_placeholders(const format_placeholders &p, long double number); std::string fill_placeholders(const format_placeholders &p, double number);
std::string fill_fraction_placeholders(const format_placeholders &numerator, std::string fill_fraction_placeholders(const format_placeholders &numerator,
const format_placeholders &denominator, long double number, bool improper); const format_placeholders &denominator, double number, bool improper);
std::string fill_scientific_placeholders(const format_placeholders &integer_part, std::string fill_scientific_placeholders(const format_placeholders &integer_part,
const format_placeholders &fractional_part, const format_placeholders &exponent_part, const format_placeholders &fractional_part, const format_placeholders &exponent_part,
long double number); double number);
std::string format_number(const format_code &format, long double number); std::string format_number(const format_code &format, double number);
std::string format_text(const format_code &format, const std::string &text); std::string format_text(const format_code &format, const std::string &text);
number_format_parser parser_; number_format_parser parser_;

View File

@ -57,18 +57,29 @@ mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
{ {
for (i = 0; i + 7 < block_len; i += 8, ptr += 8) for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
{ {
s1 += ptr[0], s2 += s1; s1 += ptr[0];
s1 += ptr[1], s2 += s1; s2 += s1;
s1 += ptr[2], s2 += s1; s1 += ptr[1];
s1 += ptr[3], s2 += s1; s2 += s1;
s1 += ptr[4], s2 += s1; s1 += ptr[2];
s1 += ptr[5], s2 += s1; s2 += s1;
s1 += ptr[6], s2 += s1; s1 += ptr[3];
s1 += ptr[7], s2 += s1; s2 += s1;
s1 += ptr[4];
s2 += s1;
s1 += ptr[5];
s2 += s1;
s1 += ptr[6];
s2 += s1;
s1 += ptr[7];
s2 += s1;
} }
for (; i < block_len; ++i) for (; i < block_len; ++i) {
s1 += *ptr++, s2 += s1; s1 += *ptr++;
s1 %= 65521U, s2 %= 65521U; s2 += s1;
}
s1 %= 65521U;
s2 %= 65521U;
buf_len -= block_len; buf_len -= block_len;
block_len = 5552; block_len = 5552;
} }
@ -208,7 +219,7 @@ int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
pStream->data_type = 0; pStream->data_type = 0;
pStream->adler = MZ_ADLER32_INIT; pStream->adler = MZ_ADLER32_INIT;
pStream->msg = NULL; pStream->msg = nullptr;
pStream->reserved = 0; pStream->reserved = 0;
pStream->total_in = 0; pStream->total_in = 0;
pStream->total_out = 0; pStream->total_out = 0;
@ -223,7 +234,7 @@ int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
pStream->state = (struct mz_internal_state *)pComp; pStream->state = (struct mz_internal_state *)pComp;
if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) if (tdefl_init(pComp, nullptr, nullptr, comp_flags) != TDEFL_STATUS_OKAY)
{ {
mz_deflateEnd(pStream); mz_deflateEnd(pStream);
return MZ_PARAM_ERROR; return MZ_PARAM_ERROR;
@ -237,7 +248,7 @@ int mz_deflateReset(mz_streamp pStream)
if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
return MZ_STREAM_ERROR; return MZ_STREAM_ERROR;
pStream->total_in = pStream->total_out = 0; pStream->total_in = pStream->total_out = 0;
tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags); tdefl_init((tdefl_compressor *)pStream->state, nullptr, nullptr, ((tdefl_compressor *)pStream->state)->m_flags);
return MZ_OK; return MZ_OK;
} }
@ -306,7 +317,7 @@ int mz_deflateEnd(mz_streamp pStream)
if (pStream->state) if (pStream->state)
{ {
pStream->zfree(pStream->opaque, pStream->state); pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL; pStream->state = nullptr;
} }
return MZ_OK; return MZ_OK;
} }
@ -355,7 +366,7 @@ int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *
mz_ulong mz_compressBound(mz_ulong source_len) mz_ulong mz_compressBound(mz_ulong source_len)
{ {
return mz_deflateBound(NULL, source_len); return mz_deflateBound(nullptr, source_len);
} }
typedef struct typedef struct
@ -377,7 +388,7 @@ int mz_inflateInit2(mz_streamp pStream, int window_bits)
pStream->data_type = 0; pStream->data_type = 0;
pStream->adler = 0; pStream->adler = 0;
pStream->msg = NULL; pStream->msg = nullptr;
pStream->total_in = 0; pStream->total_in = 0;
pStream->total_out = 0; pStream->total_out = 0;
pStream->reserved = 0; pStream->reserved = 0;
@ -527,7 +538,7 @@ int mz_inflateEnd(mz_streamp pStream)
if (pStream->state) if (pStream->state)
{ {
pStream->zfree(pStream->opaque, pStream->state); pStream->zfree(pStream->opaque, pStream->state);
pStream->state = NULL; pStream->state = nullptr;
} }
return MZ_OK; return MZ_OK;
} }
@ -577,7 +588,7 @@ const char *mz_error(int err)
for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
if (s_error_descs[i].m_err == err) if (s_error_descs[i].m_err == err)
return s_error_descs[i].m_pDesc; return s_error_descs[i].m_pDesc;
return NULL; return nullptr;
} }
#endif /*MINIZ_NO_ZLIB_APIS */ #endif /*MINIZ_NO_ZLIB_APIS */
@ -1221,7 +1232,7 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
mz_uint8 *pSaved_output_buf; mz_uint8 *pSaved_output_buf;
mz_bool comp_block_succeeded = MZ_FALSE; mz_bool comp_block_succeeded = MZ_FALSE;
int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == nullptr) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
d->m_pOutput_buf = pOutput_buf_start; d->m_pOutput_buf = pOutput_buf_start;
d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
@ -1254,7 +1265,8 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
{ {
mz_uint i; mz_uint i;
d->m_pOutput_buf = pSaved_output_buf; d->m_pOutput_buf = pSaved_output_buf;
d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; d->m_bit_buffer = saved_bit_buf;
d->m_bits_in = saved_bits_in;
TDEFL_PUT_BITS(0, 2); TDEFL_PUT_BITS(0, 2);
if (d->m_bits_in) if (d->m_bits_in)
{ {
@ -1273,7 +1285,8 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
else if (!comp_block_succeeded) else if (!comp_block_succeeded)
{ {
d->m_pOutput_buf = pSaved_output_buf; d->m_pOutput_buf = pSaved_output_buf;
d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; d->m_bit_buffer = saved_bit_buf;
d->m_bits_in = saved_bits_in;
tdefl_compress_block(d, MZ_TRUE); tdefl_compress_block(d, MZ_TRUE);
} }
@ -1287,7 +1300,8 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
} }
if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
{ {
mz_uint i, a = d->m_adler32; mz_uint i;
mz_uint a = d->m_adler32;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
@ -1297,7 +1311,8 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
} }
else else
{ {
mz_uint i, z = 0; mz_uint i;
mz_uint z = 0;
TDEFL_PUT_BITS(0, 3); TDEFL_PUT_BITS(0, 3);
if (d->m_bits_in) if (d->m_bits_in)
{ {
@ -1850,7 +1865,7 @@ tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pI
d->m_out_buf_ofs = 0; d->m_out_buf_ofs = 0;
d->m_flush = flush; d->m_flush = flush;
if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || if (((d->m_pPut_buf_func != nullptr) == ((pOut_buf != nullptr) || (pOut_buf_size != nullptr))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
(d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
{ {
if (pIn_buf_size) if (pIn_buf_size)
@ -1901,7 +1916,7 @@ tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pI
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
{ {
MZ_ASSERT(d->m_pPut_buf_func); MZ_ASSERT(d->m_pPut_buf_func);
return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); return tdefl_compress(d, pIn_buf, &in_buf_size, nullptr, nullptr, flush);
} }
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
@ -1924,12 +1939,12 @@ tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_fun
d->m_prev_return_status = TDEFL_STATUS_OKAY; d->m_prev_return_status = TDEFL_STATUS_OKAY;
d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
d->m_adler32 = 1; d->m_adler32 = 1;
d->m_pIn_buf = NULL; d->m_pIn_buf = nullptr;
d->m_pOut_buf = NULL; d->m_pOut_buf = nullptr;
d->m_pIn_buf_size = NULL; d->m_pIn_buf_size = nullptr;
d->m_pOut_buf_size = NULL; d->m_pOut_buf_size = nullptr;
d->m_flush = TDEFL_NO_FLUSH; d->m_flush = TDEFL_NO_FLUSH;
d->m_pSrc = NULL; d->m_pSrc = nullptr;
d->m_src_buf_left = 0; d->m_src_buf_left = 0;
d->m_out_buf_ofs = 0; d->m_out_buf_ofs = 0;
memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
@ -1999,12 +2014,12 @@ void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_
tdefl_output_buffer out_buf; tdefl_output_buffer out_buf;
MZ_CLEAR_OBJ(out_buf); MZ_CLEAR_OBJ(out_buf);
if (!pOut_len) if (!pOut_len)
return MZ_FALSE; return nullptr; //MZ_FALSE;
else else
*pOut_len = 0; *pOut_len = 0;
out_buf.m_expandable = MZ_TRUE; out_buf.m_expandable = MZ_TRUE;
if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
return NULL; return nullptr;
*pOut_len = out_buf.m_size; *pOut_len = out_buf.m_size;
return out_buf.m_pBuf; return out_buf.m_pBuf;
} }
@ -2063,14 +2078,14 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int
mz_uint32 c; mz_uint32 c;
*pLen_out = 0; *pLen_out = 0;
if (!pComp) if (!pComp)
return NULL; return nullptr;
MZ_CLEAR_OBJ(out_buf); MZ_CLEAR_OBJ(out_buf);
out_buf.m_expandable = MZ_TRUE; out_buf.m_expandable = MZ_TRUE;
out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) if (nullptr == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
{ {
MZ_FREE(pComp); MZ_FREE(pComp);
return NULL; return nullptr;
} }
/* write dummy header */ /* write dummy header */
for (z = 41; z; --z) for (z = 41; z; --z)
@ -2082,11 +2097,11 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int
tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
} }
if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) if (tdefl_compress_buffer(pComp, nullptr, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
{ {
MZ_FREE(pComp); MZ_FREE(pComp);
MZ_FREE(out_buf.m_pBuf); MZ_FREE(out_buf.m_pBuf);
return NULL; return nullptr;
} }
/* write real header */ /* write real header */
*pLen_out = out_buf.m_size - 41; *pLen_out = out_buf.m_size - 41;
@ -2121,7 +2136,7 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int
*pLen_out = 0; *pLen_out = 0;
MZ_FREE(pComp); MZ_FREE(pComp);
MZ_FREE(out_buf.m_pBuf); MZ_FREE(out_buf.m_pBuf);
return NULL; return nullptr;
} }
c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
for (i = 0; i < 4; ++i, c <<= 8) for (i = 0; i < 4; ++i, c <<= 8)
@ -2472,7 +2487,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
MZ_CLEAR_OBJ(pTable->m_tree); MZ_CLEAR_OBJ(pTable->m_tree);
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
total_syms[pTable->m_code_size[i]]++; total_syms[pTable->m_code_size[i]]++;
used_syms = 0, total = 0; used_syms = 0;
total = 0;
next_code[0] = next_code[1] = 0; next_code[0] = next_code[1] = 0;
for (i = 1; i <= 15; ++i) for (i = 1; i <= 15; ++i)
{ {
@ -2776,18 +2792,29 @@ common_exit:
{ {
for (i = 0; i + 7 < block_len; i += 8, ptr += 8) for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
{ {
s1 += ptr[0], s2 += s1; s1 += ptr[0];
s1 += ptr[1], s2 += s1; s2 += s1;
s1 += ptr[2], s2 += s1; s1 += ptr[1];
s1 += ptr[3], s2 += s1; s2 += s1;
s1 += ptr[4], s2 += s1; s1 += ptr[2];
s1 += ptr[5], s2 += s1; s2 += s1;
s1 += ptr[6], s2 += s1; s1 += ptr[3];
s1 += ptr[7], s2 += s1; s2 += s1;
s1 += ptr[4];
s2 += s1;
s1 += ptr[5];
s2 += s1;
s1 += ptr[6];
s2 += s1;
s1 += ptr[7];
s2 += s1;
} }
for (; i < block_len; ++i) for (; i < block_len; ++i) {
s1 += *ptr++, s2 += s1; s1 += *ptr++;
s1 %= 65521U, s2 %= 65521U; s2 += s1;
}
s1 %= 65521U;
s2 %= 65521U;
buf_len -= block_len; buf_len -= block_len;
block_len = 5552; block_len = 5552;
} }
@ -2802,20 +2829,20 @@ common_exit:
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
{ {
tinfl_decompressor decomp; tinfl_decompressor decomp;
void *pBuf = NULL, *pNew_buf; void *pBuf = nullptr, *pNew_buf;
size_t src_buf_ofs = 0, out_buf_capacity = 0; size_t src_buf_ofs = 0, out_buf_capacity = 0;
*pOut_len = 0; *pOut_len = 0;
tinfl_init(&decomp); tinfl_init(&decomp);
for (;;) for (;;)
{ {
size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size, tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : nullptr, &dst_buf_size,
(flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
{ {
MZ_FREE(pBuf); MZ_FREE(pBuf);
*pOut_len = 0; *pOut_len = 0;
return NULL; return nullptr;
} }
src_buf_ofs += src_buf_size; src_buf_ofs += src_buf_size;
*pOut_len += dst_buf_size; *pOut_len += dst_buf_size;
@ -2829,7 +2856,7 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, siz
{ {
MZ_FREE(pBuf); MZ_FREE(pBuf);
*pOut_len = 0; *pOut_len = 0;
return NULL; return nullptr;
} }
pBuf = pNew_buf; pBuf = pNew_buf;
out_buf_capacity = new_out_buf_capacity; out_buf_capacity = new_out_buf_capacity;
@ -2935,15 +2962,15 @@ extern "C" {
#if defined(_MSC_VER) || defined(__MINGW64__) #if defined(_MSC_VER) || defined(__MINGW64__)
static FILE *mz_fopen(const char *pFilename, const char *pMode) static FILE *mz_fopen(const char *pFilename, const char *pMode)
{ {
FILE *pFile = NULL; FILE *pFile = nullptr;
fopen_s(&pFile, pFilename, pMode); fopen_s(&pFile, pFilename, pMode);
return pFile; return pFile;
} }
static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
{ {
FILE *pFile = NULL; FILE *pFile = nullptr;
if (freopen_s(&pFile, pPath, pMode, pStream)) if (freopen_s(&pFile, pPath, pMode, pStream))
return NULL; return nullptr;
return pFile; return pFile;
} }
#ifndef MINIZ_NO_TIME #ifndef MINIZ_NO_TIME
@ -3207,7 +3234,7 @@ static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *
while (new_capacity < min_new_capacity) while (new_capacity < min_new_capacity)
new_capacity *= 2; new_capacity *= 2;
} }
if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) if (nullptr == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
return MZ_FALSE; return MZ_FALSE;
pArray->m_p = pNew_p; pArray->m_p = pNew_p;
pArray->m_capacity = new_capacity; pArray->m_capacity = new_capacity;
@ -3340,7 +3367,7 @@ static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
pZip->m_total_files = 0; pZip->m_total_files = 0;
pZip->m_last_error = MZ_ZIP_NO_ERROR; pZip->m_last_error = MZ_ZIP_NO_ERROR;
if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) if (nullptr == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
@ -3731,7 +3758,7 @@ static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last
if (pZip->m_pState) if (pZip->m_pState)
{ {
mz_zip_internal_state *pState = pZip->m_pState; mz_zip_internal_state *pState = pZip->m_pState;
pZip->m_pState = NULL; pZip->m_pState = nullptr;
mz_zip_array_clear(pZip, &pState->m_central_dir); mz_zip_array_clear(pZip, &pState->m_central_dir);
mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
@ -3749,7 +3776,7 @@ static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last
status = MZ_FALSE; status = MZ_FALSE;
} }
} }
pState->m_pFile = NULL; pState->m_pFile = nullptr;
} }
#endif /* #ifndef MINIZ_NO_STDIO */ #endif /* #ifndef MINIZ_NO_STDIO */
@ -3807,7 +3834,7 @@ mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t si
pZip->m_archive_size = size; pZip->m_archive_size = size;
pZip->m_pRead = mz_zip_mem_read_func; pZip->m_pRead = mz_zip_mem_read_func;
pZip->m_pIO_opaque = pZip; pZip->m_pIO_opaque = pZip;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
#ifdef __cplusplus #ifdef __cplusplus
pZip->m_pState->m_pMem = const_cast<void *>(pMem); pZip->m_pState->m_pMem = const_cast<void *>(pMem);
@ -3941,7 +3968,7 @@ mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64
static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index) static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
{ {
if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files)) if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
return NULL; return nullptr;
return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
} }
@ -4378,7 +4405,7 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file
if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) if (nullptr == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
read_buf_avail = 0; read_buf_avail = 0;
@ -4435,19 +4462,19 @@ mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
{ {
mz_uint32 file_index; mz_uint32 file_index;
if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) if (!mz_zip_reader_locate_file_v2(pZip, pFilename, nullptr, flags, &file_index))
return MZ_FALSE; return MZ_FALSE;
return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
} }
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
{ {
return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, nullptr, 0);
} }
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
{ {
return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, nullptr, 0);
} }
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
@ -4462,7 +4489,7 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si
if (!p) if (!p)
{ {
mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
return NULL; return nullptr;
} }
comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
@ -4472,19 +4499,19 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si
if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
{ {
mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
return NULL; return nullptr;
} }
if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) if (nullptr == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
{ {
mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
return NULL; return nullptr;
} }
if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
{ {
pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
return NULL; return nullptr;
} }
if (pSize) if (pSize)
@ -4495,11 +4522,11 @@ void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, si
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
{ {
mz_uint32 file_index; mz_uint32 file_index;
if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) if (!mz_zip_reader_locate_file_v2(pZip, pFilename, nullptr, flags, &file_index))
{ {
if (pSize) if (pSize)
*pSize = 0; *pSize = 0;
return MZ_FALSE; return nullptr; //MZ_FALSE;
} }
return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
} }
@ -4510,8 +4537,8 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind
mz_uint file_crc32 = MZ_CRC32_INIT; mz_uint file_crc32 = MZ_CRC32_INIT;
mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
mz_zip_archive_file_stat file_stat; mz_zip_archive_file_stat file_stat;
void *pRead_buf = NULL; void *pRead_buf = nullptr;
void *pWrite_buf = NULL; void *pWrite_buf = nullptr;
mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
@ -4555,7 +4582,7 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind
else else
{ {
read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE); read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) if (nullptr == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
read_buf_avail = 0; read_buf_avail = 0;
@ -4623,7 +4650,7 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind
tinfl_decompressor inflator; tinfl_decompressor inflator;
tinfl_init(&inflator); tinfl_init(&inflator);
if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) if (nullptr == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
{ {
mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
status = TINFL_STATUS_FAILED; status = TINFL_STATUS_FAILED;
@ -4705,7 +4732,7 @@ mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_ind
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
{ {
mz_uint32 file_index; mz_uint32 file_index;
if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index)) if (!mz_zip_reader_locate_file_v2(pZip, pFilename, nullptr, flags, &file_index))
return MZ_FALSE; return MZ_FALSE;
return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
@ -4756,7 +4783,7 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
{ {
mz_uint32 file_index; mz_uint32 file_index;
if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, nullptr, flags, &file_index))
return MZ_FALSE; return MZ_FALSE;
return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
@ -4778,7 +4805,7 @@ mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index,
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags) mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
{ {
mz_uint32 file_index; mz_uint32 file_index;
if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index)) if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, nullptr, flags, &file_index))
return MZ_FALSE; return MZ_FALSE;
return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags); return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
@ -5037,7 +5064,7 @@ mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
if (!mz_zip_reader_file_stat(pZip, i, &stat)) if (!mz_zip_reader_file_stat(pZip, i, &stat))
return MZ_FALSE; return MZ_FALSE;
if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index)) if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, nullptr, 0, &found_index))
return MZ_FALSE; return MZ_FALSE;
/* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */ /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
@ -5186,7 +5213,7 @@ static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const vo
while (new_capacity < new_size) while (new_capacity < new_size)
new_capacity *= 2; new_capacity *= 2;
if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) if (nullptr == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
{ {
mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
return 0; return 0;
@ -5213,7 +5240,7 @@ static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last
} }
pState = pZip->m_pState; pState = pZip->m_pState;
pZip->m_pState = NULL; pZip->m_pState = nullptr;
mz_zip_array_clear(pZip, &pState->m_central_dir); mz_zip_array_clear(pZip, &pState->m_central_dir);
mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
@ -5231,14 +5258,14 @@ static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last
} }
} }
pState->m_pFile = NULL; pState->m_pFile = nullptr;
} }
#endif /* #ifndef MINIZ_NO_STDIO */ #endif /* #ifndef MINIZ_NO_STDIO */
if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
{ {
pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
pState->m_pMem = NULL; pState->m_pMem = nullptr;
} }
pZip->m_pFree(pZip->m_pAlloc_opaque, pState); pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
@ -5277,7 +5304,7 @@ mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_
pZip->m_central_directory_file_ofs = 0; pZip->m_central_directory_file_ofs = 0;
pZip->m_total_files = 0; pZip->m_total_files = 0;
if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) if (nullptr == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
@ -5303,7 +5330,7 @@ mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags) mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
{ {
pZip->m_pWrite = mz_zip_heap_write_func; pZip->m_pWrite = mz_zip_heap_write_func;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
pZip->m_pRead = mz_zip_mem_read_func; pZip->m_pRead = mz_zip_mem_read_func;
@ -5317,7 +5344,7 @@ mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_
if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
{ {
if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) if (nullptr == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
{ {
mz_zip_writer_end_internal(pZip, MZ_FALSE); mz_zip_writer_end_internal(pZip, MZ_FALSE);
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
@ -5360,7 +5387,7 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename,
MZ_FILE *pFile; MZ_FILE *pFile;
pZip->m_pWrite = mz_zip_file_write_func; pZip->m_pWrite = mz_zip_file_write_func;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
pZip->m_pRead = mz_zip_file_read_func; pZip->m_pRead = mz_zip_file_read_func;
@ -5370,7 +5397,7 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename,
if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags)) if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
return MZ_FALSE; return MZ_FALSE;
if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) if (nullptr == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
{ {
mz_zip_writer_end(pZip); mz_zip_writer_end(pZip);
return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
@ -5405,7 +5432,7 @@ mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename,
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags) mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
{ {
pZip->m_pWrite = mz_zip_file_write_func; pZip->m_pWrite = mz_zip_file_write_func;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
pZip->m_pRead = mz_zip_file_read_func; pZip->m_pRead = mz_zip_file_read_func;
@ -5469,16 +5496,16 @@ mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFil
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
/* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */ /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) if (nullptr == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
{ {
/* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */ /* The mz_zip_archive is now in a bogus state because pState->m_pFile is nullptr, so just close it. */
mz_zip_reader_end_internal(pZip, MZ_FALSE); mz_zip_reader_end_internal(pZip, MZ_FALSE);
return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
} }
} }
pZip->m_pWrite = mz_zip_file_write_func; pZip->m_pWrite = mz_zip_file_write_func;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
#endif /* #ifdef MINIZ_NO_STDIO */ #endif /* #ifdef MINIZ_NO_STDIO */
} }
else if (pState->m_pMem) else if (pState->m_pMem)
@ -5489,7 +5516,7 @@ mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFil
pState->m_mem_capacity = pState->m_mem_size; pState->m_mem_capacity = pState->m_mem_size;
pZip->m_pWrite = mz_zip_heap_write_func; pZip->m_pWrite = mz_zip_heap_write_func;
pZip->m_pNeeds_keepalive = NULL; pZip->m_pNeeds_keepalive = nullptr;
} }
/* Archive is being read via a user provided read function - make sure the user has specified a write function too. */ /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
else if (!pZip->m_pWrite) else if (!pZip->m_pWrite)
@ -5518,7 +5545,7 @@ mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilena
/* TODO: pArchive_name is a terrible name here! */ /* TODO: pArchive_name is a terrible name here! */
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
{ {
return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, nullptr, 0, level_and_flags, 0, 0);
} }
typedef struct typedef struct
@ -5704,7 +5731,7 @@ static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_fil
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
{ {
return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0); return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, nullptr, nullptr, 0, nullptr, 0);
} }
mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
@ -5716,10 +5743,10 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
size_t archive_name_size; size_t archive_name_size;
mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
tdefl_compressor *pComp = NULL; tdefl_compressor *pComp = nullptr;
mz_bool store_data_uncompressed; mz_bool store_data_uncompressed;
mz_zip_internal_state *pState; mz_zip_internal_state *pState;
mz_uint8 *pExtra_data = NULL; mz_uint8 *pExtra_data = nullptr;
mz_uint32 extra_size = 0; mz_uint32 extra_size = 0;
mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
mz_uint16 bit_flags = 0; mz_uint16 bit_flags = 0;
@ -5766,7 +5793,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
#ifndef MINIZ_NO_TIME #ifndef MINIZ_NO_TIME
if (last_modified != NULL) if (last_modified != nullptr)
{ {
mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date); mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
} }
@ -5814,7 +5841,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
if ((!store_data_uncompressed) && (buf_size)) if ((!store_data_uncompressed) && (buf_size))
{ {
if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) if (nullptr == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
} }
@ -5843,8 +5870,8 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
{ {
pExtra_data = extra_data; pExtra_data = extra_data;
extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : nullptr,
(uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : nullptr, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : nullptr);
} }
if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
@ -5862,7 +5889,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
} }
cur_archive_file_ofs += archive_name_size; cur_archive_file_ofs += archive_name_size;
if (pExtra_data != NULL) if (pExtra_data != nullptr)
{ {
if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size) if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
@ -5940,7 +5967,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
} }
pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
pComp = NULL; pComp = nullptr;
if (uncomp_size) if (uncomp_size)
{ {
@ -5951,7 +5978,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
if (pExtra_data == NULL) if (pExtra_data == nullptr)
{ {
if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
@ -5972,10 +5999,10 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
cur_archive_file_ofs += local_dir_footer_size; cur_archive_file_ofs += local_dir_footer_size;
} }
if (pExtra_data != NULL) if (pExtra_data != nullptr)
{ {
extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : nullptr,
(uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : nullptr, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : nullptr);
} }
if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment,
@ -5999,7 +6026,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0; mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
size_t archive_name_size; size_t archive_name_size;
mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
mz_uint8 *pExtra_data = NULL; mz_uint8 *pExtra_data = nullptr;
mz_uint32 extra_size = 0; mz_uint32 extra_size = 0;
mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
mz_zip_internal_state *pState; mz_zip_internal_state *pState;
@ -6099,8 +6126,8 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
{ {
pExtra_data = extra_data; pExtra_data = extra_data;
extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : nullptr,
(uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : nullptr, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : nullptr);
} }
if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
@ -6213,7 +6240,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
uncomp_remaining -= in_buf_size; uncomp_remaining -= in_buf_size;
if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque)) if (pZip->m_pNeeds_keepalive != nullptr && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
flush = TDEFL_FULL_FLUSH; flush = TDEFL_FULL_FLUSH;
status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH); status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
@ -6250,7 +6277,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID); MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32); MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
if (pExtra_data == NULL) if (pExtra_data == nullptr)
{ {
if (comp_size > MZ_UINT32_MAX) if (comp_size > MZ_UINT32_MAX)
return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
@ -6271,10 +6298,10 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
cur_archive_file_ofs += local_dir_footer_size; cur_archive_file_ofs += local_dir_footer_size;
} }
if (pExtra_data != NULL) if (pExtra_data != nullptr)
{ {
extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL, extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : nullptr,
(uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : nullptr, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : nullptr);
} }
if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size,
@ -6290,10 +6317,10 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name,
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
{ {
MZ_FILE *pSrc_file = NULL; MZ_FILE *pSrc_file = nullptr;
mz_uint64 uncomp_size = 0; mz_uint64 uncomp_size = 0;
MZ_TIME_T file_modified_time; MZ_TIME_T file_modified_time;
MZ_TIME_T *pFile_time = NULL; MZ_TIME_T *pFile_time = nullptr;
mz_bool status; mz_bool status;
memset(&file_modified_time, 0, sizeof(file_modified_time)); memset(&file_modified_time, 0, sizeof(file_modified_time));
@ -6312,7 +6339,7 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
uncomp_size = MZ_FTELL64(pSrc_file); uncomp_size = MZ_FTELL64(pSrc_file);
MZ_FSEEK64(pSrc_file, 0, SEEK_SET); MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0); status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, nullptr, 0, nullptr, 0);
MZ_FCLOSE(pSrc_file); MZ_FCLOSE(pSrc_file);
@ -6429,7 +6456,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
/* Get pointer to the source central dir header and crack it */ /* Get pointer to the source central dir header and crack it */
if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index))) if (nullptr == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG) if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
@ -6458,7 +6485,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *
return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
} }
if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL)) if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, nullptr))
return MZ_FALSE; return MZ_FALSE;
cur_src_file_ofs = src_file_stat.m_local_header_ofs; cur_src_file_ofs = src_file_stat.m_local_header_ofs;
@ -6575,7 +6602,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *
cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
/* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */ /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining))))) if (nullptr == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
while (src_archive_bytes_remaining) while (src_archive_bytes_remaining)
@ -6683,7 +6710,7 @@ mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *
MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX); MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX); MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL)) if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, nullptr))
{ {
mz_zip_array_clear(pZip, &new_ext_block); mz_zip_array_clear(pZip, &new_ext_block);
return MZ_FALSE; return MZ_FALSE;
@ -6855,7 +6882,7 @@ mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf,
if ((!ppBuf) || (!pSize)) if ((!ppBuf) || (!pSize))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
*ppBuf = NULL; *ppBuf = nullptr;
*pSize = 0; *pSize = 0;
if ((!pZip) || (!pZip->m_pState)) if ((!pZip) || (!pZip->m_pState))
@ -6869,7 +6896,7 @@ mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf,
*ppBuf = pZip->m_pState->m_pMem; *ppBuf = pZip->m_pState->m_pMem;
*pSize = pZip->m_pState->m_mem_size; *pSize = pZip->m_pState->m_mem_size;
pZip->m_pState->m_pMem = NULL; pZip->m_pState->m_pMem = nullptr;
pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
return MZ_TRUE; return MZ_TRUE;
@ -6883,7 +6910,7 @@ mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
#ifndef MINIZ_NO_STDIO #ifndef MINIZ_NO_STDIO
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
{ {
return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL); return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, nullptr);
} }
mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr) mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
@ -6983,7 +7010,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
{ {
mz_uint32 file_index; mz_uint32 file_index;
mz_zip_archive zip_archive; mz_zip_archive zip_archive;
void *p = NULL; void *p = nullptr;
if (pSize) if (pSize)
*pSize = 0; *pSize = 0;
@ -6993,7 +7020,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
if (pErr) if (pErr)
*pErr = MZ_ZIP_INVALID_PARAMETER; *pErr = MZ_ZIP_INVALID_PARAMETER;
return NULL; return nullptr;
} }
mz_zip_zero_struct(&zip_archive); mz_zip_zero_struct(&zip_archive);
@ -7002,7 +7029,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
if (pErr) if (pErr)
*pErr = zip_archive.m_last_error; *pErr = zip_archive.m_last_error;
return NULL; return nullptr;
} }
if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index)) if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
@ -7010,7 +7037,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
} }
mz_zip_reader_end_internal(&zip_archive, p != NULL); mz_zip_reader_end_internal(&zip_archive, p != nullptr);
if (pErr) if (pErr)
*pErr = zip_archive.m_last_error; *pErr = zip_archive.m_last_error;
@ -7020,7 +7047,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch
void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
{ {
return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL); return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, nullptr, pSize, flags, nullptr);
} }
#endif /* #ifndef MINIZ_NO_STDIO */ #endif /* #ifndef MINIZ_NO_STDIO */
@ -7192,7 +7219,7 @@ mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
{ {
if ((!pZip) || (!pZip->m_pState)) if ((!pZip) || (!pZip->m_pState))
return 0; return nullptr;
return pZip->m_pState->m_pFile; return pZip->m_pState->m_pFile;
} }
@ -7227,7 +7254,7 @@ mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, cha
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
{ {
return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL); return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, nullptr);
} }
mz_bool mz_zip_end(mz_zip_archive *pZip) mz_bool mz_zip_end(mz_zip_archive *pZip)

View File

@ -23,6 +23,8 @@
#include <cctype> #include <cctype>
#include <numeric> // for std::accumulate #include <numeric> // for std::accumulate
#include <sstream>
#include <unordered_map>
#include <detail/constants.hpp> #include <detail/constants.hpp>
#include <detail/header_footer/header_footer_code.hpp> #include <detail/header_footer/header_footer_code.hpp>
@ -58,14 +60,20 @@ struct hash<xml::qname>
namespace { namespace {
xml::qname qn(const std::string &namespace_, const std::string &name) xml::qname &qn(const std::string &namespace_, const std::string &name)
{ {
return xml::qname(xlnt::constants::ns(namespace_), name); using qname_map = std::unordered_map<std::string, xml::qname>;
} static auto &memo = *new std::unordered_map<std::string, qname_map>();
#ifndef NDEBUG auto &ns_memo = memo[namespace_];
#define THROW_ON_INVALID_XML
#endif if (ns_memo.find(name) == ns_memo.end())
{
return ns_memo.emplace(name, xml::qname(xlnt::constants::ns(namespace_), name)).first->second;
}
return ns_memo[name];
}
#ifdef THROW_ON_INVALID_XML #ifdef THROW_ON_INVALID_XML
#define unexpected_element(element) throw xlnt::exception(element.string()); #define unexpected_element(element) throw xlnt::exception(element.string());
@ -96,14 +104,24 @@ bool is_true(const std::string &bool_string)
#endif #endif
} }
/// <summary> struct number_converter
/// Helper template function that returns true if element is in container.
/// </summary>
template <typename T>
bool contains(const std::vector<T> &container, const T &element)
{ {
return std::find(container.begin(), container.end(), element) != container.end(); number_converter()
} {
stream.imbue(std::locale("C"));
}
double stold(const std::string &s)
{
stream.str(s);
stream.clear();
stream >> result;
return result;
}
std::istringstream stream;
double result;
};
} // namespace } // namespace
@ -149,12 +167,6 @@ void xlsx_consumer::open(std::istream &source)
populate_workbook(true); populate_workbook(true);
} }
// caching frequently used names
static const auto sheetData_el = qn("spreadsheetml", "sheetData");
static const auto row_el = qn("spreadsheetml", "row");
static const auto cell_el = qn("spreadsheetml", "c");
static const auto val_el = qn("spreadsheetml", "v");
cell xlsx_consumer::read_cell() cell xlsx_consumer::read_cell()
{ {
if (!has_cell()) if (!has_cell())
@ -164,9 +176,9 @@ cell xlsx_consumer::read_cell()
auto ws = worksheet(current_worksheet_); auto ws = worksheet(current_worksheet_);
if (in_element(sheetData_el)) if (in_element(qn("spreadsheetml", "sheetData")))
{ {
expect_start_element(row_el, xml::content::complex); // CT_Row expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row
auto row_index = static_cast<row_t>(std::stoul(parser().attribute("r"))); auto row_index = static_cast<row_t>(std::stoul(parser().attribute("r")));
if (parser().attribute_present("ht")) if (parser().attribute_present("ht"))
@ -189,12 +201,12 @@ cell xlsx_consumer::read_cell()
"ph", "spans" }); "ph", "spans" });
} }
if (!in_element(row_el)) if (!in_element(qn("spreadsheetml", "row")))
{ {
return cell(nullptr); return cell(nullptr);
} }
expect_start_element(cell_el, xml::content::complex); expect_start_element(qn("spreadsheetml", "c"), xml::content::complex);
auto cell = streaming_ ? xlnt::cell(streaming_cell_.get()) auto cell = streaming_ ? xlnt::cell(streaming_cell_.get())
: ws.cell(cell_reference(parser().attribute("r"))); : ws.cell(cell_reference(parser().attribute("r")));
@ -206,8 +218,10 @@ cell xlsx_consumer::read_cell()
auto has_type = parser().attribute_present("t"); auto has_type = parser().attribute_present("t");
auto type = has_type ? parser().attribute("t") : "n"; auto type = has_type ? parser().attribute("t") : "n";
if (parser().attribute_present("s")) if (parser().attribute_present("s"))
cell.format(target_.format(std::stoull(parser().attribute("s")))); {
cell.format(target_.format(std::stoull(parser().attribute("s"))));
}
auto has_value = false; auto has_value = false;
auto value_string = std::string(); auto value_string = std::string();
@ -216,11 +230,11 @@ cell xlsx_consumer::read_cell()
auto has_shared_formula = false; auto has_shared_formula = false;
auto formula_value_string = std::string(); auto formula_value_string = std::string();
while (in_element(cell_el)) while (in_element(qn("spreadsheetml", "c")))
{ {
auto current_element = expect_start_element(xml::content::mixed); auto current_element = expect_start_element(xml::content::mixed);
if (current_element == val_el) // s:ST_Xstring if (current_element == qn("spreadsheetml", "v")) // s:ST_Xstring
{ {
has_value = true; has_value = true;
value_string = read_text(); value_string = read_text();
@ -253,13 +267,15 @@ cell xlsx_consumer::read_cell()
expect_end_element(current_element); expect_end_element(current_element);
} }
expect_end_element(cell_el); expect_end_element(qn("spreadsheetml", "c"));
if (has_formula && !has_shared_formula) if (has_formula && !has_shared_formula)
{ {
cell.formula(formula_value_string); cell.formula(formula_value_string);
} }
number_converter converter;
if (has_value) if (has_value)
{ {
if (type == "str") if (type == "str")
@ -274,7 +290,7 @@ cell xlsx_consumer::read_cell()
} }
else if (type == "s") else if (type == "s")
{ {
cell.d_->value_numeric_ = std::stold(value_string); cell.d_->value_numeric_ = converter.stold(value_string);
cell.data_type(cell::type::shared_string); cell.data_type(cell::type::shared_string);
} }
else if (type == "b") // boolean else if (type == "b") // boolean
@ -283,7 +299,7 @@ cell xlsx_consumer::read_cell()
} }
else if (type == "n") // numeric else if (type == "n") // numeric
{ {
cell.value(std::stold(value_string)); cell.value(converter.stold(value_string));
} }
else if (!value_string.empty() && value_string[0] == '#') else if (!value_string.empty() && value_string[0] == '#')
{ {
@ -291,13 +307,13 @@ cell xlsx_consumer::read_cell()
} }
} }
if (!in_element(row_el)) if (!in_element(qn("spreadsheetml", "row")))
{ {
expect_end_element(row_el); expect_end_element(qn("spreadsheetml", "row"));
if (!in_element(sheetData_el)) if (!in_element(qn("spreadsheetml", "sheetData")))
{ {
expect_end_element(sheetData_el); expect_end_element(qn("spreadsheetml", "sheetData"));
} }
} }
@ -332,7 +348,6 @@ std::string xlsx_consumer::read_worksheet_begin(const std::string &rel_id)
expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet expect_start_element(qn("spreadsheetml", "worksheet"), xml::content::complex); // CT_Worksheet
skip_attributes({ qn("mc", "Ignorable") }); skip_attributes({ qn("mc", "Ignorable") });
read_namespaces();
while (in_element(qn("spreadsheetml", "worksheet"))) while (in_element(qn("spreadsheetml", "worksheet")))
{ {
@ -547,6 +562,8 @@ void xlsx_consumer::read_worksheet_sheetdata()
return; return;
} }
number_converter converter;
while (in_element(qn("spreadsheetml", "sheetData"))) while (in_element(qn("spreadsheetml", "sheetData")))
{ {
expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row expect_start_element(qn("spreadsheetml", "row"), xml::content::complex); // CT_Row
@ -580,8 +597,10 @@ void xlsx_consumer::read_worksheet_sheetdata()
auto has_type = parser().attribute_present("t"); auto has_type = parser().attribute_present("t");
auto type = has_type ? parser().attribute("t") : "n"; auto type = has_type ? parser().attribute("t") : "n";
if (parser().attribute_present("s")) if (parser().attribute_present("s"))
cell.format(target_.format(std::stoull(parser().attribute("s")))); {
cell.format(target_.format(std::stoull(parser().attribute("s"))));
}
auto has_value = false; auto has_value = false;
auto value_string = std::string(); auto value_string = std::string();
@ -648,7 +667,7 @@ void xlsx_consumer::read_worksheet_sheetdata()
} }
else if (type == "s") else if (type == "s")
{ {
cell.d_->value_numeric_ = std::stold(value_string); cell.d_->value_numeric_ = converter.stold(value_string);
cell.data_type(cell::type::shared_string); cell.data_type(cell::type::shared_string);
} }
else if (type == "b") // boolean else if (type == "b") // boolean
@ -657,7 +676,7 @@ void xlsx_consumer::read_worksheet_sheetdata()
} }
else if (type == "n") // numeric else if (type == "n") // numeric
{ {
cell.value(std::stold(value_string)); cell.value(converter.stold(value_string));
} }
else if (!value_string.empty() && value_string[0] == '#') else if (!value_string.empty() && value_string[0] == '#')
{ {
@ -1020,8 +1039,8 @@ xml::parser &xlsx_consumer::parser()
bool xlsx_consumer::has_cell() bool xlsx_consumer::has_cell()
{ {
return in_element(row_el) return in_element(qn("spreadsheetml", "row"))
|| in_element(sheetData_el); || in_element(qn("spreadsheetml", "sheetData"));
} }
std::vector<relationship> xlsx_consumer::read_relationships(const path &part) std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
@ -1343,7 +1362,6 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
expect_start_element(qn("workbook", "workbook"), xml::content::complex); expect_start_element(qn("workbook", "workbook"), xml::content::complex);
skip_attribute(qn("mc", "Ignorable")); skip_attribute(qn("mc", "Ignorable"));
read_namespaces();
while (in_element(qn("workbook", "workbook"))) while (in_element(qn("workbook", "workbook")))
{ {
@ -1668,7 +1686,6 @@ void xlsx_consumer::read_stylesheet()
expect_start_element(qn("spreadsheetml", "styleSheet"), xml::content::complex); expect_start_element(qn("spreadsheetml", "styleSheet"), xml::content::complex);
skip_attributes({qn("mc", "Ignorable")}); skip_attributes({qn("mc", "Ignorable")});
read_namespaces();
std::vector<std::pair<style_impl, std::size_t>> styles; std::vector<std::pair<style_impl, std::size_t>> styles;
std::vector<std::pair<format_impl, std::size_t>> format_records; std::vector<std::pair<format_impl, std::size_t>> format_records;
@ -2499,7 +2516,6 @@ void xlsx_consumer::skip_remaining_content(const xml::qname &name)
// start by assuming we've already parsed the opening tag // start by assuming we've already parsed the opening tag
skip_attributes(); skip_attributes();
read_namespaces();
read_text(); read_text();
// continue until the closing tag is reached // continue until the closing tag is reached
@ -2512,24 +2528,6 @@ void xlsx_consumer::skip_remaining_content(const xml::qname &name)
} }
} }
std::vector<std::string> xlsx_consumer::read_namespaces()
{
std::vector<std::string> namespaces;
while (parser().peek() == xml::parser::event_type::start_namespace_decl)
{
parser().next_expect(xml::parser::event_type::start_namespace_decl);
namespaces.push_back(parser().namespace_());
if (parser().peek() == xml::parser::event_type::end_namespace_decl)
{
parser().next_expect(xml::parser::event_type::end_namespace_decl);
}
}
return namespaces;
}
bool xlsx_consumer::in_element(const xml::qname &name) bool xlsx_consumer::in_element(const xml::qname &name)
{ {
return parser().peek() != xml::parser::event_type::end_element return parser().peek() != xml::parser::event_type::end_element
@ -2561,12 +2559,6 @@ void xlsx_consumer::expect_start_element(const xml::qname &name, xml::content co
void xlsx_consumer::expect_end_element(const xml::qname &name) void xlsx_consumer::expect_end_element(const xml::qname &name)
{ {
parser().next_expect(xml::parser::event_type::end_element, name); parser().next_expect(xml::parser::event_type::end_element, name);
while (parser().peek() == xml::parser::event_type::end_namespace_decl)
{
parser().next_expect(xml::parser::event_type::end_namespace_decl);
}
stack_.pop_back(); stack_.pop_back();
} }

View File

@ -357,12 +357,6 @@ private:
/// </summary> /// </summary>
bool in_element(const xml::qname &name); bool in_element(const xml::qname &name);
/// <summary>
/// Handles all start and end namespace events from the current parser
/// and returns a vector of strings containing the URL for each namespace.
/// </summary>
std::vector<std::string> read_namespaces();
// Properties // Properties
/// <summary> /// <summary>

View File

@ -47,9 +47,9 @@ namespace {
/// <summary> /// <summary>
/// Returns true if d is exactly equal to an integer. /// Returns true if d is exactly equal to an integer.
/// </summary> /// </summary>
bool is_integral(long double d) bool is_integral(double d)
{ {
return std::fabs(d - static_cast<long double>(static_cast<long long int>(d))) == 0.L; return std::fabs(d - static_cast<double>(static_cast<long long int>(d))) == 0.0;
} }
std::vector<std::pair<std::string, std::string>> core_property_namespace(xlnt::core_property type) std::vector<std::pair<std::string, std::string>> core_property_namespace(xlnt::core_property type)
@ -2330,15 +2330,15 @@ void xlsx_producer::write_worksheet(const relationship &rel)
case cell::type::number: case cell::type::number:
write_start_element(xmlns, "v"); write_start_element(xmlns, "v");
if (is_integral(cell.value<long double>())) if (is_integral(cell.value<double>()))
{ {
write_characters(static_cast<std::int64_t>(cell.value<long double>())); write_characters(static_cast<std::int64_t>(cell.value<double>()));
} }
else else
{ {
std::stringstream ss; std::stringstream ss;
ss.precision(20); ss.precision(20);
ss << cell.value<long double>(); ss << cell.value<double>();
write_characters(ss.str()); write_characters(ss.str());
} }

View File

@ -194,14 +194,14 @@ public:
in.fill(0); in.fill(0);
out.fill(0); out.fill(0);
strm.zalloc = Z_NULL; strm.zalloc = nullptr;
strm.zfree = Z_NULL; strm.zfree = nullptr;
strm.opaque = Z_NULL; strm.opaque = nullptr;
strm.avail_in = 0; strm.avail_in = 0;
strm.next_in = Z_NULL; strm.next_in = nullptr;
setg(in.data(), in.data(), in.data()); setg(in.data(), in.data(), in.data());
setp(0, 0); setp(nullptr, nullptr);
// skip the header // skip the header
read_header(istream, false); read_header(istream, false);
@ -329,9 +329,9 @@ public:
zip_streambuf_compress(zheader *central_header, std::ostream &stream) zip_streambuf_compress(zheader *central_header, std::ostream &stream)
: ostream(stream), header(central_header), valid(true) : ostream(stream), header(central_header), valid(true)
{ {
strm.zalloc = Z_NULL; strm.zalloc = nullptr;
strm.zfree = Z_NULL; strm.zfree = nullptr;
strm.opaque = Z_NULL; strm.opaque = nullptr;
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wold-style-cast"
@ -345,7 +345,7 @@ public:
return; return;
} }
setg(0, 0, 0); setg(nullptr, nullptr, nullptr);
setp(in.data(), in.data() + buffer_size - 4); // we want to be 4 aligned setp(in.data(), in.data() + buffer_size - 4); // we want to be 4 aligned
// Write appropriate header // Write appropriate header

View File

@ -32,7 +32,7 @@ namespace {
std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string) std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string)
{ {
auto x = std::strtoul(hex_string.c_str(), NULL, 16); auto x = std::strtoul(hex_string.c_str(), nullptr, 16);
auto a = static_cast<std::uint8_t>(x >> 24); auto a = static_cast<std::uint8_t>(x >> 24);
auto r = static_cast<std::uint8_t>((x >> 16) & 0xff); auto r = static_cast<std::uint8_t>((x >> 16) & 0xff);

View File

@ -344,7 +344,7 @@ std::string number_format::format(const std::string &text) const
return detail::number_formatter(format_string_, calendar::windows_1900).format_text(text); return detail::number_formatter(format_string_, calendar::windows_1900).format_text(text);
} }
std::string number_format::format(long double number, calendar base_date) const std::string number_format::format(double number, calendar base_date) const
{ {
return detail::number_formatter(format_string_, base_date).format_number(number); return detail::number_formatter(format_string_, base_date).format_number(number);
} }

View File

@ -120,7 +120,7 @@ int date::to_number(calendar base_date) const
date date::today() date date::today()
{ {
std::tm now = safe_localtime(std::time(0)); std::tm now = safe_localtime(std::time(nullptr));
return date(1900 + now.tm_year, now.tm_mon + 1, now.tm_mday); return date(1900 + now.tm_year, now.tm_mon + 1, now.tm_mday);
} }

View File

@ -43,7 +43,7 @@ std::string fill(const std::string &string, std::size_t length = 2)
namespace xlnt { namespace xlnt {
datetime datetime::from_number(long double raw_time, calendar base_date) datetime datetime::from_number(double raw_time, calendar base_date)
{ {
auto date_part = date::from_number(static_cast<int>(raw_time), base_date); auto date_part = date::from_number(static_cast<int>(raw_time), base_date);
auto time_part = time::from_number(raw_time); auto time_part = time::from_number(raw_time);
@ -54,13 +54,19 @@ datetime datetime::from_number(long double raw_time, calendar base_date)
bool datetime::operator==(const datetime &comparand) const bool datetime::operator==(const datetime &comparand) const
{ {
return year == comparand.year && month == comparand.month && day == comparand.day && hour == comparand.hour return year == comparand.year
&& minute == comparand.minute && second == comparand.second && microsecond == comparand.microsecond; && month == comparand.month
&& day == comparand.day
&& hour == comparand.hour
&& minute == comparand.minute
&& second == comparand.second
&& microsecond == comparand.microsecond;
} }
long double datetime::to_number(calendar base_date) const double datetime::to_number(calendar base_date) const
{ {
return date(year, month, day).to_number(base_date) + time(hour, minute, second, microsecond).to_number(); return date(year, month, day).to_number(base_date)
+ time(hour, minute, second, microsecond).to_number();
} }
std::string datetime::to_string() const std::string datetime::to_string() const

View File

@ -43,7 +43,7 @@ std::tm safe_localtime(std::time_t raw_time)
namespace xlnt { namespace xlnt {
time time::from_number(long double raw_time) time time::from_number(double raw_time)
{ {
time result; time result;
@ -110,23 +110,23 @@ time::time(const std::string &time_string)
} }
} }
long double time::to_number() const double time::to_number() const
{ {
std::uint64_t microseconds = static_cast<std::uint64_t>(microsecond); std::uint64_t microseconds = static_cast<std::uint64_t>(microsecond);
microseconds += static_cast<std::uint64_t>(second * 1e6); microseconds += static_cast<std::uint64_t>(second * 1e6);
microseconds += static_cast<std::uint64_t>(minute * 1e6 * 60); microseconds += static_cast<std::uint64_t>(minute * 1e6 * 60);
auto microseconds_per_hour = static_cast<std::uint64_t>(1e6) * 60 * 60; auto microseconds_per_hour = static_cast<std::uint64_t>(1e6) * 60 * 60;
microseconds += static_cast<std::uint64_t>(hour) * microseconds_per_hour; microseconds += static_cast<std::uint64_t>(hour) * microseconds_per_hour;
auto number = microseconds / (24.0L * microseconds_per_hour); auto number = microseconds / (24.0 * microseconds_per_hour);
auto hundred_billion = static_cast<std::uint64_t>(1e9) * 100; auto hundred_billion = static_cast<std::uint64_t>(1e9) * 100;
number = std::floor(number * hundred_billion + 0.5L) / hundred_billion; number = std::floor(number * hundred_billion + 0.5) / hundred_billion;
return number; return number;
} }
time time::now() time time::now()
{ {
std::tm now = safe_localtime(std::time(0)); std::tm now = safe_localtime(std::time(nullptr));
return time(now.tm_hour, now.tm_min, now.tm_sec); return time(now.tm_hour, now.tm_min, now.tm_sec);
} }

View File

@ -37,27 +37,27 @@ timedelta::timedelta(int days_, int hours_, int minutes_, int seconds_, int micr
{ {
} }
long double timedelta::to_number() const double timedelta::to_number() const
{ {
std::uint64_t total_microseconds = static_cast<std::uint64_t>(microseconds); std::uint64_t total_microseconds = static_cast<std::uint64_t>(microseconds);
total_microseconds += static_cast<std::uint64_t>(seconds * 1e6); total_microseconds += static_cast<std::uint64_t>(seconds * 1e6);
total_microseconds += static_cast<std::uint64_t>(minutes * 1e6 * 60); total_microseconds += static_cast<std::uint64_t>(minutes * 1e6 * 60);
auto microseconds_per_hour = static_cast<std::uint64_t>(1e6) * 60 * 60; auto microseconds_per_hour = static_cast<std::uint64_t>(1e6) * 60 * 60;
total_microseconds += static_cast<std::uint64_t>(hours) * microseconds_per_hour; total_microseconds += static_cast<std::uint64_t>(hours) * microseconds_per_hour;
auto number = total_microseconds / (24.0L * microseconds_per_hour); auto number = total_microseconds / (24.0 * microseconds_per_hour);
auto hundred_billion = static_cast<std::uint64_t>(1e9) * 100; auto hundred_billion = static_cast<std::uint64_t>(1e9) * 100;
number = std::floor(number * hundred_billion + 0.5L) / hundred_billion; number = std::floor(number * hundred_billion + 0.5) / hundred_billion;
number += days; number += days;
return number; return number;
} }
timedelta timedelta::from_number(long double raw_time) timedelta timedelta::from_number(double raw_time)
{ {
timedelta result; timedelta result;
result.days = static_cast<int>(raw_time); result.days = static_cast<int>(raw_time);
long double fractional_part = raw_time - result.days; double fractional_part = raw_time - result.days;
fractional_part *= 24; fractional_part *= 24;
result.hours = static_cast<int>(fractional_part); result.hours = static_cast<int>(fractional_part);
@ -68,7 +68,7 @@ timedelta timedelta::from_number(long double raw_time)
fractional_part = 1000000 * (fractional_part - result.seconds); fractional_part = 1000000 * (fractional_part - result.seconds);
result.microseconds = static_cast<int>(fractional_part); result.microseconds = static_cast<int>(fractional_part);
if (result.microseconds == 999999 && fractional_part - result.microseconds > 0.5L) if (result.microseconds == 999999 && fractional_part - result.microseconds > 0.5)
{ {
result.microseconds = 0; result.microseconds = 0;
result.seconds += 1; result.seconds += 1;

View File

@ -109,7 +109,7 @@ const cell cell_vector::back() const
std::size_t cell_vector::length() const std::size_t cell_vector::length() const
{ {
return order_ == major_order::row ? bounds_.width() + 1 : bounds_.height() + 1; return order_ == major_order::row ? bounds_.width() : bounds_.height();
} }
cell_vector::const_iterator cell_vector::begin() const cell_vector::const_iterator cell_vector::begin() const

View File

@ -90,17 +90,17 @@ range_reference range_reference::make_offset(int column_offset, int row_offset)
std::size_t range_reference::height() const std::size_t range_reference::height() const
{ {
return bottom_right_.row() - top_left_.row(); return 1 + bottom_right_.row() - top_left_.row();
} }
std::size_t range_reference::width() const std::size_t range_reference::width() const
{ {
return (bottom_right_.column() - top_left_.column()).index; return 1 + (bottom_right_.column() - top_left_.column()).index;
} }
bool range_reference::is_single_cell() const bool range_reference::is_single_cell() const
{ {
return width() == 0 && height() == 0; return width() == 1 && height() == 1;
} }
std::string range_reference::to_string() const std::string range_reference::to_string() const

View File

@ -352,22 +352,20 @@ void worksheet::unfreeze_panes()
cell worksheet::cell(const cell_reference &reference) cell worksheet::cell(const cell_reference &reference)
{ {
if (d_->cell_map_.find(reference.row()) == d_->cell_map_.end())
{
d_->cell_map_[reference.row()] = std::unordered_map<column_t, detail::cell_impl>();
}
auto &row = d_->cell_map_[reference.row()]; auto &row = d_->cell_map_[reference.row()];
auto match = row.find(reference.column_index());
if (row.find(reference.column_index()) == row.end()) if (match == row.end())
{ {
auto &impl = row[reference.column_index()] = detail::cell_impl(); match = row.emplace(reference.column_index(), detail::cell_impl()).first;
auto &impl = match->second;
impl.parent_ = d_; impl.parent_ = d_;
impl.column_ = reference.column_index(); impl.column_ = reference.column_index();
impl.row_ = reference.row(); impl.row_ = reference.row();
} }
return xlnt::cell(&row[reference.column_index()]); return xlnt::cell(&match->second);
} }
const cell worksheet::cell(const cell_reference &reference) const const cell worksheet::cell(const cell_reference &reference) const
@ -673,7 +671,7 @@ bool worksheet::compare(const worksheet &other, bool reference) const
} }
if (this_cell.data_type() == xlnt::cell::type::number if (this_cell.data_type() == xlnt::cell::type::number
&& std::fabs(this_cell.value<long double>() - other_cell.value<long double>()) > 0.L) && std::fabs(this_cell.value<double>() - other_cell.value<double>()) > 0.0)
{ {
return false; return false;
} }

View File

@ -1,11 +1,18 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(xlnt.test) project(xlnt.test)
set(CMAKE_CXX_STANDARD 14) # Require C++11 compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT COMBINED_PROJECT) if(NOT COMBINED_PROJECT)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../source ${CMAKE_CURRENT_BINARY_DIR}/source)
endif()
if(MSVC AND STATIC)
# Link with static C runtime
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ucm.cmake)
ucm_set_runtime(STATIC)
endif() endif()
file(GLOB CELL_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/cell/*.hpp) file(GLOB CELL_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/cell/*.hpp)
@ -16,12 +23,12 @@ file(GLOB WORKBOOK_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/workbook/*.hpp)
file(GLOB WORKSHEET_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/worksheet/*.hpp) file(GLOB WORKSHEET_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/worksheet/*.hpp)
set(TESTS set(TESTS
${CELL_TESTS} ${CELL_TESTS}
${PACKAGING_TESTS} ${PACKAGING_TESTS}
${STYLES_TESTS} ${STYLES_TESTS}
${UTILS_TESTS} ${UTILS_TESTS}
${WORKBOOK_TESTS} ${WORKBOOK_TESTS}
${WORKSHEET_TESTS}) ${WORKSHEET_TESTS})
file(GLOB HELPERS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.hpp) file(GLOB HELPERS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.hpp)
file(GLOB HELPERS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.cpp) file(GLOB HELPERS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.cpp)
@ -30,21 +37,22 @@ set(HELPERS ${HELPERS_HEADERS} ${HELPERS_SOURCES})
set(RUNNER ${CMAKE_CURRENT_SOURCE_DIR}/runner.cpp) set(RUNNER ${CMAKE_CURRENT_SOURCE_DIR}/runner.cpp)
if(COVERAGE) if(COVERAGE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
endif() endif()
add_executable(xlnt.test ${RUNNER} ${TESTS} ${HELPERS} $<TARGET_OBJECTS:libstudxml>) add_executable(xlnt.test ${RUNNER} ${TESTS} ${HELPERS} $<TARGET_OBJECTS:libstudxml>)
target_link_libraries(xlnt.test PRIVATE xlnt) target_link_libraries(xlnt.test PRIVATE xlnt)
target_include_directories(xlnt.test target_include_directories(xlnt.test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../source
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libstudxml) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libstudxml)
set(XLNT_TEST_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data) set(XLNT_TEST_DATA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data)
target_compile_definitions(xlnt.test PRIVATE XLNT_TEST_DATA_DIR=${XLNT_TEST_DATA_DIR}) target_compile_definitions(xlnt.test PRIVATE XLNT_TEST_DATA_DIR=${XLNT_TEST_DATA_DIR})
if(MSVC) if(MSVC)
set_target_properties(xlnt.test PROPERTIES COMPILE_FLAGS "/wd\"4068\" /bigobj") # bigobj because there are so many headers in one source file
set_target_properties(xlnt.test PROPERTIES COMPILE_FLAGS "/wd\"4068\" /bigobj")
endif() endif()
source_group(helpers FILES ${HELPERS}) source_group(helpers FILES ${HELPERS})
@ -58,8 +66,9 @@ source_group(tests\\workbook FILES ${WORKBOOK_TESTS})
source_group(tests\\worksheet FILES ${WORKSHEET_TESTS}) source_group(tests\\worksheet FILES ${WORKSHEET_TESTS})
if(MSVC AND NOT STATIC) if(MSVC AND NOT STATIC)
add_custom_command(TARGET xlnt.test POST_BUILD # copy xlnt DLL into xlnt.test directory
COMMAND ${CMAKE_COMMAND} -E copy_if_different add_custom_command(TARGET xlnt.test POST_BUILD
$<TARGET_FILE:xlnt> COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE_DIR:xlnt.test>) $<TARGET_FILE:xlnt>
$<TARGET_FILE_DIR:xlnt.test>)
endif() endif()

View File

@ -76,7 +76,7 @@ private:
auto cell = ws.cell("A1"); auto cell = ws.cell("A1");
cell.value("4.2", true); cell.value("4.2", true);
xlnt_assert_delta(cell.value<long double>(), 4.2L, 1E-9); xlnt_assert_delta(cell.value<double>(), 4.2, 1E-9);
cell.value("-42.000", true); cell.value("-42.000", true);
xlnt_assert(cell.value<int>() == -42); xlnt_assert(cell.value<int>() == -42);
@ -85,10 +85,10 @@ private:
xlnt_assert(cell.value<int>() == 0); xlnt_assert(cell.value<int>() == 0);
cell.value("0.9999", true); cell.value("0.9999", true);
xlnt_assert(cell.value<long double>() == 0.9999L); xlnt_assert(cell.value<double>() == 0.9999);
cell.value("99E-02", true); cell.value("99E-02", true);
xlnt_assert(cell.value<long double>() == 0.99L); xlnt_assert(cell.value<double>() == 0.99);
cell.value("4", true); cell.value("4", true);
xlnt_assert(cell.value<int>() == 4); xlnt_assert(cell.value<int>() == 4);
@ -100,7 +100,7 @@ private:
xlnt_assert(cell.value<int>() == 200); xlnt_assert(cell.value<int>() == 200);
cell.value("3.1%", true); cell.value("3.1%", true);
xlnt_assert_delta(cell.value<long double>(), 0.031L, 1E-9); xlnt_assert_delta(cell.value<double>(), 0.031, 1E-9);
cell.value("03:40:16", true); cell.value("03:40:16", true);
xlnt_assert(cell.value<xlnt::time>() == xlnt::time(3, 40, 16)); xlnt_assert(cell.value<xlnt::time>() == xlnt::time(3, 40, 16));
@ -256,7 +256,7 @@ private:
cell.value(xlnt::datetime(2010, 7, 13, 6, 37, 41)); cell.value(xlnt::datetime(2010, 7, 13, 6, 37, 41));
xlnt_assert(cell.data_type() == xlnt::cell::type::number); xlnt_assert(cell.data_type() == xlnt::cell::type::number);
xlnt_assert_delta(cell.value<long double>(), 40372.27616898148L, 1E-9); xlnt_assert_delta(cell.value<double>(), 40372.27616898148, 1E-9);
xlnt_assert(cell.is_date()); xlnt_assert(cell.is_date());
xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd h:mm:ss"); xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd h:mm:ss");
} }
@ -269,7 +269,7 @@ private:
cell.value(xlnt::date(2010, 7, 13)); cell.value(xlnt::date(2010, 7, 13));
xlnt_assert(cell.data_type() == xlnt::cell::type::number); xlnt_assert(cell.data_type() == xlnt::cell::type::number);
xlnt_assert(cell.value<long double>() == 40372.L); xlnt_assert(cell.value<double>() == 40372.0);
xlnt_assert(cell.is_date()); xlnt_assert(cell.is_date());
xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd"); xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd");
} }
@ -282,7 +282,7 @@ private:
cell.value(xlnt::time(1, 3)); cell.value(xlnt::time(1, 3));
xlnt_assert(cell.data_type() == xlnt::cell::type::number); xlnt_assert(cell.data_type() == xlnt::cell::type::number);
xlnt_assert_delta(cell.value<long double>(), 0.04375L, 1E-9); xlnt_assert_delta(cell.value<double>(), 0.04375, 1E-9);
xlnt_assert(cell.is_date()); xlnt_assert(cell.is_date());
xlnt_assert(cell.number_format().format_string() == "h:mm:ss"); xlnt_assert(cell.number_format().format_string() == "h:mm:ss");
} }
@ -356,7 +356,7 @@ private:
cell.value(xlnt::timedelta(1, 3, 0, 0, 0)); cell.value(xlnt::timedelta(1, 3, 0, 0, 0));
xlnt_assert(cell.value<long double>() == 1.125); xlnt_assert(cell.value<double>() == 1.125);
xlnt_assert(cell.data_type() == xlnt::cell::type::number); xlnt_assert(cell.data_type() == xlnt::cell::type::number);
xlnt_assert(!cell.is_date()); xlnt_assert(!cell.is_date());
xlnt_assert(cell.number_format().format_string() == "[hh]:mm:ss"); xlnt_assert(cell.number_format().format_string() == "[hh]:mm:ss");
@ -612,11 +612,8 @@ private:
cell.value(static_cast<float>(3.14)); cell.value(static_cast<float>(3.14));
xlnt_assert_delta(cell.value<float>(), 3.14, 0.001); xlnt_assert_delta(cell.value<float>(), 3.14, 0.001);
cell.value(static_cast<double>(4.1415)); cell.value(static_cast<double>(3.141592));
xlnt_assert_equals(cell.value<double>(), 4.1415); xlnt_assert_equals(cell.value<double>(), 3.141592);
cell.value(static_cast<long double>(3.141592));
xlnt_assert_equals(cell.value<long double>(), 3.141592);
auto cell2 = ws.cell("A2"); auto cell2 = ws.cell("A2");
cell2.value(std::string(100000, 'a')); cell2.value(std::string(100000, 'a'));

View File

@ -769,9 +769,9 @@ public:
void format_and_test(const xlnt::number_format &nf, const std::array<std::string, 4> &expect) void format_and_test(const xlnt::number_format &nf, const std::array<std::string, 4> &expect)
{ {
long double positive = 42503.1234; double positive = 42503.1234;
long double negative = -1 * positive; double negative = -1 * positive;
long double zero = 0; double zero = 0;
const std::string text = "text"; const std::string text = "text";
xlnt::calendar calendar = xlnt::calendar::windows_1900; xlnt::calendar calendar = xlnt::calendar::windows_1900;

View File

@ -51,7 +51,7 @@ public:
void test_round_trip() void test_round_trip()
{ {
long double time = 3.14159265359L; double time = 3.14159265359;
auto td = xlnt::timedelta::from_number(time); auto td = xlnt::timedelta::from_number(time);
auto time_rt = td.to_number(); auto time_rt = td.to_number();
xlnt_assert_delta(time, time_rt, 1E-9); xlnt_assert_delta(time, time_rt, 1E-9);
@ -59,8 +59,8 @@ public:
void test_to_number() void test_to_number()
{ {
xlnt::timedelta td(1, 1, 1, 1, 1); xlnt::timedelta td(1, 1, 1, 1, 1);
xlnt_assert_delta(td.to_number(), 1.0423726852L, 1E-9); xlnt_assert_delta(td.to_number(), 1.0423726852L, 1E-9);
} }
void test_carry() void test_carry()

View File

@ -120,9 +120,6 @@ public:
ws.cell("A14").value("number (double)"); ws.cell("A14").value("number (double)");
ws.cell("B14").value(std::numeric_limits<double>::max()); ws.cell("B14").value(std::numeric_limits<double>::max());
ws.cell("A15").value("number (long double)");
ws.cell("B15").value(std::numeric_limits<long double>::max());
ws.cell("A16").value("text (char *)"); ws.cell("A16").value("text (char *)");
ws.cell("B16").value("string"); ws.cell("B16").value("string");
@ -479,11 +476,10 @@ public:
while (reader.has_cell()) while (reader.has_cell())
{ {
const auto cell = reader.read_cell(); reader.read_cell();
std::cout << cell.reference().to_string() << " " << cell.to_string() << std::endl;
} }
const auto ws = reader.end_worksheet(); reader.end_worksheet();
} }
} }

View File

@ -93,6 +93,7 @@ public:
register_test(test_get_point_pos); register_test(test_get_point_pos);
register_test(test_named_range_named_cell_reference); register_test(test_named_range_named_cell_reference);
register_test(test_iteration_skip_empty); register_test(test_iteration_skip_empty);
register_test(test_dimensions);
} }
void test_new_worksheet() void test_new_worksheet()
@ -1088,4 +1089,17 @@ public:
xlnt_assert_equals(cells[1].value<std::string>(), "F6"); xlnt_assert_equals(cells[1].value<std::string>(), "F6");
} }
} }
void test_dimensions()
{
xlnt::workbook workbook;
workbook.load(path_helper::test_file("4_every_style.xlsx"));
auto active_sheet = workbook.active_sheet();
auto sheet_range = active_sheet.calculate_dimension();
xlnt_assert(!sheet_range.is_single_cell());
xlnt_assert_equals(sheet_range.width(), 4);
xlnt_assert_equals(sheet_range.height(), 35);
}
}; };

View File

@ -1,73 +1,79 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.1)
project(libstudxml) project(libstudxml)
set(CMAKE_CXX_STANDARD 14) # Require C++11 compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(LIBSTUDXML_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBSTUDXML_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBSTUDXML_INCLUDE_DIR ${LIBSTUDXML_ROOT_DIR}) set(LIBSTUDXML_INCLUDE_DIR ${LIBSTUDXML_ROOT_DIR})
if(STATIC)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/ucm.cmake)
ucm_set_runtime(STATIC)
endif()
set(LIBSTUDXML set(LIBSTUDXML
${LIBSTUDXML_ROOT_DIR}/xml/parser.cxx ${LIBSTUDXML_ROOT_DIR}/xml/parser.cxx
${LIBSTUDXML_ROOT_DIR}/xml/qname.cxx ${LIBSTUDXML_ROOT_DIR}/xml/qname.cxx
${LIBSTUDXML_ROOT_DIR}/xml/serializer.cxx ${LIBSTUDXML_ROOT_DIR}/xml/serializer.cxx
${LIBSTUDXML_ROOT_DIR}/xml/value-traits.cxx ${LIBSTUDXML_ROOT_DIR}/xml/value-traits.cxx
${LIBSTUDXML_ROOT_DIR}/xml/content ${LIBSTUDXML_ROOT_DIR}/xml/content
${LIBSTUDXML_ROOT_DIR}/xml/exception ${LIBSTUDXML_ROOT_DIR}/xml/exception
${LIBSTUDXML_ROOT_DIR}/xml/forward ${LIBSTUDXML_ROOT_DIR}/xml/forward
${LIBSTUDXML_ROOT_DIR}/xml/parser ${LIBSTUDXML_ROOT_DIR}/xml/parser
${LIBSTUDXML_ROOT_DIR}/xml/qname ${LIBSTUDXML_ROOT_DIR}/xml/qname
${LIBSTUDXML_ROOT_DIR}/xml/serializer ${LIBSTUDXML_ROOT_DIR}/xml/serializer
${LIBSTUDXML_ROOT_DIR}/xml/value-traits) ${LIBSTUDXML_ROOT_DIR}/xml/value-traits)
set(GENX set(GENX
${LIBSTUDXML_ROOT_DIR}/xml/details/genx/char-props.c ${LIBSTUDXML_ROOT_DIR}/xml/details/genx/char-props.c
${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.c ${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.c
${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.h) ${LIBSTUDXML_ROOT_DIR}/xml/details/genx/genx.h)
set(EXPAT set(EXPAT
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlparse.c ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlparse.c
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.c ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.c
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.c ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.c
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/ascii.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/ascii.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/asciitab.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/asciitab.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/config.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/config.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat_external.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat_external.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/expat.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/iasciitab.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/iasciitab.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/internal.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/internal.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/latin1tab.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/latin1tab.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/nametab.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/nametab.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/utf8tab.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/utf8tab.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmlrole.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok_impl.h ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok_impl.h
${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.h) ${LIBSTUDXML_ROOT_DIR}/xml/details/expat/xmltok.h)
add_library(libstudxml OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT}) add_library(libstudxml OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT})
target_compile_definitions(libstudxml PUBLIC LIBSTUDXML_STATIC_LIB=1) target_compile_definitions(libstudxml PUBLIC LIBSTUDXML_STATIC_LIB=1)
target_include_directories(libstudxml target_include_directories(libstudxml
PUBLIC ${LIBSTUDXML_ROOT_DIR} PUBLIC ${LIBSTUDXML_ROOT_DIR}
PUBLIC ${EXPAT_INCLUDE_DIRS}) PUBLIC ${EXPAT_INCLUDE_DIRS})
if(STATIC) if(STATIC)
target_compile_definitions(libstudxml PUBLIC XML_STATIC=1) target_compile_definitions(libstudxml PUBLIC XML_STATIC=1)
endif() endif()
# Prevent warning C4996 caused by strcpy, strncpy, sprintf in genx # Prevent warning C4996 caused by strcpy, strncpy, sprintf in genx
# TODO: would it be better to define this only in genx.c? # TODO: would it be better to define this only in genx.c?
if(MSVC) if(MSVC)
target_compile_definitions(libstudxml PRIVATE _CRT_SECURE_NO_WARNINGS=1) target_compile_definitions(libstudxml PRIVATE _CRT_SECURE_NO_WARNINGS=1)
endif() endif()
# Build with -fPIC when xlnt is a shared library # Build with -fPIC when xlnt is a shared library
# TODO: is this still necessary? try removing # TODO: is this still necessary? try removing
if(NOT STATIC) if(NOT STATIC)
set_target_properties(libstudxml PROPERTIES POSITION_INDEPENDENT_CODE 1) set_target_properties(libstudxml PROPERTIES POSITION_INDEPENDENT_CODE 1)
endif() endif()
# When xlnt is a static library, assume expat will be linked statically too # When xlnt is a static library, assume expat will be linked statically too
# TODO: is this a valid assumption? # TODO: is this a valid assumption?
if(STATIC) if(STATIC)
target_compile_definitions(libstudxml PUBLIC XML_STATIC=1) target_compile_definitions(libstudxml PUBLIC XML_STATIC=1)
endif() endif()

View File

@ -325,7 +325,7 @@ namespace xml
{ {
typedef event_type value_type; typedef event_type value_type;
iterator (parser* p = 0, event_type e = eof): p_ (p), e_ (e) {} iterator (parser* p = nullptr, event_type e = eof): p_ (p), e_ (e) {}
value_type operator* () const {return e_;} value_type operator* () const {return e_;}
iterator& operator++ () {e_ = p_->next (); return *this;} iterator& operator++ () {e_ = p_->next (); return *this;}

View File

@ -47,7 +47,7 @@ namespace xml
feature_type f) feature_type f)
: size_ (size), iname_ (iname), feature_ (f) : size_ (size), iname_ (iname), feature_ (f)
{ {
assert (data != 0 && size != 0); assert (data != nullptr && size != 0);
data_.buf = data; data_.buf = data;
init (); init ();
@ -76,7 +76,7 @@ namespace xml
inline const parser::element_entry* parser:: inline const parser::element_entry* parser::
get_element () const get_element () const
{ {
return element_state_.empty () ? 0 : get_element_ (); return element_state_.empty () ? nullptr : get_element_ ();
} }
inline const std::string& parser:: inline const std::string& parser::