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 border;
class cell;
class fill;
class font;
class number_format;

View File

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

View File

@ -18,6 +18,18 @@ public:
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()
{
auto ws = wb_guess_types.create_sheet();

View File

@ -29,9 +29,13 @@
#include <detail/format_impl.hpp>
#include <detail/style_impl.hpp>
#include <xlnt/cell/cell.hpp>
#include <xlnt/styles/format.hpp>
#include <xlnt/styles/style.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 detail {
@ -46,41 +50,17 @@ struct stylesheet
{
format_impls.push_back(format_impl());
auto &impl = format_impls.back();
impl.parent = this;
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));
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;
}
@ -214,6 +194,58 @@ struct stylesheet
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::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));
base_format::font(new_font, applied);
d_ = d_->parent->deduplicate(d_);
}
xlnt::number_format &format::number_format()

View File

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