From c8f2ca204bd0b78fe1ea9c9b380fbfeadbb9e097 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Sat, 24 Dec 2016 10:04:57 -0500 Subject: [PATCH] clang-format all source files, fix broken test helpers--lots of cleanup necessary as a result [ci skip] --- .clang-format | 2 +- include/xlnt/cell/cell.hpp | 3 + include/xlnt/styles/format.hpp | 3 +- include/xlnt/styles/style.hpp | 1 + .../xlnt/workbook/calculation_properties.hpp | 37 + include/xlnt/workbook/workbook.hpp | 22 +- include/xlnt/worksheet/worksheet.hpp | 82 +- source/cell/cell.cpp | 98 +- source/cell/cell_reference.cpp | 37 +- source/cell/comment.cpp | 15 +- source/cell/index_types.cpp | 250 +- source/cell/rich_text.cpp | 12 +- source/detail/cell_impl.cpp | 7 +- source/detail/constants.cpp | 129 +- source/detail/custom_value_traits.cpp | 265 +- source/detail/number_formatter.cpp | 447 +-- source/detail/pole.cpp | 1031 +++--- source/detail/workbook_impl.hpp | 4 +- source/detail/xlsx_consumer.cpp | 331 +- source/detail/xlsx_consumer.hpp | 4 +- source/detail/xlsx_crypto.cpp | 291 +- source/detail/xlsx_producer.cpp | 3058 +++++++++-------- source/detail/xlsx_producer.hpp | 6 +- source/detail/zip.cpp | 224 +- source/detail/zip.hpp | 99 +- source/packaging/manifest.cpp | 137 +- source/packaging/relationship.cpp | 16 +- source/packaging/uri.cpp | 3 +- source/styles/alignment.cpp | 44 +- source/styles/border.cpp | 115 +- source/styles/color.cpp | 120 +- source/styles/fill.cpp | 124 +- source/styles/font.cpp | 47 +- source/styles/format.cpp | 61 +- source/styles/number_format.cpp | 70 +- source/styles/protection.cpp | 7 +- source/styles/style.cpp | 60 +- source/utils/date.cpp | 21 +- source/utils/datetime.cpp | 58 +- source/utils/exceptions.cpp | 6 +- source/utils/path.cpp | 155 +- source/utils/time.cpp | 37 +- source/utils/timedelta.cpp | 27 +- source/workbook/const_worksheet_iterator.cpp | 6 +- source/workbook/workbook.cpp | 856 ++--- source/workbook/worksheet_iterator.cpp | 6 +- source/worksheet/cell_iterator.cpp | 19 +- source/worksheet/cell_vector.cpp | 8 +- source/worksheet/const_cell_iterator.cpp | 7 +- source/worksheet/const_range_iterator.cpp | 22 +- source/worksheet/page_margins.cpp | 2 +- source/worksheet/range.cpp | 44 +- source/worksheet/range_iterator.cpp | 27 +- source/worksheet/range_reference.cpp | 26 +- source/worksheet/sheet_protection.cpp | 4 +- source/worksheet/worksheet.cpp | 256 +- tests/data/8_minimal.xlsx | Bin 1643 -> 1701 bytes tests/data/9_default-excel.xlsx | Bin 20982 -> 13385 bytes tests/helpers/xml_helper.hpp | 54 +- 59 files changed, 4594 insertions(+), 4309 deletions(-) create mode 100644 include/xlnt/workbook/calculation_properties.hpp diff --git a/.clang-format b/.clang-format index 735a4d41..f6c1ac6d 100644 --- a/.clang-format +++ b/.clang-format @@ -27,7 +27,7 @@ BraceWrapping: BeforeElse: true BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom -ColumnLimit: 120 +ColumnLimit: 0 ConstructorInitializerAllOnOneLineOrOnePerLine: true Cpp11BracedListStyle: true DerivePointerAlignment: false diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp index 6738984e..1c10c56c 100644 --- a/include/xlnt/cell/cell.hpp +++ b/include/xlnt/cell/cell.hpp @@ -469,6 +469,9 @@ public: /// void comment(const class comment &new_comment); + double width() const; + double height() const; + // operators /// diff --git a/include/xlnt/styles/format.hpp b/include/xlnt/styles/format.hpp index 5c4a511c..39c33d5c 100644 --- a/include/xlnt/styles/format.hpp +++ b/include/xlnt/styles/format.hpp @@ -37,6 +37,7 @@ class fill; class font; class number_format; class protection; +class style; namespace detail { @@ -208,7 +209,7 @@ public: /// /// /// - format style(const xlnt::style &new_style); + format style(const class style &new_style); /// /// diff --git a/include/xlnt/styles/style.hpp b/include/xlnt/styles/style.hpp index 23810b1c..8003cd1f 100644 --- a/include/xlnt/styles/style.hpp +++ b/include/xlnt/styles/style.hpp @@ -28,6 +28,7 @@ #include #include +#include namespace xlnt { diff --git a/include/xlnt/workbook/calculation_properties.hpp b/include/xlnt/workbook/calculation_properties.hpp new file mode 100644 index 00000000..b15027e5 --- /dev/null +++ b/include/xlnt/workbook/calculation_properties.hpp @@ -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 + +namespace xlnt { + +/// +/// +/// +class XLNT_API calculation_properties +{ +}; + +} // namespace xlnt diff --git a/include/xlnt/workbook/workbook.hpp b/include/xlnt/workbook/workbook.hpp index 2193f3ed..eba2f06f 100644 --- a/include/xlnt/workbook/workbook.hpp +++ b/include/xlnt/workbook/workbook.hpp @@ -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: /// /// /// - void thumbnail( - const std::vector &thumbnail, const std::string &extension, const std::string &content_type); + void thumbnail(const std::vector &thumbnail, + const std::string &extension, const std::string &content_type); /// /// /// const std::vector &thumbnail() const; + // calculation properties + + /// + /// + /// + bool has_calculation_properties() const; + + /// + /// + /// + class calculation_properties calculation_properties() const; + + /// + /// + /// + void calculation_properties(const class calculation_properties &props); + // operators /// diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index d5c643f7..13205352 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -73,96 +73,99 @@ class XLNT_API worksheet { public: /// - /// + /// Iterate over a non-const worksheet with an iterator of this type. /// using iterator = range_iterator; /// - /// + /// Iterate over a non-const worksheet with an iterator of this type. /// using const_iterator = const_range_iterator; /// - /// + /// Iterate in reverse over a non-const worksheet with an iterator of this type. /// using reverse_iterator = std::reverse_iterator; /// - /// + /// Iterate in reverse order over a const worksheet with an iterator of this type. /// using const_reverse_iterator = std::reverse_iterator; /// - /// + /// Construct a null worksheet. No methods should be called on such a worksheet. /// worksheet(); /// - /// + /// Copy constructor. This worksheet will point to the same memory as rhs's worksheet. /// worksheet(const worksheet &rhs); /// - /// + /// Returns a reference to the workbook this worksheet is owned by. /// class workbook &workbook(); /// - /// + /// Returns a reference to the workbook this worksheet is owned by. /// const class workbook &workbook() const; /// - /// + /// 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. /// void garbage_collect(); // identification /// - /// + /// Returns the unique numeric identifier of this worksheet. This will sometimes but not necessarily + /// be the index of the worksheet in the workbook. /// std::size_t id() const; /// - /// + /// 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. /// void id(std::size_t id); /// - /// + /// Returns the title of this sheet. /// std::string title() const; /// - /// + /// Sets the title of this sheet. /// void title(const std::string &title); // freeze panes /// - /// + /// Returns the top left corner of the region above and to the left of which panes are frozen. /// cell_reference frozen_panes() const; /// - /// + /// Freeze panes above and to the left of top_left_cell. /// void freeze_panes(cell top_left_cell); /// - /// + /// Freeze panes above and to the left of top_left_coordinate. /// void freeze_panes(const cell_reference &top_left_coordinate); /// - /// + /// Remove frozen panes. The data in those panes will be unaffected--this affects only the view. /// void unfreeze_panes(); /// - /// + /// Returns true if this sheet has a frozen row, frozen column, or both. /// bool has_frozen_panes() const; @@ -260,6 +263,12 @@ public: /// void add_column_properties(column_t column, const class column_properties &props); + /// + /// 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. + /// + double column_width(column_t column) const; + /// /// /// @@ -280,6 +289,12 @@ public: /// void add_row_properties(row_t row, const class row_properties &props); + /// + /// 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. + /// + double row_height(row_t row) const; + // positioning /// @@ -686,10 +701,33 @@ public: /// void add_view(const sheet_view &new_view); - std::vector &row_breaks(); - const std::vector &row_breaks() const; - std::vector &column_breaks(); - const std::vector &column_breaks() const; + // page breaks + + /// + /// Remove all manual column and row page breaks (represented as dashed + /// blue lines in the page view in Excel). + /// + void clear_page_breaks(); + + /// + /// Returns vector where each element represents a row which will break a page below it. + /// + const std::vector &page_break_rows() const; + + /// + /// Add a page break at the given row. + /// + void page_break_at_row(row_t row); + + /// + /// Returns vector where each element represents a column which will break a page to the right. + /// + const std::vector &page_break_columns() const; + + /// + /// Add a page break at the given column. + /// + void page_break_at_column(column_t column); private: friend class cell; diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index 03486d39..330a0b67 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -57,11 +57,12 @@ namespace { std::pair 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(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 cast_percentage(const std::string &s) @@ -149,16 +150,14 @@ namespace xlnt { const std::unordered_map &cell::error_codes() { - static const auto *codes = new std::unordered_map - { + static const auto *codes = new std::unordered_map{ {"#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 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(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_anchor += default_width; + left += worksheet().cell(column_index, row()).width(); } - auto top_rows = d_->row_ - 1; - int top_anchor = 0; - auto default_height = points_to_pixels(DefaultRowHeight, 96.0L); + int top = 0; - 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_anchor += default_height; + top += worksheet().cell(column(), row_index).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(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(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 diff --git a/source/cell/cell_reference.cpp b/source/cell/cell_reference.cpp index dfe1969f..ab4402e2 100644 --- a/source/cell/cell_reference.cpp +++ b/source/cell/cell_reference.cpp @@ -41,18 +41,19 @@ cell_reference &cell_reference::make_absolute(bool absolute_column, bool absolut { column_absolute(absolute_column); row_absolute(absolute_row); - + return *this; } -cell_reference::cell_reference() : cell_reference(1, 1) +cell_reference::cell_reference() + : cell_reference(1, 1) { } cell_reference::cell_reference(const std::string &string) { auto split = split_reference(string, absolute_column_, absolute_row_); - + column(split.first); row(split.second); } @@ -65,16 +66,13 @@ 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_); } } -range_reference cell_reference::operator, (const xlnt::cell_reference &other) const +range_reference cell_reference::operator,(const xlnt::cell_reference &other) const { return range_reference(*this, other); } @@ -82,19 +80,19 @@ range_reference cell_reference::operator, (const xlnt::cell_reference &other) co std::string cell_reference::to_string() const { std::string string_representation; - + if (absolute_column_) { string_representation.append("$"); } - + string_representation.append(column_.column_string()); - + if (absolute_row_) { string_representation.append("$"); } - + string_representation.append(std::to_string(row_)); return string_representation; @@ -111,8 +109,8 @@ std::pair cell_reference::split_reference(const std::string return split_reference(reference_string, ignore1, ignore2); } -std::pair cell_reference::split_reference(const std::string &reference_string, - bool &absolute_column, bool &absolute_row) +std::pair cell_reference::split_reference( + const std::string &reference_string, bool &absolute_column, bool &absolute_row) { absolute_column = false; absolute_row = false; @@ -183,7 +181,7 @@ std::pair cell_reference::split_reference(const std::string row_string = row_string.substr(1); } - return { column_string, std::stoi(row_string) }; + return {column_string, std::stoi(row_string)}; } bool cell_reference::column_absolute() const @@ -263,19 +261,16 @@ bool cell_reference::operator!=(const char *reference_string) const cell_reference cell_reference::make_offset(int column_offset, int row_offset) const { - //TODO: check for overflow/underflow + // TODO: check for overflow/underflow auto relative_column = static_cast(static_cast(column_.index) + column_offset); auto relative_row = static_cast(static_cast(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 diff --git a/source/cell/comment.cpp b/source/cell/comment.cpp index a656a1dc..ebb2813c 100644 --- a/source/cell/comment.cpp +++ b/source/cell/comment.cpp @@ -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); } @@ -88,17 +87,17 @@ int comment::left() const { return left_; } - + int comment::top() const { return top_; } - + int comment::width() const { return width_; } - + int comment::height() const { return height_; diff --git a/source/cell/index_types.cpp b/source/cell/index_types.cpp index 5323a272..cd0147eb 100644 --- a/source/cell/index_types.cpp +++ b/source/cell/index_types.cpp @@ -23,9 +23,9 @@ // @author: see AUTHORS file #include -#include #include #include +#include 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(other)); +} -bool column_t::operator==(int other) const { return *this == column_t(static_cast(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) { diff --git a/source/cell/rich_text.cpp b/source/cell/rich_text.cpp index 316f52ed..fb333817 100644 --- a/source/cell/rich_text.cpp +++ b/source/cell/rich_text.cpp @@ -29,12 +29,12 @@ namespace xlnt { rich_text::rich_text(const std::string &plain_text) - : rich_text(rich_text_run{plain_text,{}}) + : rich_text(rich_text_run{plain_text, {}}) { } rich_text::rich_text(const std::string &plain_text, const class font &text_font) - : rich_text(rich_text_run{plain_text,text_font}) + : rich_text(rich_text_run{plain_text, text_font}) { } @@ -51,7 +51,7 @@ void rich_text::clear() void rich_text::plain_text(const std::string &s) { clear(); - add_run(rich_text_run{s,{}}); + add_run(rich_text_run{s, {}}); } std::string rich_text::plain_text() const @@ -73,12 +73,12 @@ void rich_text::add_run(const rich_text_run &t) bool rich_text::operator==(const rich_text &rhs) const { if (runs_.size() != rhs.runs_.size()) return false; - + for (std::size_t i = 0; i < runs_.size(); i++) { - if (runs_[i]!= rhs.runs_[i]) return false; + if (runs_[i] != rhs.runs_[i]) return false; } - + return true; } diff --git a/source/detail/cell_impl.cpp b/source/detail/cell_impl.cpp index ee115c26..82669ec5 100644 --- a/source/detail/cell_impl.cpp +++ b/source/detail/cell_impl.cpp @@ -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) { } diff --git a/source/detail/constants.cpp b/source/detail/constants.cpp index 70421bf6..af202f14 100644 --- a/source/detail/constants.cpp +++ b/source/detail/constants.cpp @@ -22,9 +22,9 @@ // @author: see AUTHORS file #include -#include #include #include +#include namespace xlnt { @@ -32,7 +32,7 @@ row_t constants::min_row() { return 1; } - + row_t constants::max_row() { return std::numeric_limits::max(); @@ -49,57 +49,95 @@ 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 &constants::namespaces() { static const std::unordered_map *namespaces = - new std::unordered_map - { - { "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" }, - { "drawingml", "http://schemas.openxmlformats.org/drawingml/2006/main" }, - { "workbook", "http://schemas.openxmlformats.org/spreadsheetml/2006/main" }, - { "core-properties", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" }, - { "extended-properties", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" }, - { "custom-properties", "http://schemas.openxmlformats.org/officeDocument/2006/customProperties" }, + new std::unordered_map{ + {"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"}, + {"drawingml", "http://schemas.openxmlformats.org/drawingml/2006/main"}, + {"workbook", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"}, + {"core-properties", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"}, + {"extended-properties", "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"}, + {"custom-properties", "http://schemas.openxmlformats.org/officeDocument/2006/customProperties"}, - { "encryption", "http://schemas.microsoft.com/office/2006/encryption" }, - { "encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password" }, - { "encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate" }, + {"encryption", "http://schemas.microsoft.com/office/2006/encryption"}, + {"encryption-password", "http://schemas.microsoft.com/office/2006/keyEncryptor/password"}, + {"encryption-certificate", "http://schemas.microsoft.com/office/2006/keyEncryptor/certificate"}, - { "dc", "http://purl.org/dc/elements/1.1/" }, - { "dcterms", "http://purl.org/dc/terms/" }, - { "dcmitype", "http://purl.org/dc/dcmitype/" }, - { "mc", "http://schemas.openxmlformats.org/markup-compatibility/2006" }, - { "mx", "http://schemas.microsoft.com/office/mac/excel/2008/main" }, - { "r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships" }, - { "thm15", "http://schemas.microsoft.com/office/thememl/2012/main" }, - { "vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" }, - { "x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" }, - { "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" }, + {"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"}, + {"r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"}, + {"thm15", "http://schemas.microsoft.com/office/thememl/2012/main"}, + {"vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"}, + {"x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}, + {"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"}, - { "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; } - } diff --git a/source/detail/custom_value_traits.cpp b/source/detail/custom_value_traits.cpp index 01583602..97eebb93 100644 --- a/source/detail/custom_value_traits.cpp +++ b/source/detail/custom_value_traits.cpp @@ -10,50 +10,54 @@ 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"); } - /// /// Returns the string representation of the relationship type. /// std::string to_string(relationship_type t) { - switch (t) - { - case relationship_type::office_document: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; - case relationship_type::thumbnail: - return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - case relationship_type::calculation_chain: - return "http://purl.oclc.org/ooxml/officeDocument/relationships/calcChain"; - case relationship_type::extended_properties: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; - case relationship_type::core_properties: - return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; - case relationship_type::worksheet: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; - case relationship_type::shared_string_table: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; - case relationship_type::stylesheet: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; - case relationship_type::theme: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; - case relationship_type::hyperlink: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; - case relationship_type::chartsheet: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"; - case relationship_type::comments: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; - case relationship_type::vml_drawing: - return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"; + switch (t) + { + case relationship_type::office_document: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + case relationship_type::thumbnail: + return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; + case relationship_type::calculation_chain: + return "http://purl.oclc.org/ooxml/officeDocument/relationships/calcChain"; + case relationship_type::extended_properties: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; + case relationship_type::core_properties: + return "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; + case relationship_type::worksheet: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"; + case relationship_type::shared_string_table: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; + case relationship_type::stylesheet: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; + case relationship_type::theme: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; + case relationship_type::hyperlink: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; + case relationship_type::chartsheet: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"; + case relationship_type::comments: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; + case relationship_type::vml_drawing: + return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing"; case relationship_type::unknown: return "unknown"; case relationship_type::custom_properties: @@ -98,110 +102,163 @@ std::string to_string(relationship_type t) return "volatile-dependencies"; case relationship_type::image: return "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; - } + } default_case("unknown"); } 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"; - } + 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"; + } default_case("none"); } std::string to_string(gradient_fill_type fill_type) { - return fill_type == gradient_fill_type::linear ? "linear" : "path"; + return fill_type == gradient_fill_type::linear ? "linear" : "path"; } 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"; - } + 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"; + } default_case("none"); } 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"; - } + 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"; + } default_case("top"); } 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"; - } + 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"; + } default_case("general"); } 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"; - } + 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"; + } default_case("top"); } diff --git a/source/detail/number_formatter.cpp b/source/detail/number_formatter.cpp index 439c5b1d..fcfe3bca 100644 --- a/source/detail/number_formatter.cpp +++ b/source/detail/number_formatter.cpp @@ -24,129 +24,48 @@ #include #include +#include #include #include -#include namespace { const std::unordered_map known_locales() { - static const std::unordered_map *all = - new std::unordered_map( - { - { 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 *all = new std::unordered_map( + {{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; } -[[ noreturn ]] void unhandled_case_error() +[[noreturn]] void unhandled_case_error() { throw xlnt::exception("unhandled"); } @@ -178,7 +97,7 @@ bool format_condition::satisfied_by(long double number) const return number < value; case condition_type::not_equal: return std::fabs(number - value) != 0.0L; - case condition_type::equal: + case condition_type::equal: return std::fabs(number - value) == 0.0L; } @@ -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"); } @@ -249,7 +165,7 @@ void number_format_parser::parse() section.parts.push_back(part); part = template_part(); } - + break; } @@ -299,7 +215,7 @@ void number_format_parser::parse() section.condition.type = format_condition::condition_type::equal; value = token.string.substr(1); } - + section.condition.value = std::stold(value); break; } @@ -311,7 +227,7 @@ void number_format_parser::parse() part = template_part(); break; - + case number_format_token::token_type::fill: part.type = template_part::template_type::fill; part.string = token.string; @@ -387,7 +303,7 @@ void number_format_parser::parse() part.type = template_part::template_type::month_letter; break; } - + unhandled_case(true); break; @@ -412,7 +328,7 @@ void number_format_parser::parse() part.type = template_part::template_type::day_name; break; } - + unhandled_case(true); break; @@ -427,7 +343,7 @@ void number_format_parser::parse() part.type = template_part::template_type::year_long; break; } - + unhandled_case(true); break; @@ -442,7 +358,7 @@ void number_format_parser::parse() part.type = template_part::template_type::hour_leading_zero; break; } - + unhandled_case(true); break; @@ -457,7 +373,7 @@ void number_format_parser::parse() part.type = template_part::template_type::second_leading_zero; break; } - + unhandled_case(true); break; @@ -474,7 +390,7 @@ void number_format_parser::parse() part.type = template_part::template_type::a_p; break; } - + unhandled_case(true); break; @@ -485,9 +401,9 @@ void number_format_parser::parse() section.parts.push_back(part); part = template_part(); - + break; - + case number_format_token::token_type::end: codes_.push_back(section); finalize(); @@ -519,7 +435,7 @@ void number_format_parser::finalize() bool fraction = false; std::size_t fraction_denominator_index = 0; std::size_t fraction_numerator_index = 0; - + bool seconds = false; bool fractional_seconds = false; std::size_t seconds_index = 0; @@ -527,10 +443,8 @@ void number_format_parser::finalize() for (std::size_t i = 0; i < code.parts.size(); ++i) { 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) @@ -560,7 +474,7 @@ void number_format_parser::finalize() { percentage = true; } - + if (part.type == template_part::template_type::second || part.type == template_part::template_type::second_leading_zero) { @@ -573,7 +487,7 @@ void number_format_parser::finalize() fractional_seconds = true; } - //TODO this block needs improvement + // TODO this block needs improvement if (part.type == template_part::template_type::month_number || part.type == template_part::template_type::month_number_leading_zero) { @@ -583,11 +497,10 @@ void number_format_parser::finalize() const auto &after_next = code.parts[i + 2]; 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::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,10 +513,9 @@ 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)) + || before_previous.type == template_part::template_type::hour)) { fix = true; leading_zero = part.type == template_part::template_type::month_number_leading_zero; @@ -612,25 +524,23 @@ 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) { code.parts[integer_part_index].placeholders.percentage = true; } - + if (exponent) { const auto &next = code.parts[exponent_index + 1]; @@ -644,25 +554,23 @@ void number_format_parser::finalize() code.parts[i].placeholders.scientific = true; } } - + if (fraction) { code.parts[fraction_numerator_index].placeholders.type = format_placeholders::placeholders_type::fraction_numerator; code.parts[fraction_denominator_index].placeholders.type = format_placeholders::placeholders_type::fraction_denominator; - + 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; } } } - + if (fractional_seconds) { if (code.parts[seconds_index].type == template_part::template_type::second) @@ -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_; @@ -788,7 +693,7 @@ number_format_token number_format_parser::parse_next_token() } break; - + case 'y': case 'm': case 'd': @@ -796,7 +701,7 @@ number_format_token number_format_parser::parse_next_token() case 's': token.type = number_format_token::token_type::datetime; token.string.push_back(current_char); - + while (format_string_[position_] == current_char) { token.string.push_back(current_char); @@ -853,7 +758,7 @@ number_format_token number_format_parser::parse_next_token() case ';': token.type = number_format_token::token_type::end_section; break; - + case '(': token.type = number_format_token::token_type::text; token.string.push_back(current_char); @@ -895,17 +800,17 @@ number_format_token number_format_parser::parse_next_token() token.string.push_back(current_char); break; - + case '@': token.type = number_format_token::token_type::number; token.string.push_back(current_char); break; - + case 'E': token.type = number_format_token::token_type::number; token.string.push_back(current_char); current_char = format_string_[position_++]; - + if (current_char == '+' || current_char == '-') { token.string.push_back(current_char); @@ -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,9 +862,8 @@ 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 - : format_placeholders::placeholders_type::scientific_exponent_minus; + p.type = placeholders_string[1] == '+' ? format_placeholders::placeholders_type::scientific_exponent_plus + : format_placeholders::placeholders_type::scientific_exponent_minus; return p; } else @@ -997,7 +899,7 @@ format_placeholders number_format_parser::parse_placeholders(const std::string & comma_indices.push_back(i); } } - + if (!comma_indices.empty()) { std::size_t i = placeholders_string.size() - 1; @@ -1008,10 +910,10 @@ format_placeholders number_format_parser::parse_placeholders(const std::string & --i; comma_indices.pop_back(); } - + p.use_comma_separator = !comma_indices.empty(); } - + return p; } @@ -1046,7 +948,7 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::blue; } - + unhandled_case(true); break; @@ -1055,7 +957,7 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::green; } - + unhandled_case(true); break; @@ -1064,7 +966,7 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::white; } - + unhandled_case(true); break; @@ -1073,7 +975,7 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::magenta; } - + unhandled_case(true); break; @@ -1082,7 +984,7 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::yellow; } - + unhandled_case(true); break; @@ -1091,14 +993,14 @@ format_color number_format_parser::color_from_string(const std::string &color) { return format_color::red; } - + unhandled_case(true); break; default: unhandled_case(true); } - + unhandled_case_error(); } @@ -1124,7 +1026,7 @@ std::pair number_format_parser::locale_from_string(c { throw std::runtime_error("bad locale: " + locale_string); } - + for (auto c : country_code_string) { if (!((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'))) @@ -1148,8 +1050,7 @@ std::pair 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(); @@ -1168,21 +1069,20 @@ 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); } - + if (format_.size() == 2) { return std::string(11, '#'); } - + return format_number(format_[2], number); } - + // no conditions, format based on sign: // 1 section, use for all @@ -1274,22 +1174,22 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo || p.type == format_placeholders::placeholders_type::fraction_integer) { result = std::to_string(integer_part); - + while (result.size() < p.num_zeros) { result = "0" + result; } - + while (result.size() < p.num_zeros + p.num_spaces) { result = " " + result; } - + if (p.use_comma_separator) { std::vector digits(result.rbegin(), result.rend()); std::string temp; - + for (std::size_t i = 0; i < digits.size(); i++) { temp.push_back(digits[i]); @@ -1299,7 +1199,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo temp.push_back(','); } } - + result = std::string(temp.rbegin(), temp.rend()); } @@ -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::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,11 +1240,10 @@ 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; - + if (number != 0.L) { logarithm = static_cast(std::log10(number)); @@ -1355,7 +1255,7 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol } number /= std::pow(10.L, logarithm); - + auto integer = static_cast(number); auto fraction = number - integer; @@ -1392,7 +1292,7 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol return integer_string + fractional_string + exponent_string; } -std::string number_formatter::fill_fraction_placeholders(const format_placeholders &/*numerator*/, +std::string number_formatter::fill_fraction_placeholders(const format_placeholders & /*numerator*/, const format_placeholders &denominator, long double number, bool /*improper*/) { auto fractional_part = number - static_cast(number); @@ -1407,7 +1307,7 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde fractional_part = static_cast(fractional_part); auto denominator_digits = denominator.num_zeros + denominator.num_optionals + denominator.num_spaces; -// auto denominator_digits = static_cast(std::ceil(std::log10(fractional_part))); + // auto denominator_digits = static_cast(std::ceil(std::log10(fractional_part))); auto lower = static_cast(std::pow(10, denominator_digits - 1)); auto upper = static_cast(std::pow(10, denominator_digits)); @@ -1419,7 +1319,7 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde auto numerator_full = original_fractional_part * i; auto numerator_rounded = static_cast(std::round(numerator_full)); auto difference = std::fabs(original_fractional_part - (numerator_rounded / static_cast(i))); - + if (difference < best_difference) { best_difference = difference; @@ -1433,35 +1333,12 @@ 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 *month_names = - new std::vector - { - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December" - }; + static const std::vector *month_names = new std::vector{"January", "February", "March", + "April", "May", "June", "July", "August", "September", "October", "November", "December"}; static const std::vector *day_names = - new std::vector - { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - }; - + new std::vector{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + std::string result; if (number < 0) @@ -1498,7 +1375,7 @@ std::string number_formatter::format_number(const format_code &format, long doub } } } - + bool improper_fraction = true; std::size_t fill_index = 0; bool fill = false; @@ -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(6), part.placeholders.num_zeros + part.placeholders.num_optionals); + auto digits = std::min( + static_cast(6), part.placeholders.num_zeros + part.placeholders.num_optionals); auto denominator = static_cast(std::pow(10.0, digits)); auto fractional_seconds = dt.microsecond / 1.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(number) + (60 * 60 * dt.hour) + (60 * dt.minute) + dt.second)); + result.append(std::to_string( + 24 * 60 * 60 * static_cast(number) + (60 * 60 * dt.hour) + (60 * dt.minute) + dt.second)); break; case template_part::template_type::month_letter: @@ -1699,9 +1580,9 @@ std::string number_formatter::format_number(const format_code &format, long doub break; } } - + const std::size_t width = 11; - + if (fill && result.size() < width) { auto remaining = width - result.size(); @@ -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; } } diff --git a/source/detail/pole.cpp b/source/detail/pole.cpp index 6dace976..b67674b1 100644 --- a/source/detail/pole.cpp +++ b/source/detail/pole.cpp @@ -1,16 +1,16 @@ /* POLE - Portable C++ library to access OLE Storage Copyright (C) 2002-2007 Ariya Hidayat (ariya@kde.org). - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -23,13 +23,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include #include #include -#include #include @@ -39,66 +39,62 @@ namespace { // helper function: recursively find siblings of index -void dirtree_find_siblings( POLE::DirTree* dirtree, std::vector& result, - std::size_t index ) +void dirtree_find_siblings(POLE::DirTree *dirtree, std::vector &result, std::size_t index) { - auto e = dirtree->entry( index ); - if( !e ) return; - if( !e->valid ) return; - + auto e = dirtree->entry(index); + if (!e) return; + if (!e->valid) return; + // prevent infinite loop - for( std::size_t i = 0; i < result.size(); i++ ) - if( result[i] == index ) return; - + for (std::size_t i = 0; i < result.size(); i++) + if (result[i] == index) return; + // add myself - result.push_back( index ); - + result.push_back(index); + // visit previous sibling, don't go infinitely std::size_t prev = e->prev; - if( ( prev > 0 ) && ( prev < dirtree->entryCount() ) ) + if ((prev > 0) && (prev < dirtree->entryCount())) { - for( std::size_t i = 0; i < result.size(); i++ ) - if( result[i] == prev ) prev = 0; - if( prev ) dirtree_find_siblings( dirtree, result, prev ); + for (std::size_t i = 0; i < result.size(); i++) + if (result[i] == prev) prev = 0; + if (prev) dirtree_find_siblings(dirtree, result, prev); } - + // visit next sibling, don't go infinitely std::size_t next = e->next; - if( ( next > 0 ) && ( next < dirtree->entryCount() ) ) + if ((next > 0) && (next < dirtree->entryCount())) { - for( std::size_t i = 0; i < result.size(); i++ ) - if( result[i] == next ) next = 0; - if( next ) dirtree_find_siblings( dirtree, result, next ); + for (std::size_t i = 0; i < result.size(); i++) + if (result[i] == next) next = 0; + if (next) dirtree_find_siblings(dirtree, result, next); } } - } -namespace POLE -{ - - +namespace POLE { + } // namespace POLE using namespace POLE; -static inline std::uint16_t readU16(const std::uint8_t* ptr) +static inline std::uint16_t readU16(const std::uint8_t *ptr) { return static_cast(ptr[0] + (ptr[1] << 8)); } -static inline std::uint32_t readU32(const std::uint8_t* ptr) +static inline std::uint32_t readU32(const std::uint8_t *ptr) { return static_cast(ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24)); } -static inline void writeU16( std::uint8_t* ptr, std::uint16_t data ) +static inline void writeU16(std::uint8_t *ptr, std::uint16_t data) { ptr[0] = static_cast(data & 0xff); ptr[1] = static_cast((data >> 8) & 0xff); } -static inline void writeU32( std::uint8_t* ptr, std::uint32_t data ) +static inline void writeU32(std::uint8_t *ptr, std::uint32_t data) { ptr[0] = static_cast(data & 0xff); ptr[1] = static_cast((data >> 8) & 0xff); @@ -106,81 +102,80 @@ static inline void writeU32( std::uint8_t* ptr, std::uint32_t data ) ptr[3] = static_cast((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 ), -s_shift( 6 ), -num_bat( 0 ), -dirent_start( 0 ), -threshold( 4096 ), -sbat_start( 0 ), -num_sbat( 0 ), -mbat_start( 0 ), -num_mbat( 0 ) +Header::Header() + : b_shift(9), + s_shift(6), + num_bat(0), + dirent_start(0), + threshold(4096), + sbat_start(0), + num_sbat(0), + mbat_start(0), + num_mbat(0) { - for( std::size_t i = 0; i < 8; i++ ) + for (std::size_t i = 0; i < 8; i++) id[i] = pole_magic[i]; - for( std::size_t i=0; i<109; i++ ) + for (std::size_t i = 0; i < 109; i++) bb_blocks[i] = AllocTable::Avail; } bool Header::valid() { - if( threshold != 4096 ) return false; - if( num_bat == 0 ) return false; - if( (num_bat > 109) && (num_bat > (num_mbat * 127) + 109)) return false; - if( (num_bat < 109) && (num_mbat != 0) ) return false; - if( s_shift > b_shift ) return false; - if( b_shift <= 6 ) return false; - if( b_shift >=31 ) return false; - + if (threshold != 4096) return false; + if (num_bat == 0) return false; + if ((num_bat > 109) && (num_bat > (num_mbat * 127) + 109)) return false; + if ((num_bat < 109) && (num_mbat != 0)) return false; + if (s_shift > b_shift) return false; + if (b_shift <= 6) return false; + if (b_shift >= 31) return false; + return true; } -void Header::load( const std::uint8_t* buffer ) +void Header::load(const std::uint8_t *buffer) { - b_shift = readU16( buffer + 0x1e ); - s_shift = readU16( buffer + 0x20 ); - num_bat = readU32( buffer + 0x2c ); - dirent_start = readU32( buffer + 0x30 ); - threshold = readU32( buffer + 0x38 ); - sbat_start = readU32( buffer + 0x3c ); - num_sbat = readU32( buffer + 0x40 ); - mbat_start = readU32( buffer + 0x44 ); - num_mbat = readU32( buffer + 0x48 ); - - for( std::size_t i = 0; i < 8; i++ ) + b_shift = readU16(buffer + 0x1e); + s_shift = readU16(buffer + 0x20); + num_bat = readU32(buffer + 0x2c); + dirent_start = readU32(buffer + 0x30); + threshold = readU32(buffer + 0x38); + sbat_start = readU32(buffer + 0x3c); + num_sbat = readU32(buffer + 0x40); + mbat_start = readU32(buffer + 0x44); + num_mbat = readU32(buffer + 0x48); + + for (std::size_t i = 0; i < 8; i++) id[i] = buffer[i]; - for( std::size_t i=0; i<109; i++ ) - bb_blocks[i] = readU32( buffer + 0x4C+i*4 ); + for (std::size_t i = 0; i < 109; i++) + bb_blocks[i] = readU32(buffer + 0x4C + i * 4); } -void Header::save( std::uint8_t* buffer ) +void Header::save(std::uint8_t *buffer) { - memset( buffer, 0, 0x4c ); - memcpy( buffer, pole_magic, 8 ); // ole signature - writeU32( buffer + 8, 0 ); // unknown - writeU32( buffer + 12, 0 ); // unknown - writeU32( buffer + 16, 0 ); // unknown - writeU16( buffer + 24, 0x003e ); // revision ? - writeU16( buffer + 26, 3 ); // version ? - writeU16( buffer + 28, 0xfffe ); // unknown - writeU16( buffer + 0x1e, b_shift ); - writeU16( buffer + 0x20, s_shift ); - writeU32( buffer + 0x2c, num_bat ); - writeU32( buffer + 0x30, dirent_start ); - writeU32( buffer + 0x38, threshold ); - writeU32( buffer + 0x3c, sbat_start ); - writeU32( buffer + 0x40, num_sbat ); - writeU32( buffer + 0x44, mbat_start ); - writeU32( buffer + 0x48, num_mbat ); - - for( std::size_t i=0; i<109; i++ ) - writeU32( buffer + 0x4C+i*4, bb_blocks[i] ); + memset(buffer, 0, 0x4c); + memcpy(buffer, pole_magic, 8); // ole signature + writeU32(buffer + 8, 0); // unknown + writeU32(buffer + 12, 0); // unknown + writeU32(buffer + 16, 0); // unknown + writeU16(buffer + 24, 0x003e); // revision ? + writeU16(buffer + 26, 3); // version ? + writeU16(buffer + 28, 0xfffe); // unknown + writeU16(buffer + 0x1e, b_shift); + writeU16(buffer + 0x20, s_shift); + writeU32(buffer + 0x2c, num_bat); + writeU32(buffer + 0x30, dirent_start); + writeU32(buffer + 0x38, threshold); + writeU32(buffer + 0x3c, sbat_start); + writeU32(buffer + 0x40, num_sbat); + writeU32(buffer + 0x44, mbat_start); + writeU32(buffer + 0x48, num_mbat); + + for (std::size_t i = 0; i < 109; i++) + writeU32(buffer + 0x4C + i * 4, bb_blocks[i]); } void Header::debug() @@ -195,10 +190,10 @@ void Header::debug() std::cout << "num_sbat " << num_sbat << std::endl; std::cout << "mbat_start " << mbat_start << std::endl; std::cout << "num_mbat " << num_mbat << std::endl; - - std::size_t s = (num_bat<=109) ? num_bat : 109; + + std::size_t s = (num_bat <= 109) ? num_bat : 109; std::cout << "bat blocks: "; - for( std::size_t i = 0; i < s; i++ ) + for (std::size_t i = 0; i < s; i++) std::cout << bb_blocks[i] << " "; std::cout << std::endl; } @@ -210,10 +205,11 @@ 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 ); + resize(128); } std::size_t AllocTable::count() @@ -221,96 +217,94 @@ std::size_t AllocTable::count() return data.size(); } -void AllocTable::resize( std::size_t newsize ) +void AllocTable::resize(std::size_t newsize) { std::size_t oldsize = data.size(); - data.resize( newsize ); - if( newsize > oldsize ) - for( std::size_t i = oldsize; i oldsize) + for (std::size_t i = oldsize; i < newsize; i++) data[i] = Avail; } // make sure there're still free blocks -void AllocTable::preserve( std::size_t n ) +void AllocTable::preserve(std::size_t n) { std::vector pre; - for( std::size_t i=0; i < n; i++ ) - pre.push_back( unused() ); + for (std::size_t i = 0; i < n; i++) + pre.push_back(unused()); } -std::size_t AllocTable::operator[]( std::size_t index ) +std::size_t AllocTable::operator[](std::size_t index) { std::size_t result; result = data[index]; return result; } -void AllocTable::set( std::size_t index, std::uint32_t value ) +void AllocTable::set(std::size_t index, std::uint32_t value) { - if( index >= count() ) resize( index + 1); - data[ index ] = value; + if (index >= count()) resize(index + 1); + data[index] = value; } -void AllocTable::setChain( std::vector chain ) +void AllocTable::setChain(std::vector chain) { - if( chain.size() ) + if (chain.size()) { - for( std::size_t i=0; i& chain, - std::size_t item) +static bool already_exist(const std::vector &chain, std::size_t item) { - for(std::size_t i = 0; i < chain.size(); i++) - if(chain[i] == item) return true; - + for (std::size_t i = 0; i < chain.size(); i++) + if (chain[i] == item) return true; + return false; } // follow -std::vector AllocTable::follow( std::size_t start ) +std::vector AllocTable::follow(std::size_t start) { std::vector chain; - - if( start >= count() ) return chain; - + + if (start >= count()) return chain; + std::size_t p = start; - while( p < count() ) + while (p < count()) { - if( p == static_cast(Eof) ) break; - if( p == static_cast(Bat) ) break; - if( p == static_cast(MetaBat) ) break; - if( already_exist(chain, p) ) break; + if (p == static_cast(Eof)) break; + if (p == static_cast(Bat)) break; + if (p == static_cast(MetaBat)) break; + if (already_exist(chain, p)) break; chain.push_back(p); - if( data[p] >= count() ) break; - p = data[ p ]; + if (data[p] >= count()) break; + p = data[p]; } - + return chain; } 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; - + for (std::size_t i = 0; i < data.size(); i++) + if (data[i] == Avail) return i; + // completely full, so enlarge the table std::size_t block = data.size(); - resize( data.size()+10 ); + resize(data.size() + 10); return block; } -void AllocTable::load( const std::uint8_t* buffer, std::size_t len ) +void AllocTable::load(const std::uint8_t *buffer, std::size_t len) { - resize( len / 4 ); - for( std::size_t i = 0; i < count(); i++ ) - set( i, readU32( buffer + i*4 ) ); + resize(len / 4); + for (std::size_t i = 0; i < count(); i++) + set(i, readU32(buffer + i * 4)); } // return space required to save this dirtree @@ -319,23 +313,27 @@ std::size_t AllocTable::size() return count() * 4; } -void AllocTable::save( std::uint8_t* buffer ) +void AllocTable::save(std::uint8_t *buffer) { - for( std::size_t i = 0; i < count(); i++ ) - writeU32( buffer + i*4, data[i] ); + for (std::size_t i = 0; i < count(); i++) + writeU32(buffer + i * 4, data[i]); } void AllocTable::debug() { std::cout << "block size " << data.size() << std::endl; - for( std::size_t i=0; i< data.size(); i++ ) + for (std::size_t i = 0; i < data.size(); i++) { - if( data[i] == Avail ) continue; + 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(); } @@ -352,7 +351,7 @@ DirTree::DirTree(): entries() void DirTree::clear() { // leave only root entry - entries.resize( 1 ); + entries.resize(1); entries[0].valid = true; entries[0].name = "Root Entry"; entries[0].dir = true; @@ -368,55 +367,54 @@ std::size_t DirTree::entryCount() return entries.size(); } -DirEntry* DirTree::entry( std::size_t index ) +DirEntry *DirTree::entry(std::size_t index) { - if( index >= entryCount() ) return nullptr; - return &entries[ index ]; + if (index >= entryCount()) return nullptr; + return &entries[index]; } -std::ptrdiff_t DirTree::indexOf( DirEntry* e ) +std::ptrdiff_t DirTree::indexOf(DirEntry *e) { - for( std::size_t i = 0; i < entryCount(); i++ ) - if( entry( i ) == e ) return static_cast(i); - + for (std::size_t i = 0; i < entryCount(); i++) + if (entry(i) == e) return static_cast(i); + return -1; } -std::ptrdiff_t DirTree::parent( std::size_t index ) +std::ptrdiff_t DirTree::parent(std::size_t index) { // brute-force, basically we iterate for each entries, find its children // and check if one of the children is 'index' - for( std::size_t j=0; j chi = children( j ); - for( std::size_t i=0; i(j); + std::vector chi = children(j); + for (std::size_t i = 0; i < chi.size(); i++) + if (chi[i] == index) return static_cast(j); } - + return -1; } -std::string DirTree::fullName( std::size_t index ) +std::string DirTree::fullName(std::size_t index) { // don't use root name ("Root Entry"), just give "/" - if( index == 0 ) return "/"; - - std::string result = entry( index )->name; - result.insert( 0, "/" ); - auto p = parent( index ); - DirEntry * _entry = 0; - while( p > 0 ) + if (index == 0) return "/"; + + std::string result = entry(index)->name; + result.insert(0, "/"); + auto p = parent(index); + DirEntry *_entry = 0; + while (p > 0) { - _entry = entry( static_cast(p) ); + _entry = entry(static_cast(p)); if (_entry->dir && _entry->valid) { - result.insert( 0, _entry->name); - result.insert( 0, "/" ); + result.insert(0, _entry->name); + result.insert(0, "/"); } --p; index = static_cast(p); - if( p <= 0 ) break; + if (p <= 0) break; } return result; } @@ -424,58 +422,58 @@ std::string DirTree::fullName( std::size_t index ) // given a fullname (e.g "/ObjectPool/_1020961869"), find the entry // if not found and create is false, return 0 // if create is true, a new entry is returned -DirEntry* DirTree::entry( const std::string& name, bool create ) +DirEntry *DirTree::entry(const std::string &name, bool create) { - if( !name.length() ) return nullptr; - + if (!name.length()) return nullptr; + // quick check for "/" (that's root) - if( name == "/" ) return entry( 0 ); - + if (name == "/") return entry(0); + // split the names, e.g "/ObjectPool/_1020961869" will become: // "ObjectPool" and "_1020961869" std::list names; std::string::size_type start = 0, end = 0; - if( name[0] == '/' ) start++; - while( start < name.length() ) + if (name[0] == '/') start++; + while (start < name.length()) { - end = name.find_first_of( '/', start ); - if( end == std::string::npos ) end = name.length(); - names.push_back( name.substr( start, end-start ) ); - start = end+1; + end = name.find_first_of('/', start); + if (end == std::string::npos) end = name.length(); + names.push_back(name.substr(start, end - start)); + start = end + 1; } - + // start from root - std::size_t index = 0 ; - + std::size_t index = 0; + // trace one by one std::list::iterator it; - - for( it = names.begin(); it != names.end(); ++it ) + + for (it = names.begin(); it != names.end(); ++it) { // find among the children of index - std::vector chi = children( index ); + std::vector chi = children(index); std::ptrdiff_t child = 0; - for( std::size_t i = 0; i < chi.size(); i++ ) + for (std::size_t i = 0; i < chi.size(); i++) { - DirEntry* ce = entry( chi[i] ); - if( ce ) - if( ce->valid && ( ce->name.length()>1 ) ) - if( ce->name == *it ) - child = static_cast(chi[i]); + DirEntry *ce = entry(chi[i]); + if (ce) + if (ce->valid && (ce->name.length() > 1)) + if (ce->name == *it) child = static_cast(chi[i]); } - + // traverse to the child - if( child > 0 ) index = static_cast(child); + if (child > 0) + index = static_cast(child); else { // not found among children - if( !create ) return nullptr; - + if (!create) return nullptr; + // create a new entry std::size_t parent = index; - entries.push_back( DirEntry() ); - index = entryCount()-1; - DirEntry* e = entry( index ); + entries.push_back(DirEntry()); + index = entryCount() - 1; + DirEntry *e = entry(index); e->valid = true; e->name = *it; e->dir = false; @@ -487,60 +485,60 @@ DirEntry* DirTree::entry( const std::string& name, bool create ) entry(parent)->child = static_cast(index); } } - - return entry( index ); + + return entry(index); } -std::vector DirTree::children( std::size_t index ) +std::vector DirTree::children(std::size_t index) { std::vector result; - - DirEntry* e = entry( index ); - if( e ) if( e->valid && e->child < entryCount() ) - dirtree_find_siblings( this, result, e->child ); - + + DirEntry *e = entry(index); + if (e) + if (e->valid && e->child < entryCount()) dirtree_find_siblings(this, result, e->child); + return result; } -void DirTree::load( std::uint8_t* buffer, std::size_t size ) +void DirTree::load(std::uint8_t *buffer, std::size_t size) { entries.clear(); - - for( std::size_t i = 0; i < size/128; i++ ) + + for (std::size_t i = 0; i < size / 128; i++) { std::size_t p = i * 128; - + // parse name of this entry, which stored as Unicode 16-bit std::string name; - auto name_len = static_cast(readU16( buffer + 0x40+p )); - if( name_len > 64 ) name_len = 64; - for( std::size_t j=0; ( buffer[j+p]) && (j(buffer[j+p]) ); - + auto name_len = static_cast(readU16(buffer + 0x40 + p)); + if (name_len > 64) name_len = 64; + for (std::size_t j = 0; (buffer[j + p]) && (j < name_len); j += 2) + name.append(1, static_cast(buffer[j + p])); + // first char isn't printable ? remove it... - if( buffer[p] < 32 ) + if (buffer[p] < 32) { - name.erase( 0,1 ); + name.erase(0, 1); } - + // 2 = file (aka stream), 1 = directory (aka storage), 5 = root - std::size_t type = buffer[ 0x42 + p]; - + std::size_t type = buffer[0x42 + p]; + DirEntry e; e.valid = true; e.name = name; - e.start = readU32( buffer + 0x74+p ); - e.size = readU32( buffer + 0x78+p ); - e.prev = readU32( buffer + 0x44+p ); - e.next = readU32( buffer + 0x48+p ); - e.child = readU32( buffer + 0x4C+p ); - e.dir = ( type!=2 ); - + e.start = readU32(buffer + 0x74 + p); + e.size = readU32(buffer + 0x78 + p); + e.prev = readU32(buffer + 0x44 + p); + e.next = readU32(buffer + 0x48 + p); + e.child = readU32(buffer + 0x4C + p); + e.dir = (type != 2); + // sanity checks - if( (type != 2) && (type != 1 ) && (type != 5 ) ) e.valid = false; - if( name_len < 1 ) e.valid = false; - - entries.push_back( e ); + if ((type != 2) && (type != 1) && (type != 5)) e.valid = false; + if (name_len < 1) e.valid = false; + + entries.push_back(e); } } @@ -550,73 +548,83 @@ std::size_t DirTree::size() return entryCount() * 128; } -void DirTree::save( std::uint8_t* buffer ) +void DirTree::save(std::uint8_t *buffer) { - memset( buffer, 0, size() ); - + memset(buffer, 0, size()); + // root is fixed as "Root Entry" - DirEntry* root = entry( 0 ); + DirEntry *root = entry(0); std::string entry_name = "Root Entry"; - for( std::size_t j = 0; j < entry_name.length(); j++ ) - buffer[ j*2 ] = static_cast(entry_name[j]); - writeU16( buffer + 0x40, static_cast(entry_name.length()*2 + 2) ); - writeU32( buffer + 0x74, 0xffffffff ); - writeU32( buffer + 0x78, 0 ); - writeU32( buffer + 0x44, 0xffffffff ); - writeU32( buffer + 0x48, 0xffffffff ); - writeU32( buffer + 0x4c, root->child ); - buffer[ 0x42 ] = 5; - buffer[ 0x43 ] = 1; - - for( std::size_t i = 1; i < entryCount(); i++ ) + for (std::size_t j = 0; j < entry_name.length(); j++) + buffer[j * 2] = static_cast(entry_name[j]); + writeU16(buffer + 0x40, static_cast(entry_name.length() * 2 + 2)); + writeU32(buffer + 0x74, 0xffffffff); + writeU32(buffer + 0x78, 0); + writeU32(buffer + 0x44, 0xffffffff); + writeU32(buffer + 0x48, 0xffffffff); + writeU32(buffer + 0x4c, root->child); + buffer[0x42] = 5; + buffer[0x43] = 1; + + for (std::size_t i = 1; i < entryCount(); i++) { - DirEntry* e = entry( i ); - if( !e ) continue; - if( e->dir ) + DirEntry *e = entry(i); + if (!e) continue; + if (e->dir) { e->start = 0xffffffff; e->size = 0; } - + // 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++ ) - buffer[ i*128 + j*2 ] = static_cast(entry_name[j]); - - writeU16( buffer + i*128 + 0x40, static_cast(entry_name.length()*2 + 2) ); - writeU32( buffer + i*128 + 0x74, e->start ); - writeU32( buffer + i*128 + 0x78, e->size ); - writeU32( buffer + i*128 + 0x44, e->prev ); - writeU32( buffer + i*128 + 0x48, e->next ); - writeU32( buffer + i*128 + 0x4c, e->child ); - buffer[ i*128 + 0x42 ] = e->dir ? 1 : 2; - buffer[ i*128 + 0x43 ] = 1; // always black + for (std::size_t j = 0; j < entry_name.length(); j++) + buffer[i * 128 + j * 2] = static_cast(entry_name[j]); + + writeU16(buffer + i * 128 + 0x40, static_cast(entry_name.length() * 2 + 2)); + writeU32(buffer + i * 128 + 0x74, e->start); + writeU32(buffer + i * 128 + 0x78, e->size); + writeU32(buffer + i * 128 + 0x44, e->prev); + writeU32(buffer + i * 128 + 0x48, e->next); + writeU32(buffer + i * 128 + 0x4c, e->child); + buffer[i * 128 + 0x42] = e->dir ? 1 : 2; + buffer[i * 128 + 0x43] = 1; // always black } } void DirTree::debug() { - for( std::size_t i = 0; i < entryCount(); i++ ) + for (std::size_t i = 0; i < entryCount(); i++) { - DirEntry* e = entry( i ); - if( !e ) continue; + DirEntry *e = entry(i); + if (!e) continue; std::cout << i << ": "; - if( !e->valid ) std::cout << "INVALID "; + 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,19 +632,19 @@ void DirTree::debug() // =========== StorageIO ========== -StorageIO::StorageIO( Storage* st, char* bytes, std::size_t length ): -storage( st ), -filedata(reinterpret_cast(bytes)), -dataLength(length), -result( Storage::Ok ), -opened( false ), -filesize( 0 ), -header( new Header() ), -dirtree( new DirTree() ), -bbat ( new AllocTable() ), -sbat ( new AllocTable() ), -sb_blocks(), -streams() +StorageIO::StorageIO(Storage *st, char *bytes, std::size_t length) + : storage(st), + filedata(reinterpret_cast(bytes)), + dataLength(length), + result(Storage::Ok), + opened(false), + filesize(0), + header(new Header()), + dirtree(new DirTree()), + bbat(new AllocTable()), + sbat(new AllocTable()), + sb_blocks(), + streams() { bbat->blockSize = static_cast(1) << header->b_shift; sbat->blockSize = static_cast(1) << header->s_shift; @@ -644,7 +652,7 @@ streams() StorageIO::~StorageIO() { - if( opened ) close(); + if (opened) close(); delete sbat; delete bbat; delete dirtree; @@ -654,124 +662,127 @@ StorageIO::~StorageIO() bool StorageIO::open() { // already opened ? close first - if( opened ) close(); - + if (opened) close(); + load(); - + return result == Storage::Ok; } void StorageIO::load() { - std::uint8_t* buffer = 0; + std::uint8_t *buffer = 0; std::size_t buflen = 0; std::vector blocks; - + // open the file, check for error result = Storage::OpenFailed; - //FSTREAM file.open( filename.c_str(), std::ios::binary | std::ios::in ); - //FSTREAM if( !file.good() ) return; - + // FSTREAM file.open( filename.c_str(), std::ios::binary | std::ios::in ); + // FSTREAM if( !file.good() ) return; + // find size of input file - //FSTREAM file.seekg( 0, std::ios::end ); - //FSTREAM filesize = file.tellg(); + // FSTREAM file.seekg( 0, std::ios::end ); + // FSTREAM filesize = file.tellg(); filesize = dataLength; - + // load header buffer = new std::uint8_t[512]; - //FSTREAM file.seekg( 0 ); - //FSTREAM file.read( (char*)buffer, 512 ); + // FSTREAM file.seekg( 0 ); + // FSTREAM file.read( (char*)buffer, 512 ); memcpy(buffer, filedata, 512); - header->load( buffer ); + header->load(buffer); delete[] buffer; - + // check OLE magic id result = Storage::NotOLE; - for( std::size_t i=0; i<8; i++ ) - if( header->id[i] != pole_magic[i] ) - return; - + for (std::size_t i = 0; i < 8; i++) + if (header->id[i] != pole_magic[i]) return; + // sanity checks result = Storage::BadOLE; - if( !header->valid() ) return; - if( header->threshold != 4096 ) return; - + if (!header->valid()) return; + if (header->threshold != 4096) return; + // important block size bbat->blockSize = static_cast(1) << header->b_shift; sbat->blockSize = static_cast(1) << header->s_shift; - + // find blocks allocated to store big bat // the first 109 blocks are in header, the rest in meta bat 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( (header->num_bat > 109) && (header->num_mbat > 0) ) + 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 ((header->num_bat > 109) && (header->num_mbat > 0)) { - std::uint8_t* buffer2 = new std::uint8_t[ bbat->blockSize ]; + std::uint8_t *buffer2 = new std::uint8_t[bbat->blockSize]; memset(buffer2, 0, bbat->blockSize); std::size_t k = 109; std::size_t mblock = header->mbat_start; - for( std::size_t r = 0; r < header->num_mbat; r++ ) + for (std::size_t r = 0; r < header->num_mbat; r++) { - loadBigBlock( mblock, buffer2, bbat->blockSize ); - for( std::size_t s=0; s < bbat->blockSize-4; s+=4 ) + 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 ); + mblock = readU32(buffer2 + bbat->blockSize - 4); } delete[] buffer2; } - + // load big bat - buflen = blocks.size()*bbat->blockSize; - if( buflen > 0 ) + buflen = blocks.size() * bbat->blockSize; + if (buflen > 0) { - buffer = new std::uint8_t[ buflen ]; + buffer = new std::uint8_t[buflen]; memset(buffer, 0, buflen); - loadBigBlocks( blocks, buffer, buflen ); - bbat->load( buffer, buflen ); + loadBigBlocks(blocks, buffer, buflen); + bbat->load(buffer, buflen); delete[] buffer; } - + // load small bat blocks.clear(); - blocks = bbat->follow( header->sbat_start ); - buflen = blocks.size()*bbat->blockSize; - if( buflen > 0 ) + blocks = bbat->follow(header->sbat_start); + buflen = blocks.size() * bbat->blockSize; + if (buflen > 0) { - buffer = new std::uint8_t[ buflen ]; + buffer = new std::uint8_t[buflen]; memset(buffer, 0, buflen); - loadBigBlocks( blocks, buffer, buflen ); - sbat->load( buffer, buflen ); + loadBigBlocks(blocks, buffer, buflen); + sbat->load(buffer, buflen); delete[] buffer; } - + // load directory tree blocks.clear(); - blocks = bbat->follow( header->dirent_start ); - buflen = blocks.size()*bbat->blockSize; - buffer = new std::uint8_t[ buflen ]; + blocks = bbat->follow(header->dirent_start); + buflen = blocks.size() * bbat->blockSize; + buffer = new std::uint8_t[buflen]; memset(buffer, 0, buflen); - loadBigBlocks( blocks, buffer, buflen ); - dirtree->load( buffer, buflen ); - std::size_t sb_start = readU32( buffer + 0x74 ); + loadBigBlocks(blocks, buffer, buflen); + dirtree->load(buffer, buflen); + std::size_t sb_start = readU32(buffer + 0x74); delete[] buffer; - + // fetch block chain as data for small-files - sb_blocks = bbat->follow( sb_start ); // small files - - // for troubleshooting, just enable this block + sb_blocks = bbat->follow(sb_start); // small files + +// for troubleshooting, just enable this block #if 0 header->debug(); sbat->debug(); bbat->debug(); dirtree->debug(); #endif - + // so far so good result = Storage::Ok; opened = true; @@ -780,7 +791,7 @@ void StorageIO::load() void StorageIO::create() { // std::cout << "Creating " << filename << std::endl; - + /*FSTREAM file.open( filename.c_str(), std::ios::out|std::ios::binary ); if( !file.good() ) { @@ -788,7 +799,7 @@ void StorageIO::create() result = Storage::OpenFailed; return; }*/ - + // so far so good opened = true; result = Storage::Ok; @@ -805,144 +816,140 @@ void StorageIO::flush() void StorageIO::close() { - if( !opened ) return; - - //FSTREAM file.close(); + if (!opened) return; + + // FSTREAM file.close(); opened = false; - - std::list::iterator it; - for( it = streams.begin(); it != streams.end(); ++it ) + + std::list::iterator it; + for (it = streams.begin(); it != streams.end(); ++it) delete *it; } -StreamIO* StorageIO::streamIO( const std::string& name ) +StreamIO *StorageIO::streamIO(const std::string &name) { // sanity check - if( !name.length() ) return nullptr; - + if (!name.length()) return nullptr; + // search in the entries - DirEntry* entry = dirtree->entry( name ); - //if( entry) std::cout << "FOUND\n"; - if( !entry ) return nullptr; - //if( !entry->dir ) std::cout << " NOT DIR\n"; - if( entry->dir ) return nullptr; - - StreamIO* stream = new StreamIO( this, entry ); + DirEntry *entry = dirtree->entry(name); + // if( entry) std::cout << "FOUND\n"; + if (!entry) return nullptr; + // if( !entry->dir ) std::cout << " NOT DIR\n"; + if (entry->dir) return nullptr; + + StreamIO *stream = new StreamIO(this, entry); stream->fullName = name; - + return stream; } -std::size_t StorageIO::loadBigBlocks( std::vector blocks, - std::uint8_t* data, std::size_t maxlen ) +std::size_t StorageIO::loadBigBlocks(std::vector blocks, std::uint8_t *data, std::size_t maxlen) { // sentinel - if( !data ) return 0; - if( blocks.size() < 1 ) return 0; - if( maxlen == 0 ) return 0; - + if (!data) return 0; + if (blocks.size() < 1) return 0; + if (maxlen == 0) return 0; + // read block one by one, seems fast enough std::size_t bytes = 0; - for( std::size_t i=0; (i < blocks.size() ) && ( bytesblockSize * ( block+1 ); - std::size_t p = (bbat->blockSize < maxlen-bytes) ? bbat->blockSize : maxlen-bytes; - if( pos + p > filesize ) p = filesize - pos; - //FSTREAM file.seekg( pos ); - //FSTREAM file.read( (char*)data + bytes, p ); + std::size_t pos = bbat->blockSize * (block + 1); + std::size_t p = (bbat->blockSize < maxlen - bytes) ? bbat->blockSize : maxlen - bytes; + if (pos + p > filesize) p = filesize - pos; + // FSTREAM file.seekg( pos ); + // FSTREAM file.read( (char*)data + bytes, p ); memcpy(reinterpret_cast(data) + bytes, filedata + pos, p); bytes += p; } - + 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; - + if (!data) return 0; + // wraps call for loadBigBlocks std::vector blocks; - blocks.resize( 1 ); - blocks[ 0 ] = block; - - return loadBigBlocks( blocks, data, maxlen ); + blocks.resize(1); + blocks[0] = block; + + return loadBigBlocks(blocks, data, maxlen); } // return number of bytes which has been read -std::size_t StorageIO::loadSmallBlocks( std::vector blocks, - std::uint8_t* data, std::size_t maxlen ) +std::size_t StorageIO::loadSmallBlocks(std::vector blocks, std::uint8_t *data, std::size_t maxlen) { // sentinel - if( !data ) return 0; - if( blocks.size() < 1 ) return 0; - if( maxlen == 0 ) return 0; - + if (!data) return 0; + if (blocks.size() < 1) return 0; + if (maxlen == 0) return 0; + // our own local buffer - std::uint8_t* buf = new std::uint8_t[ bbat->blockSize ]; - + std::uint8_t *buf = new std::uint8_t[bbat->blockSize]; + // read small block one by one std::size_t bytes = 0; - for( std::size_t i=0; ( iblockSize; std::size_t bbindex = pos / bbat->blockSize; - if( bbindex >= sb_blocks.size() ) break; - - loadBigBlock( sb_blocks[ bbindex ], buf, bbat->blockSize ); - + if (bbindex >= sb_blocks.size()) break; + + loadBigBlock(sb_blocks[bbindex], buf, bbat->blockSize); + // copy the data std::size_t offset = pos % bbat->blockSize; - std::size_t p = (maxlen-bytes < bbat->blockSize-offset ) ? maxlen-bytes : bbat->blockSize-offset; - p = (sbat->blockSize

