diff --git a/.gitmodules b/.gitmodules
index cb9c07a2..d66d37c4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,28 +2,34 @@
path = third-party/libstudxml
url = http://scm.codesynthesis.com/libstudxml/libstudxml.git
branch = master
+ ignore = dirty
[submodule "third-party/cxxtest"]
path = third-party/cxxtest
url = https://github.com/CxxTest/cxxtest
branch = master
+ ignore = dirty
[submodule "third-party/utfcpp"]
path = third-party/utfcpp
url = https://github.com/nemtrif/utfcpp
branch = master
+ ignore = dirty
[submodule "third-party/pugixml"]
path = third-party/pugixml
url = https://github.com/zeux/pugixml
branch = master
+ ignore = dirty
[submodule "third-party/botan"]
path = third-party/botan
url = https://github.com/randombit/botan
branch = master
+ ignore = dirty
[submodule "third-party/zlib"]
path = third-party/zlib
url = https://github.com/madler/zlib.git
- branch = develop
+ branch = develop
+ ignore = dirty
diff --git a/LICENCE.md b/LICENCE.md
index 602d8def..7d1f1995 100644
--- a/LICENCE.md
+++ b/LICENCE.md
@@ -1,5 +1,5 @@
-This software is under the MIT Licence
-======================================
+This software is distributed under the MIT Licence
+==================================================
Copyright (c) 2014-2015 Thomas Fussell
@@ -21,3 +21,420 @@ 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.
+
+
+Third-party licenses
+====================
+
+
+Pole is distributed under the BSD 2-Clause License
+==================================================
+
+POLE - Portable C++ library to access OLE Storage
+Copyright (C) 2002-2007 Ariya Hidayat (ariya@kde.org). 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.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 AUTHOR 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.
+
+
+Botan is distributed under the BSD 2-Clause License
+===================================================
+
+Copyright (C) 1999-2013,2014,2015,2016 Jack Lloyd
+ 2001 Peter J Jones
+ 2004-2007 Justin Karneges
+ 2004 Vaclav Ovsik
+ 2005 Matthew Gregan
+ 2005-2006 Matt Johnston
+ 2006 Luca Piccarreta
+ 2007 Yves Jerschow
+ 2007,2008 FlexSecure GmbH
+ 2007,2008 Technische Universitat Darmstadt
+ 2007,2008,2010,2014 Falko Strenzke
+ 2007,2008 Martin Doering
+ 2007 Manuel Hartl
+ 2007 Christoph Ludwig
+ 2007 Patrick Sona
+ 2008 Copyright Projet SECRET, INRIA, Rocquencourt
+ 2008 Bhaskar Biswas and Nicolas Sendrier
+ 2008 Google Inc.
+ 2010 Olivier de Gaalon
+ 2012 Vojtech Kral
+ 2012,2014 Markus Wanner
+ 2013 Joel Low
+ 2014 cryptosource GmbH
+ 2014 Andrew Moon
+ 2015 Daniel Seither (Kullo GmbH)
+ 2015 Simon Warta (Kullo GmbH)
+ 2015 Matej Kenda (TopIT d.o.o.)
+ 2015 René Korthaus
+ 2015,2016 Daniel Neus
+ 2015 Uri Blumenthal
+ 2015,2016 Kai Michaelis
+ 2016 Simon Cogliani
+ 2015,2016 Rohde & Schwarz Cybersecurity
+ 2016 Juraj Somorovsky
+ 2016 Christian Mainka
+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.
+
+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.
+
+
+libstudxml is distributed under the MIT License
+===============================================
+
+Summary: Everything is licensed under the MIT License (text below).
+
+Code found in the xml/details/expat/ directory is distributed under
+the MIT License (see the xml/details/expat/LICENSE file for copyright
+information).
+
+Code found in the xml/details/genx/ directory is distributed under
+the MIT License (see the xml/details/genx/LICENSE file for copyright
+information).
+
+The rest is Copyright (c) 2013-2014 Code Synthesis Tools CC and is
+distributed under the MIT License:
+
+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.
+
+
+pugixml is distributed under the MIT License
+============================================
+
+Copyright (c) 2006-2016 Arseny Kapoulkine
+
+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.
+
+
+zlib is distributed under the zlib license
+==========================================
+
+ (C) 1995-2013 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+utfcpp is distributed under the Boost Software License - Version 1.0
+====================================================================
+
+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.
+
+
+CxxTest is distributed under the LGPL License
+=============================================
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
+
+partio is distributed under the BSD 3-Clause License (with specific non-attribution clause)
+===========================================================================================
+
+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.
diff --git a/README.md b/README.md
index ab4a4e35..58a39864 100644
--- a/README.md
+++ b/README.md
@@ -8,17 +8,16 @@
[![License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://opensource.org/licenses/MIT)
## Introduction
-xlnt is a C++14 library for reading, writing, and modifying XLSX files as described in [ECMA 376 4th edition](http://www.ecma-international.org/publications/standards/Ecma-376.htm). The API is based on [openpyxl](https://bitbucket.org/openpyxl/openpyxl), a Python library to read/write Excel 2007 xlsx/xlsm files, and ultimately on [PHPExcel](https://github.com/PHPOffice/PHPExcel), pure PHP library for reading and writing spreadsheet files upon which openpyxl was based. This project is still very much a work in progress, but the core development work is complete.
+xlnt is a C++14 library for reading, writing, and modifying xlsx files as described in [ECMA 376 4th edition](http://www.ecma-international.org/publications/standards/Ecma-376.htm). The API was initially based on [openpyxl](https://bitbucket.org/openpyxl/openpyxl), a Python library to read/write Excel 2007 xlsx/xlsm files, which was itself based on [PHPExcel](https://github.com/PHPOffice/PHPExcel), pure PHP library for reading and writing spreadsheet files. xlnt is still very much a work in progress, but the core development work is complete. For a high-level summary of what you can do with this library, see [here](http://xlnt.readthedocs.io/en/latest/#summary-of-features).
## Usage
Including xlnt in your project
```c++
// with -std=c++14 -Ixlnt/include -Lxlnt/lib -lxlnt
-// can also use the generated "xlnt.pc" in ./build directory with pkg-config to get these flags
#include
```
-Creating a new spreadsheet and saving it as book1.xlsx
+Creating a new spreadsheet and saving it as "example.xlsx"
```c++
xlnt::workbook wb;
xlnt::worksheet ws = wb.get_active_sheet();
@@ -27,28 +26,11 @@ ws.get_cell("B2").set_value("string data");
ws.get_cell("C3").set_formula("=RAND()");
ws.merge_cells("C3:C4");
ws.freeze_panes("B2");
-wb.save("book1.xlsx");
-```
-
-Opening an existing spreadsheet, book2.xlsx, and printing all cells
-```c++
-xlnt::workbook wb2;
-wb2.load("book2.xlsx");
-
-// no need to use references, "cell", "range", and "worksheet" classes are only wrappers around pointers to memory in the workbook
-for(auto row : wb2["sheet2"].rows())
-{
- for(auto cell : row)
- {
- std::cout << cell << std::endl;
- }
-}
+wb.save("example.xlsx");
```
## Building
-xlnt uses continous integration and passes all 200+ tests in GCC 4.9, GCC5, VS2015, and Clang (using Apple LLVM 7.0).
-
-Build configurations for Visual Studio 2015, GNU Make, and Xcode can be created using [cmake](https://cmake.org/) and the cmake scripts in the project's cmake directory. A full list of cmake generators can be found [here](https://cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html). A basic build would look like (starting in the root xlnt directory):
+xlnt uses continous integration (thanks [Travis CI](https://travis-ci.org/) and [AppVeyor](https://www.appveyor.com/)!) and passes all 270+ tests in GCC 4, GCC 5, VS2015 U3, and Clang (using Apple LLVM 8.0). Build configurations for Visual Studio 2015, GNU Make, and Xcode can be created using [cmake](https://cmake.org/) v3.1+. A full list of cmake generators can be found [here](https://cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html). A basic build would look like (starting in the root xlnt directory):
```bash
mkdir build
@@ -57,55 +39,42 @@ cmake ..
make -j8
```
-The resulting library, libxlnt.dylib or libxlnt.so or xlnt.dll, would be found in the build/lib directory. Other cmake configuration options can be found using "cmake -LH". These options include shared vs static library and whether to build tests or not. An example of building a static library with tests as an Xcode project:
+The resulting shared (e.g. libxlnt.dylib) library would be found in the build/lib directory. Other cmake configuration options for xlnt can be found using "cmake -LH". These options include building a static library instead of shared and whether to build sample executables or not. An example of building a static library with an Xcode project:
```bash
mkdir build
cd build
-cmake -D WITH_TESTS=1 -D SHARED=0 -D STATIC=1 -G Xcode ..
+cmake -D STATIC=ON -G Xcode ..
cmake --build .
-bin/xlnt.test
+cd bin && ./xlnt.test
+```
+*Note for Windows: cmake defaults to building a 32-bit library project. To build a 64-bit library, use the Win64 generator*
+```bash
+cmake -G "Visual Studio 14 2015 Win64" ..
```
## Dependencies
-xlnt uses the following libraries, which are included in the source tree (all but miniz as [git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules#Cloning-a-Project-with-Submodules)) for convenience:
-- [miniz v1.15_r4](https://code.google.com/p/miniz/) (public domain/unlicense)
+xlnt requires the following libraries which are all distributed under permissive open source licenses. All libraries are included in the source tree as [git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules#Cloning-a-Project-with-Submodules) for convenience except for pole and partio's zip component which have been modified and reside in xlnt/source/detail:
+- [zlib v1.2.8](http://zlib.net/) (zlib License)
- [libstudxml v1.1.0](http://www.codesynthesis.com/projects/libstudxml/) (MIT license)
- [utfcpp v2.3.4](http://utfcpp.sourceforge.net/) (Boost Software License, Version 1.0)
-- [cxxtest v4.4](http://cxxtest.com/) (LGPLv3 license [only used for testing, separate from main library assembly])
-- [pugixml v1.7](http://cxxtest.com/) (LGPLv3 license [only used for testing, separate from main library assembly])
-- [botan v1.11](https://botan.randombit.net/) (BSD license)
-- [pole v0.5](https://github.com/catlan/pole) (BSD license)
+- [botan v1.11](https://botan.randombit.net/) (BSD 2-Clause License)
+- [pole v0.5](https://github.com/catlan/pole) (BSD 2-Clause License)
+- [partio v1.1.0](https://github.com/wdas/partio) (BSD 3-Clause License with specific non-attribution clause)
-Initialize the submodules with this command:
+Additionally, the xlnt test suite (bin/xlnt.test) requires two extra libraries. This test executable is separate from the main xlnt library assembly so the terms of these libraries' licenses should not apply to users of solely the xlnt library:
+- [cxxtest v4.4](http://cxxtest.com/) (LGPLv3 License)
+- [pugixml v1.7](http://pugixml.org/) (MIT License)
+
+Initialize the submodules from the HEAD of their respective Git repositories with this command called from the xlnt root directory:
```bash
-git submodule update --init
+git submodule update --init --remote
```
## Documentation
-More detailed documentation with examples can be found on [Read The Docs](http://xlnt.readthedocs.org/en/latest/) (warning: this is somewhat out of date at the moment).
+More detailed documentation with examples can be found on [Read The Docs](http://xlnt.readthedocs.org/en/latest/) (Warning: As of November 9, 2016 this is very out of date).
## License
-xlnt is currently released to the public for free under the terms of the MIT License:
-
-Copyright (c) 2015-2016 Thomas Fussell
-
-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.
+xlnt is released to the public for free under the terms of the MIT License. See [LICENSE.md](https://github.com/tfussell/xlnt/blob/master/LICENCE.md) for the full text of the license and the licenses of xlnt's third-party dependencies. [LICENSE.md](https://github.com/tfussell/xlnt/blob/master/LICENCE.md) should be distributed alongside any assemblies that use xlnt in source or compiled form.
diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp
index 9ebb4abd..e4ee69fb 100644
--- a/include/xlnt/cell/cell.hpp
+++ b/include/xlnt/cell/cell.hpp
@@ -82,6 +82,8 @@ public:
/// Return a map of error strings such as \#DIV/0! and their associated indices.
///
static const std::unordered_map &error_codes();
+
+ cell(const cell &) = default;
// value
@@ -498,6 +500,8 @@ private:
/// This is for internal use only.
///
class format modifiable_format();
+
+ cell() = delete;
///
/// Private constructor to create a cell from its implementation.
diff --git a/include/xlnt/styles/style.hpp b/include/xlnt/styles/style.hpp
index 16be8e9b..80354b9a 100644
--- a/include/xlnt/styles/style.hpp
+++ b/include/xlnt/styles/style.hpp
@@ -58,32 +58,32 @@ public:
class alignment &alignment();
const class alignment &alignment() const;
- style alignment(const xlnt::alignment &new_alignment, bool applied);
+ style alignment(const xlnt::alignment &new_alignment, bool applied = true);
bool alignment_applied() const;
class border &border();
const class border &border() const;
- style border(const xlnt::border &new_border, bool applied);
+ style border(const xlnt::border &new_border, bool applied = true);
bool border_applied() const;
class fill &fill();
const class fill &fill() const;
- style fill(const xlnt::fill &new_fill, bool applied);
+ style fill(const xlnt::fill &new_fill, bool applied = true);
bool fill_applied() const;
class font &font();
const class font &font() const;
- style font(const xlnt::font &new_font, bool applied);
+ style font(const xlnt::font &new_font, bool applied = true);
bool font_applied() const;
class number_format &number_format();
const class number_format &number_format() const;
- style number_format(const xlnt::number_format &new_number_format, bool applied);
+ style number_format(const xlnt::number_format &new_number_format, bool applied = true);
bool number_format_applied() const;
class protection &protection();
const class protection &protection() const;
- style protection(const xlnt::protection &new_protection, bool applied);
+ style protection(const xlnt::protection &new_protection, bool applied = true);
bool protection_applied() const;
bool hidden() const;
diff --git a/include/xlnt/utils/exceptions.hpp b/include/xlnt/utils/exceptions.hpp
index 322b5fcb..584f94b7 100644
--- a/include/xlnt/utils/exceptions.hpp
+++ b/include/xlnt/utils/exceptions.hpp
@@ -54,6 +54,8 @@ class XLNT_API invalid_parameter : public exception
{
public:
invalid_parameter();
+ invalid_parameter(const invalid_parameter &) = default;
+ virtual ~invalid_parameter();
};
///
@@ -63,6 +65,8 @@ class XLNT_API invalid_sheet_title : public exception
{
public:
invalid_sheet_title(const std::string &title);
+ invalid_sheet_title(const invalid_sheet_title &) = default;
+ virtual ~invalid_sheet_title();
};
///
@@ -72,6 +76,7 @@ class XLNT_API missing_number_format : public exception
{
public:
missing_number_format();
+ virtual ~missing_number_format();
};
///
@@ -81,6 +86,8 @@ class XLNT_API invalid_file : public exception
{
public:
invalid_file(const std::string &filename);
+ invalid_file(const invalid_file &) = default;
+ virtual ~invalid_file();
};
///
@@ -91,6 +98,8 @@ class XLNT_API illegal_character : public exception
{
public:
illegal_character(char c);
+ illegal_character(const illegal_character &) = default;
+ virtual ~illegal_character();
};
///
@@ -100,6 +109,8 @@ class XLNT_API invalid_data_type : public exception
{
public:
invalid_data_type();
+ invalid_data_type(const invalid_data_type &) = default;
+ virtual ~invalid_data_type();
};
///
@@ -143,6 +154,8 @@ class XLNT_API key_not_found : public exception
{
public:
key_not_found();
+ key_not_found(const key_not_found &) = default;
+ virtual ~key_not_found();
};
///
@@ -152,6 +165,8 @@ class XLNT_API no_visible_worksheets : public exception
{
public:
no_visible_worksheets();
+ no_visible_worksheets(const no_visible_worksheets &) = default;
+ virtual ~no_visible_worksheets();
};
///
@@ -161,6 +176,7 @@ class XLNT_API unhandled_switch_case : public exception
{
public:
unhandled_switch_case();
+ virtual ~unhandled_switch_case();
};
///
@@ -170,6 +186,8 @@ class XLNT_API unsupported : public exception
{
public:
unsupported(const std::string &message);
+ unsupported(const unsupported &) = default;
+ virtual ~unsupported();
};
} // namespace xlnt
diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp
index 758999f3..ce38ba40 100644
--- a/include/xlnt/workbook/workbook.hpp
+++ b/include/xlnt/workbook/workbook.hpp
@@ -424,7 +424,7 @@ public:
format get_format(std::size_t format_index);
const format get_format(std::size_t format_index) const;
- format create_format();
+ format create_format(bool default_format = false);
void clear_formats();
// styles
diff --git a/include/xlnt/worksheet/cell_iterator.hpp b/include/xlnt/worksheet/cell_iterator.hpp
index dd8fec7c..1358892f 100644
--- a/include/xlnt/worksheet/cell_iterator.hpp
+++ b/include/xlnt/worksheet/cell_iterator.hpp
@@ -38,16 +38,18 @@ class cell_reference;
class range_reference;
enum class major_order;
-class XLNT_API cell_iterator : public std::iterator
+class XLNT_API cell_iterator : public std::iterator
{
public:
- cell_iterator(worksheet ws, const cell_reference &start_cell);
+ cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits);
- cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order);
+ cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order);
cell_iterator(const cell_iterator &other);
cell operator*();
+
+ cell_iterator &operator=(const cell_iterator &) = default;
bool operator==(const cell_iterator &other) const;
diff --git a/include/xlnt/worksheet/const_cell_iterator.hpp b/include/xlnt/worksheet/const_cell_iterator.hpp
index fc122509..a163a361 100644
--- a/include/xlnt/worksheet/const_cell_iterator.hpp
+++ b/include/xlnt/worksheet/const_cell_iterator.hpp
@@ -47,6 +47,8 @@ public:
const_cell_iterator(const const_cell_iterator &other);
+ const_cell_iterator &operator=(const const_cell_iterator &) = default;
+
const cell operator*() const;
bool operator==(const const_cell_iterator &other) const;
diff --git a/include/xlnt/worksheet/const_range_iterator.hpp b/include/xlnt/worksheet/const_range_iterator.hpp
index 6b82795d..6802bb17 100644
--- a/include/xlnt/worksheet/const_range_iterator.hpp
+++ b/include/xlnt/worksheet/const_range_iterator.hpp
@@ -51,6 +51,8 @@ public:
const_range_iterator(const const_range_iterator &other);
const cell_vector operator*() const;
+
+ const_range_iterator &operator=(const const_range_iterator &) = default;
bool operator==(const const_range_iterator &other) const;
diff --git a/include/xlnt/worksheet/range.hpp b/include/xlnt/worksheet/range.hpp
index 877f6644..1a8bc2d6 100644
--- a/include/xlnt/worksheet/range.hpp
+++ b/include/xlnt/worksheet/range.hpp
@@ -54,6 +54,8 @@ public:
range(worksheet ws, const range_reference &reference, major_order order = major_order::row, bool skip_null = false);
~range();
+
+ range(const range &) = default;
cell_vector operator[](std::size_t vector_index);
diff --git a/include/xlnt/worksheet/range_iterator.hpp b/include/xlnt/worksheet/range_iterator.hpp
index 953976c7..39be8aed 100644
--- a/include/xlnt/worksheet/range_iterator.hpp
+++ b/include/xlnt/worksheet/range_iterator.hpp
@@ -28,15 +28,11 @@
#include
#include
#include
+#include
namespace xlnt {
class cell_vector;
-class worksheet;
-
-namespace detail {
-struct worksheet_impl;
-}
///
/// An iterator used by worksheet and range for traversing
@@ -45,11 +41,13 @@ struct worksheet_impl;
class XLNT_API range_iterator : public std::iterator
{
public:
- range_iterator(worksheet &ws, const range_reference &start_cell, major_order order = major_order::row);
+ range_iterator(worksheet &ws, const range_reference &start_cell, const range_reference &limits, major_order order = major_order::row);
range_iterator(const range_iterator &other);
cell_vector operator*() const;
+
+ range_iterator &operator=(const range_iterator &) = default;
bool operator==(const range_iterator &other) const;
@@ -64,7 +62,7 @@ public:
range_iterator operator++(int);
private:
- detail::worksheet_impl *ws_;
+ worksheet ws_;
cell_reference current_cell_;
range_reference range_;
major_order order_;
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index ad2bf86d..7e84e523 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -56,7 +56,7 @@ if(MSVC)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unknown-pragmas")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded -Werror")
endif()
if(APPLE)
@@ -117,7 +117,6 @@ if(NOT STATIC)
if(MSVC)
target_compile_definitions(xlnt PRIVATE XLNT_EXPORT=1 _CRT_SECURE_NO_WARNINGS=1)
- set_target_properties(xlnt PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\" /MP")
endif()
install(TARGETS xlnt
@@ -148,7 +147,6 @@ else()
if(MSVC)
target_compile_definitions(xlnt PRIVATE _CRT_SECURE_NO_WARNINGS=1 NOMINMAX)
- set_target_properties(xlnt PROPERTIES COMPILE_FLAGS "/MP")
endif()
install(TARGETS xlnt
@@ -160,6 +158,10 @@ endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE LIBSTUDXML_STATIC_LIB=1)
+if(MSVC)
+ set_target_properties(xlnt PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\" /wd\"4068\" /MP")
+endif()
+
source_group(xlnt FILES ${ROOT_HEADERS})
source_group(detail FILES ${DETAIL_HEADERS} ${DETAIL_SOURCES})
source_group(cell FILES ${CELL_HEADERS} ${CELL_SOURCES})
diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp
index c787f15c..6a949e07 100644
--- a/source/cell/cell.cpp
+++ b/source/cell/cell.cpp
@@ -25,6 +25,8 @@
#include
#include
+#include
+#include
#include
#include
#include
@@ -49,8 +51,6 @@
#include
#include
-#include
-
namespace {
std::pair cast_numeric(const std::string &s)
@@ -559,8 +559,8 @@ const workbook &cell::get_workbook() const
//TODO: this shares a lot of code with worksheet::get_point_pos, try to reduce repetion
std::pair cell::get_anchor() const
{
- static const double DefaultColumnWidth = 51.85;
- static const double DefaultRowHeight = 15.0;
+ static const auto DefaultColumnWidth = 51.85L;
+ static const auto DefaultRowHeight = 15.0L;
auto points_to_pixels = [](long double value, long double dpi)
{
@@ -569,7 +569,7 @@ std::pair cell::get_anchor() const
auto left_columns = d_->column_ - 1;
int left_anchor = 0;
- auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
+ auto default_width = points_to_pixels(DefaultColumnWidth, 96.0L);
for (column_t column_index = 1; column_index <= left_columns; column_index++)
{
@@ -579,7 +579,7 @@ std::pair cell::get_anchor() const
if (cdw > 0)
{
- left_anchor += points_to_pixels(cdw, 96.0);
+ left_anchor += points_to_pixels(cdw, 96.0L);
continue;
}
}
@@ -589,7 +589,7 @@ std::pair cell::get_anchor() const
auto top_rows = d_->row_ - 1;
int top_anchor = 0;
- auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
+ auto default_height = points_to_pixels(DefaultRowHeight, 96.0L);
for (row_t row_index = 1; row_index <= top_rows; row_index++)
{
@@ -599,7 +599,7 @@ std::pair cell::get_anchor() const
if (rdh > 0)
{
- top_anchor += points_to_pixels(rdh, 96.0);
+ top_anchor += points_to_pixels(rdh, 96.0L);
continue;
}
}
@@ -836,9 +836,11 @@ std::string cell::to_string() const
case cell::type::error:
return nf.format(get_value());
case cell::type::boolean:
- return get_value() == 0 ? "FALSE" : "TRUE";
+ return get_value() == 0.L ? "FALSE" : "TRUE";
+#ifdef WIN32
default:
- return "";
+ throw xlnt::exception("unhandled");
+#endif
}
}
@@ -849,6 +851,12 @@ bool cell::has_format() const
void cell::format(const class format new_format)
{
+ if (has_format())
+ {
+ format().d_->references -= format().d_->references > 0 ? 1 : 0;
+ }
+
+ ++new_format.d_->references;
d_->format_ = new_format.d_;
}
@@ -897,6 +905,7 @@ void cell::guess_type_and_set_value(const std::string &value)
void cell::clear_format()
{
+ format().d_->references -= format().d_->references > 0 ? 1 : 0;
d_->format_.clear();
}
diff --git a/source/cell/tests/test_cell.hpp b/source/cell/tests/test_cell.hpp
index ce2eac05..5ba2f6fd 100644
--- a/source/cell/tests/test_cell.hpp
+++ b/source/cell/tests/test_cell.hpp
@@ -7,11 +7,26 @@
#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int random(int min, int max)
+{
+ static std::random_device device{};
+ static std::default_random_engine engine{ device() };
+ std::uniform_int_distribution distribution{ min, max };
+ return distribution(engine);
+}
+
class test_cell : public CxxTest::TestSuite
{
private:
xlnt::workbook wb, wb_guess_types;
-
+
public:
test_cell()
{
diff --git a/source/detail/constants.cpp b/source/detail/constants.cpp
index eb379ccf..2075246e 100644
--- a/source/detail/constants.cpp
+++ b/source/detail/constants.cpp
@@ -66,7 +66,7 @@ const path constants::part_shared_strings() { return package_xl().append("shared
const std::unordered_map &constants::get_namespaces()
{
- const std::unordered_map *namespaces =
+ static const std::unordered_map *namespaces =
new std::unordered_map
{
{ "worksheet", "http://schemas.openxmlformats.org/spreadsheetml/2006/main" },
@@ -76,6 +76,10 @@ const std::unordered_map &constants::get_namespaces()
{ "workbook", "http://schemas.openxmlformats.org/spreadsheetml/2006/main" },
{ "core-properties", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" },
{ "extended-properties", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" },
+
+ { "encryption", "http://schemas.microsoft.com/office/2006/encryption" },
+ { "encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password" },
+ { "encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate" },
{ "dc", "http://purl.org/dc/elements/1.1/" },
{ "dcterms", "http://purl.org/dc/terms/" },
@@ -96,7 +100,7 @@ const std::unordered_map &constants::get_namespaces()
return *namespaces;
}
-const std::string constants::get_namespace(const std::string &id)
+const std::string &constants::get_namespace(const std::string &id)
{
return get_namespaces().find(id)->second;
}
diff --git a/source/detail/constants.hpp b/source/detail/constants.hpp
index 00b39e39..5af66821 100644
--- a/source/detail/constants.hpp
+++ b/source/detail/constants.hpp
@@ -130,7 +130,7 @@ struct XLNT_API constants
///
/// Returns the namespace URI from a namespace name.
///
- static const std::string get_namespace(const std::string &id);
+ static const std::string &get_namespace(const std::string &id);
};
} // namespace xlnt
diff --git a/source/detail/custom_value_traits.cpp b/source/detail/custom_value_traits.cpp
index 44db4b08..ca54b824 100644
--- a/source/detail/custom_value_traits.cpp
+++ b/source/detail/custom_value_traits.cpp
@@ -15,7 +15,9 @@ std::string to_string(font::underline_style style)
case font::underline_style::single: return "single";
case font::underline_style::single_accounting: return "singleAccounting";
case font::underline_style::none: return "none";
- default: return default_case("none");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -53,8 +55,54 @@ std::string to_string(relationship::type t)
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
case relationship::type::vml_drawing:
return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
- default:
- return default_case("?");
+ case relationship::type::unknown:
+ return "unknown";
+ case relationship::type::custom_properties:
+ return "custom-properties";
+ case relationship::type::printer_settings:
+ return "printer-settings";
+ case relationship::type::connections:
+ return "connections";
+ case relationship::type::custom_property:
+ return "custom-property";
+ case relationship::type::custom_xml_mappings:
+ return "custom-xml-mappings";
+ case relationship::type::dialogsheet:
+ return "dialogsheet";
+ case relationship::type::drawings:
+ return "drawings";
+ case relationship::type::external_workbook_references:
+ return "external-workbook-references";
+ case relationship::type::metadata:
+ return "metadata";
+ case relationship::type::pivot_table:
+ return "pivot-table";
+ case relationship::type::pivot_table_cache_definition:
+ return "pivot-table-cache-definition";
+ case relationship::type::pivot_table_cache_records:
+ return "pivot-table-cache-records";
+ case relationship::type::query_table:
+ return "query-table";
+ case relationship::type::shared_workbook_revision_headers:
+ return "shared-workbook-revision-headers";
+ case relationship::type::shared_workbook:
+ return "shared-workbook";
+ case relationship::type::revision_log:
+ return "revision-log";
+ case relationship::type::shared_workbook_user_data:
+ return "shared-workbook-user-data";
+ case relationship::type::single_cell_table_definitions:
+ return "single-cell-table-definitions";
+ case relationship::type::table_definition:
+ return "table-definition";
+ case relationship::type::volatile_dependencies:
+ return "volatile-dependencies";
+ case relationship::type::image:
+ return "image";
+#ifdef WIN32
+ default:
+ throw xlnt::exception("unhandled");
+#endif
}
}
@@ -81,7 +129,9 @@ std::string to_string(pattern_fill_type fill_type)
case pattern_fill_type::mediumgray: return "mediumgray";
case pattern_fill_type::solid: return "solid";
case pattern_fill_type::none: return "none";
- default: return default_case("none");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -108,7 +158,9 @@ std::string to_string(border_style style)
case border_style::thick: return "thick";
case border_style::thin: return "thin";
case border_style::none: return "none";
- default: return default_case("none");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -121,7 +173,9 @@ std::string to_string(vertical_alignment alignment)
case vertical_alignment::justify: return "justify";
case vertical_alignment::top: return "top";
case vertical_alignment::none: return "none";
- default: return default_case("none");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -136,7 +190,9 @@ std::string to_string(horizontal_alignment alignment)
case horizontal_alignment::left: return "left";
case horizontal_alignment::right: return "right";
case horizontal_alignment::none: return "none";
- default: return default_case("none");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -151,7 +207,9 @@ std::string to_string(border_side side)
case border_side::horizontal: return "horizontal";
case border_side::vertical: return "vertical";
case border_side::diagonal: return "diagonal";
- default: return default_case("top");
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
diff --git a/source/detail/custom_value_traits.hpp b/source/detail/custom_value_traits.hpp
index 6c19842a..6b75c9e6 100644
--- a/source/detail/custom_value_traits.hpp
+++ b/source/detail/custom_value_traits.hpp
@@ -1,7 +1,6 @@
#pragma once
-#include
-#include
+#include
#include
#include
diff --git a/source/detail/excel_thumbnail.hpp b/source/detail/excel_thumbnail.hpp
index 29637d74..b62078cc 100644
--- a/source/detail/excel_thumbnail.hpp
+++ b/source/detail/excel_thumbnail.hpp
@@ -9,7 +9,7 @@ const std::vector &excel_thumbnail();
const std::vector &excel_thumbnail()
{
- const auto *data = new std::vector{
+ static const auto *data = new std::vector{
0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x00,0x00,0x48,0x00,0x48,0x00,0x00,0xff,0xe1,0x00,0x80,0x45,0x78,0x69,0x66,0x00,0x00,0x4d,0x4d,0x00
,0x2a,0x00,0x00,0x00,0x08,0x00,0x04,0x01,0x1a,0x00,0x05,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3e,0x01,0x1b,0x00,0x05,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x46,0x01
,0x28,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x87,0x69,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00
diff --git a/source/detail/format_impl.hpp b/source/detail/format_impl.hpp
index 00d4360e..85dacdeb 100644
--- a/source/detail/format_impl.hpp
+++ b/source/detail/format_impl.hpp
@@ -49,6 +49,8 @@ struct format_impl
optional style;
+ std::size_t references = 0;
+
XLNT_API friend bool operator==(const format_impl &left, const format_impl &right)
{
return left.parent == right.parent
diff --git a/source/detail/include_botan.hpp b/source/detail/include_botan.hpp
new file mode 100644
index 00000000..94a12e63
--- /dev/null
+++ b/source/detail/include_botan.hpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2014-2016 Thomas Fussell
+//
+// 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, WRISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE
+//
+// @license: http://www.opensource.org/licenses/mit-license.php
+// @author: see AUTHORS file
+
+#pragma clang diagnostic push
+
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include
+
+#pragma clang diagnostic pop
diff --git a/source/detail/include_libstudxml.hpp b/source/detail/include_libstudxml.hpp
index eb88eb3d..c9d69584 100644
--- a/source/detail/include_libstudxml.hpp
+++ b/source/detail/include_libstudxml.hpp
@@ -22,7 +22,12 @@
// @author: see AUTHORS file
#pragma once
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#pragma clang diagnostic ignored "-Wextra-semi"
+#pragma clang diagnostic ignored "-Wdeprecated"
#include
#include
#include
#include
+#pragma clang diagnostic pop
diff --git a/source/detail/number_formatter.cpp b/source/detail/number_formatter.cpp
index 17a41cd2..7fe1b306 100644
--- a/source/detail/number_formatter.cpp
+++ b/source/detail/number_formatter.cpp
@@ -179,6 +179,10 @@ bool format_condition::satisfied_by(long double number) const
return std::fabs(number - value) >= std::numeric_limits::min();
case condition_type::equal:
return std::fabs(number - value) < std::numeric_limits::min();
+#ifdef WIN32
+ default:
+ throw xlnt::exception("unhandled");
+#endif
}
}
@@ -634,7 +638,7 @@ void number_format_parser::finalize()
auto temp = code.parts[exponent_index].placeholders.type;
code.parts[exponent_index].placeholders = next.placeholders;
code.parts[exponent_index].placeholders.type = temp;
- code.parts.erase(code.parts.begin() + exponent_index + 1);
+ code.parts.erase(code.parts.begin() + static_cast::difference_type>(exponent_index + 1));
for (std::size_t i = 0; i < code.parts.size(); ++i)
{
@@ -1261,7 +1265,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
if (p.thousands_scale > 0)
{
- number /= std::pow(1000, p.thousands_scale);
+ number /= std::pow(1000.L, p.thousands_scale);
}
auto integer_part = static_cast(number);
@@ -1341,9 +1345,9 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol
{
std::size_t logarithm = 0;
- if (number != 0)
+ if (number != 0.L)
{
- logarithm = static_cast(std::log10(number));
+ logarithm = static_cast(std::log10(number));
if (integer_part.num_zeros + integer_part.num_optionals > 1)
{
@@ -1351,14 +1355,14 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol
}
}
- number /= std::pow(10, logarithm);
+ number /= std::pow(10.L, logarithm);
auto integer = static_cast(number);
auto fraction = number - integer;
std::string integer_string = std::to_string(integer);
- if (number == 0)
+ if (number == 0.L)
{
integer_string = std::string(integer_part.num_zeros + integer_part.num_optionals, '0');
}
@@ -1389,15 +1393,15 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol
return integer_string + fractional_string + exponent_string;
}
-std::string number_formatter::fill_fraction_placeholders(const format_placeholders &numerator,
- const format_placeholders &denominator, long double number, bool improper)
+std::string number_formatter::fill_fraction_placeholders(const format_placeholders &/*numerator*/,
+ const format_placeholders &denominator, long double number, bool /*improper*/)
{
auto fractional_part = number - static_cast(number);
auto original_fractional_part = fractional_part;
fractional_part *= 10;
- while (std::abs(fractional_part - static_cast(fractional_part)) > 0.000001
- && std::abs(fractional_part - static_cast(fractional_part)) < 0.999999)
+ while (std::abs(fractional_part - static_cast(fractional_part)) > 0.000001L
+ && std::abs(fractional_part - static_cast(fractional_part)) < 0.999999L)
{
fractional_part *= 10;
}
@@ -1478,12 +1482,12 @@ std::string number_formatter::format_number(const format_code &format, long doub
if (format.is_datetime)
{
- if (number != 0)
+ if (number != 0.L)
{
dt = xlnt::datetime::from_number(number, calendar_);
}
- hour = dt.hour;
+ hour = static_cast(dt.hour);
if (format.twelve_hour)
{
@@ -1526,7 +1530,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
{
auto digits = std::min(static_cast(6), part.placeholders.num_zeros + part.placeholders.num_optionals);
auto denominator = static_cast(std::pow(10.0, digits));
- auto fractional_seconds = dt.microsecond / 1.0E6 * denominator;
+ auto fractional_seconds = dt.microsecond / 1.0E6L * denominator;
fractional_seconds = std::round(fractional_seconds) / denominator;
result.append(fill_placeholders(part.placeholders, fractional_seconds));
break;
@@ -1541,7 +1545,7 @@ std::string number_formatter::format_number(const format_code &format, long doub
{
i += 2;
- if (number == 0)
+ if (number == 0.L)
{
result.pop_back();
break;
@@ -1576,10 +1580,10 @@ std::string number_formatter::format_number(const format_code &format, long doub
result.append(std::to_string(dt.day));
break;
case template_part::template_type::month_abbreviation:
- result.append(month_names->at(dt.month - 1).substr(0, 3));
+ result.append(month_names->at(static_cast(dt.month) - 1).substr(0, 3));
break;
case template_part::template_type::month_name:
- result.append(month_names->at(dt.month - 1));
+ result.append(month_names->at(static_cast(dt.month) - 1));
break;
case template_part::template_type::month_number:
result.append(std::to_string(dt.month));
@@ -1684,15 +1688,15 @@ std::string number_formatter::format_number(const format_code &format, long doub
break;
case template_part::template_type::month_letter:
- result.append(month_names->at(dt.month - 1).substr(0, 1));
+ result.append(month_names->at(static_cast(dt.month) - 1).substr(0, 1));
break;
case template_part::template_type::day_abbreviation:
- result.append(day_names->at(dt.weekday() - 1).substr(0, 3));
+ result.append(day_names->at(static_cast(dt.weekday()) - 1).substr(0, 3));
break;
case template_part::template_type::day_name:
- result.append(day_names->at(dt.weekday() - 1));
+ result.append(day_names->at(static_cast(dt.weekday()) - 1));
break;
}
}
@@ -1736,8 +1740,32 @@ std::string number_formatter::format_text(const format_code &format, const std::
break;
- default:
- break;
+ case template_part::template_type::fill: break;
+ case template_part::template_type::space: break;
+ case template_part::template_type::month_number: break;
+ case template_part::template_type::month_number_leading_zero: break;
+ case template_part::template_type::month_abbreviation: break;
+ case template_part::template_type::month_name: break;
+ case template_part::template_type::month_letter: break;
+ case template_part::template_type::day_number: break;
+ case template_part::template_type::day_number_leading_zero: break;
+ case template_part::template_type::day_abbreviation: break;
+ case template_part::template_type::day_name: break;
+ case template_part::template_type::year_short: break;
+ case template_part::template_type::year_long: break;
+ case template_part::template_type::hour: break;
+ case template_part::template_type::hour_leading_zero: break;
+ case template_part::template_type::minute: break;
+ case template_part::template_type::minute_leading_zero: break;
+ case template_part::template_type::second: break;
+ case template_part::template_type::second_fractional: break;
+ case template_part::template_type::second_leading_zero: break;
+ case template_part::template_type::second_leading_zero_fractional: break;
+ case template_part::template_type::am_pm: break;
+ case template_part::template_type::a_p: break;
+ case template_part::template_type::elapsed_hours: break;
+ case template_part::template_type::elapsed_minutes: break;
+ case template_part::template_type::elapsed_seconds: break;
}
}
diff --git a/third-party/pole/pole.cpp b/source/detail/pole.cpp
similarity index 91%
rename from third-party/pole/pole.cpp
rename to source/detail/pole.cpp
index f576a47e..76150d19 100644
--- a/third-party/pole/pole.cpp
+++ b/source/detail/pole.cpp
@@ -31,11 +31,49 @@
#include
#include
-#include "pole.h"
+#include
// enable to activate debugging output
// #define POLE_DEBUG
+namespace {
+
+// helper function: recursively find siblings of index
+void dirtree_find_siblings( POLE::DirTree* dirtree, std::vector& result,
+ std::size_t index )
+{
+ auto e = dirtree->entry( index );
+ if( !e ) return;
+ if( !e->valid ) return;
+
+ // prevent infinite loop
+ for( std::size_t i = 0; i < result.size(); i++ )
+ if( result[i] == index ) return;
+
+ // add myself
+ result.push_back( index );
+
+ // visit previous sibling, don't go infinitely
+ std::size_t prev = e->prev;
+ if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
+ {
+ for( std::size_t i = 0; i < result.size(); i++ )
+ if( result[i] == prev ) prev = 0;
+ if( prev ) dirtree_find_siblings( dirtree, result, prev );
+ }
+
+ // visit next sibling, don't go infinitely
+ std::size_t next = e->next;
+ if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
+ {
+ for( std::size_t i = 0; i < result.size(); i++ )
+ if( result[i] == next ) next = 0;
+ if( next ) dirtree_find_siblings( dirtree, result, next );
+ }
+}
+
+}
+
namespace POLE
{
@@ -44,28 +82,28 @@ namespace POLE
using namespace POLE;
-static inline std::uint16_t readU16( const std::uint8_t* ptr )
+static inline std::uint16_t readU16(const std::uint8_t* ptr)
{
- return ptr[0]+(ptr[1]<<8);
+ return static_cast(ptr[0] + (ptr[1] << 8));
}
-static inline std::uint32_t readU32( const std::uint8_t* ptr )
+static inline std::uint32_t readU32(const std::uint8_t* ptr)
{
- return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
+ return static_cast(ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24));
}
static inline void writeU16( std::uint8_t* ptr, std::uint16_t data )
{
- ptr[0] = (std::uint8_t)(data & 0xff);
- ptr[1] = (std::uint8_t)((data >> 8) & 0xff);
+ ptr[0] = static_cast(data & 0xff);
+ ptr[1] = static_cast((data >> 8) & 0xff);
}
static inline void writeU32( std::uint8_t* ptr, std::uint32_t data )
{
- ptr[0] = (std::uint8_t)(data & 0xff);
- ptr[1] = (std::uint8_t)((data >> 8) & 0xff);
- ptr[2] = (std::uint8_t)((data >> 16) & 0xff);
- ptr[3] = (std::uint8_t)((data >> 24) & 0xff);
+ ptr[0] = static_cast(data & 0xff);
+ ptr[1] = static_cast((data >> 8) & 0xff);
+ ptr[2] = static_cast((data >> 16) & 0xff);
+ ptr[3] = static_cast((data >> 24) & 0xff);
}
static const std::uint8_t pole_magic[] =
@@ -243,9 +281,9 @@ std::vector AllocTable::follow( std::size_t start )
std::size_t p = start;
while( p < count() )
{
- if( p == (std::size_t)Eof ) break;
- if( p == (std::size_t)Bat ) break;
- if( p == (std::size_t)MetaBat ) break;
+ if( p == static_cast(Eof) ) break;
+ if( p == static_cast(Bat) ) break;
+ if( p == static_cast(MetaBat) ) break;
if( already_exist(chain, p) ) break;
chain.push_back(p);
if( data[p] >= count() ) break;
@@ -332,14 +370,14 @@ std::size_t DirTree::entryCount()
DirEntry* DirTree::entry( std::size_t index )
{
- if( index >= entryCount() ) return (DirEntry*) 0;
+ if( index >= entryCount() ) return nullptr;
return &entries[ index ];
}
std::ptrdiff_t DirTree::indexOf( DirEntry* e )
{
for( std::size_t i = 0; i < entryCount(); i++ )
- if( entry( i ) == e ) return i;
+ if( entry( i ) == e ) return static_cast(i);
return -1;
}
@@ -353,7 +391,7 @@ std::ptrdiff_t DirTree::parent( std::size_t index )
std::vector chi = children( j );
for( std::size_t i=0; i(j);
}
return -1;
@@ -370,15 +408,15 @@ std::string DirTree::fullName( std::size_t index )
DirEntry * _entry = 0;
while( p > 0 )
{
- _entry = entry( p );
+ _entry = entry( static_cast(p) );
if (_entry->dir && _entry->valid)
{
result.insert( 0, _entry->name);
result.insert( 0, "/" );
}
--p;
- index = p;
- if( index <= 0 ) break;
+ index = static_cast(p);
+ if( p <= 0 ) break;
}
return result;
}
@@ -388,7 +426,7 @@ std::string DirTree::fullName( std::size_t index )
// if create is true, a new entry is returned
DirEntry* DirTree::entry( const std::string& name, bool create )
{
- if( !name.length() ) return (DirEntry*)0;
+ if( !name.length() ) return nullptr;
// quick check for "/" (that's root)
if( name == "/" ) return entry( 0 );
@@ -423,15 +461,15 @@ DirEntry* DirTree::entry( const std::string& name, bool create )
if( ce )
if( ce->valid && ( ce->name.length()>1 ) )
if( ce->name == *it )
- child = chi[i];
+ child = static_cast(chi[i]);
}
// traverse to the child
- if( child > 0 ) index = child;
+ if( child > 0 ) index = static_cast(child);
else
{
// not found among children
- if( !create ) return (DirEntry*)0;
+ if( !create ) return nullptr;
// create a new entry
std::size_t parent = index;
@@ -453,40 +491,6 @@ DirEntry* DirTree::entry( const std::string& name, bool create )
return entry( index );
}
-// helper function: recursively find siblings of index
-void dirtree_find_siblings( DirTree* dirtree, std::vector& result,
- std::size_t index )
-{
- DirEntry* e = dirtree->entry( index );
- if( !e ) return;
- if( !e->valid ) return;
-
- // prevent infinite loop
- for( std::size_t i = 0; i < result.size(); i++ )
- if( result[i] == index ) return;
-
- // add myself
- result.push_back( index );
-
- // visit previous sibling, don't go infinitely
- std::size_t prev = e->prev;
- if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) )
- {
- for( std::size_t i = 0; i < result.size(); i++ )
- if( result[i] == prev ) prev = 0;
- if( prev ) dirtree_find_siblings( dirtree, result, prev );
- }
-
- // visit next sibling, don't go infinitely
- std::size_t next = e->next;
- if( ( next > 0 ) && ( next < dirtree->entryCount() ) )
- {
- for( std::size_t i = 0; i < result.size(); i++ )
- if( result[i] == next ) next = 0;
- if( next ) dirtree_find_siblings( dirtree, result, next );
- }
-}
-
std::vector DirTree::children( std::size_t index )
{
std::vector result;
@@ -511,10 +515,10 @@ void DirTree::load( std::uint8_t* buffer, std::size_t size )
// parse name of this entry, which stored as Unicode 16-bit
std::string name;
- int name_len = readU16( buffer + 0x40+p );
+ auto name_len = static_cast(readU16( buffer + 0x40+p ));
if( name_len > 64 ) name_len = 64;
- for( int j=0; ( buffer[j+p]) && (j(buffer[j+p]) );
// first char isn't printable ? remove it...
if( buffer[p] < 32 )
@@ -556,10 +560,10 @@ void DirTree::save( std::uint8_t* buffer )
// root is fixed as "Root Entry"
DirEntry* root = entry( 0 );
- std::string name = "Root Entry";
- for( std::size_t j = 0; j < name.length(); j++ )
- buffer[ j*2 ] = name[j];
- writeU16( buffer + 0x40, static_cast(name.length()*2 + 2) );
+ std::string entry_name = "Root Entry";
+ for( std::size_t j = 0; j < entry_name.length(); j++ )
+ buffer[ j*2 ] = static_cast(entry_name[j]);
+ writeU16( buffer + 0x40, static_cast(entry_name.length()*2 + 2) );
writeU32( buffer + 0x74, 0xffffffff );
writeU32( buffer + 0x78, 0 );
writeU32( buffer + 0x44, 0xffffffff );
@@ -579,15 +583,15 @@ void DirTree::save( std::uint8_t* buffer )
}
// max length for name is 32 chars
- std::string name = e->name;
- if( name.length() > 32 )
- name.erase( 32, name.length() );
+ entry_name = e->name;
+ if( entry_name.length() > 32 )
+ entry_name.erase( 32, entry_name.length() );
// write name as Unicode 16-bit
- for( std::size_t j = 0; j < name.length(); j++ )
- buffer[ i*128 + j*2 ] = name[j];
+ for( std::size_t j = 0; j < entry_name.length(); j++ )
+ buffer[ i*128 + j*2 ] = static_cast(entry_name[j]);
- writeU16( buffer + i*128 + 0x40, static_cast(name.length()*2 + 2) );
+ writeU16( buffer + i*128 + 0x40, static_cast(entry_name.length()*2 + 2) );
writeU32( buffer + i*128 + 0x74, e->start );
writeU32( buffer + i*128 + 0x78, e->size );
writeU32( buffer + i*128 + 0x44, e->prev );
@@ -626,7 +630,7 @@ void DirTree::debug()
StorageIO::StorageIO( Storage* st, char* bytes, std::size_t length ):
storage( st ),
-filedata((std::uint8_t *)bytes),
+filedata(reinterpret_cast(bytes)),
dataLength(length),
result( Storage::Ok ),
opened( false ),
@@ -818,19 +822,19 @@ void StorageIO::close()
StreamIO* StorageIO::streamIO( const std::string& name )
{
// sanity check
- if( !name.length() ) return (StreamIO*)0;
+ if( !name.length() ) return nullptr;
// search in the entries
DirEntry* entry = dirtree->entry( name );
//if( entry) std::cout << "FOUND\n";
- if( !entry ) return (StreamIO*)0;
+ if( !entry ) return nullptr;
//if( !entry->dir ) std::cout << " NOT DIR\n";
- if( entry->dir ) return (StreamIO*)0;
+ if( entry->dir ) return nullptr;
- StreamIO* result = new StreamIO( this, entry );
- result->fullName = name;
+ StreamIO* stream = new StreamIO( this, entry );
+ stream->fullName = name;
- return result;
+ return stream;
}
std::size_t StorageIO::loadBigBlocks( std::vector blocks,
@@ -851,7 +855,7 @@ std::size_t StorageIO::loadBigBlocks( std::vector blocks,
if( pos + p > filesize ) p = filesize - pos;
//FSTREAM file.seekg( pos );
//FSTREAM file.read( (char*)data + bytes, p );
- memcpy((char*)data + bytes, filedata + pos, p);
+ memcpy(reinterpret_cast(data) + bytes, filedata + pos, p);
bytes += p;
}
@@ -1094,8 +1098,8 @@ std::list Storage::entries( const std::string& path )
DirEntry* e = dt->entry( path, false );
if( e && e->dir )
{
- std::size_t parent = dt->indexOf( e );
- std::vector children = dt->children( parent );
+ auto parent = dt->indexOf( e );
+ std::vector children = dt->children( static_cast(parent) );
for( std::size_t i = 0; i < children.size(); i++ )
result.push_back( dt->entry( children[i] )->name );
}
@@ -1127,8 +1131,8 @@ std::list Storage::dirEntries( const std::string& path )
DirEntry* e = dt->entry( path, false );
if( e && e->dir )
{
- std::size_t parent = dt->indexOf( e );
- std::vector children = dt->children( parent );
+ auto parent = dt->indexOf( e );
+ std::vector children = dt->children( static_cast(parent) );
for( std::size_t i = 0; i < children.size(); i++ )
result.push_back( dt->entry( children[i] ) );
}
diff --git a/third-party/pole/pole.h b/source/detail/pole.hpp
similarity index 99%
rename from third-party/pole/pole.h
rename to source/detail/pole.hpp
index 69f54438..42d8f8fb 100644
--- a/third-party/pole/pole.h
+++ b/source/detail/pole.hpp
@@ -23,8 +23,7 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef POLE_H
-#define POLE_H
+#pragma once
#include
#include
@@ -36,7 +35,6 @@
namespace POLE
{
-
class StorageIO;
class Stream;
class StreamIO;
@@ -353,6 +351,3 @@ namespace POLE
};
} // namespace POLE
-
-
-#endif // POLE_H
diff --git a/source/detail/stylesheet.hpp b/source/detail/stylesheet.hpp
index 0c5cc171..95e9dc5d 100644
--- a/source/detail/stylesheet.hpp
+++ b/source/detail/stylesheet.hpp
@@ -42,7 +42,7 @@ namespace detail {
struct stylesheet
{
- format create_format()
+ format create_format(bool default_format)
{
format_impls.push_back(format_impl());
auto &impl = format_impls.back();
@@ -55,16 +55,18 @@ struct stylesheet
impl.font_id = 0;
impl.number_format_id = 0;
+ impl.references = default_format ? 1 : 0;
+
return format(&impl);
}
- format get_format(std::size_t index)
- {
+ format get_format(std::size_t index)
+ {
auto iter = format_impls.begin();
- std::advance(iter, index);
- return format(&*iter);
- }
-
+ std::advance(iter, static_cast::difference_type>(index));
+ return format(&*iter);
+ }
+
class style create_style(const std::string &name)
{
auto &impl = style_impls.emplace(name, style_impl()).first->second;
@@ -142,7 +144,7 @@ struct stylesheet
if (reference_counts.count(i) == 0 || reference_counts.at(i) == 0)
{
- container.erase(container.begin() + i - unreferenced);
+ container.erase(container.begin() + static_cast::difference_type>(i - unreferenced));
unreferenced++;
}
}
@@ -150,40 +152,24 @@ struct stylesheet
return id_map;
}
- void garbage_collect(std::size_t new_format, std::size_t old_format)
+ void garbage_collect()
{
if (!garbage_collection_enabled) return;
+
+ auto format_iter = format_impls.begin();
- std::unordered_map format_reference_counts;
-
- for (const auto &impl : format_impls)
+ while (format_iter != format_impls.end())
{
- format_reference_counts[impl.id] = 0;
- }
-
- format_reference_counts[new_format]++;
-
- parent->apply_to_cells([&format_reference_counts](cell c)
- {
- if (c.has_format())
+ auto &impl = *format_iter;
+
+ if (impl.references != 0)
{
- format_reference_counts[c.format().id()]++;
+ ++format_iter;
+ }
+ else
+ {
+ format_iter = format_impls.erase(format_iter);
}
- });
-
- if (format_reference_counts[old_format] > 0)
- {
- format_reference_counts[old_format]--;
- }
-
- for (const auto &id_count_pair : format_reference_counts)
- {
- if (id_count_pair.second != 0) continue;
-
- auto target_id = id_count_pair.first;
- auto target = std::find_if(format_impls.begin(), format_impls.end(),
- [=](const format_impl &impl) { return impl.id == target_id; });
- format_impls.erase(target);
}
std::size_t new_id = 0;
@@ -195,6 +181,9 @@ struct stylesheet
std::unordered_map number_format_reference_counts;
std::unordered_map protection_reference_counts;
+ fill_reference_counts[0]++;
+ fill_reference_counts[1]++;
+
for (auto &impl : format_impls)
{
impl.id = new_id++;
@@ -269,7 +258,6 @@ struct stylesheet
auto border_id_map = garbage_collect(border_reference_counts, borders);
auto fill_id_map = garbage_collect(fill_reference_counts, fills);
auto font_id_map = garbage_collect(font_reference_counts, fonts);
- auto number_format_id_map = garbage_collect(number_format_reference_counts, number_formats);
auto protection_id_map = garbage_collect(protection_reference_counts, protections);
for (auto &impl : format_impls)
@@ -294,9 +282,34 @@ struct stylesheet
impl.font_id = font_id_map[impl.font_id.get()];
}
- if (impl.number_format_id.is_set())
+ if (impl.protection_id.is_set())
{
- impl.number_format_id = number_format_id_map[impl.number_format_id.get()];
+ impl.protection_id = protection_id_map[impl.protection_id.get()];
+ }
+ }
+
+ for (auto &name_impl : style_impls)
+ {
+ auto &impl = name_impl.second;
+
+ if (impl.alignment_id.is_set())
+ {
+ impl.alignment_id = alignment_id_map[impl.alignment_id.get()];
+ }
+
+ if (impl.border_id.is_set())
+ {
+ impl.border_id = border_id_map[impl.border_id.get()];
+ }
+
+ if (impl.fill_id.is_set())
+ {
+ impl.fill_id = fill_id_map[impl.fill_id.get()];
+ }
+
+ if (impl.font_id.is_set())
+ {
+ impl.font_id = font_id_map[impl.font_id.get()];
}
if (impl.protection_id.is_set())
@@ -306,11 +319,11 @@ struct stylesheet
}
}
- format_impl *find_or_create(const format_impl &pattern)
+ format_impl *find_or_create(format_impl &pattern)
{
auto iter = format_impls.begin();
auto id = find_or_add(format_impls, pattern);
- std::advance(iter, id);
+ std::advance(iter, static_cast::difference_type>(id));
auto &result = *iter;
@@ -319,12 +332,22 @@ struct stylesheet
if (id != pattern.id)
{
- garbage_collect(id, pattern.id);
+ pattern.references -= pattern.references > 0 ? 1 : 0;
+ ++result.references;
+ garbage_collect();
}
return &result;
}
+ format_impl *find_or_create_with(format_impl *pattern, const std::string &style_name)
+ {
+ format_impl new_format = *pattern;
+ new_format.style = style_name;
+
+ return find_or_create(new_format);
+ }
+
format_impl *find_or_create_with(format_impl *pattern, const alignment &new_alignment, bool applied)
{
format_impl new_format = *pattern;
@@ -381,8 +404,8 @@ struct stylesheet
std::size_t style_index(const std::string &name) const
{
- return std::distance(style_names.begin(),
- std::find(style_names.begin(), style_names.end(), name));
+ return static_cast(std::distance(style_names.begin(),
+ std::find(style_names.begin(), style_names.end(), name)));
}
void clear()
@@ -401,16 +424,6 @@ struct stylesheet
colors.clear();
}
-
- void enable_garbage_collection()
- {
- garbage_collection_enabled = true;
- }
-
- void disable_garbage_collection()
- {
- garbage_collection_enabled = false;
- }
workbook *parent;
diff --git a/source/detail/vector_streambuf.hpp b/source/detail/vector_streambuf.hpp
index 1a02f246..54021c96 100644
--- a/source/detail/vector_streambuf.hpp
+++ b/source/detail/vector_streambuf.hpp
@@ -28,6 +28,9 @@
namespace xlnt {
namespace detail {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+
///
/// Allows a std::vector to be read through a std::istream.
///
@@ -160,7 +163,7 @@ private:
{
if (c != traits_type::eof())
{
- data_.push_back(c);
+ data_.push_back(static_cast(c));
position_ = data_.size() - 1;
}
@@ -248,5 +251,7 @@ private:
std::size_t position_;
};
+#pragma clang diagnostic pop
+
} // namespace detail
} // namespace xlnt
diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp
index a6bc9a19..71348736 100644
--- a/source/detail/xlsx_consumer.cpp
+++ b/source/detail/xlsx_consumer.cpp
@@ -101,15 +101,15 @@ xlnt::color read_color(xml::parser &parser)
std::vector read_relationships(const xlnt::path &part, xlnt::detail::ZipFileReader &archive)
{
- std::vector relationships;
- if (!archive.has_file(part.string())) return relationships;
+ std::vector relationships;
+ if (!archive.has_file(part.string())) return relationships;
auto &rels_stream = archive.open(part.string());
xml::parser parser(rels_stream, part.string());
xlnt::uri source(part.string());
- const auto xmlns = xlnt::constants::get_namespace("relationships");
+ static const auto &xmlns = xlnt::constants::get_namespace("relationships");
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Relationships");
parser.content(xml::content::complex);
@@ -221,8 +221,30 @@ void xlsx_consumer::populate_workbook()
read_volatile_dependencies();
break;
- default:
- break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::worksheet: break;
+ case relationship::type::shared_string_table: break;
+ case relationship::type::styles: break;
+ case relationship::type::theme: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::chartsheet: break;
+ case relationship::type::comments: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::dialogsheet: break;
+ case relationship::type::drawings: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::image: break;
}
parser_ = nullptr;
@@ -235,9 +257,12 @@ void xlsx_consumer::populate_workbook()
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
{
path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
+ auto receive = xml::parser::receive_default;
auto using_namespaces = rel.get_type() == relationship::type::styles;
- auto receive = xml::parser::receive_default
- | (using_namespaces ? xml::parser::receive_namespace_decls : 0);
+ if (using_namespaces)
+ {
+ receive |= xml::parser::receive_namespace_decls;
+ }
xml::parser parser(archive_->open(part_path.string()), part_path.string(), receive);
parser_ = &parser;
@@ -255,8 +280,38 @@ void xlsx_consumer::populate_workbook()
read_theme();
break;
- default:
- break;
+ case relationship::type::office_document: break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::extended_properties: break;
+ case relationship::type::core_properties: break;
+ case relationship::type::worksheet: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::chartsheet: break;
+ case relationship::type::comments: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::custom_properties: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::connections: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::custom_xml_mappings: break;
+ case relationship::type::dialogsheet: break;
+ case relationship::type::drawings: break;
+ case relationship::type::external_workbook_references: break;
+ case relationship::type::metadata: break;
+ case relationship::type::pivot_table: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook_revision_headers: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::volatile_dependencies: break;
+ case relationship::type::image: break;
}
parser_ = nullptr;
@@ -265,11 +320,12 @@ void xlsx_consumer::populate_workbook()
// Second pass, read sheets themselves
for (const auto &rel : manifest.get_relationships(workbook_rel.get_target().get_path()))
- {
- path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
- auto receive = xml::parser::receive_default | xml::parser::receive_namespace_decls;
- xml::parser parser(archive_->open(part_path.string()), rel.get_target().get_path().string(), receive);
- parser_ = &parser;
+ {
+ path part_path(rel.get_source().get_path().parent().append(rel.get_target().get_path()));
+ auto receive = xml::parser::receive_default;
+ receive |= xml::parser::receive_namespace_decls;
+ xml::parser parser(archive_->open(part_path.string()), rel.get_target().get_path().string(), receive);
+ parser_ = &parser;
switch (rel.get_type())
{
@@ -285,8 +341,38 @@ void xlsx_consumer::populate_workbook()
read_worksheet(rel.get_id());
break;
- default:
- break;
+ case relationship::type::office_document: break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::extended_properties: break;
+ case relationship::type::core_properties: break;
+ case relationship::type::shared_string_table: break;
+ case relationship::type::styles: break;
+ case relationship::type::theme: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::comments: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::custom_properties: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::connections: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::custom_xml_mappings: break;
+ case relationship::type::drawings: break;
+ case relationship::type::external_workbook_references: break;
+ case relationship::type::metadata: break;
+ case relationship::type::pivot_table: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook_revision_headers: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::volatile_dependencies: break;
+ case relationship::type::image: break;
}
parser_ = nullptr;
@@ -312,7 +398,7 @@ void xlsx_consumer::read_manifest()
auto package_rels = read_relationships(package_rels_path, *archive_);
auto &manifest = target_.get_manifest();
- static const auto xmlns = constants::get_namespace("content-types");
+ static const auto &xmlns = constants::get_namespace("content-types");
xml::parser parser(archive_->open("[Content_Types].xml"), "[Content_Types].xml");
parser.next_expect(xml::parser::event_type::start_element, xmlns, "Types");
@@ -364,7 +450,7 @@ void xlsx_consumer::read_manifest()
auto part_rels = read_relationships(relationship_source, *archive_);
- for (const auto part_rel : part_rels)
+ for (const auto &part_rel : part_rels)
{
path target_path(source_directory.append(part_rel.get_target().get_path()));
manifest.register_relationship(source, part_rel.get_type(),
@@ -375,8 +461,8 @@ void xlsx_consumer::read_manifest()
void xlsx_consumer::read_extended_properties()
{
- static const auto xmlns = constants::get_namespace("extended-properties");
- static const auto xmlns_vt = constants::get_namespace("vt");
+ static const auto &xmlns = constants::get_namespace("extended-properties");
+ static const auto &xmlns_vt = constants::get_namespace("vt");
parser().next_expect(xml::parser::event_type::start_element, xmlns, "Properties");
parser().content(xml::parser::content_type::complex);
@@ -459,11 +545,10 @@ void xlsx_consumer::read_extended_properties()
void xlsx_consumer::read_core_properties()
{
- static const auto xmlns_cp = constants::get_namespace("core-properties");
- static const auto xmlns_dc = constants::get_namespace("dc");
- static const auto xmlns_dcterms = constants::get_namespace("dcterms");
- static const auto xmlns_dcmitype = constants::get_namespace("dcmitype");
- static const auto xmlns_xsi = constants::get_namespace("xsi");
+ static const auto &xmlns_cp = constants::get_namespace("core-properties");
+ static const auto &xmlns_dc = constants::get_namespace("dc");
+ static const auto &xmlns_dcterms = constants::get_namespace("dcterms");
+ static const auto &xmlns_xsi = constants::get_namespace("xsi");
parser().next_expect(xml::parser::event_type::start_element, xmlns_cp, "coreProperties");
parser().content(xml::parser::content_type::complex);
@@ -514,13 +599,13 @@ void xlsx_consumer::read_custom_file_properties()
void xlsx_consumer::read_workbook()
{
- static const auto xmlns = constants::get_namespace("workbook");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_mx = constants::get_namespace("mx");
- static const auto xmlns_r = constants::get_namespace("r");
- static const auto xmlns_s = constants::get_namespace("worksheet");
- static const auto xmlns_x15 = constants::get_namespace("x15");
- static const auto xmlns_x15ac = constants::get_namespace("x15ac");
+ static const auto &xmlns = constants::get_namespace("workbook");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_mx = constants::get_namespace("mx");
+ static const auto &xmlns_r = constants::get_namespace("r");
+ static const auto &xmlns_s = constants::get_namespace("worksheet");
+ static const auto &xmlns_x15 = constants::get_namespace("x15");
+ static const auto &xmlns_x15ac = constants::get_namespace("x15ac");
parser().next_expect(xml::parser::event_type::start_element, xmlns, "workbook");
parser().content(xml::parser::content_type::complex);
@@ -809,7 +894,7 @@ void xlsx_consumer::read_pivot_table()
void xlsx_consumer::read_shared_string_table()
{
- static const auto xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns = constants::get_namespace("worksheet");
parser().next_expect(xml::parser::event_type::start_element, xmlns, "sst");
parser().content(xml::content::complex);
@@ -916,11 +1001,11 @@ void xlsx_consumer::read_shared_workbook_user_data()
void xlsx_consumer::read_stylesheet()
{
- static const auto xmlns = constants::get_namespace("worksheet");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_x14 = constants::get_namespace("x14");
- static const auto xmlns_x14ac = constants::get_namespace("x14ac");
- static const auto xmlns_x15 = constants::get_namespace("x15");
+ static const auto &xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_x14 = constants::get_namespace("x14");
+ static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
+ static const auto &xmlns_x15 = constants::get_namespace("x15");
auto &stylesheet = target_.impl().stylesheet_;
@@ -1559,7 +1644,9 @@ void xlsx_consumer::read_stylesheet()
new_format.id = record_index++;
new_format.parent = &stylesheet;
-
+
+ ++new_format.references;
+
if (record.style_id.second)
{
new_format.style = stylesheet.style_names[record.style_id.first];
@@ -1591,10 +1678,10 @@ void xlsx_consumer::read_volatile_dependencies()
void xlsx_consumer::read_worksheet(const std::string &rel_id)
{
- static const auto xmlns = constants::get_namespace("worksheet");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_r = constants::get_namespace("r");
- static const auto xmlns_x14ac = constants::get_namespace("x14ac");
+ static const auto &xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_r = constants::get_namespace("r");
+ static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
target_.d_->sheet_title_rel_id_map_.end(),
@@ -2033,8 +2120,40 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
read_comments(ws);
break;
- default:
- break;
+ case relationship::type::office_document: break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::extended_properties: break;
+ case relationship::type::core_properties: break;
+ case relationship::type::worksheet: break;
+ case relationship::type::shared_string_table: break;
+ case relationship::type::styles: break;
+ case relationship::type::theme: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::chartsheet: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::custom_properties: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::connections: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::custom_xml_mappings: break;
+ case relationship::type::dialogsheet: break;
+ case relationship::type::drawings: break;
+ case relationship::type::external_workbook_references: break;
+ case relationship::type::metadata: break;
+ case relationship::type::pivot_table: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook_revision_headers: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::volatile_dependencies: break;
+ case relationship::type::image: break;
}
parser_ = nullptr;
@@ -2045,7 +2164,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
void xlsx_consumer::read_comments(worksheet ws)
{
- static const auto xmlns = xlnt::constants::get_namespace("worksheet");
+ static const auto &xmlns = xlnt::constants::get_namespace("worksheet");
std::vector authors;
diff --git a/source/detail/xlsx_crypto.cpp b/source/detail/xlsx_crypto.cpp
index 16d054ef..5c589bac 100644
--- a/source/detail/xlsx_crypto.cpp
+++ b/source/detail/xlsx_crypto.cpp
@@ -20,11 +20,13 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
-#include
-#include
-#include
-#include
+#include
+
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -34,6 +36,66 @@
namespace xlnt {
namespace detail {
+enum class hash_algorithm
+{
+ sha1,
+ sha256,
+ sha384,
+ sha512,
+ md5,
+ md4,
+ md2,
+ ripemd128,
+ ripemd160,
+ whirlpool
+};
+
+} // namespace detail
+} // namespace xlnt
+
+namespace xml {
+
+template <>
+struct value_traits
+{
+ static xlnt::detail::hash_algorithm parse(std::string hash_algorithm_string, const parser &)
+ {
+ if (hash_algorithm_string == "SHA1") return xlnt::detail::hash_algorithm::sha1;
+ else if (hash_algorithm_string == "SHA256") return xlnt::detail::hash_algorithm::sha256;
+ else if (hash_algorithm_string == "SHA384") return xlnt::detail::hash_algorithm::sha384;
+ else if (hash_algorithm_string == "SHA512") return xlnt::detail::hash_algorithm::sha512;
+ else if (hash_algorithm_string == "MD5") return xlnt::detail::hash_algorithm::md5;
+ else if (hash_algorithm_string == "MD4") return xlnt::detail::hash_algorithm::md4;
+ else if (hash_algorithm_string == "MD2") return xlnt::detail::hash_algorithm::md2;
+ else if (hash_algorithm_string == "Ripemd128") return xlnt::detail::hash_algorithm::ripemd128;
+ else if (hash_algorithm_string == "Ripemd160") return xlnt::detail::hash_algorithm::ripemd160;
+ else if (hash_algorithm_string == "Whirlpool") return xlnt::detail::hash_algorithm::whirlpool;
+ throw xlnt::exception(hash_algorithm_string);
+ }
+
+ static std::string serialize(xlnt::detail::hash_algorithm algorithm, const serializer &)
+ {
+ switch (algorithm)
+ {
+ case xlnt::detail::hash_algorithm::sha1: return "SHA1";
+ case xlnt::detail::hash_algorithm::sha256: return "SHA256";
+ case xlnt::detail::hash_algorithm::sha384: return "SHA384";
+ case xlnt::detail::hash_algorithm::sha512: return "SHA512";
+ case xlnt::detail::hash_algorithm::md5: return "MD5";
+ case xlnt::detail::hash_algorithm::md4: return "MD4";
+ case xlnt::detail::hash_algorithm::md2: return "MD2";
+ case xlnt::detail::hash_algorithm::ripemd128: return "Ripemd128";
+ case xlnt::detail::hash_algorithm::ripemd160: return "Ripemd160";
+ case xlnt::detail::hash_algorithm::whirlpool: return "Whirlpool";
+ }
+ }
+}; // struct value_traits<>
+
+} // namespace xml
+
+namespace xlnt {
+namespace detail {
+
struct crypto_helper
{
static const std::size_t segment_length = 4096;
@@ -62,20 +124,6 @@ struct crypto_helper
decryption
};
- enum class hash_algorithm
- {
- sha1,
- sha256,
- sha384,
- sha512,
- md5,
- md4,
- md2,
- ripemd128,
- ripemd160,
- whirlpool
- };
-
static std::vector aes(const std::vector &key,
const std::vector &iv,
const std::vector &encrypted,
@@ -104,6 +152,15 @@ struct crypto_helper
return std::vector(decoded.begin(), decoded.end());
}
+ static std::string encode_base64(const std::vector &decoded)
+ {
+ Botan::Pipe pipe(new Botan::Base64_Encoder);
+ pipe.process_msg(decoded);
+ auto encoded = pipe.read_all();
+
+ return std::string(encoded.begin(), encoded.end());
+ }
+
static std::vector hash(hash_algorithm algorithm,
const std::vector &input)
{
@@ -276,7 +333,7 @@ struct crypto_helper
//todo: verify here
std::size_t package_offset = 0;
- auto decrypted_size = read_int(package_offset, encrypted_package);
+ auto decrypted_size = static_cast(read_int(package_offset, encrypted_package));
auto decrypted = aes(key_derived, {}, std::vector(
encrypted_package.begin() + 8, encrypted_package.end()),
cipher_chaining::ecb, cipher_direction::decryption);
@@ -323,12 +380,74 @@ struct crypto_helper
} key_encryptor;
};
+ static agile_encryption_info generate_agile_encryption_info(const std::string &password)
+ {
+ agile_encryption_info result;
+ result.key_data.salt_value.assign(password.begin(), password.end());
+ return result;
+ }
+
+ static std::vector write_agile_encryption_info(const std::string &password)
+ {
+ static const auto &xmlns = xlnt::constants::get_namespace("encryption");
+ static const auto &xmlns_p = xlnt::constants::get_namespace("encryption-password");
+
+ std::vector encryption_info;
+ xlnt::detail::vector_ostreambuf encryption_info_buffer(encryption_info);
+ std::ostream encryption_info_stream(&encryption_info_buffer);
+ xml::serializer serializer(encryption_info_stream, "EncryptionInfo");
+
+ agile_encryption_info result = generate_agile_encryption_info(password);
+
+ serializer.start_element(xmlns, "encryption");
+
+ serializer.start_element(xmlns, "keyData");
+ serializer.attribute("saltSize", result.key_data.salt_size);
+ serializer.attribute("blockSize", result.key_data.block_size);
+ serializer.attribute("keyBits", result.key_data.key_bits);
+ serializer.attribute("hashSize", result.key_data.hash_size);
+ serializer.attribute("cipherAlgorithm", result.key_data.cipher_algorithm);
+ serializer.attribute("cipherChaining", result.key_data.cipher_chaining);
+ serializer.attribute("hashAlgorithm", result.key_data.hash_algorithm);
+ serializer.attribute("saltValue", encode_base64(result.key_data.salt_value));
+ serializer.end_element(xmlns, "keyData");
+
+ serializer.start_element(xmlns, "dataIntegrity");
+ serializer.attribute("encryptedHmacKey", encode_base64(result.data_integrity.hmac_key));
+ serializer.attribute("encryptedHmacValue", encode_base64(result.data_integrity.hmac_value));
+ serializer.end_element(xmlns, "dataIntegrity");
+
+ serializer.start_element(xmlns, "keyEncryptors");
+ serializer.start_element(xmlns, "keyEncryptor");
+ serializer.attribute("uri", "");
+ serializer.start_element(xmlns_p, "encryptedKey");
+ serializer.attribute("spinCount", result.key_encryptor.spin_count);
+ serializer.attribute("saltSize", result.key_encryptor.salt_size);
+ serializer.attribute("blockSize", result.key_encryptor.block_size);
+ serializer.attribute("keyBits", result.key_encryptor.key_bits);
+ serializer.attribute("hashSize", result.key_encryptor.hash_size);
+ serializer.attribute("cipherAlgorithm", result.key_encryptor.cipher_algorithm);
+ serializer.attribute("cipherChaining", result.key_encryptor.cipher_chaining);
+ serializer.attribute("hashAlgorithm", result.key_encryptor.hash);
+ serializer.attribute("saltValue", encode_base64(result.key_encryptor.salt_value));
+ serializer.attribute("encryptedVerifierHashInput", encode_base64(result.key_encryptor.verifier_hash_input));
+ serializer.attribute("encryptedVerifierHashValue", encode_base64(result.key_encryptor.verifier_hash_value));
+ serializer.attribute("encryptedKeyValue", encode_base64(result.key_encryptor.encrypted_key_value));
+ serializer.end_element(xmlns_p, "encryptedKey");
+ serializer.end_element(xmlns, "keyEncryptor");
+ serializer.end_element(xmlns, "keyEncryptors");
+
+ serializer.end_element(xmlns, "encryption");
+
+ return encryption_info;
+ }
+
static std::vector decrypt_xlsx_agile(const std::vector &encryption_info,
const std::string &password, const std::vector &encrypted_package)
{
- static const auto xmlns = std::string("http://schemas.microsoft.com/office/2006/encryption");
- static const auto xmlns_p = std::string("http://schemas.microsoft.com/office/2006/keyEncryptor/password");
- static const auto xmlns_c = std::string("http://schemas.microsoft.com/office/2006/keyEncryptor/certificate");
+ static const auto &xmlns = xlnt::constants::get_namespace("encryption");
+ static const auto &xmlns_p = xlnt::constants::get_namespace("encryption-password");
+ //static const auto &xmlns_c = xlnt::constants::get_namespace("encryption-certificate");
agile_encryption_info result;
@@ -585,6 +704,8 @@ struct crypto_helper
throw xlnt::exception("empty file");
}
+ generate_agile_encryption_info(password);
+
return {};
}
};
diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp
index 8485cc92..1ac96c62 100644
--- a/source/detail/xlsx_producer.cpp
+++ b/source/detail/xlsx_producer.cpp
@@ -52,7 +52,7 @@ const bool skip_unknown_elements = true;
///
bool is_integral(long double d)
{
- return d == static_cast(d);
+ return std::fabs(d - static_cast(static_cast(d))) == 0.L;
}
std::string fill(const std::string &string, std::size_t length = 2)
@@ -129,8 +129,37 @@ void xlsx_producer::populate_archive()
write_workbook(rel);
break;
- default:
- break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::worksheet: break;
+ case relationship::type::shared_string_table: break;
+ case relationship::type::styles: break;
+ case relationship::type::theme: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::chartsheet: break;
+ case relationship::type::comments: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::connections: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::custom_xml_mappings: break;
+ case relationship::type::dialogsheet: break;
+ case relationship::type::drawings: break;
+ case relationship::type::external_workbook_references: break;
+ case relationship::type::metadata: break;
+ case relationship::type::pivot_table: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook_revision_headers: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::volatile_dependencies: break;
+ case relationship::type::image: break;
}
}
@@ -191,7 +220,7 @@ void xlsx_producer::write_content_types()
serializer().end_element(xmlns, "Types");
}
-void xlsx_producer::write_extended_properties(const relationship &rel)
+void xlsx_producer::write_extended_properties(const relationship &/*rel*/)
{
const auto xmlns = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"s;
const auto xmlns_vt = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"s;
@@ -247,13 +276,13 @@ void xlsx_producer::write_extended_properties(const relationship &rel)
serializer().end_element(xmlns, "Properties");
}
-void xlsx_producer::write_core_properties(const relationship &rel)
+void xlsx_producer::write_core_properties(const relationship &/*rel*/)
{
- static const auto xmlns_cp = constants::get_namespace("core-properties");
- static const auto xmlns_dc = constants::get_namespace("dc");
- static const auto xmlns_dcterms = constants::get_namespace("dcterms");
- static const auto xmlns_dcmitype = constants::get_namespace("dcmitype");
- static const auto xmlns_xsi = constants::get_namespace("xsi");
+ static const auto &xmlns_cp = constants::get_namespace("core-properties");
+ static const auto &xmlns_dc = constants::get_namespace("dc");
+ static const auto &xmlns_dcterms = constants::get_namespace("dcterms");
+ static const auto &xmlns_dcmitype = constants::get_namespace("dcmitype");
+ static const auto &xmlns_xsi = constants::get_namespace("xsi");
serializer().start_element(xmlns_cp, "coreProperties");
serializer().namespace_decl(xmlns_cp, "cp");
@@ -289,7 +318,7 @@ void xlsx_producer::write_core_properties(const relationship &rel)
serializer().end_element(xmlns_cp, "coreProperties");
}
-void xlsx_producer::write_custom_properties(const relationship &rel)
+void xlsx_producer::write_custom_properties(const relationship &/*rel*/)
{
serializer().element("Properties");
}
@@ -319,13 +348,13 @@ void xlsx_producer::write_workbook(const relationship &rel)
throw no_visible_worksheets();
}
- static const auto xmlns = constants::get_namespace("workbook");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_mx = constants::get_namespace("mx");
- static const auto xmlns_r = constants::get_namespace("r");
- static const auto xmlns_s = constants::get_namespace("worksheet");
- static const auto xmlns_x15 = constants::get_namespace("x15");
- static const auto xmlns_x15ac = constants::get_namespace("x15ac");
+ static const auto &xmlns = constants::get_namespace("workbook");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_mx = constants::get_namespace("mx");
+ static const auto &xmlns_r = constants::get_namespace("r");
+ static const auto &xmlns_s = constants::get_namespace("worksheet");
+ static const auto &xmlns_x15 = constants::get_namespace("x15");
+ static const auto &xmlns_x15ac = constants::get_namespace("x15ac");
serializer().start_element(xmlns, "workbook");
serializer().namespace_decl(xmlns, "");
@@ -422,6 +451,8 @@ void xlsx_producer::write_workbook(const relationship &rel)
serializer().element(xmlns, "definedNames", "");
}
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wrange-loop-analysis"
for (const auto ws : source_)
{
auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.get_title()];
@@ -453,6 +484,7 @@ void xlsx_producer::write_workbook(const relationship &rel)
serializer().end_element(xmlns, "sheet");
}
+#pragma clang diagnostic pop
serializer().end_element(xmlns, "sheets");
@@ -570,57 +602,76 @@ void xlsx_producer::write_workbook(const relationship &rel)
write_worksheet(child_rel);
break;
- default:
- break;
+ case relationship::type::office_document: break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::extended_properties: break;
+ case relationship::type::core_properties: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::comments: break;
+ case relationship::type::vml_drawing: break;
+ case relationship::type::unknown: break;
+ case relationship::type::custom_properties: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::drawings: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::image: break;
}
}
}
// Write Workbook Relationship Target Parts
-void xlsx_producer::write_calculation_chain(const relationship &rel)
+void xlsx_producer::write_calculation_chain(const relationship &/*rel*/)
{
serializer().start_element("calcChain");
}
-void xlsx_producer::write_chartsheet(const relationship &rel)
+void xlsx_producer::write_chartsheet(const relationship &/*rel*/)
{
serializer().start_element("chartsheet");
}
-void xlsx_producer::write_connections(const relationship &rel)
+void xlsx_producer::write_connections(const relationship &/*rel*/)
{
serializer().start_element("connections");
}
-void xlsx_producer::write_custom_xml_mappings(const relationship &rel)
+void xlsx_producer::write_custom_xml_mappings(const relationship &/*rel*/)
{
serializer().start_element("MapInfo");
}
-void xlsx_producer::write_dialogsheet(const relationship &rel)
+void xlsx_producer::write_dialogsheet(const relationship &/*rel*/)
{
serializer().start_element("dialogsheet");
}
-void xlsx_producer::write_external_workbook_references(const relationship &rel)
+void xlsx_producer::write_external_workbook_references(const relationship &/*rel*/)
{
serializer().start_element("externalLink");
}
-void xlsx_producer::write_metadata(const relationship &rel)
+void xlsx_producer::write_metadata(const relationship &/*rel*/)
{
serializer().start_element("metadata");
}
-void xlsx_producer::write_pivot_table(const relationship &rel)
+void xlsx_producer::write_pivot_table(const relationship &/*rel*/)
{
serializer().start_element("pivotTableDefinition");
}
-void xlsx_producer::write_shared_string_table(const relationship &rel)
+void xlsx_producer::write_shared_string_table(const relationship &/*rel*/)
{
- static const auto xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns = constants::get_namespace("worksheet");
serializer().start_element(xmlns, "sst");
serializer().namespace_decl(xmlns, "");
@@ -628,6 +679,8 @@ void xlsx_producer::write_shared_string_table(const relationship &rel)
// todo: is there a more elegant way to get this number?
std::size_t string_count = 0;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wrange-loop-analysis"
for (const auto ws : source_)
{
auto dimension = ws.calculate_dimension();
@@ -646,6 +699,7 @@ void xlsx_producer::write_shared_string_table(const relationship &rel)
}
}
}
+#pragma clang diagnostic pop
serializer().attribute("count", string_count);
serializer().attribute("uniqueCount", source_.get_shared_strings().size());
@@ -725,27 +779,27 @@ void xlsx_producer::write_shared_string_table(const relationship &rel)
serializer().end_element(xmlns, "sst");
}
-void xlsx_producer::write_shared_workbook_revision_headers(const relationship &rel)
+void xlsx_producer::write_shared_workbook_revision_headers(const relationship &/*rel*/)
{
serializer().start_element("headers");
}
-void xlsx_producer::write_shared_workbook(const relationship &rel)
+void xlsx_producer::write_shared_workbook(const relationship &/*rel*/)
{
serializer().start_element("revisions");
}
-void xlsx_producer::write_shared_workbook_user_data(const relationship &rel)
+void xlsx_producer::write_shared_workbook_user_data(const relationship &/*rel*/)
{
serializer().start_element("users");
}
-void xlsx_producer::write_styles(const relationship &rel)
+void xlsx_producer::write_styles(const relationship &/*rel*/)
{
- static const auto xmlns = constants::get_namespace("worksheet");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_x14 = constants::get_namespace("x14");
- static const auto xmlns_x14ac = constants::get_namespace("x14ac");
+ static const auto &xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_x14 = constants::get_namespace("x14");
+ static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
serializer().start_element(xmlns, "styleSheet");
serializer().namespace_decl(xmlns, "");
@@ -794,12 +848,12 @@ void xlsx_producer::write_styles(const relationship &rel)
auto num_known_fonts = std::count_if(fonts.begin(), fonts.end(), [](const xlnt::font &f)
{
- static const auto known_fonts = std::vector
- {
- xlnt::font().color(xlnt::theme_color(1)).scheme("minor").family(2)
- };
+ static const auto known_fonts = new std::vector
+ {
+ xlnt::font().color(xlnt::theme_color(1)).scheme("minor").family(2)
+ };
- return std::find(known_fonts.begin(), known_fonts.end(), f) != known_fonts.end();
+ return std::find(known_fonts->begin(), known_fonts->end(), f) != known_fonts->end();
});
if (source_.x15_enabled())
@@ -917,27 +971,27 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().start_element(xmlns, "gradientFill");
serializer().attribute("gradientType", gradient.type());
- if (gradient.degree() != 0)
+ if (gradient.degree() != 0.)
{
serializer().attribute("degree", gradient.degree());
}
- if (gradient.left() != 0)
+ if (gradient.left() != 0.)
{
serializer().attribute("left", gradient.left());
}
- if (gradient.right() != 0)
+ if (gradient.right() != 0.)
{
serializer().attribute("right", gradient.right());
}
- if (gradient.top() != 0)
+ if (gradient.top() != 0.)
{
serializer().attribute("top", gradient.top());
}
- if (gradient.bottom() != 0)
+ if (gradient.bottom() != 0.)
{
serializer().attribute("bottom", gradient.bottom());
}
@@ -1021,9 +1075,9 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().start_element(xmlns, "cellStyleXfs");
serializer().attribute("count", stylesheet.style_impls.size());
- for (auto ¤t_style_name_impl : stylesheet.style_impls)
+ for (const auto ¤t_style_name : stylesheet.style_names)
{
- auto ¤t_style_impl = current_style_name_impl.second;
+ const auto ¤t_style_impl = stylesheet.style_impls.at(current_style_name);
serializer().start_element(xmlns, "xf");
serializer().attribute("numFmtId", current_style_impl.number_format_id.get());
@@ -1123,9 +1177,19 @@ void xlsx_producer::write_styles(const relationship &rel)
for (auto ¤t_format_impl : stylesheet.format_impls)
{
serializer().start_element(xmlns, "xf");
+
serializer().attribute("numFmtId", current_format_impl.number_format_id.get());
serializer().attribute("fontId", current_format_impl.font_id.get());
- serializer().attribute("fillId", current_format_impl.fill_id.get());
+
+ if (current_format_impl.style)
+ {
+ serializer().attribute("fillId", stylesheet.style_impls.at(current_format_impl.style.get()).fill_id.get());
+ }
+ else
+ {
+ serializer().attribute("fillId", current_format_impl.fill_id.get());
+ }
+
serializer().attribute("borderId", current_format_impl.border_id.get());
if (current_format_impl.number_format_applied)
@@ -1289,10 +1353,10 @@ void xlsx_producer::write_styles(const relationship &rel)
serializer().end_element(xmlns, "styleSheet");
}
-void xlsx_producer::write_theme(const relationship &rel)
+void xlsx_producer::write_theme(const relationship &/*rel*/)
{
- static const auto xmlns_a = constants::get_namespace("drawingml");
- static const auto xmlns_thm15 = constants::get_namespace("thm15");
+ static const auto &xmlns_a = constants::get_namespace("drawingml");
+ static const auto &xmlns_thm15 = constants::get_namespace("thm15");
serializer().start_element(xmlns_a, "theme");
serializer().namespace_decl(xmlns_a, "a");
@@ -1353,7 +1417,7 @@ void xlsx_producer::write_theme(const relationship &rel)
std::string minor;
};
- static const std::vector font_schemes = {
+ static const auto font_schemes = new std::vector {
{ true, "latin", "Calibri Light", "Calibri" },
{ true, "ea", "", "" },
{ true, "cs", "", "" },
@@ -1398,7 +1462,7 @@ void xlsx_producer::write_theme(const relationship &rel)
{
serializer().start_element(xmlns_a, major ? "majorFont" : "minorFont");
- for (const auto scheme : font_schemes)
+ for (const auto &scheme : *font_schemes)
{
const auto scheme_value = major ? scheme.major : scheme.minor;
@@ -1759,17 +1823,17 @@ void xlsx_producer::write_theme(const relationship &rel)
serializer().end_element(xmlns_a, "theme");
}
-void xlsx_producer::write_volatile_dependencies(const relationship &rel)
+void xlsx_producer::write_volatile_dependencies(const relationship &/*rel*/)
{
serializer().start_element("volTypes");
}
void xlsx_producer::write_worksheet(const relationship &rel)
{
- static const auto xmlns = constants::get_namespace("worksheet");
- static const auto xmlns_r = constants::get_namespace("r");
- static const auto xmlns_mc = constants::get_namespace("mc");
- static const auto xmlns_x14ac = constants::get_namespace("x14ac");
+ static const auto &xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns_r = constants::get_namespace("r");
+ static const auto &xmlns_mc = constants::get_namespace("mc");
+ static const auto &xmlns_x14ac = constants::get_namespace("x14ac");
auto worksheet_part = rel.get_source().get_path().parent().append(rel.get_target().get_path());
auto worksheet_rels = source_.get_manifest().get_relationships(worksheet_part);
@@ -1984,7 +2048,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
serializer().attribute("customHeight", "1");
auto height = ws.get_row_properties(row.front().get_row()).height;
- if (height == std::floor(height))
+ if (std::fabs(height - std::floor(height)) == 0.L)
{
serializer().attribute("ht", std::to_string(static_cast(height)) + ".0");
}
@@ -2227,17 +2291,17 @@ void xlsx_producer::write_worksheet(const relationship &rel)
if (!ws.get_header_footer().is_default())
{
// todo: this shouldn't be hardcoded
- static const auto header_text =
+ static const auto header_text = new std::string(
"&L&\"Calibri,Regular\"&K000000Left Header Text&C&\"Arial,Regular\"&6&K445566Center Header "
- "Text&R&\"Arial,Bold\"&8&K112233Right Header Text"s;
- static const auto footer_text =
+ "Text&R&\"Arial,Bold\"&8&K112233Right Header Text");
+ static const auto footer_text = new std::string(
"&L&\"Times New Roman,Regular\"&10&K445566Left Footer Text_x000D_And &D and &T&C&\"Times New "
"Roman,Bold\"&12&K778899Center Footer Text &Z&F on &A&R&\"Times New Roman,Italic\"&14&KAABBCCRight Footer "
- "Text &P of &N"s;
+ "Text &P of &N");
serializer().start_element(xmlns, "headerFooter");
- serializer().element(xmlns, "oddHeader", header_text);
- serializer().element(xmlns, "oddFooter", footer_text);
+ serializer().element(xmlns, "oddHeader", *header_text);
+ serializer().element(xmlns, "oddFooter", *footer_text);
serializer().end_element(xmlns, "headerFooter");
}
@@ -2293,8 +2357,39 @@ void xlsx_producer::write_worksheet(const relationship &rel)
write_vml_drawings(child_rel, ws, cells_with_comments);
break;
- default:
- break;
+ case relationship::type::office_document: break;
+ case relationship::type::thumbnail: break;
+ case relationship::type::calculation_chain: break;
+ case relationship::type::extended_properties: break;
+ case relationship::type::core_properties: break;
+ case relationship::type::worksheet: break;
+ case relationship::type::shared_string_table: break;
+ case relationship::type::styles: break;
+ case relationship::type::theme: break;
+ case relationship::type::hyperlink: break;
+ case relationship::type::chartsheet: break;
+ case relationship::type::unknown: break;
+ case relationship::type::custom_properties: break;
+ case relationship::type::printer_settings: break;
+ case relationship::type::connections: break;
+ case relationship::type::custom_property: break;
+ case relationship::type::custom_xml_mappings: break;
+ case relationship::type::dialogsheet: break;
+ case relationship::type::drawings: break;
+ case relationship::type::external_workbook_references: break;
+ case relationship::type::metadata: break;
+ case relationship::type::pivot_table: break;
+ case relationship::type::pivot_table_cache_definition: break;
+ case relationship::type::pivot_table_cache_records: break;
+ case relationship::type::query_table: break;
+ case relationship::type::shared_workbook_revision_headers: break;
+ case relationship::type::shared_workbook: break;
+ case relationship::type::revision_log: break;
+ case relationship::type::shared_workbook_user_data: break;
+ case relationship::type::single_cell_table_definitions: break;
+ case relationship::type::table_definition: break;
+ case relationship::type::volatile_dependencies: break;
+ case relationship::type::image: break;
}
}
}
@@ -2302,10 +2397,10 @@ void xlsx_producer::write_worksheet(const relationship &rel)
// Sheet Relationship Target Parts
-void xlsx_producer::write_comments(const relationship &rel, worksheet ws,
+void xlsx_producer::write_comments(const relationship &/*rel*/, worksheet ws,
const std::vector &cells)
{
- static const auto xmlns = constants::get_namespace("worksheet");
+ static const auto &xmlns = constants::get_namespace("worksheet");
serializer().start_element(xmlns, "comments");
serializer().namespace_decl(xmlns, "");
@@ -2418,10 +2513,10 @@ void xlsx_producer::write_comments(const relationship &rel, worksheet ws,
void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws,
const std::vector &cells)
{
- static const auto xmlns_mv = std::string("http://macVmlSchemaUri");
- static const auto xmlns_o = std::string("urn:schemas-microsoft-com:office:office");
- static const auto xmlns_v = std::string("urn:schemas-microsoft-com:vml");
- static const auto xmlns_x = std::string("urn:schemas-microsoft-com:office:excel");
+ static const auto &xmlns_mv = std::string("http://macVmlSchemaUri");
+ static const auto &xmlns_o = std::string("urn:schemas-microsoft-com:office:office");
+ static const auto &xmlns_v = std::string("urn:schemas-microsoft-com:vml");
+ static const auto &xmlns_x = std::string("urn:schemas-microsoft-com:office:excel");
serializer().start_element("xml");
serializer().namespace_decl(xmlns_v, "v");
@@ -2620,8 +2715,11 @@ void xlsx_producer::write_color(const xlnt::color &color)
serializer().attribute("indexed", color.get_indexed().get_index());
break;
+ case xlnt::color::type::auto_:
+ serializer().attribute("auto", color.get_indexed().get_index());
+ break;
+
case xlnt::color::type::rgb:
- default:
serializer().attribute("rgb", color.get_rgb().get_hex_string());
break;
}
diff --git a/source/detail/zip.cpp b/source/detail/zip.cpp
index 2e1a4f85..5b0786a7 100644
--- a/source/detail/zip.cpp
+++ b/source/detail/zip.cpp
@@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include
+#include
#include
#include
#include
@@ -48,6 +49,7 @@ extern "C" {
}
#include
+#include
namespace xlnt {
namespace detail {
@@ -168,16 +170,18 @@ void zip_file_header::Write(std::ostream &ostream, const bool global) const
}
}
+static const std::size_t buffer_size = 512;
+
class ZipStreambufDecompress : public std::streambuf
{
- static const unsigned int buffer_size = 512;
std::istream &istream;
z_stream strm;
- unsigned char in[buffer_size], out[buffer_size];
+ std::array in;
+ std::array out;
zip_file_header header;
- int total_read, total_uncompressed;
- // bool own_istream;
+ std::size_t total_read;
+ std::size_t total_uncompressed;
bool valid;
bool compressed_data;
@@ -193,55 +197,75 @@ public:
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
- setg((char *)in, (char *)in, (char *)in);
+
+ setg(in.data(), in.data(), in.data());
setp(0, 0);
+
// skip the header
valid = header.read(istream, false);
if (header.compression_type == DEFLATE)
+ {
compressed_data = true;
+ }
else if (header.compression_type == UNCOMPRESSED)
+ {
compressed_data = false;
+ }
else
{
compressed_data = false;
std::cerr << "ZIP: got unrecognized compressed data (Supported deflate/uncompressed)" << std::endl;
valid = false;
}
+
// initialize the inflate
if (compressed_data && valid)
{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
int result = inflateInit2(&strm, -MAX_WBITS);
+#pragma clang diagnostic pop
+
if (result != Z_OK)
{
std::cerr << "gzip: inflateInit2 did not return Z_OK" << std::endl;
valid = false;
}
}
+
header = central_header;
}
virtual ~ZipStreambufDecompress()
{
- if (compressed_data && valid) inflateEnd(&strm);
+ if (compressed_data && valid)
+ {
+ inflateEnd(&strm);
+ }
}
int process()
{
if (!valid) return -1;
+
if (compressed_data)
{
strm.avail_out = buffer_size - 4;
- strm.next_out = (Bytef *)(out + 4);
+ strm.next_out = reinterpret_cast(out.data() + 4);
+
while (strm.avail_out != 0)
{
if (strm.avail_in == 0)
- { // buffer empty, read some more from file
- istream.read((char *)in, std::min((unsigned int)buffer_size, header.compressed_size - total_read));
- strm.avail_in = istream.gcount();
+ {
+ // buffer empty, read some more from file
+ istream.read(in.data(), static_cast(std::min(buffer_size, header.compressed_size - total_read)));
+ strm.avail_in = static_cast(istream.gcount());
total_read += strm.avail_in;
- strm.next_in = (Bytef *)in;
+ strm.next_in = reinterpret_cast(in.data());
}
+
int ret = inflate(&strm, Z_NO_FLUSH); // decompress
+
switch (ret)
{
case Z_STREAM_ERROR:
@@ -255,49 +279,50 @@ public:
valid = false;
return -1;
}
+
if (ret == Z_STREAM_END) break;
}
- int unzip_count = buffer_size - strm.avail_out - 4;
+
+ auto unzip_count = buffer_size - strm.avail_out - 4;
total_uncompressed += unzip_count;
- return unzip_count;
+ return static_cast(unzip_count);
}
- else
- { // uncompressed, so just read
- istream.read((char *)(out + 4), std::min(buffer_size - 4, header.uncompressed_size - total_read));
- int count = istream.gcount();
- total_read += count;
- return count;
- }
- return 1;
+
+ // uncompressed, so just read
+ istream.read(out.data() + 4, static_cast(std::min(buffer_size - 4, header.uncompressed_size - total_read)));
+ auto count = istream.gcount();
+ total_read += static_cast(count);
+ return static_cast(count);
}
virtual int underflow()
{
if (gptr() && (gptr() < egptr()))
return traits_type::to_int_type(*gptr()); // if we already have data just use it
- int put_back_count = gptr() - eback();
+ auto put_back_count = gptr() - eback();
if (put_back_count > 4) put_back_count = 4;
- std::memmove(out + (4 - put_back_count), gptr() - put_back_count, put_back_count);
+ std::memmove(out.data() + (4 - put_back_count), gptr() - put_back_count, static_cast(put_back_count));
int num = process();
- setg((char *)(out + 4 - put_back_count), (char *)(out + 4), (char *)(out + 4 + num));
+ setg(out.data() + 4 - put_back_count, out.data() + 4, out.data() + 4 + num);
if (num <= 0) return EOF;
return traits_type::to_int_type(*gptr());
}
- virtual int overflow(int c = EOF)
- {
- assert(false);
- return EOF;
- }
+ virtual int overflow(int c = EOF);
};
+int ZipStreambufDecompress::overflow(int)
+{
+ throw xlnt::exception("writing to read-only buffer");
+}
+
class ZipStreambufCompress : public std::streambuf
{
- static const int buffer_size = 512;
std::ostream &ostream; // owned when header==0 (when not part of zip file)
z_stream strm;
- unsigned char in[buffer_size], out[buffer_size];
+ std::array in;
+ std::array out;
zip_file_header *header;
unsigned int uncompressed_size;
@@ -312,21 +337,29 @@ public:
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
int ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
+#pragma clang diagnostic pop
+
if (ret != Z_OK)
{
std::cerr << "libz: failed to deflateInit" << std::endl;
valid = false;
return;
}
+
setg(0, 0, 0);
- setp((char *)in, (char *)(in + 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
if (header)
{
- header->header_offset = stream.tellp();
+ header->header_offset = static_cast(stream.tellp());
header->Write(ostream, false);
}
+
uncompressed_size = crc = 0;
}
@@ -358,13 +391,17 @@ protected:
int process(bool flush)
{
if (!valid) return -1;
- strm.next_in = (Bytef *)pbase();
- strm.avail_in = pptr() - pbase();
+
+ strm.next_in = reinterpret_cast(pbase());
+ strm.avail_in = static_cast(pptr() - pbase());
+
while (strm.avail_in != 0 || flush)
{
strm.avail_out = buffer_size;
- strm.next_out = (Bytef *)out;
+ strm.next_out = reinterpret_cast(out.data());
+
int ret = deflate(&strm, flush ? Z_FINISH : Z_NO_FLUSH);
+
if (!(ret != Z_BUF_ERROR && ret != Z_STREAM_ERROR))
{
valid = false;
@@ -372,16 +409,19 @@ protected:
;
return -1;
}
- int generated_output = strm.next_out - (Bytef *)out;
- ostream.write((char *)out, generated_output);
- if (header) header->compressed_size += generated_output;
+
+ auto generated_output = static_cast(strm.next_out - reinterpret_cast(out.data()));
+ ostream.write(out.data(), generated_output);
+ if (header) header->compressed_size += static_cast(generated_output);
if (ret == Z_STREAM_END) break;
}
+
// update counts, crc's and buffers
- int consumed_input = pptr() - pbase();
+ auto consumed_input = static_cast(pptr() - pbase());
uncompressed_size += consumed_input;
- crc = crc32(crc, (Bytef *)in, consumed_input);
+ crc = static_cast(crc32(crc, reinterpret_cast(in.data()), consumed_input));
setp(pbase(), pbase() + buffer_size - 4);
+
return 1;
}
@@ -393,22 +433,23 @@ protected:
virtual int underflow()
{
- std::runtime_error("Attempt to read write only ostream");
- return 0;
+ throw std::runtime_error("Attempt to read write only ostream");
}
- virtual int overflow(int c = EOF)
- {
- if (c != EOF)
- {
- *pptr() = c;
- pbump(1);
- }
- if (process(false) == EOF) return EOF;
- return c;
- }
+ virtual int overflow(int c = EOF);
};
+int ZipStreambufCompress::overflow(int c)
+{
+ if (c != EOF)
+ {
+ *pptr() = static_cast(c);
+ pbump(1);
+ }
+ if (process(false) == EOF) return EOF;
+ return c;
+}
+
zip_file_istream::zip_file_istream(std::unique_ptr &&buffer)
: std::istream(&*buffer)
{
@@ -438,20 +479,23 @@ ZipFileWriter::~ZipFileWriter()
{
// Write all file headers
std::ios::streampos final_position = target_stream_.tellp();
+
for (unsigned int i = 0; i < file_headers_.size(); i++)
{
file_headers_[i].Write(target_stream_, true);
}
+
std::ios::streampos central_end = target_stream_.tellp();
+
// Write end of central
- write_int(target_stream_, (unsigned int)0x06054b50); // end of central
- write_int(target_stream_, (unsigned short)0); // this disk number
- write_int(target_stream_, (unsigned short)0); // this disk number
- write_int(target_stream_, (unsigned short)file_headers_.size()); // one entry in center in this disk
- write_int(target_stream_, (unsigned short)file_headers_.size()); // one entry in center
- write_int(target_stream_, (unsigned int)(central_end - final_position)); // size of header
- write_int(target_stream_, (unsigned int)final_position); // offset to header
- write_int(target_stream_, (unsigned short)0); // zip comment
+ write_int(target_stream_, static_cast(0x06054b50)); // end of central
+ write_int(target_stream_, static_cast(0)); // this disk number
+ write_int(target_stream_, static_cast(0)); // this disk number
+ write_int(target_stream_, static_cast(file_headers_.size())); // one entry in center in this disk
+ write_int(target_stream_, static_cast(file_headers_.size())); // one entry in center
+ write_int(target_stream_, static_cast(central_end - final_position)); // size of header
+ write_int(target_stream_, static_cast(final_position)); // offset to header
+ write_int(target_stream_, static_cast(0)); // zip comment
}
std::ostream &ZipFileWriter::open(const std::string &filename)
@@ -496,20 +540,26 @@ bool ZipFileReader::read_central_header()
std::ios::streamoff read_start = max_comment_size + read_size_before_comment;
- if (read_start > end_position) read_start = end_position;
+ if (read_start > end_position)
+ {
+ read_start = end_position;
+ }
+
source_stream_.seekg(end_position - read_start);
std::vector buf(static_cast(read_start), '\0');
+
if (read_start <= 0)
{
std::cerr << "ZIP: Invalid read buffer size" << std::endl;
return false;
}
+
source_stream_.read(buf.data(), read_start);
auto found_header = false;
std::size_t header_index = 0;
- for (std::size_t i = 0; i < read_start - 3; ++i)
+ for (std::size_t i = 0; i < static_cast(read_start - 3); ++i)
{
if (buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06)
{
diff --git a/source/styles/border.cpp b/source/styles/border.cpp
index 413e0e7c..eec4b0c0 100644
--- a/source/styles/border.cpp
+++ b/source/styles/border.cpp
@@ -111,8 +111,10 @@ optional border::side(border_side s) const
case border_side::end: return end_;
case border_side::vertical: return vertical_;
case border_side::horizontal: return horizontal_;
- default:
case border_side::diagonal: return diagonal_;
+#ifdef WIN32
+ default: throw xlnt::exception("unhandled");
+#endif
}
}
@@ -126,7 +128,6 @@ border &border::side(border_side s, const border_property &prop)
case border_side::end: end_ = prop; break;
case border_side::vertical: vertical_ = prop; break;
case border_side::horizontal: horizontal_ = prop; break;
- default:
case border_side::diagonal: diagonal_ = prop; break;
}
diff --git a/source/styles/color.cpp b/source/styles/color.cpp
index e18a6ac3..ad53e7b5 100644
--- a/source/styles/color.cpp
+++ b/source/styles/color.cpp
@@ -22,6 +22,7 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
+#include
#include
#include
@@ -216,17 +217,22 @@ void color::assert_type(type t) const
XLNT_API bool color::operator==(const xlnt::color &other) const
{
- if (type_ != other.type_ || tint_ != other.tint_) return false;
+ if (type_ != other.type_ || std::fabs(tint_ - other.tint_) != 0.)
+ {
+ return false;
+ }
+
switch(type_)
{
case type::auto_:
- case type::indexed :
+ case type::indexed:
return indexed_.get_index() == other.indexed_.get_index();
case type::theme:
return theme_.get_index() == other.theme_.get_index();
case type::rgb:
return rgb_.get_hex_string() == other.rgb_.get_hex_string();
}
+
return false;
}
diff --git a/source/styles/fill.cpp b/source/styles/fill.cpp
index 3cefd42a..bd33b6a0 100644
--- a/source/styles/fill.cpp
+++ b/source/styles/fill.cpp
@@ -205,27 +205,27 @@ XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right)
return false;
}
- if (left.degree() != right.degree())
+ if (std::fabs(left.degree() - right.degree()) != 0.)
{
return false;
}
- if (left.bottom() != right.bottom())
+ if (std::fabs(left.bottom() - right.bottom()) != 0.)
{
return false;
}
- if (left.right() != right.right())
+ if (std::fabs(left.right() - right.right()) != 0.)
{
return false;
}
- if (left.top() != right.top())
+ if (std::fabs(left.top() - right.top()) != 0.)
{
return false;
}
- if (left.left() != right.left())
+ if (std::fabs(left.left() - right.left()) != 0.)
{
return false;
}
diff --git a/source/styles/format.cpp b/source/styles/format.cpp
index 6a321bf7..53d80c64 100644
--- a/source/styles/format.cpp
+++ b/source/styles/format.cpp
@@ -45,7 +45,7 @@ void format::clear_style()
format format::style(const xlnt::style &new_style)
{
- d_->style = new_style.name();
+ d_ = d_->parent->find_or_create_with(d_, new_style.name());
return format(d_);
}
diff --git a/source/utils/datetime.cpp b/source/utils/datetime.cpp
index c496993c..ad4fc347 100644
--- a/source/utils/datetime.cpp
+++ b/source/utils/datetime.cpp
@@ -31,7 +31,7 @@ namespace xlnt {
datetime datetime::from_number(long double raw_time, calendar base_date)
{
- auto date_part = date::from_number((int)raw_time, base_date);
+ auto date_part = date::from_number(static_cast(raw_time), base_date);
auto time_part = time::from_number(raw_time);
return datetime(date_part.year, date_part.month, date_part.day, time_part.hour, time_part.minute, time_part.second,
diff --git a/source/utils/exceptions.cpp b/source/utils/exceptions.cpp
index 5deea26a..949af833 100644
--- a/source/utils/exceptions.cpp
+++ b/source/utils/exceptions.cpp
@@ -41,11 +41,23 @@ void exception::set_message(const std::string &message)
message_ = message;
}
+missing_number_format::~missing_number_format()
+{
+}
+
+unhandled_switch_case::~unhandled_switch_case()
+{
+}
+
invalid_sheet_title::invalid_sheet_title(const std::string &title)
: exception(std::string("bad worksheet title: ") + title)
{
}
+invalid_sheet_title::~invalid_sheet_title()
+{
+}
+
invalid_column_string_index::invalid_column_string_index()
: exception("column string index error")
{
@@ -60,11 +72,19 @@ invalid_data_type::invalid_data_type()
{
}
+invalid_data_type::~invalid_data_type()
+{
+}
+
invalid_file::invalid_file(const std::string &filename)
: exception(std::string("couldn't open file: (") + filename + ")")
{
}
+invalid_file::~invalid_file()
+{
+}
+
invalid_cell_reference::invalid_cell_reference(column_t column, row_t row)
: exception(std::string("bad cell coordinates: (") + std::to_string(column.index) + ", " + std::to_string(row) +
")")
@@ -85,11 +105,19 @@ illegal_character::illegal_character(char c)
{
}
+illegal_character::~illegal_character()
+{
+}
+
invalid_parameter::invalid_parameter()
: exception("invalid parameter")
{
}
+invalid_parameter::~invalid_parameter()
+{
+}
+
invalid_attribute::invalid_attribute()
: exception("bad attribute")
{
@@ -104,14 +132,26 @@ key_not_found::key_not_found()
{
}
+key_not_found::~key_not_found()
+{
+}
+
no_visible_worksheets::no_visible_worksheets()
: exception("workbook needs at least one non-hidden worksheet to be saved")
{
}
+no_visible_worksheets::~no_visible_worksheets()
+{
+}
+
unsupported::unsupported(const std::string &message)
: exception(message)
{
}
+unsupported::~unsupported()
+{
+}
+
} // namespace xlnt
diff --git a/source/utils/time.cpp b/source/utils/time.cpp
index 33fcf503..72831de9 100644
--- a/source/utils/time.cpp
+++ b/source/utils/time.cpp
@@ -48,16 +48,16 @@ time time::from_number(long double raw_time)
time result;
double integer_part;
- double fractional_part = std::modf((double)raw_time, &integer_part);
+ double fractional_part = std::modf(static_cast(raw_time), &integer_part);
fractional_part *= 24;
- result.hour = (int)fractional_part;
+ result.hour = static_cast(fractional_part);
fractional_part = 60 * (fractional_part - result.hour);
- result.minute = (int)fractional_part;
+ result.minute = static_cast(fractional_part);
fractional_part = 60 * (fractional_part - result.minute);
- result.second = (int)fractional_part;
+ result.second = static_cast(fractional_part);
fractional_part = 1000000 * (fractional_part - result.second);
- result.microsecond = (int)fractional_part;
+ result.microsecond = static_cast(fractional_part);
if (result.microsecond == 999999 && fractional_part - result.microsecond > 0.5)
{
diff --git a/source/utils/timedelta.cpp b/source/utils/timedelta.cpp
index 33a3de6e..38d9be05 100644
--- a/source/utils/timedelta.cpp
+++ b/source/utils/timedelta.cpp
@@ -65,15 +65,15 @@ timedelta timedelta::from_number(long double raw_time)
result.days = static_cast(integer_part);
fractional_part *= 24;
- result.hours = (int)fractional_part;
+ result.hours = static_cast(fractional_part);
fractional_part = 60 * (fractional_part - result.hours);
- result.minutes = (int)fractional_part;
+ result.minutes = static_cast(fractional_part);
fractional_part = 60 * (fractional_part - result.minutes);
- result.seconds = (int)fractional_part;
+ result.seconds = static_cast(fractional_part);
fractional_part = 1000000 * (fractional_part - result.seconds);
- result.microseconds = (int)fractional_part;
+ result.microseconds = static_cast(fractional_part);
- if (result.microseconds == 999999 && fractional_part - result.microseconds > 0.5)
+ if (result.microseconds == 999999 && fractional_part - result.microseconds > 0.5L)
{
result.microseconds = 0;
result.seconds += 1;
diff --git a/source/utils/utf8string.cpp b/source/utils/utf8string.cpp
index e0d664a8..8b57899d 100644
--- a/source/utils/utf8string.cpp
+++ b/source/utils/utf8string.cpp
@@ -23,6 +23,8 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow"
+#pragma clang diagnostic ignored "-Wdeprecated"
+#pragma clang diagnostic ignored "-Wweak-vtables"
#include
#pragma clang diagnostic pop
diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp
index 5a775412..067f88d7 100644
--- a/source/workbook/workbook.cpp
+++ b/source/workbook/workbook.cpp
@@ -218,7 +218,7 @@ workbook workbook::empty_excel()
.font(default_font, false)
.number_format(xlnt::number_format::general(), false);
- wb.create_format()
+ wb.create_format(true)
.border(default_border, false)
.fill(default_fill, false)
.font(default_font, false)
@@ -1085,10 +1085,10 @@ std::vector workbook::get_named_ranges() const
return named_ranges;
}
-format workbook::create_format()
+format workbook::create_format(bool default_format)
{
register_stylesheet_in_manifest();
- return d_->stylesheet_.create_format();
+ return d_->stylesheet_.create_format(default_format);
}
bool workbook::has_style(const std::string &name) const
diff --git a/source/worksheet/cell_iterator.cpp b/source/worksheet/cell_iterator.cpp
index fb631bd4..12be1c34 100644
--- a/source/worksheet/cell_iterator.cpp
+++ b/source/worksheet/cell_iterator.cpp
@@ -27,9 +27,13 @@
namespace xlnt {
-cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order)
- : ws_(ws), current_cell_(start_cell), range_(start_cell.to_range()), order_(order)
+cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order)
+ : ws_(ws), current_cell_(start_cell), range_(limits), order_(order)
{
+ if (!ws.has_cell(current_cell_))
+ {
+ (*this)++;
+ }
}
cell_iterator::cell_iterator(const cell_iterator &other)
@@ -52,10 +56,20 @@ cell_iterator &cell_iterator::operator--()
if (order_ == major_order::row)
{
current_cell_.set_column_index(current_cell_.get_column_index() - 1);
+
+ while (!ws_.has_cell(current_cell_) && current_cell_.get_column() > range_.get_top_left().get_column())
+ {
+ current_cell_.set_column_index(current_cell_.get_column_index() - 1);
+ }
}
else
{
current_cell_.set_row(current_cell_.get_row() - 1);
+
+ while (!ws_.has_cell(current_cell_) && current_cell_.get_row() > range_.get_top_left().get_row())
+ {
+ current_cell_.set_row(current_cell_.get_row() - 1);
+ }
}
return *this;
@@ -72,11 +86,27 @@ cell_iterator &cell_iterator::operator++()
{
if (order_ == major_order::row)
{
- current_cell_.set_column_index(current_cell_.get_column_index() + 1);
+ if (current_cell_.get_column() <= range_.get_bottom_right().get_column())
+ {
+ current_cell_.set_column_index(current_cell_.get_column_index() + 1);
+ }
+
+ while (!ws_.has_cell(current_cell_) && current_cell_.get_column() <= range_.get_bottom_right().get_column())
+ {
+ current_cell_.set_column_index(current_cell_.get_column_index() + 1);
+ }
}
else
{
- current_cell_.set_row(current_cell_.get_row() + 1);
+ if (current_cell_.get_row() <= range_.get_bottom_right().get_row())
+ {
+ current_cell_.set_row(current_cell_.get_row() + 1);
+ }
+
+ while (!ws_.has_cell(current_cell_) && current_cell_.get_row() <= range_.get_bottom_right().get_row())
+ {
+ current_cell_.set_row(current_cell_.get_row() + 1);
+ }
}
return *this;
diff --git a/source/worksheet/cell_vector.cpp b/source/worksheet/cell_vector.cpp
index a6d9c32a..de122114 100644
--- a/source/worksheet/cell_vector.cpp
+++ b/source/worksheet/cell_vector.cpp
@@ -29,7 +29,7 @@ namespace xlnt {
cell_vector::iterator cell_vector::begin()
{
- return iterator(ws_, ref_.get_top_left(), order_);
+ return iterator(ws_, ref_.get_top_left(), ref_, order_);
}
cell_vector::iterator cell_vector::end()
@@ -38,12 +38,12 @@ cell_vector::iterator cell_vector::end()
{
auto past_end = ref_.get_bottom_right();
past_end.set_column_index(past_end.get_column_index() + 1);
- return iterator(ws_, past_end, order_);
+ return iterator(ws_, past_end, ref_, order_);
}
auto past_end = ref_.get_bottom_right();
past_end.set_row(past_end.get_row() + 1);
- return iterator(ws_, past_end, order_);
+ return iterator(ws_, past_end, ref_, order_);
}
cell_vector::const_iterator cell_vector::cbegin() const
@@ -109,10 +109,10 @@ cell cell_vector::get_cell(std::size_t index)
{
if (order_ == major_order::row)
{
- return ws_.get_cell(ref_.get_top_left().make_offset((int)index, 0));
+ return ws_.get_cell(ref_.get_top_left().make_offset(static_cast(index), 0));
}
- return ws_.get_cell(ref_.get_top_left().make_offset(0, (int)index));
+ return ws_.get_cell(ref_.get_top_left().make_offset(0, static_cast(index)));
}
std::size_t cell_vector::length() const
diff --git a/source/worksheet/range.cpp b/source/worksheet/range.cpp
index 90d8ea65..8171d48d 100644
--- a/source/worksheet/range.cpp
+++ b/source/worksheet/range.cpp
@@ -103,12 +103,12 @@ range::iterator range::begin()
{
cell_reference top_right(ref_.get_bottom_right().get_column_index(), ref_.get_top_left().get_row());
range_reference row_range(ref_.get_top_left(), top_right);
- return iterator(ws_, row_range, order_);
+ return iterator(ws_, row_range, ref_, order_);
}
cell_reference bottom_left(ref_.get_top_left().get_column_index(), ref_.get_bottom_right().get_row());
range_reference row_range(ref_.get_top_left(), bottom_left);
- return iterator(ws_, row_range, order_);
+ return iterator(ws_, row_range, ref_, order_);
}
range::iterator range::end()
@@ -118,13 +118,13 @@ range::iterator range::end()
auto past_end_row_index = ref_.get_bottom_right().get_row() + 1;
cell_reference bottom_left(ref_.get_top_left().get_column_index(), past_end_row_index);
cell_reference bottom_right(ref_.get_bottom_right().get_column_index(), past_end_row_index);
- return iterator(ws_, range_reference(bottom_left, bottom_right), order_);
+ return iterator(ws_, range_reference(bottom_left, bottom_right), ref_, order_);
}
auto past_end_column_index = ref_.get_bottom_right().get_column_index() + 1;
cell_reference top_right(past_end_column_index, ref_.get_top_left().get_row());
cell_reference bottom_right(past_end_column_index, ref_.get_bottom_right().get_row());
- return iterator(ws_, range_reference(top_right, bottom_right), order_);
+ return iterator(ws_, range_reference(top_right, bottom_right), ref_, order_);
}
range::const_iterator range::cbegin() const
diff --git a/source/worksheet/range_iterator.cpp b/source/worksheet/range_iterator.cpp
index b793fed5..cb925782 100644
--- a/source/worksheet/range_iterator.cpp
+++ b/source/worksheet/range_iterator.cpp
@@ -42,8 +42,8 @@ cell_vector range_iterator::operator*() const
return cell_vector(ws_, reference, order_);
}
-range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell, major_order order)
- : ws_(ws.d_), current_cell_(start_cell.get_top_left()), range_(start_cell), order_(order)
+range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell, const range_reference &limits, major_order order)
+ : ws_(ws), current_cell_(start_cell.get_top_left()), range_(limits), order_(order)
{
}
@@ -88,7 +88,21 @@ range_iterator &range_iterator::operator++()
{
if (order_ == major_order::row)
{
- current_cell_.set_row(current_cell_.get_row() + 1);
+ bool any_non_null = false;
+ do
+ {
+ current_cell_.set_row(current_cell_.get_row() + 1);
+ any_non_null = false;
+ for (auto column = current_cell_.get_column(); column <= range_.get_bottom_right().get_column(); column++)
+ {
+ if (ws_.has_cell(cell_reference(column, current_cell_.get_row())))
+ {
+ any_non_null = true;
+ break;
+ }
+ }
+ }
+ while (!any_non_null && current_cell_.get_row() <= range_.get_bottom_right().get_row());
}
else
{
diff --git a/source/worksheet/tests/test_worksheet.hpp b/source/worksheet/tests/test_worksheet.hpp
index 3ccbfb45..1610c268 100644
--- a/source/worksheet/tests/test_worksheet.hpp
+++ b/source/worksheet/tests/test_worksheet.hpp
@@ -1124,4 +1124,46 @@ public:
TS_ASSERT_THROWS_NOTHING(ws.create_named_range("XFE1048576", "A2"));
TS_ASSERT_THROWS_NOTHING(ws.create_named_range("XFD1048577", "A2"));
}
+
+ void test_iteration_skip_empty()
+ {
+ xlnt::workbook wb;
+ auto ws = wb.get_active_sheet();
+ ws.get_cell("A1").set_value("A1");
+ ws.get_cell("F6").set_value("F6");
+
+ {
+ std::vector cells;
+
+ for (auto row : ws)
+ {
+ for (auto cell : row)
+ {
+ cells.push_back(cell);
+ }
+ }
+
+ TS_ASSERT_EQUALS(cells.size(), 2);
+ TS_ASSERT_EQUALS(cells[0].get_value(), "A1");
+ TS_ASSERT_EQUALS(cells[1].get_value(), "F6");
+ }
+
+ const auto ws_const = ws;
+
+ {
+ std::vector cells;
+
+ for (auto row : ws_const)
+ {
+ for (auto cell : row)
+ {
+ cells.push_back(cell);
+ }
+ }
+
+ TS_ASSERT_EQUALS(cells.size(), 2);
+ TS_ASSERT_EQUALS(cells[0].get_value(), "A1");
+ TS_ASSERT_EQUALS(cells[1].get_value(), "F6");
+ }
+ }
};
diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp
index f49cead0..8f62b602 100644
--- a/source/worksheet/worksheet.cpp
+++ b/source/worksheet/worksheet.cpp
@@ -702,7 +702,8 @@ bool worksheet::compare(const worksheet &other, bool reference) const
return false;
}
- if (this_cell.get_data_type() == xlnt::cell::type::numeric && this_cell.get_value() != other_cell.get_value())
+ if (this_cell.get_data_type() == xlnt::cell::type::numeric
+ && std::fabs(this_cell.get_value() - other_cell.get_value()) > 0.L)
{
return false;
}
@@ -831,16 +832,16 @@ std::vector worksheet::get_formula_attributes() const
cell_reference worksheet::get_point_pos(int left, int top) const
{
- static const double DefaultColumnWidth = 51.85;
- static const double DefaultRowHeight = 15.0;
+ static const auto DefaultColumnWidth = 51.85L;
+ static const auto DefaultRowHeight = 15.0L;
auto points_to_pixels = [](long double value, long double dpi)
{
return static_cast(std::ceil(value * dpi / 72));
};
- auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
- auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
+ auto default_height = points_to_pixels(DefaultRowHeight, 96.0L);
+ auto default_width = points_to_pixels(DefaultColumnWidth, 96.0L);
column_t current_column = 1;
row_t current_row = 1;
@@ -858,7 +859,7 @@ cell_reference worksheet::get_point_pos(int left, int top) const
if (cdw >= 0)
{
- left_pos += points_to_pixels(cdw, 96.0);
+ left_pos += points_to_pixels(cdw, 96.0L);
continue;
}
}
@@ -876,7 +877,7 @@ cell_reference worksheet::get_point_pos(int left, int top) const
if (cdh >= 0)
{
- top_pos += points_to_pixels(cdh, 96.0);
+ top_pos += points_to_pixels(cdh, 96.0L);
continue;
}
}
@@ -938,7 +939,7 @@ worksheet::iterator worksheet::begin()
cell_reference top_right(dimensions.get_bottom_right().get_column_index(), dimensions.get_top_left().get_row());
range_reference row_range(dimensions.get_top_left(), top_right);
- return iterator(*this, row_range, major_order::row);
+ return iterator(*this, row_range, dimensions, major_order::row);
}
worksheet::iterator worksheet::end()
@@ -948,7 +949,7 @@ worksheet::iterator worksheet::end()
cell_reference bottom_left(dimensions.get_top_left().get_column_index(), past_end_row_index);
cell_reference bottom_right(dimensions.get_bottom_right().get_column_index(), past_end_row_index);
- return iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
+ return iterator(*this, range_reference(bottom_left, bottom_right), dimensions, major_order::row);
}
worksheet::const_iterator worksheet::cbegin() const
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5bbcfb27..22f39113 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -73,7 +73,7 @@ source_group(runner FILES ${RUNNER})
target_link_libraries(${PROJECT_NAME} ${LIBRARY_NAME})
if(MSVC)
- set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\"")
+ set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd\"4251\" /wd\"4275\" /wd\"4068\"")
# Needed for PathFileExists in path_helper
target_link_libraries(${PROJECT_NAME} Shlwapi)
else()
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 1381c69c..78feb43f 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -4,7 +4,6 @@ project(${LIBRARY_NAME}.third-party VERSION ${LIBRARY_VERSION} LANGUAGES CXX C)
# Includes
include_directories(libstudxml
utfcpp/source
- pole
botan
zlib
${LIBRARY_SOURCE_DIR}/detail)
@@ -47,17 +46,13 @@ set(GENX
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/genx/genx.c
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/genx/genx.h)
-set(POLE
- ${CMAKE_CURRENT_SOURCE_DIR}/pole/pole.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/pole/pole.h)
-
set(BOTAN
${CMAKE_CURRENT_SOURCE_DIR}/botan/botan_all.cpp
${CMAKE_CURRENT_SOURCE_DIR}/botan/botan_all_internal.h
${CMAKE_CURRENT_SOURCE_DIR}/botan/botan_all.h)
if(MSVC)
- set_source_files_properties(${BOTAN} PROPERTIES COMPILE_FLAGS "/wd\"4244\"")
+ set_source_files_properties(${BOTAN} PROPERTIES COMPILE_FLAGS "/wd\"4244\" /wd\"4267\"")
endif()
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -95,9 +90,11 @@ set(ZLIB ${CMAKE_CURRENT_SOURCE_DIR}/zlib/adler32.c
if(NOT MSVC)
set_source_files_properties(${ZLIB} PROPERTIES COMPILE_FLAGS "-Wno-implicit-function-declaration")
+else()
+ set_source_files_properties(${ZLIB} PROPERTIES COMPILE_FLAGS "/wd\"4018\"")
endif()
-add_library(xlnt.third-party OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT} ${POLE} ${BOTAN} ${ZLIB})
+add_library(xlnt.third-party OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT} ${BOTAN} ${ZLIB})
target_compile_definitions(xlnt.third-party PRIVATE LIBSTUDXML_STATIC_LIB=1)
if(NOT STATIC)
@@ -114,5 +111,4 @@ source_group(botan FILES ${BOTAN})
source_group(libstudxml FILES ${LIBSTUDXML})
source_group(libstudxml\\genx FILES ${GENX})
source_group(libstudxml\\expat FILES ${EXPAT})
-source_group(pole FILES ${POLE})
source_group(zlib FILES ${ZLIB})
diff --git a/third-party/botan b/third-party/botan
index 523b2a4c..e6bf87b6 160000
--- a/third-party/botan
+++ b/third-party/botan
@@ -1 +1 @@
-Subproject commit 523b2a4ca48fa5cf04ea371aabe7167ce2e5cd13
+Subproject commit e6bf87b6b0d4d9c3877b79de53de58dc34a3acca
diff --git a/third-party/pole/AUTHORS b/third-party/pole/AUTHORS
deleted file mode 100644
index 464a3050..00000000
--- a/third-party/pole/AUTHORS
+++ /dev/null
@@ -1 +0,0 @@
-Ariya Hidayat
\ No newline at end of file
diff --git a/third-party/pole/COMPILERS.txt b/third-party/pole/COMPILERS.txt
deleted file mode 100644
index 92b8c8b6..00000000
--- a/third-party/pole/COMPILERS.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-
-Borland C++ Compiler 5.5.1
-------------------------------
-The command-line Borland C++ Compiler version 5.5.1 is available for free
-(as 'free' in 'free beer') from:
-http://www.borland.com/products/downloads/download_cbuilder.html
-
-OpenWatcom 1.3
-------------------------------
-OpenWatcom 1.3 does not have STL implementation, therefore you need to
-install STLport (tested with version 4.6, earlier version may or may not
-work). Because mainstream STLport can not be used directly with OpenWatcom,
-please download and use the patched version from this site:
-http://www.ecet.vtc.edu/~pchapin/OW/index.html
-
-Digital Mars 8.41n
--------------------------------
-Digital Mars command-line C/C++ compilers are available for download
-from http://www.digitalmars.com. STLport is required and must be
-installed as well.
-
diff --git a/third-party/pole/ChangeLog b/third-party/pole/ChangeLog
deleted file mode 100644
index c9dc19b6..00000000
--- a/third-party/pole/ChangeLog
+++ /dev/null
@@ -1,24 +0,0 @@
-POLE 0.3
-
- * changed license to two-clause BSD license
- * fixed potential lock-up on corrupted file, bug reported by
- Andrew Ziem
- * fixed error reading very huge file (larger than 13 MB)
- * ported POLEView to Qt 4, making it available also for Windows
- * assorted user-interface improvements in POLEView
-
-POLE 0.2 (released March 2005)
-
- * changed license to BSD license
- * poleview: graphical tool to view a structured storage
- * fixed occasional incorrect reading of big file
- * fixed rare memory problem, found by valgrind
- * fixed compile with Microsoft Visual C++ and Borland C++ (Windows)
- * modified storage to become stateless (with better API)
- * performance improvement, especially with very large file
-
-POLE 0.1 (released March 2004)
-
- * initial release
- * support for reading structured storages, even large ones
- * no support yet for creating or modifying a storage
diff --git a/third-party/pole/LICENSE b/third-party/pole/LICENSE
deleted file mode 100644
index 84232fb6..00000000
--- a/third-party/pole/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-POLE - Portable C++ library to access OLE Storage
-Copyright (C) 2002-2007 Ariya Hidayat (ariya@kde.org). 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
-
diff --git a/third-party/pole/README b/third-party/pole/README
deleted file mode 100644
index 9ed023af..00000000
--- a/third-party/pole/README
+++ /dev/null
@@ -1,72 +0,0 @@
-POLE - portable library for structured storage
-
-POLE is a portable C++ library to create and read structured storage. With a
-structured storage, you can store files inside another file, or you can even
-create complex directory tree, if you want to. The structured storage created by
-POLE is compatible with Microsoft structured storage, also sometimes called as
-OLE Compound Document, which are used among others in Microsoft Office. However,
-POLE has the advantage that it's portable (i.e you can read or write a
-structured storage in any supported platform), you don't need to rely on Windows
-library.
-
-Download
-==========
-
-Source code is available at http://developer.berlios.de/projects/pole/.
-Please always use the latest stable version.
-
-Install
-========
-
-To compile POLE, you need a C++ compiler, with standard C++ library which
-supports STL (Standard Template Library). On Linux and other Unices, g++ will do
-the job.
-
-POLE is just a library, you have to integrate it as part of your
-application/project. Since it consists of one source file and one header file,
-it doesn't make much sense to compile POLE as separate library (either static or
-dynamic). Simply add these files to your project and you're done.
-
-The source tarball of POLE demonstrates the use of POLE to build poledump, a
-small utility to extract any stream inside a structured storage. If you use g++
-as the compiler, you can compile poledump using the following command:
-
-g++ -o poledump pole.cpp poledump.cpp
-
-You may use poledump like the example below:
-
-poledump budget.xls Workbook result.xls
-
-The above command will extract a stream named Workbook inside Excel document
-(budget.xls) and save it as result.xls. File result.xls will still be recognized
-as a valid workbook (in raw format). Launch Microsoft Excel, open this file, and
-convince yourself.
-
-Copyright and License
-=====================
-
-POLE - Portable C++ library to access OLE Storage
-Copyright (C) 2002-2007 Ariya Hidayat (ariya@kde.org). 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
-
diff --git a/third-party/pugixml b/third-party/pugixml
index a832e8a5..e4c43a0a 160000
--- a/third-party/pugixml
+++ b/third-party/pugixml
@@ -1 +1 @@
-Subproject commit a832e8a5eff11f58a00ca41ec51ff3895b0da165
+Subproject commit e4c43a0aa2d5cbc158dd279cb2bf6d21f2d27c83
diff --git a/third-party/utfcpp b/third-party/utfcpp
index a5ad5ec9..0232ab81 160000
--- a/third-party/utfcpp
+++ b/third-party/utfcpp
@@ -1 +1 @@
-Subproject commit a5ad5ec9d936d63e9c010d1054f8b11fed0fabbc
+Subproject commit 0232ab8188b16ae6f2293a5817f1d9b0030879a3