begin trying to garbage collect cell formats

This commit is contained in:
Thomas Fussell 2016-11-03 19:26:11 -04:00
parent f9e349ce8d
commit 1474c8ab82
6 changed files with 88 additions and 31 deletions

View File

@ -32,6 +32,7 @@ namespace xlnt {
class alignment; class alignment;
class border; class border;
class cell;
class fill; class fill;
class font; class font;
class number_format; class number_format;

View File

@ -781,7 +781,7 @@ void cell::set_font(const font &font_)
{ {
auto &format = duplicate_format(); auto &format = duplicate_format();
format.font(font_, true); format.font(font_, true);
d_->format_id_ = format.id(); d_->format_id_ = format.id();
} }
void cell::set_number_format(const number_format &number_format_) void cell::set_number_format(const number_format &number_format_)

View File

@ -18,6 +18,18 @@ public:
wb_guess_types.set_guess_types(true); wb_guess_types.set_guess_types(true);
} }
void test_temp()
{
xlnt::workbook wb;
auto ws = wb.get_active_sheet();
auto cell = ws.get_cell("A1");
cell.set_value(3.141592);
cell.set_font(xlnt::font().bold(true));
cell.set_font(xlnt::font().size(20));
wb.save("a.xlsx");
wb.load("a.xlsx");
}
void test_infer_numeric() void test_infer_numeric()
{ {
auto ws = wb_guess_types.create_sheet(); auto ws = wb_guess_types.create_sheet();

View File

@ -29,9 +29,13 @@
#include <detail/format_impl.hpp> #include <detail/format_impl.hpp>
#include <detail/style_impl.hpp> #include <detail/style_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/styles/format.hpp> #include <xlnt/styles/format.hpp>
#include <xlnt/styles/style.hpp> #include <xlnt/styles/style.hpp>
#include <xlnt/utils/exceptions.hpp> #include <xlnt/utils/exceptions.hpp>
#include <xlnt/worksheet/worksheet.hpp>
#include <xlnt/workbook/workbook.hpp>
#include <xlnt/workbook/worksheet_iterator.hpp>
namespace xlnt { namespace xlnt {
namespace detail { namespace detail {
@ -46,41 +50,17 @@ struct stylesheet
{ {
format_impls.push_back(format_impl()); format_impls.push_back(format_impl());
auto &impl = format_impls.back(); auto &impl = format_impls.back();
impl.parent = this; impl.parent = this;
impl.id = format_impls.size() - 1; impl.id = format_impls.size() - 1;
impl.border_id = 0;
impl.fill_id = 0;
impl.font_id = 0;
impl.number_format_id = 0;
formats.push_back(format(&impl)); formats.push_back(format(&impl));
auto &format = formats.back(); auto &format = formats.back();
if (!alignments.empty())
{
format.alignment(alignments.front(), false);
}
if (!borders.empty())
{
format.border(borders.front(), false);
}
if (!fills.empty())
{
format.fill(fills.front(), false);
}
if (!fonts.empty())
{
format.font(fonts.front(), false);
}
if (!number_formats.empty())
{
format.number_format(number_formats.front(), false);
}
if (!protections.empty())
{
format.protection(protections.front(), false);
}
return format; return format;
} }
@ -214,6 +194,58 @@ struct stylesheet
colors.clear(); colors.clear();
} }
format_impl *deduplicate(format_impl *f)
{
std::unordered_map<format_impl *, std::size_t> reference_counts;
for (auto ws : *parent)
{
auto dimension = ws.calculate_dimension();
for (auto row = dimension.get_top_left().get_row(); row <= dimension.get_bottom_right().get_row(); row++)
{
for (auto column = dimension.get_top_left().get_column(); column <= dimension.get_bottom_right().get_column(); column++)
{
if (ws.has_cell(cell_reference(column, row)))
{
auto cell = ws.get_cell(cell_reference(column, row));
if (cell.has_format())
{
reference_counts[formats.at(cell.get_format().id()).d_]++;
}
}
}
}
}
auto result = f;
for (auto &impl : format_impls)
{
if (reference_counts[&impl] == 0 && &impl != f)
{
result = &impl;
break;
}
}
/*
if (result != f)
{
auto impl_iter = std::find_if(format_impls.begin(), format_impls.end(),
[=](const format_impl &impl) { return &impl == f; });
auto index = std::distance(format_impls.begin(), impl_iter);
formats.erase(formats.begin() + index);
format_impls.erase(impl_iter);
}
*/
return f;
}
workbook *parent;
std::list<format_impl> format_impls; std::list<format_impl> format_impls;
std::vector<format> formats; std::vector<format> formats;

View File

@ -123,6 +123,7 @@ void format::font(const xlnt::font &new_font, bool applied)
{ {
font_id(d_->parent->add_font(new_font)); font_id(d_->parent->add_font(new_font));
base_format::font(new_font, applied); base_format::font(new_font, applied);
d_ = d_->parent->deduplicate(d_);
} }
xlnt::number_format &format::number_format() xlnt::number_format &format::number_format()

View File

@ -343,6 +343,10 @@ workbook::workbook()
workbook::workbook(detail::workbook_impl *impl) : d_(impl) workbook::workbook(detail::workbook_impl *impl) : d_(impl)
{ {
if (impl != nullptr)
{
d_->stylesheet_.parent = this;
}
} }
void workbook::register_app_properties_in_manifest() void workbook::register_app_properties_in_manifest()
@ -913,6 +917,8 @@ void swap(workbook &left, workbook &right)
{ {
ws.set_parent(left); ws.set_parent(left);
} }
left.d_->stylesheet_.parent = &left;
} }
if (right.d_ != nullptr) if (right.d_ != nullptr)
@ -921,12 +927,15 @@ void swap(workbook &left, workbook &right)
{ {
ws.set_parent(right); ws.set_parent(right);
} }
right.d_->stylesheet_.parent = &right;
} }
} }
workbook &workbook::operator=(workbook other) workbook &workbook::operator=(workbook other)
{ {
swap(*this, other); swap(*this, other);
d_->stylesheet_.parent = this;
return *this; return *this;
} }
@ -943,6 +952,8 @@ workbook::workbook(const workbook &other) : workbook()
{ {
ws.set_parent(*this); ws.set_parent(*this);
} }
d_->stylesheet_.parent = this;
} }
workbook::~workbook() workbook::~workbook()