blockSize : p; - memcpy( data + bytes, buf + offset, p ); + std::size_t p = (maxlen - bytes < bbat->blockSize - offset) ? maxlen - bytes : bbat->blockSize - offset; + p = (sbat->blockSize < p) ? sbat->blockSize : p; + memcpy(data + bytes, buf + offset, p); bytes += p; } - + delete[] buf; - + 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; - + if (!data) return 0; + // wraps call for loadSmallBlocks std::vector blocks; - blocks.resize( 1 ); - blocks.assign( 1, block ); - - return loadSmallBlocks( blocks, data, maxlen ); + blocks.resize(1); + blocks.assign(1, block); + + return loadSmallBlocks(blocks, data, maxlen); } // =========== StreamIO ========== -StreamIO::StreamIO( StorageIO* s, DirEntry* e ): -io( s ), -entry( e ), -fullName(), -eof( false ), -fail( false ), -blocks(), -m_pos( 0 ), -cache_data( 0 ), -cache_size( 4096 ), // optimal ? -cache_pos( 0 ) +StreamIO::StreamIO(StorageIO *s, DirEntry *e) + : io(s), + entry(e), + fullName(), + eof(false), + fail(false), + blocks(), + m_pos(0), + cache_data(0), + cache_size(4096), // optimal ? + cache_pos(0) { - if( entry->size >= io->header->threshold ) - blocks = io->bbat->follow( entry->start ); + if (entry->size >= io->header->threshold) + blocks = io->bbat->follow(entry->start); else - blocks = io->sbat->follow( entry->start ); - + blocks = io->sbat->follow(entry->start); + // prepare cache cache_data = new std::uint8_t[cache_size]; updateCache(); @@ -954,7 +961,7 @@ StreamIO::~StreamIO() delete[] cache_data; } -void StreamIO::seek( std::size_t pos ) +void StreamIO::seek(std::size_t pos) { m_pos = pos; } @@ -967,83 +974,79 @@ std::size_t StreamIO::tell() int StreamIO::getch() { // past end-of-file ? - if( m_pos > entry->size ) return -1; - + 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; - + if (!cache_size) return -1; + int data = cache_data[m_pos - cache_pos]; m_pos++; - + return data; } -std::size_t StreamIO::read( std::size_t pos, std::uint8_t* data, std::size_t maxlen ) +std::size_t StreamIO::read(std::size_t pos, std::uint8_t *data, std::size_t maxlen) { // sanity checks - if( !data ) return 0; - if( maxlen == 0 ) return 0; - + if (!data) return 0; + if (maxlen == 0) return 0; + std::size_t totalbytes = 0; - - if ( entry->size < io->header->threshold ) + + if (entry->size < io->header->threshold) { // small file std::size_t index = pos / io->sbat->blockSize; - - if( index >= blocks.size() ) return 0; - - std::uint8_t* buf = new std::uint8_t[ io->sbat->blockSize ]; + + if (index >= blocks.size()) return 0; + + std::uint8_t *buf = new std::uint8_t[io->sbat->blockSize]; std::size_t offset = pos % io->sbat->blockSize; - while( totalbytes < maxlen ) + while (totalbytes < maxlen) { - if( index >= blocks.size() ) break; - io->loadSmallBlock( blocks[index], buf, io->bbat->blockSize ); + if (index >= blocks.size()) break; + io->loadSmallBlock(blocks[index], buf, io->bbat->blockSize); std::size_t count = io->sbat->blockSize - offset; - if( count > maxlen-totalbytes ) count = maxlen-totalbytes; - memcpy( data+totalbytes, buf + offset, count ); + if (count > maxlen - totalbytes) count = maxlen - totalbytes; + memcpy(data + totalbytes, buf + offset, count); totalbytes += count; offset = 0; index++; } delete[] buf; - } else { // big file std::size_t index = pos / io->bbat->blockSize; - - if( index >= blocks.size() ) return 0; - - std::uint8_t* buf = new std::uint8_t[ io->bbat->blockSize ]; + + if (index >= blocks.size()) return 0; + + std::uint8_t *buf = new std::uint8_t[io->bbat->blockSize]; std::size_t offset = pos % io->bbat->blockSize; - while( totalbytes < maxlen ) + while (totalbytes < maxlen) { - if( index >= blocks.size() ) break; - io->loadBigBlock( blocks[index], buf, io->bbat->blockSize ); + if (index >= blocks.size()) break; + io->loadBigBlock(blocks[index], buf, io->bbat->blockSize); std::size_t count = io->bbat->blockSize - offset; - if( count > maxlen-totalbytes ) count = maxlen-totalbytes; - memcpy( data+totalbytes, buf + offset, count ); + if (count > maxlen - totalbytes) count = maxlen - totalbytes; + memcpy(data + totalbytes, buf + offset, count); totalbytes += count; index++; offset = 0; } - delete [] buf; - + delete[] buf; } - + return totalbytes; } -std::size_t StreamIO::read( std::uint8_t* data, std::size_t maxlen ) +std::size_t StreamIO::read(std::uint8_t *data, std::size_t maxlen) { - std::size_t bytes = read( tell(), data, maxlen ); + std::size_t bytes = read(tell(), data, maxlen); m_pos += bytes; return bytes; } @@ -1051,19 +1054,18 @@ std::size_t StreamIO::read( std::uint8_t* data, std::size_t maxlen ) void StreamIO::updateCache() { // sanity check - if( !cache_data ) return; - - cache_pos = m_pos - ( m_pos % cache_size ); - std::size_t bytes = cache_size; - if( cache_pos + bytes > entry->size ) bytes = entry->size - cache_pos; - cache_size = read( cache_pos, cache_data, bytes ); -} + if (!cache_data) return; + cache_pos = m_pos - (m_pos % cache_size); + std::size_t bytes = cache_size; + if (cache_pos + bytes > entry->size) bytes = entry->size - cache_pos; + 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)) { } @@ -1087,59 +1089,58 @@ void Storage::close() io->close(); } -std::list Storage::entries( const std::string& path ) +std::list Storage::entries(const std::string &path) { std::list result; - DirTree* dt = io->dirtree; - DirEntry* e = dt->entry( path, false ); - if( e && e->dir ) + DirTree *dt = io->dirtree; + DirEntry *e = dt->entry(path, false); + if (e && e->dir) { - auto parent = dt->indexOf( e ); - std::vector children = dt->children( static_cast(parent) ); - for( std::size_t i = 0; i < children.size(); i++ ) - result.push_back( dt->entry( children[i] )->name ); + auto parent = dt->indexOf(e); + std::vector children = dt->children(static_cast(parent)); + for (std::size_t i = 0; i < children.size(); i++) + result.push_back(dt->entry(children[i])->name); } - + return result; } -bool Storage::isDirectory( const std::string& name ) +bool Storage::isDirectory(const std::string &name) { - DirEntry* e = io->dirtree->entry( name, false ); + DirEntry *e = io->dirtree->entry(name, false); return e ? e->dir : false; } -DirTree* Storage::dirTree() +DirTree *Storage::dirTree() { return io->dirtree; } - -StorageIO* Storage::storageIO() +StorageIO *Storage::storageIO() { return io; } -std::list Storage::dirEntries( const std::string& path ) +std::list Storage::dirEntries(const std::string &path) { - std::list result; - DirTree* dt = io->dirtree; - DirEntry* e = dt->entry( path, false ); - if( e && e->dir ) + std::list result; + DirTree *dt = io->dirtree; + DirEntry *e = dt->entry(path, false); + if (e && e->dir) { - auto parent = dt->indexOf( e ); - std::vector children = dt->children( static_cast(parent) ); - for( std::size_t i = 0; i < children.size(); i++ ) - result.push_back( dt->entry( children[i] ) ); + auto parent = dt->indexOf(e); + std::vector children = dt->children(static_cast(parent)); + for (std::size_t i = 0; i < children.size(); i++) + result.push_back(dt->entry(children[i])); } - + return result; } // =========== 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)) { } @@ -1159,9 +1160,9 @@ std::size_t Stream::tell() return io ? io->tell() : 0; } -void Stream::seek( std::size_t newpos ) +void Stream::seek(std::size_t newpos) { - if( io ) io->seek( newpos ); + if (io) io->seek(newpos); } std::size_t Stream::size() @@ -1174,9 +1175,9 @@ int Stream::getch() return io ? io->getch() : 0; } -std::size_t Stream::read( std::uint8_t* data, std::size_t maxlen ) +std::size_t Stream::read(std::uint8_t *data, std::size_t maxlen) { - return io ? io->read( data, maxlen ) : 0; + return io ? io->read(data, maxlen) : 0; } bool Stream::eof() diff --git a/source/detail/workbook_impl.hpp b/source/detail/workbook_impl.hpp index 5c9715bb..17bde5f2 100644 --- a/source/detail/workbook_impl.hpp +++ b/source/detail/workbook_impl.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -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_; + optional calculation_properties_; }; } // namespace detail diff --git a/source/detail/xlsx_consumer.cpp b/source/detail/xlsx_consumer.cpp index 52840015..0e9bba9b 100644 --- a/source/detail/xlsx_consumer.cpp +++ b/source/detail/xlsx_consumer.cpp @@ -24,18 +24,18 @@ #include #include // for std::accumulate -#include -#include -#include -#include -#include -#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include namespace std { @@ -245,14 +245,8 @@ std::array, 3> parse_header_footer(const std::st tokens.push_back(token); } - const auto parse_section = [&tokens,&result](hf_code code) - { - std::vector 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 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)); @@ -387,39 +381,39 @@ std::array, 3> parse_header_footer(const std::st break; case hf_code::text_font_name: + { + auto comma_index = current_token.value.find(','); + auto font_name = current_token.value.substr(0, comma_index); + + if (!current_run.second.is_set()) { - auto comma_index = current_token.value.find(','); - auto font_name = current_token.value.substr(0, comma_index); - - if (!current_run.second.is_set()) - { - current_run.second = xlnt::font(); - } - - if (font_name != "-") - { - current_run.second.get().name(font_name); - } - - if (comma_index != std::string::npos) - { - auto font_type = current_token.value.substr(comma_index + 1); - - if (font_type == "Bold") - { - current_run.second.get().bold(true); - } - else if (font_type == "Italic") - { - } - else if (font_type == "BoldItalic") - { - current_run.second.get().bold(true); - } - } + current_run.second = xlnt::font(); } - break; + if (font_name != "-") + { + current_run.second.get().name(font_name); + } + + if (comma_index != std::string::npos) + { + auto font_type = current_token.value.substr(comma_index + 1); + + if (font_type == "Bold") + { + current_run.second.get().bold(true); + } + else if (font_type == "Italic") + { + } + else if (font_type == "BoldItalic") + { + current_run.second.get().bold(true); + } + } + } + + break; case hf_code::bold_font_style: if (!current_run.second.is_set()) @@ -445,8 +439,8 @@ std::array, 3> parse_header_footer(const std::st current_text.add_run(current_run); } - auto location_index = static_cast(code == hf_code::left_section ? 0 - : code == hf_code::center_section ? 1 : 2); + auto location_index = + static_cast(code == hf_code::left_section ? 0 : code == hf_code::center_section ? 1 : 2); if (!current_text.plain_text().empty()) { @@ -501,7 +495,7 @@ bool is_true(const std::string &bool_string) ///

