optimize format garbage collection and apply style fills to formats correctly, fixes #79, fix cell iteration, closes #73, add third-party licenses to LICENSE.md, update README, fix all clang and msvc warnings

This commit is contained in:
Thomas Fussell 2016-11-09 19:52:18 -05:00
parent 26c2f89abb
commit f90e35e007
58 changed files with 1649 additions and 680 deletions

6
.gitmodules vendored
View File

@ -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
ignore = dirty

View File

@ -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. <http://fsf.org/>
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.

View File

@ -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 <xlnt/xlnt.hpp>
```
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.

View File

@ -83,6 +83,8 @@ public:
/// </summary>
static const std::unordered_map<std::string, int> &error_codes();
cell(const cell &) = default;
// value
/// <summary>
@ -499,6 +501,8 @@ private:
/// </summary>
class format modifiable_format();
cell() = delete;
/// <summary>
/// Private constructor to create a cell from its implementation.
/// </summary>

View File

@ -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;

View File

@ -54,6 +54,8 @@ class XLNT_API invalid_parameter : public exception
{
public:
invalid_parameter();
invalid_parameter(const invalid_parameter &) = default;
virtual ~invalid_parameter();
};
/// <summary>
@ -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();
};
/// <summary>
@ -72,6 +76,7 @@ class XLNT_API missing_number_format : public exception
{
public:
missing_number_format();
virtual ~missing_number_format();
};
/// <summary>
@ -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();
};
/// <summary>
@ -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();
};
/// <summary>
@ -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();
};
/// <summary>
@ -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();
};
/// <summary>
@ -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();
};
/// <summary>
@ -161,6 +176,7 @@ class XLNT_API unhandled_switch_case : public exception
{
public:
unhandled_switch_case();
virtual ~unhandled_switch_case();
};
/// <summary>
@ -170,6 +186,8 @@ class XLNT_API unsupported : public exception
{
public:
unsupported(const std::string &message);
unsupported(const unsupported &) = default;
virtual ~unsupported();
};
} // namespace xlnt

View File

@ -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

View File

@ -38,17 +38,19 @@ class cell_reference;
class range_reference;
enum class major_order;
class XLNT_API cell_iterator : public std::iterator<std::bidirectional_iterator_tag, cell, std::ptrdiff_t, cell*, cell>
class XLNT_API cell_iterator : public std::iterator<std::bidirectional_iterator_tag, cell, std::ptrdiff_t, cell *, cell>
{
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;
bool operator!=(const cell_iterator &other) const;

View File

@ -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;

View File

@ -52,6 +52,8 @@ public:
const cell_vector operator*() const;
const_range_iterator &operator=(const const_range_iterator &) = default;
bool operator==(const const_range_iterator &other) const;
bool operator!=(const const_range_iterator &other) const;

View File

@ -55,6 +55,8 @@ public:
~range();
range(const range &) = default;
cell_vector operator[](std::size_t vector_index);
const cell_vector operator[](std::size_t vector_index) const;

View File

@ -28,15 +28,11 @@
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/worksheet/major_order.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
namespace xlnt {
class cell_vector;
class worksheet;
namespace detail {
struct worksheet_impl;
}
/// <summary>
/// An iterator used by worksheet and range for traversing
@ -45,12 +41,14 @@ struct worksheet_impl;
class XLNT_API range_iterator : public std::iterator<std::bidirectional_iterator_tag, cell_vector, std::ptrdiff_t, cell_vector*, cell_vector>
{
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;
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_;

View File

@ -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})

View File

@ -25,6 +25,8 @@
#include <cmath>
#include <sstream>
#include <detail/cell_impl.hpp>
#include <detail/stylesheet.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/cell/comment.hpp>
@ -49,8 +51,6 @@
#include <xlnt/worksheet/row_properties.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <detail/cell_impl.hpp>
namespace {
std::pair<bool, long double> 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<int, int> 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<int, int> 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<int, int> 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<int, int> 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<int, int> 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<std::string>());
case cell::type::boolean:
return get_value<long double>() == 0 ? "FALSE" : "TRUE";
return get_value<long double>() == 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();
}

View File

@ -7,6 +7,21 @@
#include <xlnt/xlnt.hpp>
#include <numeric>
#include <iostream>
#include <string>
#include <fstream>
#include <random>
#include <chrono>
int random(int min, int max)
{
static std::random_device device{};
static std::default_random_engine engine{ device() };
std::uniform_int_distribution<int> distribution{ min, max };
return distribution(engine);
}
class test_cell : public CxxTest::TestSuite
{
private:

View File

@ -66,7 +66,7 @@ const path constants::part_shared_strings() { return package_xl().append("shared
const std::unordered_map<std::string, std::string> &constants::get_namespaces()
{
const std::unordered_map<std::string, std::string> *namespaces =
static const std::unordered_map<std::string, std::string> *namespaces =
new std::unordered_map<std::string, std::string>
{
{ "worksheet", "http://schemas.openxmlformats.org/spreadsheetml/2006/main" },
@ -77,6 +77,10 @@ const std::unordered_map<std::string, std::string> &constants::get_namespaces()
{ "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/" },
{ "dcmitype", "http://purl.org/dc/dcmitype/" },
@ -96,7 +100,7 @@ const std::unordered_map<std::string, std::string> &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;
}

View File

@ -130,7 +130,7 @@ struct XLNT_API constants
/// <summary>
/// Returns the namespace URI from a namespace name.
/// </summary>
static const std::string get_namespace(const std::string &id);
static const std::string &get_namespace(const std::string &id);
};
} // namespace xlnt

View File

@ -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";
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:
return default_case("?");
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
}
}

View File

@ -1,7 +1,6 @@
#pragma once
#include <xml/parser>
#include <xml/serializer>
#include <detail/include_libstudxml.hpp>
#include <xlnt/packaging/relationship.hpp>
#include <xlnt/styles/border.hpp>

View File

@ -9,7 +9,7 @@ const std::vector<std::uint8_t> &excel_thumbnail();
const std::vector<std::uint8_t> &excel_thumbnail()
{
const auto *data = new std::vector<std::uint8_t>{
static const auto *data = new std::vector<std::uint8_t>{
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

View File

@ -49,6 +49,8 @@ struct format_impl
optional<std::string> style;
std::size_t references = 0;
XLNT_API friend bool operator==(const format_impl &left, const format_impl &right)
{
return left.parent == right.parent

View File

@ -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 <botan_all.h>
#pragma clang diagnostic pop

View File

@ -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 <xml/content>
#include <xml/parser>
#include <xml/qname>
#include <xml/serializer>
#pragma clang diagnostic pop

View File

@ -179,6 +179,10 @@ bool format_condition::satisfied_by(long double number) const
return std::fabs(number - value) >= std::numeric_limits<long double>::min();
case condition_type::equal:
return std::fabs(number - value) < std::numeric_limits<long double>::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<typename std::vector<format_code>::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<int>(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<int>(std::log10(number));
logarithm = static_cast<std::size_t>(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<int>(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<int>(number);
auto original_fractional_part = fractional_part;
fractional_part *= 10;
while (std::abs(fractional_part - static_cast<int>(fractional_part)) > 0.000001
&& std::abs(fractional_part - static_cast<int>(fractional_part)) < 0.999999)
while (std::abs(fractional_part - static_cast<int>(fractional_part)) > 0.000001L
&& std::abs(fractional_part - static_cast<int>(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<std::size_t>(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<std::size_t>(6), part.placeholders.num_zeros + part.placeholders.num_optionals);
auto denominator = static_cast<int>(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<std::size_t>(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<std::size_t>(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<std::size_t>(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<std::size_t>(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<std::size_t>(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;
}
}

View File

@ -31,11 +31,49 @@
#include <vector>
#include <cassert>
#include "pole.h"
#include <detail/pole.hpp>
// 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<std::size_t>& 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<std::uint16_t>(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<std::uint32_t>(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<std::uint8_t>(data & 0xff);
ptr[1] = static_cast<std::uint8_t>((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<std::uint8_t>(data & 0xff);
ptr[1] = static_cast<std::uint8_t>((data >> 8) & 0xff);
ptr[2] = static_cast<std::uint8_t>((data >> 16) & 0xff);
ptr[3] = static_cast<std::uint8_t>((data >> 24) & 0xff);
}
static const std::uint8_t pole_magic[] =
@ -243,9 +281,9 @@ std::vector<std::size_t> 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<std::size_t>(Eof) ) break;
if( p == static_cast<std::size_t>(Bat) ) break;
if( p == static_cast<std::size_t>(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<std::ptrdiff_t>(i);
return -1;
}
@ -353,7 +391,7 @@ std::ptrdiff_t DirTree::parent( std::size_t index )
std::vector<std::size_t> chi = children( j );
for( std::size_t i=0; i<chi.size();i++ )
if( chi[i] == index )
return j;
return static_cast<std::ptrdiff_t>(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<std::size_t>(p) );
if (_entry->dir && _entry->valid)
{
result.insert( 0, _entry->name);
result.insert( 0, "/" );
}
--p;
index = p;
if( index <= 0 ) break;
index = static_cast<std::size_t>(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<std::ptrdiff_t>(chi[i]);
}
// traverse to the child
if( child > 0 ) index = child;
if( child > 0 ) index = static_cast<std::size_t>(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<std::size_t>& 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<std::size_t> DirTree::children( std::size_t index )
{
std::vector<std::size_t> 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<std::size_t>(readU16( buffer + 0x40+p ));
if( name_len > 64 ) name_len = 64;
for( int j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
name.append( 1, buffer[j+p] );
for( std::size_t j=0; ( buffer[j+p]) && (j<name_len); j+= 2 )
name.append( 1, static_cast<char>(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<std::uint16_t>(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<std::uint8_t>(entry_name[j]);
writeU16( buffer + 0x40, static_cast<std::uint16_t>(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<std::uint8_t>(entry_name[j]);
writeU16( buffer + i*128 + 0x40, static_cast<std::uint16_t>(name.length()*2 + 2) );
writeU16( buffer + i*128 + 0x40, static_cast<std::uint16_t>(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<std::uint8_t *>(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<std::size_t> blocks,
@ -851,7 +855,7 @@ std::size_t StorageIO::loadBigBlocks( std::vector<std::size_t> 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<char *>(data) + bytes, filedata + pos, p);
bytes += p;
}
@ -1094,8 +1098,8 @@ std::list<std::string> 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<std::size_t> children = dt->children( parent );
auto parent = dt->indexOf( e );
std::vector<std::size_t> children = dt->children( static_cast<std::size_t>(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<DirEntry*> 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<std::size_t> children = dt->children( parent );
auto parent = dt->indexOf( e );
std::vector<std::size_t> children = dt->children( static_cast<std::size_t>(parent) );
for( std::size_t i = 0; i < children.size(); i++ )
result.push_back( dt->entry( children[i] ) );
}

View File

@ -23,8 +23,7 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POLE_H
#define POLE_H
#pragma once
#include <string>
#include <list>
@ -36,7 +35,6 @@
namespace POLE
{
class StorageIO;
class Stream;
class StreamIO;
@ -353,6 +351,3 @@ namespace POLE
};
} // namespace POLE
#endif // POLE_H

View File

@ -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,13 +55,15 @@ 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)
{
auto iter = format_impls.begin();
std::advance(iter, index);
std::advance(iter, static_cast<std::list<format_impl>::difference_type>(index));
return format(&*iter);
}
@ -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<typename std::vector<T>::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;
std::unordered_map<std::size_t, std::size_t> format_reference_counts;
auto format_iter = format_impls.begin();
for (const auto &impl : format_impls)
while (format_iter != format_impls.end())
{
format_reference_counts[impl.id] = 0;
auto &impl = *format_iter;
if (impl.references != 0)
{
++format_iter;
}
format_reference_counts[new_format]++;
parent->apply_to_cells([&format_reference_counts](cell c)
else
{
if (c.has_format())
{
format_reference_counts[c.format().id()]++;
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<std::size_t, std::size_t> number_format_reference_counts;
std::unordered_map<std::size_t, std::size_t> 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<std::list<format_impl>::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::size_t>(std::distance(style_names.begin(),
std::find(style_names.begin(), style_names.end(), name)));
}
void clear()
@ -402,16 +425,6 @@ struct stylesheet
colors.clear();
}
void enable_garbage_collection()
{
garbage_collection_enabled = true;
}
void disable_garbage_collection()
{
garbage_collection_enabled = false;
}
workbook *parent;
bool garbage_collection_enabled = true;

View File

@ -28,6 +28,9 @@
namespace xlnt {
namespace detail {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
/// <summary>
/// Allows a std::vector to be read through a std::istream.
/// </summary>
@ -160,7 +163,7 @@ private:
{
if (c != traits_type::eof())
{
data_.push_back(c);
data_.push_back(static_cast<std::uint8_t>(c));
position_ = data_.size() - 1;
}
@ -248,5 +251,7 @@ private:
std::size_t position_;
};
#pragma clang diagnostic pop
} // namespace detail
} // namespace xlnt

View File

@ -109,7 +109,7 @@ std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt:
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;
@ -267,7 +322,8 @@ 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 | xml::parser::receive_namespace_decls;
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;
@ -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_;
@ -1560,6 +1645,8 @@ 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<std::string> authors;

View File

@ -20,11 +20,13 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <array>
#include <pole.h>
#include <botan_all.h>
#include <include_libstudxml.hpp>
#include <array>
#include <detail/constants.hpp>
#include <detail/include_botan.hpp>
#include <detail/include_libstudxml.hpp>
#include <detail/pole.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
@ -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<xlnt::detail::hash_algorithm>
{
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<std::uint8_t> aes(const std::vector<std::uint8_t> &key,
const std::vector<std::uint8_t> &iv,
const std::vector<std::uint8_t> &encrypted,
@ -104,6 +152,15 @@ struct crypto_helper
return std::vector<std::uint8_t>(decoded.begin(), decoded.end());
}
static std::string encode_base64(const std::vector<std::uint8_t> &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<std::uint8_t> hash(hash_algorithm algorithm,
const std::vector<std::uint8_t> &input)
{
@ -276,7 +333,7 @@ struct crypto_helper
//todo: verify here
std::size_t package_offset = 0;
auto decrypted_size = read_int<std::uint64_t>(package_offset, encrypted_package);
auto decrypted_size = static_cast<std::size_t>(read_int<std::uint64_t>(package_offset, encrypted_package));
auto decrypted = aes(key_derived, {}, std::vector<std::uint8_t>(
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<std::uint8_t> 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<std::uint8_t> 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<std::uint8_t> decrypt_xlsx_agile(const std::vector<std::uint8_t> &encryption_info,
const std::string &password, const std::vector<std::uint8_t> &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 {};
}
};

View File

@ -52,7 +52,7 @@ const bool skip_unknown_elements = true;
/// </summary>
bool is_integral(long double d)
{
return d == static_cast<long long int>(d);
return std::fabs(d - static_cast<long double>(static_cast<long long int>(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>
static const auto known_fonts = new std::vector<xlnt::font>
{
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 &current_style_name_impl : stylesheet.style_impls)
for (const auto &current_style_name : stylesheet.style_names)
{
auto &current_style_impl = current_style_name_impl.second;
const auto &current_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 &current_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());
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_scheme> font_schemes = {
static const auto font_schemes = new std::vector<font_scheme> {
{ 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<long long int>(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<cell_reference> &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<cell_reference> &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;
}

View File

@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <algorithm>
#include <array>
#include <cassert>
#include <cstring>
#include <fstream>
@ -48,6 +49,7 @@ extern "C" {
}
#include <detail/zip.hpp>
#include <xlnt/utils/exceptions.hpp>
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<char, buffer_size> in;
std::array<char, buffer_size> 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<Bytef *>(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::streamsize>(std::min(buffer_size, header.compressed_size - total_read)));
strm.avail_in = static_cast<unsigned int>(istream.gcount());
total_read += strm.avail_in;
strm.next_in = (Bytef *)in;
strm.next_in = reinterpret_cast<Bytef *>(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<int>(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::streamsize>(std::min(buffer_size - 4, header.uncompressed_size - total_read)));
auto count = istream.gcount();
total_read += static_cast<std::size_t>(count);
return static_cast<int>(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<std::size_t>(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<char, buffer_size> in;
std::array<char, buffer_size> 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<std::uint32_t>(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<Bytef *>(pbase());
strm.avail_in = static_cast<unsigned int>(pptr() - pbase());
while (strm.avail_in != 0 || flush)
{
strm.avail_out = buffer_size;
strm.next_out = (Bytef *)out;
strm.next_out = reinterpret_cast<Bytef *>(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<int>(strm.next_out - reinterpret_cast<std::uint8_t *>(out.data()));
ostream.write(out.data(), generated_output);
if (header) header->compressed_size += static_cast<unsigned int>(generated_output);
if (ret == Z_STREAM_END) break;
}
// update counts, crc's and buffers
int consumed_input = pptr() - pbase();
auto consumed_input = static_cast<unsigned int>(pptr() - pbase());
uncompressed_size += consumed_input;
crc = crc32(crc, (Bytef *)in, consumed_input);
crc = static_cast<unsigned int>(crc32(crc, reinterpret_cast<Bytef *>(in.data()), consumed_input));
setp(pbase(), pbase() + buffer_size - 4);
return 1;
}
@ -393,21 +433,22 @@ 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)
{
virtual int overflow(int c = EOF);
};
int ZipStreambufCompress::overflow(int c)
{
if (c != EOF)
{
*pptr() = c;
*pptr() = static_cast<char>(c);
pbump(1);
}
if (process(false) == EOF) return EOF;
return c;
}
};
}
zip_file_istream::zip_file_istream(std::unique_ptr<std::streambuf> &&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<std::uint32_t>(0x06054b50)); // end of central
write_int(target_stream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(target_stream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(target_stream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center in this disk
write_int(target_stream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center
write_int(target_stream_, static_cast<std::uint32_t>(central_end - final_position)); // size of header
write_int(target_stream_, static_cast<std::uint32_t>(final_position)); // offset to header
write_int(target_stream_, static_cast<std::uint16_t>(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<char> buf(static_cast<std::size_t>(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<std::size_t>(read_start - 3); ++i)
{
if (buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06)
{

View File

@ -111,8 +111,10 @@ optional<border::border_property> 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;
}

View File

@ -22,6 +22,7 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <cmath>
#include <cstdlib>
#include <xlnt/styles/color.hpp>
@ -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;
}

View File

@ -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;
}

View File

@ -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_);
}

View File

@ -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<int>(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,

View File

@ -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

View File

@ -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<double>(raw_time), &integer_part);
fractional_part *= 24;
result.hour = (int)fractional_part;
result.hour = static_cast<int>(fractional_part);
fractional_part = 60 * (fractional_part - result.hour);
result.minute = (int)fractional_part;
result.minute = static_cast<int>(fractional_part);
fractional_part = 60 * (fractional_part - result.minute);
result.second = (int)fractional_part;
result.second = static_cast<int>(fractional_part);
fractional_part = 1000000 * (fractional_part - result.second);
result.microsecond = (int)fractional_part;
result.microsecond = static_cast<int>(fractional_part);
if (result.microsecond == 999999 && fractional_part - result.microsecond > 0.5)
{

View File

@ -65,15 +65,15 @@ timedelta timedelta::from_number(long double raw_time)
result.days = static_cast<int>(integer_part);
fractional_part *= 24;
result.hours = (int)fractional_part;
result.hours = static_cast<int>(fractional_part);
fractional_part = 60 * (fractional_part - result.hours);
result.minutes = (int)fractional_part;
result.minutes = static_cast<int>(fractional_part);
fractional_part = 60 * (fractional_part - result.minutes);
result.seconds = (int)fractional_part;
result.seconds = static_cast<int>(fractional_part);
fractional_part = 1000000 * (fractional_part - result.seconds);
result.microseconds = (int)fractional_part;
result.microseconds = static_cast<int>(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;

View File

@ -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 <utf8.h>
#pragma clang diagnostic pop

View File

@ -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<named_range> 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

View File

@ -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;
@ -71,14 +85,30 @@ cell_iterator cell_iterator::operator--(int)
cell_iterator &cell_iterator::operator++()
{
if (order_ == major_order::row)
{
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
{
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;
}

View File

@ -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<int>(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<int>(index)));
}
std::size_t cell_vector::length() const

View File

@ -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

View File

@ -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)
{
}
@ -87,8 +87,22 @@ range_iterator range_iterator::operator--(int)
range_iterator &range_iterator::operator++()
{
if (order_ == major_order::row)
{
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
{

View File

@ -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<xlnt::cell> 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<std::string>(), "A1");
TS_ASSERT_EQUALS(cells[1].get_value<std::string>(), "F6");
}
const auto ws_const = ws;
{
std::vector<xlnt::cell> 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<std::string>(), "A1");
TS_ASSERT_EQUALS(cells[1].get_value<std::string>(), "F6");
}
}
};

View File

@ -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<long double>() != other_cell.get_value<long double>())
if (this_cell.get_data_type() == xlnt::cell::type::numeric
&& std::fabs(this_cell.get_value<long double>() - other_cell.get_value<long double>()) > 0.L)
{
return false;
}
@ -831,16 +832,16 @@ std::vector<std::string> 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<int>(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

View File

@ -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()

View File

@ -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})

2
third-party/botan vendored

@ -1 +1 @@
Subproject commit 523b2a4ca48fa5cf04ea371aabe7167ce2e5cd13
Subproject commit e6bf87b6b0d4d9c3877b79de53de58dc34a3acca

View File

@ -1 +0,0 @@
Ariya Hidayat <ariya@kde.org>

View File

@ -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.

View File

@ -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 <ahziem1@mailbolt.com>
* 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

View File

@ -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.

View File

@ -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.

2
third-party/pugixml vendored

@ -1 +1 @@
Subproject commit a832e8a5eff11f58a00ca41ec51ff3895b0da165
Subproject commit e4c43a0aa2d5cbc158dd279cb2bf6d21f2d27c83

2
third-party/utfcpp vendored

@ -1 +1 @@
Subproject commit a5ad5ec9d936d63e9c010d1054f8b11fed0fabbc
Subproject commit 0232ab8188b16ae6f2293a5817f1d9b0030879a3