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