mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
clean up zip.cpp, enable and fix compiler warnings, use equality instead of hashing for style components, compile all cpp files in sample directory, track remote branches for submodules
This commit is contained in:
parent
dce2367524
commit
0d97105122
|
@ -12,8 +12,8 @@ environment:
|
|||
init: []
|
||||
install: []
|
||||
before_build:
|
||||
- git submodule update --init --recursive
|
||||
- cmake -H. -Bbuild -G"Visual Studio 14 2015 Win64" -DSTATIC=%STATIC%
|
||||
- git submodule update --init --recursive --remote
|
||||
- cmake -H. -Bbuild -G"Visual Studio 14 2015 Win64" -DSTATIC=%STATIC% -DSAMPLES=ON
|
||||
|
||||
build:
|
||||
project: build/xlnt_all.sln
|
||||
|
|
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -22,6 +22,8 @@
|
|||
path = third-party/botan
|
||||
url = https://github.com/randombit/botan
|
||||
branch = master
|
||||
|
||||
[submodule "third-party/zlib"]
|
||||
path = third-party/zlib
|
||||
url = https://github.com/madler/zlib.git
|
||||
branch = develop
|
||||
|
|
22
.travis.yml
22
.travis.yml
|
@ -23,6 +23,7 @@ matrix:
|
|||
- pip install --user git+git://github.com/eddyxu/cpp-coveralls.git
|
||||
env:
|
||||
- COMPILER=g++-4.9
|
||||
- COVERAGE=ON
|
||||
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
|
@ -35,25 +36,12 @@ matrix:
|
|||
- valgrind
|
||||
env:
|
||||
- COMPILER=g++-5
|
||||
- COVERAGE=OFF
|
||||
|
||||
script:
|
||||
- cmake --version
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -D SHARED=1 -D STATIC=0 -D WITH_TESTS=1 -D WITH_SAMPLES=1 -D CMAKE_CXX_COMPILER=$COMPILER ..
|
||||
- cmake --build . --target xlnt.test
|
||||
- cmake -D STATIC=ON -D SAMPLES=ON -D COVERAGE=$COVERAGE -D CMAKE_CXX_COMPILER=$COMPILER -D CMAKE_BUILD_TYPE=Debug ..
|
||||
- cmake --build .
|
||||
- cd bin && ./xlnt.test
|
||||
|
||||
after_success:
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 90 ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 90 ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-4.9 90 ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then cd .. ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then rm -rf ./* ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then cmake -G "Unix Makefiles" -D DEBUG=1 -D COVERAGE=1 -D SHARED=0 -DCMAKE_BUILD_TYPE=Debug -D STATIC=1 .. ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then make ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then cd bin && ./xlnt.test ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then cd ../ ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then export OLDWD=$(pwd) ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then cd "build/CMakeFiles/xlnt.static.dir$(pwd)" ; pwd ; fi
|
||||
- if [ "$COMPILER" = "g++-4.9" ]; then coveralls --root $OLDWD --verbose -x ".cpp" --gcov-options '\-p' --exclude include --exclude third-party --exclude tests --exclude samples --exclude benchmarks -E ".*/source/.*/tests/.*" -E ".*/build/tests/runner-autogen.cpp.*" -E ".*CompilerIdCXX/.*" ; fi
|
||||
- find .
|
||||
|
|
|
@ -19,57 +19,107 @@ xlnt is a C++14 library for reading, writing, and modifying XLSX files as descri
|
|||
Summary of Features
|
||||
+++++++++++++++++++
|
||||
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Feature | Read | Edit | Write |
|
||||
|---------------------------------------------------------------------|------|------|-------|
|
||||
+=====================================================================+======+======+=======+
|
||||
| Excel-style Workbook | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| LibreOffice-style Workbook | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Numbers-style Workbook | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Encrypted Workbook (Excel 2007-2010) | ✓ | ✓ | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Encrypted Workbook (Excel 2013-2016) | ✓ | ✓ | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Excel Binary Workbook (.xlsb) | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Excel Macro-Enabled Workbook (.xlsm) | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Excel Macro-Enabled Template (.xltm) | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Document Properties | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Numeric Cell Values | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Inline String Cell Values | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Shared String Cell Values | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Shared String Text Run Formatting (e.g. varied fonts within a cell) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Hyperlink Cell Values | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formula Cell Values | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formula Evaluation | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Page Margins | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Page Setup | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Print Area | | | |
|
||||
| Comments | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Comments | ✓ | ✓ | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Header and Footer | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Custom Views | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Charts | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Chartsheets | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Dialogsheets | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Themes | ✓ | | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Cell Styles | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Cell Formats | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Alignment (e.g. right align) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Border (e.g. red cell outline) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Fill (e.g. green cell background) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Font (e.g. blue cell text) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Number Format (e.g. show 2 decimals) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Formatting->Protection (e.g. hide formulas) | ✓ | ✓ | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Column Styles | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Row Styles | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Sheet Styles | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Conditional Formatting | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Tables | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Table Formatting | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Pivot Tables | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| XLSX Thumbnail | ✓ | | ✓ |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Custom OOXML Properties | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Custom OOXML Parts | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Drawing | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Text Box | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| WordArt | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Embedded Content (e.g. images) | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
| Excel VBA | | | |
|
||||
+---------------------------------------------------------------------+------+------+-------+
|
||||
|
||||
Sample code:
|
||||
++++++++++++
|
||||
|
|
|
@ -86,12 +86,6 @@ public:
|
|||
/// </summary>
|
||||
cell_reference(const std::string &reference_string);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a cell_reference from a string reprenting a column (e.g. A) and
|
||||
/// a 1-indexed row.
|
||||
/// </summary>
|
||||
cell_reference(const std::string &column, row_t row);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a cell_reference from a 1-indexed column index and row index.
|
||||
/// </summary>
|
||||
|
|
|
@ -81,12 +81,12 @@ public:
|
|||
/// <summary>
|
||||
/// Construct a column from a string.
|
||||
/// </summary>
|
||||
explicit column_t(const std::string &column_string);
|
||||
column_t(const std::string &column_string);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a column from a string.
|
||||
/// </summary>
|
||||
explicit column_t(const char *column_string);
|
||||
column_t(const char *column_string);
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <xlnt/utils/hash_combine.hpp>
|
||||
#include <xlnt/styles/horizontal_alignment.hpp>
|
||||
#include <xlnt/styles/vertical_alignment.hpp>
|
||||
#include <xlnt/utils/hashable.hpp>
|
||||
#include <xlnt/utils/optional.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -35,7 +34,7 @@ namespace xlnt {
|
|||
/// <summary>
|
||||
/// Alignment options for use in cell formats.
|
||||
/// </summary>
|
||||
class XLNT_API alignment : public hashable
|
||||
class XLNT_API alignment
|
||||
{
|
||||
public:
|
||||
optional<bool> shrink() const;
|
||||
|
@ -62,8 +61,15 @@ public:
|
|||
|
||||
alignment &vertical(vertical_alignment vertical);
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const alignment &left, const alignment &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const alignment &left, const alignment &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
optional<bool> shrink_to_fit_;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <xlnt/styles/color.hpp>
|
||||
#include <xlnt/styles/diagonal_direction.hpp>
|
||||
#include <xlnt/styles/side.hpp>
|
||||
#include <xlnt/utils/hashable.hpp>
|
||||
#include <xlnt/utils/optional.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -56,7 +55,7 @@ namespace xlnt {
|
|||
/// <summary>
|
||||
/// Describes the border style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API border : public hashable
|
||||
class XLNT_API border
|
||||
{
|
||||
public:
|
||||
class XLNT_API border_property
|
||||
|
@ -68,6 +67,16 @@ public:
|
|||
optional<border_style> style() const;
|
||||
border_property &style(border_style style);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const border_property &left, const border_property &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const border_property &left, const border_property &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
optional<class color> color_;
|
||||
optional<border_style> style_;
|
||||
|
@ -83,8 +92,15 @@ public:
|
|||
optional<diagonal_direction> diagonal() const;
|
||||
border &diagonal(diagonal_direction dir);
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const border &left, const border &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const border &left, const border &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
optional<border_property> start_;
|
||||
|
|
|
@ -87,7 +87,7 @@ private:
|
|||
/// <summary>
|
||||
/// Colors can be applied to many parts of a cell's style.
|
||||
/// </summary>
|
||||
class XLNT_API color : public hashable
|
||||
class XLNT_API color
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
|
@ -136,9 +136,6 @@ public:
|
|||
bool operator==(const color &other) const;
|
||||
bool operator!=(const color &other) const { return !(*this == other); }
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
|
||||
private:
|
||||
void assert_type(type t) const;
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ enum class XLNT_API pattern_fill_type
|
|||
gray0625
|
||||
};
|
||||
|
||||
class XLNT_API pattern_fill : public hashable
|
||||
class XLNT_API pattern_fill
|
||||
{
|
||||
public:
|
||||
pattern_fill();
|
||||
|
@ -71,8 +71,15 @@ public:
|
|||
|
||||
pattern_fill &background(const color &background);
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const pattern_fill &left, const pattern_fill &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const pattern_fill &left, const pattern_fill &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
pattern_fill_type type_ = pattern_fill_type::none;
|
||||
|
@ -87,7 +94,7 @@ enum class XLNT_API gradient_fill_type
|
|||
path
|
||||
};
|
||||
|
||||
class XLNT_API gradient_fill : public hashable
|
||||
class XLNT_API gradient_fill
|
||||
{
|
||||
public:
|
||||
gradient_fill();
|
||||
|
@ -135,8 +142,15 @@ public:
|
|||
|
||||
std::unordered_map<double, color> stops() const;
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const gradient_fill &left, const gradient_fill &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const gradient_fill &left, const gradient_fill &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
gradient_fill_type type_ = gradient_fill_type::linear;
|
||||
|
@ -160,7 +174,7 @@ enum class XLNT_API fill_type
|
|||
/// <summary>
|
||||
/// Describes the fill style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API fill : public hashable
|
||||
class XLNT_API fill
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
|
@ -204,8 +218,15 @@ public:
|
|||
/// </summary>
|
||||
class pattern_fill pattern_fill() const;
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const fill &left, const fill &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const fill &left, const fill &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
fill_type type_ = fill_type::pattern;
|
||||
|
|
|
@ -36,7 +36,7 @@ class style;
|
|||
/// <summary>
|
||||
/// Describes the font style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API font : public hashable
|
||||
class XLNT_API font
|
||||
{
|
||||
public:
|
||||
enum class underline_style
|
||||
|
@ -92,8 +92,15 @@ public:
|
|||
|
||||
optional<std::string> scheme() const;
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const font &left, const font &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const font &left, const font &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
friend class style;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/utils/hashable.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
@ -36,7 +35,7 @@ enum class calendar;
|
|||
/// <summary>
|
||||
/// Describes the number formatting applied to text and numbers within a certain cell.
|
||||
/// </summary>
|
||||
class XLNT_API number_format : public hashable
|
||||
class XLNT_API number_format
|
||||
{
|
||||
public:
|
||||
static const number_format general();
|
||||
|
@ -88,8 +87,16 @@ public:
|
|||
|
||||
bool is_date_format() const;
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const number_format &left, const number_format &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const number_format &left, const number_format &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
bool id_set_;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <cstddef>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/utils/hashable.hpp>
|
||||
#include <xlnt/utils/optional.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -34,7 +33,7 @@ namespace xlnt {
|
|||
/// <summary>
|
||||
/// Describes the protection style of a particular cell.
|
||||
/// </summary>
|
||||
class XLNT_API protection : public hashable
|
||||
class XLNT_API protection
|
||||
{
|
||||
public:
|
||||
static protection unlocked_and_visible();
|
||||
|
@ -50,8 +49,15 @@ public:
|
|||
bool hidden() const;
|
||||
protection &hidden(bool hidden);
|
||||
|
||||
protected:
|
||||
std::string to_hash_string() const override;
|
||||
/// <summary>
|
||||
/// Returns true if left is exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator==(const protection &left, const protection &right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if left is not exactly equal to right.
|
||||
/// </summary>
|
||||
friend bool operator!=(const protection &left, const protection &right) { return !(left == right); }
|
||||
|
||||
private:
|
||||
bool locked_;
|
||||
|
|
|
@ -38,6 +38,8 @@ class XLNT_API exception : public std::runtime_error
|
|||
{
|
||||
public:
|
||||
exception(const std::string &message);
|
||||
exception(const exception &) = default;
|
||||
virtual ~exception();
|
||||
|
||||
void set_message(const std::string &message);
|
||||
|
||||
|
@ -107,6 +109,8 @@ class XLNT_API invalid_column_string_index : public exception
|
|||
{
|
||||
public:
|
||||
invalid_column_string_index();
|
||||
invalid_column_string_index(const invalid_column_string_index &) = default;
|
||||
~invalid_column_string_index();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -117,6 +121,8 @@ class XLNT_API invalid_cell_reference : public exception
|
|||
public:
|
||||
invalid_cell_reference(column_t column, row_t row);
|
||||
invalid_cell_reference(const std::string &reference_string);
|
||||
invalid_cell_reference(const invalid_cell_reference &) = default;
|
||||
~invalid_cell_reference();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -126,6 +132,8 @@ class XLNT_API invalid_attribute : public exception
|
|||
{
|
||||
public:
|
||||
invalid_attribute();
|
||||
invalid_attribute(const invalid_attribute &) = default;
|
||||
virtual ~invalid_attribute();
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
// 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 once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
class XLNT_API hashable
|
||||
{
|
||||
public:
|
||||
std::size_t hash() const;
|
||||
bool operator==(const hashable &other) const;
|
||||
|
||||
protected:
|
||||
virtual std::string to_hash_string() const = 0;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<xlnt::hashable>
|
||||
{
|
||||
size_t operator()(const xlnt::hashable &k) const
|
||||
{
|
||||
return k.hash();
|
||||
}
|
||||
};
|
||||
|
||||
} // namepsace std
|
|
@ -24,7 +24,6 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <utf8.h>
|
||||
#include <xlnt/xlnt_config.hpp> // for XLNT_API
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
#include <xlnt/cell/index_types.hpp>
|
||||
#include <xlnt/cell/cell_reference.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
@ -57,8 +58,8 @@ public:
|
|||
cell_reference top_left_cell;
|
||||
pane_state state;
|
||||
pane_corner active_pane;
|
||||
int y_split;
|
||||
int x_split;
|
||||
row_t y_split;
|
||||
column_t x_split;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -223,10 +223,10 @@ public:
|
|||
|
||||
range iter_cells(bool skip_null);
|
||||
|
||||
void add_print_title(int i);
|
||||
void add_print_title(int i, const std::string &rows_or_cols);
|
||||
void set_print_title_rows(const std::string &rows);
|
||||
void set_print_title_cols(const std::string &rows);
|
||||
void set_print_title_rows(row_t first_row, row_t last_row);
|
||||
void set_print_title_rows(row_t last_row);
|
||||
void set_print_title_cols(column_t first_column, column_t last_column);
|
||||
void set_print_title_cols(column_t last_column);
|
||||
std::string get_print_titles() const;
|
||||
|
||||
void set_print_area(const std::string &print_area);
|
||||
|
|
|
@ -26,28 +26,6 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of possible limit styles.
|
||||
/// Excel places limitations on the number of rows and columns,
|
||||
/// but we may wish to change those limits in some cases. Values
|
||||
/// other than excel might prevent the file from being opened in Excel.
|
||||
/// </summary>
|
||||
enum class limit_style
|
||||
{
|
||||
/// <summary>
|
||||
/// limits used in openpyxl
|
||||
/// </summary>
|
||||
openpyxl,
|
||||
/// <summary>
|
||||
/// limits as determined by Excel
|
||||
/// </summary>
|
||||
excel,
|
||||
/// <summary>
|
||||
/// limits as high as possible based on system (i.e. 32-bit or 64-bit)
|
||||
/// </summary>
|
||||
maximum
|
||||
};
|
||||
|
||||
#ifndef XLNT_API
|
||||
#if !defined(XLNT_STATIC) && defined(_MSC_VER)
|
||||
#ifdef XLNT_EXPORT
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/common.cmake)
|
||||
project(${LIBRARY_NAME}.samples VERSION ${LIBRARY_VERSION} LANGUAGES CXX C)
|
||||
|
||||
|
@ -7,18 +8,22 @@ endif()
|
|||
|
||||
include_directories(${LIBRARY_INCLUDE_DIR})
|
||||
|
||||
add_executable(sample-basic ${CMAKE_CURRENT_SOURCE_DIR}/sample.cpp)
|
||||
target_link_libraries(sample-basic ${LIBRARY_NAME})
|
||||
|
||||
add_executable(sample-decrypt ${CMAKE_CURRENT_SOURCE_DIR}/decrypt.cpp)
|
||||
target_link_libraries(sample-decrypt ${LIBRARY_NAME})
|
||||
file(GLOB SAMPLE_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
|
||||
if(NOT MSVC)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(sample-basic Threads::Threads)
|
||||
target_link_libraries(sample-decrypt Threads::Threads)
|
||||
endif()
|
||||
|
||||
foreach(SAMPLE_SOURCE IN ITEMS ${SAMPLE_SOURCES})
|
||||
get_filename_component(SAMPLE_NAME ${SAMPLE_SOURCE} NAME_WE)
|
||||
set(SAMPLE_EXECUTABLE sample-${SAMPLE_NAME})
|
||||
add_executable(${SAMPLE_EXECUTABLE} ${SAMPLE_SOURCE})
|
||||
target_link_libraries(${SAMPLE_EXECUTABLE} ${LIBRARY_NAME})
|
||||
if(NOT MSVC)
|
||||
target_link_libraries(${SAMPLE_EXECUTABLE} Threads::Threads)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
|
|
|
@ -51,6 +51,14 @@ if(COVERAGE)
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything -Wno-c++98-compat -Wno-padded")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# Prevent a warning about deployment target not being set
|
||||
execute_process(COMMAND "sw_vers -productVersion | awk -F'.' '{print $1\".\"$2}'"
|
||||
|
@ -68,7 +76,6 @@ include_directories(${XLNT_INCLUDE_DIR}
|
|||
${THIRD_PARTY_DIR}/utfcpp/source
|
||||
${THIRD_PARTY_DIR}/pole
|
||||
${THIRD_PARTY_DIR}/botan
|
||||
${THIRD_PARTY_DIR}/partio
|
||||
${THIRD_PARTY_DIR}/zlib)
|
||||
|
||||
file(GLOB ROOT_HEADERS ${XLNT_INCLUDE_DIR}/xlnt/*.hpp)
|
||||
|
@ -92,7 +99,7 @@ file(GLOB WORKBOOK_HEADERS ${XLNT_INCLUDE_DIR}/xlnt/workbook/*.hpp)
|
|||
file(GLOB WORKBOOK_SOURCES ${XLNT_SOURCE_DIR}/workbook/*.cpp)
|
||||
file(GLOB WORKSHEET_HEADERS ${XLNT_INCLUDE_DIR}/xlnt/worksheet/*.hpp)
|
||||
file(GLOB WORKSHEET_SOURCES ${XLNT_SOURCE_DIR}/worksheet/*.cpp)
|
||||
file(GLOB DETAIL_HEADERS ${XLNT_INCLUDE_DIR}/detail/*.hpp)
|
||||
file(GLOB DETAIL_HEADERS ${XLNT_SOURCE_DIR}/detail/*.hpp)
|
||||
file(GLOB DETAIL_SOURCES ${XLNT_SOURCE_DIR}/detail/*.cpp)
|
||||
|
||||
set(XLNT_HEADERS ${ROOT_HEADERS} ${CELL_HEADERS} ${CHARTS_HEADERS}
|
||||
|
|
|
@ -522,7 +522,7 @@ void cell::set_error(const std::string &error)
|
|||
|
||||
cell cell::offset(int column, int row)
|
||||
{
|
||||
return get_worksheet().get_cell(cell_reference(d_->column_ + column, d_->row_ + row));
|
||||
return get_worksheet().get_cell(get_reference().make_offset(column, row));
|
||||
}
|
||||
|
||||
worksheet cell::get_worksheet()
|
||||
|
|
|
@ -61,11 +61,6 @@ cell_reference::cell_reference(const char *reference_string)
|
|||
{
|
||||
}
|
||||
|
||||
cell_reference::cell_reference(const std::string &column, row_t row)
|
||||
: cell_reference(column_t(column), row)
|
||||
{
|
||||
}
|
||||
|
||||
cell_reference::cell_reference(column_t column_index, row_t row)
|
||||
: column_(column_index), row_(row), absolute_row_(false), absolute_column_(false)
|
||||
{
|
||||
|
@ -268,8 +263,10 @@ bool cell_reference::operator!=(const char *reference_string) const
|
|||
cell_reference cell_reference::make_offset(int column_offset, int row_offset) const
|
||||
{
|
||||
//TODO: check for overflow/underflow
|
||||
return cell_reference(static_cast<column_t>(static_cast<int>(column_.index) + column_offset),
|
||||
static_cast<row_t>(static_cast<int>(row_) + row_offset));
|
||||
auto relative_column = static_cast<column_t::index_t>(static_cast<int>(column_.index) + column_offset);
|
||||
auto relative_row = static_cast<row_t>(static_cast<int>(row_) + row_offset);
|
||||
return cell_reference(relative_column, relative_row);
|
||||
|
||||
}
|
||||
|
||||
bool cell_reference::operator==(const cell_reference &comparand) const
|
||||
|
|
|
@ -114,7 +114,7 @@ bool column_t::operator==(const column_t &other) const { return index == other.i
|
|||
|
||||
bool column_t::operator!=(const column_t &other) const { return !(*this == other); }
|
||||
|
||||
bool column_t::operator==(int other) const { return *this == column_t(other); }
|
||||
bool column_t::operator==(int other) const { return *this == column_t(static_cast<index_t>(other)); }
|
||||
|
||||
bool column_t::operator==(index_t other) const { return *this == column_t(other); }
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ bool text_run::has_formatting() const
|
|||
|
||||
bool text_run::has_size() const
|
||||
{
|
||||
return (bool)size_;
|
||||
return size_.is_set();
|
||||
}
|
||||
|
||||
std::size_t text_run::get_size() const
|
||||
|
@ -66,7 +66,7 @@ void text_run::set_size(std::size_t size)
|
|||
|
||||
bool text_run::has_color() const
|
||||
{
|
||||
return (bool)color_;
|
||||
return color_.is_set();
|
||||
}
|
||||
|
||||
color text_run::get_color() const
|
||||
|
@ -81,7 +81,7 @@ void text_run::set_color(const color &new_color)
|
|||
|
||||
bool text_run::has_font() const
|
||||
{
|
||||
return (bool)font_;
|
||||
return font_.is_set();
|
||||
}
|
||||
|
||||
std::string text_run::get_font() const
|
||||
|
@ -96,7 +96,7 @@ void text_run::set_font(const std::string &font)
|
|||
|
||||
bool text_run::has_family() const
|
||||
{
|
||||
return (bool)family_;
|
||||
return family_.is_set();
|
||||
}
|
||||
|
||||
std::size_t text_run::get_family() const
|
||||
|
@ -111,7 +111,7 @@ void text_run::set_family(std::size_t family)
|
|||
|
||||
bool text_run::has_scheme() const
|
||||
{
|
||||
return (bool)scheme_;
|
||||
return scheme_.is_set();
|
||||
}
|
||||
|
||||
std::string text_run::get_scheme() const
|
||||
|
@ -126,7 +126,7 @@ void text_run::set_scheme(const std::string &scheme)
|
|||
|
||||
bool text_run::bold_set() const
|
||||
{
|
||||
return (bool)bold_;
|
||||
return bold_.is_set();
|
||||
}
|
||||
|
||||
bool text_run::is_bold() const
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
const row_t constants::min_row()
|
||||
row_t constants::min_row()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const row_t constants::max_row()
|
||||
row_t constants::max_row()
|
||||
{
|
||||
return std::numeric_limits<row_t>::max();
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ struct XLNT_API constants
|
|||
/// <summary>
|
||||
/// Returns the lowest allowable row index in a worksheet.
|
||||
/// </summary>
|
||||
static const row_t min_row();
|
||||
static row_t min_row();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the largest allowable row index in a worksheet.
|
||||
/// </summary>
|
||||
static const row_t max_row();
|
||||
static row_t max_row();
|
||||
|
||||
/// <summary>
|
||||
/// Returns the lowest allowable column index in a worksheet.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
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>{
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <detail/number_formatter.hpp>
|
||||
#include <xlnt/utils/exceptions.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
namespace {
|
||||
|
||||
const std::unordered_map<int, std::string> known_locales()
|
||||
{
|
||||
|
@ -139,11 +139,30 @@ const std::unordered_map<int, std::string> known_locales()
|
|||
{ 0x3409, "English - Phillippines" },
|
||||
{ 0x3801, "Arabic - United Arab Emirates" },
|
||||
{ 0x4001, "Arabic - Qatar" }
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return *all;
|
||||
}
|
||||
|
||||
[[ noreturn ]] void unhandled_case_error()
|
||||
{
|
||||
throw xlnt::exception("unhandled");
|
||||
}
|
||||
|
||||
void unhandled_case(bool error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
unhandled_case_error();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
bool format_condition::satisfied_by(long double number) const
|
||||
{
|
||||
switch (type)
|
||||
|
@ -157,10 +176,9 @@ bool format_condition::satisfied_by(long double number) const
|
|||
case condition_type::less_than:
|
||||
return number < value;
|
||||
case condition_type::not_equal:
|
||||
return number != value;
|
||||
return std::fabs(number - value) >= std::numeric_limits<long double>::min();
|
||||
case condition_type::equal:
|
||||
default:
|
||||
return number == value;
|
||||
return std::fabs(number - value) < std::numeric_limits<long double>::min();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,6 +354,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::elapsed_seconds;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (token.string == "m")
|
||||
{
|
||||
|
@ -362,6 +384,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::month_letter;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (token.string == "d")
|
||||
{
|
||||
|
@ -383,6 +409,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::day_name;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
if (token.string == "yy")
|
||||
{
|
||||
|
@ -394,6 +424,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::year_long;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
if (token.string == "h")
|
||||
{
|
||||
|
@ -405,6 +439,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::hour_leading_zero;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (token.string == "s")
|
||||
{
|
||||
|
@ -416,6 +454,10 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::second_leading_zero;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
section.twelve_hour = true;
|
||||
|
||||
|
@ -429,6 +471,13 @@ void number_format_parser::parse()
|
|||
part.type = template_part::template_type::a_p;
|
||||
break;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
unhandled_case(true);
|
||||
break;
|
||||
}
|
||||
|
||||
section.parts.push_back(part);
|
||||
|
@ -445,8 +494,6 @@ void number_format_parser::parse()
|
|||
|
||||
token = parse_next_token();
|
||||
}
|
||||
|
||||
throw std::runtime_error("bad format");
|
||||
}
|
||||
|
||||
void number_format_parser::finalize()
|
||||
|
@ -805,11 +852,41 @@ number_format_token number_format_parser::parse_next_token()
|
|||
break;
|
||||
|
||||
case '(':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case ')':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case '-':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case '+':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case ':':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
||||
break;
|
||||
|
||||
case '/':
|
||||
token.type = number_format_token::token_type::text;
|
||||
token.string.push_back(current_char);
|
||||
|
@ -832,6 +909,8 @@ number_format_token number_format_parser::parse_next_token()
|
|||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("unexpected character");
|
||||
}
|
||||
|
@ -951,6 +1030,10 @@ format_color number_format_parser::color_from_string(const std::string &color)
|
|||
return static_cast<format_color>(color_number);
|
||||
}
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
if (color == "Black")
|
||||
{
|
||||
|
@ -960,34 +1043,60 @@ format_color number_format_parser::color_from_string(const std::string &color)
|
|||
{
|
||||
return format_color::blue;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
if (color == "Green")
|
||||
{
|
||||
return format_color::green;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
if (color == "White")
|
||||
{
|
||||
return format_color::white;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (color == "Magenta")
|
||||
{
|
||||
return format_color::magenta;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (color == "Yellow")
|
||||
{
|
||||
return format_color::yellow;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if (color == "Red")
|
||||
{
|
||||
return format_color::red;
|
||||
}
|
||||
|
||||
unhandled_case(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad color: " + color);
|
||||
unhandled_case(true);
|
||||
}
|
||||
|
||||
unhandled_case_error();
|
||||
}
|
||||
|
||||
std::pair<format_locale, std::string> number_format_parser::locale_from_string(const std::string &locale_string)
|
||||
|
@ -1199,7 +1308,8 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
|
|||
else if (p.type == format_placeholders::placeholders_type::fractional_part)
|
||||
{
|
||||
auto fractional_part = number - integer_part;
|
||||
result = fractional_part == 0 ? std::string(".") : std::to_string(fractional_part).substr(1);
|
||||
result = std::fabs(fractional_part) < std::numeric_limits<long double>::min()
|
||||
? std::string(".") : std::to_string(fractional_part).substr(1);
|
||||
|
||||
while (result.back() == '0' || result.size() > (p.num_zeros + p.num_optionals + p.num_spaces + 1))
|
||||
{
|
||||
|
|
|
@ -48,39 +48,32 @@ public:
|
|||
private:
|
||||
int_type underflow()
|
||||
{
|
||||
return (position_ == static_cast<std::streampos>(data_.size()))
|
||||
? traits_type::eof() : traits_type::to_int_type(data_[position_]);
|
||||
if (position_ == data_.size())
|
||||
{
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
return traits_type::to_int_type(static_cast<char>(data_[position_]));
|
||||
}
|
||||
|
||||
int_type uflow()
|
||||
{
|
||||
if (position_ == static_cast<std::streampos>(data_.size()))
|
||||
if (position_ == data_.size())
|
||||
{
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
auto previous = position_;
|
||||
position_ += 1;
|
||||
|
||||
return traits_type::to_int_type(data_[previous]);
|
||||
}
|
||||
|
||||
int_type pbackfail(int_type ch)
|
||||
{
|
||||
if (position_ == std::streampos(0) || (ch != traits_type::eof() && ch != data_[position_ - std::streampos(1)]))
|
||||
{
|
||||
return traits_type::eof();
|
||||
}
|
||||
|
||||
auto old_pos = position_;
|
||||
position_ -= 1;
|
||||
|
||||
return traits_type::to_int_type(data_[position_]);
|
||||
return traits_type::to_int_type(static_cast<char>(data_[position_++]));
|
||||
}
|
||||
|
||||
std::streamsize showmanyc()
|
||||
{
|
||||
return position_ < data_.size() ? data_.size() - position_ : -1;
|
||||
if (position_ == data_.size())
|
||||
{
|
||||
return static_cast<std::streamsize>(-1);
|
||||
}
|
||||
|
||||
return static_cast<std::streamsize>(data_.size() - position_);
|
||||
}
|
||||
|
||||
std::streampos seekoff(std::streamoff off,
|
||||
|
@ -96,23 +89,56 @@ private:
|
|||
position_ = data_.size();
|
||||
}
|
||||
|
||||
position_ += off;
|
||||
if (off < 0)
|
||||
{
|
||||
if (static_cast<std::size_t>(-off) > position_)
|
||||
{
|
||||
position_ = 0;
|
||||
return static_cast<std::ptrdiff_t>(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ -= static_cast<std::size_t>(-off);
|
||||
}
|
||||
}
|
||||
else if (off > 0)
|
||||
{
|
||||
if (static_cast<std::size_t>(off) + position_ > data_.size())
|
||||
{
|
||||
position_ = data_.size();
|
||||
return static_cast<std::ptrdiff_t>(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ += static_cast<std::size_t>(off);
|
||||
}
|
||||
}
|
||||
|
||||
if (position_ < 0) return -1;
|
||||
if (position_ > data_.size()) return -1;
|
||||
|
||||
return position_;
|
||||
return static_cast<std::ptrdiff_t>(position_);
|
||||
}
|
||||
|
||||
std::streampos seekpos(std::streampos sp,
|
||||
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
return position_ = sp;
|
||||
if (sp < 0)
|
||||
{
|
||||
position_ = 0;
|
||||
}
|
||||
else if (static_cast<std::size_t>(sp) > data_.size())
|
||||
{
|
||||
position_ = data_.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ = static_cast<std::size_t>(sp);
|
||||
}
|
||||
|
||||
return static_cast<std::ptrdiff_t>(position_);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<std::uint8_t> &data_;
|
||||
std::streampos position_;
|
||||
std::size_t position_;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -141,59 +167,91 @@ private:
|
|||
position_ = data_.size() - 1;
|
||||
}
|
||||
|
||||
return traits_type::to_int_type(data_[position_]);
|
||||
return traits_type::to_int_type(static_cast<char>(data_[position_]));
|
||||
}
|
||||
|
||||
std::streamsize xsputn(const char *s, std::streamsize n)
|
||||
{
|
||||
if (data_.empty())
|
||||
{
|
||||
data_.resize(n);
|
||||
data_.resize(static_cast<std::size_t>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto position_size = data_.size();
|
||||
auto required_size = static_cast<std::size_t>(position_ + static_cast<std::streampos>(n));
|
||||
auto required_size = static_cast<std::size_t>(position_ + static_cast<std::size_t>(n));
|
||||
data_.resize(std::max(position_size, required_size));
|
||||
}
|
||||
|
||||
std::copy(s, s + n, data_.begin() + position_);
|
||||
position_ += n;
|
||||
std::copy(s, s + n, data_.begin() + static_cast<std::ptrdiff_t>(position_));
|
||||
position_ += static_cast<std::size_t>(n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way,
|
||||
std::streampos seekoff(std::streamoff off,
|
||||
std::ios_base::seekdir way,
|
||||
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
if (way == std::ios_base::beg)
|
||||
{
|
||||
position_ = off;
|
||||
}
|
||||
else if (way == std::ios_base::cur)
|
||||
{
|
||||
position_ += off;
|
||||
position_ = 0;
|
||||
}
|
||||
else if (way == std::ios_base::end)
|
||||
{
|
||||
position_ = data_.size();
|
||||
}
|
||||
|
||||
return (position_ < 0 || position_ > data_.size())
|
||||
? std::streampos(-1) : position_;
|
||||
if (off < 0)
|
||||
{
|
||||
if (static_cast<std::size_t>(-off) > position_)
|
||||
{
|
||||
position_ = 0;
|
||||
return static_cast<std::ptrdiff_t>(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ -= static_cast<std::size_t>(-off);
|
||||
}
|
||||
}
|
||||
else if (off > 0)
|
||||
{
|
||||
if (static_cast<std::size_t>(off) + position_ > data_.size())
|
||||
{
|
||||
position_ = data_.size();
|
||||
return static_cast<std::ptrdiff_t>(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ += static_cast<std::size_t>(off);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<std::ptrdiff_t>(position_);
|
||||
}
|
||||
|
||||
std::streampos seekpos(std::streampos sp,
|
||||
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
position_ = sp;
|
||||
return (position_ < 0 || position_ > data_.size())
|
||||
? std::streampos(-1) : position_;
|
||||
if (sp < 0)
|
||||
{
|
||||
position_ = 0;
|
||||
}
|
||||
else if (static_cast<std::size_t>(sp) > data_.size())
|
||||
{
|
||||
position_ = data_.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
position_ = static_cast<std::size_t>(sp);
|
||||
}
|
||||
|
||||
return static_cast<std::ptrdiff_t>(position_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::uint8_t> &data_;
|
||||
std::streampos position_;
|
||||
std::size_t position_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
@ -99,13 +99,13 @@ xlnt::color read_color(xml::parser &parser)
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, Partio::ZipFileReader &archive)
|
||||
std::vector<xlnt::relationship> read_relationships(const xlnt::path &part, xlnt::detail::ZipFileReader &archive)
|
||||
{
|
||||
std::vector<xlnt::relationship> relationships;
|
||||
if (!archive.Has_File(part.string())) return relationships;
|
||||
if (!archive.has_file(part.string())) return relationships;
|
||||
|
||||
std::unique_ptr<std::istream> rels_stream(archive.Get_File(part.string(), true));
|
||||
xml::parser parser(*rels_stream, part.string());
|
||||
auto &rels_stream = archive.open(part.string());
|
||||
xml::parser parser(rels_stream, part.string());
|
||||
|
||||
xlnt::uri source(part.string());
|
||||
|
||||
|
@ -152,7 +152,7 @@ xlsx_consumer::xlsx_consumer(workbook &target)
|
|||
|
||||
void xlsx_consumer::read(std::istream &source)
|
||||
{
|
||||
archive_.reset(new Partio::ZipFileReader(source));
|
||||
archive_.reset(new ZipFileReader(source));
|
||||
populate_workbook();
|
||||
}
|
||||
|
||||
|
@ -170,8 +170,8 @@ void xlsx_consumer::populate_workbook()
|
|||
|
||||
for (const auto &rel : manifest.get_relationships(path("/")))
|
||||
{
|
||||
std::unique_ptr<std::istream> parser_stream(archive_->Get_File(rel.get_target().get_path().string(), true));
|
||||
xml::parser parser(*parser_stream, rel.get_target().get_path().string());
|
||||
xml::parser parser(archive_->open(rel.get_target().get_path().string()),
|
||||
rel.get_target().get_path().string());
|
||||
parser_ = &parser;
|
||||
|
||||
switch (rel.get_type())
|
||||
|
@ -235,11 +235,10 @@ 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()));
|
||||
std::unique_ptr<std::istream> parser_stream(archive_->Get_File(part_path.string(), true));
|
||||
auto using_namespaces = rel.get_type() == relationship::type::styles;
|
||||
auto receive = xml::parser::receive_default
|
||||
| (using_namespaces ? xml::parser::receive_namespace_decls : 0);
|
||||
xml::parser parser(*parser_stream, part_path.string(), receive);
|
||||
xml::parser parser(archive_->open(part_path.string()), part_path.string(), receive);
|
||||
parser_ = &parser;
|
||||
|
||||
switch (rel.get_type())
|
||||
|
@ -268,9 +267,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()));
|
||||
std::unique_ptr<std::istream> parser_stream(archive_->Get_File(part_path.string(), true));
|
||||
auto receive = xml::parser::receive_default | xml::parser::receive_namespace_decls;
|
||||
xml::parser parser(*parser_stream, rel.get_target().get_path().string(), receive);
|
||||
xml::parser parser(archive_->open(part_path.string()), rel.get_target().get_path().string(), receive);
|
||||
parser_ = &parser;
|
||||
|
||||
switch (rel.get_type())
|
||||
|
@ -306,21 +304,17 @@ void xlsx_consumer::read_manifest()
|
|||
{
|
||||
path package_rels_path("_rels/.rels");
|
||||
|
||||
if (!archive_->Has_File(package_rels_path.string()))
|
||||
if (!archive_->has_file(package_rels_path.string()))
|
||||
{
|
||||
throw invalid_file("missing package rels");
|
||||
}
|
||||
|
||||
auto package_rels = read_relationships(package_rels_path, *archive_);
|
||||
|
||||
std::unique_ptr<std::istream> parser_stream(archive_->Get_File("[Content_Types].xml", true));
|
||||
//std::string stream_string((std::istreambuf_iterator<char>(*parser_stream)), std::istreambuf_iterator<char>());
|
||||
xml::parser parser(*parser_stream, "[Content_Types].xml");
|
||||
|
||||
auto &manifest = target_.get_manifest();
|
||||
|
||||
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");
|
||||
parser.content(xml::content::complex);
|
||||
|
||||
|
@ -355,10 +349,7 @@ void xlsx_consumer::read_manifest()
|
|||
package_rel.get_id());
|
||||
}
|
||||
|
||||
std::vector<std::string> file_list;
|
||||
archive_->Get_File_List(file_list);
|
||||
|
||||
for (const auto &relationship_source_string : file_list)
|
||||
for (const auto &relationship_source_string : archive_->files())
|
||||
{
|
||||
auto relationship_source = path(relationship_source_string);
|
||||
|
||||
|
@ -2013,9 +2004,8 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
|
|||
part_path = std::accumulate(split_part_path.begin(), split_part_path.end(), path(""),
|
||||
[](const path &a, const std::string &b) { return a.append(b); });
|
||||
|
||||
std::unique_ptr<std::istream> parser_stream(archive_->Get_File(part_path.string(), true));
|
||||
auto receive = xml::parser::receive_default;
|
||||
xml::parser parser(*parser_stream, rel.get_target().get_path().string(), receive);
|
||||
xml::parser parser(archive_->open(part_path.string()), rel.get_target().get_path().string(), receive);
|
||||
parser_ = &parser;
|
||||
|
||||
switch (rel.get_type())
|
||||
|
|
|
@ -30,10 +30,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <detail/include_libstudxml.hpp>
|
||||
|
||||
namespace Partio {
|
||||
class ZipFileReader;
|
||||
}
|
||||
#include <detail/zip.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
@ -44,6 +41,8 @@ class worksheet;
|
|||
|
||||
namespace detail {
|
||||
|
||||
class ZipFileReader;
|
||||
|
||||
/// <summary>
|
||||
/// Handles writing a workbook into an XLSX file.
|
||||
/// </summary>
|
||||
|
@ -218,7 +217,7 @@ private:
|
|||
/// <summary>
|
||||
/// The ZIP file containing the files that make up the OOXML package.
|
||||
/// </summary>
|
||||
std::unique_ptr<Partio::ZipFileReader> archive_;
|
||||
std::unique_ptr<ZipFileReader> archive_;
|
||||
|
||||
/// <summary>
|
||||
/// Map of sheet titles to relationship IDs.
|
||||
|
|
|
@ -33,10 +33,12 @@
|
|||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
static const std::size_t segment_length = 4096;
|
||||
|
||||
enum class cipher_algorithm
|
||||
struct crypto_helper
|
||||
{
|
||||
static const std::size_t segment_length = 4096;
|
||||
|
||||
enum class cipher_algorithm
|
||||
{
|
||||
aes,
|
||||
rc2,
|
||||
rc4,
|
||||
|
@ -44,23 +46,23 @@ enum class cipher_algorithm
|
|||
desx,
|
||||
triple_des,
|
||||
triple_des_112
|
||||
};
|
||||
};
|
||||
|
||||
enum class cipher_chaining
|
||||
{
|
||||
enum class cipher_chaining
|
||||
{
|
||||
ecb, // electronic code book
|
||||
cbc, // cipher block chaining
|
||||
cfb // cipher feedback chaining
|
||||
};
|
||||
};
|
||||
|
||||
enum class cipher_direction
|
||||
{
|
||||
enum class cipher_direction
|
||||
{
|
||||
encryption,
|
||||
decryption
|
||||
};
|
||||
};
|
||||
|
||||
enum class hash_algorithm
|
||||
{
|
||||
enum class hash_algorithm
|
||||
{
|
||||
sha1,
|
||||
sha256,
|
||||
sha384,
|
||||
|
@ -71,13 +73,13 @@ enum class hash_algorithm
|
|||
ripemd128,
|
||||
ripemd160,
|
||||
whirlpool
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> aes(const std::vector<std::uint8_t> &key,
|
||||
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,
|
||||
cipher_chaining chaining, cipher_direction direction)
|
||||
{
|
||||
{
|
||||
std::string cipher_name("AES-");
|
||||
cipher_name.append(std::to_string(key.size() * 8));
|
||||
cipher_name.append(chaining == cipher_chaining::ecb
|
||||
|
@ -90,48 +92,48 @@ std::vector<std::uint8_t> aes(const std::vector<std::uint8_t> &key,
|
|||
auto decrypted = pipe.read_all();
|
||||
|
||||
return std::vector<std::uint8_t>(decrypted.begin(), decrypted.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> decode_base64(const std::string &encoded)
|
||||
{
|
||||
static std::vector<std::uint8_t> decode_base64(const std::string &encoded)
|
||||
{
|
||||
Botan::Pipe pipe(new Botan::Base64_Decoder);
|
||||
pipe.process_msg(encoded);
|
||||
auto decoded = pipe.read_all();
|
||||
|
||||
return std::vector<std::uint8_t>(decoded.begin(), decoded.end());
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> hash(hash_algorithm algorithm,
|
||||
static std::vector<std::uint8_t> hash(hash_algorithm algorithm,
|
||||
const std::vector<std::uint8_t> &input)
|
||||
{
|
||||
{
|
||||
Botan::Pipe pipe(new Botan::Hash_Filter(
|
||||
algorithm == hash_algorithm::sha512 ? "SHA-512" : "SHA-1"));
|
||||
pipe.process_msg(input);
|
||||
auto hash = pipe.read_all();
|
||||
|
||||
return std::vector<std::uint8_t>(hash.begin(), hash.end());
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> get_file(POLE::Storage &storage, const std::string &name)
|
||||
{
|
||||
static std::vector<std::uint8_t> get_file(POLE::Storage &storage, const std::string &name)
|
||||
{
|
||||
POLE::Stream stream(&storage, name.c_str());
|
||||
if (stream.fail()) return {};
|
||||
std::vector<std::uint8_t> bytes(stream.size(), 0);
|
||||
stream.read(bytes.data(), static_cast<unsigned long>(bytes.size()));
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto read_int(std::size_t &index, const std::vector<std::uint8_t> &raw_data)
|
||||
{
|
||||
template<typename T>
|
||||
static auto read_int(std::size_t &index, const std::vector<std::uint8_t> &raw_data)
|
||||
{
|
||||
auto result = *reinterpret_cast<const T *>(&raw_data[index]);
|
||||
index += sizeof(T);
|
||||
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
struct standard_encryption_info
|
||||
{
|
||||
struct standard_encryption_info
|
||||
{
|
||||
const std::size_t spin_count = 50000;
|
||||
std::size_t block_size;
|
||||
std::size_t key_bits;
|
||||
|
@ -144,11 +146,11 @@ struct standard_encryption_info
|
|||
std::vector<std::uint8_t> verifier_hash_input;
|
||||
std::vector<std::uint8_t> verifier_hash_value;
|
||||
std::vector<std::uint8_t> encrypted_key_value;
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t> &encryption_info,
|
||||
static std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t> &encryption_info,
|
||||
const std::string &password, const std::vector<std::uint8_t> &encrypted_package)
|
||||
{
|
||||
{
|
||||
std::size_t offset = 0;
|
||||
|
||||
standard_encryption_info info;
|
||||
|
@ -191,8 +193,8 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t>
|
|||
|
||||
const auto csp_name_length = header_length - (offset - index_at_start);
|
||||
std::vector<std::uint16_t> csp_name_wide(
|
||||
reinterpret_cast<const std::uint16_t *>(&*(encryption_info.begin() + offset)),
|
||||
reinterpret_cast<const std::uint16_t *>(&*(encryption_info.begin() + offset + csp_name_length)));
|
||||
reinterpret_cast<const std::uint16_t *>(&*(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset))),
|
||||
reinterpret_cast<const std::uint16_t *>(&*(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + csp_name_length))));
|
||||
std::string csp_name(csp_name_wide.begin(), csp_name_wide.end() - 1); // without trailing null
|
||||
if (csp_name != "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)"
|
||||
&& csp_name != "Microsoft Enhanced RSA and AES Cryptographic Provider")
|
||||
|
@ -202,18 +204,18 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t>
|
|||
offset += csp_name_length;
|
||||
|
||||
const auto salt_size = read_int<std::uint32_t>(offset, encryption_info);
|
||||
std::vector<std::uint8_t> salt(encryption_info.begin() + offset,
|
||||
encryption_info.begin() + offset + salt_size);
|
||||
std::vector<std::uint8_t> salt(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset),
|
||||
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + salt_size));
|
||||
offset += salt_size;
|
||||
|
||||
static const auto verifier_size = std::size_t(16);
|
||||
std::vector<std::uint8_t> verifier_hash_input(encryption_info.begin() + offset,
|
||||
encryption_info.begin() + offset + verifier_size);
|
||||
std::vector<std::uint8_t> verifier_hash_input(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset),
|
||||
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + verifier_size));
|
||||
offset += verifier_size;
|
||||
|
||||
const auto verifier_hash_size = read_int<std::uint32_t>(offset, encryption_info);
|
||||
std::vector<std::uint8_t> verifier_hash_value(encryption_info.begin() + offset,
|
||||
encryption_info.begin() + offset + 32);
|
||||
std::vector<std::uint8_t> verifier_hash_value(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset),
|
||||
encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + verifier_hash_size));
|
||||
offset += verifier_hash_size;
|
||||
|
||||
// begin key generation algorithm
|
||||
|
@ -268,7 +270,7 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t>
|
|||
auto X3 = X1;
|
||||
X3.insert(X3.end(), X2.begin(), X2.end());
|
||||
|
||||
auto key_derived = std::vector<std::uint8_t>(X3.begin(), X3.begin() + info.key_bytes);
|
||||
auto key_derived = std::vector<std::uint8_t>(X3.begin(), X3.begin() + static_cast<std::ptrdiff_t>(info.key_bytes));
|
||||
|
||||
//todo: verify here
|
||||
|
||||
|
@ -280,11 +282,10 @@ std::vector<std::uint8_t> decrypt_xlsx_standard(const std::vector<std::uint8_t>
|
|||
decrypted.resize(decrypted_size);
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct agile_encryption_info
|
||||
{
|
||||
struct agile_encryption_info
|
||||
{
|
||||
// key data
|
||||
struct
|
||||
{
|
||||
|
@ -319,11 +320,11 @@ struct agile_encryption_info
|
|||
std::vector<std::uint8_t> verifier_hash_value;
|
||||
std::vector<std::uint8_t> encrypted_key_value;
|
||||
} key_encryptor;
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<std::uint8_t> decrypt_xlsx_agile(const std::vector<std::uint8_t> &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");
|
||||
|
@ -496,8 +497,10 @@ std::vector<std::uint8_t> decrypt_xlsx_agile(const std::vector<std::uint8_t> &en
|
|||
iv.resize(16);
|
||||
|
||||
auto decrypted_segment = aes(key, iv, std::vector<std::uint8_t>(
|
||||
encrypted_package.begin() + i, encrypted_package.begin() + i + segment_length),
|
||||
encrypted_package.begin() + static_cast<std::ptrdiff_t>(i),
|
||||
encrypted_package.begin() + static_cast<std::ptrdiff_t>(i) + segment_length),
|
||||
cipher_chaining::cbc, cipher_direction::decryption);
|
||||
|
||||
decrypted_package.insert(decrypted_package.end(),
|
||||
decrypted_segment.begin(), decrypted_segment.end());
|
||||
|
||||
|
@ -507,10 +510,10 @@ std::vector<std::uint8_t> decrypt_xlsx_agile(const std::vector<std::uint8_t> &en
|
|||
decrypted_package.resize(total_size);
|
||||
|
||||
return decrypted_package;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> decrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password)
|
||||
{
|
||||
static std::vector<std::uint8_t> decrypt_xlsx(const std::vector<std::uint8_t> &bytes, const std::string &password)
|
||||
{
|
||||
if (bytes.empty())
|
||||
{
|
||||
throw xlnt::exception("empty file");
|
||||
|
@ -534,7 +537,8 @@ std::vector<std::uint8_t> decrypt_xlsx(const std::vector<std::uint8_t> &bytes, c
|
|||
auto encryption_flags = read_int<std::uint32_t>(index, encryption_info);
|
||||
|
||||
// get rid of header
|
||||
encryption_info.erase(encryption_info.begin(), encryption_info.begin() + index);
|
||||
encryption_info.erase(encryption_info.begin(),
|
||||
encryption_info.begin() + static_cast<std::ptrdiff_t>(index));
|
||||
|
||||
// version 4.4 is agile
|
||||
if (version_major == 4 && version_minor == 4)
|
||||
|
@ -571,13 +575,14 @@ std::vector<std::uint8_t> decrypt_xlsx(const std::vector<std::uint8_t> &bytes, c
|
|||
}
|
||||
|
||||
return decrypt_xlsx_standard(encryption_info, password, encrypted_package);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void xlsx_consumer::read(std::istream &source, const std::string &password)
|
||||
{
|
||||
std::vector<std::uint8_t> data((std::istreambuf_iterator<char>(source)),
|
||||
(std::istreambuf_iterator<char>()));
|
||||
const auto decrypted = decrypt_xlsx(data, password);
|
||||
const auto decrypted = crypto_helper::decrypt_xlsx(data, password);
|
||||
vector_istreambuf decrypted_buffer(decrypted);
|
||||
std::istream decrypted_stream(&decrypted_buffer);
|
||||
read(decrypted_stream);
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
#include <numeric> // for std::accumulate
|
||||
#include <string>
|
||||
|
||||
#include <detail/custom_value_traits.hpp>
|
||||
#include <detail/xlsx_producer.hpp>
|
||||
#include <detail/constants.hpp>
|
||||
#include <detail/custom_value_traits.hpp>
|
||||
#include <detail/vector_streambuf.hpp>
|
||||
#include <detail/workbook_impl.hpp>
|
||||
#include <detail/xlsx_producer.hpp>
|
||||
#include <detail/zip.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/utils/path.hpp>
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
|
@ -84,7 +86,7 @@ xlsx_producer::xlsx_producer(const workbook &target) : source_(target)
|
|||
|
||||
void xlsx_producer::write(std::ostream &destination)
|
||||
{
|
||||
Partio::ZipFileWriter archive(destination);
|
||||
ZipFileWriter archive(destination);
|
||||
archive_ = &archive;
|
||||
populate_archive();
|
||||
}
|
||||
|
@ -100,6 +102,13 @@ void xlsx_producer::populate_archive()
|
|||
|
||||
for (auto &rel : root_rels)
|
||||
{
|
||||
// thumbnail is binary content so we don't want to open an xml serializer stream
|
||||
if (rel.get_type() == relationship::type::thumbnail)
|
||||
{
|
||||
write_thumbnail(rel);
|
||||
continue;
|
||||
}
|
||||
|
||||
begin_part(rel.get_target().get_path());
|
||||
|
||||
switch (rel.get_type())
|
||||
|
@ -120,10 +129,6 @@ void xlsx_producer::populate_archive()
|
|||
write_workbook(rel);
|
||||
break;
|
||||
|
||||
case relationship::type::thumbnail:
|
||||
write_thumbnail(rel);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -154,7 +159,7 @@ void xlsx_producer::begin_part(const path &part)
|
|||
{
|
||||
end_part();
|
||||
|
||||
current_part_stream_.reset(archive_->Add_File(part.string(), true));
|
||||
current_part_stream_.reset(archive_->open(part.string()));
|
||||
current_part_serializer_.reset(new xml::serializer(*current_part_stream_, part.string()));
|
||||
}
|
||||
|
||||
|
@ -2498,11 +2503,12 @@ void xlsx_producer::write_unknown_relationships()
|
|||
|
||||
void xlsx_producer::write_thumbnail(const relationship &rel)
|
||||
{
|
||||
end_part();
|
||||
|
||||
const auto &thumbnail = source_.get_thumbnail();
|
||||
std::unique_ptr<std::ostream> thumbnail_stream(
|
||||
archive_->Add_File(rel.get_target().get_path().string(), true));
|
||||
std::for_each(thumbnail.begin(), thumbnail.end(),
|
||||
[&thumbnail_stream](std::uint8_t b) { *thumbnail_stream << b; });
|
||||
current_part_stream_.reset(archive_->open(rel.get_target().get_path().string()));
|
||||
vector_istreambuf thumbnail_buffer(thumbnail);
|
||||
*current_part_stream_ << &thumbnail_buffer;
|
||||
}
|
||||
|
||||
xml::serializer &xlsx_producer::serializer()
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
#include <vector>
|
||||
|
||||
#include <detail/include_libstudxml.hpp>
|
||||
#include <detail/zip.hpp>
|
||||
|
||||
namespace Partio {
|
||||
class ZipFileWriter;
|
||||
}
|
||||
|
||||
namespace xml {
|
||||
class serializer;
|
||||
|
@ -49,6 +44,8 @@ class worksheet;
|
|||
|
||||
namespace detail {
|
||||
|
||||
class ZipFileWriter;
|
||||
|
||||
/// <summary>
|
||||
/// Handles writing a workbook into an XLSX file.
|
||||
/// </summary>
|
||||
|
@ -138,7 +135,7 @@ private:
|
|||
/// </summary>
|
||||
const workbook &source_;
|
||||
|
||||
Partio::ZipFileWriter *archive_;
|
||||
ZipFileWriter *archive_;
|
||||
std::unique_ptr<std::ostream> current_part_stream_;
|
||||
std::unique_ptr<xml::serializer> current_part_serializer_;
|
||||
};
|
||||
|
|
|
@ -33,10 +33,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
extern "C"{
|
||||
#include <zlib.h>
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
|
@ -46,123 +42,129 @@ extern "C"{
|
|||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <detail/zip.hpp>
|
||||
|
||||
namespace Partio{
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
inline void Swap_Endianity(T& x)
|
||||
inline T read_int(std::istream &stream)
|
||||
{
|
||||
assert(sizeof(T)<=8);
|
||||
if(sizeof(T)>1) {
|
||||
T old=x;
|
||||
for(unsigned int k=1;k<=sizeof(T);k++) ((char*)&x)[k-1]=((char*)&old)[sizeof(T)-k];
|
||||
}
|
||||
T value;
|
||||
stream.read(reinterpret_cast<char *>(&value), sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Read_Primitive(std::istream& stream,T& x)
|
||||
inline void write_int(std::ostream &stream, T value)
|
||||
{
|
||||
stream.read(&(char&)x,sizeof(T));
|
||||
stream.write(reinterpret_cast<char *>(&value), sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Write_Primitive(std::ostream& stream,const T& x)
|
||||
struct zip_file_header
|
||||
{
|
||||
stream.write(&(char&)x,sizeof(T));
|
||||
}
|
||||
|
||||
//#####################################################################
|
||||
// class ZipFileHeader
|
||||
//#####################################################################
|
||||
struct ZipFileHeader
|
||||
{
|
||||
unsigned short version;
|
||||
unsigned short flags;
|
||||
unsigned short compression_type;
|
||||
unsigned short stamp_date,stamp_time;
|
||||
unsigned int crc;
|
||||
unsigned int compressed_size,uncompressed_size;
|
||||
std::uint16_t version = 20;
|
||||
std::uint16_t flags = 0;
|
||||
std::uint16_t compression_type = 8;
|
||||
std::uint16_t stamp_date,stamp_time = 0;
|
||||
std::uint32_t crc = 0;
|
||||
std::uint32_t compressed_size = 0;
|
||||
std::uint32_t uncompressed_size = 0;
|
||||
std::string filename;
|
||||
unsigned int header_offset; // local header offset
|
||||
std::string comment;
|
||||
std::vector<std::uint8_t> extra;
|
||||
std::uint32_t header_offset = 0; // local header offset
|
||||
|
||||
ZipFileHeader()
|
||||
{}
|
||||
zip_file_header()
|
||||
{
|
||||
}
|
||||
|
||||
ZipFileHeader(const std::string& filename_input)
|
||||
:version(20),flags(0),compression_type(8),stamp_date(0),stamp_time(0),crc(0),
|
||||
compressed_size(0),uncompressed_size(0),filename(filename_input),header_offset(0)
|
||||
{}
|
||||
bool read(std::istream& istream,const bool global)
|
||||
{
|
||||
auto sig = read_int<std::uint32_t>(istream);
|
||||
|
||||
bool Read(std::istream& istream,const bool global)
|
||||
{unsigned int sig;
|
||||
unsigned short version,flags;
|
||||
// read and check for local/global magic
|
||||
if(global){
|
||||
Read_Primitive(istream,sig);
|
||||
if(sig!=0x02014b50){std::cerr<<"Did not find global header signature"<<std::endl;return false;}
|
||||
Read_Primitive(istream,version);}
|
||||
else{
|
||||
Read_Primitive(istream,sig);
|
||||
if(sig!=0x04034b50){std::cerr<<"Did not find local header signature"<<std::endl;return false;}}
|
||||
if(global)
|
||||
{
|
||||
if(sig!=0x02014b50)
|
||||
{
|
||||
std::cerr<<"Did not find global header signature"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
version = read_int<std::uint16_t>(istream);
|
||||
}
|
||||
else if(sig!=0x04034b50)
|
||||
{
|
||||
std::cerr<<"Did not find local header signature"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read rest of header
|
||||
Read_Primitive(istream,version);
|
||||
Read_Primitive(istream,flags);
|
||||
Read_Primitive(istream,compression_type);
|
||||
Read_Primitive(istream,stamp_date);
|
||||
Read_Primitive(istream,stamp_time);
|
||||
Read_Primitive(istream,crc);
|
||||
Read_Primitive(istream,compressed_size);
|
||||
Read_Primitive(istream,uncompressed_size);
|
||||
unsigned short filename_length,extra_length;
|
||||
Read_Primitive(istream,filename_length);
|
||||
Read_Primitive(istream,extra_length);
|
||||
unsigned short comment_length=0;
|
||||
if(global){
|
||||
Read_Primitive(istream,comment_length); // filecomment
|
||||
unsigned short disk_number_start,int_file_attrib;
|
||||
unsigned int ext_file_attrib;
|
||||
Read_Primitive(istream,disk_number_start); // disk# start
|
||||
Read_Primitive(istream,int_file_attrib); // internal file
|
||||
Read_Primitive(istream,ext_file_attrib); // ext final
|
||||
Read_Primitive(istream,header_offset);} // rel offset
|
||||
char* buf=new char[std::max(comment_length,std::max(filename_length,extra_length))+1];
|
||||
istream.read(buf,filename_length);
|
||||
buf[filename_length]=0;
|
||||
filename=std::string(buf, buf + filename_length);
|
||||
istream.read(buf,extra_length);
|
||||
if(global) istream.read(buf,comment_length);
|
||||
delete [] buf;
|
||||
return true;}
|
||||
version = read_int<std::uint16_t>(istream);
|
||||
flags = read_int<std::uint16_t>(istream);
|
||||
compression_type = read_int<std::uint16_t>(istream);
|
||||
stamp_date = read_int<std::uint16_t>(istream);
|
||||
stamp_time = read_int<std::uint16_t>(istream);
|
||||
crc = read_int<std::uint32_t>(istream);
|
||||
compressed_size = read_int<std::uint32_t>(istream);
|
||||
uncompressed_size = read_int<std::uint32_t>(istream);
|
||||
|
||||
auto filename_length = read_int<std::uint16_t>(istream);
|
||||
auto extra_length = read_int<std::uint16_t>(istream);
|
||||
|
||||
std::uint16_t comment_length = 0;
|
||||
|
||||
if(global)
|
||||
{
|
||||
comment_length = read_int<std::uint16_t>(istream);
|
||||
/*std::uint16_t disk_number_start = */read_int<std::uint16_t>(istream);
|
||||
/*std::uint16_t int_file_attrib = */read_int<std::uint16_t>(istream);
|
||||
/*std::uint32_t ext_file_attrib = */read_int<std::uint32_t>(istream);
|
||||
header_offset = read_int<std::uint32_t>(istream);
|
||||
}
|
||||
|
||||
filename.resize(filename_length, '\0');
|
||||
istream.read(&filename[0], filename_length);
|
||||
|
||||
extra.resize(extra_length, 0);
|
||||
istream.read(reinterpret_cast<char *>(extra.data()), extra_length);
|
||||
|
||||
if (global)
|
||||
{
|
||||
comment.resize(comment_length, '\0');
|
||||
istream.read(&comment[0], comment_length);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Write(std::ostream& ostream,const bool global) const
|
||||
{if(global){
|
||||
Write_Primitive(ostream,(unsigned int)0x02014b50); // header sig
|
||||
Write_Primitive(ostream,(unsigned short)00);} // version made by
|
||||
else Write_Primitive(ostream,(unsigned int)0x04034b50);
|
||||
Write_Primitive(ostream,version);
|
||||
Write_Primitive(ostream,flags);
|
||||
Write_Primitive(ostream,compression_type);
|
||||
Write_Primitive(ostream,stamp_date);
|
||||
Write_Primitive(ostream,stamp_time);
|
||||
Write_Primitive(ostream,crc);
|
||||
Write_Primitive(ostream,compressed_size);
|
||||
Write_Primitive(ostream,uncompressed_size);
|
||||
Write_Primitive(ostream,(unsigned short)filename.length());
|
||||
Write_Primitive(ostream,(unsigned short)0); // extra lengthx
|
||||
write_int(ostream,(unsigned int)0x02014b50); // header sig
|
||||
write_int(ostream,(unsigned short)00);} // version made by
|
||||
else write_int(ostream,(unsigned int)0x04034b50);
|
||||
write_int(ostream,version);
|
||||
write_int(ostream,flags);
|
||||
write_int(ostream,compression_type);
|
||||
write_int(ostream,stamp_date);
|
||||
write_int(ostream,stamp_time);
|
||||
write_int(ostream,crc);
|
||||
write_int(ostream,compressed_size);
|
||||
write_int(ostream,uncompressed_size);
|
||||
write_int(ostream,(unsigned short)filename.length());
|
||||
write_int(ostream,(unsigned short)0); // extra lengthx
|
||||
if(global){
|
||||
Write_Primitive(ostream,(unsigned short)0); // filecomment
|
||||
Write_Primitive(ostream,(unsigned short)0); // disk# start
|
||||
Write_Primitive(ostream,(unsigned short)0); // internal file
|
||||
Write_Primitive(ostream,(unsigned int)0); // ext final
|
||||
Write_Primitive(ostream,(unsigned int)header_offset);} // rel offset
|
||||
for(unsigned int i=0;i<filename.length();i++) Write_Primitive(ostream,filename.c_str()[i]);}
|
||||
//#####################################################################
|
||||
write_int(ostream,(unsigned short)0); // filecomment
|
||||
write_int(ostream,(unsigned short)0); // disk# start
|
||||
write_int(ostream,(unsigned short)0); // internal file
|
||||
write_int(ostream,(unsigned int)0); // ext final
|
||||
write_int(ostream,(unsigned int)header_offset);} // rel offset
|
||||
for(unsigned int i=0;i<filename.length();i++) write_int(ostream,filename.c_str()[i]);}
|
||||
};
|
||||
|
||||
//#####################################################################
|
||||
// class ZipStreambufDecompress
|
||||
//#####################################################################
|
||||
class ZipStreambufDecompress:public std::streambuf
|
||||
{
|
||||
static const unsigned int buffer_size=512;
|
||||
|
@ -170,23 +172,23 @@ class ZipStreambufDecompress:public std::streambuf
|
|||
|
||||
z_stream strm;
|
||||
unsigned char in[buffer_size],out[buffer_size];
|
||||
ZipFileHeader header;
|
||||
zip_file_header header;
|
||||
int total_read,total_uncompressed;
|
||||
bool own_istream;
|
||||
//bool own_istream;
|
||||
bool valid;
|
||||
bool compressed_data;
|
||||
|
||||
static const unsigned short DEFLATE=8;
|
||||
static const unsigned short UNCOMPRESSED=0;
|
||||
public:
|
||||
ZipStreambufDecompress(std::istream& stream,ZipFileHeader central_header)
|
||||
:istream(stream),total_read(0),total_uncompressed(0),valid(true),header(central_header)
|
||||
ZipStreambufDecompress(std::istream& stream,zip_file_header central_header)
|
||||
:istream(stream),header(central_header),total_read(0),total_uncompressed(0),valid(true)
|
||||
{
|
||||
strm.zalloc=Z_NULL;strm.zfree=Z_NULL;strm.opaque=Z_NULL;strm.avail_in=0;strm.next_in=Z_NULL;
|
||||
setg((char*)in,(char*)in,(char*)in);
|
||||
setp(0,0);
|
||||
// skip the header
|
||||
valid=header.Read(istream,false);
|
||||
valid=header.read(istream,false);
|
||||
if(header.compression_type==DEFLATE) compressed_data=true;
|
||||
else if(header.compression_type==UNCOMPRESSED) compressed_data=false;
|
||||
else{
|
||||
|
@ -246,13 +248,8 @@ public:
|
|||
|
||||
virtual int overflow(int c=EOF)
|
||||
{assert(false);return EOF;}
|
||||
|
||||
//#####################################################################
|
||||
};
|
||||
|
||||
//#####################################################################
|
||||
// class ZipStreambufCompress
|
||||
//#####################################################################
|
||||
class ZipStreambufCompress:public std::streambuf
|
||||
{
|
||||
static const int buffer_size=512;
|
||||
|
@ -261,16 +258,15 @@ class ZipStreambufCompress:public std::streambuf
|
|||
z_stream strm;
|
||||
unsigned char in[buffer_size],out[buffer_size];
|
||||
|
||||
ZipFileHeader* header;
|
||||
unsigned int header_offset;
|
||||
zip_file_header* header;
|
||||
unsigned int uncompressed_size;
|
||||
unsigned int crc;
|
||||
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
ZipStreambufCompress(ZipFileHeader* header,std::ostream& stream)
|
||||
:ostream(stream),header(header),valid(true)
|
||||
ZipStreambufCompress(zip_file_header* central_header,std::ostream& stream)
|
||||
:ostream(stream),header(central_header),valid(true)
|
||||
{
|
||||
strm.zalloc=Z_NULL;strm.zfree=Z_NULL;strm.opaque=Z_NULL;
|
||||
int ret=deflateInit2(&strm,Z_DEFAULT_COMPRESSION,Z_DEFLATED,-MAX_WBITS,8,Z_DEFAULT_STRATEGY);
|
||||
|
@ -293,7 +289,7 @@ public:
|
|||
ostream.seekp(header->header_offset);
|
||||
header->Write(ostream,false);
|
||||
ostream.seekp(final_position);}
|
||||
else{Write_Primitive(ostream,crc);Write_Primitive(ostream,uncompressed_size);}}
|
||||
else{write_int(ostream,crc);write_int(ostream,uncompressed_size);}}
|
||||
if(!header) delete &ostream;}
|
||||
|
||||
protected:
|
||||
|
@ -329,174 +325,189 @@ protected:
|
|||
{if(c!=EOF){*pptr()=c;pbump(1);}
|
||||
if(process(false)==EOF) return EOF;
|
||||
return c;}
|
||||
|
||||
//#####################################################################
|
||||
};
|
||||
//#####################################################################
|
||||
// Class ZIP_FILE_ISTREAM
|
||||
//#####################################################################
|
||||
// Class needed because istream cannot own its streambuf
|
||||
|
||||
class ZIP_FILE_ISTREAM:public std::istream
|
||||
{
|
||||
ZipStreambufDecompress buf;
|
||||
|
||||
public:
|
||||
ZIP_FILE_ISTREAM(std::istream& istream,ZipFileHeader header)
|
||||
ZIP_FILE_ISTREAM(std::istream& istream,zip_file_header header)
|
||||
:std::istream(&buf),buf(istream,header)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ZIP_FILE_ISTREAM()
|
||||
{}
|
||||
|
||||
//#####################################################################
|
||||
{
|
||||
}
|
||||
};
|
||||
//#####################################################################
|
||||
// Class ZIP_FILE_OSTREAM
|
||||
//#####################################################################
|
||||
// Class needed because ostream cannot own its streambuf
|
||||
|
||||
class ZIP_FILE_OSTREAM:public std::ostream
|
||||
{
|
||||
ZipStreambufCompress buf;
|
||||
|
||||
public:
|
||||
ZIP_FILE_OSTREAM(ZipFileHeader* header,std::ostream& ostream)
|
||||
ZIP_FILE_OSTREAM(zip_file_header* header,std::ostream& ostream)
|
||||
:std::ostream(&buf),buf(header,ostream)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ZIP_FILE_OSTREAM()
|
||||
{}
|
||||
|
||||
//#####################################################################
|
||||
{
|
||||
}
|
||||
};
|
||||
//#####################################################################
|
||||
// Function ZipFileWriter
|
||||
//#####################################################################
|
||||
ZipFileWriter::
|
||||
ZipFileWriter(std::ostream& stream) : ostream(stream)
|
||||
|
||||
ZipFileWriter::ZipFileWriter(std::ostream& stream) : target_stream_(stream)
|
||||
{
|
||||
if(!ostream) throw std::runtime_error("ZIP: Invalid file handle");
|
||||
if(!target_stream_) throw std::runtime_error("ZIP: Invalid file handle");
|
||||
}
|
||||
//#####################################################################
|
||||
// Function ZipFileWriter
|
||||
//#####################################################################
|
||||
ZipFileWriter::
|
||||
~ZipFileWriter()
|
||||
|
||||
ZipFileWriter::~ZipFileWriter()
|
||||
{
|
||||
// Write all file headers
|
||||
std::ios::streampos final_position=ostream.tellp();
|
||||
for(unsigned int i=0;i<files.size();i++){files[i]->Write(ostream,true);delete files[i];}
|
||||
std::ios::streampos central_end=ostream.tellp();
|
||||
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_Primitive(ostream,(unsigned int)0x06054b50); // end of central
|
||||
Write_Primitive(ostream,(unsigned short)0); // this disk number
|
||||
Write_Primitive(ostream,(unsigned short)0); // this disk number
|
||||
Write_Primitive(ostream,(unsigned short)files.size()); // one entry in center in this disk
|
||||
Write_Primitive(ostream,(unsigned short)files.size()); // one entry in center
|
||||
Write_Primitive(ostream,(unsigned int)(central_end-final_position)); // size of header
|
||||
Write_Primitive(ostream,(unsigned int)final_position); // offset to header
|
||||
Write_Primitive(ostream,(unsigned short)0); // zip comment
|
||||
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
|
||||
}
|
||||
//#####################################################################
|
||||
// Function ZipFileWriter
|
||||
//#####################################################################
|
||||
std::ostream* ZipFileWriter::
|
||||
Add_File(const std::string& filename,const bool binary)
|
||||
|
||||
std::ostream* ZipFileWriter::open(const std::string& filename)
|
||||
{
|
||||
files.push_back(new ZipFileHeader(filename));
|
||||
return new ZIP_FILE_OSTREAM(files.back(),ostream);
|
||||
zip_file_header header;
|
||||
header.filename = filename;
|
||||
file_headers_.push_back(header);
|
||||
return new ZIP_FILE_OSTREAM(&file_headers_.back(),target_stream_);
|
||||
}
|
||||
//#####################################################################
|
||||
// Function ZipFileReader
|
||||
//#####################################################################
|
||||
ZipFileReader::
|
||||
ZipFileReader(std::istream &stream) : istream(stream)
|
||||
|
||||
ZipFileReader::ZipFileReader(std::istream &stream) : source_stream_(stream)
|
||||
{
|
||||
if(!istream) throw std::runtime_error("ZIP: Invalid file handle");
|
||||
Find_And_Read_Central_Header();
|
||||
if(!stream)
|
||||
{
|
||||
throw std::runtime_error("ZIP: Invalid file handle");
|
||||
}
|
||||
|
||||
read_central_header();
|
||||
}
|
||||
//#####################################################################
|
||||
// Function ZipFileReader
|
||||
//#####################################################################
|
||||
ZipFileReader::
|
||||
~ZipFileReader()
|
||||
|
||||
ZipFileReader::~ZipFileReader()
|
||||
{
|
||||
std::map<std::string,ZipFileHeader*>::iterator i=filename_to_header.begin();
|
||||
for(;i!=filename_to_header.end();++i)
|
||||
delete i->second;
|
||||
}
|
||||
//#####################################################################
|
||||
// Function Find_And_Read_Central_Header
|
||||
//#####################################################################
|
||||
bool ZipFileReader::
|
||||
Find_And_Read_Central_Header()
|
||||
|
||||
bool ZipFileReader::read_central_header()
|
||||
{
|
||||
// Find the header
|
||||
// NOTE: this assumes the zip file header is the last thing written to file...
|
||||
istream.seekg(0,std::ios_base::end);
|
||||
std::ios::streampos end_position=istream.tellg();
|
||||
unsigned int max_comment_size=0xffff; // max size of header
|
||||
unsigned int read_size_before_comment=22;
|
||||
source_stream_.seekg(0,std::ios_base::end);
|
||||
std::ios::streampos end_position=source_stream_.tellg();
|
||||
|
||||
auto max_comment_size = std::uint32_t(0xffff); // max size of header
|
||||
auto read_size_before_comment = std::uint32_t(22);
|
||||
|
||||
std::ios::streamoff read_start=max_comment_size+read_size_before_comment;
|
||||
|
||||
if(read_start>end_position) read_start=end_position;
|
||||
istream.seekg(end_position-read_start);
|
||||
char *buf=new char[read_start];
|
||||
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;}
|
||||
istream.read(buf,read_start);
|
||||
int found=-1;
|
||||
for(unsigned int i=0;i<read_start-3;i++){
|
||||
if(buf[i]==0x50 && buf[i+1]==0x4b && buf[i+2]==0x05 && buf[i+3]==0x06){found=i;break;}}
|
||||
delete [] buf;
|
||||
if(found==-1){std::cerr<<"ZIP: Failed to find zip header"<<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)
|
||||
{
|
||||
if(buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06)
|
||||
{
|
||||
found_header = true;
|
||||
header_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found_header)
|
||||
{
|
||||
std::cerr<<"ZIP: Failed to find zip header"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// seek to end of central header and read
|
||||
istream.seekg(end_position-(read_start-found));
|
||||
unsigned int word;
|
||||
unsigned short disk_number1,disk_number2,num_files,num_files_this_disk;
|
||||
Read_Primitive(istream,word); // end of central
|
||||
Read_Primitive(istream,disk_number1); // this disk number
|
||||
Read_Primitive(istream,disk_number2); // this disk number
|
||||
if(disk_number1!=disk_number2 || disk_number1!=0){
|
||||
std::cerr<<"ZIP: multiple disk zip files are not supported"<<std::endl;return false;}
|
||||
Read_Primitive(istream,num_files); // one entry in center in this disk
|
||||
Read_Primitive(istream,num_files_this_disk); // one entry in center
|
||||
if(num_files != num_files_this_disk){
|
||||
std::cerr<<"ZIP: multi disk zip files are not supported"<<std::endl;return false;}
|
||||
unsigned int size_of_header,header_offset;
|
||||
Read_Primitive(istream,size_of_header); // size of header
|
||||
Read_Primitive(istream,header_offset); // offset to header
|
||||
source_stream_.seekg(end_position - (read_start - static_cast<std::ptrdiff_t>(header_index)));
|
||||
|
||||
/*auto word = */read_int<std::uint32_t>(source_stream_);
|
||||
auto disk_number1 = read_int<std::uint16_t>(source_stream_);
|
||||
auto disk_number2 = read_int<std::uint16_t>(source_stream_);
|
||||
|
||||
if(disk_number1 != disk_number2 || disk_number1 != 0)
|
||||
{
|
||||
std::cerr<<"ZIP: multiple disk zip files are not supported"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto num_files = read_int<std::uint16_t>(source_stream_); // one entry in center in this disk
|
||||
auto num_files_this_disk = read_int<std::uint16_t>(source_stream_); // one entry in center
|
||||
|
||||
if(num_files != num_files_this_disk)
|
||||
{
|
||||
std::cerr<<"ZIP: multi disk zip files are not supported"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*auto size_of_header = */read_int<std::uint32_t>(source_stream_); // size of header
|
||||
auto header_offset = read_int<std::uint32_t>(source_stream_); // offset to header
|
||||
|
||||
// go to header and read all file headers
|
||||
istream.seekg(header_offset);
|
||||
for(int i=0;i<num_files;i++){
|
||||
ZipFileHeader* header=new ZipFileHeader;
|
||||
bool valid=header->Read(istream,true);
|
||||
if(valid) filename_to_header[header->filename]=header;}
|
||||
source_stream_.seekg(header_offset);
|
||||
|
||||
for (std::uint16_t i = 0; i < num_files; ++i)
|
||||
{
|
||||
zip_file_header header;
|
||||
|
||||
if (header.read(source_stream_, true))
|
||||
{
|
||||
file_headers_[header.filename] = header;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//#####################################################################
|
||||
// Function Get_File
|
||||
//#####################################################################
|
||||
std::istream* ZipFileReader::Get_File(const std::string& filename,const bool binary)
|
||||
|
||||
std::istream &ZipFileReader::open(const std::string &filename)
|
||||
{
|
||||
std::map<std::string,ZipFileHeader*>::iterator i=filename_to_header.find(filename);
|
||||
if(i!=filename_to_header.end()){
|
||||
ZipFileHeader* header=i->second;
|
||||
istream.seekg((*header).header_offset);return new ZIP_FILE_ISTREAM(istream,*header);
|
||||
if (!has_file(filename))
|
||||
{
|
||||
throw "not found";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//#####################################################################
|
||||
// Function Get_File_List
|
||||
//#####################################################################
|
||||
void ZipFileReader::Get_File_List(std::vector<std::string>& filenames) const
|
||||
{
|
||||
filenames.clear();
|
||||
std::map<std::string,ZipFileHeader*>::const_iterator i=filename_to_header.begin();
|
||||
for(;i!=filename_to_header.end();++i)
|
||||
filenames.push_back(i->first);
|
||||
}
|
||||
//#####################################################################
|
||||
// Function Has_File
|
||||
//#####################################################################
|
||||
bool ZipFileReader::Has_File(const std::string &filename) const
|
||||
{
|
||||
return filename_to_header.find(filename) != filename_to_header.end();
|
||||
|
||||
auto header = file_headers_.at(filename);
|
||||
source_stream_.seekg(header.header_offset);
|
||||
read_stream_.reset(new ZIP_FILE_ISTREAM(source_stream_, header));
|
||||
|
||||
return *read_stream_;
|
||||
}
|
||||
|
||||
} // namespace Partio
|
||||
std::vector<std::string> ZipFileReader::files() const
|
||||
{
|
||||
std::vector<std::string> filenames;
|
||||
std::transform(file_headers_.begin(), file_headers_.end(), std::back_inserter(filenames),
|
||||
[](const std::pair<std::string, zip_file_header> &h) { return h.first; });
|
||||
return filenames;
|
||||
}
|
||||
|
||||
bool ZipFileReader::has_file(const std::string &filename) const
|
||||
{
|
||||
return file_headers_.count(filename) != 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -33,56 +33,46 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
#ifndef __ZIP__
|
||||
#define __ZIP__
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Partio{
|
||||
struct ZipFileHeader;
|
||||
//#####################################################################
|
||||
// Functions Gzip_Out/Gzip_In - Create streams that read/write .gz
|
||||
//#####################################################################
|
||||
std::istream* Gzip_In(const std::string& filename,std::ios::openmode mode);
|
||||
std::ostream* Gzip_Out(const std::string& filename,std::ios::openmode mode);
|
||||
//#####################################################################
|
||||
// Class ZipFileWriter
|
||||
//#####################################################################
|
||||
namespace xlnt {
|
||||
namespace detail {
|
||||
|
||||
struct zip_file_header;
|
||||
|
||||
class ZipFileWriter
|
||||
{
|
||||
std::ostream &ostream;
|
||||
std::vector<ZipFileHeader*> files;
|
||||
public:
|
||||
|
||||
//#####################################################################
|
||||
ZipFileWriter(std::ostream &filename);
|
||||
virtual ~ZipFileWriter();
|
||||
std::ostream* Add_File(const std::string& filename,const bool binary=true);
|
||||
//#####################################################################
|
||||
std::ostream* open(const std::string& filename);
|
||||
|
||||
private:
|
||||
std::ostream &target_stream_;
|
||||
std::vector<zip_file_header> file_headers_;
|
||||
};
|
||||
|
||||
//#####################################################################
|
||||
// Class ZipFileReader
|
||||
//#####################################################################
|
||||
class ZipFileReader
|
||||
{
|
||||
std::istream &istream;
|
||||
public:
|
||||
std::map<std::string,ZipFileHeader*> filename_to_header;
|
||||
|
||||
//#####################################################################
|
||||
ZipFileReader(std::istream &stream);
|
||||
virtual ~ZipFileReader();
|
||||
std::istream* Get_File(const std::string& filename,const bool binary=true);
|
||||
void Get_File_List(std::vector<std::string>& filenames) const;
|
||||
bool Has_File(const std::string &filename) const;
|
||||
std::istream &open(const std::string &filename);
|
||||
std::vector<std::string> files() const;
|
||||
bool has_file(const std::string &filename) const;
|
||||
|
||||
private:
|
||||
bool Find_And_Read_Central_Header();
|
||||
//#####################################################################
|
||||
bool read_central_header();
|
||||
|
||||
std::unordered_map<std::string, zip_file_header> file_headers_;
|
||||
std::istream &source_stream_;
|
||||
std::unique_ptr<std::istream> read_stream_;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -92,18 +92,87 @@ optional<int> alignment::rotation() const
|
|||
return text_rotation_;
|
||||
}
|
||||
|
||||
std::string alignment::to_hash_string() const
|
||||
bool operator==(const alignment &left, const alignment &right)
|
||||
{
|
||||
std::string hash_string;
|
||||
if (left.horizontal().is_set() != right.horizontal().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_string.append(wrap_text_ ? "1" : "0");
|
||||
hash_string.append(shrink_to_fit_ ? "1" : "0");
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(horizontal_)));
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(vertical_)));
|
||||
hash_string.append(std::to_string(text_rotation_));
|
||||
hash_string.append(std::to_string(indent_));
|
||||
if (left.horizontal().is_set())
|
||||
{
|
||||
if (left.horizontal().get() != right.horizontal().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return hash_string;
|
||||
if (left.indent().is_set() != right.indent().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.indent().is_set())
|
||||
{
|
||||
if (left.indent().get() != right.indent().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.rotation().is_set() != right.rotation().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.rotation().is_set())
|
||||
{
|
||||
if (left.rotation().get() != right.rotation().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.shrink().is_set() != right.shrink().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.shrink().is_set())
|
||||
{
|
||||
if (left.shrink().get() != right.shrink().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.vertical().is_set() != right.vertical().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.vertical().is_set())
|
||||
{
|
||||
if (left.vertical().get() != right.vertical().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.wrap().is_set() != right.wrap().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.wrap().is_set())
|
||||
{
|
||||
if (left.wrap().get() != right.wrap().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -49,6 +49,38 @@ border::border_property &border::border_property::style(border_style s)
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const border::border_property &left,
|
||||
const border::border_property &right)
|
||||
{
|
||||
if (left.style().is_set() != right.style().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.style().is_set())
|
||||
{
|
||||
if (left.style().get() != right.style().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.color().is_set() != right.color().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.color().is_set())
|
||||
{
|
||||
if (left.color().get() != right.color().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
border::border()
|
||||
{
|
||||
}
|
||||
|
@ -112,45 +144,25 @@ optional<diagonal_direction> border::diagonal() const
|
|||
return diagonal_direction_;
|
||||
}
|
||||
|
||||
std::string border::to_hash_string() const
|
||||
bool operator==(const border &left, const border &right)
|
||||
{
|
||||
std::string hash_string;
|
||||
|
||||
for (const auto &side_type : all_sides())
|
||||
for (auto side : border::all_sides())
|
||||
{
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(side_type)));
|
||||
|
||||
if (side(side_type))
|
||||
if (left.side(side).is_set() != right.side(side).is_set())
|
||||
{
|
||||
const auto side_properties = *side(side_type);
|
||||
|
||||
if (side_properties.style())
|
||||
{
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(*side_properties.style())));
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_string.push_back(' ');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (side_properties.color())
|
||||
if (left.side(side).is_set())
|
||||
{
|
||||
hash_string.append(std::to_string(std::hash<xlnt::hashable>()(*side_properties.color())));
|
||||
}
|
||||
else
|
||||
if (left.side(side).get() != right.side(side).get())
|
||||
{
|
||||
hash_string.push_back(' ');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_string.push_back(' ');
|
||||
}
|
||||
|
||||
hash_string.push_back(' ');
|
||||
}
|
||||
|
||||
return hash_string;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -206,32 +206,6 @@ void color::set_tint(double tint)
|
|||
tint_ = tint;
|
||||
}
|
||||
|
||||
std::string color::to_hash_string() const
|
||||
{
|
||||
std::string hash_string = "color";
|
||||
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(type_)));
|
||||
hash_string.append(std::to_string(static_cast<double>(tint_)));
|
||||
|
||||
if (type_ == type::indexed)
|
||||
{
|
||||
hash_string.append("indexed");
|
||||
hash_string.append(std::to_string(indexed_.get_index()));
|
||||
}
|
||||
else if (type_ == type::theme)
|
||||
{
|
||||
hash_string.append("theme");
|
||||
hash_string.append(std::to_string(theme_.get_index()));
|
||||
}
|
||||
else if (type_ == type::rgb)
|
||||
{
|
||||
hash_string.append("rgb");
|
||||
hash_string.append(rgb_.get_hex_string());
|
||||
}
|
||||
|
||||
return hash_string;
|
||||
}
|
||||
|
||||
void color::assert_type(type t) const
|
||||
{
|
||||
if (t != type_)
|
||||
|
|
|
@ -72,25 +72,40 @@ pattern_fill &pattern_fill::background(const color &new_background)
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::string pattern_fill::to_hash_string() const
|
||||
bool operator==(const pattern_fill &left, const pattern_fill &right)
|
||||
{
|
||||
std::string hash_string = "pattern_fill";
|
||||
|
||||
hash_string.append(background_ ? "1" : "0");
|
||||
|
||||
if (background_)
|
||||
if (left.background().is_set() != right.background().is_set())
|
||||
{
|
||||
hash_string.append(std::to_string(background_->hash()));
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_string.append(background_ ? "1" : "0");
|
||||
|
||||
if (background_)
|
||||
if (left.background().is_set())
|
||||
{
|
||||
hash_string.append(std::to_string(background_->hash()));
|
||||
if (left.background().get() != right.background().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return hash_string;
|
||||
if (left.foreground().is_set() != right.foreground().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.foreground().is_set())
|
||||
{
|
||||
if (left.foreground().get() != right.foreground().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.type() != right.type())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// gradient_fill
|
||||
|
@ -166,21 +181,6 @@ gradient_fill &gradient_fill::bottom(double value)
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::string gradient_fill::to_hash_string() const
|
||||
{
|
||||
std::string hash_string = "gradient_fill";
|
||||
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(type_)));
|
||||
hash_string.append(std::to_string(stops_.size()));
|
||||
hash_string.append(std::to_string(degree_));
|
||||
hash_string.append(std::to_string(left_));
|
||||
hash_string.append(std::to_string(right_));
|
||||
hash_string.append(std::to_string(top_));
|
||||
hash_string.append(std::to_string(bottom_));
|
||||
|
||||
return hash_string;
|
||||
}
|
||||
|
||||
gradient_fill &gradient_fill::add_stop(double position, color stop_color)
|
||||
{
|
||||
stops_[position] = stop_color;
|
||||
|
@ -198,6 +198,46 @@ std::unordered_map<double, color> gradient_fill::stops() const
|
|||
return stops_;
|
||||
}
|
||||
|
||||
bool operator==(const gradient_fill &left, const gradient_fill &right)
|
||||
{
|
||||
if (left.type() != right.type())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.degree() != right.degree())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.bottom() != right.bottom())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.right() != right.right())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.top() != right.top())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.left() != right.left())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.stops() != right.stops())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// fill
|
||||
|
||||
fill fill::solid(const color &fill_color)
|
||||
|
@ -249,27 +289,19 @@ pattern_fill fill::pattern_fill() const
|
|||
return pattern_;
|
||||
}
|
||||
|
||||
std::string fill::to_hash_string() const
|
||||
bool operator==(const fill &left, const fill &right)
|
||||
{
|
||||
std::string hash_string = "fill";
|
||||
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(type_)));
|
||||
|
||||
switch (type_)
|
||||
if (left.type() != right.type())
|
||||
{
|
||||
case fill_type::pattern:
|
||||
hash_string.append(std::to_string(pattern_.hash()));
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
case fill_type::gradient:
|
||||
hash_string.append(std::to_string(gradient_.hash()));
|
||||
break;
|
||||
if (left.type() == fill_type::gradient)
|
||||
{
|
||||
return left.gradient_fill() == right.gradient_fill();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch (type_)
|
||||
|
||||
return hash_string;
|
||||
return left.pattern_fill() == right.pattern_fill();
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -153,22 +153,83 @@ optional<std::string> font::scheme() const
|
|||
return scheme_;
|
||||
}
|
||||
|
||||
std::string font::to_hash_string() const
|
||||
bool operator==(const font &left, const font &right)
|
||||
{
|
||||
std::string hash_string = "font";
|
||||
if (left.bold() != right.bold())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hash_string.append(std::to_string(bold_));
|
||||
hash_string.append(std::to_string(italic_));
|
||||
hash_string.append(std::to_string(superscript_));
|
||||
hash_string.append(std::to_string(subscript_));
|
||||
hash_string.append(std::to_string(strikethrough_));
|
||||
hash_string.append(name_);
|
||||
hash_string.append(std::to_string(size_));
|
||||
hash_string.append(std::to_string(static_cast<std::size_t>(underline_)));
|
||||
hash_string.append(family_ ? std::to_string(*family_) : "");
|
||||
hash_string.append(scheme_ ? *scheme_ : "");
|
||||
if (left.color().is_set() != right.color().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return hash_string;
|
||||
if (left.color().is_set())
|
||||
{
|
||||
if (left.color().get() != right.color().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.family().is_set() != right.family().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.family().is_set())
|
||||
{
|
||||
if (left.family().get() != right.family().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.italic() != right.italic())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.name() != right.name())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.scheme().is_set() != right.scheme().is_set())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.scheme().is_set())
|
||||
{
|
||||
if (left.scheme().get() != right.scheme().get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (left.size() != right.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.strikethrough() != right.strikethrough())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.superscript() != right.superscript())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left.underline() != right.underline())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -273,17 +273,6 @@ std::string number_format::get_format_string() const
|
|||
return format_string_;
|
||||
}
|
||||
|
||||
std::string number_format::to_hash_string() const
|
||||
{
|
||||
std::string hash_string("number_format");
|
||||
hash_string.append(format_string_);
|
||||
hash_string.append("|||");
|
||||
hash_string.append(std::to_string(id_));
|
||||
|
||||
return hash_string;
|
||||
}
|
||||
|
||||
|
||||
void number_format::set_format_string(const std::string &format_string)
|
||||
{
|
||||
format_string_ = format_string;
|
||||
|
@ -364,4 +353,11 @@ std::string number_format::format(long double number, calendar base_date) const
|
|||
return detail::number_formatter(format_string_, base_date).format_number(number);
|
||||
}
|
||||
|
||||
bool operator==(const number_format &left, const number_format &right)
|
||||
{
|
||||
return left.id_set_ == right.id_set_
|
||||
&& left.id_ == right.id_
|
||||
&& left.format_string_ == right.format_string_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -52,14 +52,9 @@ protection &protection::hidden(bool hidden)
|
|||
return *this;
|
||||
}
|
||||
|
||||
std::string protection::to_hash_string() const
|
||||
bool operator==(const protection &left, const protection &right)
|
||||
{
|
||||
std::string hash_string = "protection";
|
||||
|
||||
hash_string.append(locked_ ? "1" : "0");
|
||||
hash_string.append(hidden_ ? "1" : "0");
|
||||
|
||||
return hash_string;
|
||||
return left.locked_ == right.locked_ && left.hidden_ == right.hidden_;
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -43,14 +43,14 @@ public:
|
|||
TS_ASSERT(const_fill.pattern_fill().background());
|
||||
}
|
||||
|
||||
void test_hash()
|
||||
void test_comparison()
|
||||
{
|
||||
xlnt::fill pattern_fill = xlnt::pattern_fill().type(xlnt::pattern_fill_type::solid);
|
||||
xlnt::fill gradient_fill_linear = xlnt::gradient_fill().type(xlnt::gradient_fill_type::linear);
|
||||
xlnt::fill gradient_fill_path = xlnt::gradient_fill().type(xlnt::gradient_fill_type::path);
|
||||
|
||||
TS_ASSERT_DIFFERS(pattern_fill.hash(), gradient_fill_linear.hash());
|
||||
TS_ASSERT_DIFFERS(gradient_fill_linear.hash(), gradient_fill_path.hash());
|
||||
TS_ASSERT_DIFFERS(gradient_fill_path.hash(), pattern_fill.hash());
|
||||
TS_ASSERT_DIFFERS(pattern_fill, gradient_fill_linear);
|
||||
TS_ASSERT_DIFFERS(gradient_fill_linear, gradient_fill_path);
|
||||
TS_ASSERT_DIFFERS(gradient_fill_path, pattern_fill);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -32,6 +32,10 @@ exception::exception(const std::string &message)
|
|||
set_message(message);
|
||||
}
|
||||
|
||||
exception::~exception()
|
||||
{
|
||||
}
|
||||
|
||||
void exception::set_message(const std::string &message)
|
||||
{
|
||||
message_ = message;
|
||||
|
@ -47,6 +51,10 @@ invalid_column_string_index::invalid_column_string_index()
|
|||
{
|
||||
}
|
||||
|
||||
invalid_column_string_index::~invalid_column_string_index()
|
||||
{
|
||||
}
|
||||
|
||||
invalid_data_type::invalid_data_type()
|
||||
: exception("data type error")
|
||||
{
|
||||
|
@ -68,6 +76,10 @@ invalid_cell_reference::invalid_cell_reference(const std::string &coord_string)
|
|||
{
|
||||
}
|
||||
|
||||
invalid_cell_reference::~invalid_cell_reference()
|
||||
{
|
||||
}
|
||||
|
||||
illegal_character::illegal_character(char c)
|
||||
: exception(std::string("illegal character: (") + std::to_string(static_cast<unsigned char>(c)) + ")")
|
||||
{
|
||||
|
@ -83,6 +95,10 @@ invalid_attribute::invalid_attribute()
|
|||
{
|
||||
}
|
||||
|
||||
invalid_attribute::~invalid_attribute()
|
||||
{
|
||||
}
|
||||
|
||||
key_not_found::key_not_found()
|
||||
: exception("key not found in container")
|
||||
{
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) 2014-2016 Thomas Fussell
|
||||
// Copyright (c) 2010-2015 openpyxl
|
||||
//
|
||||
// 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
|
||||
#include <xlnt/utils/hashable.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
std::size_t hashable::hash() const
|
||||
{
|
||||
static std::hash<std::string> hasher;
|
||||
return hasher.operator()(to_hash_string());
|
||||
}
|
||||
|
||||
bool hashable::operator==(const xlnt::hashable &other) const
|
||||
{
|
||||
return hash() == other.hash();
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
|
@ -20,6 +20,12 @@
|
|||
//
|
||||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#include <utf8.h>
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#include <xlnt/utils/utf8string.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
|
|
@ -70,6 +70,10 @@ public:
|
|||
#ifdef WIN32
|
||||
xlnt::workbook wb;
|
||||
wb.load(L"data\\19_unicode_Λ.xlsx");
|
||||
#else
|
||||
xlnt::workbook wb;
|
||||
wb.load("data/19_unicode_Λ.xlsx");
|
||||
#endif
|
||||
TS_ASSERT_EQUALS(wb.get_active_sheet().get_cell("A1").get_value<std::string>(), "unicode!");
|
||||
}
|
||||
};
|
||||
|
|
|
@ -637,7 +637,7 @@ std::size_t workbook::get_index(worksheet ws)
|
|||
throw invalid_parameter();
|
||||
}
|
||||
|
||||
return std::distance(begin(), match);
|
||||
return static_cast<std::size_t>(std::distance(begin(), match));
|
||||
}
|
||||
|
||||
void workbook::create_named_range(const std::string &name, worksheet range_owner, const std::string &reference_string)
|
||||
|
|
|
@ -521,11 +521,11 @@ public:
|
|||
xlnt::workbook wb;
|
||||
|
||||
auto ws = wb.get_active_sheet();
|
||||
ws.add_print_title(3);
|
||||
ws.set_print_title_rows(3);
|
||||
TS_ASSERT_EQUALS(ws.get_print_titles(), "Sheet1!1:3");
|
||||
|
||||
auto ws2 = wb.create_sheet();
|
||||
ws2.add_print_title(4, "cols");
|
||||
ws2.set_print_title_cols(4);
|
||||
TS_ASSERT_EQUALS(ws2.get_print_titles(), "Sheet2!A:D");
|
||||
}
|
||||
|
||||
|
@ -534,17 +534,17 @@ public:
|
|||
xlnt::workbook wb;
|
||||
|
||||
auto ws = wb.get_active_sheet();
|
||||
ws.set_print_title_rows("1:4");
|
||||
ws.set_print_title_rows(4);
|
||||
TS_ASSERT_EQUALS(ws.get_print_titles(), "Sheet1!1:4");
|
||||
|
||||
auto ws2 = wb.create_sheet();
|
||||
ws2.set_print_title_cols("A:F");
|
||||
ws2.set_print_title_cols("F");
|
||||
TS_ASSERT_EQUALS(ws2.get_print_titles(), "Sheet2!A:F");
|
||||
|
||||
auto ws3 = wb.create_sheet();
|
||||
ws3.set_print_title_rows("1:2");
|
||||
ws3.set_print_title_cols("C:D");
|
||||
TS_ASSERT_EQUALS(ws3.get_print_titles(), "Sheet3!1:2,Sheet3!C:D");
|
||||
ws3.set_print_title_rows(2, 3);
|
||||
ws3.set_print_title_cols("C", "D");
|
||||
TS_ASSERT_EQUALS(ws3.get_print_titles(), "Sheet3!2:3,Sheet3!C:D");
|
||||
}
|
||||
|
||||
void test_print_area()
|
||||
|
|
|
@ -624,7 +624,7 @@ void worksheet::append(const std::unordered_map<int, std::string> &cells)
|
|||
|
||||
for (auto cell : cells)
|
||||
{
|
||||
get_cell(cell_reference(static_cast<column_t>(cell.first), row)).set_value(cell.second);
|
||||
get_cell(cell_reference(static_cast<column_t::index_t>(cell.first), row)).set_value(cell.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -985,31 +985,24 @@ range worksheet::iter_cells(bool skip_null)
|
|||
return range(*this, calculate_dimension(), major_order::row, skip_null);
|
||||
}
|
||||
|
||||
void worksheet::add_print_title(int i)
|
||||
void worksheet::set_print_title_rows(row_t last_row)
|
||||
{
|
||||
add_print_title(i, "rows");
|
||||
set_print_title_rows(1, last_row);
|
||||
}
|
||||
|
||||
void worksheet::add_print_title(int i, const std::string &rows_or_cols)
|
||||
void worksheet::set_print_title_rows(row_t first_row, row_t last_row)
|
||||
{
|
||||
if(rows_or_cols == "cols")
|
||||
{
|
||||
set_print_title_cols("A:" + column_t::column_string_from_index(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
set_print_title_rows("1:" + std::to_string(i));
|
||||
}
|
||||
d_->print_title_rows_ = std::to_string(first_row) + ":" + std::to_string(last_row);
|
||||
}
|
||||
|
||||
void worksheet::set_print_title_rows(const std::string &rows)
|
||||
void worksheet::set_print_title_cols(column_t last_column)
|
||||
{
|
||||
d_->print_title_rows_ = rows;
|
||||
set_print_title_cols(1, last_column);
|
||||
}
|
||||
|
||||
void worksheet::set_print_title_cols(const std::string &cols)
|
||||
void worksheet::set_print_title_cols(column_t first_column, column_t last_column)
|
||||
{
|
||||
d_->print_title_cols_ = cols;
|
||||
d_->print_title_cols_ = first_column.column_string() + ":" + last_column.column_string();
|
||||
}
|
||||
|
||||
std::string worksheet::get_print_titles() const
|
||||
|
|
|
@ -26,15 +26,21 @@ file(GLOB UTILS_TESTS ${LIBRARY_SOURCE_DIR}/utils/tests/test_*.hpp)
|
|||
file(GLOB WORKBOOK_TESTS ${LIBRARY_SOURCE_DIR}/workbook/tests/test_*.hpp)
|
||||
file(GLOB WORKSHEET_TESTS ${LIBRARY_SOURCE_DIR}/worksheet/tests/test_*.hpp)
|
||||
|
||||
set(ZIP ${LIBRARY_SOURCE_DIR}/detail/zip.cpp)
|
||||
set(XLNT_ZIP
|
||||
${LIBRARY_SOURCE_DIR}/detail/zip.cpp
|
||||
${LIBRARY_SOURCE_DIR}/detail/zip.hpp)
|
||||
|
||||
set(TESTS ${CELL_TESTS} ${CHARTS_TESTS} ${CHARTSHEET_TESTS} ${DRAWING_TESTS}
|
||||
${FORMULA_TESTS} ${PACKAGING_TESTS} ${STYLES_TESTS} ${UTILS_TESTS}
|
||||
${WORKBOOK_TESTS} ${WORKSHEET_TESTS})
|
||||
set(PUGIXML ${THIRD_PARTY_DIR}/pugixml/src/pugixml.cpp)
|
||||
|
||||
file(GLOB TEST_HELPERS_HEADERS ${XLNT_TESTS_DIR}/helpers/*.hpp)
|
||||
file(GLOB TEST_HELPERS_SOURCES ${XLNT_TESTS_DIR}/helpers/*.cpp)
|
||||
set(PUGIXML
|
||||
${THIRD_PARTY_DIR}/pugixml/src/pugixml.cpp
|
||||
${THIRD_PARTY_DIR}/pugixml/src/pugixml.hpp
|
||||
${THIRD_PARTY_DIR}/pugixml/src/pugiconfig.hpp)
|
||||
|
||||
file(GLOB TEST_HELPERS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.hpp)
|
||||
file(GLOB TEST_HELPERS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/helpers/*.cpp)
|
||||
|
||||
SET(TEST_HELPERS ${TEST_HELPERS_HEADERS} ${TEST_HELPERS_SOURCES})
|
||||
|
||||
|
@ -42,9 +48,11 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tests")
|
|||
set(RUNNER "${CMAKE_CURRENT_BINARY_DIR}/runner-autogen.cpp")
|
||||
set_source_files_properties(${RUNNER} PROPERTIES GENERATED TRUE)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${TEST_HELPERS} ${TESTS} ${RUNNER} ${PUGIXML} $<TARGET_OBJECTS:xlnt.third-party> ${ZIP})
|
||||
add_executable(${PROJECT_NAME} ${TEST_HELPERS} ${TESTS} ${RUNNER} ${PUGIXML} $<TARGET_OBJECTS:xlnt.third-party> ${XLNT_ZIP})
|
||||
|
||||
source_group(helpers FILES ${TEST_HELPERS})
|
||||
source_group(xlnt\\detail FILES ${XLNT_ZIP})
|
||||
source_group(third-party\\pugixml FILES ${PUGIXML})
|
||||
source_group(tests\\cell FILES ${CELL_TESTS})
|
||||
source_group(tests\\charts FILES ${CHARTS_TESTS})
|
||||
source_group(tests\\chartsheet FILES ${CHARTSHEET_TESTS})
|
||||
|
|
Binary file not shown.
|
@ -276,7 +276,7 @@ public:
|
|||
std::vector<std::uint8_t> bytes;
|
||||
wb.save(bytes);
|
||||
std::istringstream file_stream(std::string(bytes.begin(), bytes.end()));
|
||||
Partio::ZipFileReader archive(file_stream);
|
||||
xlnt::detail::ZipFileReader archive(file_stream);
|
||||
|
||||
return string_matches_archive_member(expected, archive, part, content_type);
|
||||
}
|
||||
|
@ -287,33 +287,32 @@ public:
|
|||
std::vector<std::uint8_t> bytes;
|
||||
wb.save(bytes);
|
||||
std::istringstream file_stream(std::string(bytes.begin(), bytes.end()));
|
||||
Partio::ZipFileReader archive(file_stream);
|
||||
xlnt::detail::ZipFileReader archive(file_stream);
|
||||
|
||||
return file_matches_archive_member(expected, archive, part, content_type);
|
||||
}
|
||||
|
||||
static bool string_matches_archive_member(const std::string &expected,
|
||||
Partio::ZipFileReader &archive,
|
||||
xlnt::detail::ZipFileReader &archive,
|
||||
const xlnt::path &member,
|
||||
const std::string &content_type)
|
||||
{
|
||||
auto stream = archive.Get_File(member.string(), true);
|
||||
std::string contents((std::istreambuf_iterator<char>(*stream)), (std::istreambuf_iterator<char>()));
|
||||
delete stream;
|
||||
auto &stream = archive.open(member.string());
|
||||
std::string contents((std::istreambuf_iterator<char>(stream)), (std::istreambuf_iterator<char>()));
|
||||
return compare_files(expected, contents, content_type);
|
||||
}
|
||||
|
||||
static bool file_matches_archive_member(const xlnt::path &file,
|
||||
Partio::ZipFileReader &archive,
|
||||
xlnt::detail::ZipFileReader &archive,
|
||||
const xlnt::path &member,
|
||||
const std::string &content_type)
|
||||
{
|
||||
if (!archive.Has_File(member.string())) return false;
|
||||
if (!archive.has_file(member.string())) return false;
|
||||
std::vector<std::uint8_t> member_data;
|
||||
xlnt::detail::vector_ostreambuf member_data_buffer(member_data);
|
||||
std::ostream member_data_stream(&member_data_buffer);
|
||||
std::unique_ptr<std::istream> member_stream(archive.Get_File(member.string(), true));
|
||||
member_data_stream << member_stream->rdbuf();
|
||||
auto &member_stream = archive.open(member.string());
|
||||
member_data_stream << member_stream.rdbuf();
|
||||
std::string contents(member_data.begin(), member_data.end());
|
||||
return compare_files(file.read_contents(), contents, content_type);
|
||||
}
|
||||
|
@ -337,15 +336,15 @@ public:
|
|||
{
|
||||
xlnt::detail::vector_istreambuf left_buffer(left);
|
||||
std::istream left_stream(&left_buffer);
|
||||
Partio::ZipFileReader left_archive(left_stream);
|
||||
xlnt::detail::ZipFileReader left_archive(left_stream);
|
||||
|
||||
const auto left_info = left_archive.filename_to_header;
|
||||
const auto left_info = left_archive.files();
|
||||
|
||||
xlnt::detail::vector_istreambuf right_buffer(right);
|
||||
std::istream right_stream(&right_buffer);
|
||||
Partio::ZipFileReader right_archive(right_stream);
|
||||
xlnt::detail::ZipFileReader right_archive(right_stream);
|
||||
|
||||
const auto right_info = right_archive.filename_to_header;
|
||||
const auto right_info = right_archive.files();
|
||||
|
||||
if (left_info.size() != right_info.size())
|
||||
{
|
||||
|
@ -354,14 +353,14 @@ public:
|
|||
std::cout << "left has: ";
|
||||
for (auto &info : left_info)
|
||||
{
|
||||
std::cout << info.first << ", ";
|
||||
std::cout << info << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "right has: ";
|
||||
for (auto &info : right_info)
|
||||
{
|
||||
std::cout << info.first << ", ";
|
||||
std::cout << info << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
@ -379,33 +378,33 @@ public:
|
|||
|
||||
for (auto left_member : left_info)
|
||||
{
|
||||
if (!right_archive.Has_File(left_member.first))
|
||||
if (!right_archive.has_file(left_member))
|
||||
{
|
||||
match = false;
|
||||
std::cout << "right is missing file: " << left_member.first << std::endl;
|
||||
std::cout << "right is missing file: " << left_member << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::istream> left_member_stream(left_archive.Get_File(left_member.first));
|
||||
auto &left_member_stream = left_archive.open(left_member);
|
||||
std::vector<std::uint8_t> left_contents_raw;
|
||||
xlnt::detail::vector_ostreambuf left_contents_buffer(left_contents_raw);
|
||||
std::ostream left_contents_stream(&left_contents_buffer);
|
||||
left_contents_stream << left_member_stream->rdbuf();
|
||||
left_contents_stream << left_member_stream.rdbuf();
|
||||
std::string left_member_contents(left_contents_raw.begin(), left_contents_raw.end());
|
||||
|
||||
std::unique_ptr<std::istream> right_member_stream(left_archive.Get_File(left_member.first));
|
||||
auto &right_member_stream = left_archive.open(left_member);
|
||||
std::vector<std::uint8_t> right_contents_raw;
|
||||
xlnt::detail::vector_ostreambuf right_contents_buffer(right_contents_raw);
|
||||
std::ostream right_contents_stream(&right_contents_buffer);
|
||||
right_contents_stream << right_member_stream->rdbuf();
|
||||
right_contents_stream << right_member_stream.rdbuf();
|
||||
std::string right_member_contents(right_contents_raw.begin(), right_contents_raw.end());
|
||||
|
||||
std::string left_content_type, right_content_type;
|
||||
|
||||
if (left_member.first != "[Content_Types].xml")
|
||||
if (left_member != "[Content_Types].xml")
|
||||
{
|
||||
left_content_type = left_manifest.get_content_type(xlnt::path(left_member.first));
|
||||
right_content_type = right_manifest.get_content_type(xlnt::path(left_member.first));
|
||||
left_content_type = left_manifest.get_content_type(xlnt::path(left_member));
|
||||
right_content_type = right_manifest.get_content_type(xlnt::path(left_member));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -415,7 +414,7 @@ public:
|
|||
if (left_content_type != right_content_type)
|
||||
{
|
||||
std::cout << "content types differ: "
|
||||
<< left_member.first
|
||||
<< left_member
|
||||
<< " "
|
||||
<< left_content_type
|
||||
<< " "
|
||||
|
@ -425,7 +424,7 @@ public:
|
|||
}
|
||||
else if (!compare_files(left_member_contents, right_member_contents, left_content_type))
|
||||
{
|
||||
std::cout << left_member.first << std::endl;
|
||||
std::cout << left_member << std::endl;
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
|
|
92
third-party/CMakeLists.txt
vendored
92
third-party/CMakeLists.txt
vendored
|
@ -14,30 +14,47 @@ set(LIBSTUDXML
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/qname.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/serializer.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/value-traits.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/content
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/exception
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/forward
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/parser
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/qname
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/serializer
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/value-traits)
|
||||
|
||||
set(EXPAT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmlparse.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmlrole.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmltok_impl.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmltok_ns.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmltok.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/ascii.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/asciitab.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/config.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/expat_external.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/expat.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/iasciitab.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/internal.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/latin1tab.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/nametab.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/utf8tab.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmlrole.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmltok_impl.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/expat/xmltok.h)
|
||||
|
||||
set(GENX
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/genx/char-props.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libstudxml/xml/details/genx/genx.c)
|
||||
set(POLE pole/pole.cpp)
|
||||
set(BOTAN ${CMAKE_CURRENT_SOURCE_DIR}/botan/botan_all.cpp)
|
||||
set(ZLIB ${CMAKE_CURRENT_SOURCE_DIR}/zlib/adler32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/compress.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/crc32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/deflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzclose.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzread.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzwrite.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/infback.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inffast.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inftrees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/trees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/uncompr.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/zutil.c)
|
||||
${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\"")
|
||||
|
@ -52,9 +69,40 @@ endif()
|
|||
add_custom_command(OUTPUT ${BOTAN}
|
||||
COMMAND python configure.py --minimized-build --enable-modules=sha1,aes,filters,codec_filt,cbc,ecb,sha2_32,sha2_64 --without-sphinx --disable-shared --amalgamation --cpu=${CPU}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/botan
|
||||
COMMENT "Generating botan amalgamation ${BOTAN}")
|
||||
COMMENT "Generating botan amalgamation")
|
||||
|
||||
add_library(xlnt.third-party OBJECT ${LIBSTUDXML} ${POLE} ${BOTAN} ${ZLIB})
|
||||
set(ZLIB ${CMAKE_CURRENT_SOURCE_DIR}/zlib/adler32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/compress.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/crc32.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/deflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzclose.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzlib.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzread.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzwrite.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/infback.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inffast.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inflate.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inftrees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/trees.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/uncompr.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/zutil.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/crc32.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/deflate.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/gzguts.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inffast.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inffixed.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inflate.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/inftrees.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/trees.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/zconf.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/zlib.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/zlib/zutil.h)
|
||||
|
||||
if(NOT MSVC)
|
||||
set_source_files_properties(${ZLIB} PROPERTIES COMPILE_FLAGS "-Wno-implicit-function-declaration")
|
||||
endif()
|
||||
|
||||
add_library(xlnt.third-party OBJECT ${LIBSTUDXML} ${GENX} ${EXPAT} ${POLE} ${BOTAN} ${ZLIB})
|
||||
target_compile_definitions(xlnt.third-party PRIVATE LIBSTUDXML_STATIC_LIB=1)
|
||||
|
||||
if(NOT STATIC)
|
||||
|
@ -69,5 +117,7 @@ endif()
|
|||
|
||||
source_group(botan FILES ${BOTAN})
|
||||
source_group(libstudxml FILES ${LIBSTUDXML})
|
||||
source_group(pole 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
2
third-party/botan
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 36e0ea1e407027ac48e82b56016a6813ff6a1082
|
||||
Subproject commit 73c2605f50e6192bf6cb560c51d32bc53b4c5597
|
2
third-party/libstudxml
vendored
2
third-party/libstudxml
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 54d64e7ca405e06d2328e6207bb4752e20577e50
|
||||
Subproject commit 132522ca4c895e9b07d7e323d5529474806e5829
|
2
third-party/pugixml
vendored
2
third-party/pugixml
vendored
|
@ -1 +1 @@
|
|||
Subproject commit dfe9360cdf038c0ecf53d45bfc75cf8fd34604b8
|
||||
Subproject commit a832e8a5eff11f58a00ca41ec51ff3895b0da165
|
2
third-party/utfcpp
vendored
2
third-party/utfcpp
vendored
|
@ -1 +1 @@
|
|||
Subproject commit f029fcc2fbc7cd979925f198f7e6ca8170d45000
|
||||
Subproject commit a5ad5ec9d936d63e9c010d1054f8b11fed0fabbc
|
2
third-party/zlib
vendored
2
third-party/zlib
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 50893291621658f355bc5b4d450a8d06a563053d
|
||||
Subproject commit 94575859cf7f657f0f31aff4c50761fe3f182699
|
Loading…
Reference in New Issue
Block a user