1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10 #include <mtvelements.hxx>
11 #include <document.hxx>
12 #include <cellvalue.hxx>
13 #include <column.hxx>
14 #include <table.hxx>
15
16 #include <sstream>
17
18 namespace sc {
19
CellStoreEvent()20 CellStoreEvent::CellStoreEvent() : mpCol(nullptr) {}
21
CellStoreEvent(ScColumn * pCol)22 CellStoreEvent::CellStoreEvent(ScColumn* pCol) : mpCol(pCol) {}
23
element_block_acquired(const mdds::mtv::base_element_block * block)24 void CellStoreEvent::element_block_acquired(const mdds::mtv::base_element_block* block)
25 {
26 if (!mpCol)
27 return;
28
29 switch (mdds::mtv::get_block_type(*block))
30 {
31 case sc::element_type_formula:
32 ++mpCol->mnBlkCountFormula;
33 break;
34 default:
35 ;
36 }
37 }
38
element_block_released(const mdds::mtv::base_element_block * block)39 void CellStoreEvent::element_block_released(const mdds::mtv::base_element_block* block)
40 {
41 if (!mpCol)
42 return;
43
44 switch (mdds::mtv::get_block_type(*block))
45 {
46 case sc::element_type_formula:
47 --mpCol->mnBlkCountFormula;
48 break;
49 default:
50 ;
51 }
52 }
53
ColumnBlockPositionSet(ScDocument & rDoc)54 ColumnBlockPositionSet::ColumnBlockPositionSet(ScDocument& rDoc) : mrDoc(rDoc) {}
55
getBlockPosition(SCTAB nTab,SCCOL nCol)56 ColumnBlockPosition* ColumnBlockPositionSet::getBlockPosition(SCTAB nTab, SCCOL nCol)
57 {
58 osl::MutexGuard aGuard(&maMtxTables);
59
60 TablesType::iterator itTab = maTables.find(nTab);
61 if (itTab == maTables.end())
62 {
63 std::pair<TablesType::iterator,bool> r =
64 maTables.emplace(nTab, ColumnsType());
65 if (!r.second)
66 // insertion failed.
67 return nullptr;
68
69 itTab = r.first;
70 }
71
72 ColumnsType& rCols = itTab->second;
73
74 ColumnsType::iterator it = rCols.find(nCol);
75 if (it != rCols.end())
76 // Block position for this column has already been fetched.
77 return &it->second;
78
79 std::pair<ColumnsType::iterator,bool> r =
80 rCols.emplace(nCol, ColumnBlockPosition());
81
82 if (!r.second)
83 // insertion failed.
84 return nullptr;
85
86 it = r.first;
87
88 if (!mrDoc.InitColumnBlockPosition(it->second, nTab, nCol))
89 return nullptr;
90
91 return &it->second;
92 }
93
clear()94 void ColumnBlockPositionSet::clear()
95 {
96 osl::MutexGuard aGuard(&maMtxTables);
97 maTables.clear();
98 }
99
100 struct TableColumnBlockPositionSet::Impl
101 {
102 typedef std::unordered_map<SCCOL, ColumnBlockPosition> ColumnsType;
103
104 ScTable* mpTab;
105 ColumnsType maColumns;
106
Implsc::TableColumnBlockPositionSet::Impl107 Impl() : mpTab(nullptr) {}
108 };
109
TableColumnBlockPositionSet(ScDocument & rDoc,SCTAB nTab)110 TableColumnBlockPositionSet::TableColumnBlockPositionSet( ScDocument& rDoc, SCTAB nTab ) :
111 mpImpl(std::make_unique<Impl>())
112 {
113 mpImpl->mpTab = rDoc.FetchTable(nTab);
114
115 if (!mpImpl->mpTab)
116 {
117 std::ostringstream os;
118 os << "Passed table index " << nTab << " is invalid.";
119 throw std::invalid_argument(os.str());
120 }
121 }
122
TableColumnBlockPositionSet(TableColumnBlockPositionSet && rOther)123 TableColumnBlockPositionSet::TableColumnBlockPositionSet( TableColumnBlockPositionSet&& rOther ) noexcept :
124 mpImpl(std::move(rOther.mpImpl)) {}
125
~TableColumnBlockPositionSet()126 TableColumnBlockPositionSet::~TableColumnBlockPositionSet() {}
127
getBlockPosition(SCCOL nCol)128 ColumnBlockPosition* TableColumnBlockPositionSet::getBlockPosition( SCCOL nCol )
129 {
130 using ColumnsType = Impl::ColumnsType;
131
132 ColumnsType::iterator it = mpImpl->maColumns.find(nCol);
133
134 if (it != mpImpl->maColumns.end())
135 // Block position for this column has already been fetched.
136 return &it->second;
137
138 std::pair<ColumnsType::iterator,bool> r =
139 mpImpl->maColumns.emplace(nCol, ColumnBlockPosition());
140
141 if (!r.second)
142 // insertion failed.
143 return nullptr;
144
145 it = r.first;
146
147 if (!mpImpl->mpTab->InitColumnBlockPosition(it->second, nCol))
148 return nullptr;
149
150 return &it->second;
151 }
152
invalidate()153 void TableColumnBlockPositionSet::invalidate()
154 {
155 mpImpl->maColumns.clear();
156 }
157
toRefCell(const sc::CellStoreType::const_iterator & itPos,size_t nOffset)158 ScRefCellValue toRefCell( const sc::CellStoreType::const_iterator& itPos, size_t nOffset )
159 {
160 switch (itPos->type)
161 {
162 case sc::element_type_numeric:
163 // Numeric cell
164 return ScRefCellValue(sc::numeric_block::at(*itPos->data, nOffset));
165 case sc::element_type_string:
166 // String cell
167 return ScRefCellValue(&sc::string_block::at(*itPos->data, nOffset));
168 case sc::element_type_edittext:
169 // Edit cell
170 return ScRefCellValue(sc::edittext_block::at(*itPos->data, nOffset));
171 case sc::element_type_formula:
172 // Formula cell
173 return ScRefCellValue(sc::formula_block::at(*itPos->data, nOffset));
174 default:
175 ;
176 }
177
178 return ScRefCellValue();
179 }
180
181 }
182
183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
184