clang-format all source files, fix broken test helpers--lots of cleanup necessary as a result [ci skip]

This commit is contained in:
Thomas Fussell 2016-12-24 10:04:57 -05:00
parent 6c32563d18
commit c8f2ca204b
59 changed files with 4594 additions and 4309 deletions

View File

@ -27,7 +27,7 @@ BraceWrapping:
BeforeElse: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
ColumnLimit: 120
ColumnLimit: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true
Cpp11BracedListStyle: true
DerivePointerAlignment: false

View File

@ -469,6 +469,9 @@ public:
/// </summary>
void comment(const class comment &new_comment);
double width() const;
double height() const;
// operators
/// <summary>

View File

@ -37,6 +37,7 @@ class fill;
class font;
class number_format;
class protection;
class style;
namespace detail {
@ -208,7 +209,7 @@ public:
/// <summary>
///
/// </summary>
format style(const xlnt::style &new_style);
format style(const class style &new_style);
/// <summary>
///

View File

@ -28,6 +28,7 @@
#include <string>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/utils/optional.hpp>
namespace xlnt {

View File

@ -0,0 +1,37 @@
// Copyright (c) 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 <xlnt/xlnt_config.hpp>
namespace xlnt {
/// <summary>
///
/// </summary>
class XLNT_API calculation_properties
{
};
} // namespace xlnt

View File

@ -41,6 +41,7 @@ enum class relationship_type;
class alignment;
class border;
class calculation_properties;
class cell;
class cell_style;
class color;
@ -633,14 +634,31 @@ public:
/// <summary>
///
/// </summary>
void thumbnail(
const std::vector<std::uint8_t> &thumbnail, const std::string &extension, const std::string &content_type);
void thumbnail(const std::vector<std::uint8_t> &thumbnail,
const std::string &extension, const std::string &content_type);
/// <summary>
///
/// </summary>
const std::vector<std::uint8_t> &thumbnail() const;
// calculation properties
/// <summary>
///
/// </summary>
bool has_calculation_properties() const;
/// <summary>
///
/// </summary>
class calculation_properties calculation_properties() const;
/// <summary>
///
/// </summary>
void calculation_properties(const class calculation_properties &props);
// operators
/// <summary>

View File

@ -73,96 +73,99 @@ class XLNT_API worksheet
{
public:
/// <summary>
///
/// Iterate over a non-const worksheet with an iterator of this type.
/// </summary>
using iterator = range_iterator;
/// <summary>
///
/// Iterate over a non-const worksheet with an iterator of this type.
/// </summary>
using const_iterator = const_range_iterator;
/// <summary>
///
/// Iterate in reverse over a non-const worksheet with an iterator of this type.
/// </summary>
using reverse_iterator = std::reverse_iterator<iterator>;
/// <summary>
///
/// Iterate in reverse order over a const worksheet with an iterator of this type.
/// </summary>
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// <summary>
///
/// Construct a null worksheet. No methods should be called on such a worksheet.
/// </summary>
worksheet();
/// <summary>
///
/// Copy constructor. This worksheet will point to the same memory as rhs's worksheet.
/// </summary>
worksheet(const worksheet &rhs);
/// <summary>
///
/// Returns a reference to the workbook this worksheet is owned by.
/// </summary>
class workbook &workbook();
/// <summary>
///
/// Returns a reference to the workbook this worksheet is owned by.
/// </summary>
const class workbook &workbook() const;
/// <summary>
///
/// Deletes data held in the worksheet that does not affect the internal data or display.
/// For example, unreference styles and empty cells will be removed.
/// </summary>
void garbage_collect();
// identification
/// <summary>
///
/// Returns the unique numeric identifier of this worksheet. This will sometimes but not necessarily
/// be the index of the worksheet in the workbook.
/// </summary>
std::size_t id() const;
/// <summary>
///
/// Set the unique numeric identifier. The id defaults to the lowest unused id in the workbook
/// so this should not be called without a good reason.
/// </summary>
void id(std::size_t id);
/// <summary>
///
/// Returns the title of this sheet.
/// </summary>
std::string title() const;
/// <summary>
///
/// Sets the title of this sheet.
/// </summary>
void title(const std::string &title);
// freeze panes
/// <summary>
///
/// Returns the top left corner of the region above and to the left of which panes are frozen.
/// </summary>
cell_reference frozen_panes() const;
/// <summary>
///
/// Freeze panes above and to the left of top_left_cell.
/// </summary>
void freeze_panes(cell top_left_cell);
/// <summary>
///
/// Freeze panes above and to the left of top_left_coordinate.
/// </summary>
void freeze_panes(const cell_reference &top_left_coordinate);
/// <summary>
///
/// Remove frozen panes. The data in those panes will be unaffected--this affects only the view.
/// </summary>
void unfreeze_panes();
/// <summary>
///
/// Returns true if this sheet has a frozen row, frozen column, or both.
/// </summary>
bool has_frozen_panes() const;
@ -260,6 +263,12 @@ public:
/// </summary>
void add_column_properties(column_t column, const class column_properties &props);
/// <summary>
/// Calculate the width of the given column. This will be the default column width if
/// a custom width is not set on this column's column_properties.
/// </summary>
double column_width(column_t column) const;
/// <summary>
///
/// </summary>
@ -280,6 +289,12 @@ public:
/// </summary>
void add_row_properties(row_t row, const class row_properties &props);
/// <summary>
/// Calculate the height of the given row. This will be the default row height if
/// a custom height is not set on this row's row_properties.
/// </summary>
double row_height(row_t row) const;
// positioning
/// <summary>
@ -686,10 +701,33 @@ public:
/// </summary>
void add_view(const sheet_view &new_view);
std::vector<row_t> &row_breaks();
const std::vector<row_t> &row_breaks() const;
std::vector<column_t> &column_breaks();
const std::vector<column_t> &column_breaks() const;
// page breaks
/// <summary>
/// Remove all manual column and row page breaks (represented as dashed
/// blue lines in the page view in Excel).
/// </summary>
void clear_page_breaks();
/// <summary>
/// Returns vector where each element represents a row which will break a page below it.
/// </summary>
const std::vector<row_t> &page_break_rows() const;
/// <summary>
/// Add a page break at the given row.
/// </summary>
void page_break_at_row(row_t row);
/// <summary>
/// Returns vector where each element represents a column which will break a page to the right.
/// </summary>
const std::vector<column_t> &page_break_columns() const;
/// <summary>
/// Add a page break at the given column.
/// </summary>
void page_break_at_column(column_t column);
private:
friend class cell;

View File

@ -57,11 +57,12 @@ namespace {
std::pair<bool, long double> cast_numeric(const std::string &s)
{
const char *str = s.c_str();
char *str_end = nullptr;
auto result = std::strtold(str, &str_end);
if (str_end != str + s.size()) return {false, 0};
return {true, result};
auto str_end = static_cast<char *>(nullptr);
auto result = std::strtold(s.c_str(), &str_end);
return (str_end != s.c_str() + s.size())
? std::make_pair(false, 0.0L)
: std::make_pair(true, result);
}
std::pair<bool, long double> cast_percentage(const std::string &s)
@ -149,16 +150,14 @@ namespace xlnt {
const std::unordered_map<std::string, int> &cell::error_codes()
{
static const auto *codes = new std::unordered_map<std::string, int>
{
static const auto *codes = new std::unordered_map<std::string, int>{
{"#NULL!", 0},
{"#DIV/0!", 1},
{"#VALUE!", 2},
{"#REF!", 3},
{"#NAME?", 4},
{"#NUM!", 5},
{"#N/A!", 6}
};
{"#N/A!", 6}};
return *codes;
}
@ -188,7 +187,8 @@ std::string cell::check_string(const std::string &to_check)
return s;
}
cell::cell(detail::cell_impl *d) : d_(d)
cell::cell(detail::cell_impl *d)
: d_(d)
{
}
@ -546,56 +546,23 @@ const workbook &cell::workbook() const
return worksheet().workbook();
}
// TODO: this shares a lot of code with worksheet::point_pos, try to reduce repetion
std::pair<int, int> cell::anchor() const
{
static const auto DefaultColumnWidth = 51.85L;
static const auto DefaultRowHeight = 15.0L;
int left = 0;
auto points_to_pixels = [](
long double value, long double dpi) { return static_cast<int>(std::ceil(value * dpi / 72)); };
auto left_columns = d_->column_ - 1;
int left_anchor = 0;
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0L);
for (column_t column_index = 1; column_index <= left_columns; column_index++)
for (column_t column_index = 1; column_index <= d_->column_ - 1; column_index++)
{
if (worksheet().has_column_properties(column_index))
{
auto cdw = worksheet().column_properties(column_index).width;
if (cdw > 0)
{
left_anchor += points_to_pixels(cdw, 96.0L);
continue;
}
left += worksheet().cell(column_index, row()).width();
}
left_anchor += default_width;
}
int top = 0;
auto top_rows = d_->row_ - 1;
int top_anchor = 0;
auto default_height = points_to_pixels(DefaultRowHeight, 96.0L);
for (row_t row_index = 1; row_index <= top_rows; row_index++)
for (row_t row_index = 1; row_index <= d_->row_ - 1; row_index++)
{
if (worksheet().has_row_properties(row_index))
{
auto rdh = worksheet().row_properties(row_index).height;
if (rdh > 0)
{
top_anchor += points_to_pixels(rdh, 96.0L);
continue;
}
top += worksheet().cell(column(), row_index).height();
}
top_anchor += default_height;
}
return {left_anchor, top_anchor};
return {left, top};
}
cell::type cell::data_type() const
@ -1024,32 +991,13 @@ void cell::comment(const std::string &text, const class font &comment_font, cons
comment(xlnt::comment(rich_comment_text, author));
}
void cell::comment(const class comment &new_comment)
{
d_->comment_.set(new_comment);
// offset comment 5 pixels down and 5 pixels right of the top right corner of the cell
auto cell_position = anchor();
// todo: make this cell_position.first += width() instead
if (worksheet().has_column_properties(column()))
{
cell_position.first += static_cast<int>(worksheet().column_properties(column()).width);
}
else
{
static const auto DefaultColumnWidth = 51.85L;
auto points_to_pixels = [](long double value, long double dpi)
{
return static_cast<int>(std::ceil(value * dpi / 72));
};
cell_position.first += points_to_pixels(DefaultColumnWidth, 96.0L);
}
cell_position.first += 5;
cell_position.first += width() + 5;
cell_position.second += 5;
d_->comment_.get().position(cell_position.first, cell_position.second);
@ -1058,4 +1006,14 @@ void cell::comment(const class comment &new_comment)
worksheet().register_comments_in_manifest();
}
double cell::width() const
{
return worksheet().column_width(column());
}
double cell::height() const
{
return worksheet().row_height(row());
}
} // namespace xlnt

View File

@ -45,7 +45,8 @@ cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolut
return *this;
}
cell_reference::cell_reference() : cell_reference(1, 1)
cell_reference::cell_reference()
: cell_reference(1, 1)
{
}
@ -65,10 +66,7 @@ cell_reference::cell_reference(const char *reference_string)
cell_reference::cell_reference(column_t column_index, row_t row)
: column_(column_index), row_(row), absolute_row_(false), absolute_column_(false)
{
if (row_ == 0
|| column_ == 0
|| !(row_ <= constants::max_row())
|| !(column_ <= constants::max_column()))
if (row_ == 0 || column_ == 0 || !(row_ <= constants::max_row()) || !(column_ <= constants::max_column()))
{
throw invalid_cell_reference(column_, row_);
}
@ -111,8 +109,8 @@ std::pair<std::string, row_t> cell_reference::split_reference(const std::string
return split_reference(reference_string, ignore1, ignore2);
}
std::pair<std::string, row_t> cell_reference::split_reference(const std::string &reference_string,
bool &absolute_column, bool &absolute_row)
std::pair<std::string, row_t> cell_reference::split_reference(
const std::string &reference_string, bool &absolute_column, bool &absolute_row)
{
absolute_column = false;
absolute_row = false;
@ -267,15 +265,12 @@ cell_reference cell_reference::make_offset(int column_offset, int row_offset) co
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
{
return comparand.column_ == column_ &&
comparand.row_ == row_ &&
absolute_column_ == comparand.absolute_column_ &&
absolute_row_ == comparand.absolute_row_;
return comparand.column_ == column_ && comparand.row_ == row_ && absolute_column_ == comparand.absolute_column_
&& absolute_row_ == comparand.absolute_row_;
}
} // namespace xlnt

View File

@ -25,19 +25,18 @@
namespace xlnt {
comment::comment() : comment("", "")
comment::comment()
: comment("", "")
{
}
comment::comment(const rich_text &text, const std::string &author)
: text_(text),
author_(author)
: text_(text), author_(author)
{
}
comment::comment(const std::string &text, const std::string &author)
: text_(),
author_(author)
: text_(), author_(author)
{
text_.plain_text(text);
}

View File

@ -23,9 +23,9 @@
// @author: see AUTHORS file
#include <locale>
#include <detail/constants.hpp>
#include <xlnt/cell/index_types.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <detail/constants.hpp>
namespace xlnt {
@ -89,98 +89,252 @@ std::string column_t::column_string_from_index(column_t::index_t column_index)
return column_letter;
}
column_t::column_t()
: index(1)
{
}
column_t::column_t() : index(1) {}
column_t::column_t(index_t column_index)
: index(column_index)
{
}
column_t::column_t(index_t column_index) : index(column_index) {}
column_t::column_t(const std::string &column_string)
: index(column_index_from_string(column_string))
{
}
column_t::column_t(const std::string &column_string) : index(column_index_from_string(column_string)) {}
column_t::column_t(const char *column_string)
: column_t(std::string(column_string))
{
}
column_t::column_t(const char *column_string) : column_t(std::string(column_string)) {}
column_t::column_t(const column_t &other)
: column_t(other.index)
{
}
column_t::column_t(const column_t &other) : column_t(other.index) {}
column_t::column_t(column_t &&other)
{
swap(*this, other);
}
column_t::column_t(column_t &&other) { swap(*this, other); }
std::string column_t::column_string() const
{
return column_string_from_index(index);
}
std::string column_t::column_string() const { return column_string_from_index(index); }
column_t &column_t::operator=(column_t rhs)
{
swap(*this, rhs);
return *this;
}
column_t &column_t::operator=(column_t rhs) { swap(*this, rhs); return *this; }
column_t &column_t::operator=(const std::string &rhs)
{
return *this = column_t(rhs);
}
column_t &column_t::operator=(const std::string &rhs) { return *this = column_t(rhs); }
column_t &column_t::operator=(const char *rhs)
{
return *this = column_t(rhs);
}
column_t &column_t::operator=(const char *rhs) { return *this = column_t(rhs); }
bool column_t::operator==(const column_t &other) const
{
return index == other.index;
}
bool column_t::operator==(const column_t &other) const { return index == other.index; }
bool column_t::operator!=(const column_t &other) const
{
return !(*this == other);
}
bool column_t::operator!=(const column_t &other) const { return !(*this == other); }
bool column_t::operator==(int other) const
{
return *this == column_t(static_cast<index_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);
}
bool column_t::operator==(index_t other) const { return *this == column_t(other); }
bool column_t::operator==(const std::string &other) const
{
return *this == column_t(other);
}
bool column_t::operator==(const std::string &other) const { return *this == column_t(other); }
bool column_t::operator==(const char *other) const
{
return *this == column_t(other);
}
bool column_t::operator==(const char *other) const { return *this == column_t(other); }
bool column_t::operator!=(int other) const
{
return !(*this == other);
}
bool column_t::operator!=(int other) const { return !(*this == other); }
bool column_t::operator!=(index_t other) const
{
return !(*this == other);
}
bool column_t::operator!=(index_t other) const { return !(*this == other); }
bool column_t::operator!=(const std::string &other) const
{
return !(*this == other);
}
bool column_t::operator!=(const std::string &other) const { return !(*this == other); }
bool column_t::operator!=(const char *other) const
{
return !(*this == other);
}
bool column_t::operator!=(const char *other) const { return !(*this == other); }
bool column_t::operator>(const column_t &other) const
{
return index > other.index;
}
bool column_t::operator>(const column_t &other) const { return index > other.index; }
bool column_t::operator>=(const column_t &other) const
{
return index >= other.index;
}
bool column_t::operator>=(const column_t &other) const { return index >= other.index; }
bool column_t::operator<(const column_t &other) const
{
return index < other.index;
}
bool column_t::operator<(const column_t &other) const { return index < other.index; }
bool column_t::operator<=(const column_t &other) const
{
return index <= other.index;
}
bool column_t::operator<=(const column_t &other) const { return index <= other.index; }
bool column_t::operator>(const column_t::index_t &other) const
{
return index > other;
}
bool column_t::operator>(const column_t::index_t &other) const { return index > other; }
bool column_t::operator>=(const column_t::index_t &other) const
{
return index >= other;
}
bool column_t::operator>=(const column_t::index_t &other) const { return index >= other; }
bool column_t::operator<(const column_t::index_t &other) const
{
return index < other;
}
bool column_t::operator<(const column_t::index_t &other) const { return index < other; }
bool column_t::operator<=(const column_t::index_t &other) const
{
return index <= other;
}
bool column_t::operator<=(const column_t::index_t &other) const { return index <= other; }
column_t &column_t::operator++()
{
index++;
return *this;
}
column_t &column_t::operator++() { index++; return *this; }
column_t &column_t::operator--()
{
index--;
return *this;
}
column_t &column_t::operator--() { index--; return *this; }
column_t column_t::operator++(int)
{
column_t copy(index);
++(*this);
return copy;
}
column_t column_t::operator++(int) { column_t copy(index); ++(*this); return copy; }
column_t column_t::operator--(int)
{
column_t copy(index);
--(*this);
return copy;
}
column_t column_t::operator--(int) { column_t copy(index); --(*this); return copy; }
column_t operator+(column_t lhs, const column_t &rhs)
{
lhs += rhs;
return lhs;
}
column_t operator+(column_t lhs, const column_t& rhs) { lhs += rhs; return lhs; }
column_t operator-(column_t lhs, const column_t &rhs)
{
lhs -= rhs;
return lhs;
}
column_t operator-(column_t lhs, const column_t& rhs) { lhs -= rhs; return lhs; }
column_t operator*(column_t lhs, const column_t &rhs)
{
lhs *= rhs;
return lhs;
}
column_t operator*(column_t lhs, const column_t& rhs) { lhs *= rhs; return lhs; }
column_t operator/(column_t lhs, const column_t &rhs)
{
lhs /= rhs;
return lhs;
}
column_t operator/(column_t lhs, const column_t& rhs) { lhs /= rhs; return lhs; }
column_t operator%(column_t lhs, const column_t &rhs)
{
lhs %= rhs;
return lhs;
}
column_t operator%(column_t lhs, const column_t& rhs) { lhs %= rhs; return lhs; }
column_t &column_t::operator+=(const column_t &rhs)
{
index += rhs.index;
return *this;
}
column_t &column_t::operator+=(const column_t &rhs) { index += rhs.index; return *this; }
column_t &column_t::operator-=(const column_t &rhs)
{
index -= rhs.index;
return *this;
}
column_t &column_t::operator-=(const column_t &rhs) { index -= rhs.index; return *this; }
column_t &column_t::operator*=(const column_t &rhs)
{
index *= rhs.index;
return *this;
}
column_t &column_t::operator*=(const column_t &rhs) { index *= rhs.index; return *this; }
column_t &column_t::operator/=(const column_t &rhs)
{
index /= rhs.index;
return *this;
}
column_t &column_t::operator/=(const column_t &rhs) { index /= rhs.index; return *this; }
column_t &column_t::operator%=(const column_t &rhs)
{
index %= rhs.index;
return *this;
}
column_t &column_t::operator%=(const column_t &rhs) { index %= rhs.index; return *this; }
bool operator>(const column_t::index_t &left, const column_t &right)
{
return column_t(left) > right;
}
bool operator>(const column_t::index_t &left, const column_t &right) { return column_t(left) > right; }
bool operator>=(const column_t::index_t &left, const column_t &right)
{
return column_t(left) >= right;
}
bool operator>=(const column_t::index_t &left, const column_t &right) { return column_t(left) >= right; }
bool operator<(const column_t::index_t &left, const column_t &right)
{
return column_t(left) < right;
}
bool operator<(const column_t::index_t &left, const column_t &right) { return column_t(left) < right; }
bool operator<=(const column_t::index_t &left, const column_t &right) { return column_t(left) <= right; }
bool operator<=(const column_t::index_t &left, const column_t &right)
{
return column_t(left) <= right;
}
void swap(column_t &left, column_t &right)
{

View File

@ -29,12 +29,7 @@ namespace xlnt {
namespace detail {
cell_impl::cell_impl()
: type_(cell_type::null),
parent_(nullptr),
column_(1),
row_(1),
is_merged_(false),
value_numeric_(0)
: type_(cell_type::null), parent_(nullptr), column_(1), row_(1), is_merged_(false), value_numeric_(0)
{
}

View File

@ -22,9 +22,9 @@
// @author: see AUTHORS file
#include <limits>
#include <detail/constants.hpp>
#include <xlnt/xlnt_config.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <detail/constants.hpp>
namespace xlnt {
@ -49,27 +49,68 @@ const column_t constants::max_column()
}
// constants
const path constants::package_properties() { return path("docProps"); }
const path constants::package_xl() { return path("/xl"); }
const path constants::package_root_rels() { return path(std::string("_rels")); }
const path constants::package_theme() { return package_xl().append("theme"); }
const path constants::package_worksheets() { return package_xl().append("worksheets"); }
const path constants::package_drawings() { return package_xl().append("drawings"); }
const path constants::package_properties()
{
return path("docProps");
}
const path constants::package_xl()
{
return path("/xl");
}
const path constants::package_root_rels()
{
return path(std::string("_rels"));
}
const path constants::package_theme()
{
return package_xl().append("theme");
}
const path constants::package_worksheets()
{
return package_xl().append("worksheets");
}
const path constants::package_drawings()
{
return package_xl().append("drawings");
}
const path constants::part_content_types() { return path("[Content_Types].xml"); }
const path constants::part_root_relationships() { return package_root_rels().append(".rels"); }
const path constants::part_core() { return package_properties().append("core.xml"); }
const path constants::part_app() { return package_properties().append("app.xml"); }
const path constants::part_workbook() { return package_xl().append("workbook.xml"); }
const path constants::part_styles() { return package_xl().append("styles.xml"); }
const path constants::part_theme() { return package_theme().append("theme1.xml"); }
const path constants::part_shared_strings() { return package_xl().append("sharedStrings.xml"); }
const path constants::part_content_types()
{
return path("[Content_Types].xml");
}
const path constants::part_root_relationships()
{
return package_root_rels().append(".rels");
}
const path constants::part_core()
{
return package_properties().append("core.xml");
}
const path constants::part_app()
{
return package_properties().append("app.xml");
}
const path constants::part_workbook()
{
return package_xl().append("workbook.xml");
}
const path constants::part_styles()
{
return package_xl().append("styles.xml");
}
const path constants::part_theme()
{
return package_theme().append("theme1.xml");
}
const path constants::part_shared_strings()
{
return package_xl().append("sharedStrings.xml");
}
const std::unordered_map<std::string, std::string> &constants::namespaces()
{
static const std::unordered_map<std::string, std::string> *namespaces =
new std::unordered_map<std::string, std::string>
{
new std::unordered_map<std::string, std::string>{
{"spreadsheetml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"},
{"content-types", "http://schemas.openxmlformats.org/package/2006/content-types"},
{"relationships", "http://schemas.openxmlformats.org/package/2006/relationships"},
@ -83,8 +124,7 @@ const std::unordered_map<std::string, std::string> &constants::namespaces()
{"encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password"},
{"encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate"},
{ "dc", "http://purl.org/dc/elements/1.1/" },
{ "dcterms", "http://purl.org/dc/terms/" },
{"dc", "http://purl.org/dc/elements/1.1/"}, {"dcterms", "http://purl.org/dc/terms/"},
{"dcmitype", "http://purl.org/dc/dcmitype/"},
{"mc", "http://schemas.openxmlformats.org/markup-compatibility/2006"},
{"mx", "http://schemas.microsoft.com/office/mac/excel/2008/main"},
@ -95,11 +135,9 @@ const std::unordered_map<std::string, std::string> &constants::namespaces()
{"x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"},
{"x15", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"},
{"x15ac", "http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac"},
{ "xml", "http://www.w3.org/XML/1998/namespace" },
{ "xsi", "http://www.w3.org/2001/XMLSchema-instance" },
{"xml", "http://www.w3.org/XML/1998/namespace"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
{ "loext", "http://schemas.libreoffice.org/" }
};
{"loext", "http://schemas.libreoffice.org/"}};
return *namespaces;
}
@ -115,5 +153,4 @@ const std::string &constants::namespace_(const std::string &id)
return match->second;
}
}

View File

@ -10,17 +10,21 @@ std::string to_string(font::underline_style style)
{
switch (style)
{
case font::underline_style::double_: return "double";
case font::underline_style::double_accounting: return "doubleAccounting";
case font::underline_style::single: return "single";
case font::underline_style::single_accounting: return "singleAccounting";
case font::underline_style::none: return "none";
case font::underline_style::double_:
return "double";
case font::underline_style::double_accounting:
return "doubleAccounting";
case font::underline_style::single:
return "single";
case font::underline_style::single_accounting:
return "singleAccounting";
case font::underline_style::none:
return "none";
}
default_case("single");
}
/// <summary>
/// Returns the string representation of the relationship type.
/// </summary>
@ -107,25 +111,44 @@ std::string to_string(pattern_fill_type fill_type)
{
switch (fill_type)
{
case pattern_fill_type::darkdown: return "darkdown";
case pattern_fill_type::darkgray: return "darkgray";
case pattern_fill_type::darkgrid: return "darkgrid";
case pattern_fill_type::darkhorizontal: return "darkhorizontal";
case pattern_fill_type::darktrellis: return "darkhorizontal";
case pattern_fill_type::darkup: return "darkup";
case pattern_fill_type::darkvertical: return "darkvertical";
case pattern_fill_type::gray0625: return "gray0625";
case pattern_fill_type::gray125: return "gray125";
case pattern_fill_type::lightdown: return "lightdown";
case pattern_fill_type::lightgray: return "lightgray";
case pattern_fill_type::lightgrid: return "lightgrid";
case pattern_fill_type::lighthorizontal: return "lighthorizontal";
case pattern_fill_type::lighttrellis: return "lighttrellis";
case pattern_fill_type::lightup: return "lightup";
case pattern_fill_type::lightvertical: return "lightvertical";
case pattern_fill_type::mediumgray: return "mediumgray";
case pattern_fill_type::solid: return "solid";
case pattern_fill_type::none: return "none";
case pattern_fill_type::darkdown:
return "darkdown";
case pattern_fill_type::darkgray:
return "darkgray";
case pattern_fill_type::darkgrid:
return "darkgrid";
case pattern_fill_type::darkhorizontal:
return "darkhorizontal";
case pattern_fill_type::darktrellis:
return "darkhorizontal";
case pattern_fill_type::darkup:
return "darkup";
case pattern_fill_type::darkvertical:
return "darkvertical";
case pattern_fill_type::gray0625:
return "gray0625";
case pattern_fill_type::gray125:
return "gray125";
case pattern_fill_type::lightdown:
return "lightdown";
case pattern_fill_type::lightgray:
return "lightgray";
case pattern_fill_type::lightgrid:
return "lightgrid";
case pattern_fill_type::lighthorizontal:
return "lighthorizontal";
case pattern_fill_type::lighttrellis:
return "lighttrellis";
case pattern_fill_type::lightup:
return "lightup";
case pattern_fill_type::lightvertical:
return "lightvertical";
case pattern_fill_type::mediumgray:
return "mediumgray";
case pattern_fill_type::solid:
return "solid";
case pattern_fill_type::none:
return "none";
}
default_case("none");
@ -140,20 +163,34 @@ std::string to_string(border_style style)
{
switch (style)
{
case border_style::dashdot: return "dashdot";
case border_style::dashdotdot: return "dashdotdot";
case border_style::dashed: return "dashed";
case border_style::dotted: return "dotted";
case border_style::double_: return "double";
case border_style::hair: return "hair";
case border_style::medium: return "medium";
case border_style::mediumdashdot: return "mediumdashdot";
case border_style::mediumdashdotdot: return "mediumdashdotdot";
case border_style::mediumdashed: return "mediumdashed";
case border_style::slantdashdot: return "slantdashdot";
case border_style::thick: return "thick";
case border_style::thin: return "thin";
case border_style::none: return "none";
case border_style::dashdot:
return "dashdot";
case border_style::dashdotdot:
return "dashdotdot";
case border_style::dashed:
return "dashed";
case border_style::dotted:
return "dotted";
case border_style::double_:
return "double";
case border_style::hair:
return "hair";
case border_style::medium:
return "medium";
case border_style::mediumdashdot:
return "mediumdashdot";
case border_style::mediumdashdotdot:
return "mediumdashdotdot";
case border_style::mediumdashed:
return "mediumdashed";
case border_style::slantdashdot:
return "slantdashdot";
case border_style::thick:
return "thick";
case border_style::thin:
return "thin";
case border_style::none:
return "none";
}
default_case("none");
@ -163,11 +200,16 @@ std::string to_string(vertical_alignment alignment)
{
switch (alignment)
{
case vertical_alignment::top: return "top";
case vertical_alignment::center: return "center";
case vertical_alignment::bottom: return "bottom";
case vertical_alignment::justify: return "justify";
case vertical_alignment::distributed: return "distributed";
case vertical_alignment::top:
return "top";
case vertical_alignment::center:
return "center";
case vertical_alignment::bottom:
return "bottom";
case vertical_alignment::justify:
return "justify";
case vertical_alignment::distributed:
return "distributed";
}
default_case("top");
@ -177,14 +219,22 @@ std::string to_string(horizontal_alignment alignment)
{
switch (alignment)
{
case horizontal_alignment::general: return "general";
case horizontal_alignment::left: return "left";
case horizontal_alignment::center: return "center";
case horizontal_alignment::right: return "right";
case horizontal_alignment::fill: return "fill";
case horizontal_alignment::justify: return "justify";
case horizontal_alignment::center_continuous: return "centerContinuous";
case horizontal_alignment::distributed: return "distributed";
case horizontal_alignment::general:
return "general";
case horizontal_alignment::left:
return "left";
case horizontal_alignment::center:
return "center";
case horizontal_alignment::right:
return "right";
case horizontal_alignment::fill:
return "fill";
case horizontal_alignment::justify:
return "justify";
case horizontal_alignment::center_continuous:
return "centerContinuous";
case horizontal_alignment::distributed:
return "distributed";
}
default_case("general");
@ -194,13 +244,20 @@ std::string to_string(border_side side)
{
switch (side)
{
case border_side::bottom: return "bottom";
case border_side::top: return "top";
case border_side::start: return "left";
case border_side::end: return "right";
case border_side::horizontal: return "horizontal";
case border_side::vertical: return "vertical";
case border_side::diagonal: return "diagonal";
case border_side::bottom:
return "bottom";
case border_side::top:
return "top";
case border_side::start:
return "left";
case border_side::end:
return "right";
case border_side::horizontal:
return "horizontal";
case border_side::vertical:
return "vertical";
case border_side::diagonal:
return "diagonal";
}
default_case("top");

View File

@ -24,124 +24,43 @@
#include <algorithm>
#include <cmath>
#include <xlnt/utils/exceptions.hpp>
#include <detail/default_case.hpp>
#include <detail/number_formatter.hpp>
#include <xlnt/utils/exceptions.hpp>
namespace {
const std::unordered_map<int, std::string> known_locales()
{
static const std::unordered_map<int, std::string> *all =
new std::unordered_map<int, std::string>(
{
{ 0x401, "Arabic - Saudi Arabia" },
{ 0x402, "Bulgarian" },
{ 0x403, "Catalan" },
{ 0x404, "Chinese - Taiwan" },
{ 0x405, "Czech" },
{ 0x406, "Danish" },
{ 0x407, "German - Germany" },
{ 0x408, "Greek" },
{ 0x409, "English - United States" },
{ 0x410, "Italian - Italy" },
{ 0x411, "Japanese" },
{ 0x412, "Korean" },
{ 0x413, "Dutch - Netherlands" },
{ 0x414, "Norwegian - Bokml" },
{ 0x415, "Polish" },
{ 0x416, "Portuguese - Brazil" },
{ 0x417, "Raeto-Romance" },
{ 0x418, "Romanian - Romania" },
{ 0x419, "Russian" },
{ 0x420, "Urdu" },
{ 0x421, "Indonesian" },
{ 0x422, "Ukrainian" },
{ 0x423, "Belarusian" },
{ 0x424, "Slovenian" },
{ 0x425, "Estonian" },
{ 0x426, "Latvian" },
{ 0x427, "Lithuanian" },
{ 0x428, "Tajik" },
{ 0x429, "Farsi - Persian" },
{ 0x430, "Sesotho (Sutu)" },
{ 0x431, "Tsonga" },
{ 0x432, "Setsuana" },
{ 0x433, "Venda" },
{ 0x434, "Xhosa" },
{ 0x435, "Zulu" },
{ 0x436, "Afrikaans" },
{ 0x437, "Georgian" },
{ 0x438, "Faroese" },
{ 0x439, "Hindi" },
{ 0x440, "Kyrgyz - Cyrillic" },
{ 0x441, "Swahili" },
{ 0x442, "Turkmen" },
{ 0x443, "Uzbek - Latin" },
{ 0x444, "Tatar" },
{ 0x445, "Bengali - India" },
{ 0x446, "Punjabi" },
{ 0x447, "Gujarati" },
{ 0x448, "Oriya" },
{ 0x449, "Tamil" },
{ 0x450, "Mongolian" },
{ 0x451, "Tibetan" },
{ 0x452, "Welsh" },
{ 0x453, "Khmer" },
{ 0x454, "Lao" },
{ 0x455, "Burmese" },
{ 0x456, "Galician" },
{ 0x457, "Konkani" },
{ 0x458, "Manipuri" },
{ 0x459, "Sindhi" },
{ 0x460, "Kashmiri" },
{ 0x461, "Nepali" },
{ 0x462, "Frisian - Netherlands" },
{ 0x464, "Filipino" },
{ 0x465, "Divehi; Dhivehi; Maldivian" },
{ 0x466, "Edo" },
{ 0x470, "Igbo - Nigeria" },
{ 0x474, "Guarani - Paraguay" },
{ 0x476, "Latin" },
{ 0x477, "Somali" },
{ 0x481, "Maori" },
{ 0x801, "Arabic - Iraq" },
{ 0x804, "Chinese - China" },
{ 0x807, "German - Switzerland" },
{ 0x809, "English - Great Britain" },
{ 0x810, "Italian - Switzerland" },
{ 0x813, "Dutch - Belgium" },
{ 0x814, "Norwegian - Nynorsk" },
{ 0x816, "Portuguese - Portugal" },
{ 0x818, "Romanian - Moldova" },
{ 0x819, "Russian - Moldova" },
{ 0x843, "Uzbek - Cyrillic" },
{ 0x845, "Bengali - Bangladesh" },
{ 0x850, "Mongolian" },
{ 0x1001, "Arabic - Libya" },
{ 0x1004, "Chinese - Singapore" },
{ 0x1007, "German - Luxembourg" },
{ 0x1009, "English - Canada" },
{ 0x1401, "Arabic - Algeria" },
{ 0x1404, "Chinese - Macau SAR" },
{ 0x1407, "German - Liechtenstein" },
{ 0x1409, "English - New Zealand" },
{ 0x1801, "Arabic - Morocco" },
{ 0x1809, "English - Ireland" },
{ 0x2001, "Arabic - Oman" },
{ 0x2009, "English - Jamaica" },
{ 0x2401, "Arabic - Yemen" },
{ 0x2409, "English - Caribbean" },
{ 0x2801, "Arabic - Syria" },
{ 0x2809, "English - Belize" },
{ 0x3001, "Arabic - Lebanon" },
{ 0x3009, "English - Zimbabwe" },
{ 0x3401, "Arabic - Kuwait" },
{ 0x3409, "English - Phillippines" },
{ 0x3801, "Arabic - United Arab Emirates" },
{ 0x4001, "Arabic - Qatar" }
}
);
static const std::unordered_map<int, std::string> *all = new std::unordered_map<int, std::string>(
{{0x401, "Arabic - Saudi Arabia"}, {0x402, "Bulgarian"}, {0x403, "Catalan"}, {0x404, "Chinese - Taiwan"},
{0x405, "Czech"}, {0x406, "Danish"}, {0x407, "German - Germany"}, {0x408, "Greek"},
{0x409, "English - United States"}, {0x410, "Italian - Italy"}, {0x411, "Japanese"}, {0x412, "Korean"},
{0x413, "Dutch - Netherlands"}, {0x414, "Norwegian - Bokml"}, {0x415, "Polish"},
{0x416, "Portuguese - Brazil"}, {0x417, "Raeto-Romance"}, {0x418, "Romanian - Romania"}, {0x419, "Russian"},
{0x420, "Urdu"}, {0x421, "Indonesian"}, {0x422, "Ukrainian"}, {0x423, "Belarusian"}, {0x424, "Slovenian"},
{0x425, "Estonian"}, {0x426, "Latvian"}, {0x427, "Lithuanian"}, {0x428, "Tajik"},
{0x429, "Farsi - Persian"}, {0x430, "Sesotho (Sutu)"}, {0x431, "Tsonga"}, {0x432, "Setsuana"},
{0x433, "Venda"}, {0x434, "Xhosa"}, {0x435, "Zulu"}, {0x436, "Afrikaans"}, {0x437, "Georgian"},
{0x438, "Faroese"}, {0x439, "Hindi"}, {0x440, "Kyrgyz - Cyrillic"}, {0x441, "Swahili"}, {0x442, "Turkmen"},
{0x443, "Uzbek - Latin"}, {0x444, "Tatar"}, {0x445, "Bengali - India"}, {0x446, "Punjabi"},
{0x447, "Gujarati"}, {0x448, "Oriya"}, {0x449, "Tamil"}, {0x450, "Mongolian"}, {0x451, "Tibetan"},
{0x452, "Welsh"}, {0x453, "Khmer"}, {0x454, "Lao"}, {0x455, "Burmese"}, {0x456, "Galician"},
{0x457, "Konkani"}, {0x458, "Manipuri"}, {0x459, "Sindhi"}, {0x460, "Kashmiri"}, {0x461, "Nepali"},
{0x462, "Frisian - Netherlands"}, {0x464, "Filipino"}, {0x465, "Divehi; Dhivehi; Maldivian"},
{0x466, "Edo"}, {0x470, "Igbo - Nigeria"}, {0x474, "Guarani - Paraguay"}, {0x476, "Latin"},
{0x477, "Somali"}, {0x481, "Maori"}, {0x801, "Arabic - Iraq"}, {0x804, "Chinese - China"},
{0x807, "German - Switzerland"}, {0x809, "English - Great Britain"}, {0x810, "Italian - Switzerland"},
{0x813, "Dutch - Belgium"}, {0x814, "Norwegian - Nynorsk"}, {0x816, "Portuguese - Portugal"},
{0x818, "Romanian - Moldova"}, {0x819, "Russian - Moldova"}, {0x843, "Uzbek - Cyrillic"},
{0x845, "Bengali - Bangladesh"}, {0x850, "Mongolian"}, {0x1001, "Arabic - Libya"},
{0x1004, "Chinese - Singapore"}, {0x1007, "German - Luxembourg"}, {0x1009, "English - Canada"},
{0x1401, "Arabic - Algeria"}, {0x1404, "Chinese - Macau SAR"}, {0x1407, "German - Liechtenstein"},
{0x1409, "English - New Zealand"}, {0x1801, "Arabic - Morocco"}, {0x1809, "English - Ireland"},
{0x2001, "Arabic - Oman"}, {0x2009, "English - Jamaica"}, {0x2401, "Arabic - Yemen"},
{0x2409, "English - Caribbean"}, {0x2801, "Arabic - Syria"}, {0x2809, "English - Belize"},
{0x3001, "Arabic - Lebanon"}, {0x3009, "English - Zimbabwe"}, {0x3401, "Arabic - Kuwait"},
{0x3409, "English - Phillippines"}, {0x3801, "Arabic - United Arab Emirates"}, {0x4001, "Arabic - Qatar"}});
return *all;
}
@ -219,10 +138,7 @@ void number_format_parser::parse()
break;
case number_format_token::token_type::color:
if (section.has_color
|| section.has_condition
|| section.has_locale
|| !section.parts.empty())
if (section.has_color || section.has_condition || section.has_locale || !section.parts.empty())
{
throw std::runtime_error("color should be the first part of a format");
}
@ -528,9 +444,7 @@ void number_format_parser::finalize()
{
const auto &part = code.parts[i];
if (i > 0
&& i + 1 < code.parts.size()
&& part.type == template_part::template_type::text
if (i > 0 && i + 1 < code.parts.size() && part.type == template_part::template_type::text
&& part.string == "/"
&& code.parts[i - 1].placeholders.type == format_placeholders::placeholders_type::integer_part
&& code.parts[i + 1].placeholders.type == format_placeholders::placeholders_type::integer_part)
@ -584,10 +498,9 @@ void number_format_parser::finalize()
if ((next.type == template_part::template_type::second
|| next.type == template_part::template_type::second_leading_zero)
|| (next.type == template_part::template_type::text
&& next.string == ":"
&& (after_next.type == template_part::template_type::second ||
after_next.type == template_part::template_type::second_leading_zero)))
|| (next.type == template_part::template_type::text && next.string == ":"
&& (after_next.type == template_part::template_type::second
|| after_next.type == template_part::template_type::second_leading_zero)))
{
fix = true;
leading_zero = part.type == template_part::template_type::month_number_leading_zero;
@ -600,8 +513,7 @@ void number_format_parser::finalize()
const auto &previous = code.parts[i - 1];
const auto &before_previous = code.parts[i - 2];
if (previous.type == template_part::template_type::text
&& previous.string == ":"
if (previous.type == template_part::template_type::text && previous.string == ":"
&& (before_previous.type == template_part::template_type::hour_leading_zero
|| before_previous.type == template_part::template_type::hour))
{
@ -615,15 +527,13 @@ void number_format_parser::finalize()
if (fix)
{
code.parts[minutes_index].type = leading_zero ?
template_part::template_type::minute_leading_zero :
template_part::template_type::minute;
code.parts[minutes_index].type =
leading_zero ? template_part::template_type::minute_leading_zero : template_part::template_type::minute;
}
if (integer_part && !fractional_part)
{
code.parts[integer_part_index].placeholders.type =
format_placeholders::placeholders_type::integer_only;
code.parts[integer_part_index].placeholders.type = format_placeholders::placeholders_type::integer_only;
}
if (integer_part && fractional_part && percentage)
@ -654,11 +564,9 @@ void number_format_parser::finalize()
for (std::size_t i = 0; i < code.parts.size(); ++i)
{
if (code.parts[i].placeholders.type ==
format_placeholders::placeholders_type::integer_part)
if (code.parts[i].placeholders.type == format_placeholders::placeholders_type::integer_part)
{
code.parts[i].placeholders.type =
format_placeholders::placeholders_type::fraction_integer;
code.parts[i].placeholders.type = format_placeholders::placeholders_type::fraction_integer;
}
}
}
@ -707,8 +615,7 @@ number_format_token number_format_parser::parse_next_token()
do
{
token.string.push_back(format_string_[position_++]);
}
while (position_ < format_string_.size() && format_string_[position_] != ']');
} while (position_ < format_string_.size() && format_string_[position_] != ']');
if (token.string[0] == '<' || token.string[0] == '>' || token.string[0] == '=')
{
@ -718,10 +625,9 @@ number_format_token number_format_parser::parse_next_token()
{
token.type = number_format_token::token_type::locale;
}
else if (token.string.size() <= 2 &&
((token.string == "h" || token.string == "hh") ||
(token.string == "m" || token.string == "mm") ||
(token.string == "s" || token.string == "ss")))
else if (token.string.size() <= 2
&& ((token.string == "h" || token.string == "hh") || (token.string == "m" || token.string == "mm")
|| (token.string == "s" || token.string == "ss")))
{
token.type = number_format_token::token_type::datetime;
token.string = "[" + token.string + "]";
@ -776,8 +682,7 @@ number_format_token number_format_parser::parse_next_token()
{
token.string.push_back(current_char);
current_char = format_string_[position_++];
}
while (current_char == '0' || current_char == '#' || current_char == '?' || current_char == ',');
} while (current_char == '0' || current_char == '#' || current_char == '?' || current_char == ',');
--position_;
@ -930,9 +835,7 @@ void number_format_parser::validate()
if (codes_.size() > 2)
{
if (codes_[0].has_condition
&& codes_[1].has_condition
&& codes_[2].has_condition)
if (codes_[0].has_condition && codes_[1].has_condition && codes_[2].has_condition)
{
throw std::runtime_error("format should have a maximum of two codes with conditions");
}
@ -959,8 +862,7 @@ format_placeholders number_format_parser::parse_placeholders(const std::string &
}
else if (placeholders_string.front() == 'E')
{
p.type = placeholders_string[1] == '+'
? format_placeholders::placeholders_type::scientific_exponent_plus
p.type = placeholders_string[1] == '+' ? format_placeholders::placeholders_type::scientific_exponent_plus
: format_placeholders::placeholders_type::scientific_exponent_minus;
return p;
}
@ -1148,8 +1050,7 @@ std::pair<format_locale, std::string> number_format_parser::locale_from_string(c
}
number_formatter::number_formatter(const std::string &format_string, xlnt::calendar calendar)
: parser_(format_string),
calendar_(calendar)
: parser_(format_string), calendar_(calendar)
{
parser_.parse();
format_ = parser_.result();
@ -1169,8 +1070,7 @@ std::string number_formatter::format_number(long double number)
return std::string(11, '#');
}
if (!format_[1].has_condition
|| format_[1].condition.satisfied_by(number))
if (!format_[1].has_condition || format_[1].condition.satisfied_by(number))
{
return format_number(format_[1], number);
}
@ -1312,7 +1212,8 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
{
auto fractional_part = number - integer_part;
result = std::fabs(fractional_part) < std::numeric_limits<long double>::min()
? std::string(".") : std::to_string(fractional_part).substr(1);
? 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))
{
@ -1339,8 +1240,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo
}
std::string number_formatter::fill_scientific_placeholders(const format_placeholders &integer_part,
const format_placeholders &fractional_part, const format_placeholders &exponent_part,
long double number)
const format_placeholders &fractional_part, const format_placeholders &exponent_part, long double number)
{
std::size_t logarithm = 0;
@ -1433,34 +1333,11 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde
std::string number_formatter::format_number(const format_code &format, long double number)
{
static const std::vector<std::string> *month_names =
new std::vector<std::string>
{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
static const std::vector<std::string> *month_names = new std::vector<std::string>{"January", "February", "March",
"April", "May", "June", "July", "August", "September", "October", "November", "December"};
static const std::vector<std::string> *day_names =
new std::vector<std::string>
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
new std::vector<std::string>{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
std::string result;
@ -1527,7 +1404,8 @@ std::string number_formatter::format_number(const format_code &format, long doub
if (part.placeholders.type == format_placeholders::placeholders_type::fractional_part
&& (format.is_datetime || format.is_timedelta))
{
auto digits = std::min(static_cast<std::size_t>(6), part.placeholders.num_zeros + part.placeholders.num_optionals);
auto digits = std::min(
static_cast<std::size_t>(6), part.placeholders.num_zeros + part.placeholders.num_optionals);
auto denominator = static_cast<int>(std::pow(10.0, digits));
auto fractional_seconds = dt.microsecond / 1.0E6L * denominator;
fractional_seconds = std::round(fractional_seconds) / denominator;
@ -1550,9 +1428,11 @@ std::string number_formatter::format_number(const format_code &format, long doub
break;
}
result.append(fill_fraction_placeholders(part.placeholders, format.parts[i].placeholders, number, improper_fraction));
result.append(fill_fraction_placeholders(
part.placeholders, format.parts[i].placeholders, number, improper_fraction));
}
else if (part.placeholders.scientific && part.placeholders.type == format_placeholders::placeholders_type::integer_part)
else if (part.placeholders.scientific
&& part.placeholders.type == format_placeholders::placeholders_type::integer_part)
{
auto integer_part = part.placeholders;
++i;
@ -1683,7 +1563,8 @@ std::string number_formatter::format_number(const format_code &format, long doub
break;
case template_part::template_type::elapsed_seconds:
result.append(std::to_string(24 * 60 * 60 * static_cast<int>(number) + (60 * 60 * dt.hour) + (60 * dt.minute) + dt.second));
result.append(std::to_string(
24 * 60 * 60 * static_cast<int>(number) + (60 * 60 * dt.hour) + (60 * dt.minute) + dt.second));
break;
case template_part::template_type::month_letter:
@ -1739,32 +1620,58 @@ std::string number_formatter::format_text(const format_code &format, const std::
break;
case template_part::template_type::fill: break;
case template_part::template_type::space: break;
case template_part::template_type::month_number: break;
case template_part::template_type::month_number_leading_zero: break;
case template_part::template_type::month_abbreviation: break;
case template_part::template_type::month_name: break;
case template_part::template_type::month_letter: break;
case template_part::template_type::day_number: break;
case template_part::template_type::day_number_leading_zero: break;
case template_part::template_type::day_abbreviation: break;
case template_part::template_type::day_name: break;
case template_part::template_type::year_short: break;
case template_part::template_type::year_long: break;
case template_part::template_type::hour: break;
case template_part::template_type::hour_leading_zero: break;
case template_part::template_type::minute: break;
case template_part::template_type::minute_leading_zero: break;
case template_part::template_type::second: break;
case template_part::template_type::second_fractional: break;
case template_part::template_type::second_leading_zero: break;
case template_part::template_type::second_leading_zero_fractional: break;
case template_part::template_type::am_pm: break;
case template_part::template_type::a_p: break;
case template_part::template_type::elapsed_hours: break;
case template_part::template_type::elapsed_minutes: break;
case template_part::template_type::elapsed_seconds: break;
case template_part::template_type::fill:
break;
case template_part::template_type::space:
break;
case template_part::template_type::month_number:
break;
case template_part::template_type::month_number_leading_zero:
break;
case template_part::template_type::month_abbreviation:
break;
case template_part::template_type::month_name:
break;
case template_part::template_type::month_letter:
break;
case template_part::template_type::day_number:
break;
case template_part::template_type::day_number_leading_zero:
break;
case template_part::template_type::day_abbreviation:
break;
case template_part::template_type::day_name:
break;
case template_part::template_type::year_short:
break;
case template_part::template_type::year_long:
break;
case template_part::template_type::hour:
break;
case template_part::template_type::hour_leading_zero:
break;
case template_part::template_type::minute:
break;
case template_part::template_type::minute_leading_zero:
break;
case template_part::template_type::second:
break;
case template_part::template_type::second_fractional:
break;
case template_part::template_type::second_leading_zero:
break;
case template_part::template_type::second_leading_zero_fractional:
break;
case template_part::template_type::am_pm:
break;
case template_part::template_type::a_p:
break;
case template_part::template_type::elapsed_hours:
break;
case template_part::template_type::elapsed_minutes:
break;
case template_part::template_type::elapsed_seconds:
break;
}
}

View File

@ -23,13 +23,13 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <cassert>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <cassert>
#include <detail/pole.hpp>
@ -39,8 +39,7 @@
namespace {
// helper function: recursively find siblings of index
void dirtree_find_siblings( POLE::DirTree* dirtree, std::vector<std::size_t>& result,
std::size_t index )
void dirtree_find_siblings(POLE::DirTree *dirtree, std::vector<std::size_t> &result, std::size_t index)
{
auto e = dirtree->entry(index);
if (!e) return;
@ -71,12 +70,9 @@ void dirtree_find_siblings( POLE::DirTree* dirtree, std::vector<std::size_t>& re
if (next) dirtree_find_siblings(dirtree, result, next);
}
}
}
namespace POLE
{
namespace POLE {
} // namespace POLE
@ -106,13 +102,12 @@ static inline void writeU32( std::uint8_t* ptr, std::uint32_t data )
ptr[3] = static_cast<std::uint8_t>((data >> 24) & 0xff);
}
static const std::uint8_t pole_magic[] =
{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
static const std::uint8_t pole_magic[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
// =========== Header ==========
Header::Header():
b_shift( 9 ),
Header::Header()
: b_shift(9),
s_shift(6),
num_bat(0),
dirent_start(0),
@ -210,7 +205,8 @@ const std::uint32_t AllocTable::Eof = 0xfffffffe;
const std::uint32_t AllocTable::Bat = 0xfffffffd;
const std::uint32_t AllocTable::MetaBat = 0xfffffffc;
AllocTable::AllocTable(): blockSize( 4096 ), data()
AllocTable::AllocTable()
: blockSize(4096), data()
{
// initial size
resize(128);
@ -262,8 +258,7 @@ void AllocTable::setChain( std::vector<std::uint32_t> chain )
}
// TODO: optimize this with better search
static bool already_exist(const std::vector<std::size_t>& chain,
std::size_t item)
static bool already_exist(const std::vector<std::size_t> &chain, std::size_t item)
{
for (std::size_t i = 0; i < chain.size(); i++)
if (chain[i] == item) return true;
@ -297,8 +292,7 @@ std::size_t AllocTable::unused()
{
// find first available block
for (std::size_t i = 0; i < data.size(); i++)
if( data[i] == Avail )
return i;
if (data[i] == Avail) return i;
// completely full, so enlarge the table
std::size_t block = data.size();
@ -332,10 +326,14 @@ void AllocTable::debug()
{
if (data[i] == Avail) continue;
std::cout << i << ": ";
if( data[i] == Eof ) std::cout << "[eof]";
else if( data[i] == Bat ) std::cout << "[bat]";
else if( data[i] == MetaBat ) std::cout << "[metabat]";
else std::cout << data[i];
if (data[i] == Eof)
std::cout << "[eof]";
else if (data[i] == Bat)
std::cout << "[bat]";
else if (data[i] == MetaBat)
std::cout << "[metabat]";
else
std::cout << data[i];
std::cout << std::endl;
}
}
@ -344,7 +342,8 @@ void AllocTable::debug()
const std::uint32_t DirTree::End = 0xffffffff;
DirTree::DirTree(): entries()
DirTree::DirTree()
: entries()
{
clear();
}
@ -390,8 +389,7 @@ std::ptrdiff_t DirTree::parent( std::size_t index )
{
std::vector<std::size_t> chi = children(j);
for (std::size_t i = 0; i < chi.size(); i++)
if( chi[i] == index )
return static_cast<std::ptrdiff_t>(j);
if (chi[i] == index) return static_cast<std::ptrdiff_t>(j);
}
return -1;
@ -460,12 +458,12 @@ DirEntry* DirTree::entry( const std::string& name, bool create )
DirEntry *ce = entry(chi[i]);
if (ce)
if (ce->valid && (ce->name.length() > 1))
if( ce->name == *it )
child = static_cast<std::ptrdiff_t>(chi[i]);
if (ce->name == *it) child = static_cast<std::ptrdiff_t>(chi[i]);
}
// traverse to the child
if( child > 0 ) index = static_cast<std::size_t>(child);
if (child > 0)
index = static_cast<std::size_t>(child);
else
{
// not found among children
@ -496,8 +494,8 @@ std::vector<std::size_t> DirTree::children( std::size_t index )
std::vector<std::size_t> result;
DirEntry *e = entry(index);
if( e ) if( e->valid && e->child < entryCount() )
dirtree_find_siblings( this, result, e->child );
if (e)
if (e->valid && e->child < entryCount()) dirtree_find_siblings(this, result, e->child);
return result;
}
@ -580,8 +578,7 @@ void DirTree::save( std::uint8_t* buffer )
// max length for name is 32 chars
entry_name = e->name;
if( entry_name.length() > 32 )
entry_name.erase( 32, entry_name.length() );
if (entry_name.length() > 32) entry_name.erase(32, entry_name.length());
// write name as Unicode 16-bit
for (std::size_t j = 0; j < entry_name.length(); j++)
@ -607,16 +604,27 @@ void DirTree::debug()
std::cout << i << ": ";
if (!e->valid) std::cout << "INVALID ";
std::cout << e->name << " ";
if( e->dir ) std::cout << "(Dir) ";
else std::cout << "(File) ";
if (e->dir)
std::cout << "(Dir) ";
else
std::cout << "(File) ";
std::cout << e->size << " ";
std::cout << "s:" << e->start << " ";
std::cout << "(";
if( e->child == End ) std::cout << "-"; else std::cout << e->child;
if (e->child == End)
std::cout << "-";
else
std::cout << e->child;
std::cout << " ";
if( e->prev == End ) std::cout << "-"; else std::cout << e->prev;
if (e->prev == End)
std::cout << "-";
else
std::cout << e->prev;
std::cout << ":";
if( e->next == End ) std::cout << "-"; else std::cout << e->next;
if (e->next == End)
std::cout << "-";
else
std::cout << e->next;
std::cout << ")";
std::cout << std::endl;
}
@ -624,8 +632,8 @@ void DirTree::debug()
// =========== StorageIO ==========
StorageIO::StorageIO( Storage* st, char* bytes, std::size_t length ):
storage( st ),
StorageIO::StorageIO(Storage *st, char *bytes, std::size_t length)
: storage(st),
filedata(reinterpret_cast<std::uint8_t *>(bytes)),
dataLength(length),
result(Storage::Ok),
@ -688,8 +696,7 @@ void StorageIO::load()
// check OLE magic id
result = Storage::NotOLE;
for (std::size_t i = 0; i < 8; i++)
if( header->id[i] != pole_magic[i] )
return;
if (header->id[i] != pole_magic[i]) return;
// sanity checks
result = Storage::BadOLE;
@ -705,8 +712,10 @@ void StorageIO::load()
blocks.clear();
blocks.resize(header->num_bat);
for (std::size_t i = 0; i < 109; i++)
if( i >= header->num_bat ) break;
else blocks[i] = header->bb_blocks[i];
if (i >= header->num_bat)
break;
else
blocks[i] = header->bb_blocks[i];
if ((header->num_bat > 109) && (header->num_mbat > 0))
{
std::uint8_t *buffer2 = new std::uint8_t[bbat->blockSize];
@ -718,8 +727,10 @@ void StorageIO::load()
loadBigBlock(mblock, buffer2, bbat->blockSize);
for (std::size_t s = 0; s < bbat->blockSize - 4; s += 4)
{
if( k >= header->num_bat ) break;
else blocks[k++] = readU32( buffer2 + s );
if (k >= header->num_bat)
break;
else
blocks[k++] = readU32(buffer2 + s);
}
mblock = readU32(buffer2 + bbat->blockSize - 4);
}
@ -833,8 +844,7 @@ StreamIO* StorageIO::streamIO( const std::string& name )
return stream;
}
std::size_t StorageIO::loadBigBlocks( std::vector<std::size_t> blocks,
std::uint8_t* data, std::size_t maxlen )
std::size_t StorageIO::loadBigBlocks(std::vector<std::size_t> blocks, std::uint8_t *data, std::size_t maxlen)
{
// sentinel
if (!data) return 0;
@ -858,8 +868,7 @@ std::size_t StorageIO::loadBigBlocks( std::vector<std::size_t> blocks,
return bytes;
}
std::size_t StorageIO::loadBigBlock( std::size_t block,
std::uint8_t* data, std::size_t maxlen )
std::size_t StorageIO::loadBigBlock(std::size_t block, std::uint8_t *data, std::size_t maxlen)
{
// sentinel
if (!data) return 0;
@ -873,8 +882,7 @@ std::size_t StorageIO::loadBigBlock( std::size_t block,
}
// return number of bytes which has been read
std::size_t StorageIO::loadSmallBlocks( std::vector<std::size_t> blocks,
std::uint8_t* data, std::size_t maxlen )
std::size_t StorageIO::loadSmallBlocks(std::vector<std::size_t> blocks, std::uint8_t *data, std::size_t maxlen)
{
// sentinel
if (!data) return 0;
@ -910,8 +918,7 @@ std::size_t StorageIO::loadSmallBlocks( std::vector<std::size_t> blocks,
return bytes;
}
std::size_t StorageIO::loadSmallBlock( std::size_t block,
std::uint8_t* data, std::size_t maxlen )
std::size_t StorageIO::loadSmallBlock(std::size_t block, std::uint8_t *data, std::size_t maxlen)
{
// sentinel
if (!data) return 0;
@ -926,8 +933,8 @@ std::size_t StorageIO::loadSmallBlock( std::size_t block,
// =========== StreamIO ==========
StreamIO::StreamIO( StorageIO* s, DirEntry* e ):
io( s ),
StreamIO::StreamIO(StorageIO *s, DirEntry *e)
: io(s),
entry(e),
fullName(),
eof(false),
@ -970,9 +977,7 @@ int StreamIO::getch()
if (m_pos > entry->size) return -1;
// need to update cache ?
if( !cache_size || ( m_pos < cache_pos ) ||
( m_pos >= cache_pos + cache_size ) )
updateCache();
if (!cache_size || (m_pos < cache_pos) || (m_pos >= cache_pos + cache_size)) updateCache();
// something bad if we don't get good cache
if (!cache_size) return -1;
@ -1012,7 +1017,6 @@ std::size_t StreamIO::read( std::size_t pos, std::uint8_t* data, std::size_t max
index++;
}
delete[] buf;
}
else
{
@ -1035,7 +1039,6 @@ std::size_t StreamIO::read( std::size_t pos, std::uint8_t* data, std::size_t max
offset = 0;
}
delete[] buf;
}
return totalbytes;
@ -1059,11 +1062,10 @@ void StreamIO::updateCache()
cache_size = read(cache_pos, cache_data, bytes);
}
// =========== Storage ==========
Storage::Storage( char* bytes, std::size_t length ):
io( new StorageIO( this, bytes, length ) )
Storage::Storage(char *bytes, std::size_t length)
: io(new StorageIO(this, bytes, length))
{
}
@ -1114,7 +1116,6 @@ DirTree* Storage::dirTree()
return io->dirtree;
}
StorageIO *Storage::storageIO()
{
return io;
@ -1138,8 +1139,8 @@ std::list<DirEntry*> Storage::dirEntries( const std::string& path )
// =========== Stream ==========
Stream::Stream( Storage* storage, const std::string& name ):
io( storage->io->streamIO( name ) )
Stream::Stream(Storage *storage, const std::string &name)
: io(storage->io->streamIO(name))
{
}

View File

@ -31,6 +31,7 @@
#include <detail/worksheet_impl.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/utils/datetime.hpp>
#include <xlnt/workbook/calculation_properties.hpp>
#include <xlnt/workbook/theme.hpp>
#include <xlnt/workbook/workbook_view.hpp>
#include <xlnt/worksheet/range.hpp>
@ -44,7 +45,7 @@ struct worksheet_impl;
struct workbook_impl
{
workbook_impl() : active_sheet_index_(0)
workbook_impl() : base_date_(calendar::windows_1900)
{
}
@ -111,6 +112,7 @@ struct workbook_impl
};
optional<file_version_t> file_version_;
optional<calculation_properties> calculation_properties_;
};
} // namespace detail

View File

@ -24,18 +24,18 @@
#include <cctype>
#include <numeric> // for std::accumulate
#include <detail/constants.hpp>
#include <detail/custom_value_traits.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/workbook_impl.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/zip.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/utils/path.hpp>
#include <xlnt/workbook/const_worksheet_iterator.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <detail/constants.hpp>
#include <detail/custom_value_traits.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/workbook_impl.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/zip.hpp>
namespace std {
@ -245,14 +245,8 @@ std::array<xlnt::optional<xlnt::rich_text>, 3> parse_header_footer(const std::st
tokens.push_back(token);
}
const auto parse_section = [&tokens,&result](hf_code code)
{
std::vector<hf_code> end_codes
{
hf_code::left_section,
hf_code::center_section,
hf_code::right_section
};
const auto parse_section = [&tokens, &result](hf_code code) {
std::vector<hf_code> end_codes{hf_code::left_section, hf_code::center_section, hf_code::right_section};
end_codes.erase(std::find(end_codes.begin(), end_codes.end(), code));
@ -445,8 +439,8 @@ std::array<xlnt::optional<xlnt::rich_text>, 3> parse_header_footer(const std::st
current_text.add_run(current_run);
}
auto location_index = static_cast<std::size_t>(code == hf_code::left_section ? 0
: code == hf_code::center_section ? 1 : 2);
auto location_index =
static_cast<std::size_t>(code == hf_code::left_section ? 0 : code == hf_code::center_section ? 1 : 2);
if (!current_text.plain_text().empty())
{
@ -513,7 +507,7 @@ bool contains(const std::vector<T> &container, const T &element)
class parsing_context
{
public:
parsing_context(xlnt::detail::ZipFileReader &archive, const std::string &filename)
parsing_context(xlnt::detail::zip_file_reader &archive, const std::string &filename)
: parser_(stream_, filename)
{
}
@ -530,14 +524,13 @@ namespace xlnt {
namespace detail {
xlsx_consumer::xlsx_consumer(workbook &target)
: target_(target),
parser_(nullptr)
: target_(target), parser_(nullptr)
{
}
void xlsx_consumer::read(std::istream &source)
{
archive_.reset(new ZipFileReader(source));
archive_.reset(new zip_file_reader(source));
populate_workbook();
}
@ -548,15 +541,13 @@ xml::parser &xlsx_consumer::parser()
std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
{
auto part_rels_path = part.parent()
.append("_rels")
.append(part.filename() + ".rels")
.relative_to(path("/"));
auto part_rels_path = part.parent().append("_rels").append(part.filename() + ".rels").relative_to(path("/"));
std::vector<xlnt::relationship> relationships;
if (!archive_->has_file(part_rels_path.string())) return relationships;
if (!archive_->has_file(part_rels_path)) return relationships;
auto &rels_stream = archive_->open(part_rels_path.string());
auto rels_streambuf = archive_->open(part_rels_path);
std::istream rels_stream(rels_streambuf.get());
xml::parser parser(rels_stream, part_rels_path.string());
parser_ = &parser;
@ -577,10 +568,8 @@ std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
target_mode = parser.attribute<xlnt::target_mode>("TargetMode");
}
relationships.emplace_back(parser.attribute("Id"),
parser.attribute<xlnt::relationship_type>("Type"), source,
xlnt::uri(parser.attribute("Target")),
target_mode);
relationships.emplace_back(parser.attribute("Id"), parser.attribute<xlnt::relationship_type>("Type"), source,
xlnt::uri(parser.attribute("Target")), target_mode);
expect_end_element(xml::qname(xmlns, "Relationship"));
}
@ -592,18 +581,12 @@ std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
return relationships;
}
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
{
// ignore namespace declarations except in parts of these types
const auto using_namespaces = std::vector<relationship_type>
{
relationship_type::office_document,
relationship_type::stylesheet,
relationship_type::chartsheet,
relationship_type::dialogsheet,
relationship_type::worksheet
};
const auto using_namespaces =
std::vector<relationship_type>{relationship_type::office_document, relationship_type::stylesheet,
relationship_type::chartsheet, relationship_type::dialogsheet, relationship_type::worksheet};
auto receive = xml::parser::receive_default;
@ -614,8 +597,9 @@ void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
const auto &manifest = target_.manifest();
auto part_path = manifest.canonicalize(rel_chain);
auto &stream = archive_->open(part_path.string());
xml::parser parser(stream, part_path.string(), receive);
auto part_streambuf = archive_->open(part_path);
std::istream part_stream(part_streambuf.get());
xml::parser parser(part_stream, part_path.string(), receive);
parser_ = &parser;
switch (rel_chain.back().type())
@ -792,7 +776,9 @@ void xlsx_consumer::read_content_types()
static const auto &xmlns = constants::namespace_("content-types");
xml::parser parser(archive_->open("[Content_Types].xml"), "[Content_Types].xml");
auto content_types_streambuf = archive_->open(path("[Content_Types].xml"));
std::istream content_types_stream(content_types_streambuf.get());
xml::parser parser(content_types_stream, "[Content_Types].xml");
parser_ = &parser;
expect_start_element(xml::qname(xmlns, "Types"), xml::content::complex);
@ -854,8 +840,8 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
static const auto &xmlns_r = constants::namespace_("r");
static const auto &xmlns_s = constants::namespace_("spreadsheetml");
if (content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" &&
content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml")
if (content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
&& content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml")
{
throw xlnt::invalid_file(content_type);
}
@ -904,12 +890,12 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
{
if (parser().attribute_present("date1904"))
{
target_.base_date(is_true(parser().attribute("date1904"))
? calendar::mac_1904 : calendar::windows_1900);
target_.base_date(
is_true(parser().attribute("date1904")) ? calendar::mac_1904 : calendar::windows_1900);
}
skip_attributes({"codeName", "defaultThemeVersion",
"backupFile", "showObjects", "filterPrivacy", "dateCompatibility"});
skip_attributes(
{"codeName", "defaultThemeVersion", "backupFile", "showObjects", "filterPrivacy", "dateCompatibility"});
}
else if (current_workbook_element == xml::qname(xmlns, "workbookProtection")) // CT_WorkbookProtection 0-1
{
@ -921,8 +907,8 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
{
expect_start_element(xml::qname(xmlns, "workbookView"), xml::content::simple);
skip_attributes({"activeTab", "firstSheet", "showHorizontalScroll",
"showSheetTabs", "showVerticalScroll"});
skip_attributes(
{"activeTab", "firstSheet", "showHorizontalScroll", "showSheetTabs", "showVerticalScroll"});
workbook_view view;
view.x_window = parser().attribute<std::size_t>("xWindow");
@ -1503,8 +1489,8 @@ void xlsx_consumer::read_stylesheet()
throw xlnt::exception("counts don't match");
}
}
else if (current_style_element == xml::qname(xmlns, "cellStyleXfs") ||
current_style_element == xml::qname(xmlns, "cellXfs"))
else if (current_style_element == xml::qname(xmlns, "cellStyleXfs")
|| current_style_element == xml::qname(xmlns, "cellXfs"))
{
auto in_style_records = current_style_element.name() == "cellStyleXfs";
auto count = parser().attribute<std::size_t>("count");
@ -1513,42 +1499,35 @@ void xlsx_consumer::read_stylesheet()
{
expect_start_element(xml::qname(xmlns, "xf"), xml::content::complex);
auto &record = *(!in_style_records
? format_records.emplace(format_records.end())
auto &record = *(!in_style_records ? format_records.emplace(format_records.end())
: style_records.emplace(style_records.end()));
auto apply_alignment_present = parser().attribute_present("applyAlignment");
auto alignment_applied = apply_alignment_present
&& is_true(parser().attribute("applyAlignment"));
auto alignment_applied = apply_alignment_present && is_true(parser().attribute("applyAlignment"));
record.alignment.second = alignment_applied;
auto border_applied = parser().attribute_present("applyBorder")
&& is_true(parser().attribute("applyBorder"));
auto border_index = parser().attribute_present("borderId")
? parser().attribute<std::size_t>("borderId") : 0;
auto border_applied =
parser().attribute_present("applyBorder") && is_true(parser().attribute("applyBorder"));
auto border_index =
parser().attribute_present("borderId") ? parser().attribute<std::size_t>("borderId") : 0;
record.border_id = {border_index, border_applied};
auto fill_applied = parser().attribute_present("applyFill")
&& is_true(parser().attribute("applyFill"));
auto fill_index = parser().attribute_present("fillId")
? parser().attribute<std::size_t>("fillId") : 0;
auto fill_applied = parser().attribute_present("applyFill") && is_true(parser().attribute("applyFill"));
auto fill_index = parser().attribute_present("fillId") ? parser().attribute<std::size_t>("fillId") : 0;
record.fill_id = {fill_index, fill_applied};
auto font_applied = parser().attribute_present("applyFont")
&& is_true(parser().attribute("applyFont"));
auto font_index = parser().attribute_present("fontId")
? parser().attribute<std::size_t>("fontId") : 0;
auto font_applied = parser().attribute_present("applyFont") && is_true(parser().attribute("applyFont"));
auto font_index = parser().attribute_present("fontId") ? parser().attribute<std::size_t>("fontId") : 0;
record.font_id = {font_index, font_applied};
auto number_format_applied = parser().attribute_present("applyNumberFormat")
&& is_true(parser().attribute("applyNumberFormat"));
auto number_format_id = parser().attribute_present("numFmtId")
? parser().attribute<std::size_t>("numFmtId") : 0;
auto number_format_applied =
parser().attribute_present("applyNumberFormat") && is_true(parser().attribute("applyNumberFormat"));
auto number_format_id =
parser().attribute_present("numFmtId") ? parser().attribute<std::size_t>("numFmtId") : 0;
record.number_format_id = {number_format_id, number_format_applied};
auto apply_protection_present = parser().attribute_present("applyProtection");
auto protection_applied = apply_protection_present
&& is_true(parser().attribute("applyProtection"));
auto protection_applied = apply_protection_present && is_true(parser().attribute("applyProtection"));
record.protection.second = protection_applied;
if (parser().attribute_present("xfId") && parser().name() == "cellXfs")
@ -1617,8 +1596,8 @@ void xlsx_consumer::read_stylesheet()
expect_end_element(xml::qname(xmlns, "xf"));
}
if ((in_style_records && count != style_records.size()) ||
(!in_style_records && count != format_records.size()))
if ((in_style_records && count != style_records.size())
|| (!in_style_records && count != format_records.size()))
{
throw xlnt::exception("counts don't match");
}
@ -1703,8 +1682,7 @@ void xlsx_consumer::read_stylesheet()
expect_end_element(xml::qname(xmlns, "styleSheet"));
auto lookup_number_format = [&](std::size_t number_format_id)
{
auto lookup_number_format = [&](std::size_t number_format_id) {
auto result = number_format::general();
bool is_custom_number_format = false;
@ -1730,8 +1708,8 @@ void xlsx_consumer::read_stylesheet()
for (const auto &record : style_records)
{
auto style_data_iter = std::find_if(style_datas.begin(), style_datas.end(),
[&xf_id](const style_data &s) { return s.record_id == xf_id; });
auto style_data_iter = std::find_if(
style_datas.begin(), style_datas.end(), [&xf_id](const style_data &s) { return s.record_id == xf_id; });
++xf_id;
if (style_data_iter == style_datas.end()) continue;
@ -1814,16 +1792,16 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
static const auto &xmlns_x14ac = constants::namespace_("x14ac");
static const auto &xmlns_r = constants::namespace_("r");
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(),
target_.d_->sheet_title_rel_id_map_.end(),
[&](const std::pair<std::string, std::string> &p) { return p.second == rel_id; })->first;
auto title = std::find_if(target_.d_->sheet_title_rel_id_map_.begin(), target_.d_->sheet_title_rel_id_map_.end(),
[&](const std::pair<std::string, std::string> &p) {
return p.second == rel_id;
})->first;
auto id = sheet_title_id_map_[title];
auto index = sheet_title_index_map_[title];
auto insertion_iter = target_.d_->worksheets_.begin();
while (insertion_iter != target_.d_->worksheets_.end()
&& sheet_title_index_map_[insertion_iter->title_] < index)
while (insertion_iter != target_.d_->worksheets_.end() && sheet_title_index_map_[insertion_iter->title_] < index)
{
++insertion_iter;
}
@ -1915,13 +1893,13 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().attribute_present("view") && parser().attribute("view") != "normal")
{
new_view.type(parser().attribute("view") == "pageBreakPreview" ?sheet_view_type::page_break_preview : sheet_view_type::page_layout);
new_view.type(parser().attribute("view") == "pageBreakPreview" ? sheet_view_type::page_break_preview
: sheet_view_type::page_layout);
}
skip_attributes({"windowProtection", "showFormulas", "showRowColHeaders", "showZeros",
"rightToLeft", "tabSelected", "showRuler", "showOutlineSymbols", "showWhiteSpace", "view",
"topLeftCell", "colorId", "zoomScale", "zoomScaleNormal", "zoomScaleSheetLayoutView",
"zoomScalePageLayoutView"});
skip_attributes({"windowProtection", "showFormulas", "showRowColHeaders", "showZeros", "rightToLeft",
"tabSelected", "showRuler", "showOutlineSymbols", "showWhiteSpace", "view", "topLeftCell",
"colorId", "zoomScale", "zoomScaleNormal", "zoomScaleSheetLayoutView", "zoomScalePageLayoutView"});
while (in_element(xml::qname(xmlns, "sheetView")))
{
@ -2012,10 +1990,9 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
column_style = parser().attribute<std::size_t>("style");
}
auto custom = parser().attribute_present("customWidth")
? is_true(parser().attribute("customWidth")) : false;
auto hidden = parser().attribute_present("hidden")
? is_true(parser().attribute("hidden")) : false;
auto custom =
parser().attribute_present("customWidth") ? is_true(parser().attribute("customWidth")) : false;
auto hidden = parser().attribute_present("hidden") ? is_true(parser().attribute("hidden")) : false;
expect_end_element(xml::qname(xmlns, "col"));
@ -2062,8 +2039,8 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
}
skip_attributes({xml::qname(xmlns_x14ac, "dyDescent")});
skip_attributes({"customFormat", "s", "customFont", "outlineLevel",
"collapsed", "thickTop", "thickBot", "ph", "spans"});
skip_attributes({"customFormat", "s", "customFont", "outlineLevel", "collapsed", "thickTop", "thickBot",
"ph", "spans"});
while (in_element(xml::qname(xmlns, "row")))
{
@ -2101,8 +2078,8 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
has_shared_formula = parser().attribute("t") == "shared";
}
skip_attributes({"aca", "ref", "dt2D", "dtr", "del1", "del2",
"r1", "r2", "ca", "si", "bx"});
skip_attributes(
{"aca", "ref", "dt2D", "dtr", "del1", "del2", "r1", "r2", "ca", "si", "bx"});
formula_value_string = read_text();
}
@ -2270,14 +2247,14 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
{
header_footer hf;
hf.align_with_margins(!parser().attribute_present("alignWithMargins")
|| is_true(parser().attribute("alignWithMargins")));
hf.scale_with_doc(!parser().attribute_present("alignWithMargins")
|| is_true(parser().attribute("alignWithMargins")));
auto different_odd_even = parser().attribute_present("differentOddEven")
&& is_true(parser().attribute("differentOddEven"));
auto different_first = parser().attribute_present("differentFirst")
&& is_true(parser().attribute("differentFirst"));
hf.align_with_margins(
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins")));
hf.scale_with_doc(
!parser().attribute_present("alignWithMargins") || is_true(parser().attribute("alignWithMargins")));
auto different_odd_even =
parser().attribute_present("differentOddEven") && is_true(parser().attribute("differentOddEven"));
auto different_first =
parser().attribute_present("differentFirst") && is_true(parser().attribute("differentFirst"));
optional<std::array<optional<rich_text>, 3>> odd_header;
optional<std::array<optional<rich_text>, 3>> odd_footer;
@ -2325,19 +2302,18 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
for (std::size_t i = 0; i < 3; ++i)
{
auto loc = i == 0 ? header_footer::location::left
: i == 1 ? header_footer::location::center
: header_footer::location::right;
: i == 1 ? header_footer::location::center : header_footer::location::right;
if (different_odd_even)
{
if (odd_header.is_set() && odd_header.get().at(i).is_set()
&& even_header.is_set() && even_header.get().at(i).is_set())
if (odd_header.is_set() && odd_header.get().at(i).is_set() && even_header.is_set()
&& even_header.get().at(i).is_set())
{
hf.odd_even_header(loc, odd_header.get().at(i).get(), even_header.get().at(i).get());
}
if (odd_footer.is_set() && odd_footer.get().at(i).is_set()
&& even_footer.is_set() && even_footer.get().at(i).is_set())
if (odd_footer.is_set() && odd_footer.get().at(i).is_set() && even_footer.is_set()
&& even_footer.get().at(i).is_set())
{
hf.odd_even_footer(loc, odd_footer.get().at(i).get(), even_footer.get().at(i).get());
}
@ -2357,7 +2333,6 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (different_first)
{
}
}
@ -2366,7 +2341,9 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
else if (current_worksheet_element == xml::qname(xmlns, "rowBreaks")) // CT_PageBreak 0-1
{
auto count = parser().attribute_present("count") ? parser().attribute<std::size_t>("count") : 0;
auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute<std::size_t>("manualBreakCount") : 0;
auto manual_break_count = parser().attribute_present("manualBreakCount")
? parser().attribute<std::size_t>("manualBreakCount")
: 0;
while (in_element(xml::qname(xmlns, "rowBreaks")))
{
@ -2374,7 +2351,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().attribute_present("id"))
{
ws.row_breaks().push_back(parser().attribute<row_t>("id"));
ws.page_break_at_row(parser().attribute<row_t>("id"));
--count;
}
@ -2390,7 +2367,9 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
else if (current_worksheet_element == xml::qname(xmlns, "colBreaks")) // CT_PageBreak 0-1
{
auto count = parser().attribute_present("count") ? parser().attribute<std::size_t>("count") : 0;
auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute<std::size_t>("manualBreakCount") : 0;
auto manual_break_count = parser().attribute_present("manualBreakCount")
? parser().attribute<std::size_t>("manualBreakCount")
: 0;
while (in_element(xml::qname(xmlns, "colBreaks")))
{
@ -2398,7 +2377,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
if (parser().attribute_present("id"))
{
ws.column_breaks().push_back(parser().attribute<column_t::index_t>("id"));
ws.page_break_at_column(parser().attribute<column_t::index_t>("id"));
--count;
}
@ -2455,17 +2434,21 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id)
{workbook_rel, sheet_rel, manifest.relationship(sheet_path, xlnt::relationship_type::comments)});
auto receive = xml::parser::receive_default;
xml::parser parser(archive_->open(comments_part.string()), comments_part.string(), receive);
auto comments_part_streambuf = archive_->open(comments_part);
std::istream comments_part_stream(comments_part_streambuf.get());
xml::parser parser(comments_part_stream, comments_part.string(), receive);
parser_ = &parser;
read_comments(ws);
if (manifest.has_relationship(sheet_path, xlnt::relationship_type::vml_drawing))
{
auto vml_drawings_part = manifest.canonicalize({workbook_rel, sheet_rel,
manifest.relationship(sheet_path, xlnt::relationship_type::vml_drawing)});
auto vml_drawings_part = manifest.canonicalize(
{workbook_rel, sheet_rel, manifest.relationship(sheet_path, xlnt::relationship_type::vml_drawing)});
xml::parser vml_parser(archive_->open(vml_drawings_part.string()), vml_drawings_part.string(), receive);
auto vml_drawings_part_streambuf = archive_->open(comments_part);
std::istream vml_drawings_part_stream(comments_part_streambuf.get());
xml::parser vml_parser(vml_drawings_part_stream, vml_drawings_part.string(), receive);
parser_ = &vml_parser;
read_vml_drawings(ws);
@ -2533,10 +2516,10 @@ void xlsx_consumer::read_unknown_relationships()
void xlsx_consumer::read_image(const xlnt::path &image_path)
{
auto &in_stream = archive_->open(image_path.string());
auto image_streambuf = archive_->open(image_path);
vector_ostreambuf buffer(target_.d_->images_[image_path.string()]);
std::ostream out_stream(&buffer);
out_stream << in_stream.rdbuf();
out_stream << image_streambuf.get();
}
std::string xlsx_consumer::read_text()
@ -2648,8 +2631,7 @@ xml::qname xlsx_consumer::expect_start_element(xml::content content)
stack_.push_back(parser().qname());
const auto xml_space = xml::qname(constants::namespace_("xml"), "space");
preserve_space_ = parser().attribute_present(xml_space)
? parser().attribute(xml_space) == "preserve" : false;
preserve_space_ = parser().attribute_present(xml_space) ? parser().attribute(xml_space) == "preserve" : false;
return stack_.back();
}
@ -2661,8 +2643,7 @@ void xlsx_consumer::expect_start_element(const xml::qname &name, xml::content co
stack_.push_back(name);
const auto xml_space = xml::qname(constants::namespace_("xml"), "space");
preserve_space_ = parser().attribute_present(xml_space)
? parser().attribute(xml_space) == "preserve" : false;
preserve_space_ = parser().attribute_present(xml_space) ? parser().attribute(xml_space) == "preserve" : false;
}
void xlsx_consumer::expect_end_element(const xml::qname &name)
@ -2731,7 +2712,8 @@ rich_text xlsx_consumer::read_rich_text(const xml::qname &parent)
}
else if (current_run_property_element == xml::qname(xmlns, "b"))
{
run.second.get().bold(parser().attribute_present("val") ? is_true(parser().attribute("val")) : true);
run.second.get().bold(
parser().attribute_present("val") ? is_true(parser().attribute("val")) : true);
}
else if (current_run_property_element == xml::qname(xmlns, "u"))
{
@ -2789,7 +2771,6 @@ rich_text xlsx_consumer::read_rich_text(const xml::qname &parent)
return t;
}
xlnt::color xlsx_consumer::read_color()
{
xlnt::color result;

View File

@ -45,7 +45,7 @@ class worksheet;
namespace detail {
class ZipFileReader;
class zip_file_reader;
/// <summary>
/// Handles writing a workbook into an XLSX file.
@ -338,7 +338,7 @@ private:
/// <summary>
/// The ZIP file containing the files that make up the OOXML package.
/// </summary>
std::unique_ptr<ZipFileReader> archive_;
std::unique_ptr<zip_file_reader> archive_;
/// <summary>
/// Map of sheet titles to relationship IDs.

View File

@ -23,6 +23,8 @@
#include <array>
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <detail/constants.hpp>
#include <detail/include_cryptopp.hpp>
#include <detail/include_libstudxml.hpp>
@ -30,8 +32,6 @@
#include <detail/vector_streambuf.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/workbook/workbook.hpp>
namespace xlnt {
namespace detail {
@ -60,16 +60,26 @@ struct value_traits<xlnt::detail::hash_algorithm>
{
static xlnt::detail::hash_algorithm parse(std::string hash_algorithm_string, const parser &)
{
if (hash_algorithm_string == "SHA1") return xlnt::detail::hash_algorithm::sha1;
else if (hash_algorithm_string == "SHA256") return xlnt::detail::hash_algorithm::sha256;
else if (hash_algorithm_string == "SHA384") return xlnt::detail::hash_algorithm::sha384;
else if (hash_algorithm_string == "SHA512") return xlnt::detail::hash_algorithm::sha512;
else if (hash_algorithm_string == "MD5") return xlnt::detail::hash_algorithm::md5;
else if (hash_algorithm_string == "MD4") return xlnt::detail::hash_algorithm::md4;
else if (hash_algorithm_string == "MD2") return xlnt::detail::hash_algorithm::md2;
else if (hash_algorithm_string == "Ripemd128") return xlnt::detail::hash_algorithm::ripemd128;
else if (hash_algorithm_string == "Ripemd160") return xlnt::detail::hash_algorithm::ripemd160;
else if (hash_algorithm_string == "Whirlpool") return xlnt::detail::hash_algorithm::whirlpool;
if (hash_algorithm_string == "SHA1")
return xlnt::detail::hash_algorithm::sha1;
else if (hash_algorithm_string == "SHA256")
return xlnt::detail::hash_algorithm::sha256;
else if (hash_algorithm_string == "SHA384")
return xlnt::detail::hash_algorithm::sha384;
else if (hash_algorithm_string == "SHA512")
return xlnt::detail::hash_algorithm::sha512;
else if (hash_algorithm_string == "MD5")
return xlnt::detail::hash_algorithm::md5;
else if (hash_algorithm_string == "MD4")
return xlnt::detail::hash_algorithm::md4;
else if (hash_algorithm_string == "MD2")
return xlnt::detail::hash_algorithm::md2;
else if (hash_algorithm_string == "Ripemd128")
return xlnt::detail::hash_algorithm::ripemd128;
else if (hash_algorithm_string == "Ripemd160")
return xlnt::detail::hash_algorithm::ripemd160;
else if (hash_algorithm_string == "Whirlpool")
return xlnt::detail::hash_algorithm::whirlpool;
throw xlnt::exception(hash_algorithm_string);
}
@ -77,16 +87,26 @@ struct value_traits<xlnt::detail::hash_algorithm>
{
switch (algorithm)
{
case xlnt::detail::hash_algorithm::sha1: return "SHA1";
case xlnt::detail::hash_algorithm::sha256: return "SHA256";
case xlnt::detail::hash_algorithm::sha384: return "SHA384";
case xlnt::detail::hash_algorithm::sha512: return "SHA512";
case xlnt::detail::hash_algorithm::md5: return "MD5";
case xlnt::detail::hash_algorithm::md4: return "MD4";
case xlnt::detail::hash_algorithm::md2: return "MD2";
case xlnt::detail::hash_algorithm::ripemd128: return "Ripemd128";
case xlnt::detail::hash_algorithm::ripemd160: return "Ripemd160";
case xlnt::detail::hash_algorithm::whirlpool: return "Whirlpool";
case xlnt::detail::hash_algorithm::sha1:
return "SHA1";
case xlnt::detail::hash_algorithm::sha256:
return "SHA256";
case xlnt::detail::hash_algorithm::sha384:
return "SHA384";
case xlnt::detail::hash_algorithm::sha512:
return "SHA512";
case xlnt::detail::hash_algorithm::md5:
return "MD5";
case xlnt::detail::hash_algorithm::md4:
return "MD4";
case xlnt::detail::hash_algorithm::md2:
return "MD2";
case xlnt::detail::hash_algorithm::ripemd128:
return "Ripemd128";
case xlnt::detail::hash_algorithm::ripemd160:
return "Ripemd160";
case xlnt::detail::hash_algorithm::whirlpool:
return "Whirlpool";
}
}
}; // struct value_traits<>
@ -124,10 +144,8 @@ struct crypto_helper
decryption
};
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> &source,
cipher_chaining chaining, cipher_direction direction)
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> &source, cipher_chaining chaining, cipher_direction direction)
{
std::vector<std::uint8_t> destination(source.size(), 0);
@ -136,8 +154,8 @@ struct crypto_helper
CryptoPP::AES::Encryption aesEncryption(key.data(), key.size());
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv.data());
CryptoPP::ArraySource as(source.data(), source.size(), true,
new CryptoPP::StreamTransformationFilter(cbcEncryption,
CryptoPP::ArraySource as(
source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcEncryption,
new CryptoPP::ArraySink(destination.data(), destination.size()),
CryptoPP::BlockPaddingSchemeDef::NO_PADDING));
}
@ -146,8 +164,8 @@ struct crypto_helper
CryptoPP::AES::Decryption aesDecryption(key.data(), key.size());
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
CryptoPP::ArraySource as(source.data(), source.size(), true,
new CryptoPP::StreamTransformationFilter(cbcDecryption,
CryptoPP::ArraySource as(
source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcDecryption,
new CryptoPP::ArraySink(destination.data(), destination.size()),
CryptoPP::BlockPaddingSchemeDef::NO_PADDING));
}
@ -156,8 +174,8 @@ struct crypto_helper
CryptoPP::AES::Encryption aesEncryption(key.data(), key.size());
CryptoPP::ECB_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv.data());
CryptoPP::ArraySource as(source.data(), source.size(), true,
new CryptoPP::StreamTransformationFilter(cbcEncryption,
CryptoPP::ArraySource as(
source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcEncryption,
new CryptoPP::ArraySink(destination.data(), destination.size()),
CryptoPP::BlockPaddingSchemeDef::NO_PADDING));
}
@ -166,8 +184,8 @@ struct crypto_helper
CryptoPP::AES::Decryption aesDecryption(key.data(), key.size());
CryptoPP::ECB_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
CryptoPP::ArraySource as(source.data(), source.size(), true,
new CryptoPP::StreamTransformationFilter(cbcDecryption,
CryptoPP::ArraySource as(
source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcDecryption,
new CryptoPP::ArraySink(destination.data(), destination.size()),
CryptoPP::BlockPaddingSchemeDef::NO_PADDING));
}
@ -199,8 +217,7 @@ struct crypto_helper
return std::string(encoded.begin(), encoded.end());
}
static std::vector<std::uint8_t> hash(hash_algorithm algorithm,
const std::vector<std::uint8_t> &input)
static std::vector<std::uint8_t> hash(hash_algorithm algorithm, const std::vector<std::uint8_t> &input)
{
std::vector<std::uint8_t> digest;
@ -300,7 +317,8 @@ struct crypto_helper
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() + static_cast<std::ptrdiff_t>(offset))),
reinterpret_cast<const std::uint16_t *>(&*(encryption_info.begin() + static_cast<std::ptrdiff_t>(offset + csp_name_length))));
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")
@ -329,11 +347,8 @@ struct crypto_helper
// H_0 = H(salt + password)
auto salt_plus_password = salt;
std::vector<std::uint16_t> password_wide(password.begin(), password.end());
std::for_each(password_wide.begin(), password_wide.end(),
[&salt_plus_password](std::uint16_t c)
{
salt_plus_password.insert(salt_plus_password.end(),
reinterpret_cast<char *>(&c),
std::for_each(password_wide.begin(), password_wide.end(), [&salt_plus_password](std::uint16_t c) {
salt_plus_password.insert(salt_plus_password.end(), reinterpret_cast<char *>(&c),
reinterpret_cast<char *>(&c) + sizeof(std::uint16_t));
});
std::vector<std::uint8_t> h_0 = hash(info.hash, salt_plus_password);
@ -352,8 +367,7 @@ struct crypto_helper
// H_final = H(H_n + block)
auto h_n_plus_block = h_n;
const std::uint32_t block_number = 0;
h_n_plus_block.insert(h_n_plus_block.end(),
reinterpret_cast<const std::uint8_t *>(&block_number),
h_n_plus_block.insert(h_n_plus_block.end(), reinterpret_cast<const std::uint8_t *>(&block_number),
reinterpret_cast<const std::uint8_t *>(&block_number) + sizeof(std::uint32_t));
auto h_final = hash(info.hash, h_n_plus_block);
@ -376,14 +390,15 @@ struct crypto_helper
auto X3 = X1;
X3.insert(X3.end(), X2.begin(), X2.end());
auto key_derived = std::vector<std::uint8_t>(X3.begin(), X3.begin() + static_cast<std::ptrdiff_t>(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
std::size_t package_offset = 0;
auto decrypted_size = static_cast<std::size_t>(read_int<std::uint64_t>(package_offset, encrypted_package));
auto decrypted = aes(key_derived, {}, std::vector<std::uint8_t>(
encrypted_package.begin() + 8, encrypted_package.end()),
auto decrypted =
aes(key_derived, {}, std::vector<std::uint8_t>(encrypted_package.begin() + 8, encrypted_package.end()),
cipher_chaining::ecb, cipher_direction::decryption);
decrypted.resize(decrypted_size);
@ -558,8 +573,10 @@ struct crypto_helper
}
result.key_encryptor.salt_value = decode_base64(parser.attribute("saltValue"));
result.key_encryptor.verifier_hash_input = decode_base64(parser.attribute("encryptedVerifierHashInput"));
result.key_encryptor.verifier_hash_value = decode_base64(parser.attribute("encryptedVerifierHashValue"));
result.key_encryptor.verifier_hash_input =
decode_base64(parser.attribute("encryptedVerifierHashInput"));
result.key_encryptor.verifier_hash_value =
decode_base64(parser.attribute("encryptedVerifierHashValue"));
result.key_encryptor.encrypted_key_value = decode_base64(parser.attribute("encryptedKeyValue"));
}
else
@ -580,18 +597,14 @@ struct crypto_helper
parser.next_expect(xml::parser::event_type::end_element, xmlns, "encryption");
// begin key generation algorithm
// H_0 = H(salt + password)
auto salt_plus_password = result.key_encryptor.salt_value;
std::vector<std::uint16_t> password_wide(password.begin(), password.end());
std::for_each(password_wide.begin(), password_wide.end(),
[&salt_plus_password](std::uint16_t c)
{
salt_plus_password.insert(salt_plus_password.end(),
reinterpret_cast<char *>(&c),
std::for_each(password_wide.begin(), password_wide.end(), [&salt_plus_password](std::uint16_t c) {
salt_plus_password.insert(salt_plus_password.end(), reinterpret_cast<char *>(&c),
reinterpret_cast<char *>(&c) + sizeof(std::uint16_t));
});
@ -611,43 +624,36 @@ struct crypto_helper
static const std::size_t block_size = 8;
auto calculate_block = [&result](
const std::vector<std::uint8_t> &raw_key,
const std::array<std::uint8_t, block_size> &block,
const std::vector<std::uint8_t> &encrypted)
{
auto calculate_block = [&result](const std::vector<std::uint8_t> &raw_key,
const std::array<std::uint8_t, block_size> &block, const std::vector<std::uint8_t> &encrypted) {
auto combined = raw_key;
combined.insert(combined.end(), block.begin(), block.end());
auto key = hash(result.key_encryptor.hash, combined);
key.resize(result.key_encryptor.key_bits / 8);
return aes(key, result.key_encryptor.salt_value, encrypted,
cipher_chaining::cbc, cipher_direction::decryption);
return aes(
key, result.key_encryptor.salt_value, encrypted, cipher_chaining::cbc, cipher_direction::decryption);
};
const std::array<std::uint8_t, block_size> input_block_key
= { {0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79} };
auto hash_input = calculate_block(h_n, input_block_key,
result.key_encryptor.verifier_hash_input);
const std::array<std::uint8_t, block_size> input_block_key = {{0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79}};
auto hash_input = calculate_block(h_n, input_block_key, result.key_encryptor.verifier_hash_input);
auto calculated_verifier = hash(result.key_encryptor.hash, hash_input);
const std::array<std::uint8_t, block_size> verifier_block_key
= { {0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e} };
auto expected_verifier = calculate_block(h_n, verifier_block_key,
result.key_encryptor.verifier_hash_value);
const std::array<std::uint8_t, block_size> verifier_block_key = {
{0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e}};
auto expected_verifier = calculate_block(h_n, verifier_block_key, result.key_encryptor.verifier_hash_value);
expected_verifier.resize(calculated_verifier.size());
if (calculated_verifier.size() != expected_verifier.size()
|| std::mismatch(calculated_verifier.begin(), calculated_verifier.end(),
expected_verifier.begin(), expected_verifier.end())
|| std::mismatch(calculated_verifier.begin(), calculated_verifier.end(), expected_verifier.begin(),
expected_verifier.end())
!= std::make_pair(calculated_verifier.end(), expected_verifier.end()))
{
throw xlnt::exception("bad password");
}
const std::array<std::uint8_t, block_size> key_value_block_key
= { {0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6} };
auto key = calculate_block(h_n, key_value_block_key,
result.key_encryptor.encrypted_key_value);
const std::array<std::uint8_t, block_size> key_value_block_key = {
{0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6}};
auto key = calculate_block(h_n, key_value_block_key, result.key_encryptor.encrypted_key_value);
auto salt_size = result.key_data.salt_size;
auto salt_with_block_key = result.key_data.salt_value;
@ -667,15 +673,13 @@ struct crypto_helper
auto segment_begin = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i);
auto current_segment_length = std::min(segment_length, encrypted_package.size() - i);
auto segment_end = encrypted_package.begin()
+ static_cast<std::ptrdiff_t>(i + current_segment_length);
auto segment_end = encrypted_package.begin() + static_cast<std::ptrdiff_t>(i + current_segment_length);
encrypted_segment.assign(segment_begin, segment_end);
auto decrypted_segment = aes(key, iv, encrypted_segment,
cipher_chaining::cbc, cipher_direction::decryption);
auto decrypted_segment =
aes(key, iv, encrypted_segment, cipher_chaining::cbc, cipher_direction::decryption);
decrypted_segment.resize(current_segment_length);
decrypted_package.insert(decrypted_package.end(),
decrypted_segment.begin(), decrypted_segment.end());
decrypted_package.insert(decrypted_package.end(), decrypted_segment.begin(), decrypted_segment.end());
++segment;
}
@ -710,8 +714,7 @@ struct crypto_helper
auto encryption_flags = read_int<std::uint32_t>(index, encryption_info);
// get rid of header
encryption_info.erase(encryption_info.begin(),
encryption_info.begin() + static_cast<std::ptrdiff_t>(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)
@ -725,8 +728,7 @@ struct crypto_helper
}
// not agile, only try to decrypt versions 3.2 and 4.2
if (version_minor != 2
|| (version_major != 2 && version_major != 3 && version_major != 4))
if (version_minor != 2 || (version_major != 2 && version_major != 3 && version_major != 4))
{
throw xlnt::exception("unsupported encryption version");
}
@ -767,8 +769,7 @@ const std::size_t crypto_helper::segment_length = 4096;
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>()));
std::vector<std::uint8_t> data((std::istreambuf_iterator<char>(source)), (std::istreambuf_iterator<char>()));
const auto decrypted = crypto_helper::decrypt_xlsx(data, password);
vector_istreambuf decrypted_buffer(decrypted);
std::istream decrypted_stream(&decrypted_buffer);

View File

@ -24,20 +24,20 @@
#include <numeric> // for std::accumulate
#include <string>
#include <xlnt/cell/cell.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/utils/path.hpp>
#include <xlnt/workbook/const_worksheet_iterator.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/workbook/workbook_view.hpp>
#include <xlnt/worksheet/header_footer.hpp>
#include <xlnt/worksheet/worksheet.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>
#include <xlnt/workbook/const_worksheet_iterator.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/workbook/workbook_view.hpp>
#include <xlnt/worksheet/header_footer.hpp>
#include <xlnt/worksheet/worksheet.hpp>
using namespace std::string_literals;
@ -56,13 +56,15 @@ bool is_integral(long double d)
namespace xlnt {
namespace detail {
xlsx_producer::xlsx_producer(const workbook &target) : source_(target)
xlsx_producer::xlsx_producer(const workbook &target)
: source_(target),
current_part_stream_(nullptr)
{
}
void xlsx_producer::write(std::ostream &destination)
{
ZipFileWriter archive(destination);
zip_file_writer archive(destination);
archive_ = &archive;
populate_archive();
}
@ -105,37 +107,68 @@ void xlsx_producer::populate_archive()
write_workbook(rel);
break;
case relationship_type::thumbnail: break;
case relationship_type::calculation_chain: break;
case relationship_type::worksheet: break;
case relationship_type::shared_string_table: break;
case relationship_type::stylesheet: break;
case relationship_type::theme: break;
case relationship_type::hyperlink: break;
case relationship_type::chartsheet: break;
case relationship_type::comments: break;
case relationship_type::vml_drawing: break;
case relationship_type::unknown: break;
case relationship_type::printer_settings: break;
case relationship_type::connections: break;
case relationship_type::custom_property: break;
case relationship_type::custom_xml_mappings: break;
case relationship_type::dialogsheet: break;
case relationship_type::drawings: break;
case relationship_type::external_workbook_references: break;
case relationship_type::metadata: break;
case relationship_type::pivot_table: break;
case relationship_type::pivot_table_cache_definition: break;
case relationship_type::pivot_table_cache_records: break;
case relationship_type::query_table: break;
case relationship_type::shared_workbook_revision_headers: break;
case relationship_type::shared_workbook: break;
case relationship_type::revision_log: break;
case relationship_type::shared_workbook_user_data: break;
case relationship_type::single_cell_table_definitions: break;
case relationship_type::table_definition: break;
case relationship_type::volatile_dependencies: break;
case relationship_type::image: break;
case relationship_type::thumbnail:
break;
case relationship_type::calculation_chain:
break;
case relationship_type::worksheet:
break;
case relationship_type::shared_string_table:
break;
case relationship_type::stylesheet:
break;
case relationship_type::theme:
break;
case relationship_type::hyperlink:
break;
case relationship_type::chartsheet:
break;
case relationship_type::comments:
break;
case relationship_type::vml_drawing:
break;
case relationship_type::unknown:
break;
case relationship_type::printer_settings:
break;
case relationship_type::connections:
break;
case relationship_type::custom_property:
break;
case relationship_type::custom_xml_mappings:
break;
case relationship_type::dialogsheet:
break;
case relationship_type::drawings:
break;
case relationship_type::external_workbook_references:
break;
case relationship_type::metadata:
break;
case relationship_type::pivot_table:
break;
case relationship_type::pivot_table_cache_definition:
break;
case relationship_type::pivot_table_cache_records:
break;
case relationship_type::query_table:
break;
case relationship_type::shared_workbook_revision_headers:
break;
case relationship_type::shared_workbook:
break;
case relationship_type::revision_log:
break;
case relationship_type::shared_workbook_user_data:
break;
case relationship_type::single_cell_table_definitions:
break;
case relationship_type::table_definition:
break;
case relationship_type::volatile_dependencies:
break;
case relationship_type::image:
break;
}
}
@ -154,13 +187,15 @@ void xlsx_producer::end_part()
current_part_serializer_.reset();
}
archive_->close();
current_part_streambuf_.reset();
}
void xlsx_producer::begin_part(const path &part)
{
end_part();
current_part_serializer_.reset(new xml::serializer(archive_->open(part.string()), part.string()));
current_part_streambuf_ = archive_->open(part);
current_part_stream_.rdbuf(current_part_streambuf_.get());
current_part_serializer_.reset(new xml::serializer(current_part_stream_, part.string()));
}
// Package Parts
@ -179,8 +214,7 @@ void xlsx_producer::write_content_types()
{
serializer().start_element(xmlns, "Default");
serializer().attribute("Extension", extension);
serializer().attribute("ContentType",
source_.manifest().default_type(extension));
serializer().attribute("ContentType", source_.manifest().default_type(extension));
serializer().end_element(xmlns, "Default");
}
@ -188,8 +222,7 @@ void xlsx_producer::write_content_types()
{
serializer().start_element(xmlns, "Override");
serializer().attribute("PartName", part.resolve(path("/")).string());
serializer().attribute("ContentType",
source_.manifest().override_type(part));
serializer().attribute("ContentType", source_.manifest().override_type(part));
serializer().end_element(xmlns, "Override");
}
@ -468,8 +501,8 @@ void xlsx_producer::write_workbook(const relationship &rel)
serializer().attribute("name", "_xlnm._FilterDatabase");
serializer().attribute("hidden", write_bool(true));
serializer().attribute("localSheetId", "0");
serializer().characters("'" + ws.title() + "'!"
+ range_reference::make_absolute(ws.auto_filter()).to_string());
serializer().characters(
"'" + ws.title() + "'!" + range_reference::make_absolute(ws.auto_filter()).to_string());
serializer().end_element(xmlns, "definedName");
}
@ -480,12 +513,15 @@ void xlsx_producer::write_workbook(const relationship &rel)
serializer().end_element(xmlns, "sheets");
if (source_.has_calculation_properties())
{
serializer().start_element(xmlns, "calcPr");
serializer().attribute("calcId", 150000);
serializer().attribute("calcMode", "auto");
serializer().attribute("fullCalcOnLoad", "1");
serializer().attribute("concurrentCalc", "0");
serializer().end_element(xmlns, "calcPr");
}
if (!source_.named_ranges().empty())
{
@ -497,8 +533,7 @@ void xlsx_producer::write_workbook(const relationship &rel)
serializer().namespace_decl(xmlns_s, "s");
serializer().attribute("name", named_range.name());
const auto &target = named_range.targets().front();
serializer().characters("'" + target.first.title()
+ "\'!" + target.second.to_string());
serializer().characters("'" + target.first.title() + "\'!" + target.second.to_string());
serializer().end_element(xmlns_s, "definedName");
}
@ -573,27 +608,48 @@ void xlsx_producer::write_workbook(const relationship &rel)
write_worksheet(child_rel);
break;
case relationship_type::office_document: break;
case relationship_type::thumbnail: break;
case relationship_type::extended_properties: break;
case relationship_type::core_properties: break;
case relationship_type::hyperlink: break;
case relationship_type::comments: break;
case relationship_type::vml_drawing: break;
case relationship_type::unknown: break;
case relationship_type::custom_properties: break;
case relationship_type::printer_settings: break;
case relationship_type::custom_property: break;
case relationship_type::drawings: break;
case relationship_type::pivot_table_cache_definition: break;
case relationship_type::pivot_table_cache_records: break;
case relationship_type::query_table: break;
case relationship_type::shared_workbook: break;
case relationship_type::revision_log: break;
case relationship_type::shared_workbook_user_data: break;
case relationship_type::single_cell_table_definitions: break;
case relationship_type::table_definition: break;
case relationship_type::image: break;
case relationship_type::office_document:
break;
case relationship_type::thumbnail:
break;
case relationship_type::extended_properties:
break;
case relationship_type::core_properties:
break;
case relationship_type::hyperlink:
break;
case relationship_type::comments:
break;
case relationship_type::vml_drawing:
break;
case relationship_type::unknown:
break;
case relationship_type::custom_properties:
break;
case relationship_type::printer_settings:
break;
case relationship_type::custom_property:
break;
case relationship_type::drawings:
break;
case relationship_type::pivot_table_cache_definition:
break;
case relationship_type::pivot_table_cache_records:
break;
case relationship_type::query_table:
break;
case relationship_type::shared_workbook:
break;
case relationship_type::revision_log:
break;
case relationship_type::shared_workbook_user_data:
break;
case relationship_type::single_cell_table_definitions:
break;
case relationship_type::table_definition:
break;
case relationship_type::image:
break;
}
}
}
@ -656,16 +712,15 @@ void xlsx_producer::write_shared_string_table(const relationship &/*rel*/)
{
auto dimension = ws.calculate_dimension();
for (xlnt::row_t row = dimension.top_left().row();
row <= dimension.bottom_right().row(); ++row)
for (xlnt::row_t row = dimension.top_left().row(); row <= dimension.bottom_right().row(); ++row)
{
for (xlnt::column_t column = dimension.top_left().column();
column <= dimension.bottom_right().column(); ++column)
for (xlnt::column_t column = dimension.top_left().column(); column <= dimension.bottom_right().column();
++column)
{
if (ws.has_cell(xlnt::cell_reference(column, row)))
{
string_count += (ws.cell(xlnt::cell_reference(column, row))
.data_type() == cell::type::string) ? 1 : 0;
string_count +=
(ws.cell(xlnt::cell_reference(column, row)).data_type() == cell::type::string) ? 1 : 0;
}
}
}
@ -783,6 +838,8 @@ void xlsx_producer::write_styles(const relationship &/*rel*/)
auto num_custom = std::count_if(number_formats.begin(), number_formats.end(),
[](const number_format &nf) { return nf.id() >= 164; });
if (num_custom > 0)
{
serializer().start_element(xmlns, "numFmts");
serializer().attribute("count", num_custom);
@ -797,6 +854,7 @@ void xlsx_producer::write_styles(const relationship &/*rel*/)
serializer().end_element(xmlns, "numFmts");
}
}
// Fonts
@ -1312,18 +1370,10 @@ void xlsx_producer::write_theme(const relationship &theme_rel)
};
std::vector<scheme_element> scheme_elements = {
{ "dk1", "sysClr", "windowText" },
{ "lt1", "sysClr", "window" },
{ "dk2", "srgbClr", "44546A" },
{ "lt2", "srgbClr", "E7E6E6" },
{ "accent1", "srgbClr", "5B9BD5" },
{ "accent2", "srgbClr", "ED7D31" },
{ "accent3", "srgbClr", "A5A5A5" },
{ "accent4", "srgbClr", "FFC000" },
{ "accent5", "srgbClr", "4472C4" },
{ "accent6", "srgbClr", "70AD47" },
{ "hlink", "srgbClr", "0563C1" },
{ "folHlink", "srgbClr", "954F72" },
{"dk1", "sysClr", "windowText"}, {"lt1", "sysClr", "window"}, {"dk2", "srgbClr", "44546A"},
{"lt2", "srgbClr", "E7E6E6"}, {"accent1", "srgbClr", "5B9BD5"}, {"accent2", "srgbClr", "ED7D31"},
{"accent3", "srgbClr", "A5A5A5"}, {"accent4", "srgbClr", "FFC000"}, {"accent5", "srgbClr", "4472C4"},
{"accent6", "srgbClr", "70AD47"}, {"hlink", "srgbClr", "0563C1"}, {"folHlink", "srgbClr", "954F72"},
};
for (auto element : scheme_elements)
@ -1355,43 +1405,26 @@ void xlsx_producer::write_theme(const relationship &theme_rel)
std::string minor;
};
static const auto font_schemes = new std::vector<font_scheme> {
{ true, "latin", "Calibri Light", "Calibri" },
{ true, "ea", "", "" },
{ true, "cs", "", "" },
{ false, "Jpan", "Yu Gothic Light", "Yu Gothic" },
static const auto font_schemes = new std::vector<font_scheme>{{true, "latin", "Calibri Light", "Calibri"},
{true, "ea", "", ""}, {true, "cs", "", ""}, {false, "Jpan", "Yu Gothic Light", "Yu Gothic"},
{false, "Hang", "\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95",
"\xeb\xa7\x91\xec\x9d\x80 \xea\xb3\xa0\xeb\x94\x95"},
{false, "Hans", "DengXian Light", "DengXian"},
{false, "Hant", "\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94",
"\xe6\x96\xb0\xe7\xb4\xb0\xe6\x98\x8e\xe9\xab\x94"},
{ false, "Arab", "Times New Roman", "Arial" },
{ false, "Hebr", "Times New Roman", "Arial" },
{ false, "Thai", "Tahoma", "Tahoma" },
{ false, "Ethi", "Nyala", "Nyala" },
{ false, "Beng", "Vrinda", "Vrinda" },
{ false, "Gujr", "Shruti", "Shruti" },
{ false, "Khmr", "MoolBoran", "DaunPenh" },
{ false, "Knda", "Tunga", "Tunga" },
{ false, "Guru", "Raavi", "Raavi" },
{ false, "Cans", "Euphemia", "Euphemia" },
{false, "Arab", "Times New Roman", "Arial"}, {false, "Hebr", "Times New Roman", "Arial"},
{false, "Thai", "Tahoma", "Tahoma"}, {false, "Ethi", "Nyala", "Nyala"}, {false, "Beng", "Vrinda", "Vrinda"},
{false, "Gujr", "Shruti", "Shruti"}, {false, "Khmr", "MoolBoran", "DaunPenh"},
{false, "Knda", "Tunga", "Tunga"}, {false, "Guru", "Raavi", "Raavi"}, {false, "Cans", "Euphemia", "Euphemia"},
{false, "Cher", "Plantagenet Cherokee", "Plantagenet Cherokee"},
{false, "Yiii", "Microsoft Yi Baiti", "Microsoft Yi Baiti"},
{ false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya" },
{ false, "Thaa", "MV Boli", "MV Boli" },
{ false, "Deva", "Mangal", "Mangal" },
{ false, "Telu", "Gautami", "Gautami" },
{ false, "Taml", "Latha", "Latha" },
{ false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa" },
{ false, "Orya", "Kalinga", "Kalinga" },
{ false, "Mlym", "Kartika", "Kartika" },
{ false, "Laoo", "DokChampa", "DokChampa" },
{ false, "Sinh", "Iskoola Pota", "Iskoola Pota" },
{ false, "Mong", "Mongolian Baiti", "Mongolian Baiti" },
{ false, "Viet", "Times New Roman", "Arial" },
{ false, "Uigh", "Microsoft Uighur", "Microsoft Uighur" },
{ false, "Geor", "Sylfaen", "Sylfaen" }
};
{false, "Tibt", "Microsoft Himalaya", "Microsoft Himalaya"}, {false, "Thaa", "MV Boli", "MV Boli"},
{false, "Deva", "Mangal", "Mangal"}, {false, "Telu", "Gautami", "Gautami"}, {false, "Taml", "Latha", "Latha"},
{false, "Syrc", "Estrangelo Edessa", "Estrangelo Edessa"}, {false, "Orya", "Kalinga", "Kalinga"},
{false, "Mlym", "Kartika", "Kartika"}, {false, "Laoo", "DokChampa", "DokChampa"},
{false, "Sinh", "Iskoola Pota", "Iskoola Pota"}, {false, "Mong", "Mongolian Baiti", "Mongolian Baiti"},
{false, "Viet", "Times New Roman", "Arial"}, {false, "Uigh", "Microsoft Uighur", "Microsoft Uighur"},
{false, "Geor", "Sylfaen", "Sylfaen"}};
serializer().start_element(xmlns_a, "fontScheme");
serializer().attribute("name", "Office");
@ -1792,10 +1825,8 @@ void xlsx_producer::write_worksheet(const relationship &rel)
auto worksheet_part = rel.source().path().parent().append(rel.target().path());
auto worksheet_rels = source_.manifest().relationships(worksheet_part);
auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(),
source_.d_->sheet_title_rel_id_map_.end(),
[&](const std::pair<std::string, std::string> &p)
{
auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(), source_.d_->sheet_title_rel_id_map_.end(),
[&](const std::pair<std::string, std::string> &p) {
return p.second == rel.id();
})->first;
@ -1823,8 +1854,8 @@ void xlsx_producer::write_worksheet(const relationship &rel)
serializer().start_element(xmlns, "dimension");
const auto dimension = ws.calculate_dimension();
serializer().attribute("ref", dimension.is_single_cell()
? dimension.top_left().to_string() : dimension.to_string());
serializer().attribute(
"ref", dimension.is_single_cell() ? dimension.top_left().to_string() : dimension.to_string());
serializer().end_element(xmlns, "dimension");
if (ws.has_view())
@ -1839,7 +1870,8 @@ void xlsx_producer::write_worksheet(const relationship &rel)
if (view.type() != sheet_view_type::normal)
{
serializer().attribute("view", view.type() == sheet_view_type::page_break_preview ? "pageBreakPreview" : "pageLayout");
serializer().attribute(
"view", view.type() == sheet_view_type::page_break_preview ? "pageBreakPreview" : "pageLayout");
}
if (view.has_pane())
@ -2194,8 +2226,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
serializer().start_element(xmlns, "pageMargins");
// TODO: there must be a better way to do this
auto remove_trailing_zeros = [](const std::string &n)
{
auto remove_trailing_zeros = [](const std::string &n) {
auto decimal = n.find('.');
if (decimal == std::string::npos) return n;
@ -2228,9 +2259,8 @@ void xlsx_producer::write_worksheet(const relationship &rel)
if (ws.has_page_setup())
{
serializer().start_element(xmlns, "pageSetup");
serializer().attribute("orientation",
ws.page_setup().orientation() == xlnt::orientation::landscape
? "landscape" : "portrait");
serializer().attribute(
"orientation", ws.page_setup().orientation() == xlnt::orientation::landscape ? "landscape" : "portrait");
serializer().attribute("paperSize", static_cast<std::size_t>(ws.page_setup().paper_size()));
serializer().attribute("fitToHeight", write_bool(ws.page_setup().fit_to_height()));
serializer().attribute("fitToWidth", write_bool(ws.page_setup().fit_to_width()));
@ -2250,12 +2280,10 @@ void xlsx_producer::write_worksheet(const relationship &rel)
auto first_header = std::string();
auto first_footer = std::string();
const auto encode_text = [](const rich_text &t, header_footer::location where)
{
const auto location_code_map = std::unordered_map<header_footer::location, std::string, scoped_enum_hash<header_footer::location>>
{
{ header_footer::location::left, "&L" },
{ header_footer::location::center, "&C" },
const auto encode_text = [](const rich_text &t, header_footer::location where) {
const auto location_code_map =
std::unordered_map<header_footer::location, std::string, scoped_enum_hash<header_footer::location>>{
{header_footer::location::left, "&L"}, {header_footer::location::center, "&C"},
{header_footer::location::right, "&R"},
};
@ -2311,12 +2339,8 @@ void xlsx_producer::write_worksheet(const relationship &rel)
return encoded;
};
const auto locations =
{
header_footer::location::left,
header_footer::location::center,
header_footer::location::right
};
const auto locations = {
header_footer::location::left, header_footer::location::center, header_footer::location::right};
for (auto location : locations)
{
@ -2394,14 +2418,14 @@ void xlsx_producer::write_worksheet(const relationship &rel)
serializer().end_element(xmlns, "headerFooter");
}
if (!ws.row_breaks().empty())
if (!ws.page_break_rows().empty())
{
serializer().start_element(xmlns, "rowBreaks");
serializer().attribute("count", ws.row_breaks().size());
serializer().attribute("manualBreakCount", ws.row_breaks().size());
serializer().attribute("count", ws.page_break_rows().size());
serializer().attribute("manualBreakCount", ws.page_break_rows().size());
for (auto break_id : ws.row_breaks())
for (auto break_id : ws.page_break_rows())
{
serializer().start_element(xmlns, "brk");
serializer().attribute("id", break_id);
@ -2413,14 +2437,14 @@ void xlsx_producer::write_worksheet(const relationship &rel)
serializer().end_element(xmlns, "rowBreaks");
}
if (!ws.column_breaks().empty())
if (!ws.page_break_columns().empty())
{
serializer().start_element(xmlns, "colBreaks");
serializer().attribute("count", ws.column_breaks().size());
serializer().attribute("manualBreakCount", ws.column_breaks().size());
serializer().attribute("count", ws.page_break_columns().size());
serializer().attribute("manualBreakCount", ws.page_break_columns().size());
for (auto break_id : ws.column_breaks())
for (auto break_id : ws.page_break_columns())
{
serializer().start_element(xmlns, "brk");
serializer().attribute("id", break_id.index);
@ -2487,39 +2511,72 @@ void xlsx_producer::write_worksheet(const relationship &rel)
write_vml_drawings(child_rel, ws, cells_with_comments);
break;
case relationship_type::office_document: break;
case relationship_type::thumbnail: break;
case relationship_type::calculation_chain: break;
case relationship_type::extended_properties: break;
case relationship_type::core_properties: break;
case relationship_type::worksheet: break;
case relationship_type::shared_string_table: break;
case relationship_type::stylesheet: break;
case relationship_type::theme: break;
case relationship_type::hyperlink: break;
case relationship_type::chartsheet: break;
case relationship_type::unknown: break;
case relationship_type::custom_properties: break;
case relationship_type::printer_settings: break;
case relationship_type::connections: break;
case relationship_type::custom_property: break;
case relationship_type::custom_xml_mappings: break;
case relationship_type::dialogsheet: break;
case relationship_type::drawings: break;
case relationship_type::external_workbook_references: break;
case relationship_type::metadata: break;
case relationship_type::pivot_table: break;
case relationship_type::pivot_table_cache_definition: break;
case relationship_type::pivot_table_cache_records: break;
case relationship_type::query_table: break;
case relationship_type::shared_workbook_revision_headers: break;
case relationship_type::shared_workbook: break;
case relationship_type::revision_log: break;
case relationship_type::shared_workbook_user_data: break;
case relationship_type::single_cell_table_definitions: break;
case relationship_type::table_definition: break;
case relationship_type::volatile_dependencies: break;
case relationship_type::image: break;
case relationship_type::office_document:
break;
case relationship_type::thumbnail:
break;
case relationship_type::calculation_chain:
break;
case relationship_type::extended_properties:
break;
case relationship_type::core_properties:
break;
case relationship_type::worksheet:
break;
case relationship_type::shared_string_table:
break;
case relationship_type::stylesheet:
break;
case relationship_type::theme:
break;
case relationship_type::hyperlink:
break;
case relationship_type::chartsheet:
break;
case relationship_type::unknown:
break;
case relationship_type::custom_properties:
break;
case relationship_type::printer_settings:
break;
case relationship_type::connections:
break;
case relationship_type::custom_property:
break;
case relationship_type::custom_xml_mappings:
break;
case relationship_type::dialogsheet:
break;
case relationship_type::drawings:
break;
case relationship_type::external_workbook_references:
break;
case relationship_type::metadata:
break;
case relationship_type::pivot_table:
break;
case relationship_type::pivot_table_cache_definition:
break;
case relationship_type::pivot_table_cache_records:
break;
case relationship_type::query_table:
break;
case relationship_type::shared_workbook_revision_headers:
break;
case relationship_type::shared_workbook:
break;
case relationship_type::revision_log:
break;
case relationship_type::shared_workbook_user_data:
break;
case relationship_type::single_cell_table_definitions:
break;
case relationship_type::table_definition:
break;
case relationship_type::volatile_dependencies:
break;
case relationship_type::image:
break;
}
}
}
@ -2527,8 +2584,7 @@ void xlsx_producer::write_worksheet(const relationship &rel)
// Sheet Relationship Target Parts
void xlsx_producer::write_comments(const relationship &/*rel*/, worksheet ws,
const std::vector<cell_reference> &cells)
void xlsx_producer::write_comments(const relationship & /*rel*/, worksheet ws, const std::vector<cell_reference> &cells)
{
static const auto &xmlns = constants::namespace_("spreadsheetml");
@ -2640,8 +2696,7 @@ void xlsx_producer::write_comments(const relationship &/*rel*/, worksheet ws,
serializer().end_element(xmlns, "comments");
}
void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws,
const std::vector<cell_reference> &cells)
void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws, const std::vector<cell_reference> &cells)
{
static const auto &xmlns_mv = std::string("http://macVmlSchemaUri");
static const auto &xmlns_o = std::string("urn:schemas-microsoft-com:office:office");
@ -2796,7 +2851,8 @@ void xlsx_producer::write_image(const path &image_path)
end_part();
vector_istreambuf buffer(source_.d_->images_.at(image_path.string()));
archive_->open(image_path.string()) << &buffer;
auto image_streambuf = archive_->open(image_path);
std::ostream(image_streambuf.get()) << &buffer;
}
xml::serializer &xlsx_producer::serializer()
@ -2809,7 +2865,6 @@ std::string xlsx_producer::write_bool(bool boolean) const
return boolean ? "true" : "false";
}
void xlsx_producer::write_relationships(const std::vector<xlnt::relationship> &relationships, const path &part)
{
path parent = part.parent();
@ -2846,7 +2901,6 @@ void xlsx_producer::write_relationships(const std::vector<xlnt::relationship> &r
serializer().end_element(xmlns, "Relationships");
}
void xlsx_producer::write_color(const xlnt::color &color)
{
if (color.is_auto())

View File

@ -44,7 +44,7 @@ class worksheet;
namespace detail {
class ZipFileWriter;
class zip_file_writer;
/// <summary>
/// Handles writing a workbook into an XLSX file.
@ -137,8 +137,10 @@ private:
/// </summary>
const workbook &source_;
ZipFileWriter *archive_;
zip_file_writer *archive_;
std::unique_ptr<xml::serializer> current_part_serializer_;
std::unique_ptr<std::streambuf> current_part_streambuf_;
std::ostream current_part_stream_;
};
} // namespace detail

View File

@ -48,32 +48,30 @@ extern "C" {
#include <zlib.h>
}
#include <detail/zip.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <detail/zip.hpp>
namespace xlnt {
namespace detail {
namespace {
template <class T>
inline T read_int(std::istream &stream)
T read_int(std::istream &stream)
{
T value;
stream.read(reinterpret_cast<char *>(&value), sizeof(T));
return value;
}
template <class T>
inline void write_int(std::ostream &stream, T value)
void write_int(std::ostream &stream, T value)
{
stream.write(reinterpret_cast<char *>(&value), sizeof(T));
}
zip_file_header::zip_file_header()
xlnt::detail::zip_file_header read_header(std::istream &istream, const bool global)
{
}
xlnt::detail::zip_file_header header;
bool zip_file_header::read(std::istream &istream, const bool global)
{
auto sig = read_int<std::uint32_t>(istream);
// read and check for local/global magic
@ -81,27 +79,25 @@ bool zip_file_header::read(std::istream &istream, const bool global)
{
if (sig != 0x02014b50)
{
std::cerr << "Did not find global header signature" << std::endl;
return false;
throw xlnt::exception("missing global header signature");
}
version = read_int<std::uint16_t>(istream);
header.version = read_int<std::uint16_t>(istream);
}
else if (sig != 0x04034b50)
{
std::cerr << "Did not find local header signature" << std::endl;
return false;
throw xlnt::exception("missing local header signature");
}
// Read rest of header
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);
header.version = read_int<std::uint16_t>(istream);
header.flags = read_int<std::uint16_t>(istream);
header.compression_type = read_int<std::uint16_t>(istream);
header.stamp_date = read_int<std::uint16_t>(istream);
header.stamp_time = read_int<std::uint16_t>(istream);
header.crc = read_int<std::uint32_t>(istream);
header.compressed_size = read_int<std::uint32_t>(istream);
header.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);
@ -114,25 +110,25 @@ bool zip_file_header::read(std::istream &istream, const bool global)
/*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);
header.header_offset = read_int<std::uint32_t>(istream);
}
filename.resize(filename_length, '\0');
istream.read(&filename[0], filename_length);
header.filename.resize(filename_length, '\0');
istream.read(&header.filename[0], filename_length);
extra.resize(extra_length, 0);
istream.read(reinterpret_cast<char *>(extra.data()), extra_length);
header.extra.resize(extra_length, 0);
istream.read(reinterpret_cast<char *>(header.extra.data()), extra_length);
if (global)
{
comment.resize(comment_length, '\0');
istream.read(&comment[0], comment_length);
header.comment.resize(comment_length, '\0');
istream.read(&header.comment[0], comment_length);
}
return true;
return header;
}
void zip_file_header::Write(std::ostream &ostream, const bool global) const
void write_header(const xlnt::detail::zip_file_header &header, std::ostream &ostream, const bool global)
{
if (global)
{
@ -144,15 +140,15 @@ void zip_file_header::Write(std::ostream &ostream, const bool global) const
write_int(ostream, static_cast<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, static_cast<unsigned short>(filename.length()));
write_int(ostream, header.version);
write_int(ostream, header.flags);
write_int(ostream, header.compression_type);
write_int(ostream, header.stamp_date);
write_int(ostream, header.stamp_time);
write_int(ostream, header.crc);
write_int(ostream, header.compressed_size);
write_int(ostream, header.uncompressed_size);
write_int(ostream, static_cast<unsigned short>(header.filename.length()));
write_int(ostream, static_cast<unsigned short>(0)); // extra lengthx
if (global)
@ -161,18 +157,23 @@ void zip_file_header::Write(std::ostream &ostream, const bool global) const
write_int(ostream, static_cast<unsigned short>(0)); // disk# start
write_int(ostream, static_cast<unsigned short>(0)); // internal file
write_int(ostream, static_cast<unsigned int>(0)); // ext final
write_int(ostream, static_cast<unsigned int>(header_offset)); // rel offset
write_int(ostream, static_cast<unsigned int>(header.header_offset)); // rel offset
}
for (unsigned int i = 0; i < filename.length(); i++)
for (auto c : header.filename)
{
write_int(ostream, filename.c_str()[i]);
write_int(ostream, c);
}
}
} // namespace
namespace xlnt {
namespace detail {
static const std::size_t buffer_size = 512;
class ZipStreambufDecompress : public std::streambuf
class zip_streambuf_decompress : public std::streambuf
{
std::istream &istream;
@ -189,7 +190,7 @@ class ZipStreambufDecompress : public std::streambuf
static const unsigned short UNCOMPRESSED = 0;
public:
ZipStreambufDecompress(std::istream &stream, zip_file_header central_header)
zip_streambuf_decompress(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;
@ -202,7 +203,8 @@ public:
setp(0, 0);
// skip the header
valid = header.read(istream, false);
read_header(istream, false);
if (header.compression_type == DEFLATE)
{
compressed_data = true;
@ -236,7 +238,7 @@ public:
header = central_header;
}
virtual ~ZipStreambufDecompress()
virtual ~zip_streambuf_decompress()
{
if (compressed_data && valid)
{
@ -258,7 +260,8 @@ public:
if (strm.avail_in == 0)
{
// buffer empty, read some more from file
istream.read(in.data(), static_cast<std::streamsize>(std::min(buffer_size, header.compressed_size - total_read)));
istream.read(in.data(),
static_cast<std::streamsize>(std::min(buffer_size, header.compressed_size - total_read)));
strm.avail_in = static_cast<unsigned int>(istream.gcount());
total_read += strm.avail_in;
strm.next_in = reinterpret_cast<Bytef *>(in.data());
@ -289,7 +292,8 @@ public:
}
// uncompressed, so just read
istream.read(out.data() + 4, static_cast<std::streamsize>(std::min(buffer_size - 4, header.uncompressed_size - total_read)));
istream.read(out.data() + 4,
static_cast<std::streamsize>(std::min(buffer_size - 4, header.uncompressed_size - total_read)));
auto count = istream.gcount();
total_read += static_cast<std::size_t>(count);
return static_cast<int>(count);
@ -301,7 +305,8 @@ public:
return traits_type::to_int_type(*gptr()); // if we already have data just use it
auto put_back_count = gptr() - eback();
if (put_back_count > 4) put_back_count = 4;
std::memmove(out.data() + (4 - put_back_count), gptr() - put_back_count, static_cast<std::size_t>(put_back_count));
std::memmove(
out.data() + (4 - put_back_count), gptr() - put_back_count, static_cast<std::size_t>(put_back_count));
int num = process();
setg(out.data() + 4 - put_back_count, out.data() + 4, out.data() + 4 + num);
if (num <= 0) return EOF;
@ -311,12 +316,12 @@ public:
virtual int overflow(int c = EOF);
};
int ZipStreambufDecompress::overflow(int)
int zip_streambuf_decompress::overflow(int)
{
throw xlnt::exception("writing to read-only buffer");
}
class ZipStreambufCompress : public std::streambuf
class zip_streambuf_compress : public std::streambuf
{
std::ostream &ostream; // owned when header==0 (when not part of zip file)
@ -331,7 +336,7 @@ class ZipStreambufCompress : public std::streambuf
bool valid;
public:
ZipStreambufCompress(zip_file_header *central_header, std::ostream &stream)
zip_streambuf_compress(zip_file_header *central_header, std::ostream &stream)
: ostream(stream), header(central_header), valid(true)
{
strm.zalloc = Z_NULL;
@ -357,13 +362,13 @@ public:
if (header)
{
header->header_offset = static_cast<std::uint32_t>(stream.tellp());
header->Write(ostream, false);
write_header(*header, ostream, false);
}
uncompressed_size = crc = 0;
}
virtual ~ZipStreambufCompress()
virtual ~zip_streambuf_compress()
{
if (valid)
{
@ -375,7 +380,7 @@ public:
header->uncompressed_size = uncompressed_size;
header->crc = crc;
ostream.seekp(header->header_offset);
header->Write(ostream, false);
write_header(*header, ostream, false);
ostream.seekp(final_position);
}
else
@ -439,7 +444,7 @@ protected:
virtual int overflow(int c = EOF);
};
int ZipStreambufCompress::overflow(int c)
int zip_streambuf_compress::overflow(int c)
{
if (c != EOF)
{
@ -450,71 +455,48 @@ int ZipStreambufCompress::overflow(int c)
return c;
}
zip_file_istream::zip_file_istream(std::unique_ptr<std::streambuf> &&buffer)
: std::istream(&*buffer)
zip_file_writer::zip_file_writer(std::ostream &stream)
: destination_stream_(stream)
{
buf.swap(buffer);
if (!destination_stream_)
{
throw xlnt::exception("bad zip stream");
}
}
zip_file_istream::~zip_file_istream()
{
}
zip_file_ostream::zip_file_ostream(std::unique_ptr<std::streambuf> &&buffer)
: std::ostream(&*buffer)
{
buf.swap(buffer);
}
zip_file_ostream::~zip_file_ostream()
{
}
ZipFileWriter::ZipFileWriter(std::ostream &stream) : tarstream_(stream)
{
if (!tarstream_) throw std::runtime_error("ZIP: Invalid file handle");
}
ZipFileWriter::~ZipFileWriter()
zip_file_writer::~zip_file_writer()
{
// Write all file headers
std::ios::streampos final_position = tarstream_.tellp();
std::ios::streampos final_position = destination_stream_.tellp();
for (unsigned int i = 0; i < file_headers_.size(); i++)
for (const auto &header : file_headers_)
{
file_headers_[i].Write(tarstream_, true);
write_header(header, destination_stream_, true);
}
std::ios::streampos central_end = tarstream_.tellp();
std::ios::streampos central_end = destination_stream_.tellp();
// Write end of central
write_int(tarstream_, static_cast<std::uint32_t>(0x06054b50)); // end of central
write_int(tarstream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(tarstream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(tarstream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center in this disk
write_int(tarstream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center
write_int(tarstream_, static_cast<std::uint32_t>(central_end - final_position)); // size of header
write_int(tarstream_, static_cast<std::uint32_t>(final_position)); // offset to header
write_int(tarstream_, static_cast<std::uint16_t>(0)); // zip comment
write_int(destination_stream_, static_cast<std::uint32_t>(0x06054b50)); // end of central
write_int(destination_stream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(destination_stream_, static_cast<std::uint16_t>(0)); // this disk number
write_int(destination_stream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center in this disk
write_int(destination_stream_, static_cast<std::uint16_t>(file_headers_.size())); // one entry in center
write_int(destination_stream_, static_cast<std::uint32_t>(central_end - final_position)); // size of header
write_int(destination_stream_, static_cast<std::uint32_t>(final_position)); // offset to header
write_int(destination_stream_, static_cast<std::uint16_t>(0)); // zip comment
}
std::ostream &ZipFileWriter::open(const std::string &filename)
std::unique_ptr<std::streambuf> zip_file_writer::open(const path &filename)
{
zip_file_header header;
header.filename = filename;
header.filename = filename.string();
file_headers_.push_back(header);
auto streambuf = std::make_unique<ZipStreambufCompress>(&file_headers_.back(), tarstream_);
auto stream = new zip_file_ostream(std::move(streambuf));
write_stream_.reset(stream);
return *write_stream_;
return std::make_unique<zip_streambuf_compress>(&file_headers_.back(), destination_stream_);
}
void ZipFileWriter::close()
{
write_stream_.reset(nullptr);
}
ZipFileReader::ZipFileReader(std::istream &stream) : source_stream_(stream)
zip_file_reader::zip_file_reader(std::istream &stream)
: source_stream_(stream)
{
if (!stream)
{
@ -524,11 +506,11 @@ ZipFileReader::ZipFileReader(std::istream &stream) : source_stream_(stream)
read_central_header();
}
ZipFileReader::~ZipFileReader()
zip_file_reader::~zip_file_reader()
{
}
bool ZipFileReader::read_central_header()
bool zip_file_reader::read_central_header()
{
// Find the header
// NOTE: this assumes the zip file header is the last thing written to file...
@ -605,43 +587,37 @@ bool ZipFileReader::read_central_header()
for (std::uint16_t i = 0; i < num_files; ++i)
{
zip_file_header header;
if (header.read(source_stream_, true))
{
auto header = read_header(source_stream_, true);
file_headers_[header.filename] = header;
}
}
return true;
}
std::istream &ZipFileReader::open(const std::string &filename)
std::unique_ptr<std::streambuf> zip_file_reader::open(const path &filename)
{
if (!has_file(filename))
{
throw "not found";
}
auto header = file_headers_.at(filename);
auto header = file_headers_.at(filename.string());
source_stream_.seekg(header.header_offset);
auto streambuf = std::make_unique<ZipStreambufDecompress>(source_stream_, header);
read_stream_.reset(new zip_file_istream(std::move(streambuf)));
return *read_stream_;
return std::make_unique<zip_streambuf_decompress>(source_stream_, header);
}
std::vector<std::string> ZipFileReader::files() const
std::vector<path> zip_file_reader::files() const
{
std::vector<std::string> filenames;
std::vector<path> 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; });
[](const std::pair<std::string, zip_file_header> &h) { return path(h.first); });
return filenames;
}
bool ZipFileReader::has_file(const std::string &filename) const
bool zip_file_reader::has_file(const path &filename) const
{
return file_headers_.count(filename) != 0;
return file_headers_.count(filename.string()) != 0;
}
} // namespace detail

View File

@ -40,9 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
#include <unordered_map>
#include <vector>
#include <xlnt/utils/path.hpp>
namespace xlnt {
namespace detail {
/// <summary>
/// A structure representing the header that occurs before each compressed file in a ZIP
/// archive and again at the end of the file with more information.
/// </summary>
struct zip_file_header
{
std::uint16_t version = 20;
@ -56,61 +62,82 @@ struct zip_file_header
std::string comment;
std::vector<std::uint8_t> extra;
std::uint32_t header_offset = 0;
zip_file_header();
bool read(std::istream &istream, const bool global);
void Write(std::ostream &ostream, const bool global) const;
};
class zip_file_istream : public std::istream
/// <summary>
/// Writes a series of uncompressed binary file data as ostreams into another ostream
/// according to the ZIP format.
/// </summary>
class zip_file_writer
{
public:
zip_file_istream(std::unique_ptr<std::streambuf> &&buf);
virtual ~zip_file_istream();
/// <summary>
/// Construct a new zip_file_writer which writes a ZIP archive to the given stream.
/// </summary>
zip_file_writer(std::ostream &stream);
private:
std::unique_ptr<std::streambuf> buf;
};
/// <summary>
/// Destructor.
/// </summary>
virtual ~zip_file_writer();
class zip_file_ostream : public std::ostream
{
public:
zip_file_ostream(std::unique_ptr<std::streambuf> &&buf);
virtual ~zip_file_ostream();
/// <summary>
/// Returns a pointer to a streambuf which compresses the data it receives.
/// </summary>
std::unique_ptr<std::streambuf> open(const path &file);
private:
std::unique_ptr<std::streambuf> buf;
};
class ZipFileWriter
{
public:
ZipFileWriter(std::ostream &filename);
virtual ~ZipFileWriter();
std::ostream &open(const std::string &filename);
void close();
private:
std::vector<zip_file_header> file_headers_;
std::ostream &tarstream_;
std::unique_ptr<std::ostream> write_stream_;
std::ostream &destination_stream_;
};
class ZipFileReader
/// <summary>
/// Reads an archive containing a number of files from an istream and allows them
/// to be decompressed into an istream.
/// </summary>
class zip_file_reader
{
public:
ZipFileReader(std::istream &stream);
virtual ~ZipFileReader();
std::istream &open(const std::string &filename);
std::vector<std::string> files() const;
bool has_file(const std::string &filename) const;
/// <summary>
/// Construct a new zip_file_reader which reads a ZIP archive from the given stream.
/// </summary>
zip_file_reader(std::istream &stream);
/// <summary>
/// Destructor.
/// </summary>
virtual ~zip_file_reader();
/// <summary>
///
/// </summary>
std::unique_ptr<std::streambuf> open(const path &file);
/// <summary>
///
/// </summary>
std::vector<path> files() const;
/// <summary>
///
/// </summary>
bool has_file(const path &filename) const;
private:
/// <summary>
///
/// </summary>
bool read_central_header();
/// <summary>
///
/// </summary>
std::unordered_map<std::string, zip_file_header> file_headers_;
/// <summary>
///
/// </summary>
std::istream &source_stream_;
std::unique_ptr<std::istream> read_stream_;
};
} // namespace detail

View File

@ -214,7 +214,8 @@ std::vector<path> manifest::parts() const
return std::vector<path>(parts.begin(), parts.end());
}
std::string manifest::register_relationship(const uri &source, relationship_type type, const uri &target, target_mode mode)
std::string manifest::register_relationship(
const uri &source, relationship_type type, const uri &target, target_mode mode)
{
xlnt::relationship rel(next_relationship_id(source.path()), type, source, target, mode);
return register_relationship(rel);

View File

@ -30,12 +30,9 @@ relationship::relationship()
{
}
relationship::relationship(const std::string &id, relationship_type t, const uri &source, const uri &target, xlnt::target_mode mode)
: id_(id),
type_(t),
source_(source),
target_(target),
mode_(mode)
relationship::relationship(
const std::string &id, relationship_type t, const uri &source, const uri &target, xlnt::target_mode mode)
: id_(id), type_(t), source_(source), target_(target), mode_(mode)
{
}
@ -66,10 +63,7 @@ relationship_type relationship::type() const
bool relationship::operator==(const relationship &rhs) const
{
return type_ == rhs.type_
&& id_ == rhs.id_
&& source_ == rhs.source_
&& target_ == rhs.target_
return type_ == rhs.type_ && id_ == rhs.id_ && source_ == rhs.source_ && target_ == rhs.target_
&& mode_ == rhs.mode_;
}

View File

@ -6,7 +6,8 @@ uri::uri()
{
}
uri::uri(const std::string &uri_string) : path_(uri_string)
uri::uri(const std::string &uri_string)
: path_(uri_string)
{
}

View File

@ -22,9 +22,9 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <detail/default_case.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <detail/default_case.hpp>
namespace xlnt {
@ -50,8 +50,7 @@ border::border_property &border::border_property::style(border_style s)
return *this;
}
bool operator==(const border::border_property &left,
const border::border_property &right)
bool operator==(const border::border_property &left, const border::border_property &right)
{
if (left.style().is_set() != right.style().is_set())
{
@ -88,16 +87,9 @@ border::border()
const std::vector<xlnt::border_side> &border::all_sides()
{
static auto *sides = new std::vector<xlnt::border_side>
{
xlnt::border_side::start,
xlnt::border_side::end,
xlnt::border_side::top,
xlnt::border_side::bottom,
xlnt::border_side::diagonal,
xlnt::border_side::vertical,
xlnt::border_side::horizontal
};
static auto *sides = new std::vector<xlnt::border_side>{xlnt::border_side::start, xlnt::border_side::end,
xlnt::border_side::top, xlnt::border_side::bottom, xlnt::border_side::diagonal, xlnt::border_side::vertical,
xlnt::border_side::horizontal};
return *sides;
}
@ -106,13 +98,20 @@ optional<border::border_property> border::side(border_side s) const
{
switch (s)
{
case border_side::bottom: return bottom_;
case border_side::top: return top_;
case border_side::start: return start_;
case border_side::end: return end_;
case border_side::vertical: return vertical_;
case border_side::horizontal: return horizontal_;
case border_side::diagonal: return diagonal_;
case border_side::bottom:
return bottom_;
case border_side::top:
return top_;
case border_side::start:
return start_;
case border_side::end:
return end_;
case border_side::vertical:
return vertical_;
case border_side::horizontal:
return horizontal_;
case border_side::diagonal:
return diagonal_;
}
default_case(start_);
@ -122,13 +121,27 @@ border &border::side(border_side s, const border_property &prop)
{
switch (s)
{
case border_side::bottom: bottom_ = prop; break;
case border_side::top: top_ = prop; break;
case border_side::start: start_ = prop; break;
case border_side::end: end_ = prop; break;
case border_side::vertical: vertical_ = prop; break;
case border_side::horizontal: horizontal_ = prop; break;
case border_side::diagonal: diagonal_ = prop; break;
case border_side::bottom:
bottom_ = prop;
break;
case border_side::top:
top_ = prop;
break;
case border_side::start:
start_ = prop;
break;
case border_side::end:
end_ = prop;
break;
case border_side::vertical:
vertical_ = prop;
break;
case border_side::horizontal:
horizontal_ = prop;
break;
case border_side::diagonal:
diagonal_ = prop;
break;
}
return *this;

View File

@ -30,11 +30,13 @@
namespace xlnt {
indexed_color::indexed_color(std::size_t index) : index_(index)
indexed_color::indexed_color(std::size_t index)
: index_(index)
{
}
theme_color::theme_color(std::size_t index) : index_(index)
theme_color::theme_color(std::size_t index)
: index_(index)
{
}
@ -89,42 +91,22 @@ const color color::darkyellow()
}
color::color()
: type_(color_type::indexed),
rgb_(rgb_color(0, 0, 0, 0)),
indexed_(0),
theme_(0),
tint_(0),
auto__(false)
: type_(color_type::indexed), rgb_(rgb_color(0, 0, 0, 0)), indexed_(0), theme_(0), tint_(0), auto__(false)
{
}
color::color(const rgb_color &rgb)
: type_(color_type::rgb),
rgb_(rgb),
indexed_(0),
theme_(0),
tint_(0),
auto__(false)
: type_(color_type::rgb), rgb_(rgb), indexed_(0), theme_(0), tint_(0), auto__(false)
{
}
color::color(const indexed_color &indexed)
: type_(color_type::indexed),
rgb_(rgb_color(0, 0, 0, 0)),
indexed_(indexed),
theme_(0),
tint_(0),
auto__(false)
: type_(color_type::indexed), rgb_(rgb_color(0, 0, 0, 0)), indexed_(indexed), theme_(0), tint_(0), auto__(false)
{
}
color::color(const theme_color &theme)
: type_(color_type::theme),
rgb_(rgb_color(0, 0, 0, 0)),
indexed_(0),
theme_(theme),
tint_(0),
auto__(false)
: type_(color_type::theme), rgb_(rgb_color(0, 0, 0, 0)), indexed_(0), theme_(theme), tint_(0), auto__(false)
{
}
@ -226,9 +208,7 @@ void color::assert_type(color_type t) const
XLNT_API bool color::operator==(const xlnt::color &other) const
{
if (type_ != other.type_
|| std::fabs(tint_ - other.tint_) != 0.0
|| auto__ != other.auto__)
if (type_ != other.type_ || std::fabs(tint_ - other.tint_) != 0.0 || auto__ != other.auto__)
{
return false;
}

View File

@ -32,7 +32,6 @@ namespace xlnt {
pattern_fill::pattern_fill()
{
}
pattern_fill_type pattern_fill::type() const
@ -112,7 +111,8 @@ XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right)
// gradient_fill
gradient_fill::gradient_fill() : type_(gradient_fill_type::linear)
gradient_fill::gradient_fill()
: type_(gradient_fill_type::linear)
{
}
@ -138,7 +138,6 @@ double gradient_fill::degree() const
return degree_;
}
double gradient_fill::left() const
{
return left_;
@ -244,25 +243,22 @@ XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right)
fill fill::solid(const color &fill_color)
{
return fill(xlnt::pattern_fill()
.type(xlnt::pattern_fill_type::solid)
.foreground(fill_color)
.background(indexed_color(64)));
return fill(
xlnt::pattern_fill().type(xlnt::pattern_fill_type::solid).foreground(fill_color).background(indexed_color(64)));
}
fill::fill() : type_(fill_type::pattern)
fill::fill()
: type_(fill_type::pattern)
{
}
fill::fill(const xlnt::pattern_fill &pattern)
: type_(fill_type::pattern),
pattern_(pattern)
: type_(fill_type::pattern), pattern_(pattern)
{
}
fill::fill(const xlnt::gradient_fill &gradient)
: type_(fill_type::gradient),
gradient_(gradient)
: type_(fill_type::gradient), gradient_(gradient)
{
}

View File

@ -28,7 +28,6 @@
namespace xlnt {
font::font()
: name_("Calibri"),
size_(12.0),

View File

@ -22,14 +22,15 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <detail/format_impl.hpp>
#include <detail/stylesheet.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/style.hpp>
#include <detail/format_impl.hpp>
#include <detail/stylesheet.hpp>
namespace xlnt {
format::format(detail::format_impl *d) : d_(d)
format::format(detail::format_impl *d)
: d_(d)
{
}

View File

@ -27,41 +27,22 @@
#include <unordered_map>
#include <vector>
#include <detail/number_formatter.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/utils/datetime.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <detail/number_formatter.hpp>
namespace {
const std::unordered_map<std::size_t, std::string> &builtin_formats()
{
static const std::unordered_map<std::size_t, std::string> *formats =
new std::unordered_map<std::size_t, std::string>
({
{ 0, "General" },
{ 1, "0" },
{ 2, "0.00" },
{ 3, "#,##0" },
{ 4, "#,##0.00" },
{ 9, "0%" },
{ 10, "0.00%" },
{ 11, "0.00E+00" },
{ 12, "# ?/?" },
{ 13, "# \?\?/??" }, // escape trigraph
{ 14, "mm-dd-yy" },
{ 15, "d-mmm-yy" },
{ 16, "d-mmm" },
{ 17, "mmm-yy" },
{ 18, "h:mm AM/PM" },
{ 19, "h:mm:ss AM/PM" },
{ 20, "h:mm" },
{ 21, "h:mm:ss" },
{ 22, "m/d/yy h:mm" },
{ 37, "#,##0 ;(#,##0)" },
{ 38, "#,##0 ;[Red](#,##0)" },
{ 39, "#,##0.00;(#,##0.00)" },
{ 40, "#,##0.00;[Red](#,##0.00)" },
new std::unordered_map<std::size_t, std::string>(
{{0, "General"}, {1, "0"}, {2, "0.00"}, {3, "#,##0"}, {4, "#,##0.00"}, {9, "0%"}, {10, "0.00%"},
{11, "0.00E+00"}, {12, "# ?/?"}, {13, "# \?\?/??"}, // escape trigraph
{14, "mm-dd-yy"}, {15, "d-mmm-yy"}, {16, "d-mmm"}, {17, "mmm-yy"}, {18, "h:mm AM/PM"},
{19, "h:mm:ss AM/PM"}, {20, "h:mm"}, {21, "h:mm:ss"}, {22, "m/d/yy h:mm"}, {37, "#,##0 ;(#,##0)"},
{38, "#,##0 ;[Red](#,##0)"}, {39, "#,##0.00;(#,##0.00)"}, {40, "#,##0.00;[Red](#,##0.00)"},
// 41-44 aren't in the ECMA 376 v4 standard, but Libre Office uses them
{41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"},
@ -69,12 +50,7 @@ const std::unordered_map<std::size_t, std::string> &builtin_formats()
{43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"},
{44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)"},
{ 45, "mm:ss" },
{ 46, "[h]:mm:ss" },
{ 47, "mmss.0" },
{ 48, "##0.0E+0" },
{ 49, "@" }
});
{45, "mm:ss"}, {46, "[h]:mm:ss"}, {47, "mmss.0"}, {48, "##0.0E+0"}, {49, "@"}});
return *formats;
}
@ -239,20 +215,24 @@ const number_format number_format::date_time6()
return *format;
}
number_format::number_format() : number_format(general())
number_format::number_format()
: number_format(general())
{
}
number_format::number_format(std::size_t id) : number_format(from_builtin_id(id))
number_format::number_format(std::size_t id)
: number_format(from_builtin_id(id))
{
}
number_format::number_format(const std::string &format_string) : id_set_(false), id_(0)
number_format::number_format(const std::string &format_string)
: id_set_(false), id_(0)
{
this->format_string(format_string);
}
number_format::number_format(const std::string &format_string, std::size_t id) : id_set_(false), id_(0)
number_format::number_format(const std::string &format_string, std::size_t id)
: id_set_(false), id_(0)
{
this->format_string(format_string, id);
}

View File

@ -26,7 +26,8 @@
namespace xlnt {
protection::protection() : locked_(false), hidden_(false)
protection::protection()
: locked_(false), hidden_(false)
{
}

View File

@ -22,7 +22,6 @@
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <detail/stylesheet.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/fill.hpp>
@ -30,10 +29,12 @@
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/styles/style.hpp>
#include <detail/stylesheet.hpp>
namespace xlnt {
style::style(detail::style_impl *d) : d_(d)
style::style(detail::style_impl *d)
: d_(d)
{
}
@ -177,8 +178,7 @@ style style::number_format(const xlnt::number_format &new_number_format, bool ap
copy.id(d_->parent->next_custom_number_format_id());
d_->parent->number_formats.push_back(copy);
}
else if (std::find_if(d_->parent->number_formats.begin(),
d_->parent->number_formats.end(),
else if (std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
[&copy](const class number_format &nf) { return nf.id() == copy.id(); })
== d_->parent->number_formats.end())
{

View File

@ -43,7 +43,8 @@ std::tm safe_localtime(std::time_t raw_time)
namespace xlnt {
date::date(int year_, int month_, int day_) : year(year_), month(month_), day(day_)
date::date(int year_, int month_, int day_)
: year(year_), month(month_), day(day_)
{
}
@ -95,9 +96,9 @@ int date::to_number(calendar base_date) const
return 60;
}
int days_since_1900 = int((1461 * (year + 4800 + int((month - 14) / 12))) / 4) +
int((367 * (month - 2 - 12 * ((month - 14) / 12))) / 12) -
int((3 * (int((year + 4900 + int((month - 14) / 12)) / 100))) / 4) + day - 2415019 - 32075;
int days_since_1900 = int((1461 * (year + 4800 + int((month - 14) / 12))) / 4)
+ int((367 * (month - 2 - 12 * ((month - 14) / 12))) / 12)
- int((3 * (int((year + 4900 + int((month - 14) / 12)) / 100))) / 4) + day - 2415019 - 32075;
if (days_since_1900 <= 60)
{
@ -124,8 +125,8 @@ int date::weekday() const
auto month_temp = month == 1 ? 13 : month == 2 ? 14 : month;
auto day_temp = day + 1;
auto days = day_temp + static_cast<int>(13 * (month_temp + 1) / 5.0)
+ (year_temp % 100) + static_cast<int>((year_temp % 100) / 4.0);
auto days = day_temp + static_cast<int>(13 * (month_temp + 1) / 5.0) + (year_temp % 100)
+ static_cast<int>((year_temp % 100) / 4.0);
auto gregorian = days + static_cast<int>(year_temp / 400.0) - 2 * year_temp / 100;
auto julian = days + 5 - year_temp / 100;

View File

@ -23,8 +23,8 @@
#include <cmath>
#include <ctime>
#include <xlnt/utils/datetime.hpp>
#include <xlnt/utils/date.hpp>
#include <xlnt/utils/datetime.hpp>
#include <xlnt/utils/time.hpp>
namespace {
@ -54,8 +54,8 @@ datetime datetime::from_number(long double raw_time, calendar base_date)
bool datetime::operator==(const datetime &comparand) const
{
return year == comparand.year && month == comparand.month && day == comparand.day && hour == comparand.hour &&
minute == comparand.minute && second == comparand.second && microsecond == comparand.microsecond;
return year == comparand.year && month == comparand.month && day == comparand.day && hour == comparand.hour
&& minute == comparand.minute && second == comparand.second && microsecond == comparand.microsecond;
}
long double datetime::to_number(calendar base_date) const
@ -65,8 +65,8 @@ long double datetime::to_number(calendar base_date) const
std::string datetime::to_string() const
{
return std::to_string(year) + "/" + std::to_string(month) + "/" + std::to_string(day) + " " + std::to_string(hour) +
":" + std::to_string(minute) + ":" + std::to_string(second) + ":" + std::to_string(microsecond);
return std::to_string(year) + "/" + std::to_string(month) + "/" + std::to_string(day) + " " + std::to_string(hour)
+ ":" + std::to_string(minute) + ":" + std::to_string(second) + ":" + std::to_string(microsecond);
}
datetime datetime::now()
@ -80,13 +80,7 @@ datetime datetime::today()
}
datetime::datetime(int year_, int month_, int day_, int hour_, int minute_, int second_, int microsecond_)
: year(year_),
month(month_),
day(day_),
hour(hour_),
minute(minute_),
second(second_),
microsecond(microsecond_)
: year(year_), month(month_), day(day_), hour(hour_), minute(minute_), second(second_), microsecond(microsecond_)
{
}
@ -127,12 +121,8 @@ datetime datetime::from_iso_string(const std::string &string)
std::string datetime::to_iso_string() const
{
return std::to_string(year) + "-"
+ fill(std::to_string(month)) + "-"
+ fill(std::to_string(day)) + "T"
+ fill(std::to_string(hour)) + ":"
+ fill(std::to_string(minute)) + ":"
+ fill(std::to_string(second)) + "Z";
return std::to_string(year) + "-" + fill(std::to_string(month)) + "-" + fill(std::to_string(day)) + "T"
+ fill(std::to_string(hour)) + ":" + fill(std::to_string(minute)) + ":" + fill(std::to_string(second)) + "Z";
}
} // namespace xlnt

View File

@ -86,8 +86,8 @@ invalid_file::~invalid_file()
}
invalid_cell_reference::invalid_cell_reference(column_t column, row_t row)
: exception(std::string("bad cell coordinates: (") + std::to_string(column.index) + ", " + std::to_string(row) +
")")
: exception(
std::string("bad cell coordinates: (") + std::to_string(column.index) + ", " + std::to_string(row) + ")")
{
}

View File

@ -27,13 +27,13 @@
#ifdef __APPLE__
#include <mach-o/dyld.h>
#elif defined(__linux)
#include <unistd.h>
#include <linux/limits.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#include <detail/include_windows.hpp>
#include <xlnt/utils/path.hpp>
#include <detail/include_windows.hpp>
namespace {
@ -54,8 +54,7 @@ bool is_root(const std::string &part)
if (part.size() == 1 && part[0] == '/') return true;
if (part.size() != 3) return false;
return is_drive_letter(part[0]) && part[1] == ':'
&& (part[2] == '\\' || part[2] == '/');
return is_drive_letter(part[0]) && part[1] == ':' && (part[2] == '\\' || part[2] == '/');
}
bool is_absolute(const std::string &part)
@ -78,7 +77,6 @@ bool is_root(const std::string &part)
return part == "/";
}
bool is_absolute(const std::string &part)
{
return !part.empty() && part[0] == '/';
@ -135,7 +133,8 @@ path::path()
{
}
path::path(const std::string &path_string) : internal_(path_string)
path::path(const std::string &path_string)
: internal_(path_string)
{
}

View File

@ -88,11 +88,12 @@ time::time(int hour_, int minute_, int second_, int microsecond_)
bool time::operator==(const time &comparand) const
{
return hour == comparand.hour && minute == comparand.minute && second == comparand.second &&
microsecond == comparand.microsecond;
return hour == comparand.hour && minute == comparand.minute && second == comparand.second
&& microsecond == comparand.microsecond;
}
time::time(const std::string &time_string) : hour(0), minute(0), second(0), microsecond(0)
time::time(const std::string &time_string)
: hour(0), minute(0), second(0), microsecond(0)
{
std::string remaining = time_string;
auto colon_index = remaining.find(':');

View File

@ -27,16 +27,13 @@
namespace xlnt {
timedelta::timedelta() : timedelta(0, 0, 0, 0, 0)
timedelta::timedelta()
: timedelta(0, 0, 0, 0, 0)
{
}
timedelta::timedelta(int days_, int hours_, int minutes_, int seconds_, int microseconds_)
: days(days_),
hours(hours_),
minutes(minutes_),
seconds(seconds_),
microseconds(microseconds_)
: days(days_), hours(hours_), minutes(minutes_), seconds(seconds_), microseconds(microseconds_)
{
}

View File

@ -27,11 +27,13 @@
namespace xlnt {
const_worksheet_iterator::const_worksheet_iterator(const workbook &wb, std::size_t index) : wb_(wb), index_(index)
const_worksheet_iterator::const_worksheet_iterator(const workbook &wb, std::size_t index)
: wb_(wb), index_(index)
{
}
const_worksheet_iterator::const_worksheet_iterator(const const_worksheet_iterator &rhs) : wb_(rhs.wb_), index_(rhs.index_)
const_worksheet_iterator::const_worksheet_iterator(const const_worksheet_iterator &rhs)
: wb_(rhs.wb_), index_(rhs.index_)
{
}

View File

@ -29,28 +29,20 @@
#include <set>
#ifdef _MSC_VER
#include <codecvt> // utf-8 -> utf-16 conversion
#include <codecvt> // for std::wstring_convert
#endif
#include <detail/cell_impl.hpp>
#include <detail/constants.hpp>
#include <detail/excel_thumbnail.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/workbook_impl.hpp>
#include <detail/worksheet_impl.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/packaging/manifest.hpp>
#include <xlnt/packaging/relationship.hpp>
#include <xlnt/styles/alignment.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/style.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/protection.hpp>
#include <xlnt/styles/style.hpp>
#include <xlnt/utils/exceptions.hpp>
#include <xlnt/utils/path.hpp>
#include <xlnt/workbook/const_worksheet_iterator.hpp>
@ -62,6 +54,14 @@
#include <xlnt/worksheet/header_footer.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <detail/cell_impl.hpp>
#include <detail/constants.hpp>
#include <detail/excel_thumbnail.hpp>
#include <detail/vector_streambuf.hpp>
#include <detail/workbook_impl.hpp>
#include <detail/worksheet_impl.hpp>
#include <detail/xlsx_consumer.hpp>
#include <detail/xlsx_producer.hpp>
namespace {
@ -135,21 +135,20 @@ workbook workbook::minimal()
auto impl = new detail::workbook_impl();
workbook wb(impl);
wb.d_->manifest_.register_default_type("rels",
"application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_default_type("rels", "application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_override_type(path("/workbook.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::office_document,
uri("workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("/workbook.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::office_document, uri("workbook.xml"), target_mode::internal);
std::string title("1");
wb.d_->worksheets_.push_back(detail::worksheet_impl(&wb, 1, title));
wb.d_->manifest_.register_override_type(path("/sheet1.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = wb.d_->manifest_.register_relationship(uri("workbook.xml"),
relationship_type::worksheet, uri("sheet1.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("/sheet1.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = wb.d_->manifest_.register_relationship(
uri("workbook.xml"), relationship_type::worksheet, uri("sheet1.xml"), target_mode::internal);
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
return wb;
@ -160,26 +159,25 @@ workbook workbook::empty_excel()
auto impl = new detail::workbook_impl();
workbook wb(impl);
wb.d_->manifest_.register_override_type(path("/xl/workbook.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::office_document,
uri("xl/workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("/xl/workbook.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::office_document, uri("xl/workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_default_type("rels",
"application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_default_type("rels", "application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_default_type("xml", "application/xml");
wb.thumbnail(excel_thumbnail(), "jpeg", "image/jpeg");
wb.d_->manifest_.register_override_type(path("/docProps/core.xml"),
"application/vnd.openxmlformats-package.core-properties+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::core_properties,
uri("docProps/core.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("/docProps/core.xml"), "application/vnd.openxmlformats-package.core-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::core_properties, uri("docProps/core.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(path("/docProps/app.xml"),
"application/vnd.openxmlformats-officedocument.extended-properties+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::extended_properties,
uri("docProps/app.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("/docProps/app.xml"), "application/vnd.openxmlformats-officedocument.extended-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::extended_properties, uri("docProps/app.xml"), target_mode::internal);
wb.core_property("Creator", "Microsoft Office User");
wb.core_property("LastModifiedBy", "Microsoft Office User");
@ -208,7 +206,8 @@ workbook workbook::empty_excel()
wb.d_->stylesheet_ = detail::stylesheet();
auto &stylesheet = wb.d_->stylesheet_.get();
auto default_border = border().side(border_side::bottom, border::border_property())
auto default_border = border()
.side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
@ -220,15 +219,11 @@ workbook workbook::empty_excel()
auto gray125_fill = pattern_fill().type(pattern_fill_type::gray125);
stylesheet.fills.push_back(gray125_fill);
auto default_font = font()
.name("Calibri")
.size(12)
.scheme("minor")
.family(2)
.color(theme_color(1));
auto default_font = font().name("Calibri").size(12).scheme("minor").family(2).color(theme_color(1));
stylesheet.fonts.push_back(default_font);
wb.create_style("Normal").builtin_id(0)
wb.create_style("Normal")
.builtin_id(0)
.border(default_border, false)
.fill(default_fill, false)
.font(default_font, false)
@ -251,33 +246,33 @@ workbook workbook::empty_libre_office()
auto impl = new detail::workbook_impl();
workbook wb(impl);
wb.d_->manifest_.register_override_type(path("xl/workbook.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::office_document,
uri("xl/workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("xl/workbook.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::office_document, uri("xl/workbook.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(path("docProps/core.xml"),
"application/vnd.openxmlformats-package.core-properties+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::core_properties,
uri("docProps/core.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("docProps/core.xml"), "application/vnd.openxmlformats-package.core-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::core_properties, uri("docProps/core.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(path("docProps/app.xml"),
"application/vnd.openxmlformats-officedocument.extended-properties+xml");
wb.d_->manifest_.register_relationship(uri("/"), relationship_type::extended_properties,
uri("docProps/app.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("docProps/app.xml"), "application/vnd.openxmlformats-officedocument.extended-properties+xml");
wb.d_->manifest_.register_relationship(
uri("/"), relationship_type::extended_properties, uri("docProps/app.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(path("_rels/.rels"),
"application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_override_type(path("xl/_rels/workbook.xml.rels"),
"application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_override_type(
path("_rels/.rels"), "application/vnd.openxmlformats-package.relationships+xml");
wb.d_->manifest_.register_override_type(
path("xl/_rels/workbook.xml.rels"), "application/vnd.openxmlformats-package.relationships+xml");
std::string title("Sheet1");
wb.d_->worksheets_.push_back(detail::worksheet_impl(&wb, 1, title));
wb.d_->manifest_.register_override_type(path("xl/worksheets/sheet1.xml"),
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = wb.d_->manifest_.register_relationship(uri("xl/workbook.xml"),
relationship_type::worksheet, uri("worksheets/sheet1.xml"), target_mode::internal);
wb.d_->manifest_.register_override_type(
path("xl/worksheets/sheet1.xml"), "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = wb.d_->manifest_.register_relationship(
uri("xl/workbook.xml"), relationship_type::worksheet, uri("worksheets/sheet1.xml"), target_mode::internal);
wb.d_->sheet_title_rel_id_map_[title] = ws_rel;
auto ws = wb.sheet_by_index(0);
@ -313,7 +308,8 @@ workbook workbook::empty_libre_office()
.shrink(false);
stylesheet.alignments.push_back(default_alignment);
auto default_border = border().side(border_side::bottom, border::border_property())
auto default_border = border()
.side(border_side::bottom, border::border_property())
.side(border_side::top, border::border_property())
.side(border_side::start, border::border_property())
.side(border_side::end, border::border_property())
@ -338,12 +334,12 @@ workbook workbook::empty_libre_office()
default_number_format.id(164);
stylesheet.number_formats.push_back(default_number_format);
auto default_protection = xlnt::protection()
.locked(true)
.hidden(false);
auto default_protection = xlnt::protection().locked(true).hidden(false);
stylesheet.protections.push_back(default_protection);
wb.create_style("Normal").builtin_id(0).custom(false)
wb.create_style("Normal")
.builtin_id(0)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
@ -351,7 +347,9 @@ workbook workbook::empty_libre_office()
.number_format(default_number_format, false)
.protection(default_protection, false);
wb.create_style("Comma").builtin_id(3).custom(false)
wb.create_style("Comma")
.builtin_id(3)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
@ -359,7 +357,9 @@ workbook workbook::empty_libre_office()
.number_format(number_format::from_builtin_id(43), false)
.protection(default_protection, false);
wb.create_style("Comma [0]").builtin_id(6).custom(false)
wb.create_style("Comma [0]")
.builtin_id(6)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
@ -367,7 +367,9 @@ workbook workbook::empty_libre_office()
.number_format(number_format::from_builtin_id(41), false)
.protection(default_protection, false);
wb.create_style("Currency").builtin_id(4).custom(false)
wb.create_style("Currency")
.builtin_id(4)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
@ -375,7 +377,9 @@ workbook workbook::empty_libre_office()
.number_format(number_format::from_builtin_id(44), false)
.protection(default_protection, false);
wb.create_style("Currency [0]").builtin_id(7).custom(false)
wb.create_style("Currency [0]")
.builtin_id(7)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, true)
@ -383,7 +387,9 @@ workbook workbook::empty_libre_office()
.number_format(number_format::from_builtin_id(42), false)
.protection(default_protection, false);
wb.create_style("Percent").builtin_id(5).custom(false)
wb.create_style("Percent")
.builtin_id(5)
.custom(false)
.alignment(default_alignment, false)
.border(default_border, true)
.fill(default_fill, false)
@ -397,7 +403,8 @@ workbook workbook::empty_libre_office()
.protection(default_protection, true)
.style("Normal");
wb.core_property("Application", "LibreOffice/5.1.4.2$Windows_x86 LibreOffice_project/f99d75f39f1c57ebdd7ffc5f42867c12031db97a");
wb.core_property(
"Application", "LibreOffice/5.1.4.2$Windows_x86 LibreOffice_project/f99d75f39f1c57ebdd7ffc5f42867c12031db97a");
return wb;
}
@ -413,7 +420,8 @@ workbook::workbook()
swap(*this, wb_template);
}
workbook::workbook(detail::workbook_impl *impl) : d_(impl)
workbook::workbook(detail::workbook_impl *impl)
: d_(impl)
{
if (impl != nullptr)
{
@ -430,10 +438,10 @@ void workbook::register_app_properties_in_manifest()
if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::extended_properties))
{
manifest().register_override_type(path("/docProps/app.xml"),
"application/vnd.openxmlformats-officedocument.extended-properties+xml");
manifest().register_relationship(uri("/"), relationship_type::extended_properties,
uri("docProps/app.xml"), target_mode::internal);
manifest().register_override_type(
path("/docProps/app.xml"), "application/vnd.openxmlformats-officedocument.extended-properties+xml");
manifest().register_relationship(
uri("/"), relationship_type::extended_properties, uri("docProps/app.xml"), target_mode::internal);
}
}
@ -443,10 +451,10 @@ void workbook::register_core_properties_in_manifest()
if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::core_properties))
{
manifest().register_override_type(path("/docProps/core.xml"),
"application/vnd.openxmlformats-package.core-properties+xml");
manifest().register_relationship(uri("/"), relationship_type::core_properties,
uri("docProps/core.xml"), target_mode::internal);
manifest().register_override_type(
path("/docProps/core.xml"), "application/vnd.openxmlformats-package.core-properties+xml");
manifest().register_relationship(
uri("/"), relationship_type::core_properties, uri("docProps/core.xml"), target_mode::internal);
}
}
@ -458,8 +466,8 @@ void workbook::register_shared_string_table_in_manifest()
{
manifest().register_override_type(constants::part_shared_strings(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml");
manifest().register_relationship(wb_rel.target(),
relationship_type::shared_string_table, uri("sharedStrings.xml"), target_mode::internal);
manifest().register_relationship(
wb_rel.target(), relationship_type::shared_string_table, uri("sharedStrings.xml"), target_mode::internal);
}
}
@ -469,10 +477,10 @@ void workbook::register_stylesheet_in_manifest()
if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::stylesheet))
{
manifest().register_override_type(constants::part_styles(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
manifest().register_relationship(wb_rel.target(),
relationship_type::stylesheet, uri("styles.xml"), target_mode::internal);
manifest().register_override_type(
constants::part_styles(), "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml");
manifest().register_relationship(
wb_rel.target(), relationship_type::stylesheet, uri("styles.xml"), target_mode::internal);
}
}
@ -482,18 +490,17 @@ void workbook::register_theme_in_manifest()
if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::theme))
{
manifest().register_override_type(constants::part_theme(),
"application/vnd.openxmlformats-officedocument.theme+xml");
manifest().register_relationship(wb_rel.target(),
relationship_type::theme, uri("theme/theme1.xml"), target_mode::internal);
manifest().register_override_type(
constants::part_theme(), "application/vnd.openxmlformats-officedocument.theme+xml");
manifest().register_relationship(
wb_rel.target(), relationship_type::theme, uri("theme/theme1.xml"), target_mode::internal);
}
}
void workbook::register_comments_in_manifest(worksheet ws)
{
auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document);
auto ws_rel = manifest().relationship(wb_rel.target().path(),
d_->sheet_title_rel_id_map_.at(ws.title()));
auto ws_rel = manifest().relationship(wb_rel.target().path(), d_->sheet_title_rel_id_map_.at(ws.title()));
path ws_path(ws_rel.source().path().parent().append(ws_rel.target().path()));
if (!manifest().has_relationship(ws_path, relationship_type::vml_drawing))
@ -506,12 +513,14 @@ void workbook::register_comments_in_manifest(worksheet ws)
{
filename_exists = false;
for (auto current_ws_rel : manifest().relationships(wb_rel.target().path(), xlnt::relationship_type::worksheet))
for (auto current_ws_rel :
manifest().relationships(wb_rel.target().path(), xlnt::relationship_type::worksheet))
{
path current_ws_path(current_ws_rel.source().path().parent().append(current_ws_rel.target().path()));
if (!manifest().has_relationship(current_ws_path, xlnt::relationship_type::vml_drawing)) continue;
for (auto current_ws_child_rel : manifest().relationships(current_ws_path, xlnt::relationship_type::vml_drawing))
for (auto current_ws_child_rel :
manifest().relationships(current_ws_path, xlnt::relationship_type::vml_drawing))
{
if (current_ws_child_rel.target().path() == path("../drawings").append(filename))
{
@ -528,12 +537,11 @@ void workbook::register_comments_in_manifest(worksheet ws)
}
}
manifest().register_default_type("vml",
"application/vnd.openxmlformats-officedocument.vmlDrawing");
manifest().register_default_type("vml", "application/vnd.openxmlformats-officedocument.vmlDrawing");
const path relative_path(path("../drawings").append(filename));
manifest().register_relationship(uri(ws_path.string()),
relationship_type::vml_drawing, uri(relative_path.string()), target_mode::internal);
manifest().register_relationship(
uri(ws_path.string()), relationship_type::vml_drawing, uri(relative_path.string()), target_mode::internal);
}
if (!manifest().has_relationship(ws_path, relationship_type::comments))
@ -550,12 +558,12 @@ void workbook::register_comments_in_manifest(worksheet ws)
}
const path absolute_path(constants::package_xl().append(filename));
manifest().register_override_type(absolute_path,
"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml");
manifest().register_override_type(
absolute_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml");
const path relative_path(path("..").append(filename));
manifest().register_relationship(uri(ws_path.string()),
relationship_type::comments, uri(relative_path.string()), target_mode::internal);
manifest().register_relationship(
uri(ws_path.string()), relationship_type::comments, uri(relative_path.string()), target_mode::internal);
}
}
@ -641,8 +649,7 @@ const worksheet workbook::sheet_by_id(std::size_t id) const
worksheet workbook::active_sheet()
{
return sheet_by_index(d_->active_sheet_index_.is_set()
? d_->active_sheet_index_.get() : 0);
return sheet_by_index(d_->active_sheet_index_.is_set() ? d_->active_sheet_index_.get() : 0);
}
bool workbook::has_named_range(const std::string &name) const
@ -675,10 +682,10 @@ worksheet workbook::create_sheet()
auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document);
uri relative_sheet_uri(path("worksheets").append(sheet_filename).string());
auto absolute_sheet_path = path("/xl").append(relative_sheet_uri.path());
d_->manifest_.register_override_type(absolute_sheet_path,
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = d_->manifest_.register_relationship(workbook_rel.target(),
relationship_type::worksheet, relative_sheet_uri, target_mode::internal);
d_->manifest_.register_override_type(
absolute_sheet_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = d_->manifest_.register_relationship(
workbook_rel.target(), relationship_type::worksheet, relative_sheet_uri, target_mode::internal);
d_->sheet_title_rel_id_map_[title] = ws_rel;
return worksheet(&d_->worksheets_.back());
@ -897,8 +904,8 @@ void workbook::load(const std::wstring &filename, const std::string &password)
void workbook::remove_sheet(worksheet ws)
{
auto match_iter = std::find_if(d_->worksheets_.begin(), d_->worksheets_.end(),
[=](detail::worksheet_impl &comp) { return &comp == ws.d_; });
auto match_iter = std::find_if(
d_->worksheets_.begin(), d_->worksheets_.end(), [=](detail::worksheet_impl &comp) { return &comp == ws.d_; });
if (match_iter == d_->worksheets_.end())
{
@ -909,7 +916,8 @@ void workbook::remove_sheet(worksheet ws)
auto wb_rel = d_->manifest_.relationship(xlnt::path("/"), xlnt::relationship_type::office_document);
auto ws_rel = d_->manifest_.relationship(wb_rel.target().path(), ws_rel_id);
d_->manifest_.unregister_override_type(ws_rel.target().path());
d_->manifest_.unregister_relationship(wb_rel.target(), ws_rel_id);;
d_->manifest_.unregister_relationship(wb_rel.target(), ws_rel_id);
;
d_->sheet_title_rel_id_map_.erase(ws.title());
d_->worksheets_.erase(match_iter);
}
@ -940,10 +948,10 @@ worksheet workbook::create_sheet_with_rel(const std::string &title, const relati
auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document);
auto sheet_absoulute_path = workbook_rel.target().path().parent().append(rel.target().path());
d_->manifest_.register_override_type(sheet_absoulute_path,
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = d_->manifest_.register_relationship(workbook_rel.target(),
relationship_type::worksheet, rel.target(), target_mode::internal);
d_->manifest_.register_override_type(
sheet_absoulute_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
auto ws_rel = d_->manifest_.register_relationship(
workbook_rel.target(), relationship_type::worksheet, rel.target(), target_mode::internal);
d_->sheet_title_rel_id_map_[title] = ws_rel;
return worksheet(&d_->worksheets_.back());
@ -1062,12 +1070,14 @@ workbook &workbook::operator=(workbook other)
return *this;
}
workbook::workbook(workbook &&other) : workbook(nullptr)
workbook::workbook(workbook &&other)
: workbook(nullptr)
{
swap(*this, other);
}
workbook::workbook(const workbook &other) : workbook()
workbook::workbook(const workbook &other)
: workbook()
{
*d_.get() = *other.d_.get();
@ -1208,14 +1218,14 @@ bool workbook::contains(const std::string &sheet_title) const
return false;
}
void workbook::thumbnail(const std::vector<std::uint8_t> &thumbnail,
const std::string &extension, const std::string &content_type)
void workbook::thumbnail(
const std::vector<std::uint8_t> &thumbnail, const std::string &extension, const std::string &content_type)
{
if (!d_->manifest_.has_relationship(path("/"), relationship_type::thumbnail))
{
d_->manifest_.register_default_type(extension, content_type);
d_->manifest_.register_relationship(uri("/"), relationship_type::thumbnail,
uri("docProps/thumbnail.jpeg"), target_mode::internal);
d_->manifest_.register_relationship(
uri("/"), relationship_type::thumbnail, uri("docProps/thumbnail.jpeg"), target_mode::internal);
}
auto thumbnail_rel = d_->manifest_.relationship(path("/"), relationship_type::thumbnail);
@ -1349,4 +1359,28 @@ std::string workbook::core_property(const std::string &property_name) const
return d_->core_properties_.at(property_name);
}
/// <summary>
///
/// </summary>
bool workbook::has_calculation_properties() const
{
return d_->calculation_properties_.is_set();
}
/// <summary>
///
/// </summary>
class calculation_properties workbook::calculation_properties() const
{
return d_->calculation_properties_.get();
}
/// <summary>
///
/// </summary>
void workbook::calculation_properties(const class calculation_properties &props)
{
d_->calculation_properties_ = props;
}
} // namespace xlnt

View File

@ -27,11 +27,13 @@
namespace xlnt {
worksheet_iterator::worksheet_iterator(workbook &wb, std::size_t index) : wb_(wb), index_(index)
worksheet_iterator::worksheet_iterator(workbook &wb, std::size_t index)
: wb_(wb), index_(index)
{
}
worksheet_iterator::worksheet_iterator(const worksheet_iterator &rhs) : wb_(rhs.wb_), index_(rhs.index_)
worksheet_iterator::worksheet_iterator(const worksheet_iterator &rhs)
: wb_(rhs.wb_), index_(rhs.index_)
{
}

View File

@ -27,12 +27,16 @@
namespace xlnt {
cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell, const range_reference &limits, major_order order)
: ws_(ws), current_cell_(start_cell), range_(limits), order_(order)
cell_iterator::cell_iterator(worksheet ws, const cell_reference &start_cell,
const range_reference &limits, major_order order)
: ws_(ws),
current_cell_(start_cell),
range_(limits),
order_(order)
{
if (!ws.has_cell(current_cell_))
{
(*this)++;
(*this)++; // move to the next non-empty cell or one past the end if none exists
}
}
@ -43,7 +47,9 @@ cell_iterator::cell_iterator(const cell_iterator &other)
bool cell_iterator::operator==(const cell_iterator &other) const
{
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
}
bool cell_iterator::operator!=(const cell_iterator &other) const
@ -116,6 +122,7 @@ cell_iterator cell_iterator::operator++(int)
{
cell_iterator old = *this;
++*this;
return old;
}

View File

@ -38,11 +38,13 @@ cell_vector::iterator cell_vector::end()
{
auto past_end = ref_.bottom_right();
past_end.column_index(past_end.column_index() + 1);
return iterator(ws_, past_end, ref_, order_);
}
auto past_end = ref_.bottom_right();
past_end.row(past_end.row() + 1);
return iterator(ws_, past_end, ref_, order_);
}
@ -57,11 +59,13 @@ cell_vector::const_iterator cell_vector::cend() const
{
auto past_end = ref_.bottom_right();
past_end.column_index(past_end.column_index() + 1);
return const_iterator(ws_, past_end, order_);
}
auto past_end = ref_.bottom_right();
past_end.row(past_end.row() + 1);
return const_iterator(ws_, past_end, order_);
}
@ -102,9 +106,7 @@ cell cell_vector::back()
std::size_t cell_vector::length() const
{
return order_ == major_order::row
? ref_.width() + 1
: ref_.height() + 1;
return order_ == major_order::row ? ref_.width() + 1 : ref_.height() + 1;
}
cell_vector::const_iterator cell_vector::begin() const

View File

@ -28,7 +28,10 @@
namespace xlnt {
const_cell_iterator::const_cell_iterator(worksheet ws, const cell_reference &start_cell, major_order order)
: ws_(ws), current_cell_(start_cell), range_(start_cell.to_range()), order_(order)
: ws_(ws),
current_cell_(start_cell),
range_(start_cell.to_range()),
order_(order)
{
}
@ -65,6 +68,7 @@ const_cell_iterator const_cell_iterator::operator--(int)
{
const_cell_iterator old = *this;
--*this;
return old;
}
@ -86,6 +90,7 @@ const_cell_iterator const_cell_iterator::operator++(int)
{
const_cell_iterator old = *this;
++*this;
return old;
}

View File

@ -20,16 +20,20 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <xlnt/worksheet/range.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/worksheet/const_range_iterator.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
namespace xlnt {
const_range_iterator::const_range_iterator(const worksheet &ws, const range_reference &start_cell, major_order order)
: ws_(ws.d_), current_cell_(start_cell.top_left()), range_(start_cell), order_(order)
const_range_iterator::const_range_iterator(const worksheet &ws,
const range_reference &start_cell, major_order order)
: ws_(ws.d_),
current_cell_(start_cell.top_left()),
range_(start_cell),
order_(order)
{
}
@ -40,7 +44,9 @@ const_range_iterator::const_range_iterator(const const_range_iterator &other)
bool const_range_iterator::operator==(const const_range_iterator &other) const
{
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
}
bool const_range_iterator::operator!=(const const_range_iterator &other) const

View File

@ -20,9 +20,9 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <xlnt/worksheet/range.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/worksheet/const_range_iterator.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/range_iterator.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
@ -30,7 +30,10 @@
namespace xlnt {
range::range(worksheet ws, const range_reference &reference, major_order order, bool skip_null)
: ws_(ws), ref_(reference), order_(order), skip_null_(skip_null)
: ws_(ws),
ref_(reference),
order_(order),
skip_null_(skip_null)
{
}
@ -60,36 +63,37 @@ std::size_t range::length() const
bool range::operator==(const range &comparand) const
{
return ref_ == comparand.ref_ && ws_ == comparand.ws_ && order_ == comparand.order_;
return ref_ == comparand.ref_
&& ws_ == comparand.ws_
&& order_ == comparand.order_;
}
cell_vector range::vector(std::size_t vector_index)
{
range_reference vector_ref = ref_;
if (order_ == major_order::row)
{
range_reference reference(
ref_.top_left().column_index(),
static_cast<row_t>(static_cast<std::size_t>(ref_.top_left().row()) + vector_index),
ref_.bottom_right().column_index(),
static_cast<row_t>(static_cast<std::size_t>(ref_.top_left().row()) + vector_index));
return cell_vector(ws_, reference, order_);
auto row = ref_.top_left().row() + static_cast<row_t>(vector_index);
vector_ref.top_left().row(row);
vector_ref.bottom_right().row(row);
}
else
{
auto column = ref_.top_left().column() + static_cast<column_t::index_t>(vector_index);
vector_ref.top_left().column_index(column);
vector_ref.bottom_right().column_index(column);
}
range_reference reference(
static_cast<column_t::index_t>(static_cast<std::size_t>(ref_.top_left().column().index) + vector_index),
ref_.top_left().row(),
static_cast<column_t::index_t>(static_cast<std::size_t>(ref_.top_left().column().index) + vector_index),
ref_.bottom_right().row());
return cell_vector(ws_, reference, order_);
return cell_vector(ws_, vector_ref, order_);
}
bool range::contains(const cell_reference &ref)
{
return ref_.top_left().column_index() <= ref.column_index() &&
ref_.bottom_right().column_index() >= ref.column_index() &&
ref_.top_left().row() <= ref.row() && ref_.bottom_right().row() >= ref.row();
return ref_.top_left().column_index() <= ref.column_index()
&& ref_.bottom_right().column_index() >= ref.column_index()
&& ref_.top_left().row() <= ref.row()
&& ref_.bottom_right().row() >= ref.row();
}
cell range::cell(const cell_reference &ref)

View File

@ -20,8 +20,8 @@
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
#include <xlnt/worksheet/range.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/range_iterator.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
@ -42,8 +42,12 @@ cell_vector range_iterator::operator*() const
return cell_vector(ws_, reference, order_);
}
range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell, const range_reference &limits, major_order order)
: ws_(ws), current_cell_(start_cell.top_left()), range_(limits), order_(order)
range_iterator::range_iterator(worksheet &ws, const range_reference &start_cell,
const range_reference &limits, major_order order)
: ws_(ws),
current_cell_(start_cell.top_left()),
range_(limits),
order_(order)
{
}
@ -54,7 +58,9 @@ range_iterator::range_iterator(const range_iterator &other)
bool range_iterator::operator==(const range_iterator &other) const
{
return ws_ == other.ws_ && current_cell_ == other.current_cell_ && order_ == other.order_;
return ws_ == other.ws_
&& current_cell_ == other.current_cell_
&& order_ == other.order_;
}
bool range_iterator::operator!=(const range_iterator &other) const
@ -89,10 +95,12 @@ range_iterator &range_iterator::operator++()
if (order_ == major_order::row)
{
bool any_non_null = false;
do
{
current_cell_.row(current_cell_.row() + 1);
any_non_null = false;
for (auto column = current_cell_.column(); column <= range_.bottom_right().column(); column++)
{
if (ws_.has_cell(cell_reference(column, current_cell_.row())))
@ -101,8 +109,7 @@ range_iterator &range_iterator::operator++()
break;
}
}
}
while (!any_non_null && current_cell_.row() <= range_.bottom_right().row());
} while (!any_non_null && current_cell_.row() <= range_.bottom_right().row());
}
else
{

View File

@ -26,23 +26,28 @@
namespace xlnt {
range_reference range_reference::make_absolute(const xlnt::range_reference &relative_reference)
range_reference range_reference::make_absolute(const xlnt::range_reference &relative)
{
range_reference copy = relative_reference;
range_reference copy = relative;
copy.top_left_.make_absolute(true, true);
copy.bottom_right_.make_absolute(true, true);
return copy;
}
range_reference::range_reference() : range_reference("A1")
range_reference::range_reference()
: range_reference("A1")
{
}
range_reference::range_reference(const char *range_string) : range_reference(std::string(range_string))
range_reference::range_reference(const char *range_string)
: range_reference(std::string(range_string))
{
}
range_reference::range_reference(const std::string &range_string) : top_left_("A1"), bottom_right_("A1")
range_reference::range_reference(const std::string &range_string)
: top_left_("A1"), bottom_right_("A1")
{
auto colon_index = range_string.find(':');
@ -63,16 +68,19 @@ range_reference::range_reference(const cell_reference &top_left, const cell_refe
{
}
range_reference::range_reference(column_t column_index_start, row_t row_index_start, column_t column_index_end,
row_t row_index_end)
range_reference::range_reference(
column_t column_index_start, row_t row_index_start, column_t column_index_end, row_t row_index_end)
: top_left_(column_index_start, row_index_start), bottom_right_(column_index_end, row_index_end)
{
}
range_reference range_reference::make_offset(int column_offset, int row_offset) const
{
return range_reference(top_left_.make_offset(column_offset, row_offset),
bottom_right_.make_offset(column_offset, row_offset));
auto top_left = top_left_.make_offset(column_offset, row_offset);
auto bottom_right = bottom_right_.make_offset(column_offset, row_offset);
return top_left, bottom_right; // lol
}
std::size_t range_reference::height() const

View File

@ -34,6 +34,7 @@ std::string int_to_hex(T i)
{
std::stringstream stream;
stream << std::hex << i;
return stream.str();
}
@ -71,6 +72,7 @@ std::string sheet_protection::hash_password(const std::string &plaintext_passwor
std::string hashed = int_to_hex(password);
std::transform(hashed.begin(), hashed.end(), hashed.begin(),
[](char c) { return std::toupper(c, std::locale::classic()); });
return hashed;
}
}

View File

@ -38,10 +38,10 @@
#include <xlnt/worksheet/cell_iterator.hpp>
#include <xlnt/worksheet/const_cell_iterator.hpp>
#include <xlnt/worksheet/const_range_iterator.hpp>
#include <xlnt/worksheet/header_footer.hpp>
#include <xlnt/worksheet/range.hpp>
#include <xlnt/worksheet/range_iterator.hpp>
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/header_footer.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <detail/cell_impl.hpp>
@ -49,24 +49,35 @@
#include <detail/workbook_impl.hpp>
#include <detail/worksheet_impl.hpp>
namespace {
int points_to_pixels(double points, double dpi)
{
return static_cast<int>(std::ceil(points * dpi / 72));
};
} // namespace
namespace xlnt {
worksheet::worksheet() : d_(nullptr)
worksheet::worksheet()
: d_(nullptr)
{
}
worksheet::worksheet(detail::worksheet_impl *d) : d_(d)
worksheet::worksheet(detail::worksheet_impl *d)
: d_(d)
{
}
worksheet::worksheet(const worksheet &rhs) : d_(rhs.d_)
worksheet::worksheet(const worksheet &rhs)
: d_(rhs.d_)
{
}
bool worksheet::has_frozen_panes() const
{
return !d_->views_.empty()
&& d_->views_.front().has_pane()
return !d_->views_.empty() && d_->views_.front().has_pane()
&& (d_->views_.front().pane().state == pane_state::frozen
|| d_->views_.front().pane().state == pane_state::frozen_split);
}
@ -264,16 +275,15 @@ void worksheet::title(const std::string &title)
throw invalid_sheet_title(title);
}
auto same_title = std::find_if(workbook().begin(), workbook().end(),
[&](worksheet ws) { return ws.title() == title; });
auto same_title =
std::find_if(workbook().begin(), workbook().end(), [&](worksheet ws) { return ws.title() == title; });
if (same_title != workbook().end() && *same_title != *this)
{
throw invalid_sheet_title(title);
}
workbook().d_->sheet_title_rel_id_map_[title] =
workbook().d_->sheet_title_rel_id_map_[d_->title_];
workbook().d_->sheet_title_rel_id_map_[title] = workbook().d_->sheet_title_rel_id_map_[d_->title_];
workbook().d_->sheet_title_rel_id_map_.erase(d_->title_);
d_->title_ = title;
}
@ -399,12 +409,10 @@ const cell worksheet::cell(const cell_reference &reference) const
bool worksheet::has_cell(const cell_reference &reference) const
{
const auto row = d_->cell_map_.find(reference.row());
if(row == d_->cell_map_.cend())
return false;
if (row == d_->cell_map_.cend()) return false;
const auto col = row->second.find(reference.column_index());
if(col == row->second.cend())
return false;
if (col == row->second.cend()) return false;
return true;
}
@ -729,8 +737,7 @@ bool worksheet::compare(const worksheet &other, bool reference) const
// todo: missing some comparisons
if(d_->auto_filter_ == other.d_->auto_filter_
&& d_->views_ == other.d_->views_
if (d_->auto_filter_ == other.d_->auto_filter_ && d_->views_ == other.d_->views_
&& d_->merged_cells_ == other.d_->merged_cells_)
{
return true;
@ -815,17 +822,6 @@ std::vector<std::string> worksheet::formula_attributes() const
cell_reference worksheet::point_pos(int left, int top) const
{
static const auto DefaultColumnWidth = 51.85;
static const auto DefaultRowHeight = 15.0;
auto points_to_pixels = [](double value, double dpi)
{
return static_cast<int>(std::ceil(value * dpi / 72));
};
auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
column_t current_column = 1;
row_t current_row = 1;
@ -834,38 +830,12 @@ cell_reference worksheet::point_pos(int left, int top) const
while (left_pos <= left)
{
current_column++;
if (has_column_properties(current_column) && column_properties(current_column).width.is_set())
{
auto cdw = column_properties(current_column).width.get();
if (cdw >= 0)
{
left_pos += points_to_pixels(cdw, 96.0);
continue;
}
}
left_pos += default_width;
left_pos += column_width(current_column++);
}
while (top_pos <= top)
{
current_row++;
if (has_row_properties(current_row) && row_properties(current_row).height.is_set())
{
auto cdh = row_properties(current_row).height.get();
if (cdh >= 0)
{
top_pos += points_to_pixels(cdh, 96.0);
continue;
}
}
top_pos += default_height;
top_pos += row_height(current_row++);
}
return {current_column - 1, current_row - 1};
@ -1045,24 +1015,52 @@ void worksheet::header_footer(const class header_footer &hf)
d_->header_footer_ = hf;
}
std::vector<row_t> &worksheet::row_breaks()
void worksheet::page_break_at_row(row_t row)
{
d_->row_breaks_.push_back(row);
}
const std::vector<row_t> &worksheet::page_break_rows() const
{
return d_->row_breaks_;
}
const std::vector<row_t> &worksheet::row_breaks() const
void worksheet::page_break_at_column(xlnt::column_t column)
{
return d_->row_breaks_;
d_->column_breaks_.push_back(column);
}
std::vector<column_t> &worksheet::column_breaks()
const std::vector<column_t> &worksheet::page_break_columns() const
{
return d_->column_breaks_;
}
const std::vector<column_t> &worksheet::column_breaks() const
double worksheet::column_width(column_t column) const
{
return d_->column_breaks_;
static const auto DefaultColumnWidth = 51.85;
if (has_column_properties(column))
{
return column_properties(column).width.get();
}
else
{
return points_to_pixels(DefaultColumnWidth, 96.0);
}
}
double worksheet::row_height(row_t row) const
{
static const auto DefaultRowHeight = 15.0;
if (has_row_properties(row))
{
return row_properties(row).height.get();
}
else
{
return points_to_pixels(DefaultRowHeight, 96.0);
}
}
} // namespace xlnt

Binary file not shown.

Binary file not shown.

View File

@ -62,7 +62,7 @@ public:
auto is_whitespace = [](const std::string &v)
{
return v.find_first_not_of("\n ") == std::string::npos;
return v.find_first_not_of("\n\t ") == std::string::npos;
};
for (auto left_event : left_parser)
@ -155,11 +155,17 @@ public:
std::cout << "documents don't match" << std::endl;
std::cout << "left:" << std::endl;
std::cout << left;
for (auto c : left)
{
std::cout << c << std::flush;
}
std::cout << std::endl;
std::cout << "right:" << std::endl;
std::cout << right;
for (auto c : right)
{
std::cout << c << std::flush;
}
std::cout << std::endl;
}
@ -172,7 +178,7 @@ public:
std::vector<std::uint8_t> bytes;
wb.save(bytes);
std::istringstream file_stream(std::string(bytes.begin(), bytes.end()));
xlnt::detail::ZipFileReader archive(file_stream);
xlnt::detail::zip_file_reader archive(file_stream);
return string_matches_archive_member(expected, archive, part, content_type);
}
@ -183,31 +189,33 @@ public:
std::vector<std::uint8_t> bytes;
wb.save(bytes);
std::istringstream file_stream(std::string(bytes.begin(), bytes.end()));
xlnt::detail::ZipFileReader archive(file_stream);
xlnt::detail::zip_file_reader archive(file_stream);
return file_matches_archive_member(expected, archive, part, content_type);
}
static bool string_matches_archive_member(const std::string &expected,
xlnt::detail::ZipFileReader &archive,
xlnt::detail::zip_file_reader &archive,
const xlnt::path &member,
const std::string &content_type)
{
auto &stream = archive.open(member.string());
auto streambuf = archive.open(member);
std::istream stream(streambuf.get());
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,
xlnt::detail::ZipFileReader &archive,
xlnt::detail::zip_file_reader &archive,
const xlnt::path &member,
const std::string &content_type)
{
if (!archive.has_file(member.string())) return false;
if (!archive.has_file(member)) 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);
auto &member_stream = archive.open(member.string());
auto member_streambuf = archive.open(member);
std::ostream member_stream(member_streambuf.get());
member_data_stream << member_stream.rdbuf();
std::string contents(member_data.begin(), member_data.end());
return compare_files(file.read_contents(), contents, content_type);
@ -217,13 +225,13 @@ public:
{
xlnt::detail::vector_istreambuf left_buffer(left);
std::istream left_stream(&left_buffer);
xlnt::detail::ZipFileReader left_archive(left_stream);
xlnt::detail::zip_file_reader left_archive(left_stream);
const auto left_info = left_archive.files();
xlnt::detail::vector_istreambuf right_buffer(right);
std::istream right_stream(&right_buffer);
xlnt::detail::ZipFileReader right_archive(right_stream);
xlnt::detail::zip_file_reader right_archive(right_stream);
const auto right_info = right_archive.files();
@ -234,14 +242,14 @@ public:
std::cout << "left has: ";
for (auto &info : left_info)
{
std::cout << info << ", ";
std::cout << info.string() << ", ";
}
std::cout << std::endl;
std::cout << "right has: ";
for (auto &info : right_info)
{
std::cout << info << ", ";
std::cout << info.string() << ", ";
}
std::cout << std::endl;
}
@ -262,18 +270,20 @@ public:
if (!right_archive.has_file(left_member))
{
match = false;
std::cout << "right is missing file: " << left_member << std::endl;
std::cout << "right is missing file: " << left_member.string() << std::endl;
continue;
}
auto &left_member_stream = left_archive.open(left_member);
auto left_member_streambuf = left_archive.open(left_member);
std::istream left_member_stream(left_member_streambuf.get());
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();
std::string left_member_contents(left_contents_raw.begin(), left_contents_raw.end());
auto &right_member_stream = left_archive.open(left_member);
auto right_member_streambuf = right_archive.open(left_member);
std::istream right_member_stream(right_member_streambuf.get());
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);
@ -282,10 +292,10 @@ public:
std::string left_content_type, right_content_type;
if (left_member != "[Content_Types].xml")
if (left_member.string() != "[Content_Types].xml")
{
left_content_type = left_manifest.content_type(xlnt::path(left_member));
right_content_type = right_manifest.content_type(xlnt::path(left_member));
left_content_type = left_manifest.content_type(left_member);
right_content_type = right_manifest.content_type(left_member);
}
else
{
@ -295,7 +305,7 @@ public:
if (left_content_type != right_content_type)
{
std::cout << "content types differ: "
<< left_member
<< left_member.string()
<< " "
<< left_content_type
<< " "
@ -305,7 +315,7 @@ public:
}
else if (!compare_files(left_member_contents, right_member_contents, left_content_type))
{
std::cout << left_member << std::endl;
std::cout << left_member.string() << std::endl;
match = false;
}
}