/// Helper template function that returns true if element is in container. /// -template +template bool contains(const std::vector &container, const T &element) { return std::find(container.begin(), container.end(), element) != container.end(); @@ -513,7 +507,7 @@ bool contains(const std::vector &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 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 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,33 +568,25 @@ std::vector xlsx_consumer::read_relationships(const path &part) target_mode = parser.attribute("TargetMode"); } - relationships.emplace_back(parser.attribute("Id"), - parser.attribute("Type"), source, - xlnt::uri(parser.attribute("Target")), - target_mode); + relationships.emplace_back(parser.attribute("Id"), parser.attribute("Type"), source, + xlnt::uri(parser.attribute("Target")), target_mode); expect_end_element(xml::qname(xmlns, "Relationship")); } expect_end_element(xml::qname(xmlns, "Relationships")); - + parser_ = nullptr; return relationships; } - void xlsx_consumer::read_part(const std::vector &rel_chain) { // ignore namespace declarations except in parts of these types - const auto using_namespaces = std::vector - { - relationship_type::office_document, - relationship_type::stylesheet, - relationship_type::chartsheet, - relationship_type::dialogsheet, - relationship_type::worksheet - }; + const auto using_namespaces = + std::vector{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 &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("xWindow"); @@ -1141,9 +1127,9 @@ void xlsx_consumer::read_stylesheet() target_.impl().stylesheet_ = detail::stylesheet(); auto &stylesheet = target_.impl().stylesheet_.get(); - - //todo: should this really be defined here? - //todo: maybe xlnt::style and xlnt::format can be used here instead now + + // todo: should this really be defined here? + // todo: maybe xlnt::style and xlnt::format can be used here instead now struct formatting_record { std::pair alignment = {{}, 0}; @@ -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("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()) - : style_records.emplace(style_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("borderId") : 0; + auto border_applied = + parser().attribute_present("applyBorder") && is_true(parser().attribute("applyBorder")); + auto border_index = + parser().attribute_present("borderId") ? parser().attribute("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("fillId") : 0; + auto fill_applied = parser().attribute_present("applyFill") && is_true(parser().attribute("applyFill")); + auto fill_index = parser().attribute_present("fillId") ? parser().attribute("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("fontId") : 0; + auto font_applied = parser().attribute_present("applyFont") && is_true(parser().attribute("applyFont")); + auto font_index = parser().attribute_present("fontId") ? parser().attribute("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("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("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"); } @@ -1632,7 +1611,7 @@ void xlsx_consumer::read_stylesheet() { auto current_element = expect_start_element(xml::content::complex); skip_remaining_content(current_element); - + ++processed; } @@ -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 &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 &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,22 +1893,22 @@ 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"))) { auto sheet_view_child_element = expect_start_element(xml::content::simple); - + if (sheet_view_child_element == xml::qname(xmlns, "pane")) // CT_Pane 0-1 { pane new_pane; - + if (parser().attribute_present("topLeftCell")) { new_pane.top_left_cell = cell_reference(parser().attribute("topLeftCell")); @@ -2006,16 +1984,15 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) } optional column_style; - + if (parser().attribute_present("style")) { column_style = parser().attribute("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"))) { @@ -2086,7 +2063,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) while (in_element(xml::qname(xmlns, "c"))) { auto current_element = expect_start_element(xml::content::mixed); - + if (current_element == xml::qname(xmlns, "v")) // s:ST_Xstring { has_value = true; @@ -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, 3>> odd_header; optional, 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("count") : 0; - auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute("manualBreakCount") : 0; + auto manual_break_count = parser().attribute_present("manualBreakCount") + ? parser().attribute("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("id")); + ws.page_break_at_row(parser().attribute("id")); --count; } @@ -2382,7 +2359,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) { --manual_break_count; } - + skip_attributes({"min", "max", "pt"}); expect_end_element(xml::qname(xmlns, "brk")); } @@ -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("count") : 0; - auto manual_break_count = parser().attribute_present("manualBreakCount") ? parser().attribute("manualBreakCount") : 0; + auto manual_break_count = parser().attribute_present("manualBreakCount") + ? parser().attribute("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("id")); + ws.page_break_at_column(parser().attribute("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); @@ -2475,7 +2458,7 @@ void xlsx_consumer::read_worksheet(const std::string &rel_id) // Sheet Relationship Target Parts -void xlsx_consumer::read_vml_drawings(worksheet/*ws*/) +void xlsx_consumer::read_vml_drawings(worksheet /*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) @@ -2700,7 +2681,7 @@ rich_text xlsx_consumer::read_rich_text(const xml::qname &parent) { auto run_element = expect_start_element(xml::content::mixed); auto run_text = read_text(); - + if (run_element == xml::qname(xmlns, "rPr")) { while (in_element(xml::qname(xmlns, "rPr"))) @@ -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")) { @@ -2766,7 +2748,7 @@ rich_text xlsx_consumer::read_rich_text(const xml::qname &parent) expect_end_element(run_element); read_text(); } - + t.add_run(run); } else if (text_element == xml::qname(xmlns, "rPh")) @@ -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; diff --git a/source/detail/xlsx_consumer.hpp b/source/detail/xlsx_consumer.hpp index 2a4d9310..6422c5d1 100644 --- a/source/detail/xlsx_consumer.hpp +++ b/source/detail/xlsx_consumer.hpp @@ -45,7 +45,7 @@ class worksheet; namespace detail { -class ZipFileReader; +class zip_file_reader; /// /// Handles writing a workbook into an XLSX file. @@ -338,7 +338,7 @@ private: /// /// The ZIP file containing the files that make up the OOXML package. /// - std::unique_ptr archive_; + std::unique_ptr archive_; /// /// Map of sheet titles to relationship IDs. diff --git a/source/detail/xlsx_crypto.cpp b/source/detail/xlsx_crypto.cpp index 7df0dd55..4ed9fffb 100644 --- a/source/detail/xlsx_crypto.cpp +++ b/source/detail/xlsx_crypto.cpp @@ -23,6 +23,8 @@ #include +#include +#include #include #include #include @@ -30,8 +32,6 @@ #include #include #include -#include -#include namespace xlnt { namespace detail { @@ -60,34 +60,54 @@ struct value_traits { static xlnt::detail::hash_algorithm parse(std::string hash_algorithm_string, const parser &) { - if (hash_algorithm_string == "SHA1") return xlnt::detail::hash_algorithm::sha1; - else if (hash_algorithm_string == "SHA256") return xlnt::detail::hash_algorithm::sha256; - else if (hash_algorithm_string == "SHA384") return xlnt::detail::hash_algorithm::sha384; - else if (hash_algorithm_string == "SHA512") return xlnt::detail::hash_algorithm::sha512; - else if (hash_algorithm_string == "MD5") return xlnt::detail::hash_algorithm::md5; - else if (hash_algorithm_string == "MD4") return xlnt::detail::hash_algorithm::md4; - else if (hash_algorithm_string == "MD2") return xlnt::detail::hash_algorithm::md2; - else if (hash_algorithm_string == "Ripemd128") return xlnt::detail::hash_algorithm::ripemd128; - else if (hash_algorithm_string == "Ripemd160") return xlnt::detail::hash_algorithm::ripemd160; - else if (hash_algorithm_string == "Whirlpool") return xlnt::detail::hash_algorithm::whirlpool; - throw xlnt::exception(hash_algorithm_string); + if (hash_algorithm_string == "SHA1") + return xlnt::detail::hash_algorithm::sha1; + else if (hash_algorithm_string == "SHA256") + return xlnt::detail::hash_algorithm::sha256; + else if (hash_algorithm_string == "SHA384") + return xlnt::detail::hash_algorithm::sha384; + else if (hash_algorithm_string == "SHA512") + return xlnt::detail::hash_algorithm::sha512; + else if (hash_algorithm_string == "MD5") + return xlnt::detail::hash_algorithm::md5; + else if (hash_algorithm_string == "MD4") + return xlnt::detail::hash_algorithm::md4; + else if (hash_algorithm_string == "MD2") + return xlnt::detail::hash_algorithm::md2; + else if (hash_algorithm_string == "Ripemd128") + return xlnt::detail::hash_algorithm::ripemd128; + else if (hash_algorithm_string == "Ripemd160") + return xlnt::detail::hash_algorithm::ripemd160; + else if (hash_algorithm_string == "Whirlpool") + return xlnt::detail::hash_algorithm::whirlpool; + throw xlnt::exception(hash_algorithm_string); } static std::string serialize(xlnt::detail::hash_algorithm algorithm, const serializer &) { - switch (algorithm) - { - case xlnt::detail::hash_algorithm::sha1: return "SHA1"; - case xlnt::detail::hash_algorithm::sha256: return "SHA256"; - case xlnt::detail::hash_algorithm::sha384: return "SHA384"; - case xlnt::detail::hash_algorithm::sha512: return "SHA512"; - case xlnt::detail::hash_algorithm::md5: return "MD5"; - case xlnt::detail::hash_algorithm::md4: return "MD4"; - case xlnt::detail::hash_algorithm::md2: return "MD2"; - case xlnt::detail::hash_algorithm::ripemd128: return "Ripemd128"; - case xlnt::detail::hash_algorithm::ripemd160: return "Ripemd160"; - case xlnt::detail::hash_algorithm::whirlpool: return "Whirlpool"; - } + switch (algorithm) + { + case xlnt::detail::hash_algorithm::sha1: + return "SHA1"; + case xlnt::detail::hash_algorithm::sha256: + return "SHA256"; + case xlnt::detail::hash_algorithm::sha384: + return "SHA384"; + case xlnt::detail::hash_algorithm::sha512: + return "SHA512"; + case xlnt::detail::hash_algorithm::md5: + return "MD5"; + case xlnt::detail::hash_algorithm::md4: + return "MD4"; + case xlnt::detail::hash_algorithm::md2: + return "MD2"; + case xlnt::detail::hash_algorithm::ripemd128: + return "Ripemd128"; + case xlnt::detail::hash_algorithm::ripemd160: + return "Ripemd160"; + case xlnt::detail::hash_algorithm::whirlpool: + return "Whirlpool"; + } } }; // struct value_traits<> @@ -124,10 +144,8 @@ struct crypto_helper decryption }; - static std::vector aes(const std::vector &key, - const std::vector &iv, - const std::vector &source, - cipher_chaining chaining, cipher_direction direction) + static std::vector aes(const std::vector &key, const std::vector &iv, + const std::vector &source, cipher_chaining chaining, cipher_direction direction) { std::vector destination(source.size(), 0); @@ -136,40 +154,40 @@ 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, - new CryptoPP::ArraySink(destination.data(), destination.size()), - CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); + CryptoPP::ArraySource as( + source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcEncryption, + new CryptoPP::ArraySink(destination.data(), destination.size()), + CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); } else if (direction == cipher_direction::decryption && chaining == cipher_chaining::cbc) { 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, - new CryptoPP::ArraySink(destination.data(), destination.size()), - CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); + CryptoPP::ArraySource as( + source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcDecryption, + new CryptoPP::ArraySink(destination.data(), destination.size()), + CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); } else if (direction == cipher_direction::encryption && chaining == cipher_chaining::ecb) { 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, - new CryptoPP::ArraySink(destination.data(), destination.size()), - CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); + CryptoPP::ArraySource as( + source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcEncryption, + new CryptoPP::ArraySink(destination.data(), destination.size()), + CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); } else if (direction == cipher_direction::decryption && chaining == cipher_chaining::ecb) { 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, - new CryptoPP::ArraySink(destination.data(), destination.size()), - CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); + CryptoPP::ArraySource as( + source.data(), source.size(), true, new CryptoPP::StreamTransformationFilter(cbcDecryption, + new CryptoPP::ArraySink(destination.data(), destination.size()), + CryptoPP::BlockPaddingSchemeDef::NO_PADDING)); } return destination; @@ -199,8 +217,7 @@ struct crypto_helper return std::string(encoded.begin(), encoded.end()); } - static std::vector hash(hash_algorithm algorithm, - const std::vector &input) + static std::vector hash(hash_algorithm algorithm, const std::vector &input) { std::vector digest; @@ -229,7 +246,7 @@ struct crypto_helper return bytes; } - template + template static auto read_int(std::size_t &index, const std::vector &raw_data) { auto result = *reinterpret_cast(&raw_data[index]); @@ -263,8 +280,8 @@ struct crypto_helper auto header_length = read_int(offset, encryption_info); auto index_at_start = offset; - /*auto skip_flags = */read_int(offset, encryption_info); - /*auto size_extra = */read_int(offset, encryption_info); + /*auto skip_flags = */ read_int(offset, encryption_info); + /*auto size_extra = */ read_int(offset, encryption_info); auto alg_id = read_int(offset, encryption_info); if (alg_id == 0 || alg_id == 0x0000660E || alg_id == 0x0000660F || alg_id == 0x00006610) @@ -281,7 +298,7 @@ struct crypto_helper { throw xlnt::exception("invalid hash algorithm"); } - + info.key_bits = read_int(offset, encryption_info); info.key_bytes = info.key_bits / 8; @@ -300,7 +317,8 @@ struct crypto_helper const auto csp_name_length = header_length - (offset - index_at_start); std::vector csp_name_wide( reinterpret_cast(&*(encryption_info.begin() + static_cast(offset))), - reinterpret_cast(&*(encryption_info.begin() + static_cast(offset + csp_name_length)))); + reinterpret_cast( + &*(encryption_info.begin() + static_cast(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 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(&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(&c), reinterpret_cast(&c) + sizeof(std::uint16_t)); }); std::vector 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(&block_number), + h_n_plus_block.insert(h_n_plus_block.end(), reinterpret_cast(&block_number), reinterpret_cast(&block_number) + sizeof(std::uint32_t)); auto h_final = hash(info.hash, h_n_plus_block); @@ -375,16 +389,17 @@ struct crypto_helper auto X3 = X1; X3.insert(X3.end(), X2.begin(), X2.end()); - - auto key_derived = std::vector(X3.begin(), X3.begin() + static_cast(info.key_bytes)); - //todo: verify here + auto key_derived = + std::vector(X3.begin(), X3.begin() + static_cast(info.key_bytes)); + + // todo: verify here std::size_t package_offset = 0; auto decrypted_size = static_cast(read_int(package_offset, encrypted_package)); - auto decrypted = aes(key_derived, {}, std::vector( - encrypted_package.begin() + 8, encrypted_package.end()), - cipher_chaining::ecb, cipher_direction::decryption); + auto decrypted = + aes(key_derived, {}, std::vector(encrypted_package.begin() + 8, encrypted_package.end()), + cipher_chaining::ecb, cipher_direction::decryption); decrypted.resize(decrypted_size); return decrypted; @@ -420,7 +435,7 @@ struct crypto_helper std::size_t hash_size; std::string cipher_algorithm; std::string cipher_chaining; - hash_algorithm hash; + hash_algorithm hash; std::vector salt_value; std::vector verifier_hash_input; std::vector verifier_hash_value; @@ -430,9 +445,9 @@ struct crypto_helper static agile_encryption_info generate_agile_encryption_info(const std::string &password) { - agile_encryption_info result; - result.key_data.salt_value.assign(password.begin(), password.end()); - return result; + agile_encryption_info result; + result.key_data.salt_value.assign(password.begin(), password.end()); + return result; } static std::vector write_agile_encryption_info(const std::string &password) @@ -440,20 +455,20 @@ struct crypto_helper static const auto &xmlns = xlnt::constants::namespace_("encryption"); static const auto &xmlns_p = xlnt::constants::namespace_("encryption-password"); - std::vector encryption_info; - xlnt::detail::vector_ostreambuf encryption_info_buffer(encryption_info); - std::ostream encryption_info_stream(&encryption_info_buffer); - xml::serializer serializer(encryption_info_stream, "EncryptionInfo"); + std::vector encryption_info; + xlnt::detail::vector_ostreambuf encryption_info_buffer(encryption_info); + std::ostream encryption_info_stream(&encryption_info_buffer); + xml::serializer serializer(encryption_info_stream, "EncryptionInfo"); agile_encryption_info result = generate_agile_encryption_info(password); serializer.start_element(xmlns, "encryption"); serializer.start_element(xmlns, "keyData"); - serializer.attribute("saltSize", result.key_data.salt_size); - serializer.attribute("blockSize", result.key_data.block_size); - serializer.attribute("keyBits", result.key_data.key_bits); - serializer.attribute("hashSize", result.key_data.hash_size); + serializer.attribute("saltSize", result.key_data.salt_size); + serializer.attribute("blockSize", result.key_data.block_size); + serializer.attribute("keyBits", result.key_data.key_bits); + serializer.attribute("hashSize", result.key_data.hash_size); serializer.attribute("cipherAlgorithm", result.key_data.cipher_algorithm); serializer.attribute("cipherChaining", result.key_data.cipher_chaining); serializer.attribute("hashAlgorithm", result.key_data.hash_algorithm); @@ -468,26 +483,26 @@ struct crypto_helper serializer.start_element(xmlns, "keyEncryptors"); serializer.start_element(xmlns, "keyEncryptor"); serializer.attribute("uri", ""); - serializer.start_element(xmlns_p, "encryptedKey"); - serializer.attribute("spinCount", result.key_encryptor.spin_count); - serializer.attribute("saltSize", result.key_encryptor.salt_size); - serializer.attribute("blockSize", result.key_encryptor.block_size); - serializer.attribute("keyBits", result.key_encryptor.key_bits); - serializer.attribute("hashSize", result.key_encryptor.hash_size); - serializer.attribute("cipherAlgorithm", result.key_encryptor.cipher_algorithm); - serializer.attribute("cipherChaining", result.key_encryptor.cipher_chaining); - serializer.attribute("hashAlgorithm", result.key_encryptor.hash); - serializer.attribute("saltValue", encode_base64(result.key_encryptor.salt_value)); - serializer.attribute("encryptedVerifierHashInput", encode_base64(result.key_encryptor.verifier_hash_input)); - serializer.attribute("encryptedVerifierHashValue", encode_base64(result.key_encryptor.verifier_hash_value)); - serializer.attribute("encryptedKeyValue", encode_base64(result.key_encryptor.encrypted_key_value)); - serializer.end_element(xmlns_p, "encryptedKey"); - serializer.end_element(xmlns, "keyEncryptor"); - serializer.end_element(xmlns, "keyEncryptors"); + serializer.start_element(xmlns_p, "encryptedKey"); + serializer.attribute("spinCount", result.key_encryptor.spin_count); + serializer.attribute("saltSize", result.key_encryptor.salt_size); + serializer.attribute("blockSize", result.key_encryptor.block_size); + serializer.attribute("keyBits", result.key_encryptor.key_bits); + serializer.attribute("hashSize", result.key_encryptor.hash_size); + serializer.attribute("cipherAlgorithm", result.key_encryptor.cipher_algorithm); + serializer.attribute("cipherChaining", result.key_encryptor.cipher_chaining); + serializer.attribute("hashAlgorithm", result.key_encryptor.hash); + serializer.attribute("saltValue", encode_base64(result.key_encryptor.salt_value)); + serializer.attribute("encryptedVerifierHashInput", encode_base64(result.key_encryptor.verifier_hash_input)); + serializer.attribute("encryptedVerifierHashValue", encode_base64(result.key_encryptor.verifier_hash_value)); + serializer.attribute("encryptedKeyValue", encode_base64(result.key_encryptor.encrypted_key_value)); + serializer.end_element(xmlns_p, "encryptedKey"); + serializer.end_element(xmlns, "keyEncryptor"); + serializer.end_element(xmlns, "keyEncryptors"); - serializer.end_element(xmlns, "encryption"); + serializer.end_element(xmlns, "encryption"); - return encryption_info; + return encryption_info; } static std::vector decrypt_xlsx_agile(const std::vector &encryption_info, @@ -495,7 +510,7 @@ struct crypto_helper { static const auto &xmlns = xlnt::constants::namespace_("encryption"); static const auto &xmlns_p = xlnt::constants::namespace_("encryption-password"); - //static const auto &xmlns_c = xlnt::constants::namespace_("encryption-certificate"); + // static const auto &xmlns_c = xlnt::constants::namespace_("encryption-certificate"); agile_encryption_info result; @@ -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 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(&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(&c), reinterpret_cast(&c) + sizeof(std::uint16_t)); }); @@ -608,46 +621,39 @@ struct crypto_helper h_n = hash(result.key_encryptor.hash, iterator_plus_h_n); std::copy(h_n.begin(), h_n.end(), iterator_plus_h_n.begin() + 4); } - + static const std::size_t block_size = 8; - auto calculate_block = [&result]( - const std::vector &raw_key, - const std::array &block, - const std::vector &encrypted) - { + auto calculate_block = [&result](const std::vector &raw_key, + const std::array &block, const std::vector &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 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 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 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 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 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 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(i); auto current_segment_length = std::min(segment_length, encrypted_package.size() - i); - auto segment_end = encrypted_package.begin() - + static_cast(i + current_segment_length); + auto segment_end = encrypted_package.begin() + static_cast(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(index, encryption_info); // get rid of header - encryption_info.erase(encryption_info.begin(), - encryption_info.begin() + static_cast(index)); + encryption_info.erase(encryption_info.begin(), encryption_info.begin() + static_cast(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"); } @@ -757,7 +759,7 @@ struct crypto_helper throw xlnt::exception("empty file"); } - generate_agile_encryption_info(password); + generate_agile_encryption_info(password); return {}; } @@ -767,12 +769,11 @@ const std::size_t crypto_helper::segment_length = 4096; void xlsx_consumer::read(std::istream &source, const std::string &password) { - std::vector data((std::istreambuf_iterator(source)), - (std::istreambuf_iterator())); - const auto decrypted = crypto_helper::decrypt_xlsx(data, password); - vector_istreambuf decrypted_buffer(decrypted); - std::istream decrypted_stream(&decrypted_buffer); - read(decrypted_stream); + std::vector data((std::istreambuf_iterator(source)), (std::istreambuf_iterator())); + const auto decrypted = crypto_helper::decrypt_xlsx(data, password); + vector_istreambuf decrypted_buffer(decrypted); + std::istream decrypted_stream(&decrypted_buffer); + read(decrypted_stream); } void xlsx_producer::write(std::ostream &destination, const std::string &password) @@ -787,7 +788,7 @@ void xlsx_producer::write(std::ostream &destination, const std::string &password const auto encrypted = crypto_helper::encrypt_xlsx(decrypted, password); vector_istreambuf encrypted_buffer(encrypted); - + destination << &encrypted_buffer; } diff --git a/source/detail/xlsx_producer.cpp b/source/detail/xlsx_producer.cpp index 45c880fa..0dc304c8 100644 --- a/source/detail/xlsx_producer.cpp +++ b/source/detail/xlsx_producer.cpp @@ -24,20 +24,20 @@ #include // for std::accumulate #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include using namespace std::string_literals; @@ -48,7 +48,7 @@ namespace { /// bool is_integral(long double d) { - return std::fabs(d - static_cast(static_cast(d))) == 0.L; + return std::fabs(d - static_cast(static_cast(d))) == 0.L; } } // namespace @@ -56,28 +56,30 @@ 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(); + populate_archive(); } // Part Writing Methods void xlsx_producer::populate_archive() { - write_content_types(); - + write_content_types(); + const auto root_rels = source_.manifest().relationships(path("/")); write_relationships(root_rels, path("/")); - for (auto &rel : root_rels) - { + for (auto &rel : root_rels) + { // thumbnail is binary content so we don't want to open an xml serializer stream if (rel.type() == relationship_type::thumbnail) { @@ -87,62 +89,93 @@ void xlsx_producer::populate_archive() begin_part(rel.target().path()); - switch (rel.type()) - { - case relationship_type::core_properties: - write_core_properties(rel); - break; - - case relationship_type::extended_properties: - write_extended_properties(rel); - break; - - case relationship_type::custom_properties: - write_custom_properties(rel); - break; - - case relationship_type::office_document: - 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; + switch (rel.type()) + { + case relationship_type::core_properties: + write_core_properties(rel); + break; + + case relationship_type::extended_properties: + write_extended_properties(rel); + break; + + case relationship_type::custom_properties: + write_custom_properties(rel); + break; + + case relationship_type::office_document: + 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; } - } + } - // Unknown Parts + // Unknown Parts - void write_unknown_parts(); - void write_unknown_relationships(); + void write_unknown_parts(); + void write_unknown_relationships(); end_part(); } @@ -153,14 +186,16 @@ 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 @@ -172,35 +207,33 @@ void xlsx_producer::write_content_types() const auto xmlns = "http://schemas.openxmlformats.org/package/2006/content-types"s; - serializer().start_element(xmlns, "Types"); - serializer().namespace_decl(xmlns, ""); + serializer().start_element(xmlns, "Types"); + serializer().namespace_decl(xmlns, ""); - for (const auto &extension : source_.manifest().extensions_with_default_types()) - { - serializer().start_element(xmlns, "Default"); - serializer().attribute("Extension", extension); - serializer().attribute("ContentType", - source_.manifest().default_type(extension)); - serializer().end_element(xmlns, "Default"); - } + for (const auto &extension : source_.manifest().extensions_with_default_types()) + { + serializer().start_element(xmlns, "Default"); + serializer().attribute("Extension", extension); + serializer().attribute("ContentType", source_.manifest().default_type(extension)); + serializer().end_element(xmlns, "Default"); + } - for (const auto &part : source_.manifest().parts_with_overriden_types()) - { - serializer().start_element(xmlns, "Override"); - serializer().attribute("PartName", part.resolve(path("/")).string()); - serializer().attribute("ContentType", - source_.manifest().override_type(part)); - serializer().end_element(xmlns, "Override"); - } - - serializer().end_element(xmlns, "Types"); + for (const auto &part : source_.manifest().parts_with_overriden_types()) + { + serializer().start_element(xmlns, "Override"); + serializer().attribute("PartName", part.resolve(path("/")).string()); + serializer().attribute("ContentType", source_.manifest().override_type(part)); + serializer().end_element(xmlns, "Override"); + } + + serializer().end_element(xmlns, "Types"); } -void xlsx_producer::write_extended_properties(const relationship &/*rel*/) +void xlsx_producer::write_extended_properties(const relationship & /*rel*/) { const auto xmlns = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"s; const auto xmlns_vt = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"s; - + serializer().start_element(xmlns, "Properties"); serializer().namespace_decl(xmlns, ""); serializer().namespace_decl(xmlns_vt, "vt"); @@ -221,9 +254,9 @@ void xlsx_producer::write_extended_properties(const relationship &/*rel*/) } serializer().start_element(xmlns, "HeadingPairs"); - serializer().start_element(xmlns_vt, "vector"); - serializer().attribute("size", "2"); - serializer().attribute("baseType", "variant"); + serializer().start_element(xmlns_vt, "vector"); + serializer().attribute("size", "2"); + serializer().attribute("baseType", "variant"); serializer().start_element(xmlns_vt, "variant"); serializer().element(xmlns_vt, "lpstr", "Worksheets"); serializer().end_element(xmlns_vt, "variant"); @@ -238,18 +271,18 @@ void xlsx_producer::write_extended_properties(const relationship &/*rel*/) serializer().attribute("size", source_.sheet_titles().size()); serializer().attribute("baseType", "lpstr"); - for (auto ws : source_) - { + for (auto ws : source_) + { serializer().element(xmlns_vt, "lpstr", ws.title()); - } + } serializer().end_element(xmlns_vt, "vector"); serializer().end_element(xmlns, "TitlesOfParts"); - if (source_.has_core_property("Company")) - { + if (source_.has_core_property("Company")) + { serializer().element(xmlns, "Company", source_.core_property("Company")); - } + } if (source_.has_core_property("LinksUpToDate")) { @@ -260,7 +293,7 @@ void xlsx_producer::write_extended_properties(const relationship &/*rel*/) { serializer().element(xmlns, "SharedDoc", source_.core_property("SharedDoc")); } - + if (source_.has_core_property("LinksUpToDate")) { serializer().element(xmlns, "HyperlinksChanged", source_.core_property("HyperlinksChanged")); @@ -270,19 +303,19 @@ void xlsx_producer::write_extended_properties(const relationship &/*rel*/) { serializer().element(xmlns, "AppVersion", source_.core_property("AppVersion")); } - + serializer().end_element(xmlns, "Properties"); } -void xlsx_producer::write_core_properties(const relationship &/*rel*/) +void xlsx_producer::write_core_properties(const relationship & /*rel*/) { static const auto &xmlns_cp = constants::namespace_("core-properties"); static const auto &xmlns_dc = constants::namespace_("dc"); static const auto &xmlns_dcterms = constants::namespace_("dcterms"); static const auto &xmlns_dcmitype = constants::namespace_("dcmitype"); static const auto &xmlns_xsi = constants::namespace_("xsi"); - - serializer().start_element(xmlns_cp, "coreProperties"); + + serializer().start_element(xmlns_cp, "coreProperties"); serializer().namespace_decl(xmlns_cp, "cp"); serializer().namespace_decl(xmlns_dc, "dc"); serializer().namespace_decl(xmlns_dcterms, "dcterms"); @@ -315,10 +348,10 @@ void xlsx_producer::write_core_properties(const relationship &/*rel*/) serializer().end_element(xmlns_dcterms, "modified"); } - if (source_.has_title()) - { - serializer().element(xmlns_dc, "title", source_.title()); - } + if (source_.has_title()) + { + serializer().element(xmlns_dc, "title", source_.title()); + } if (source_.has_core_property("description")) { @@ -343,79 +376,79 @@ void xlsx_producer::write_core_properties(const relationship &/*rel*/) serializer().end_element(xmlns_cp, "coreProperties"); } -void xlsx_producer::write_custom_properties(const relationship &/*rel*/) +void xlsx_producer::write_custom_properties(const relationship & /*rel*/) { - serializer().element("Properties"); + serializer().element("Properties"); } // Write SpreadsheetML-Specific Package Parts void xlsx_producer::write_workbook(const relationship &rel) { - std::size_t num_visible = 0; - bool any_defined_names = false; + std::size_t num_visible = 0; + bool any_defined_names = false; - for (auto ws : source_) - { - if (!ws.has_page_setup() || ws.page_setup().sheet_state() == sheet_state::visible) - { - num_visible++; - } + for (auto ws : source_) + { + if (!ws.has_page_setup() || ws.page_setup().sheet_state() == sheet_state::visible) + { + num_visible++; + } - if (ws.has_auto_filter()) - { - any_defined_names = true; - } - } + if (ws.has_auto_filter()) + { + any_defined_names = true; + } + } - if (num_visible == 0) - { - throw no_visible_worksheets(); - } + if (num_visible == 0) + { + throw no_visible_worksheets(); + } static const auto &xmlns = constants::namespace_("workbook"); static const auto &xmlns_r = constants::namespace_("r"); static const auto &xmlns_s = constants::namespace_("spreadsheetml"); - serializer().start_element(xmlns, "workbook"); + serializer().start_element(xmlns, "workbook"); serializer().namespace_decl(xmlns, ""); serializer().namespace_decl(xmlns_r, "r"); - if (source_.has_file_version()) - { - serializer().start_element(xmlns, "fileVersion"); + if (source_.has_file_version()) + { + serializer().start_element(xmlns, "fileVersion"); - serializer().attribute("appName", source_.app_name()); - serializer().attribute("lastEdited", source_.last_edited()); - serializer().attribute("lowestEdited", source_.lowest_edited()); - serializer().attribute("rupBuild", source_.rup_build()); - - serializer().end_element(xmlns, "fileVersion"); - } + serializer().attribute("appName", source_.app_name()); + serializer().attribute("lastEdited", source_.last_edited()); + serializer().attribute("lowestEdited", source_.lowest_edited()); + serializer().attribute("rupBuild", source_.rup_build()); - if (source_.has_code_name() || source_.base_date() == calendar::mac_1904) - { - serializer().start_element(xmlns, "workbookPr"); + serializer().end_element(xmlns, "fileVersion"); + } - if (source_.has_code_name()) - { - serializer().attribute("codeName", source_.code_name()); - } + if (source_.has_code_name() || source_.base_date() == calendar::mac_1904) + { + serializer().start_element(xmlns, "workbookPr"); + + if (source_.has_code_name()) + { + serializer().attribute("codeName", source_.code_name()); + } if (source_.base_date() == calendar::mac_1904) { serializer().attribute("date1904", "1"); } - - serializer().end_element(xmlns, "workbookPr"); - } - if (source_.has_view()) - { - serializer().start_element(xmlns, "bookViews"); - serializer().start_element(xmlns, "workbookView"); + serializer().end_element(xmlns, "workbookPr"); + } - const auto &view = source_.view(); + if (source_.has_view()) + { + serializer().start_element(xmlns, "bookViews"); + serializer().start_element(xmlns, "workbookView"); + + const auto &view = source_.view(); serializer().attribute("activeTab", "0"); serializer().attribute("autoFilterDateGrouping", "1"); @@ -426,225 +459,248 @@ void xlsx_producer::write_workbook(const relationship &rel) serializer().attribute("showVerticalScroll", "1"); serializer().attribute("visibility", "visible"); - serializer().attribute("xWindow", view.x_window); - serializer().attribute("yWindow", view.y_window); - serializer().attribute("windowWidth", view.window_width); - serializer().attribute("windowHeight", view.window_height); - serializer().attribute("tabRatio", view.tab_ratio); - - serializer().end_element(xmlns, "workbookView"); - serializer().end_element(xmlns, "bookViews"); - } + serializer().attribute("xWindow", view.x_window); + serializer().attribute("yWindow", view.y_window); + serializer().attribute("windowWidth", view.window_width); + serializer().attribute("windowHeight", view.window_height); + serializer().attribute("tabRatio", view.tab_ratio); - serializer().start_element(xmlns, "sheets"); + serializer().end_element(xmlns, "workbookView"); + serializer().end_element(xmlns, "bookViews"); + } - if (any_defined_names) - { - serializer().element(xmlns, "definedNames", ""); - } + serializer().start_element(xmlns, "sheets"); + + if (any_defined_names) + { + serializer().element(xmlns, "definedNames", ""); + } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wrange-loop-analysis" - for (const auto ws : source_) - { - auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.title()]; - auto sheet_rel = source_.d_->manifest_.relationship(rel.target().path(), sheet_rel_id); + for (const auto ws : source_) + { + auto sheet_rel_id = source_.d_->sheet_title_rel_id_map_[ws.title()]; + auto sheet_rel = source_.d_->manifest_.relationship(rel.target().path(), sheet_rel_id); - serializer().start_element(xmlns, "sheet"); - serializer().attribute("name", ws.title()); - serializer().attribute("sheetId", ws.id()); + serializer().start_element(xmlns, "sheet"); + serializer().attribute("name", ws.title()); + serializer().attribute("sheetId", ws.id()); - if (ws.has_page_setup() && ws.sheet_state() == xlnt::sheet_state::hidden) - { + if (ws.has_page_setup() && ws.sheet_state() == xlnt::sheet_state::hidden) + { serializer().attribute("state", "hidden"); - } + } serializer().attribute(xmlns_r, "id", sheet_rel_id); - if (ws.has_auto_filter()) - { - serializer().start_element(xmlns, "definedName"); - - 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().end_element(xmlns, "definedName"); - } - + if (ws.has_auto_filter()) + { + serializer().start_element(xmlns, "definedName"); + + 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().end_element(xmlns, "definedName"); + } + serializer().end_element(xmlns, "sheet"); - } + } #pragma clang diagnostic pop - + serializer().end_element(xmlns, "sheets"); - 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_.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()) - { + if (!source_.named_ranges().empty()) + { serializer().start_element(xmlns, "definedNames"); - for (auto &named_range : source_.named_ranges()) - { + for (auto &named_range : source_.named_ranges()) + { serializer().start_element(xmlns_s, "definedName"); 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()); + const auto &target = named_range.targets().front(); + serializer().characters("'" + target.first.title() + "\'!" + target.second.to_string()); serializer().end_element(xmlns_s, "definedName"); - } - + } + serializer().end_element(xmlns, "definedNames"); - } + } serializer().end_element(xmlns, "workbook"); - + auto workbook_rels = source_.manifest().relationships(rel.target().path()); write_relationships(workbook_rels, rel.target().path()); - + for (const auto &child_rel : workbook_rels) { - path archive_path(child_rel.source().path().parent().append(child_rel.target().path())); + path archive_path(child_rel.source().path().parent().append(child_rel.target().path())); begin_part(archive_path); - + switch (child_rel.type()) { case relationship_type::calculation_chain: - write_calculation_chain(child_rel); - break; - - case relationship_type::chartsheet: - write_chartsheet(child_rel); - break; - - case relationship_type::connections: - write_connections(child_rel); - break; - - case relationship_type::custom_xml_mappings: - write_custom_xml_mappings(child_rel); - break; - - case relationship_type::dialogsheet: - write_dialogsheet(child_rel); - break; - - case relationship_type::external_workbook_references: - write_external_workbook_references(child_rel); - break; - - case relationship_type::metadata: - write_metadata(child_rel); - break; - - case relationship_type::pivot_table: - write_pivot_table(child_rel); - break; + write_calculation_chain(child_rel); + break; - case relationship_type::shared_string_table: - write_shared_string_table(child_rel); - break; + case relationship_type::chartsheet: + write_chartsheet(child_rel); + break; - case relationship_type::shared_workbook_revision_headers: - write_shared_workbook_revision_headers(child_rel); - break; - - case relationship_type::stylesheet: - write_styles(child_rel); - break; - - case relationship_type::theme: - write_theme(child_rel); - break; - - case relationship_type::volatile_dependencies: - write_volatile_dependencies(child_rel); - break; - - case relationship_type::worksheet: - 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::connections: + write_connections(child_rel); + break; + + case relationship_type::custom_xml_mappings: + write_custom_xml_mappings(child_rel); + break; + + case relationship_type::dialogsheet: + write_dialogsheet(child_rel); + break; + + case relationship_type::external_workbook_references: + write_external_workbook_references(child_rel); + break; + + case relationship_type::metadata: + write_metadata(child_rel); + break; + + case relationship_type::pivot_table: + write_pivot_table(child_rel); + break; + + case relationship_type::shared_string_table: + write_shared_string_table(child_rel); + break; + + case relationship_type::shared_workbook_revision_headers: + write_shared_workbook_revision_headers(child_rel); + break; + + case relationship_type::stylesheet: + write_styles(child_rel); + break; + + case relationship_type::theme: + write_theme(child_rel); + break; + + case relationship_type::volatile_dependencies: + write_volatile_dependencies(child_rel); + break; + + case relationship_type::worksheet: + 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; + } } } // Write Workbook Relationship Target Parts -void xlsx_producer::write_calculation_chain(const relationship &/*rel*/) +void xlsx_producer::write_calculation_chain(const relationship & /*rel*/) { - serializer().start_element("calcChain"); + serializer().start_element("calcChain"); } -void xlsx_producer::write_chartsheet(const relationship &/*rel*/) +void xlsx_producer::write_chartsheet(const relationship & /*rel*/) { - serializer().start_element("chartsheet"); + serializer().start_element("chartsheet"); } -void xlsx_producer::write_connections(const relationship &/*rel*/) +void xlsx_producer::write_connections(const relationship & /*rel*/) { - serializer().start_element("connections"); + serializer().start_element("connections"); } -void xlsx_producer::write_custom_xml_mappings(const relationship &/*rel*/) +void xlsx_producer::write_custom_xml_mappings(const relationship & /*rel*/) { - serializer().start_element("MapInfo"); + serializer().start_element("MapInfo"); } -void xlsx_producer::write_dialogsheet(const relationship &/*rel*/) +void xlsx_producer::write_dialogsheet(const relationship & /*rel*/) { - serializer().start_element("dialogsheet"); + serializer().start_element("dialogsheet"); } -void xlsx_producer::write_external_workbook_references(const relationship &/*rel*/) +void xlsx_producer::write_external_workbook_references(const relationship & /*rel*/) { - serializer().start_element("externalLink"); + serializer().start_element("externalLink"); } -void xlsx_producer::write_metadata(const relationship &/*rel*/) +void xlsx_producer::write_metadata(const relationship & /*rel*/) { - serializer().start_element("metadata"); + serializer().start_element("metadata"); } -void xlsx_producer::write_pivot_table(const relationship &/*rel*/) +void xlsx_producer::write_pivot_table(const relationship & /*rel*/) { - serializer().start_element("pivotTableDefinition"); + serializer().start_element("pivotTableDefinition"); } -void xlsx_producer::write_shared_string_table(const relationship &/*rel*/) +void xlsx_producer::write_shared_string_table(const relationship & /*rel*/) { static const auto &xmlns = constants::namespace_("spreadsheetml"); - serializer().start_element(xmlns, "sst"); + serializer().start_element(xmlns, "sst"); serializer().namespace_decl(xmlns, ""); // todo: is there a more elegant way to get this number? @@ -656,35 +712,34 @@ 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; } } } } #pragma clang diagnostic pop - serializer().attribute("count", string_count); - serializer().attribute("uniqueCount", source_.shared_strings().size()); + serializer().attribute("count", string_count); + serializer().attribute("uniqueCount", source_.shared_strings().size()); - for (const auto &string : source_.shared_strings()) - { - if (string.runs().size() == 1 && !string.runs().at(0).second.is_set()) - { + for (const auto &string : source_.shared_strings()) + { + if (string.runs().size() == 1 && !string.runs().at(0).second.is_set()) + { serializer().start_element(xmlns, "si"); serializer().element(xmlns, "t", string.plain_text()); serializer().end_element(xmlns, "si"); - + continue; - } + } serializer().start_element(xmlns, "si"); @@ -731,322 +786,325 @@ void xlsx_producer::write_shared_string_table(const relationship &/*rel*/) serializer().end_element(xmlns, "scheme"); } - if (run.second.get().bold()) - { - serializer().start_element(xmlns, "b"); - serializer().end_element(xmlns, "b"); - } - + if (run.second.get().bold()) + { + serializer().start_element(xmlns, "b"); + serializer().end_element(xmlns, "b"); + } + serializer().end_element(xmlns, "rPr"); } serializer().element(xmlns, "t", run.first); serializer().end_element(xmlns, "r"); } - + serializer().end_element(xmlns, "si"); - } + } serializer().end_element(xmlns, "sst"); } -void xlsx_producer::write_shared_workbook_revision_headers(const relationship &/*rel*/) +void xlsx_producer::write_shared_workbook_revision_headers(const relationship & /*rel*/) { - serializer().start_element("headers"); + serializer().start_element("headers"); } -void xlsx_producer::write_shared_workbook(const relationship &/*rel*/) +void xlsx_producer::write_shared_workbook(const relationship & /*rel*/) { - serializer().start_element("revisions"); + serializer().start_element("revisions"); } -void xlsx_producer::write_shared_workbook_user_data(const relationship &/*rel*/) +void xlsx_producer::write_shared_workbook_user_data(const relationship & /*rel*/) { - serializer().start_element("users"); + serializer().start_element("users"); } -void xlsx_producer::write_styles(const relationship &/*rel*/) +void xlsx_producer::write_styles(const relationship & /*rel*/) { static const auto &xmlns = constants::namespace_("spreadsheetml"); - - serializer().start_element(xmlns, "styleSheet"); - serializer().namespace_decl(xmlns, ""); - const auto &stylesheet = source_.impl().stylesheet_.get(); + serializer().start_element(xmlns, "styleSheet"); + serializer().namespace_decl(xmlns, ""); - // Number Formats + const auto &stylesheet = source_.impl().stylesheet_.get(); - if (!stylesheet.number_formats.empty()) - { + // Number Formats + + if (!stylesheet.number_formats.empty()) + { const auto &number_formats = stylesheet.number_formats; auto num_custom = std::count_if(number_formats.begin(), number_formats.end(), [](const number_format &nf) { return nf.id() >= 164; }); - serializer().start_element(xmlns, "numFmts"); - serializer().attribute("count", num_custom); + if (num_custom > 0) + { + serializer().start_element(xmlns, "numFmts"); + serializer().attribute("count", num_custom); - for (const auto &num_fmt : number_formats) - { - if (num_fmt.id() < 164) continue; - serializer().start_element(xmlns, "numFmt"); - serializer().attribute("numFmtId", num_fmt.id()); - serializer().attribute("formatCode", num_fmt.format_string()); - serializer().end_element(xmlns, "numFmt"); - } - - serializer().end_element(xmlns, "numFmts"); - } + for (const auto &num_fmt : number_formats) + { + if (num_fmt.id() < 164) continue; + serializer().start_element(xmlns, "numFmt"); + serializer().attribute("numFmtId", num_fmt.id()); + serializer().attribute("formatCode", num_fmt.format_string()); + serializer().end_element(xmlns, "numFmt"); + } - // Fonts + serializer().end_element(xmlns, "numFmts"); + } + } - if (!stylesheet.fonts.empty()) - { - const auto &fonts = stylesheet.fonts; + // Fonts - serializer().start_element(xmlns, "fonts"); - serializer().attribute("count", fonts.size()); + if (!stylesheet.fonts.empty()) + { + const auto &fonts = stylesheet.fonts; - for (const auto ¤t_font : fonts) - { - serializer().start_element(xmlns, "font"); + serializer().start_element(xmlns, "fonts"); + serializer().attribute("count", fonts.size()); - if (current_font.bold()) - { + for (const auto ¤t_font : fonts) + { + serializer().start_element(xmlns, "font"); + + if (current_font.bold()) + { serializer().start_element(xmlns, "b"); serializer().attribute("val", write_bool(true)); serializer().end_element(xmlns, "b"); - } + } - if (current_font.italic()) - { + if (current_font.italic()) + { serializer().start_element(xmlns, "i"); serializer().attribute("val", write_bool(true)); serializer().end_element(xmlns, "i"); - } + } - if (current_font.underlined()) - { + if (current_font.underlined()) + { serializer().start_element(xmlns, "u"); serializer().attribute("val", current_font.underline()); serializer().end_element(xmlns, "u"); - } + } - if (current_font.strikethrough()) - { + if (current_font.strikethrough()) + { serializer().start_element(xmlns, "strike"); serializer().attribute("val", write_bool(true)); serializer().end_element(xmlns, "strike"); - } + } serializer().start_element(xmlns, "sz"); serializer().attribute("val", current_font.size()); serializer().end_element(xmlns, "sz"); - if (current_font.has_color()) - { + if (current_font.has_color()) + { serializer().start_element(xmlns, "color"); write_color(current_font.color()); serializer().end_element(xmlns, "color"); - } + } - serializer().start_element(xmlns, "name"); + serializer().start_element(xmlns, "name"); serializer().attribute("val", current_font.name()); serializer().end_element(xmlns, "name"); - if (current_font.has_family()) - { + if (current_font.has_family()) + { serializer().start_element(xmlns, "family"); serializer().attribute("val", current_font.family()); serializer().end_element(xmlns, "family"); - } + } - if (current_font.has_scheme()) - { + if (current_font.has_scheme()) + { serializer().start_element(xmlns, "scheme"); serializer().attribute("val", current_font.scheme()); serializer().end_element(xmlns, "scheme"); - } - + } + serializer().end_element(xmlns, "font"); - } - - serializer().end_element(xmlns, "fonts"); - } + } - // Fills + serializer().end_element(xmlns, "fonts"); + } - if (!stylesheet.fills.empty()) - { - const auto &fills = stylesheet.fills; + // Fills - serializer().start_element(xmlns, "fills"); - serializer().attribute("count", fills.size()); + if (!stylesheet.fills.empty()) + { + const auto &fills = stylesheet.fills; - for (auto &fill_ : fills) - { - serializer().start_element(xmlns, "fill"); + serializer().start_element(xmlns, "fills"); + serializer().attribute("count", fills.size()); - if (fill_.type() == xlnt::fill_type::pattern) - { - const auto &pattern = fill_.pattern_fill(); + for (auto &fill_ : fills) + { + serializer().start_element(xmlns, "fill"); - serializer().start_element(xmlns, "patternFill"); - serializer().attribute("patternType", pattern.type()); + if (fill_.type() == xlnt::fill_type::pattern) + { + const auto &pattern = fill_.pattern_fill(); - if (pattern.foreground()) - { + serializer().start_element(xmlns, "patternFill"); + serializer().attribute("patternType", pattern.type()); + + if (pattern.foreground()) + { serializer().start_element(xmlns, "fgColor"); - write_color(*pattern.foreground()); + write_color(*pattern.foreground()); serializer().end_element(xmlns, "fgColor"); - } + } - if (pattern.background()) - { + if (pattern.background()) + { serializer().start_element(xmlns, "bgColor"); - write_color(*pattern.background()); + write_color(*pattern.background()); serializer().end_element(xmlns, "bgColor"); - } - - serializer().end_element(xmlns, "patternFill"); - } - else if (fill_.type() == xlnt::fill_type::gradient) - { - const auto &gradient = fill_.gradient_fill(); + } - serializer().start_element(xmlns, "gradientFill"); - serializer().attribute("gradientType", gradient.type()); + serializer().end_element(xmlns, "patternFill"); + } + else if (fill_.type() == xlnt::fill_type::gradient) + { + const auto &gradient = fill_.gradient_fill(); - if (gradient.degree() != 0.) - { - serializer().attribute("degree", gradient.degree()); - } + serializer().start_element(xmlns, "gradientFill"); + serializer().attribute("gradientType", gradient.type()); - if (gradient.left() != 0.) - { - serializer().attribute("left", gradient.left()); - } + if (gradient.degree() != 0.) + { + serializer().attribute("degree", gradient.degree()); + } - if (gradient.right() != 0.) - { - serializer().attribute("right", gradient.right()); - } + if (gradient.left() != 0.) + { + serializer().attribute("left", gradient.left()); + } - if (gradient.top() != 0.) - { - serializer().attribute("top", gradient.top()); - } + if (gradient.right() != 0.) + { + serializer().attribute("right", gradient.right()); + } - if (gradient.bottom() != 0.) - { - serializer().attribute("bottom", gradient.bottom()); - } + if (gradient.top() != 0.) + { + serializer().attribute("top", gradient.top()); + } - for (const auto &stop : gradient.stops()) - { - serializer().start_element(xmlns, "stop"); - serializer().attribute("position", stop.first); - serializer().start_element(xmlns, "color"); - write_color(stop.second); - serializer().end_element(xmlns, "color"); - serializer().end_element(xmlns, "stop"); - } - - serializer().end_element(xmlns, "gradientFill"); - } - - serializer().end_element(xmlns, "fill"); - } - - serializer().end_element(xmlns, "fills"); - } + if (gradient.bottom() != 0.) + { + serializer().attribute("bottom", gradient.bottom()); + } - // Borders + for (const auto &stop : gradient.stops()) + { + serializer().start_element(xmlns, "stop"); + serializer().attribute("position", stop.first); + serializer().start_element(xmlns, "color"); + write_color(stop.second); + serializer().end_element(xmlns, "color"); + serializer().end_element(xmlns, "stop"); + } - if (!stylesheet.borders.empty()) - { - const auto &borders = stylesheet.borders; + serializer().end_element(xmlns, "gradientFill"); + } - serializer().start_element(xmlns, "borders"); - serializer().attribute("count", borders.size()); + serializer().end_element(xmlns, "fill"); + } - for (const auto ¤t_border : borders) - { - serializer().start_element(xmlns, "border"); + serializer().end_element(xmlns, "fills"); + } - if (current_border.diagonal()) - { - auto up = *current_border.diagonal() == diagonal_direction::both - || *current_border.diagonal() == diagonal_direction::up; - serializer().attribute("diagonalUp", up ? "true" : "false"); + // Borders - auto down = *current_border.diagonal() == diagonal_direction::both - || *current_border.diagonal() == diagonal_direction::down; + if (!stylesheet.borders.empty()) + { + const auto &borders = stylesheet.borders; + + serializer().start_element(xmlns, "borders"); + serializer().attribute("count", borders.size()); + + for (const auto ¤t_border : borders) + { + serializer().start_element(xmlns, "border"); + + if (current_border.diagonal()) + { + auto up = *current_border.diagonal() == diagonal_direction::both + || *current_border.diagonal() == diagonal_direction::up; + serializer().attribute("diagonalUp", up ? "true" : "false"); + + auto down = *current_border.diagonal() == diagonal_direction::both + || *current_border.diagonal() == diagonal_direction::down; serializer().attribute("diagonalDown", down ? "true" : "false"); - } + } - for (const auto &side : xlnt::border::all_sides()) - { - if (current_border.side(side)) - { - const auto current_side = *current_border.side(side); + for (const auto &side : xlnt::border::all_sides()) + { + if (current_border.side(side)) + { + const auto current_side = *current_border.side(side); - auto side_name = to_string(side); - serializer().start_element(xmlns, side_name); + auto side_name = to_string(side); + serializer().start_element(xmlns, side_name); - if (current_side.style()) - { + if (current_side.style()) + { serializer().attribute("style", *current_side.style()); - } + } - if (current_side.color()) - { - serializer().start_element(xmlns, "color"); - write_color(*current_side.color()); - serializer().end_element(xmlns, "color"); - } - - serializer().end_element(xmlns, side_name); - } - } - - serializer().end_element(xmlns, "border"); - } - - serializer().end_element(xmlns, "borders"); - } + if (current_side.color()) + { + serializer().start_element(xmlns, "color"); + write_color(*current_side.color()); + serializer().end_element(xmlns, "color"); + } + + serializer().end_element(xmlns, side_name); + } + } + + serializer().end_element(xmlns, "border"); + } + + serializer().end_element(xmlns, "borders"); + } // Style XFs - + serializer().start_element(xmlns, "cellStyleXfs"); serializer().attribute("count", stylesheet.style_impls.size()); - for (const auto ¤t_style_name : stylesheet.style_names) - { + for (const auto ¤t_style_name : stylesheet.style_names) + { const auto ¤t_style_impl = stylesheet.style_impls.at(current_style_name); - serializer().start_element(xmlns, "xf"); + serializer().start_element(xmlns, "xf"); serializer().attribute("numFmtId", current_style_impl.number_format_id.get()); serializer().attribute("fontId", current_style_impl.font_id.get()); - serializer().attribute("fillId", current_style_impl.fill_id.get()); - serializer().attribute("borderId", current_style_impl.border_id.get()); + serializer().attribute("fillId", current_style_impl.fill_id.get()); + serializer().attribute("borderId", current_style_impl.border_id.get()); - if (current_style_impl.number_format_applied) + if (current_style_impl.number_format_applied) { serializer().attribute("applyNumberFormat", write_bool(true)); } - if (current_style_impl.fill_applied) + if (current_style_impl.fill_applied) { serializer().attribute("applyFill", write_bool(true)); } - if (current_style_impl.font_applied) + if (current_style_impl.font_applied) { serializer().attribute("applyFont", write_bool(true)); } - if (current_style_impl.border_applied) + if (current_style_impl.border_applied) { serializer().attribute("applyBorder", write_bool(true)); } @@ -1061,72 +1119,72 @@ void xlsx_producer::write_styles(const relationship &/*rel*/) serializer().attribute("applyProtection", write_bool(true)); } - if (current_style_impl.alignment_applied) - { + if (current_style_impl.alignment_applied) + { const auto ¤t_alignment = stylesheet.alignments[current_style_impl.alignment_id.get()]; - serializer().start_element(xmlns, "alignment"); + serializer().start_element(xmlns, "alignment"); - if (current_alignment.vertical()) - { - serializer().attribute("vertical", current_alignment.vertical().get()); - } + if (current_alignment.vertical()) + { + serializer().attribute("vertical", current_alignment.vertical().get()); + } - if (current_alignment.horizontal()) - { - serializer().attribute("horizontal", current_alignment.horizontal().get()); - } + if (current_alignment.horizontal()) + { + serializer().attribute("horizontal", current_alignment.horizontal().get()); + } - if (current_alignment.rotation()) - { - serializer().attribute("textRotation", current_alignment.rotation().get()); - } + if (current_alignment.rotation()) + { + serializer().attribute("textRotation", current_alignment.rotation().get()); + } - if (current_alignment.wrap()) - { - serializer().attribute("wrapText", write_bool(current_alignment.wrap().get())); - } + if (current_alignment.wrap()) + { + serializer().attribute("wrapText", write_bool(current_alignment.wrap().get())); + } - if (current_alignment.indent()) - { - serializer().attribute("indent", current_alignment.indent().get()); - } + if (current_alignment.indent()) + { + serializer().attribute("indent", current_alignment.indent().get()); + } - if (current_alignment.shrink()) - { - serializer().attribute("shrinkToFit", write_bool(current_alignment.shrink().get())); - } - - serializer().end_element(xmlns, "alignment"); - } + if (current_alignment.shrink()) + { + serializer().attribute("shrinkToFit", write_bool(current_alignment.shrink().get())); + } - if (current_style_impl.protection_applied) - { + serializer().end_element(xmlns, "alignment"); + } + + if (current_style_impl.protection_applied) + { const auto ¤t_protection = stylesheet.protections[current_style_impl.protection_id.get()]; - serializer().start_element(xmlns, "protection"); - serializer().attribute("locked", write_bool(current_protection.locked())); - serializer().attribute("hidden", write_bool(current_protection.hidden())); - serializer().end_element(xmlns, "protection"); - } - + serializer().start_element(xmlns, "protection"); + serializer().attribute("locked", write_bool(current_protection.locked())); + serializer().attribute("hidden", write_bool(current_protection.hidden())); + serializer().end_element(xmlns, "protection"); + } + serializer().end_element(xmlns, "xf"); - } - + } + serializer().end_element(xmlns, "cellStyleXfs"); - // Format XFs + // Format XFs - serializer().start_element(xmlns, "cellXfs"); - serializer().attribute("count", stylesheet.format_impls.size()); + serializer().start_element(xmlns, "cellXfs"); + serializer().attribute("count", stylesheet.format_impls.size()); - for (auto ¤t_format_impl : stylesheet.format_impls) - { + for (auto ¤t_format_impl : stylesheet.format_impls) + { serializer().start_element(xmlns, "xf"); - + serializer().attribute("numFmtId", current_format_impl.number_format_id.get()); serializer().attribute("fontId", current_format_impl.font_id.get()); - + if (current_format_impl.style) { serializer().attribute("fillId", stylesheet.style_impls.at(current_format_impl.style.get()).fill_id.get()); @@ -1135,25 +1193,25 @@ void xlsx_producer::write_styles(const relationship &/*rel*/) { serializer().attribute("fillId", current_format_impl.fill_id.get()); } - - serializer().attribute("borderId", current_format_impl.border_id.get()); - if (current_format_impl.number_format_applied) + serializer().attribute("borderId", current_format_impl.border_id.get()); + + if (current_format_impl.number_format_applied) { serializer().attribute("applyNumberFormat", write_bool(true)); } - if (current_format_impl.fill_applied) + if (current_format_impl.fill_applied) { serializer().attribute("applyFill", write_bool(true)); } - if (current_format_impl.font_applied) + if (current_format_impl.font_applied) { serializer().attribute("applyFont", write_bool(true)); } - if (current_format_impl.border_applied) + if (current_format_impl.border_applied) { serializer().attribute("applyBorder", write_bool(true)); } @@ -1168,110 +1226,110 @@ void xlsx_producer::write_styles(const relationship &/*rel*/) serializer().attribute("applyProtection", write_bool(true)); } - if (current_format_impl.style.is_set()) - { - serializer().attribute("xfId", stylesheet.style_index(current_format_impl.style.get())); - } + if (current_format_impl.style.is_set()) + { + serializer().attribute("xfId", stylesheet.style_index(current_format_impl.style.get())); + } - if (current_format_impl.alignment_applied) - { + if (current_format_impl.alignment_applied) + { const auto ¤t_alignment = stylesheet.alignments[current_format_impl.alignment_id.get()]; - serializer().start_element(xmlns, "alignment"); + serializer().start_element(xmlns, "alignment"); - if (current_alignment.vertical()) - { - serializer().attribute("vertical", *current_alignment.vertical()); - } + if (current_alignment.vertical()) + { + serializer().attribute("vertical", *current_alignment.vertical()); + } - if (current_alignment.horizontal()) - { - serializer().attribute("horizontal", *current_alignment.horizontal()); - } + if (current_alignment.horizontal()) + { + serializer().attribute("horizontal", *current_alignment.horizontal()); + } - if (current_alignment.rotation()) - { - serializer().attribute("textRotation", *current_alignment.rotation()); - } + if (current_alignment.rotation()) + { + serializer().attribute("textRotation", *current_alignment.rotation()); + } - if (current_alignment.wrap()) - { - serializer().attribute("wrapText", write_bool(*current_alignment.wrap())); - } + if (current_alignment.wrap()) + { + serializer().attribute("wrapText", write_bool(*current_alignment.wrap())); + } - if (current_alignment.indent()) - { - serializer().attribute("indent", *current_alignment.indent()); - } + if (current_alignment.indent()) + { + serializer().attribute("indent", *current_alignment.indent()); + } - if (current_alignment.shrink()) - { - serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink())); - } - - serializer().end_element(xmlns, "alignment"); - } + if (current_alignment.shrink()) + { + serializer().attribute("shrinkToFit", write_bool(*current_alignment.shrink())); + } - if (current_format_impl.protection_applied) - { + serializer().end_element(xmlns, "alignment"); + } + + if (current_format_impl.protection_applied) + { const auto ¤t_protection = stylesheet.protections[current_format_impl.protection_id.get()]; - serializer().start_element(xmlns, "protection"); - serializer().attribute("locked", write_bool(current_protection.locked())); - serializer().attribute("hidden", write_bool(current_protection.hidden())); - serializer().end_element(xmlns, "protection"); - } + serializer().start_element(xmlns, "protection"); + serializer().attribute("locked", write_bool(current_protection.locked())); + serializer().attribute("hidden", write_bool(current_protection.hidden())); + serializer().end_element(xmlns, "protection"); + } serializer().end_element(xmlns, "xf"); - } - + } + serializer().end_element(xmlns, "cellXfs"); - // Styles + // Styles - serializer().start_element(xmlns, "cellStyles"); + serializer().start_element(xmlns, "cellStyles"); serializer().attribute("count", stylesheet.style_impls.size()); - std::size_t style_index = 0; + std::size_t style_index = 0; - for (auto ¤t_style_name : stylesheet.style_names) - { + for (auto ¤t_style_name : stylesheet.style_names) + { const auto ¤t_style = stylesheet.style_impls.at(current_style_name); - serializer().start_element(xmlns, "cellStyle"); + serializer().start_element(xmlns, "cellStyle"); - serializer().attribute("name", current_style.name); - serializer().attribute("xfId", style_index++); + serializer().attribute("name", current_style.name); + serializer().attribute("xfId", style_index++); - if (current_style.builtin_id) - { - serializer().attribute("builtinId", current_style.builtin_id.get()); - } + if (current_style.builtin_id) + { + serializer().attribute("builtinId", current_style.builtin_id.get()); + } - if (current_style.hidden_style) - { - serializer().attribute("hidden", write_bool(true)); - } + if (current_style.hidden_style) + { + serializer().attribute("hidden", write_bool(true)); + } + + if (current_style.custom_builtin) + { + serializer().attribute("customBuiltin", write_bool(current_style.custom_builtin.get())); + } + + serializer().end_element(xmlns, "cellStyle"); + } - if (current_style.custom_builtin) - { - serializer().attribute("customBuiltin", write_bool(current_style.custom_builtin.get())); - } - - serializer().end_element(xmlns, "cellStyle"); - } - serializer().end_element(xmlns, "cellStyles"); serializer().start_element(xmlns, "dxfs"); - serializer().attribute("count", "0"); + serializer().attribute("count", "0"); serializer().end_element(xmlns, "dxfs"); - + serializer().start_element(xmlns, "tableStyles"); - serializer().attribute("count", "0"); - serializer().attribute("defaultTableStyle", "TableStyleMedium9"); - serializer().attribute("defaultPivotStyle", "PivotStyleMedium7"); + serializer().attribute("count", "0"); + serializer().attribute("defaultTableStyle", "TableStyleMedium9"); + serializer().attribute("defaultPivotStyle", "PivotStyleMedium7"); serializer().end_element(xmlns, "tableStyles"); - + if (!stylesheet.colors.empty()) { serializer().start_element(xmlns, "colors"); @@ -1287,7 +1345,7 @@ void xlsx_producer::write_styles(const relationship &/*rel*/) serializer().end_element(xmlns, "indexedColors"); serializer().end_element(xmlns, "colors"); } - + serializer().end_element(xmlns, "styleSheet"); } @@ -1295,111 +1353,86 @@ void xlsx_producer::write_theme(const relationship &theme_rel) { static const auto &xmlns_a = constants::namespace_("drawingml"); static const auto &xmlns_thm15 = constants::namespace_("thm15"); - - serializer().start_element(xmlns_a, "theme"); + + serializer().start_element(xmlns_a, "theme"); serializer().namespace_decl(xmlns_a, "a"); serializer().attribute("name", "Office Theme"); - serializer().start_element(xmlns_a, "themeElements"); - serializer().start_element(xmlns_a, "clrScheme"); - serializer().attribute("name", "Office"); + serializer().start_element(xmlns_a, "themeElements"); + serializer().start_element(xmlns_a, "clrScheme"); + serializer().attribute("name", "Office"); - struct scheme_element - { - std::string name; - std::string sub_element_name; - std::string val; - }; + struct scheme_element + { + std::string name; + std::string sub_element_name; + std::string val; + }; - std::vector 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" }, - }; + std::vector 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"}, + }; - for (auto element : scheme_elements) - { + for (auto element : scheme_elements) + { serializer().start_element(xmlns_a, element.name); serializer().start_element(xmlns_a, element.sub_element_name); serializer().attribute("val", element.val); - if (element.name == "dk1") - { + if (element.name == "dk1") + { serializer().attribute("lastClr", "000000"); - } - else if (element.name == "lt1") - { + } + else if (element.name == "lt1") + { serializer().attribute("lastClr", "FFFFFF"); - } - + } + serializer().end_element(xmlns_a, element.sub_element_name); serializer().end_element(xmlns_a, element.name); - } - + } + serializer().end_element(xmlns_a, "clrScheme"); - struct font_scheme - { - bool typeface; - std::string script; - std::string major; - std::string minor; - }; + struct font_scheme + { + bool typeface; + std::string script; + std::string major; + std::string minor; + }; - static const auto font_schemes = new std::vector { - { 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, "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" } - }; + static const auto font_schemes = new std::vector{{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, "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"}}; - serializer().start_element(xmlns_a, "fontScheme"); + serializer().start_element(xmlns_a, "fontScheme"); serializer().attribute("name", "Office"); for (auto major : {true, false}) { serializer().start_element(xmlns_a, major ? "majorFont" : "minorFont"); - + for (const auto &scheme : *font_schemes) { const auto scheme_value = major ? scheme.major : scheme.minor; @@ -1417,7 +1450,7 @@ void xlsx_producer::write_theme(const relationship &theme_rel) { serializer().attribute("panose", "020F0502020204030204"); } - + serializer().end_element(xmlns_a, scheme.script); } else @@ -1428,336 +1461,336 @@ void xlsx_producer::write_theme(const relationship &theme_rel) serializer().end_element(xmlns_a, "font"); } } - + serializer().end_element(xmlns_a, major ? "majorFont" : "minorFont"); } - - serializer().end_element(xmlns_a, "fontScheme"); - serializer().start_element(xmlns_a, "fmtScheme"); + serializer().end_element(xmlns_a, "fontScheme"); + + serializer().start_element(xmlns_a, "fmtScheme"); serializer().attribute("name", "Office"); - serializer().start_element(xmlns_a, "fillStyleLst"); - serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "fillStyleLst"); + serializer().start_element(xmlns_a, "solidFill"); serializer().start_element(xmlns_a, "schemeClr"); serializer().attribute("val", "phClr"); serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); + serializer().end_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "gradFill"); - serializer().attribute("rotWithShape", "1"); - serializer().start_element(xmlns_a, "gsLst"); - - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "0"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "gradFill"); + serializer().attribute("rotWithShape", "1"); + serializer().start_element(xmlns_a, "gsLst"); + + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "0"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "lumMod"); serializer().attribute("val", "110000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "satMod"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "satMod"); serializer().attribute("val", "105000"); serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "tint"); serializer().attribute("val", "67000"); - serializer().end_element(xmlns_a, "tint"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); + serializer().end_element(xmlns_a, "tint"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "50000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "50000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "lumMod"); serializer().attribute("val", "105000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "satMod"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "satMod"); serializer().attribute("val", "103000"); serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "tint"); serializer().attribute("val", "73000"); - serializer().end_element(xmlns_a, "tint"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); + serializer().end_element(xmlns_a, "tint"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "100000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "100000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "lumMod"); serializer().attribute("val", "105000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "satMod"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "satMod"); serializer().attribute("val", "109000"); serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "tint"); serializer().attribute("val", "81000"); - serializer().end_element(xmlns_a, "tint"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); - - serializer().end_element(xmlns_a, "gsLst"); - - serializer().start_element(xmlns_a, "lin"); - serializer().attribute("ang", "5400000"); - serializer().attribute("scaled", "0"); - serializer().end_element(xmlns_a, "lin"); - - serializer().end_element(xmlns_a, "gradFill"); - - serializer().start_element(xmlns_a, "gradFill"); - serializer().attribute("rotWithShape", "1"); - serializer().start_element(xmlns_a, "gsLst"); - - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "0"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "103000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "lumMod"); - serializer().attribute("val", "102000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "tint"); - serializer().attribute("val", "94000"); - serializer().end_element(xmlns_a, "tint"); - serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "tint"); + serializer().end_element(xmlns_a, "schemeClr"); serializer().end_element(xmlns_a, "gs"); - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "50000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "110000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "lumMod"); - serializer().attribute("val", "100000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "shade"); - serializer().attribute("val", "100000"); - serializer().end_element(xmlns_a, "shade"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); + serializer().end_element(xmlns_a, "gsLst"); - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "100000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "lumMod"); - serializer().attribute("val", "99000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "120000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "shade"); - serializer().attribute("val", "78000"); - serializer().end_element(xmlns_a, "shade"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); - - serializer().end_element(xmlns_a, "gsLst"); - - serializer().start_element(xmlns_a, "lin"); - serializer().attribute("ang", "5400000"); - serializer().attribute("scaled", "0"); + serializer().start_element(xmlns_a, "lin"); + serializer().attribute("ang", "5400000"); + serializer().attribute("scaled", "0"); serializer().end_element(xmlns_a, "lin"); - + serializer().end_element(xmlns_a, "gradFill"); - serializer().end_element(xmlns_a, "fillStyleLst"); - serializer().start_element(xmlns_a, "lnStyleLst"); + serializer().start_element(xmlns_a, "gradFill"); + serializer().attribute("rotWithShape", "1"); + serializer().start_element(xmlns_a, "gsLst"); - serializer().start_element(xmlns_a, "ln"); - serializer().attribute("w", "6350"); - serializer().attribute("cap", "flat"); - serializer().attribute("cmpd", "sng"); - serializer().attribute("algn", "ctr"); - serializer().start_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "prstDash"); - serializer().attribute("val", "solid"); - serializer().end_element(xmlns_a, "prstDash"); - serializer().start_element(xmlns_a, "miter"); - serializer().attribute("lim", "800000"); - serializer().end_element(xmlns_a, "miter"); - serializer().end_element(xmlns_a, "ln"); - - serializer().start_element(xmlns_a, "ln"); - serializer().attribute("w", "12700"); - serializer().attribute("cap", "flat"); - serializer().attribute("cmpd", "sng"); - serializer().attribute("algn", "ctr"); - serializer().start_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "prstDash"); - serializer().attribute("val", "solid"); - serializer().end_element(xmlns_a, "prstDash"); - serializer().start_element(xmlns_a, "miter"); - serializer().attribute("lim", "800000"); - serializer().end_element(xmlns_a, "miter"); - serializer().end_element(xmlns_a, "ln"); - - serializer().start_element(xmlns_a, "ln"); - serializer().attribute("w", "19050"); - serializer().attribute("cap", "flat"); - serializer().attribute("cmpd", "sng"); - serializer().attribute("algn", "ctr"); - serializer().start_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "prstDash"); - serializer().attribute("val", "solid"); - serializer().end_element(xmlns_a, "prstDash"); - serializer().start_element(xmlns_a, "miter"); - serializer().attribute("lim", "800000"); - serializer().end_element(xmlns_a, "miter"); - serializer().end_element(xmlns_a, "ln"); - - serializer().end_element(xmlns_a, "lnStyleLst"); - - serializer().start_element(xmlns_a, "effectStyleLst"); - - serializer().start_element(xmlns_a, "effectStyle"); - serializer().element(xmlns_a, "effectLst", ""); - serializer().end_element(xmlns_a, "effectStyle"); - - serializer().start_element(xmlns_a, "effectStyle"); - serializer().element(xmlns_a, "effectLst", ""); - serializer().end_element(xmlns_a, "effectStyle"); - - serializer().start_element(xmlns_a, "effectStyle"); - serializer().start_element(xmlns_a, "effectLst"); - serializer().start_element(xmlns_a, "outerShdw"); - serializer().attribute("blurRad", "57150"); - serializer().attribute("dist", "19050"); - serializer().attribute("dir", "5400000"); - serializer().attribute("algn", "ctr"); - serializer().attribute("rotWithShape", "0"); - serializer().start_element(xmlns_a, "srgbClr"); - serializer().attribute("val", "000000"); - serializer().start_element(xmlns_a, "alpha"); - serializer().attribute("val", "63000"); - serializer().end_element(xmlns_a, "alpha"); - serializer().end_element(xmlns_a, "srgbClr"); - serializer().end_element(xmlns_a, "outerShdw"); - serializer().end_element(xmlns_a, "effectLst"); - serializer().end_element(xmlns_a, "effectStyle"); - - serializer().end_element(xmlns_a, "effectStyleLst"); - - serializer().start_element(xmlns_a, "bgFillStyleLst"); - - serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "0"); serializer().start_element(xmlns_a, "schemeClr"); serializer().attribute("val", "phClr"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); - - serializer().start_element(xmlns_a, "solidFill"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "tint"); - serializer().attribute("val", "95000"); - serializer().end_element(xmlns_a, "tint"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "170000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "solidFill"); - - serializer().start_element(xmlns_a, "gradFill"); - serializer().attribute("rotWithShape", "1"); - serializer().start_element(xmlns_a, "gsLst"); - - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "0"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "tint"); - serializer().attribute("val", "93000"); - serializer().end_element(xmlns_a, "tint"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "150000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "shade"); - serializer().attribute("val", "98000"); - serializer().end_element(xmlns_a, "shade"); - serializer().start_element(xmlns_a, "lumMod"); - serializer().attribute("val", "102000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); - - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "50000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "tint"); - serializer().attribute("val", "98000"); - serializer().end_element(xmlns_a, "tint"); - serializer().start_element(xmlns_a, "satMod"); - serializer().attribute("val", "130000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().start_element(xmlns_a, "shade"); - serializer().attribute("val", "90000"); - serializer().end_element(xmlns_a, "shade"); - serializer().start_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "satMod"); serializer().attribute("val", "103000"); - serializer().end_element(xmlns_a, "lumMod"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); + serializer().end_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "lumMod"); + serializer().attribute("val", "102000"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "tint"); + serializer().attribute("val", "94000"); + serializer().end_element(xmlns_a, "tint"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); - serializer().start_element(xmlns_a, "gs"); - serializer().attribute("pos", "100000"); - serializer().start_element(xmlns_a, "schemeClr"); - serializer().attribute("val", "phClr"); - serializer().start_element(xmlns_a, "shade"); - serializer().attribute("val", "63000"); - serializer().end_element(xmlns_a, "shade"); - serializer().start_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "50000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "satMod"); + serializer().attribute("val", "110000"); + serializer().end_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "lumMod"); + serializer().attribute("val", "100000"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "shade"); + serializer().attribute("val", "100000"); + serializer().end_element(xmlns_a, "shade"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); + + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "100000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "lumMod"); + serializer().attribute("val", "99000"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().start_element(xmlns_a, "satMod"); serializer().attribute("val", "120000"); - serializer().end_element(xmlns_a, "satMod"); - serializer().end_element(xmlns_a, "schemeClr"); - serializer().end_element(xmlns_a, "gs"); + serializer().end_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "shade"); + serializer().attribute("val", "78000"); + serializer().end_element(xmlns_a, "shade"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); - serializer().end_element(xmlns_a, "gsLst"); + serializer().end_element(xmlns_a, "gsLst"); - serializer().start_element(xmlns_a, "lin"); - serializer().attribute("ang", "5400000"); - serializer().attribute("scaled", "0"); - serializer().end_element(xmlns_a, "lin"); + serializer().start_element(xmlns_a, "lin"); + serializer().attribute("ang", "5400000"); + serializer().attribute("scaled", "0"); + serializer().end_element(xmlns_a, "lin"); - serializer().end_element(xmlns_a, "gradFill"); + serializer().end_element(xmlns_a, "gradFill"); + serializer().end_element(xmlns_a, "fillStyleLst"); - serializer().end_element(xmlns_a, "bgFillStyleLst"); - serializer().end_element(xmlns_a, "fmtScheme"); - serializer().end_element(xmlns_a, "themeElements"); + serializer().start_element(xmlns_a, "lnStyleLst"); - serializer().element(xmlns_a, "objectDefaults", ""); - serializer().element(xmlns_a, "extraClrSchemeLst", ""); + serializer().start_element(xmlns_a, "ln"); + serializer().attribute("w", "6350"); + serializer().attribute("cap", "flat"); + serializer().attribute("cmpd", "sng"); + serializer().attribute("algn", "ctr"); + serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "prstDash"); + serializer().attribute("val", "solid"); + serializer().end_element(xmlns_a, "prstDash"); + serializer().start_element(xmlns_a, "miter"); + serializer().attribute("lim", "800000"); + serializer().end_element(xmlns_a, "miter"); + serializer().end_element(xmlns_a, "ln"); - serializer().start_element(xmlns_a, "extLst"); - serializer().start_element(xmlns_a, "ext"); - serializer().attribute("uri", "{05A4C25C-085E-4340-85A3-A5531E510DB2}"); + serializer().start_element(xmlns_a, "ln"); + serializer().attribute("w", "12700"); + serializer().attribute("cap", "flat"); + serializer().attribute("cmpd", "sng"); + serializer().attribute("algn", "ctr"); + serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "prstDash"); + serializer().attribute("val", "solid"); + serializer().end_element(xmlns_a, "prstDash"); + serializer().start_element(xmlns_a, "miter"); + serializer().attribute("lim", "800000"); + serializer().end_element(xmlns_a, "miter"); + serializer().end_element(xmlns_a, "ln"); + + serializer().start_element(xmlns_a, "ln"); + serializer().attribute("w", "19050"); + serializer().attribute("cap", "flat"); + serializer().attribute("cmpd", "sng"); + serializer().attribute("algn", "ctr"); + serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "prstDash"); + serializer().attribute("val", "solid"); + serializer().end_element(xmlns_a, "prstDash"); + serializer().start_element(xmlns_a, "miter"); + serializer().attribute("lim", "800000"); + serializer().end_element(xmlns_a, "miter"); + serializer().end_element(xmlns_a, "ln"); + + serializer().end_element(xmlns_a, "lnStyleLst"); + + serializer().start_element(xmlns_a, "effectStyleLst"); + + serializer().start_element(xmlns_a, "effectStyle"); + serializer().element(xmlns_a, "effectLst", ""); + serializer().end_element(xmlns_a, "effectStyle"); + + serializer().start_element(xmlns_a, "effectStyle"); + serializer().element(xmlns_a, "effectLst", ""); + serializer().end_element(xmlns_a, "effectStyle"); + + serializer().start_element(xmlns_a, "effectStyle"); + serializer().start_element(xmlns_a, "effectLst"); + serializer().start_element(xmlns_a, "outerShdw"); + serializer().attribute("blurRad", "57150"); + serializer().attribute("dist", "19050"); + serializer().attribute("dir", "5400000"); + serializer().attribute("algn", "ctr"); + serializer().attribute("rotWithShape", "0"); + serializer().start_element(xmlns_a, "srgbClr"); + serializer().attribute("val", "000000"); + serializer().start_element(xmlns_a, "alpha"); + serializer().attribute("val", "63000"); + serializer().end_element(xmlns_a, "alpha"); + serializer().end_element(xmlns_a, "srgbClr"); + serializer().end_element(xmlns_a, "outerShdw"); + serializer().end_element(xmlns_a, "effectLst"); + serializer().end_element(xmlns_a, "effectStyle"); + + serializer().end_element(xmlns_a, "effectStyleLst"); + + serializer().start_element(xmlns_a, "bgFillStyleLst"); + + serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "solidFill"); + + serializer().start_element(xmlns_a, "solidFill"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "tint"); + serializer().attribute("val", "95000"); + serializer().end_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "satMod"); + serializer().attribute("val", "170000"); + serializer().end_element(xmlns_a, "satMod"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "solidFill"); + + serializer().start_element(xmlns_a, "gradFill"); + serializer().attribute("rotWithShape", "1"); + serializer().start_element(xmlns_a, "gsLst"); + + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "0"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "tint"); + serializer().attribute("val", "93000"); + serializer().end_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "satMod"); + serializer().attribute("val", "150000"); + serializer().end_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "shade"); + serializer().attribute("val", "98000"); + serializer().end_element(xmlns_a, "shade"); + serializer().start_element(xmlns_a, "lumMod"); + serializer().attribute("val", "102000"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); + + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "50000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "tint"); + serializer().attribute("val", "98000"); + serializer().end_element(xmlns_a, "tint"); + serializer().start_element(xmlns_a, "satMod"); + serializer().attribute("val", "130000"); + serializer().end_element(xmlns_a, "satMod"); + serializer().start_element(xmlns_a, "shade"); + serializer().attribute("val", "90000"); + serializer().end_element(xmlns_a, "shade"); + serializer().start_element(xmlns_a, "lumMod"); + serializer().attribute("val", "103000"); + serializer().end_element(xmlns_a, "lumMod"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); + + serializer().start_element(xmlns_a, "gs"); + serializer().attribute("pos", "100000"); + serializer().start_element(xmlns_a, "schemeClr"); + serializer().attribute("val", "phClr"); + serializer().start_element(xmlns_a, "shade"); + serializer().attribute("val", "63000"); + serializer().end_element(xmlns_a, "shade"); + serializer().start_element(xmlns_a, "satMod"); + serializer().attribute("val", "120000"); + serializer().end_element(xmlns_a, "satMod"); + serializer().end_element(xmlns_a, "schemeClr"); + serializer().end_element(xmlns_a, "gs"); + + serializer().end_element(xmlns_a, "gsLst"); + + serializer().start_element(xmlns_a, "lin"); + serializer().attribute("ang", "5400000"); + serializer().attribute("scaled", "0"); + serializer().end_element(xmlns_a, "lin"); + + serializer().end_element(xmlns_a, "gradFill"); + + serializer().end_element(xmlns_a, "bgFillStyleLst"); + serializer().end_element(xmlns_a, "fmtScheme"); + serializer().end_element(xmlns_a, "themeElements"); + + serializer().element(xmlns_a, "objectDefaults", ""); + serializer().element(xmlns_a, "extraClrSchemeLst", ""); + + serializer().start_element(xmlns_a, "extLst"); + serializer().start_element(xmlns_a, "ext"); + serializer().attribute("uri", "{05A4C25C-085E-4340-85A3-A5531E510DB2}"); serializer().start_element(xmlns_thm15, "themeFamily"); serializer().namespace_decl(xmlns_thm15, "thm15"); - serializer().attribute("name", "Office Theme"); - serializer().attribute("id", "{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}"); - serializer().attribute("vid", "{4A3C46E8-61CC-4603-A589-7422A47A8E4A}"); - serializer().end_element(xmlns_thm15, "themeFamily"); - serializer().end_element(xmlns_a, "ext"); - serializer().end_element(xmlns_a, "extLst"); - + serializer().attribute("name", "Office Theme"); + serializer().attribute("id", "{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}"); + serializer().attribute("vid", "{4A3C46E8-61CC-4603-A589-7422A47A8E4A}"); + serializer().end_element(xmlns_thm15, "themeFamily"); + serializer().end_element(xmlns_a, "ext"); + serializer().end_element(xmlns_a, "extLst"); + serializer().end_element(xmlns_a, "theme"); const auto workbook_rel = source_.manifest().relationship(path("/"), relationship_type::office_document); @@ -1779,71 +1812,70 @@ void xlsx_producer::write_theme(const relationship &theme_rel) } } -void xlsx_producer::write_volatile_dependencies(const relationship &/*rel*/) +void xlsx_producer::write_volatile_dependencies(const relationship & /*rel*/) { - serializer().start_element("volTypes"); + serializer().start_element("volTypes"); } void xlsx_producer::write_worksheet(const relationship &rel) { - static const auto &xmlns = constants::namespace_("spreadsheetml"); - static const auto &xmlns_r = constants::namespace_("r"); + static const auto &xmlns = constants::namespace_("spreadsheetml"); + static const auto &xmlns_r = constants::namespace_("r"); - auto worksheet_part = rel.source().path().parent().append(rel.target().path()); - auto worksheet_rels = source_.manifest().relationships(worksheet_part); + 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 &p) - { - return p.second == rel.id(); - })->first; + auto title = std::find_if(source_.d_->sheet_title_rel_id_map_.begin(), source_.d_->sheet_title_rel_id_map_.end(), + [&](const std::pair &p) { + return p.second == rel.id(); + })->first; - auto ws = source_.sheet_by_title(title); + auto ws = source_.sheet_by_title(title); - serializer().start_element(xmlns, "worksheet"); + serializer().start_element(xmlns, "worksheet"); serializer().namespace_decl(xmlns, ""); serializer().namespace_decl(xmlns_r, "r"); - if (ws.has_page_setup()) - { - serializer().start_element(xmlns, "sheetPr"); + if (ws.has_page_setup()) + { + serializer().start_element(xmlns, "sheetPr"); - serializer().start_element(xmlns, "outlinePr"); + serializer().start_element(xmlns, "outlinePr"); serializer().attribute("summaryBelow", "1"); - serializer().attribute("summaryRight", "1"); + serializer().attribute("summaryRight", "1"); serializer().end_element(xmlns, "outlinePr"); - serializer().start_element(xmlns, "pageSetUpPr"); - serializer().attribute("fitToPage", write_bool(ws.page_setup().fit_to_page())); - serializer().end_element(xmlns, "pageSetUpPr"); + serializer().start_element(xmlns, "pageSetUpPr"); + serializer().attribute("fitToPage", write_bool(ws.page_setup().fit_to_page())); + serializer().end_element(xmlns, "pageSetUpPr"); - serializer().end_element(xmlns, "sheetPr"); - } + serializer().end_element(xmlns, "sheetPr"); + } 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()) - { - serializer().start_element(xmlns, "sheetViews"); - serializer().start_element(xmlns, "sheetView"); + if (ws.has_view()) + { + serializer().start_element(xmlns, "sheetViews"); + serializer().start_element(xmlns, "sheetView"); - const auto view = ws.view(); + const auto view = ws.view(); - serializer().attribute("tabSelected", write_bool(view.id() == 0)); - serializer().attribute("workbookViewId", view.id()); + serializer().attribute("tabSelected", write_bool(view.id() == 0)); + serializer().attribute("workbookViewId", view.id()); 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()) - { + if (view.has_pane()) + { const auto ¤t_pane = view.pane(); serializer().start_element(xmlns, "pane"); // CT_Pane @@ -1866,64 +1898,64 @@ void xlsx_producer::write_worksheet(const relationship &rel) } serializer().end_element(xmlns, "pane"); - } + } for (const auto ¤t_selection : view.selections()) - { - serializer().start_element(xmlns, "selection"); // CT_Selection + { + serializer().start_element(xmlns, "selection"); // CT_Selection - if (current_selection.has_active_cell()) - { - serializer().attribute("activeCell", current_selection.active_cell().to_string()); - serializer().attribute("sqref", current_selection.active_cell().to_string()); - } -/* - if (current_selection.sqref() != "A1:A1") + if (current_selection.has_active_cell()) { - serializer().attribute("sqref", current_selection.sqref().to_string()); + serializer().attribute("activeCell", current_selection.active_cell().to_string()); + serializer().attribute("sqref", current_selection.active_cell().to_string()); } -*/ + /* + if (current_selection.sqref() != "A1:A1") + { + serializer().attribute("sqref", current_selection.sqref().to_string()); + } + */ if (current_selection.pane() != pane_corner::top_left) { serializer().attribute("pane", current_selection.pane()); } serializer().end_element(xmlns, "selection"); - } + } - serializer().end_element(xmlns, "sheetView"); + serializer().end_element(xmlns, "sheetView"); serializer().end_element(xmlns, "sheetViews"); - } + } serializer().start_element(xmlns, "sheetFormatPr"); serializer().attribute("baseColWidth", "10"); serializer().attribute("defaultRowHeight", "16"); serializer().end_element(xmlns, "sheetFormatPr"); - bool has_column_properties = false; + bool has_column_properties = false; - for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++) - { - if (ws.has_column_properties(column)) - { - has_column_properties = true; - break; - } - } + for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++) + { + if (ws.has_column_properties(column)) + { + has_column_properties = true; + break; + } + } - if (has_column_properties) - { - serializer().start_element(xmlns, "cols"); + if (has_column_properties) + { + serializer().start_element(xmlns, "cols"); - for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++) - { - if (!ws.has_column_properties(column)) continue; + for (auto column = ws.lowest_column(); column <= ws.highest_column(); column++) + { + if (!ws.has_column_properties(column)) continue; - const auto &props = ws.column_properties(column); + const auto &props = ws.column_properties(column); serializer().start_element(xmlns, "col"); - serializer().attribute("min", column.index); - serializer().attribute("max", column.index); + serializer().attribute("min", column.index); + serializer().attribute("max", column.index); if (props.width.is_set()) { @@ -1939,63 +1971,63 @@ void xlsx_producer::write_worksheet(const relationship &rel) { serializer().attribute("style", props.style.get()); } - + if (props.hidden) { serializer().attribute("hidden", write_bool(true)); } serializer().end_element(xmlns, "col"); - } - - serializer().end_element(xmlns, "cols"); - } + } + + serializer().end_element(xmlns, "cols"); + } const auto hyperlink_rels = source_.manifest().relationships(worksheet_part, relationship_type::hyperlink); std::unordered_map reverse_hyperlink_references; - + for (auto hyperlink_rel : hyperlink_rels) { reverse_hyperlink_references[hyperlink_rel.target().path().string()] = rel.id(); } - std::unordered_map hyperlink_references; + std::unordered_map hyperlink_references; - serializer().start_element(xmlns, "sheetData"); - const auto &shared_strings = ws.workbook().shared_strings(); - std::vector cells_with_comments; + serializer().start_element(xmlns, "sheetData"); + const auto &shared_strings = ws.workbook().shared_strings(); + std::vector cells_with_comments; - for (auto row : ws.rows()) - { - auto min = static_cast(row.length()); - xlnt::row_t max = 0; - bool any_non_null = false; + for (auto row : ws.rows()) + { + auto min = static_cast(row.length()); + xlnt::row_t max = 0; + bool any_non_null = false; - for (auto cell : row) - { - min = std::min(min, cell.column().index); - max = std::max(max, cell.column().index); + for (auto cell : row) + { + min = std::min(min, cell.column().index); + max = std::max(max, cell.column().index); - if (!cell.garbage_collectible()) - { - any_non_null = true; - } - } + if (!cell.garbage_collectible()) + { + any_non_null = true; + } + } - if (!any_non_null) - { - continue; - } + if (!any_non_null) + { + continue; + } - serializer().start_element(xmlns, "row"); + serializer().start_element(xmlns, "row"); - serializer().attribute("r", row.front().row()); - serializer().attribute("spans", std::to_string(min) + ":" + std::to_string(max)); + serializer().attribute("r", row.front().row()); + serializer().attribute("spans", std::to_string(min) + ":" + std::to_string(max)); - if (ws.has_row_properties(row.front().row())) - { + if (ws.has_row_properties(row.front().row())) + { const auto &props = ws.row_properties(row.front().row()); - + if (props.custom_height) { serializer().attribute("customHeight", write_bool(true)); @@ -2019,155 +2051,155 @@ void xlsx_producer::write_worksheet(const relationship &rel) { serializer().attribute("hidden", write_bool(true)); } - } + } - for (auto cell : row) - { - if (cell.has_comment()) - { - cells_with_comments.push_back(cell.reference()); - } + for (auto cell : row) + { + if (cell.has_comment()) + { + cells_with_comments.push_back(cell.reference()); + } - if (!cell.garbage_collectible()) - { - serializer().start_element(xmlns, "c"); - serializer().attribute("r", cell.reference().to_string()); - - if (cell.has_format()) - { - serializer().attribute("s", cell.format().id()); - } + if (!cell.garbage_collectible()) + { + serializer().start_element(xmlns, "c"); + serializer().attribute("r", cell.reference().to_string()); + + if (cell.has_format()) + { + serializer().attribute("s", cell.format().id()); + } if (cell.has_hyperlink()) { hyperlink_references[cell.reference().to_string()] = reverse_hyperlink_references[cell.hyperlink()]; } - if (cell.data_type() == cell::type::string) - { - if (cell.has_formula()) - { - serializer().attribute("t", "str"); - serializer().element(xmlns, "f", cell.formula()); - serializer().element(xmlns, "v", cell.to_string()); + if (cell.data_type() == cell::type::string) + { + if (cell.has_formula()) + { + serializer().attribute("t", "str"); + serializer().element(xmlns, "f", cell.formula()); + serializer().element(xmlns, "v", cell.to_string()); serializer().end_element(xmlns, "c"); - continue; - } + continue; + } - int match_index = -1; + int match_index = -1; - for (std::size_t i = 0; i < shared_strings.size(); i++) - { - if (shared_strings[i] == cell.value()) - { - match_index = static_cast(i); - break; - } - } + for (std::size_t i = 0; i < shared_strings.size(); i++) + { + if (shared_strings[i] == cell.value()) + { + match_index = static_cast(i); + break; + } + } - if (match_index == -1) - { - if (cell.value().empty()) - { - serializer().attribute("t", "s"); - } - else - { - serializer().attribute("t", "inlineStr"); - serializer().start_element(xmlns, "is"); - serializer().element(xmlns, "t", cell.value()); - serializer().end_element(xmlns, "is"); - } - } - else - { - serializer().attribute("t", "s"); - serializer().element(xmlns, "v", match_index); - } - } - else - { - if (cell.data_type() != cell::type::null) - { - if (cell.data_type() == cell::type::boolean) - { - serializer().attribute("t", "b"); - serializer().element(xmlns, "v", write_bool(cell.value())); - } - else if (cell.data_type() == cell::type::numeric) - { - if (cell.has_formula()) - { - serializer().element(xmlns, "f", cell.formula()); - serializer().element(xmlns, "v", cell.to_string()); + if (match_index == -1) + { + if (cell.value().empty()) + { + serializer().attribute("t", "s"); + } + else + { + serializer().attribute("t", "inlineStr"); + serializer().start_element(xmlns, "is"); + serializer().element(xmlns, "t", cell.value()); + serializer().end_element(xmlns, "is"); + } + } + else + { + serializer().attribute("t", "s"); + serializer().element(xmlns, "v", match_index); + } + } + else + { + if (cell.data_type() != cell::type::null) + { + if (cell.data_type() == cell::type::boolean) + { + serializer().attribute("t", "b"); + serializer().element(xmlns, "v", write_bool(cell.value())); + } + else if (cell.data_type() == cell::type::numeric) + { + if (cell.has_formula()) + { + serializer().element(xmlns, "f", cell.formula()); + serializer().element(xmlns, "v", cell.to_string()); serializer().end_element(xmlns, "c"); - continue; - } + continue; + } - serializer().attribute("t", "n"); - serializer().start_element(xmlns, "v"); + serializer().attribute("t", "n"); + serializer().start_element(xmlns, "v"); - if (is_integral(cell.value())) - { + if (is_integral(cell.value())) + { serializer().characters(cell.value()); - } - else - { - std::stringstream ss; - ss.precision(20); - ss << cell.value(); - ss.str(); + } + else + { + std::stringstream ss; + ss.precision(20); + ss << cell.value(); + ss.str(); serializer().characters(ss.str()); - } - + } + serializer().end_element(xmlns, "v"); - } - } - else if (cell.has_formula()) - { + } + } + else if (cell.has_formula()) + { serializer().element(xmlns, "f", cell.formula()); // todo (but probably not) could calculate the formula and set the value here serializer().end_element(xmlns, "c"); continue; - } - } - + } + } + serializer().end_element(xmlns, "c"); - } - } - + } + } + serializer().end_element(xmlns, "row"); - } + } serializer().end_element(xmlns, "sheetData"); - if (ws.has_auto_filter()) - { - serializer().start_element(xmlns, "autoFilter"); - serializer().attribute("ref", ws.auto_filter().to_string()); - serializer().end_element(xmlns, "autoFilter"); - } + if (ws.has_auto_filter()) + { + serializer().start_element(xmlns, "autoFilter"); + serializer().attribute("ref", ws.auto_filter().to_string()); + serializer().end_element(xmlns, "autoFilter"); + } - if (!ws.merged_ranges().empty()) - { - serializer().start_element(xmlns, "mergeCells"); - serializer().attribute("count", ws.merged_ranges().size()); + if (!ws.merged_ranges().empty()) + { + serializer().start_element(xmlns, "mergeCells"); + serializer().attribute("count", ws.merged_ranges().size()); - for (auto merged_range : ws.merged_ranges()) - { + for (auto merged_range : ws.merged_ranges()) + { serializer().start_element(xmlns, "mergeCell"); - serializer().attribute("ref", merged_range.to_string()); + serializer().attribute("ref", merged_range.to_string()); serializer().end_element(xmlns, "mergeCell"); - } - - serializer().end_element(xmlns, "mergeCells"); - } + } - if (!hyperlink_rels.empty()) - { + serializer().end_element(xmlns, "mergeCells"); + } + + if (!hyperlink_rels.empty()) + { serializer().start_element(xmlns, "hyperlinks"); for (const auto &hyperlink : hyperlink_references) @@ -2177,71 +2209,69 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().attribute(xmlns_r, "id", hyperlink.second); serializer().end_element(xmlns, "hyperlink"); } - + serializer().end_element(xmlns, "hyperlinks"); - } + } - if (ws.has_page_setup()) - { - serializer().start_element(xmlns, "printOptions"); - serializer().attribute("horizontalCentered", write_bool(ws.page_setup().horizontal_centered())); - serializer().attribute("verticalCentered", write_bool(ws.page_setup().vertical_centered())); - serializer().end_element(xmlns, "printOptions"); - } + if (ws.has_page_setup()) + { + serializer().start_element(xmlns, "printOptions"); + serializer().attribute("horizontalCentered", write_bool(ws.page_setup().horizontal_centered())); + serializer().attribute("verticalCentered", write_bool(ws.page_setup().vertical_centered())); + serializer().end_element(xmlns, "printOptions"); + } - if (ws.has_page_margins()) - { - serializer().start_element(xmlns, "pageMargins"); + if (ws.has_page_margins()) + { + serializer().start_element(xmlns, "pageMargins"); - //TODO: there must be a better way to do this - auto remove_trailing_zeros = [](const std::string &n) - { - auto decimal = n.find('.'); + // TODO: there must be a better way to do this + auto remove_trailing_zeros = [](const std::string &n) { + auto decimal = n.find('.'); - if (decimal == std::string::npos) return n; + if (decimal == std::string::npos) return n; - auto index = n.size() - 1; + auto index = n.size() - 1; - while (index >= decimal && n[index] == '0') - { - index--; - } + while (index >= decimal && n[index] == '0') + { + index--; + } - if (index == decimal) - { - return n.substr(0, decimal); - } + if (index == decimal) + { + return n.substr(0, decimal); + } - return n.substr(0, index + 1); - }; + return n.substr(0, index + 1); + }; + + serializer().attribute("left", remove_trailing_zeros(std::to_string(ws.page_margins().left()))); + serializer().attribute("right", remove_trailing_zeros(std::to_string(ws.page_margins().right()))); + serializer().attribute("top", remove_trailing_zeros(std::to_string(ws.page_margins().top()))); + serializer().attribute("bottom", remove_trailing_zeros(std::to_string(ws.page_margins().bottom()))); + serializer().attribute("header", remove_trailing_zeros(std::to_string(ws.page_margins().header()))); + serializer().attribute("footer", remove_trailing_zeros(std::to_string(ws.page_margins().footer()))); - serializer().attribute("left", remove_trailing_zeros(std::to_string(ws.page_margins().left()))); - serializer().attribute("right", remove_trailing_zeros(std::to_string(ws.page_margins().right()))); - serializer().attribute("top", remove_trailing_zeros(std::to_string(ws.page_margins().top()))); - serializer().attribute("bottom", remove_trailing_zeros(std::to_string(ws.page_margins().bottom()))); - serializer().attribute("header", remove_trailing_zeros(std::to_string(ws.page_margins().header()))); - serializer().attribute("footer", remove_trailing_zeros(std::to_string(ws.page_margins().footer()))); - serializer().end_element(xmlns, "pageMargins"); - } + } - if (ws.has_page_setup()) - { - serializer().start_element(xmlns, "pageSetup"); - serializer().attribute("orientation", - ws.page_setup().orientation() == xlnt::orientation::landscape - ? "landscape" : "portrait"); - serializer().attribute("paperSize", static_cast(ws.page_setup().paper_size())); + if (ws.has_page_setup()) + { + serializer().start_element(xmlns, "pageSetup"); + serializer().attribute( + "orientation", ws.page_setup().orientation() == xlnt::orientation::landscape ? "landscape" : "portrait"); + serializer().attribute("paperSize", static_cast(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())); - serializer().end_element(xmlns, "pageSetup"); - } + serializer().attribute("fitToWidth", write_bool(ws.page_setup().fit_to_width())); + serializer().end_element(xmlns, "pageSetup"); + } - if (ws.has_header_footer()) - { + if (ws.has_header_footer()) + { const auto hf = ws.header_footer(); - serializer().start_element(xmlns, "headerFooter"); + serializer().start_element(xmlns, "headerFooter"); auto odd_header = std::string(); auto odd_footer = std::string(); @@ -2250,14 +2280,12 @@ 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::left, "&L" }, - { header_footer::location::center, "&C" }, - { header_footer::location::right, "&R" }, - }; + const auto encode_text = [](const rich_text &t, header_footer::location where) { + const auto location_code_map = + std::unordered_map>{ + {header_footer::location::left, "&L"}, {header_footer::location::center, "&C"}, + {header_footer::location::right, "&R"}, + }; auto encoded = location_code_map.at(where); @@ -2282,7 +2310,7 @@ void xlsx_producer::write_worksheet(const relationship &rel) { encoded.append("Regular"); } - //todo: BoldItalic? + // todo: BoldItalic? encoded.push_back('"'); } @@ -2290,7 +2318,7 @@ void xlsx_producer::write_worksheet(const relationship &rel) { encoded.append("&B"); } - + if (run.second.get().has_size()) { encoded.push_back('&'); @@ -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) { @@ -2391,17 +2415,17 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().element(xmlns, "firstFooter", first_footer); } - serializer().end_element(xmlns, "headerFooter"); - } + serializer().end_element(xmlns, "headerFooter"); + } - if (!ws.row_breaks().empty()) - { - serializer().start_element(xmlns, "rowBreaks"); + 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); @@ -2410,17 +2434,17 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().end_element(xmlns, "brk"); } - serializer().end_element(xmlns, "rowBreaks"); - } + serializer().end_element(xmlns, "rowBreaks"); + } - if (!ws.column_breaks().empty()) - { - serializer().start_element(xmlns, "colBreaks"); + 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); @@ -2429,219 +2453,250 @@ void xlsx_producer::write_worksheet(const relationship &rel) serializer().end_element(xmlns, "brk"); } - serializer().end_element(xmlns, "colBreaks"); - } + serializer().end_element(xmlns, "colBreaks"); + } - if (!worksheet_rels.empty()) - { - for (const auto &child_rel : worksheet_rels) - { - if (child_rel.type() == xlnt::relationship_type::vml_drawing) - { - serializer().start_element(xmlns, "legacyDrawing"); - serializer().attribute(xml::qname(xmlns_r, "id"), child_rel.id()); - serializer().end_element(xmlns, "legacyDrawing"); + if (!worksheet_rels.empty()) + { + for (const auto &child_rel : worksheet_rels) + { + if (child_rel.type() == xlnt::relationship_type::vml_drawing) + { + serializer().start_element(xmlns, "legacyDrawing"); + serializer().attribute(xml::qname(xmlns_r, "id"), child_rel.id()); + serializer().end_element(xmlns, "legacyDrawing"); + + // todo: there's only one of these per sheet, right? + break; + } + } + } - //todo: there's only one of these per sheet, right? - break; - } - } - } - serializer().end_element(xmlns, "worksheet"); - if (!worksheet_rels.empty()) - { - write_relationships(worksheet_rels, worksheet_part); + if (!worksheet_rels.empty()) + { + write_relationships(worksheet_rels, worksheet_part); - for (const auto &child_rel : worksheet_rels) - { + for (const auto &child_rel : worksheet_rels) + { if (child_rel.target_mode() == target_mode::external) continue; // todo: this is ugly - path archive_path(worksheet_part.parent().append(child_rel.target().path())); - auto split_part_path = archive_path.split(); - auto part_path_iter = split_part_path.begin(); - while (part_path_iter != split_part_path.end()) - { - if (*part_path_iter == "..") - { - part_path_iter = split_part_path.erase(part_path_iter - 1, part_path_iter + 1); - continue; - } + path archive_path(worksheet_part.parent().append(child_rel.target().path())); + auto split_part_path = archive_path.split(); + auto part_path_iter = split_part_path.begin(); + while (part_path_iter != split_part_path.end()) + { + if (*part_path_iter == "..") + { + part_path_iter = split_part_path.erase(part_path_iter - 1, part_path_iter + 1); + continue; + } - ++part_path_iter; - } - archive_path = std::accumulate(split_part_path.begin(), split_part_path.end(), path(""), - [](const path &a, const std::string &b) { return a.append(b); }); + ++part_path_iter; + } + archive_path = std::accumulate(split_part_path.begin(), split_part_path.end(), path(""), + [](const path &a, const std::string &b) { return a.append(b); }); begin_part(archive_path); - switch (child_rel.type()) - { - case relationship_type::comments: - write_comments(child_rel, ws, cells_with_comments); - break; + switch (child_rel.type()) + { + case relationship_type::comments: + write_comments(child_rel, ws, cells_with_comments); + break; - case relationship_type::vml_drawing: - write_vml_drawings(child_rel, ws, cells_with_comments); - break; + case relationship_type::vml_drawing: + 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; + } + } + } } // Sheet Relationship Target Parts -void xlsx_producer::write_comments(const relationship &/*rel*/, worksheet ws, - const std::vector &cells) +void xlsx_producer::write_comments(const relationship & /*rel*/, worksheet ws, const std::vector &cells) { - static const auto &xmlns = constants::namespace_("spreadsheetml"); + static const auto &xmlns = constants::namespace_("spreadsheetml"); - serializer().start_element(xmlns, "comments"); - serializer().namespace_decl(xmlns, ""); + serializer().start_element(xmlns, "comments"); + serializer().namespace_decl(xmlns, ""); - if (!cells.empty()) - { - std::unordered_map authors; + if (!cells.empty()) + { + std::unordered_map authors; - for (auto cell_ref : cells) - { - auto cell = ws.cell(cell_ref); - auto author = cell.comment().author(); + for (auto cell_ref : cells) + { + auto cell = ws.cell(cell_ref); + auto author = cell.comment().author(); - if (authors.find(author) == authors.end()) - { - authors[author] = authors.size(); - } - } + if (authors.find(author) == authors.end()) + { + authors[author] = authors.size(); + } + } - serializer().start_element(xmlns, "authors"); + serializer().start_element(xmlns, "authors"); - for (const auto &author : authors) - { - serializer().start_element(xmlns, "author"); - serializer().characters(author.first); - serializer().end_element(xmlns, "author"); - } + for (const auto &author : authors) + { + serializer().start_element(xmlns, "author"); + serializer().characters(author.first); + serializer().end_element(xmlns, "author"); + } - serializer().end_element(xmlns, "authors"); - serializer().start_element(xmlns, "commentList"); + serializer().end_element(xmlns, "authors"); + serializer().start_element(xmlns, "commentList"); - for (const auto &cell_ref : cells) - { - serializer().start_element(xmlns, "comment"); + for (const auto &cell_ref : cells) + { + serializer().start_element(xmlns, "comment"); - auto cell = ws.cell(cell_ref); - auto cell_comment = cell.comment(); + auto cell = ws.cell(cell_ref); + auto cell_comment = cell.comment(); - serializer().attribute("ref", cell_ref.to_string()); - auto author_id = authors.at(cell_comment.author()); - serializer().attribute("authorId", author_id); - serializer().start_element(xmlns, "text"); + serializer().attribute("ref", cell_ref.to_string()); + auto author_id = authors.at(cell_comment.author()); + serializer().attribute("authorId", author_id); + serializer().start_element(xmlns, "text"); - for (const auto &run : cell_comment.text().runs()) - { - serializer().start_element(xmlns, "r"); + for (const auto &run : cell_comment.text().runs()) + { + serializer().start_element(xmlns, "r"); - if (run.second.is_set()) - { - serializer().start_element(xmlns, "rPr"); + if (run.second.is_set()) + { + serializer().start_element(xmlns, "rPr"); - if (run.second.get().has_size()) - { - serializer().start_element(xmlns, "sz"); - serializer().attribute("val", run.second.get().size()); - serializer().end_element(xmlns, "sz"); - } + if (run.second.get().has_size()) + { + serializer().start_element(xmlns, "sz"); + serializer().attribute("val", run.second.get().size()); + serializer().end_element(xmlns, "sz"); + } - if (run.second.get().has_color()) - { - serializer().start_element(xmlns, "color"); - write_color(run.second.get().color()); - serializer().end_element(xmlns, "color"); - } + if (run.second.get().has_color()) + { + serializer().start_element(xmlns, "color"); + write_color(run.second.get().color()); + serializer().end_element(xmlns, "color"); + } - if (run.second.get().has_name()) - { - serializer().start_element(xmlns, "rFont"); - serializer().attribute("val", run.second.get().name()); - serializer().end_element(xmlns, "rFont"); - } + if (run.second.get().has_name()) + { + serializer().start_element(xmlns, "rFont"); + serializer().attribute("val", run.second.get().name()); + serializer().end_element(xmlns, "rFont"); + } - if (run.second.get().has_family()) - { - serializer().start_element(xmlns, "family"); - serializer().attribute("val", run.second.get().family()); - serializer().end_element(xmlns, "family"); - } + if (run.second.get().has_family()) + { + serializer().start_element(xmlns, "family"); + serializer().attribute("val", run.second.get().family()); + serializer().end_element(xmlns, "family"); + } - if (run.second.get().has_scheme()) - { - serializer().start_element(xmlns, "scheme"); - serializer().attribute("val", run.second.get().scheme()); - serializer().end_element(xmlns, "scheme"); - } + if (run.second.get().has_scheme()) + { + serializer().start_element(xmlns, "scheme"); + serializer().attribute("val", run.second.get().scheme()); + serializer().end_element(xmlns, "scheme"); + } - if (run.second.get().bold()) - { - serializer().start_element(xmlns, "b"); - serializer().end_element(xmlns, "b"); - } + if (run.second.get().bold()) + { + serializer().start_element(xmlns, "b"); + serializer().end_element(xmlns, "b"); + } - serializer().end_element(xmlns, "rPr"); - } + serializer().end_element(xmlns, "rPr"); + } - serializer().element(xmlns, "t", run.first); - serializer().end_element(xmlns, "r"); - } + serializer().element(xmlns, "t", run.first); + serializer().end_element(xmlns, "r"); + } - serializer().end_element(xmlns, "text"); - serializer().end_element(xmlns, "comment"); - } + serializer().end_element(xmlns, "text"); + serializer().end_element(xmlns, "comment"); + } - serializer().end_element(xmlns, "commentList"); - } + serializer().end_element(xmlns, "commentList"); + } - serializer().end_element(xmlns, "comments"); + serializer().end_element(xmlns, "comments"); } -void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws, - const std::vector &cells) +void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws, const std::vector &cells) { static const auto &xmlns_mv = std::string("http://macVmlSchemaUri"); static const auto &xmlns_o = std::string("urn:schemas-microsoft-com:office:office"); @@ -2653,7 +2708,7 @@ void xlsx_producer::write_vml_drawings(const relationship &rel, worksheet ws, serializer().namespace_decl(xmlns_o, "o"); serializer().namespace_decl(xmlns_x, "x"); serializer().namespace_decl(xmlns_mv, "mv"); - + serializer().start_element(xmlns_o, "shapelayout"); serializer().attribute(xml::qname(xmlns_v, "ext"), "edit"); serializer().start_element(xmlns_o, "idmap"); @@ -2794,9 +2849,10 @@ void xlsx_producer::write_unknown_relationships() 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() @@ -2806,10 +2862,9 @@ xml::serializer &xlsx_producer::serializer() std::string xlsx_producer::write_bool(bool boolean) const { - return boolean ? "true" : "false"; + return boolean ? "true" : "false"; } - void xlsx_producer::write_relationships(const std::vector &relationships, const path &part) { path parent = part.parent(); @@ -2819,7 +2874,7 @@ void xlsx_producer::write_relationships(const std::vector &r parent = path(parent.string().substr(1)); } - path rels_path(parent.append("_rels").append(part.filename() + ".rels").string()); + path rels_path(parent.append("_rels").append(part.filename() + ".rels").string()); begin_part(rels_path); const auto xmlns = xlnt::constants::namespace_("relationships"); @@ -2827,26 +2882,25 @@ void xlsx_producer::write_relationships(const std::vector &r serializer().start_element(xmlns, "Relationships"); serializer().namespace_decl(xmlns, ""); - for (const auto &relationship : relationships) - { + for (const auto &relationship : relationships) + { serializer().start_element(xmlns, "Relationship"); serializer().attribute("Id", relationship.id()); serializer().attribute("Type", relationship.type()); serializer().attribute("Target", relationship.target().path().string()); - if (relationship.target_mode() == xlnt::target_mode::external) - { + if (relationship.target_mode() == xlnt::target_mode::external) + { serializer().attribute("TargetMode", "External"); - } + } serializer().end_element(xmlns, "Relationship"); - } - + } + serializer().end_element(xmlns, "Relationships"); } - void xlsx_producer::write_color(const xlnt::color &color) { if (color.is_auto()) @@ -2855,20 +2909,20 @@ void xlsx_producer::write_color(const xlnt::color &color) return; } - switch (color.type()) - { - case xlnt::color_type::theme: + switch (color.type()) + { + case xlnt::color_type::theme: serializer().attribute("theme", color.theme().index()); - break; + break; - case xlnt::color_type::indexed: + case xlnt::color_type::indexed: serializer().attribute("indexed", color.indexed().index()); - break; + break; - case xlnt::color_type::rgb: + case xlnt::color_type::rgb: serializer().attribute("rgb", color.rgb().hex_string()); - break; - } + break; + } } } // namespace detail diff --git a/source/detail/xlsx_producer.hpp b/source/detail/xlsx_producer.hpp index f6848b58..4a2ed70a 100644 --- a/source/detail/xlsx_producer.hpp +++ b/source/detail/xlsx_producer.hpp @@ -44,7 +44,7 @@ class worksheet; namespace detail { -class ZipFileWriter; +class zip_file_writer; /// /// Handles writing a workbook into an XLSX file. @@ -137,8 +137,10 @@ private: /// const workbook &source_; - ZipFileWriter *archive_; + zip_file_writer *archive_; std::unique_ptr current_part_serializer_; + std::unique_ptr current_part_streambuf_; + std::ostream current_part_stream_; }; } // namespace detail diff --git a/source/detail/zip.cpp b/source/detail/zip.cpp index 38151934..316e5a4c 100644 --- a/source/detail/zip.cpp +++ b/source/detail/zip.cpp @@ -48,32 +48,30 @@ extern "C" { #include } -#include #include +#include -namespace xlnt { -namespace detail { +namespace { template -inline T read_int(std::istream &stream) +T read_int(std::istream &stream) { T value; stream.read(reinterpret_cast(&value), sizeof(T)); + return value; } template -inline void write_int(std::ostream &stream, T value) +void write_int(std::ostream &stream, T value) { stream.write(reinterpret_cast(&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(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(istream); + header.version = read_int(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(istream); - flags = read_int(istream); - compression_type = read_int(istream); - stamp_date = read_int(istream); - stamp_time = read_int(istream); - crc = read_int(istream); - compressed_size = read_int(istream); - uncompressed_size = read_int(istream); + header.version = read_int(istream); + header.flags = read_int(istream); + header.compression_type = read_int(istream); + header.stamp_date = read_int(istream); + header.stamp_time = read_int(istream); + header.crc = read_int(istream); + header.compressed_size = read_int(istream); + header.uncompressed_size = read_int(istream); auto filename_length = read_int(istream); auto extra_length = read_int(istream); @@ -114,25 +110,25 @@ bool zip_file_header::read(std::istream &istream, const bool global) /*std::uint16_t disk_number_start = */ read_int(istream); /*std::uint16_t int_file_attrib = */ read_int(istream); /*std::uint32_t ext_file_attrib = */ read_int(istream); - header_offset = read_int(istream); + header.header_offset = read_int(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(extra.data()), extra_length); + header.extra.resize(extra_length, 0); + istream.read(reinterpret_cast(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(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(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(header.filename.length())); write_int(ostream, static_cast(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(0)); // disk# start write_int(ostream, static_cast(0)); // internal file write_int(ostream, static_cast(0)); // ext final - write_int(ostream, static_cast(header_offset)); // rel offset + write_int(ostream, static_cast(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::min(buffer_size, header.compressed_size - total_read))); + istream.read(in.data(), + static_cast(std::min(buffer_size, header.compressed_size - total_read))); strm.avail_in = static_cast(istream.gcount()); total_read += strm.avail_in; strm.next_in = reinterpret_cast(in.data()); @@ -289,7 +292,8 @@ public: } // uncompressed, so just read - istream.read(out.data() + 4, static_cast(std::min(buffer_size - 4, header.uncompressed_size - total_read))); + istream.read(out.data() + 4, + static_cast(std::min(buffer_size - 4, header.uncompressed_size - total_read))); auto count = istream.gcount(); total_read += static_cast(count); return static_cast(count); @@ -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(put_back_count)); + std::memmove( + out.data() + (4 - put_back_count), gptr() - put_back_count, static_cast(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; @@ -341,7 +346,7 @@ public: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" int ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); -#pragma clang diagnostic pop +#pragma clang diagnostic pop if (ret != Z_OK) { @@ -357,13 +362,13 @@ public: if (header) { header->header_offset = static_cast(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 &&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 &&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(0x06054b50)); // end of central - write_int(tarstream_, static_cast(0)); // this disk number - write_int(tarstream_, static_cast(0)); // this disk number - write_int(tarstream_, static_cast(file_headers_.size())); // one entry in center in this disk - write_int(tarstream_, static_cast(file_headers_.size())); // one entry in center - write_int(tarstream_, static_cast(central_end - final_position)); // size of header - write_int(tarstream_, static_cast(final_position)); // offset to header - write_int(tarstream_, static_cast(0)); // zip comment + write_int(destination_stream_, static_cast(0x06054b50)); // end of central + write_int(destination_stream_, static_cast(0)); // this disk number + write_int(destination_stream_, static_cast(0)); // this disk number + write_int(destination_stream_, static_cast(file_headers_.size())); // one entry in center in this disk + write_int(destination_stream_, static_cast(file_headers_.size())); // one entry in center + write_int(destination_stream_, static_cast(central_end - final_position)); // size of header + write_int(destination_stream_, static_cast(final_position)); // offset to header + write_int(destination_stream_, static_cast(0)); // zip comment } -std::ostream &ZipFileWriter::open(const std::string &filename) +std::unique_ptr 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(&file_headers_.back(), tarstream_); - auto stream = new zip_file_ostream(std::move(streambuf)); - write_stream_.reset(stream); - return *write_stream_; + return std::make_unique(&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)) - { - file_headers_[header.filename] = header; - } + 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 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(source_stream_, header); - read_stream_.reset(new zip_file_istream(std::move(streambuf))); - - return *read_stream_; + return std::make_unique(source_stream_, header); } -std::vector ZipFileReader::files() const +std::vector zip_file_reader::files() const { - std::vector filenames; + std::vector filenames; std::transform(file_headers_.begin(), file_headers_.end(), std::back_inserter(filenames), - [](const std::pair &h) { return h.first; }); + [](const std::pair &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 diff --git a/source/detail/zip.hpp b/source/detail/zip.hpp index 5653abcd..e3242a12 100644 --- a/source/detail/zip.hpp +++ b/source/detail/zip.hpp @@ -40,9 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. #include #include +#include + namespace xlnt { namespace detail { +/// +/// 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. +/// struct zip_file_header { std::uint16_t version = 20; @@ -56,61 +62,82 @@ struct zip_file_header std::string comment; std::vector 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 +/// +/// Writes a series of uncompressed binary file data as ostreams into another ostream +/// according to the ZIP format. +/// +class zip_file_writer { public: - zip_file_istream(std::unique_ptr &&buf); - virtual ~zip_file_istream(); - -private: - std::unique_ptr buf; -}; + /// + /// Construct a new zip_file_writer which writes a ZIP archive to the given stream. + /// + zip_file_writer(std::ostream &stream); -class zip_file_ostream : public std::ostream -{ -public: - zip_file_ostream(std::unique_ptr &&buf); - virtual ~zip_file_ostream(); + /// + /// Destructor. + /// + virtual ~zip_file_writer(); -private: - std::unique_ptr buf; -}; + /// + /// Returns a pointer to a streambuf which compresses the data it receives. + /// + std::unique_ptr open(const path &file); -class ZipFileWriter -{ -public: - ZipFileWriter(std::ostream &filename); - virtual ~ZipFileWriter(); - std::ostream &open(const std::string &filename); - void close(); private: std::vector file_headers_; - std::ostream &tarstream_; - std::unique_ptr write_stream_; + std::ostream &destination_stream_; }; -class ZipFileReader +/// +/// Reads an archive containing a number of files from an istream and allows them +/// to be decompressed into an istream. +/// +class zip_file_reader { public: - ZipFileReader(std::istream &stream); - virtual ~ZipFileReader(); - std::istream &open(const std::string &filename); - std::vector files() const; - bool has_file(const std::string &filename) const; + /// + /// Construct a new zip_file_reader which reads a ZIP archive from the given stream. + /// + zip_file_reader(std::istream &stream); + + /// + /// Destructor. + /// + virtual ~zip_file_reader(); + + /// + /// + /// + std::unique_ptr open(const path &file); + + /// + /// + /// + std::vector files() const; + + /// + /// + /// + bool has_file(const path &filename) const; private: + /// + /// + /// bool read_central_header(); + /// + /// + /// std::unordered_map file_headers_; + + /// + /// + /// std::istream &source_stream_; - std::unique_ptr read_stream_; }; } // namespace detail diff --git a/source/packaging/manifest.cpp b/source/packaging/manifest.cpp index 5dd27ab0..b02b9b47 100644 --- a/source/packaging/manifest.cpp +++ b/source/packaging/manifest.cpp @@ -64,17 +64,17 @@ path manifest::canonicalize(const std::vector &rels) const absolute_parts.pop_back(); continue; } - + absolute_parts.push_back(component); } - + xlnt::path result; - + for (const auto &component : absolute_parts) { result = result.append(component); } - + return result; } @@ -86,7 +86,7 @@ bool manifest::has_relationship(const path &part, relationship_type type) const { if (rel.second.type() == type) return true; } - + return false; } @@ -98,13 +98,13 @@ relationship manifest::relationship(const path &part, relationship_type type) co { if (rel.second.type() == type) return rel.second; } - - throw key_not_found(); + + throw key_not_found(); } std::vector manifest::relationships(const path &part, relationship_type type) const { - std::vector matches; + std::vector matches; if (has_relationship(part, type)) { @@ -117,23 +117,23 @@ std::vector manifest::relationships(const path &part, relati } } - return matches; + return matches; } std::string manifest::content_type(const path &part) const { - auto absolute = part.resolve(path("/")); + auto absolute = part.resolve(path("/")); if (has_override_type(absolute)) { return override_type(absolute); } - + if (has_default_type(part.extension())) { return default_type(part.extension()); } - + throw key_not_found(); } @@ -144,27 +144,27 @@ void manifest::register_override_type(const path &part, const std::string &conte void manifest::unregister_override_type(const path &part) { - override_content_types_.erase(part); + override_content_types_.erase(part); } std::vector manifest::parts_with_overriden_types() const { - std::vector overriden; + std::vector overriden; - for (const auto &part : override_content_types_) - { + for (const auto &part : override_content_types_) + { overriden.push_back(part.first); - } + } - return overriden; + return overriden; } std::vector manifest::relationships(const path &part) const { - if (relationships_.find(part) == relationships_.end()) - { - return {}; - } + if (relationships_.find(part) == relationships_.end()) + { + return {}; + } std::vector relationships; @@ -172,36 +172,36 @@ std::vector manifest::relationships(const path &part) const { relationships.push_back(rel.second); } - - return relationships; + + return relationships; } relationship manifest::relationship(const path &part, const std::string &rel_id) const { - if (relationships_.find(part) == relationships_.end()) - { - throw key_not_found(); - } + if (relationships_.find(part) == relationships_.end()) + { + throw key_not_found(); + } - for (const auto &rel : relationships_.at(part)) - { - if (rel.second.id() == rel_id) - { - return rel.second; - } - } + for (const auto &rel : relationships_.at(part)) + { + if (rel.second.id() == rel_id) + { + return rel.second; + } + } - throw key_not_found(); + throw key_not_found(); } std::vector manifest::parts() const { - std::unordered_set parts; + std::unordered_set parts; - for (const auto &part_rels : relationships_) - { + for (const auto &part_rels : relationships_) + { parts.insert(part_rels.first); - + for (const auto &rel : part_rels.second) { if (rel.second.target_mode() == target_mode::internal) @@ -209,78 +209,79 @@ std::vector manifest::parts() const parts.insert(rel.second.target().path()); } } - } + } - return std::vector(parts.begin(), parts.end()); + return std::vector(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); + return register_relationship(rel); } std::string manifest::register_relationship(const class relationship &rel) { relationships_[rel.source().path()][rel.id()] = rel; - return rel.id(); + return rel.id(); } void manifest::unregister_relationship(const uri &source, const std::string &rel_id) { - relationships_.at(source.path()).erase(rel_id); + relationships_.at(source.path()).erase(rel_id); } bool manifest::has_default_type(const std::string &extension) const { - return default_content_types_.find(extension) != default_content_types_.end(); + return default_content_types_.find(extension) != default_content_types_.end(); } std::vector manifest::extensions_with_default_types() const { - std::vector extensions; + std::vector extensions; - for (const auto &extension_type_pair : default_content_types_) - { - extensions.push_back(extension_type_pair.first); - } + for (const auto &extension_type_pair : default_content_types_) + { + extensions.push_back(extension_type_pair.first); + } - return extensions; + return extensions; } std::string manifest::default_type(const std::string &extension) const { - if (default_content_types_.find(extension) == default_content_types_.end()) - { - throw key_not_found(); - } + if (default_content_types_.find(extension) == default_content_types_.end()) + { + throw key_not_found(); + } - return default_content_types_.at(extension); + return default_content_types_.at(extension); } void manifest::register_default_type(const std::string &extension, const std::string &content_type) { - default_content_types_[extension] = content_type; + default_content_types_[extension] = content_type; } void manifest::unregister_default_type(const std::string &extension) { - default_content_types_.erase(extension); + default_content_types_.erase(extension); } std::string manifest::next_relationship_id(const path &part) const { if (relationships_.find(part) == relationships_.end()) return "rId1"; - std::size_t index = 1; - const auto &part_rels = relationships_.at(part); + std::size_t index = 1; + const auto &part_rels = relationships_.at(part); - while (part_rels.find("rId" + std::to_string(index)) != part_rels.end()) - { - ++index; - } + while (part_rels.find("rId" + std::to_string(index)) != part_rels.end()) + { + ++index; + } - return "rId" + std::to_string(index); + return "rId" + std::to_string(index); } bool manifest::has_override_type(const xlnt::path &part) const @@ -294,7 +295,7 @@ std::string manifest::override_type(const xlnt::path &part) const { throw key_not_found(); } - + return override_content_types_.at(part); } diff --git a/source/packaging/relationship.cpp b/source/packaging/relationship.cpp index e4493a38..b9ebab86 100644 --- a/source/packaging/relationship.cpp +++ b/source/packaging/relationship.cpp @@ -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,11 +63,8 @@ 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_ - && mode_ == rhs.mode_; + return type_ == rhs.type_ && id_ == rhs.id_ && source_ == rhs.source_ && target_ == rhs.target_ + && mode_ == rhs.mode_; } } // namespace xlnt diff --git a/source/packaging/uri.cpp b/source/packaging/uri.cpp index 4aaef70c..66d8b367 100644 --- a/source/packaging/uri.cpp +++ b/source/packaging/uri.cpp @@ -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) { } diff --git a/source/styles/alignment.cpp b/source/styles/alignment.cpp index d85aa8ce..a3e26cc4 100644 --- a/source/styles/alignment.cpp +++ b/source/styles/alignment.cpp @@ -33,19 +33,19 @@ optional alignment::wrap() const alignment &alignment::wrap(bool wrap_text) { - wrap_text_ = wrap_text; - return *this; + wrap_text_ = wrap_text; + return *this; } optional alignment::shrink() const { - return shrink_to_fit_; + return shrink_to_fit_; } alignment &alignment::shrink(bool shrink_to_fit) { shrink_to_fit_ = shrink_to_fit; - return *this; + return *this; } optional alignment::horizontal() const @@ -56,7 +56,7 @@ optional alignment::horizontal() const alignment &alignment::horizontal(horizontal_alignment horizontal) { horizontal_ = horizontal; - return *this; + return *this; } optional alignment::vertical() const @@ -67,29 +67,29 @@ optional alignment::vertical() const alignment &alignment::vertical(vertical_alignment vertical) { vertical_ = vertical; - return *this; + return *this; } alignment &alignment::indent(int value) { - indent_ = value; - return *this; + indent_ = value; + return *this; } optional alignment::indent() const { - return indent_; + return indent_; } alignment &alignment::rotation(int value) { - text_rotation_ = value; - return *this; + text_rotation_ = value; + return *this; } optional alignment::rotation() const { - return text_rotation_; + return text_rotation_; } XLNT_API bool operator==(const alignment &left, const alignment &right) @@ -98,7 +98,7 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) { return false; } - + if (left.horizontal().is_set()) { if (left.horizontal().get() != right.horizontal().get()) @@ -111,7 +111,7 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) { return false; } - + if (left.indent().is_set()) { if (left.indent().get() != right.indent().get()) @@ -124,7 +124,7 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) { return false; } - + if (left.rotation().is_set()) { if (left.rotation().get() != right.rotation().get()) @@ -132,12 +132,12 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) return false; } } - + if (left.shrink().is_set() != right.shrink().is_set()) { return false; } - + if (left.shrink().is_set()) { if (left.shrink().get() != right.shrink().get()) @@ -145,12 +145,12 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) return false; } } - + if (left.vertical().is_set() != right.vertical().is_set()) { return false; } - + if (left.vertical().is_set()) { if (left.vertical().get() != right.vertical().get()) @@ -158,12 +158,12 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) return false; } } - + if (left.wrap().is_set() != right.wrap().is_set()) { return false; } - + if (left.wrap().is_set()) { if (left.wrap().get() != right.wrap().get()) @@ -171,7 +171,7 @@ XLNT_API bool operator==(const alignment &left, const alignment &right) return false; } } - + return true; } diff --git a/source/styles/border.cpp b/source/styles/border.cpp index 64852ba5..7c66be30 100644 --- a/source/styles/border.cpp +++ b/source/styles/border.cpp @@ -22,42 +22,41 @@ // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include -#include #include +#include +#include namespace xlnt { optional border::border_property::color() const { - return color_; + return color_; } border::border_property &border::border_property::color(const xlnt::color &c) { - color_ = c; - return *this; + color_ = c; + return *this; } optional border::border_property::style() const { - return style_; + return style_; } border::border_property &border::border_property::style(border_style s) { - style_ = s; - return *this; + 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()) { return false; } - + if (left.style().is_set()) { if (left.style().get() != right.style().get()) @@ -65,12 +64,12 @@ bool operator==(const border::border_property &left, return false; } } - + if (left.color().is_set() != right.color().is_set()) { return false; } - + if (left.color().is_set()) { if (left.color().get() != right.color().get()) @@ -78,7 +77,7 @@ bool operator==(const border::border_property &left, return false; } } - + return true; } @@ -88,61 +87,75 @@ border::border() const std::vector &border::all_sides() { - static auto *sides = new std::vector - { - 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::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; + return *sides; } optional 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_; - } + 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_; + } default_case(start_); } 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; - } + 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; + } - return *this; + return *this; } border &border::diagonal(diagonal_direction direction) { - diagonal_direction_ = direction; - return *this; + diagonal_direction_ = direction; + return *this; } optional border::diagonal() const { - return diagonal_direction_; + return diagonal_direction_; } XLNT_API bool operator==(const border &left, const border &right) @@ -153,7 +166,7 @@ XLNT_API bool operator==(const border &left, const border &right) { return false; } - + if (left.side(side).is_set()) { if (left.side(side).get() != right.side(side).get()) @@ -162,7 +175,7 @@ XLNT_API bool operator==(const border &left, const border &right) } } } - + return true; } diff --git a/source/styles/color.cpp b/source/styles/color.cpp index dd21455d..9b3567ee 100644 --- a/source/styles/color.cpp +++ b/source/styles/color.cpp @@ -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) { } @@ -135,7 +117,7 @@ color_type color::type() const bool color::is_auto() const { - return auto__; + return auto__; } void color::auto_(bool value) @@ -145,102 +127,100 @@ void color::auto_(bool value) const indexed_color &color::indexed() const { - assert_type(color_type::indexed); - return indexed_; + assert_type(color_type::indexed); + return indexed_; } const theme_color &color::theme() const { - assert_type(color_type::theme); - return theme_; + assert_type(color_type::theme); + return theme_; } std::string rgb_color::hex_string() const { - static const char* digits = "0123456789abcdef"; - std::string hex_string(8, '0'); - auto out_iter = hex_string.begin(); + static const char *digits = "0123456789abcdef"; + std::string hex_string(8, '0'); + auto out_iter = hex_string.begin(); - for (auto byte : { rgba_[3], rgba_[0], rgba_[1], rgba_[2] }) - { - for (auto i = 0; i < 2; ++i) - { - auto nibble = byte >> (4 * (1 - i)) & 0xf; - *(out_iter++) = digits[nibble]; - } - } + for (auto byte : {rgba_[3], rgba_[0], rgba_[1], rgba_[2]}) + { + for (auto i = 0; i < 2; ++i) + { + auto nibble = byte >> (4 * (1 - i)) & 0xf; + *(out_iter++) = digits[nibble]; + } + } - return hex_string; + return hex_string; } std::array rgb_color::decode_hex_string(const std::string &hex_string) { - auto x = std::strtoul(hex_string.c_str(), NULL, 16); + auto x = std::strtoul(hex_string.c_str(), NULL, 16); - auto a = static_cast(x >> 24); - auto r = static_cast((x >> 16) & 0xff); - auto g = static_cast((x >> 8) & 0xff); - auto b = static_cast(x & 0xff); + auto a = static_cast(x >> 24); + auto r = static_cast((x >> 16) & 0xff); + auto g = static_cast((x >> 8) & 0xff); + auto b = static_cast(x & 0xff); - return { {r, g, b, a} }; + return {{r, g, b, a}}; } rgb_color::rgb_color(const std::string &hex_string) - : rgba_(decode_hex_string(hex_string)) + : rgba_(decode_hex_string(hex_string)) { } rgb_color::rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a) - : rgba_({{r, g, b, a}}) + : rgba_({{r, g, b, a}}) { } std::size_t indexed_color::index() const { - return index_; + return index_; } std::size_t theme_color::index() const { - return index_; + return index_; } const rgb_color &color::rgb() const { - assert_type(color_type::rgb); - return rgb_; + assert_type(color_type::rgb); + return rgb_; } void color::tint(double tint) { - tint_ = tint; + tint_ = tint; } void color::assert_type(color_type t) const { - if (t != type_) - { - throw invalid_attribute(); - } + if (t != type_) + { + throw invalid_attribute(); + } } 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; } - switch(type_) + switch (type_) { - case color_type::indexed: - return indexed_.index() == other.indexed_.index(); - case color_type::theme: - return theme_.index() == other.theme_.index(); - case color_type::rgb: - return rgb_.hex_string() == other.rgb_.hex_string(); + case color_type::indexed: + return indexed_.index() == other.indexed_.index(); + case color_type::theme: + return theme_.index() == other.theme_.index(); + case color_type::rgb: + return rgb_.hex_string() == other.rgb_.hex_string(); } return false; diff --git a/source/styles/fill.cpp b/source/styles/fill.cpp index bdc98fe3..118ef59e 100644 --- a/source/styles/fill.cpp +++ b/source/styles/fill.cpp @@ -32,46 +32,45 @@ namespace xlnt { pattern_fill::pattern_fill() { - } pattern_fill_type pattern_fill::type() const { - return type_; + return type_; } pattern_fill &pattern_fill::type(pattern_fill_type type) { - type_ = type; - return *this; + type_ = type; + return *this; } optional pattern_fill::foreground() const { - return foreground_; + return foreground_; } pattern_fill &pattern_fill::foreground(const color &new_foreground) { - foreground_ = new_foreground; + foreground_ = new_foreground; - if (!background_) - { - background_.set(indexed_color(64)); - } + if (!background_) + { + background_.set(indexed_color(64)); + } - return *this; + return *this; } optional pattern_fill::background() const { - return background_; + return background_; } pattern_fill &pattern_fill::background(const color &new_background) { - background_ = new_background; - return *this; + background_ = new_background; + return *this; } XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right) @@ -80,7 +79,7 @@ XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right) { return false; } - + if (left.background().is_set()) { if (left.background().get() != right.background().get()) @@ -93,7 +92,7 @@ XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right) { return false; } - + if (left.foreground().is_set()) { if (left.foreground().get() != right.foreground().get()) @@ -101,103 +100,103 @@ XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right) return false; } } - + if (left.type() != right.type()) { return false; } - + return true; } // gradient_fill -gradient_fill::gradient_fill() : type_(gradient_fill_type::linear) +gradient_fill::gradient_fill() + : type_(gradient_fill_type::linear) { } gradient_fill_type gradient_fill::type() const { - return type_; + return type_; } gradient_fill &gradient_fill::type(gradient_fill_type t) { - type_ = t; - return *this; + type_ = t; + return *this; } gradient_fill &gradient_fill::degree(double degree) { - degree_ = degree; - return *this; + degree_ = degree; + return *this; } double gradient_fill::degree() const { - return degree_; + return degree_; } - double gradient_fill::left() const { - return left_; + return left_; } gradient_fill &gradient_fill::left(double value) { - left_ = value; - return *this; + left_ = value; + return *this; } double gradient_fill::right() const { - return right_; + return right_; } gradient_fill &gradient_fill::right(double value) { - right_ = value; - return *this; + right_ = value; + return *this; } double gradient_fill::top() const { - return top_; + return top_; } gradient_fill &gradient_fill::top(double value) { - top_ = value; - return *this; + top_ = value; + return *this; } double gradient_fill::bottom() const { - return bottom_; + return bottom_; } gradient_fill &gradient_fill::bottom(double value) { - bottom_ = value; - return *this; + bottom_ = value; + return *this; } gradient_fill &gradient_fill::add_stop(double position, color stop_color) { - stops_[position] = stop_color; - return *this; + stops_[position] = stop_color; + return *this; } gradient_fill &gradient_fill::clear_stops() { - stops_.clear(); - return *this; + stops_.clear(); + return *this; } std::unordered_map gradient_fill::stops() const { - return stops_; + return stops_; } XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right) @@ -206,37 +205,37 @@ XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right) { return false; } - + if (std::fabs(left.degree() - right.degree()) != 0.) { return false; } - + if (std::fabs(left.bottom() - right.bottom()) != 0.) { return false; } - + if (std::fabs(left.right() - right.right()) != 0.) { return false; } - + if (std::fabs(left.top() - right.top()) != 0.) { return false; } - + if (std::fabs(left.left() - right.left()) != 0.) { return false; } - + if (left.stops() != right.stops()) { return false; } - + return true; } @@ -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) +fill::fill(const xlnt::pattern_fill &pattern) + : type_(fill_type::pattern), pattern_(pattern) { } -fill::fill(const xlnt::gradient_fill &gradient) - : type_(fill_type::gradient), - gradient_(gradient) +fill::fill(const xlnt::gradient_fill &gradient) + : type_(fill_type::gradient), gradient_(gradient) { } @@ -275,7 +271,7 @@ gradient_fill fill::gradient_fill() const { if (type_ != fill_type::gradient) { - throw invalid_attribute(); + throw invalid_attribute(); } return gradient_; @@ -285,7 +281,7 @@ pattern_fill fill::pattern_fill() const { if (type_ != fill_type::pattern) { - throw invalid_attribute(); + throw invalid_attribute(); } return pattern_; @@ -297,7 +293,7 @@ XLNT_API bool operator==(const fill &left, const fill &right) { return false; } - + if (left.type() == fill_type::gradient) { return left.gradient_fill() == right.gradient_fill(); diff --git a/source/styles/font.cpp b/source/styles/font.cpp index cb383380..9ff9b92b 100644 --- a/source/styles/font.cpp +++ b/source/styles/font.cpp @@ -28,7 +28,6 @@ namespace xlnt { - font::font() : name_("Calibri"), size_(12.0), @@ -44,7 +43,7 @@ font::font() font &font::bold(bool bold) { bold_ = bold; - return *this; + return *this; } bool font::bold() const @@ -54,19 +53,19 @@ bool font::bold() const font &font::superscript(bool superscript) { - superscript_ = superscript; - return *this; + superscript_ = superscript; + return *this; } bool font::superscript() const { - return superscript_; + return superscript_; } font &font::italic(bool italic) { italic_ = italic; - return *this; + return *this; } bool font::italic() const @@ -77,7 +76,7 @@ bool font::italic() const font &font::strikethrough(bool strikethrough) { strikethrough_ = strikethrough; - return *this; + return *this; } bool font::strikethrough() const @@ -88,7 +87,7 @@ bool font::strikethrough() const font &font::underline(underline_style new_underline) { underline_ = new_underline; - return *this; + return *this; } bool font::underlined() const @@ -109,7 +108,7 @@ bool font::has_size() const font &font::size(double size) { size_ = size; - return *this; + return *this; } double font::size() const @@ -125,7 +124,7 @@ bool font::has_name() const font &font::name(const std::string &name) { name_ = name; - return *this; + return *this; } std::string font::name() const @@ -141,7 +140,7 @@ bool font::has_color() const font &font::color(const xlnt::color &c) { color_ = c; - return *this; + return *this; } bool font::has_family() const @@ -152,7 +151,7 @@ bool font::has_family() const font &font::family(std::size_t family) { family_ = family; - return *this; + return *this; } bool font::has_scheme() const @@ -163,7 +162,7 @@ bool font::has_scheme() const font &font::scheme(const std::string &scheme) { scheme_ = scheme; - return *this; + return *this; } color font::color() const @@ -192,7 +191,7 @@ XLNT_API bool operator==(const font &left, const font &right) { return false; } - + if (left.has_color()) { if (left.color() != right.color()) @@ -205,7 +204,7 @@ XLNT_API bool operator==(const font &left, const font &right) { return false; } - + if (left.has_family()) { if (left.family() != right.family()) @@ -213,22 +212,22 @@ XLNT_API bool operator==(const font &left, const font &right) return false; } } - + if (left.italic() != right.italic()) { return false; } - + if (left.name() != right.name()) { return false; } - + if (left.has_scheme() != right.has_scheme()) { return false; } - + if (left.has_scheme()) { if (left.scheme() != right.scheme()) @@ -236,27 +235,27 @@ XLNT_API bool operator==(const font &left, const font &right) return false; } } - + if (std::fabs(left.size() - right.size()) != 0.0) { return false; } - + if (left.strikethrough() != right.strikethrough()) { return false; } - + if (left.superscript() != right.superscript()) { return false; } - + if (left.underline() != right.underline()) { return false; } - + return true; } diff --git a/source/styles/format.cpp b/source/styles/format.cpp index a3463e61..d7cfc28c 100644 --- a/source/styles/format.cpp +++ b/source/styles/format.cpp @@ -22,20 +22,21 @@ // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include -#include #include #include +#include +#include namespace xlnt { -format::format(detail::format_impl *d) : d_(d) +format::format(detail::format_impl *d) + : d_(d) { } std::size_t format::id() const { - return d_->id; + return d_->id; } void format::clear_style() @@ -45,39 +46,39 @@ void format::clear_style() format format::style(const xlnt::style &new_style) { - d_ = d_->parent->find_or_create_with(d_, new_style.name()); + d_ = d_->parent->find_or_create_with(d_, new_style.name()); return format(d_); } format format::style(const std::string &new_style) { - d_->style = new_style; + d_->style = new_style; return format(d_); } bool format::has_style() const { - return d_->style; + return d_->style; } const style format::style() const { - if (!has_style()) - { - throw invalid_attribute(); - } + if (!has_style()) + { + throw invalid_attribute(); + } - return d_->parent->style(d_->style.get()); + return d_->parent->style(d_->style.get()); } xlnt::alignment &format::alignment() { - return d_->parent->alignments.at(d_->alignment_id.get()); + return d_->parent->alignments.at(d_->alignment_id.get()); } const xlnt::alignment &format::alignment() const { - return d_->parent->alignments.at(d_->alignment_id.get()); + return d_->parent->alignments.at(d_->alignment_id.get()); } format format::alignment(const xlnt::alignment &new_alignment, bool applied) @@ -88,12 +89,12 @@ format format::alignment(const xlnt::alignment &new_alignment, bool applied) xlnt::border &format::border() { - return d_->parent->borders.at(d_->border_id.get()); + return d_->parent->borders.at(d_->border_id.get()); } const xlnt::border &format::border() const { - return d_->parent->borders.at(d_->border_id.get()); + return d_->parent->borders.at(d_->border_id.get()); } format format::border(const xlnt::border &new_border, bool applied) @@ -104,12 +105,12 @@ format format::border(const xlnt::border &new_border, bool applied) xlnt::fill &format::fill() { - return d_->parent->fills.at(d_->fill_id.get()); + return d_->parent->fills.at(d_->fill_id.get()); } const xlnt::fill &format::fill() const { - return d_->parent->fills.at(d_->fill_id.get()); + return d_->parent->fills.at(d_->fill_id.get()); } format format::fill(const xlnt::fill &new_fill, bool applied) @@ -120,12 +121,12 @@ format format::fill(const xlnt::fill &new_fill, bool applied) xlnt::font &format::font() { - return d_->parent->fonts.at(d_->font_id.get()); + return d_->parent->fonts.at(d_->font_id.get()); } const xlnt::font &format::font() const { - return d_->parent->fonts.at(d_->font_id.get()); + return d_->parent->fonts.at(d_->font_id.get()); } format format::font(const xlnt::font &new_font, bool applied) @@ -136,23 +137,23 @@ format format::font(const xlnt::font &new_font, bool applied) xlnt::number_format &format::number_format() { - return d_->parent->number_formats.at(d_->number_format_id.get()); + return d_->parent->number_formats.at(d_->number_format_id.get()); } const xlnt::number_format &format::number_format() const { - return d_->parent->number_formats.at(d_->number_format_id.get()); + return d_->parent->number_formats.at(d_->number_format_id.get()); } format format::number_format(const xlnt::number_format &new_number_format, bool applied) { - auto copy = new_number_format; + auto copy = new_number_format; - if (!copy.has_id()) - { - copy.id(d_->parent->next_custom_number_format_id()); - d_->parent->number_formats.push_back(copy); - } + if (!copy.has_id()) + { + copy.id(d_->parent->next_custom_number_format_id()); + d_->parent->number_formats.push_back(copy); + } d_ = d_->parent->find_or_create_with(d_, copy, applied); return format(d_); @@ -160,12 +161,12 @@ format format::number_format(const xlnt::number_format &new_number_format, bool xlnt::protection &format::protection() { - return d_->parent->protections.at(d_->protection_id.get()); + return d_->parent->protections.at(d_->protection_id.get()); } const xlnt::protection &format::protection() const { - return d_->parent->protections.at(d_->protection_id.get()); + return d_->parent->protections.at(d_->protection_id.get()); } format format::protection(const xlnt::protection &new_protection, bool applied) diff --git a/source/styles/number_format.cpp b/source/styles/number_format.cpp index 16bed945..be114430 100644 --- a/source/styles/number_format.cpp +++ b/source/styles/number_format.cpp @@ -27,54 +27,30 @@ #include #include -#include #include #include #include +#include namespace { const std::unordered_map &builtin_formats() { static const std::unordered_map *formats = - new std::unordered_map - ({ - { 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( + {{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\\);_(* \"-\"_);_(@_)" }, - { 42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)" }, - { 43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)" }, - { 44, "_(\"$\"* #,##0.00_)_(\"$\"* \\(#,##0.00\\)_(\"$\"* \"-\"??_)_(@_)" }, + // 41-44 aren't in the ECMA 376 v4 standard, but Libre Office uses them + {41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"}, + {42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"}, + {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); } @@ -261,7 +241,7 @@ number_format number_format::from_builtin_id(std::size_t builtin_id) { if (builtin_formats().find(builtin_id) == builtin_formats().end()) { - throw invalid_parameter(); //("unknown id: " + std::to_string(builtin_id)); + throw invalid_parameter(); //("unknown id: " + std::to_string(builtin_id)); } auto format_string = builtin_formats().at(builtin_id); @@ -310,11 +290,11 @@ void number_format::id(std::size_t id) std::size_t number_format::id() const { - if(!id_set_) + if (!id_set_) { - throw invalid_attribute(); + throw invalid_attribute(); } - + return id_; } diff --git a/source/styles/protection.cpp b/source/styles/protection.cpp index 5e411a2e..a2be4121 100644 --- a/source/styles/protection.cpp +++ b/source/styles/protection.cpp @@ -26,7 +26,8 @@ namespace xlnt { -protection::protection() : locked_(false), hidden_(false) +protection::protection() + : locked_(false), hidden_(false) { } @@ -38,7 +39,7 @@ bool protection::locked() const protection &protection::locked(bool locked) { locked_ = locked; - return *this; + return *this; } bool protection::hidden() const @@ -49,7 +50,7 @@ bool protection::hidden() const protection &protection::hidden(bool hidden) { hidden_ = hidden; - return *this; + return *this; } XLNT_API bool operator==(const protection &left, const protection &right) diff --git a/source/styles/style.cpp b/source/styles/style.cpp index 2946a119..a58d018f 100644 --- a/source/styles/style.cpp +++ b/source/styles/style.cpp @@ -22,7 +22,6 @@ // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include #include #include #include @@ -30,10 +29,12 @@ #include #include #include +#include namespace xlnt { -style::style(detail::style_impl *d) : d_(d) +style::style(detail::style_impl *d) + : d_(d) { } @@ -45,7 +46,7 @@ bool style::hidden() const style style::hidden(bool value) { d_->hidden_style = value; - return style(d_); + return style(d_); } optional style::builtin_id() const @@ -56,7 +57,7 @@ optional style::builtin_id() const style style::builtin_id(std::size_t builtin_id) { d_->builtin_id = builtin_id; - return *this; + return *this; } std::string style::name() const @@ -67,33 +68,33 @@ std::string style::name() const style style::name(const std::string &name) { d_->name = name; - return *this; + return *this; } optional style::custom() const { - return d_->custom_builtin; + return d_->custom_builtin; } style style::custom(bool value) { - d_->custom_builtin = value; - return *this; + d_->custom_builtin = value; + return *this; } bool style::operator==(const style &other) const { - return name() == other.name(); + return name() == other.name(); } xlnt::alignment &style::alignment() { - return d_->parent->alignments.at(d_->alignment_id.get()); + return d_->parent->alignments.at(d_->alignment_id.get()); } const xlnt::alignment &style::alignment() const { - return d_->parent->alignments.at(d_->alignment_id.get()); + return d_->parent->alignments.at(d_->alignment_id.get()); } style style::alignment(const xlnt::alignment &new_alignment, bool applied) @@ -105,12 +106,12 @@ style style::alignment(const xlnt::alignment &new_alignment, bool applied) xlnt::border &style::border() { - return d_->parent->borders.at(d_->border_id.get()); + return d_->parent->borders.at(d_->border_id.get()); } const xlnt::border &style::border() const { - return d_->parent->borders.at(d_->border_id.get()); + return d_->parent->borders.at(d_->border_id.get()); } style style::border(const xlnt::border &new_border, bool applied) @@ -122,12 +123,12 @@ style style::border(const xlnt::border &new_border, bool applied) xlnt::fill &style::fill() { - return d_->parent->fills.at(d_->fill_id.get()); + return d_->parent->fills.at(d_->fill_id.get()); } const xlnt::fill &style::fill() const { - return d_->parent->fills.at(d_->fill_id.get()); + return d_->parent->fills.at(d_->fill_id.get()); } style style::fill(const xlnt::fill &new_fill, bool applied) @@ -139,12 +140,12 @@ style style::fill(const xlnt::fill &new_fill, bool applied) xlnt::font &style::font() { - return d_->parent->fonts.at(d_->font_id.get()); + return d_->parent->fonts.at(d_->font_id.get()); } const xlnt::font &style::font() const { - return d_->parent->fonts.at(d_->font_id.get()); + return d_->parent->fonts.at(d_->font_id.get()); } style style::font(const xlnt::font &new_font, bool applied) @@ -157,34 +158,33 @@ style style::font(const xlnt::font &new_font, bool applied) xlnt::number_format &style::number_format() { auto tarid = d_->number_format_id.get(); - return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), + return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), [=](const class number_format &nf) { return nf.id() == tarid; }); } const xlnt::number_format &style::number_format() const { auto tarid = d_->number_format_id.get(); - return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), + return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), [=](const class number_format &nf) { return nf.id() == tarid; }); } style style::number_format(const xlnt::number_format &new_number_format, bool applied) { - auto copy = new_number_format; + auto copy = new_number_format; - if (!copy.has_id()) - { - copy.id(d_->parent->next_custom_number_format_id()); + if (!copy.has_id()) + { + 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(), - [©](const class number_format &nf) { return nf.id() == copy.id(); }) + } + else if (std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), + [©](const class number_format &nf) { return nf.id() == copy.id(); }) == d_->parent->number_formats.end()) { d_->parent->number_formats.push_back(copy); } - + d_->number_format_id = copy.id(); d_->number_format_applied = applied; @@ -193,12 +193,12 @@ style style::number_format(const xlnt::number_format &new_number_format, bool ap xlnt::protection &style::protection() { - return d_->parent->protections.at(d_->protection_id.get()); + return d_->parent->protections.at(d_->protection_id.get()); } const xlnt::protection &style::protection() const { - return d_->parent->protections.at(d_->protection_id.get()); + return d_->parent->protections.at(d_->protection_id.get()); } style style::protection(const xlnt::protection &new_protection, bool applied) diff --git a/source/utils/date.cpp b/source/utils/date.cpp index b23a731f..b48dbbe0 100644 --- a/source/utils/date.cpp +++ b/source/utils/date.cpp @@ -30,12 +30,12 @@ namespace { std::tm safe_localtime(std::time_t raw_time) { #ifdef _MSC_VER - std::tm result; - localtime_s(&result, &raw_time); + std::tm result; + localtime_s(&result, &raw_time); - return result; + return result; #else - return *localtime(&raw_time); + return *localtime(&raw_time); #endif } @@ -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(13 * (month_temp + 1) / 5.0) - + (year_temp % 100) + static_cast((year_temp % 100) / 4.0); + auto days = day_temp + static_cast(13 * (month_temp + 1) / 5.0) + (year_temp % 100) + + static_cast((year_temp % 100) / 4.0); auto gregorian = days + static_cast(year_temp / 400.0) - 2 * year_temp / 100; auto julian = days + 5 - year_temp / 100; diff --git a/source/utils/datetime.cpp b/source/utils/datetime.cpp index 40e92df8..cc2cc85f 100644 --- a/source/utils/datetime.cpp +++ b/source/utils/datetime.cpp @@ -23,20 +23,20 @@ #include #include -#include #include +#include #include namespace { std::string fill(const std::string &string, std::size_t length = 2) { - if (string.size() >= length) - { - return string; - } + if (string.size() >= length) + { + return string; + } - return std::string(length - string.size(), '0') + string; + return std::string(length - string.size(), '0') + string; } } // namespace @@ -47,15 +47,15 @@ datetime datetime::from_number(long double raw_time, calendar base_date) { auto date_part = date::from_number(static_cast(raw_time), base_date); auto time_part = time::from_number(raw_time); - + return datetime(date_part.year, date_part.month, date_part.day, time_part.hour, time_part.minute, time_part.second, - time_part.microsecond); + time_part.microsecond); } 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,39 +65,33 @@ 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() { - return datetime(date::today(), time::now()); + return datetime(date::today(), time::now()); } datetime datetime::today() { - return datetime(date::today(), time(0, 0, 0, 0)); + return datetime(date::today(), time(0, 0, 0, 0)); } 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_) { } datetime::datetime(const date &d, const time &t) - : year(d.year), - month(d.month), - day(d.day), - hour(t.hour), - minute(t.minute), - second(t.second), - microsecond(t.microsecond) + : year(d.year), + month(d.month), + day(d.day), + hour(t.hour), + minute(t.minute), + second(t.second), + microsecond(t.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 diff --git a/source/utils/exceptions.cpp b/source/utils/exceptions.cpp index d5228ee1..d03622b1 100644 --- a/source/utils/exceptions.cpp +++ b/source/utils/exceptions.cpp @@ -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) + ")") { } @@ -146,7 +146,7 @@ no_visible_worksheets::~no_visible_worksheets() } unsupported::unsupported(const std::string &message) - : exception(message) + : exception(message) { } diff --git a/source/utils/path.cpp b/source/utils/path.cpp index 467da0fb..e54d80b1 100644 --- a/source/utils/path.cpp +++ b/source/utils/path.cpp @@ -27,13 +27,13 @@ #ifdef __APPLE__ #include #elif defined(__linux) -#include #include #include +#include #endif -#include #include +#include namespace { @@ -41,44 +41,42 @@ namespace { char system_separator() { - return '\\'; + return '\\'; } bool is_drive_letter(char letter) { - return letter >= 'A' && letter <= 'Z'; + return letter >= 'A' && letter <= 'Z'; } bool is_root(const std::string &part) { - if (part.size() == 1 && part[0] == '/') return true; - if (part.size() != 3) return false; + 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) { - if (!part.empty() && part[0] == '/') return true; - if (part.size() < 3) return false; + if (!part.empty() && part[0] == '/') return true; + if (part.size() < 3) return false; - return is_root(part.substr(0, 3)); + return is_root(part.substr(0, 3)); } #else char system_separator() { - return '/'; + return '/'; } bool is_root(const std::string &part) { - return part == "/"; + return part == "/"; } - bool is_absolute(const std::string &part) { return !part.empty() && part[0] == '/'; @@ -88,38 +86,38 @@ bool is_absolute(const std::string &part) std::vector split_path(const std::string &path, char delim) { - std::vector split; - std::string::size_type previous_index = 0; - auto separator_index = path.find(delim); + std::vector split; + std::string::size_type previous_index = 0; + auto separator_index = path.find(delim); - while (separator_index != std::string::npos) - { - auto part = path.substr(previous_index, separator_index - previous_index); - split.push_back(part); + while (separator_index != std::string::npos) + { + auto part = path.substr(previous_index, separator_index - previous_index); + split.push_back(part); - previous_index = separator_index + 1; - separator_index = path.find(delim, previous_index); - } + previous_index = separator_index + 1; + separator_index = path.find(delim, previous_index); + } - // Don't add trailing slash - if (previous_index < path.size()) - { - split.push_back(path.substr(previous_index)); - } + // Don't add trailing slash + if (previous_index < path.size()) + { + split.push_back(path.substr(previous_index)); + } - return split; + return split; } bool file_exists(const std::string &path) { - struct stat info; - return stat(path.c_str(), &info) == 0 && (info.st_mode & S_IFREG); + struct stat info; + return stat(path.c_str(), &info) == 0 && (info.st_mode & S_IFREG); } bool directory_exists(const std::string path) { - struct stat info; - return stat(path.c_str(), &info) == 0 && (info.st_mode & S_IFDIR); + struct stat info; + return stat(path.c_str(), &info) == 0 && (info.st_mode & S_IFDIR); } } // namespace @@ -128,27 +126,28 @@ namespace xlnt { char path::system_separator() { - return ::system_separator(); + return ::system_separator(); } path::path() { } -path::path(const std::string &path_string) : internal_(path_string) +path::path(const std::string &path_string) + : internal_(path_string) { } -// general attributes +// general attributes bool path::is_relative() const { - return !is_absolute(); + return !is_absolute(); } bool path::is_absolute() const { - return ::is_absolute(internal_); + return ::is_absolute(internal_); } bool path::is_root() const @@ -161,44 +160,44 @@ path path::parent() const if (is_root()) return *this; auto split_path = split(); - + split_path.pop_back(); - + if (split_path.empty()) { return path(""); } - + path result; - + for (const auto &component : split_path) { result = result.append(component); } - - return result; + + return result; } std::string path::filename() const { auto split_path = split(); - return split_path.empty() ? "" : split_path.back(); + return split_path.empty() ? "" : split_path.back(); } std::string path::extension() const { - auto base = filename(); - auto last_dot = base.find_last_of('.'); - - return last_dot == std::string::npos ? "" : base.substr(last_dot + 1); + auto base = filename(); + auto last_dot = base.find_last_of('.'); + + return last_dot == std::string::npos ? "" : base.substr(last_dot + 1); } std::pair path::split_extension() const { - auto base = filename(); - auto last_dot = base.find_last_of('.'); + auto base = filename(); + auto last_dot = base.find_last_of('.'); - return{ base.substr(0, last_dot), base.substr(last_dot + 1) }; + return {base.substr(0, last_dot), base.substr(last_dot + 1)}; } // conversion @@ -215,18 +214,18 @@ std::vector path::split() const path path::resolve(const path &base_path) const { - if (is_absolute()) - { - return *this; - } + if (is_absolute()) + { + return *this; + } - path copy(base_path.internal_); + path copy(base_path.internal_); - for (const auto &part : split()) - { + for (const auto &part : split()) + { copy = copy.append(part); - } - + } + return copy; } @@ -234,28 +233,28 @@ path path::resolve(const path &base_path) const bool path::exists() const { - return is_file() || is_directory(); + return is_file() || is_directory(); } bool path::is_directory() const { - return directory_exists(string()); + return directory_exists(string()); } bool path::is_file() const { - return file_exists(string()); + return file_exists(string()); } // filesystem std::string path::read_contents() const { - std::ifstream f(string()); - std::ostringstream ss; - ss << f.rdbuf(); + std::ifstream f(string()); + std::ostringstream ss; + ss << f.rdbuf(); - return ss.str(); + return ss.str(); } // append @@ -263,27 +262,27 @@ std::string path::read_contents() const path path::append(const std::string &to_append) const { path copy(internal_); - + if (!internal_.empty() && internal_.back() != guess_separator()) { copy.internal_.push_back(guess_separator()); } - + copy.internal_.append(to_append); - + return copy; } path path::append(const path &to_append) const { - path copy(internal_); + path copy(internal_); - for (const auto &component : to_append.split()) - { - copy = copy.append(component); - } + for (const auto &component : to_append.split()) + { + copy = copy.append(component); + } - return copy; + return copy; } char path::guess_separator() const diff --git a/source/utils/time.cpp b/source/utils/time.cpp index 72831de9..165012be 100644 --- a/source/utils/time.cpp +++ b/source/utils/time.cpp @@ -30,12 +30,12 @@ namespace { std::tm safe_localtime(std::time_t raw_time) { #ifdef _MSC_VER - std::tm result; - localtime_s(&result, &raw_time); + std::tm result; + localtime_s(&result, &raw_time); - return result; + return result; #else - return *localtime(&raw_time); + return *localtime(&raw_time); #endif } @@ -58,18 +58,18 @@ time time::from_number(long double raw_time) result.second = static_cast(fractional_part); fractional_part = 1000000 * (fractional_part - result.second); result.microsecond = static_cast(fractional_part); - + if (result.microsecond == 999999 && fractional_part - result.microsecond > 0.5) { result.microsecond = 0; result.second += 1; - + if (result.second == 60) { result.second = 0; result.minute += 1; - - //TODO: too much nesting + + // TODO: too much nesting if (result.minute == 60) { result.minute = 0; @@ -77,7 +77,7 @@ time time::from_number(long double raw_time) } } } - + return result; } @@ -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(':'); @@ -101,7 +102,7 @@ time::time(const std::string &time_string) : hour(0), minute(0), second(0), micr colon_index = remaining.find(':'); minute = std::stoi(remaining.substr(0, colon_index)); colon_index = remaining.find(':'); - + if (colon_index != std::string::npos) { remaining = remaining.substr(colon_index + 1); @@ -114,19 +115,19 @@ long double time::to_number() const std::uint64_t microseconds = static_cast(microsecond); microseconds += static_cast(second * 1e6); microseconds += static_cast(minute * 1e6 * 60); - auto microseconds_per_hour = static_cast(1e6) * 60 * 60; + auto microseconds_per_hour = static_cast(1e6) * 60 * 60; microseconds += static_cast(hour) * microseconds_per_hour; auto number = microseconds / (24.0L * microseconds_per_hour); - auto hundred_billion = static_cast(1e9) * 100; + auto hundred_billion = static_cast(1e9) * 100; number = std::floor(number * hundred_billion + 0.5L) / hundred_billion; - + return number; } time time::now() { - std::tm now = safe_localtime(std::time(0)); - return time(now.tm_hour, now.tm_min, now.tm_sec); + std::tm now = safe_localtime(std::time(0)); + return time(now.tm_hour, now.tm_min, now.tm_sec); } } // namespace xlnt diff --git a/source/utils/timedelta.cpp b/source/utils/timedelta.cpp index 392debb2..b6439c61 100644 --- a/source/utils/timedelta.cpp +++ b/source/utils/timedelta.cpp @@ -27,18 +27,15 @@ 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_) +{ +} long double timedelta::to_number() const { @@ -51,7 +48,7 @@ long double timedelta::to_number() const auto hundred_billion = static_cast(1e9) * 100; number = std::floor(number * hundred_billion + 0.5L) / hundred_billion; number += days; - + return number; } @@ -70,23 +67,23 @@ timedelta timedelta::from_number(long double raw_time) result.seconds = static_cast(fractional_part); fractional_part = 1000000 * (fractional_part - result.seconds); result.microseconds = static_cast(fractional_part); - + if (result.microseconds == 999999 && fractional_part - result.microseconds > 0.5L) { result.microseconds = 0; result.seconds += 1; - + if (result.seconds == 60) { result.seconds = 0; result.minutes += 1; - - //TODO: too much nesting + + // TODO: too much nesting if (result.minutes == 60) { result.minutes = 0; result.hours += 1; - + if (result.hours == 24) { result.hours = 0; @@ -95,7 +92,7 @@ timedelta timedelta::from_number(long double raw_time) } } } - + return result; } diff --git a/source/workbook/const_worksheet_iterator.cpp b/source/workbook/const_worksheet_iterator.cpp index afb9bc44..2e87e7c0 100644 --- a/source/workbook/const_worksheet_iterator.cpp +++ b/source/workbook/const_worksheet_iterator.cpp @@ -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_) { } diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 2e0ea80e..e47f016a 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -29,28 +29,20 @@ #include #ifdef _MSC_VER -#include // utf-8 -> utf-16 conversion +#include // for std::wstring_convert #endif -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include #include #include -#include +#include #include #include +#include #include #include #include @@ -62,6 +54,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include namespace { @@ -112,19 +112,19 @@ bool workbook::has_core_property(const std::string &property_name) const return d_->core_properties_.count(property_name) > 0; } -template<> +template <> void workbook::core_property(const std::string &property_name, const std::string value) { d_->core_properties_[property_name] = value; } -template<> +template <> void workbook::core_property(const std::string &property_name, const char *value) { d_->core_properties_[property_name] = value; } -template<> +template <> void workbook::core_property(const std::string &property_name, const datetime value) { d_->core_properties_[property_name] = value.to_iso_string(); @@ -132,66 +132,64 @@ void workbook::core_property(const std::string &property_name, const datetime va workbook workbook::minimal() { - auto impl = new detail::workbook_impl(); - workbook wb(impl); + 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)); + 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_->sheet_title_rel_id_map_[title] = ws_rel; + 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; + return wb; } workbook workbook::empty_excel() { - auto impl = new detail::workbook_impl(); - workbook wb(impl); + 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("xml", "application/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.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"); - wb.core_property("Created", datetime(2016, 8, 12, 3, 16, 56)); - wb.core_property("Modified", datetime(2016, 8, 12, 3, 17, 16)); - wb.core_property("Application", "Microsoft Macintosh Excel"); - wb.core_property("AppVersion", "15.0300"); + wb.core_property("Creator", "Microsoft Office User"); + wb.core_property("LastModifiedBy", "Microsoft Office User"); + wb.core_property("Created", datetime(2016, 8, 12, 3, 16, 56)); + wb.core_property("Modified", datetime(2016, 8, 12, 3, 17, 16)); + wb.core_property("Application", "Microsoft Macintosh Excel"); + wb.core_property("AppVersion", "15.0300"); - auto file_version = detail::workbook_impl::file_version_t{"xl", 6, 6, 26709 }; - wb.d_->file_version_ = file_version; + auto file_version = detail::workbook_impl::file_version_t{"xl", 6, 6, 26709}; + wb.d_->file_version_ = file_version; - auto ws = wb.create_sheet(); + auto ws = wb.create_sheet(); page_margins margins; margins.left(0.7); @@ -200,7 +198,7 @@ workbook workbook::empty_excel() margins.bottom(0.75); margins.header(0.3); margins.footer(0.3); - ws.page_margins(margins); + ws.page_margins(margins); sheet_view view; ws.add_view(view); @@ -208,27 +206,24 @@ 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()) - .side(border_side::top, border::border_property()) - .side(border_side::start, border::border_property()) - .side(border_side::end, border::border_property()) - .side(border_side::diagonal, border::border_property()); - wb.d_->stylesheet_.get().borders.push_back(default_border); + 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()) + .side(border_side::diagonal, border::border_property()); + wb.d_->stylesheet_.get().borders.push_back(default_border); auto default_fill = fill(pattern_fill().type(pattern_fill_type::none)); - stylesheet.fills.push_back(default_fill); + stylesheet.fills.push_back(default_fill); auto gray125_fill = pattern_fill().type(pattern_fill_type::gray125); - stylesheet.fills.push_back(gray125_fill); + stylesheet.fills.push_back(gray125_fill); - auto default_font = font() - .name("Calibri") - .size(12) - .scheme("minor") - .family(2) - .color(theme_color(1)); - stylesheet.fonts.push_back(default_font); + 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) @@ -241,109 +236,110 @@ workbook workbook::empty_excel() .number_format(xlnt::number_format::general(), false) .style("Normal"); - wb.theme(xlnt::theme()); + wb.theme(xlnt::theme()); - return wb; + return wb; } workbook workbook::empty_libre_office() { - auto impl = new detail::workbook_impl(); - workbook wb(impl); + 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)); + 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_->sheet_title_rel_id_map_[title] = ws_rel; + 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); - auto ws = wb.sheet_by_index(0); - sheet_view view; ws.add_view(view); - page_margins margins; - margins.left(0.7875); - margins.right(0.7875); - margins.top(1.05277777777778); - margins.bottom(1.05277777777778); - margins.header(0.7875); - margins.footer(0.7875); - ws.page_margins(margins); - ws.page_setup(page_setup()); - ws.header_footer(xlnt::header_footer() - .header(header_footer::location::center, - rich_text(rich_text_run{"&A",font().name("Times New Roman").size(12)})) - .footer(header_footer::location::center, - rich_text(rich_text_run{"Page &B",font().name("Times New Roman").size(12)}))); - ws.add_column_properties(1, column_properties()); + page_margins margins; + margins.left(0.7875); + margins.right(0.7875); + margins.top(1.05277777777778); + margins.bottom(1.05277777777778); + margins.header(0.7875); + margins.footer(0.7875); + ws.page_margins(margins); + ws.page_setup(page_setup()); + ws.header_footer(xlnt::header_footer() + .header(header_footer::location::center, + rich_text(rich_text_run{"&A", font().name("Times New Roman").size(12)})) + .footer(header_footer::location::center, + rich_text(rich_text_run{"Page &B", font().name("Times New Roman").size(12)}))); + ws.add_column_properties(1, column_properties()); wb.d_->stylesheet_ = detail::stylesheet(); auto &stylesheet = wb.d_->stylesheet_.get(); - auto default_alignment = xlnt::alignment() - .horizontal(horizontal_alignment::general) - .vertical(vertical_alignment::bottom) - .rotation(0) - .wrap(false) - .indent(0) - .shrink(false); - stylesheet.alignments.push_back(default_alignment); + auto default_alignment = xlnt::alignment() + .horizontal(horizontal_alignment::general) + .vertical(vertical_alignment::bottom) + .rotation(0) + .wrap(false) + .indent(0) + .shrink(false); + stylesheet.alignments.push_back(default_alignment); - 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()) - .side(border_side::diagonal, border::border_property()) - .diagonal(diagonal_direction::neither); - stylesheet.borders.push_back(default_border); + 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()) + .side(border_side::diagonal, border::border_property()) + .diagonal(diagonal_direction::neither); + stylesheet.borders.push_back(default_border); - auto default_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::none)); - stylesheet.fills.push_back(default_fill); + auto default_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::none)); + stylesheet.fills.push_back(default_fill); - auto gray125_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::gray125)); - stylesheet.fills.push_back(gray125_fill); + auto gray125_fill = xlnt::fill(xlnt::pattern_fill().type(pattern_fill_type::gray125)); + stylesheet.fills.push_back(gray125_fill); - auto default_font = font().name("Arial").size(10).family(2); - stylesheet.fonts.push_back(default_font); + auto default_font = font().name("Arial").size(10).family(2); + stylesheet.fonts.push_back(default_font); - auto second_font = font().name("Arial").size(10).family(0); - stylesheet.fonts.push_back(second_font); + auto second_font = font().name("Arial").size(10).family(0); + stylesheet.fonts.push_back(second_font); - auto default_number_format = xlnt::number_format(); - default_number_format.format_string("General"); - default_number_format.id(164); - stylesheet.number_formats.push_back(default_number_format); + auto default_number_format = xlnt::number_format(); + default_number_format.format_string("General"); + default_number_format.id(164); + stylesheet.number_formats.push_back(default_number_format); - auto default_protection = xlnt::protection() - .locked(true) - .hidden(false); - stylesheet.protections.push_back(default_protection); + 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) @@ -391,29 +397,31 @@ workbook workbook::empty_libre_office() .number_format(number_format::percentage(), false) .protection(default_protection, false); - wb.create_format() + wb.create_format() .number_format(default_number_format, true) .alignment(default_alignment, true) .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; + return wb; } workbook workbook::empty_numbers() { - return empty_excel(); + return empty_excel(); } workbook::workbook() { - auto wb_template = empty_excel(); - swap(*this, wb_template); + auto wb_template = empty_excel(); + swap(*this, wb_template); } -workbook::workbook(detail::workbook_impl *impl) : d_(impl) +workbook::workbook(detail::workbook_impl *impl) + : d_(impl) { if (impl != nullptr) { @@ -426,137 +434,137 @@ workbook::workbook(detail::workbook_impl *impl) : d_(impl) void workbook::register_app_properties_in_manifest() { - auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); - 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); - } + 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); + } } void workbook::register_core_properties_in_manifest() { - auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); - 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); - } + 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); + } } void workbook::register_shared_string_table_in_manifest() { - auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); - if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::shared_string_table)) - { - 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); - } + if (!manifest().has_relationship(wb_rel.target().path(), relationship_type::shared_string_table)) + { + 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); + } } void workbook::register_stylesheet_in_manifest() { - auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); - 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); - } + 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); + } } void workbook::register_theme_in_manifest() { - auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); + auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document); - 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); - } + 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); + } } 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())); - path ws_path(ws_rel.source().path().parent().append(ws_rel.target().path())); + 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())); + path ws_path(ws_rel.source().path().parent().append(ws_rel.target().path())); - if (!manifest().has_relationship(ws_path, relationship_type::vml_drawing)) - { - std::size_t file_number = 1; - path filename("vmlDrawing1.vml"); + if (!manifest().has_relationship(ws_path, relationship_type::vml_drawing)) + { + std::size_t file_number = 1; + path filename("vmlDrawing1.vml"); bool filename_exists = true; - while (filename_exists) - { + while (filename_exists) + { filename_exists = false; - 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_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)) - { - if (current_ws_child_rel.target().path() == path("../drawings").append(filename)) - { - filename_exists = true; - break; - } - } - } + 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)) + { + filename_exists = true; + break; + } + } + } if (filename_exists) { file_number++; filename = path("vmlDrawing" + std::to_string(file_number) + ".vml"); } - } + } - 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); - } + 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); + } - if (!manifest().has_relationship(ws_path, relationship_type::comments)) - { - std::size_t file_number = 1; - path filename("comments1.xml"); + if (!manifest().has_relationship(ws_path, relationship_type::comments)) + { + std::size_t file_number = 1; + path filename("comments1.xml"); - while (true) - { - if (!manifest().has_override_type(constants::package_xl().append(filename))) break; + while (true) + { + if (!manifest().has_override_type(constants::package_xl().append(filename))) break; - file_number++; - filename = path("comments" + std::to_string(file_number) + ".xml"); - } + file_number++; + filename = path("comments" + std::to_string(file_number) + ".xml"); + } - const path absolute_path(constants::package_xl().append(filename)); - manifest().register_override_type(absolute_path, - "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"); + const path absolute_path(constants::package_xl().append(filename)); + 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); - } + const path relative_path(path("..").append(filename)); + manifest().register_relationship( + uri(ws_path.string()), relationship_type::comments, uri(relative_path.string()), target_mode::internal); + } } const worksheet workbook::sheet_by_title(const std::string &title) const @@ -592,57 +600,56 @@ worksheet workbook::sheet_by_index(std::size_t index) throw invalid_parameter(); } - auto iter = d_->worksheets_.begin(); + auto iter = d_->worksheets_.begin(); - for (std::size_t i = 0; i < index; ++i) - { + for (std::size_t i = 0; i < index; ++i) + { ++iter; - } + } - return worksheet(&*iter); + return worksheet(&*iter); } const worksheet workbook::sheet_by_index(std::size_t index) const { - auto iter = d_->worksheets_.begin(); + auto iter = d_->worksheets_.begin(); - for (std::size_t i = 0; i < index; ++i, ++iter) - { - } + for (std::size_t i = 0; i < index; ++i, ++iter) + { + } - return worksheet(&*iter); + return worksheet(&*iter); } worksheet workbook::sheet_by_id(std::size_t id) { - for (auto &impl : d_->worksheets_) - { - if (impl.id_ == id) - { - return worksheet(&impl); - } - } + for (auto &impl : d_->worksheets_) + { + if (impl.id_ == id) + { + return worksheet(&impl); + } + } - throw key_not_found(); + throw key_not_found(); } const worksheet workbook::sheet_by_id(std::size_t id) const { - for (auto &impl : d_->worksheets_) - { - if (impl.id_ == id) - { - return worksheet(&impl); - } - } + for (auto &impl : d_->worksheets_) + { + if (impl.id_ == id) + { + return worksheet(&impl); + } + } - throw key_not_found(); + throw key_not_found(); } 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 @@ -672,21 +679,21 @@ worksheet workbook::create_sheet() d_->worksheets_.push_back(detail::worksheet_impl(this, sheet_id, title)); - auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document); + 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_->sheet_title_rel_id_map_[title] = ws_rel; + 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()); } void workbook::copy_sheet(worksheet to_copy) { - if(to_copy.d_->parent_ != this) throw invalid_parameter(); + if (to_copy.d_->parent_ != this) throw invalid_parameter(); detail::worksheet_impl impl(*to_copy.d_); auto new_sheet = create_sheet(); @@ -700,14 +707,14 @@ void workbook::copy_sheet(worksheet to_copy, std::size_t index) if (index != d_->worksheets_.size() - 1) { - auto iter = d_->worksheets_.begin(); + auto iter = d_->worksheets_.begin(); - for (std::size_t i = 0; i < index; ++i, ++iter) - { - } + for (std::size_t i = 0; i < index; ++i, ++iter) + { + } - d_->worksheets_.insert(iter, d_->worksheets_.back()); - d_->worksheets_.pop_back(); + d_->worksheets_.insert(iter, d_->worksheets_.back()); + d_->worksheets_.pop_back(); } } @@ -717,7 +724,7 @@ std::size_t workbook::index(worksheet ws) if (match == end()) { - throw invalid_parameter(); + throw invalid_parameter(); } return static_cast(std::distance(begin(), match)); @@ -744,7 +751,7 @@ void workbook::remove_named_range(const std::string &name) } } - throw key_not_found(); + throw key_not_found(); } range workbook::named_range(const std::string &name) @@ -762,9 +769,9 @@ range workbook::named_range(const std::string &name) void workbook::load(std::istream &stream) { - clear(); + clear(); detail::xlsx_consumer consumer(*this); - consumer.read(stream); + consumer.read(stream); } void workbook::load(const std::vector &data) @@ -781,12 +788,12 @@ void workbook::load(const std::vector &data) void workbook::load(const std::string &filename) { - return load(path(filename)); + return load(path(filename)); } void workbook::load(const path &filename) { - std::ifstream file_stream; + std::ifstream file_stream; open_stream(file_stream, filename.string()); if (!file_stream.good()) @@ -799,12 +806,12 @@ void workbook::load(const path &filename) void workbook::load(const std::string &filename, const std::string &password) { - return load(path(filename), password); + return load(path(filename), password); } void workbook::load(const path &filename, const std::string &password) { - std::ifstream file_stream; + std::ifstream file_stream; open_stream(file_stream, filename.string()); if (!file_stream.good()) @@ -812,7 +819,7 @@ void workbook::load(const path &filename, const std::string &password) throw xlnt::exception("file not found " + filename.string()); } - return load(file_stream, password); + return load(file_stream, password); } void workbook::load(const std::vector &data, const std::string &password) @@ -829,9 +836,9 @@ void workbook::load(const std::vector &data, const std::string &pa void workbook::load(std::istream &stream, const std::string &password) { - clear(); - detail::xlsx_consumer consumer(*this); - consumer.read(stream, password); + clear(); + detail::xlsx_consumer consumer(*this); + consumer.read(stream, password); } void workbook::save(std::vector &data) const @@ -843,20 +850,20 @@ void workbook::save(std::vector &data) const void workbook::save(const std::string &filename) const { - return save(path(filename)); + return save(path(filename)); } void workbook::save(const path &filename) const { - std::ofstream file_stream; + std::ofstream file_stream; open_stream(file_stream, filename.string()); - save(file_stream); + save(file_stream); } void workbook::save(std::ostream &stream) const { - detail::xlsx_producer producer(*this); - producer.write(stream); + detail::xlsx_producer producer(*this); + producer.write(stream); } void workbook::save(std::ostream &stream, const std::string &password) @@ -897,20 +904,21 @@ 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()) { - throw invalid_parameter(); + throw invalid_parameter(); } - auto ws_rel_id = d_->sheet_title_rel_id_map_.at(ws.title()); - 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_->sheet_title_rel_id_map_.erase(ws.title()); + auto ws_rel_id = d_->sheet_title_rel_id_map_.at(ws.title()); + 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_->sheet_title_rel_id_map_.erase(ws.title()); d_->worksheets_.erase(match_iter); } @@ -920,17 +928,17 @@ worksheet workbook::create_sheet(std::size_t index) if (index != d_->worksheets_.size() - 1) { - auto iter = d_->worksheets_.begin(); + auto iter = d_->worksheets_.begin(); - for (std::size_t i = 0; i < index; ++i, ++iter) - { - } + for (std::size_t i = 0; i < index; ++i, ++iter) + { + } - d_->worksheets_.insert(iter, d_->worksheets_.back()); - d_->worksheets_.pop_back(); + d_->worksheets_.insert(iter, d_->worksheets_.back()); + d_->worksheets_.pop_back(); } - return sheet_by_index(index); + return sheet_by_index(index); } worksheet workbook::create_sheet_with_rel(const std::string &title, const relationship &rel) @@ -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()); @@ -993,7 +1001,7 @@ std::vector workbook::sheet_titles() const std::size_t workbook::sheet_count() const { - return d_->worksheets_.size(); + return d_->worksheets_.size(); } worksheet workbook::operator[](const std::string &name) @@ -1003,12 +1011,12 @@ worksheet workbook::operator[](const std::string &name) worksheet workbook::operator[](std::size_t index) { - return sheet_by_index(index); + return sheet_by_index(index); } void workbook::clear() { - *d_ = detail::workbook_impl(); + *d_ = detail::workbook_impl(); d_->stylesheet_.clear(); } @@ -1027,31 +1035,31 @@ void swap(workbook &left, workbook &right) using std::swap; swap(left.d_, right.d_); - if (left.d_ != nullptr) - { - for (auto ws : left) - { - ws.parent(left); - } + if (left.d_ != nullptr) + { + for (auto ws : left) + { + ws.parent(left); + } - if (left.d_->stylesheet_.is_set()) - { - left.d_->stylesheet_->parent = &left; - } - } + if (left.d_->stylesheet_.is_set()) + { + left.d_->stylesheet_->parent = &left; + } + } - if (right.d_ != nullptr) - { - for (auto ws : right) - { - ws.parent(right); - } + if (right.d_ != nullptr) + { + for (auto ws : right) + { + ws.parent(right); + } - if (left.d_->stylesheet_.is_set()) - { - right.d_->stylesheet_->parent = &right; - } - } + if (left.d_->stylesheet_.is_set()) + { + right.d_->stylesheet_->parent = &right; + } + } } workbook &workbook::operator=(workbook other) @@ -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(); @@ -1085,7 +1095,7 @@ workbook::~workbook() bool workbook::has_theme() const { - return d_->theme_.is_set(); + return d_->theme_.is_set(); } const theme &workbook::theme() const @@ -1095,8 +1105,8 @@ const theme &workbook::theme() const void workbook::theme(const class theme &value) { - register_theme_in_manifest(); - d_->theme_ = value; + register_theme_in_manifest(); + d_->theme_ = value; } std::vector workbook::named_ranges() const @@ -1116,13 +1126,13 @@ std::vector workbook::named_ranges() const format workbook::create_format(bool default_format) { - register_stylesheet_in_manifest(); + register_stylesheet_in_manifest(); return d_->stylesheet_->create_format(default_format); } bool workbook::has_style(const std::string &name) const { - return d_->stylesheet_->has_style(name); + return d_->stylesheet_->has_style(name); } void workbook::clear_styles() @@ -1154,12 +1164,12 @@ void workbook::apply_to_cells(std::function f) format workbook::format(std::size_t format_index) { - return d_->stylesheet_->format(format_index); + return d_->stylesheet_->format(format_index); } const format workbook::format(std::size_t format_index) const { - return d_->stylesheet_->format(format_index); + return d_->stylesheet_->format(format_index); } manifest &workbook::manifest() @@ -1184,39 +1194,39 @@ const std::vector &workbook::shared_strings() const void workbook::add_shared_string(const rich_text &shared, bool allow_duplicates) { - register_shared_string_table_in_manifest(); + register_shared_string_table_in_manifest(); + + if (!allow_duplicates) + { + // TODO: inefficient, use a set or something? + for (auto &s : d_->shared_strings_) + { + if (s == shared) return; + } + } - if (!allow_duplicates) - { - //TODO: inefficient, use a set or something? - for (auto &s : d_->shared_strings_) - { - if (s == shared) return; - } - } - d_->shared_strings_.push_back(shared); } bool workbook::contains(const std::string &sheet_title) const { - for(auto ws : *this) + for (auto ws : *this) { - if(ws.title() == sheet_title) return true; + if (ws.title() == sheet_title) return true; } - + return false; } -void workbook::thumbnail(const std::vector &thumbnail, - const std::string &extension, const std::string &content_type) +void workbook::thumbnail( + const std::vector &thumbnail, const std::string &extension, const std::string &content_type) { - if (!d_->manifest_.has_relationship(path("/"), relationship_type::thumbnail)) - { + 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); d_->images_[thumbnail_rel.target().to_string()] = thumbnail; @@ -1230,123 +1240,147 @@ const std::vector &workbook::thumbnail() const style workbook::create_style(const std::string &name) { - return d_->stylesheet_->create_style(name); + return d_->stylesheet_->create_style(name); } style workbook::style(const std::string &name) { - return d_->stylesheet_->style(name); + return d_->stylesheet_->style(name); } const style workbook::style(const std::string &name) const { - return d_->stylesheet_->style(name); + return d_->stylesheet_->style(name); } calendar workbook::base_date() const { - return d_->base_date_; + return d_->base_date_; } void workbook::base_date(calendar base_date) { - d_->base_date_ = base_date; + d_->base_date_ = base_date; } bool workbook::has_title() const { - return d_->title_.is_set(); + return d_->title_.is_set(); } std::string workbook::title() const { - return d_->title_.get(); + return d_->title_.get(); } void workbook::title(const std::string &title) { - d_->title_ = title; + d_->title_ = title; } detail::workbook_impl &workbook::impl() { - return *d_; + return *d_; } const detail::workbook_impl &workbook::impl() const { - return *d_; + return *d_; } bool workbook::has_view() const { - return d_->view_.is_set(); + return d_->view_.is_set(); } workbook_view workbook::view() const { - if (!d_->view_.is_set()) - { - throw invalid_attribute(); - } + if (!d_->view_.is_set()) + { + throw invalid_attribute(); + } - return d_->view_.get(); + return d_->view_.get(); } void workbook::view(const workbook_view &view) { - d_->view_ = view; + d_->view_ = view; } bool workbook::has_code_name() const { - return d_->code_name_.is_set(); + return d_->code_name_.is_set(); } std::string workbook::code_name() const { - if (has_code_name()) - { - throw invalid_attribute(); - } + if (has_code_name()) + { + throw invalid_attribute(); + } - return d_->code_name_.get(); + return d_->code_name_.get(); } void workbook::code_name(const std::string &code_name) { - d_->code_name_ = code_name; + d_->code_name_ = code_name; } bool workbook::has_file_version() const { - return d_->file_version_.is_set(); + return d_->file_version_.is_set(); } std::string workbook::app_name() const { - return d_->file_version_.get().app_name; + return d_->file_version_.get().app_name; } std::size_t workbook::last_edited() const { - return d_->file_version_.get().last_edited; + return d_->file_version_.get().last_edited; } std::size_t workbook::lowest_edited() const { - return d_->file_version_.get().lowest_edited; + return d_->file_version_.get().lowest_edited; } std::size_t workbook::rup_build() const { - return d_->file_version_.get().rup_build; + return d_->file_version_.get().rup_build; } -template<> +template <> std::string workbook::core_property(const std::string &property_name) const { return d_->core_properties_.at(property_name); } +/// +/// +/// +bool workbook::has_calculation_properties() const +{ + return d_->calculation_properties_.is_set(); +} + +/// +/// +/// +class calculation_properties workbook::calculation_properties() const +{ + return d_->calculation_properties_.get(); +} + +/// +/// +/// +void workbook::calculation_properties(const class calculation_properties &props) +{ + d_->calculation_properties_ = props; +} + } // namespace xlnt diff --git a/source/workbook/worksheet_iterator.cpp b/source/workbook/worksheet_iterator.cpp index b492685c..86db1e70 100644 --- a/source/workbook/worksheet_iterator.cpp +++ b/source/workbook/worksheet_iterator.cpp @@ -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_) { } diff --git a/source/worksheet/cell_iterator.cpp b/source/worksheet/cell_iterator.cpp index 9e8127f3..5e024df8 100644 --- a/source/worksheet/cell_iterator.cpp +++ b/source/worksheet/cell_iterator.cpp @@ -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 @@ -56,7 +62,7 @@ cell_iterator &cell_iterator::operator--() if (order_ == major_order::row) { current_cell_.column_index(current_cell_.column_index() - 1); - + while (!ws_.has_cell(current_cell_) && current_cell_.column() > range_.top_left().column()) { current_cell_.column_index(current_cell_.column_index() - 1); @@ -90,7 +96,7 @@ cell_iterator &cell_iterator::operator++() { current_cell_.column_index(current_cell_.column_index() + 1); } - + while (!ws_.has_cell(current_cell_) && current_cell_.column() <= range_.bottom_right().column()) { current_cell_.column_index(current_cell_.column_index() + 1); @@ -116,6 +122,7 @@ cell_iterator cell_iterator::operator++(int) { cell_iterator old = *this; ++*this; + return old; } diff --git a/source/worksheet/cell_vector.cpp b/source/worksheet/cell_vector.cpp index b39ca6d4..60e227e6 100644 --- a/source/worksheet/cell_vector.cpp +++ b/source/worksheet/cell_vector.cpp @@ -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 diff --git a/source/worksheet/const_cell_iterator.cpp b/source/worksheet/const_cell_iterator.cpp index a6ed2baf..55c3237c 100644 --- a/source/worksheet/const_cell_iterator.cpp +++ b/source/worksheet/const_cell_iterator.cpp @@ -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; } diff --git a/source/worksheet/const_range_iterator.cpp b/source/worksheet/const_range_iterator.cpp index 44b800fa..a6809640 100644 --- a/source/worksheet/const_range_iterator.cpp +++ b/source/worksheet/const_range_iterator.cpp @@ -20,16 +20,20 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include #include #include +#include #include #include 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 @@ -66,7 +72,7 @@ const_range_iterator const_range_iterator::operator--(int) { const_range_iterator old = *this; --*this; - + return old; } @@ -88,7 +94,7 @@ const_range_iterator const_range_iterator::operator++(int) { const_range_iterator old = *this; ++*this; - + return old; } @@ -97,12 +103,12 @@ const cell_vector const_range_iterator::operator*() const if (order_ == major_order::row) { range_reference reference(range_.top_left().column_index(), current_cell_.row(), - range_.bottom_right().column_index(), current_cell_.row()); + range_.bottom_right().column_index(), current_cell_.row()); return cell_vector(ws_, reference, order_); } range_reference reference(current_cell_.column_index(), range_.top_left().row(), - current_cell_.column_index(), range_.bottom_right().row()); + current_cell_.column_index(), range_.bottom_right().row()); return cell_vector(ws_, reference, order_); } diff --git a/source/worksheet/page_margins.cpp b/source/worksheet/page_margins.cpp index 240d6518..c2e429a0 100644 --- a/source/worksheet/page_margins.cpp +++ b/source/worksheet/page_margins.cpp @@ -88,5 +88,5 @@ void page_margins::footer(double footer) { footer_ = footer; } - + } // namespace xlnt diff --git a/source/worksheet/range.cpp b/source/worksheet/range.cpp index 6cf0e643..5db40f26 100644 --- a/source/worksheet/range.cpp +++ b/source/worksheet/range.cpp @@ -20,9 +20,9 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include #include #include +#include #include #include #include @@ -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(static_cast(ref_.top_left().row()) + vector_index), - ref_.bottom_right().column_index(), - static_cast(static_cast(ref_.top_left().row()) + vector_index)); - - return cell_vector(ws_, reference, order_); + auto row = ref_.top_left().row() + static_cast(vector_index); + vector_ref.top_left().row(row); + vector_ref.bottom_right().row(row); + } + else + { + auto column = ref_.top_left().column() + static_cast(vector_index); + vector_ref.top_left().column_index(column); + vector_ref.bottom_right().column_index(column); } - range_reference reference( - static_cast(static_cast(ref_.top_left().column().index) + vector_index), - ref_.top_left().row(), - static_cast(static_cast(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) diff --git a/source/worksheet/range_iterator.cpp b/source/worksheet/range_iterator.cpp index 711f8ffd..9fa8a376 100644 --- a/source/worksheet/range_iterator.cpp +++ b/source/worksheet/range_iterator.cpp @@ -20,8 +20,8 @@ // // @license: http://www.opensource.org/licenses/mit-license.php // @author: see AUTHORS file -#include #include +#include #include #include #include @@ -33,17 +33,21 @@ cell_vector range_iterator::operator*() const if (order_ == major_order::row) { range_reference reference(range_.top_left().column_index(), current_cell_.row(), - range_.bottom_right().column_index(), current_cell_.row()); + range_.bottom_right().column_index(), current_cell_.row()); return cell_vector(ws_, reference, order_); } range_reference reference(current_cell_.column_index(), range_.top_left().row(), - current_cell_.column_index(), range_.bottom_right().row()); + current_cell_.column_index(), range_.bottom_right().row()); 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 @@ -80,7 +86,7 @@ range_iterator range_iterator::operator--(int) { range_iterator old = *this; --*this; - + return old; } @@ -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 { @@ -116,7 +123,7 @@ range_iterator range_iterator::operator++(int) { range_iterator old = *this; ++*this; - + return old; } diff --git a/source/worksheet/range_reference.cpp b/source/worksheet/range_reference.cpp index f8a55ef6..6002ab41 100644 --- a/source/worksheet/range_reference.cpp +++ b/source/worksheet/range_reference.cpp @@ -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 diff --git a/source/worksheet/sheet_protection.cpp b/source/worksheet/sheet_protection.cpp index 57277821..de22010f 100644 --- a/source/worksheet/sheet_protection.cpp +++ b/source/worksheet/sheet_protection.cpp @@ -34,6 +34,7 @@ std::string int_to_hex(T i) { std::stringstream stream; stream << std::hex << i; + return stream.str(); } @@ -70,7 +71,8 @@ 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()); }); + [](char c) { return std::toupper(c, std::locale::classic()); }); + return hashed; } } diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index 044d6abb..736dc0e6 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -38,10 +38,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -49,26 +49,37 @@ #include #include +namespace { + +int points_to_pixels(double points, double dpi) +{ + return static_cast(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); + || d_->views_.front().pane().state == pane_state::frozen_split); } std::string worksheet::unique_sheet_name(const std::string &value) const @@ -94,24 +105,24 @@ void worksheet::create_named_range(const std::string &name, const std::string &r void worksheet::create_named_range(const std::string &name, const range_reference &reference) { - try - { - auto temp = cell_reference::split_reference(name); + try + { + auto temp = cell_reference::split_reference(name); - // name is a valid reference, make sure it's outside the allowed range + // name is a valid reference, make sure it's outside the allowed range - if (column_t(temp.first).index <= column_t("XFD").index && temp.second <= 1048576) - { - throw invalid_parameter(); //("named range name must be outside the range A1-XFD1048576"); - } - } - catch (xlnt::invalid_cell_reference) - { - // name is not a valid reference, that's good - } + if (column_t(temp.first).index <= column_t("XFD").index && temp.second <= 1048576) + { + throw invalid_parameter(); //("named range name must be outside the range A1-XFD1048576"); + } + } + catch (xlnt::invalid_cell_reference) + { + // name is not a valid reference, that's good + } std::vector targets; - targets.push_back({ *this, reference }); + targets.push_back({*this, reference}); d_->named_ranges_[name] = xlnt::named_range(name, targets); } @@ -133,12 +144,12 @@ std::vector worksheet::merged_ranges() const bool worksheet::has_page_margins() const { - return d_->page_margins_.is_set(); + return d_->page_margins_.is_set(); } bool worksheet::has_page_setup() const { - return d_->page_setup_.is_set(); + return d_->page_setup_.is_set(); } page_margins worksheet::page_margins() const @@ -148,7 +159,7 @@ page_margins worksheet::page_margins() const void worksheet::page_margins(const class page_margins &margins) { - d_->page_margins_ = margins; + d_->page_margins_ = margins; } void worksheet::auto_filter(const std::string &reference_string) @@ -183,15 +194,15 @@ void worksheet::clear_auto_filter() void worksheet::page_setup(const struct page_setup &setup) { - d_->page_setup_ = setup; + d_->page_setup_ = setup; } page_setup worksheet::page_setup() const { - if (!has_page_setup()) - { - throw invalid_attribute(); - } + if (!has_page_setup()) + { + throw invalid_attribute(); + } return d_->page_setup_.get(); } @@ -203,7 +214,7 @@ workbook &worksheet::workbook() const workbook &worksheet::workbook() const { - return *d_->parent_; + return *d_->parent_; } void worksheet::garbage_collect() @@ -254,28 +265,27 @@ std::string worksheet::title() const void worksheet::title(const std::string &title) { - if (title.length() > 31) - { - throw invalid_sheet_title(title); - } + if (title.length() > 31) + { + throw invalid_sheet_title(title); + } - if (title.find_first_of("*:/\\?[]") != std::string::npos) - { - throw invalid_sheet_title(title); - } + if (title.find_first_of("*:/\\?[]") != std::string::npos) + { + 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); - } + 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_.erase(d_->title_); - d_->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_.erase(d_->title_); + d_->title_ = title; } cell_reference worksheet::frozen_panes() const @@ -312,7 +322,7 @@ void worksheet::freeze_panes(const cell_reference &ref) primary_view.clear_selections(); primary_view.add_selection(selection()); - + if (ref == "A1") { unfreeze_panes(); @@ -383,9 +393,9 @@ cell worksheet::cell(const cell_reference &reference) if (row.find(reference.column_index()) == row.end()) { auto &impl = row[reference.column_index()] = detail::cell_impl(); - impl.parent_ = d_; - impl.column_ = reference.column_index(); - impl.row_ = reference.row(); + impl.parent_ = d_; + impl.column_ = reference.column_index(); + impl.row_ = reference.row(); } return xlnt::cell(&row[reference.column_index()]); @@ -399,13 +409,11 @@ 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; } @@ -420,7 +428,7 @@ range worksheet::named_range(const std::string &name) { throw key_not_found(); } - + if (!has_named_range(name)) { throw key_not_found(); @@ -567,7 +575,7 @@ void worksheet::unmerge_cells(const range_reference &reference) if (match == d_->merged_cells_.end()) { - throw invalid_parameter(); + throw invalid_parameter(); } d_->merged_cells_.erase(match); @@ -690,29 +698,29 @@ bool worksheet::operator==(const worksheet &other) const bool worksheet::compare(const worksheet &other, bool reference) const { - if(reference) + if (reference) { return d_ == other.d_; } - - if(d_->parent_ != other.d_->parent_) return false; - - for(auto &row : d_->cell_map_) + + if (d_->parent_ != other.d_->parent_) return false; + + for (auto &row : d_->cell_map_) { - if(other.d_->cell_map_.find(row.first) == other.d_->cell_map_.end()) + if (other.d_->cell_map_.find(row.first) == other.d_->cell_map_.end()) { return false; } - - for(auto &cell : row.second) + + for (auto &cell : row.second) { - if(other.d_->cell_map_[row.first].find(cell.first) == other.d_->cell_map_[row.first].end()) + if (other.d_->cell_map_[row.first].find(cell.first) == other.d_->cell_map_[row.first].end()) { return false; } - + xlnt::cell this_cell(&cell.second); - xlnt::cell other_cell(&other.d_->cell_map_[row.first][cell.first]); + xlnt::cell other_cell(&other.d_->cell_map_[row.first][cell.first]); if (this_cell.data_type() != other_cell.data_type()) { @@ -726,16 +734,15 @@ 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; } - + return false; } @@ -787,7 +794,7 @@ void worksheet::remove_named_range(const std::string &name) { if (!has_named_range(name)) { - throw key_not_found(); + throw key_not_found(); } d_->named_ranges_.erase(name); @@ -815,17 +822,6 @@ std::vector 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(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,41 +830,15 @@ 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 }; + return {current_column - 1, current_row - 1}; } cell_reference worksheet::point_pos(const std::pair &point) const @@ -921,7 +891,7 @@ worksheet::iterator worksheet::begin() auto dimensions = calculate_dimension(); cell_reference top_right(dimensions.bottom_right().column_index(), dimensions.top_left().row()); range_reference row_range(dimensions.top_left(), top_right); - + return iterator(*this, row_range, dimensions, major_order::row); } @@ -931,7 +901,7 @@ worksheet::iterator worksheet::end() auto past_end_row_index = dimensions.bottom_right().row() + 1; cell_reference bottom_left(dimensions.top_left().column_index(), past_end_row_index); cell_reference bottom_right(dimensions.bottom_right().column_index(), past_end_row_index); - + return iterator(*this, range_reference(bottom_left, bottom_right), dimensions, major_order::row); } @@ -940,7 +910,7 @@ worksheet::const_iterator worksheet::cbegin() const auto dimensions = calculate_dimension(); cell_reference top_right(dimensions.bottom_right().column_index(), dimensions.top_left().row()); range_reference row_range(dimensions.top_left(), top_right); - + return const_iterator(*this, row_range, major_order::row); } @@ -950,7 +920,7 @@ worksheet::const_iterator worksheet::cend() const auto past_end_row_index = dimensions.bottom_right().row() + 1; cell_reference bottom_left(dimensions.top_left().column_index(), past_end_row_index); cell_reference bottom_right(dimensions.bottom_right().column_index(), past_end_row_index); - + return const_iterator(*this, range_reference(bottom_left, bottom_right), major_order::row); } @@ -1017,7 +987,7 @@ range_reference worksheet::print_area() const bool worksheet::has_view() const { - return !d_->views_.empty(); + return !d_->views_.empty(); } sheet_view worksheet::view(std::size_t index) const @@ -1032,7 +1002,7 @@ void worksheet::add_view(const sheet_view &new_view) void worksheet::register_comments_in_manifest() { - workbook().register_comments_in_manifest(*this); + workbook().register_comments_in_manifest(*this); } bool worksheet::has_header_footer() const @@ -1045,24 +1015,52 @@ void worksheet::header_footer(const class header_footer &hf) d_->header_footer_ = hf; } -std::vector &worksheet::row_breaks() +void worksheet::page_break_at_row(row_t row) +{ + d_->row_breaks_.push_back(row); +} + +const std::vector &worksheet::page_break_rows() const { return d_->row_breaks_; } -const std::vector &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 &worksheet::column_breaks() +const std::vector &worksheet::page_break_columns() const { return d_->column_breaks_; } -const std::vector &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 diff --git a/tests/data/8_minimal.xlsx b/tests/data/8_minimal.xlsx index d8f0f1f632a275a789700af8d5b8abb035deb55a..99d3194a490d9b98f0ce5c6883adaf3961522985 100644 GIT binary patch delta 567 zcmaFOvy_)7z?+#xgn@y9gMle#B99iwm;STiuFY`~6YYL7W=*zWRALJYUmqS8J~@GL zJ5WG^Ne>|)IysSP5ucFP49}}S?cW{-nxeuuS&&(@-UVoY8xWUPa5FHnd}U-{0Nc?! z!8Y%(0Z;4mUm{I>0+zByEZdqFIZoX8;?m5mD?K{ucqVyP{V^)Lxbx15J5%O`WQOCBDG8^GTTV@m$ zozLA}TrZilQ9IH9e`3h{#~sJ5;*7;26~KvnC6(8YqIo8^5X)RvTRcs?Z|kEUU62C{pm48=E~@kWEIMfrSC;i~MZ8 Yirk#g5LO1}q=?BbY>I5pfN~5B0540t+yDRo delta 388 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 EAH*kgLjV8( literal 20982 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 diff --git a/tests/helpers/xml_helper.hpp b/tests/helpers/xml_helper.hpp index 664fcb0e..7c1e8743 100644 --- a/tests/helpers/xml_helper.hpp +++ b/tests/helpers/xml_helper.hpp @@ -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 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 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(stream)), (std::istreambuf_iterator())); 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 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 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 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; } }