1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <algorithm>
25 #include <iterator>
26 
27 #ifndef INCLUDED_DOCTOK_EXCEPTIONS
28 #include <resourcemodel/exceptions.hxx>
29 #endif
30 #include <WW8PieceTableImpl.hxx>
31 #include <WW8Clx.hxx>
32 
33 namespace writerfilter {
34 namespace doctok
35 {
36 using namespace ::std;
37 
operator <<(ostream & o,const WW8PieceTable & rPieceTable)38 ostream & operator << (ostream & o, const WW8PieceTable & rPieceTable)
39 {
40     rPieceTable.dump(o);
41 
42     return o;
43 }
44 
WW8PieceTableImpl(WW8Stream & rStream,sal_uInt32 nOffset,sal_uInt32 nCount)45 WW8PieceTableImpl::WW8PieceTableImpl(WW8Stream & rStream,
46                                      sal_uInt32 nOffset,
47                                      sal_uInt32 nCount)
48 {
49     WW8Clx aClx(rStream, nOffset, nCount);
50 
51     sal_uInt32 nPieceCount = aClx.getPieceCount();
52 
53     if (nPieceCount > 0)
54     {
55         for (sal_uInt32 n = 0; n < nPieceCount;  n++)
56         {
57             Cp aCp(aClx.getCp(n));
58             Fc aFc(aClx.getFc(n), aClx.isComplexFc(n));
59 
60             CpAndFc aCpAndFc(aCp, aFc, PROP_DOC);
61 
62             mEntries.push_back(aCpAndFc);
63         }
64 
65         CpAndFc aBack = mEntries.back();
66         Cp aCp(aClx.getCp(aClx.getPieceCount()));
67         Fc aFc(aBack.getFc() + (aCp - aBack.getCp()));
68 
69         CpAndFc aCpAndFc(aCp, aFc, PROP_DOC);
70 
71         mEntries.push_back(aCpAndFc);
72     }
73 }
74 
getCount() const75 sal_uInt32 WW8PieceTableImpl::getCount() const
76 {
77     return mEntries.size();
78 }
79 
80 WW8PieceTableImpl::tEntries::const_iterator
findCp(const Cp & rCp) const81 WW8PieceTableImpl::findCp(const Cp & rCp) const
82 {
83     tEntries::const_iterator aResult = mEntries.end();
84     tEntries::const_iterator aEnd = mEntries.end();
85 
86     for (tEntries::const_iterator aIt = mEntries.begin(); aIt != aEnd;
87          aIt++)
88     {
89         if (aIt->getCp() <= rCp)
90         {
91             aResult = aIt;
92 
93             //break;
94         }
95     }
96 
97     return aResult;
98 }
99 
100 WW8PieceTableImpl::tEntries::const_iterator
findFc(const Fc & rFc) const101 WW8PieceTableImpl::findFc(const Fc & rFc) const
102 {
103     tEntries::const_iterator aResult = mEntries.end();
104     tEntries::const_iterator aEnd = mEntries.end();
105 
106     if (mEntries.size() > 0)
107     {
108         if (rFc < mEntries.begin()->getFc())
109             aResult = mEntries.begin();
110         else
111         {
112             for (tEntries::const_iterator aIt = mEntries.begin();
113                  aIt != aEnd; aIt++)
114             {
115                 if (aIt->getFc() <= rFc)
116                 {
117                     tEntries::const_iterator aItNext = aIt;
118                     aItNext++;
119 
120                     if (aItNext != aEnd)
121                     {
122                         sal_uInt32 nOffset = rFc.get() - aIt->getFc().get();
123                         sal_uInt32 nLength = aItNext->getCp() - aIt->getCp();
124 
125                         if (! aIt->isComplex())
126                             nLength *= 2;
127 
128                         if (nOffset < nLength)
129                         {
130                             aResult = aIt;
131 
132                             break;
133                         }
134                     }
135 
136                 }
137             }
138         }
139     }
140 
141     return aResult;
142 }
143 
getFirstCp() const144 Cp WW8PieceTableImpl::getFirstCp() const
145 {
146     Cp aResult;
147 
148     if (getCount() > 0)
149         aResult = getCp(0);
150     else
151         throw ExceptionNotFound("WW8PieceTableImpl::getFirstCp");
152 
153     return aResult;
154 }
155 
getFirstFc() const156 Fc WW8PieceTableImpl::getFirstFc() const
157 {
158     Fc aResult;
159 
160     if (getCount() > 0)
161         aResult = getFc(0);
162     else
163         throw ExceptionNotFound(" WW8PieceTableImpl::getFirstFc");
164 
165     return aResult;
166 }
167 
getLastCp() const168 Cp WW8PieceTableImpl::getLastCp() const
169 {
170     Cp aResult;
171 
172     if (getCount() > 0)
173         aResult = getCp(getCount() - 1);
174     else
175         throw ExceptionNotFound("WW8PieceTableImpl::getLastCp");
176 
177     return aResult;
178 }
179 
getLastFc() const180 Fc WW8PieceTableImpl::getLastFc() const
181 {
182     Fc aResult;
183 
184     if (getCount() > 0)
185         aResult = getFc(getCount() - 1);
186     else
187         throw ExceptionNotFound("WW8PieceTableImpl::getLastFc");
188 
189     return aResult;
190 }
191 
getCp(sal_uInt32 nIndex) const192 Cp WW8PieceTableImpl::getCp(sal_uInt32 nIndex) const
193 {
194     return mEntries[nIndex].getCp();
195 }
196 
getFc(sal_uInt32 nIndex) const197 Fc WW8PieceTableImpl::getFc(sal_uInt32 nIndex) const
198 {
199     return mEntries[nIndex].getFc();
200 }
201 
fc2cp(const Fc & rFc) const202 Cp WW8PieceTableImpl::fc2cp(const Fc & rFc) const
203 {
204     Cp cpResult;
205 
206     if (mEntries.size() > 0)
207     {
208         Fc aFc;
209 
210         if (rFc < mEntries.begin()->getFc())
211             aFc = mEntries.begin()->getFc();
212         else
213             aFc = rFc;
214 
215         tEntries::const_iterator aIt = findFc(aFc);
216 
217         if (aIt != mEntries.end())
218         {
219             cpResult = aIt->getCp() + (aFc - aIt->getFc());
220         }
221         else
222             throw ExceptionNotFound("WW8PieceTableImpl::fc2cp: " + aFc.toString());
223     }
224 
225     return cpResult;
226 }
227 
cp2fc(const Cp & rCp) const228 Fc WW8PieceTableImpl::cp2fc(const Cp & rCp) const
229 {
230     Fc aResult;
231 
232     Cp2FcHashMap_t::iterator aItCp = mCp2FcCache.find(rCp);
233 
234     if (aItCp == mCp2FcCache.end())
235     {
236         tEntries::const_iterator aIt = findCp(rCp);
237 
238         if (aIt != mEntries.end())
239         {
240             aResult = aIt->getFc() + (rCp - aIt->getCp());
241             mCp2FcCache[rCp] = aResult;
242         }
243         else
244             throw ExceptionNotFound
245                 ("WW8PieceTableImpl::cp2fc: " + rCp.toString());
246     }
247     else
248         aResult = mCp2FcCache[rCp];
249 
250     return aResult;
251 }
252 
isComplex(const Cp & rCp) const253 bool WW8PieceTableImpl::isComplex(const Cp & rCp) const
254 {
255     bool bResult = false;
256 
257     tEntries::const_iterator aIt = findCp(rCp);
258 
259     if (aIt != mEntries.end())
260         bResult = aIt->isComplex();
261 
262     return bResult;
263 }
264 
isComplex(const Fc & rFc) const265 bool WW8PieceTableImpl::isComplex(const Fc & rFc) const
266 {
267     bool bResult = false;
268 
269     tEntries::const_iterator aIt = findFc(rFc);
270 
271     if (aIt != mEntries.end())
272         bResult = aIt->isComplex();
273 
274     return bResult;
275 }
276 
createCpAndFc(const Cp & rCp,PropertyType eType) const277 CpAndFc WW8PieceTableImpl::createCpAndFc
278 (const Cp & rCp, PropertyType eType) const
279 {
280     return CpAndFc(rCp, cp2fc(rCp), eType);
281 }
282 
createCpAndFc(const Fc & rFc,PropertyType eType) const283 CpAndFc WW8PieceTableImpl::createCpAndFc
284 (const Fc & rFc, PropertyType eType) const
285 {
286     return CpAndFc(fc2cp(rFc), rFc, eType);
287 }
288 
dump(ostream & o) const289 void WW8PieceTableImpl::dump(ostream & o) const
290 {
291     o << "<piecetable>" << endl;
292     copy(mEntries.begin(), mEntries.end(), ostream_iterator<CpAndFc>(o, "\n"));
293     o << "</piecetable>" << endl;
294 }
295 }}
296