1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  *  The Contents of this file are made available subject to the terms of
5  *  either of the following licenses
6  *
7  *         - GNU Lesser General Public License Version 2.1
8  *         - Sun Industry Standards Source License Version 1.1
9  *
10  *  Sun Microsystems Inc., October, 2000
11  *
12  *  GNU Lesser General Public License Version 2.1
13  *  =============================================
14  *  Copyright 2000 by Sun Microsystems, Inc.
15  *  901 San Antonio Road, Palo Alto, CA 94303, USA
16  *
17  *  This library is free software; you can redistribute it and/or
18  *  modify it under the terms of the GNU Lesser General Public
19  *  License version 2.1, as published by the Free Software Foundation.
20  *
21  *  This library is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  *  Lesser General Public License for more details.
25  *
26  *  You should have received a copy of the GNU Lesser General Public
27  *  License along with this library; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29  *  MA  02111-1307  USA
30  *
31  *
32  *  Sun Industry Standards Source License Version 1.1
33  *  =================================================
34  *  The contents of this file are subject to the Sun Industry Standards
35  *  Source License Version 1.1 (the "License"); You may not use this file
36  *  except in compliance with the License. You may obtain a copy of the
37  *  License at http://www.openoffice.org/license.html.
38  *
39  *  Software provided under this License is provided on an "AS IS" basis,
40  *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41  *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42  *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43  *  See the License for the specific provisions governing your rights and
44  *  obligations concerning the Software.
45  *
46  *  The Initial Developer of the Original Code is: IBM Corporation
47  *
48  *  Copyright: 2008 by IBM Corporation
49  *
50  *  All Rights Reserved.
51  *
52  *  Contributor(s): _______________________________________
53  *
54  *
55  ************************************************************************/
56 
57 /**********************************************************************************************************************
58  * @file
59  *   index manager implementation
60  *  Three record types are related with index information, and two ways are used.
61 *  1. VO_ROOTOBJINDEX works with one or more VO_LEAFOBJINDEX records to
62 *  provide the map of all object ids and their offsets.
63 *  VO_ROOTOBJINDEX includes k (object id, offset) and timetable which is used to map index to actual low id
64  *  2. VO_ROOTLEAFOBJINDEX is used when the file is so small that the number of objects is less than 256(?)
65  *  VO_ROOTLEAFOBJINDEX contains directly the (object id, offset) map and time table.
66 
67 **********************************************************************************************************************/
68 
69 #include <lwpidxmgr.hxx>
70 #include <lwpobjhdr.hxx>
71 #include <lwptools.hxx>
72 #include <memory>
73 
74 const sal_uInt8 LwpIndexManager::MAXOBJECTIDS = 255;
75 
LwpIndexManager()76 LwpIndexManager::LwpIndexManager()
77     : m_nKeyCount(0)
78     , m_nLeafCount(0)
79 {
80     m_TempVec.resize( LwpIndexManager::MAXOBJECTIDS );
81 
82 }
83 
84 /**
85  * @descr   Read all index records, VO_ROOTLEAFOBJINDEX, VO_ROOTOBJINDEX, VO_LEAFOBJINDEX
86  */
Read(LwpSvStream * pStrm)87 void LwpIndexManager::Read(LwpSvStream* pStrm)
88 {
89     //Read index obj
90     LwpObjectHeader ObjHdr;
91     ObjHdr.Read(*pStrm);
92     std::unique_ptr<LwpObjectStream> xObjStrm(new LwpObjectStream(pStrm, ObjHdr.IsCompressed(),
93             static_cast<sal_uInt16>(ObjHdr.GetSize())));
94 
95     if( ObjHdr.GetTag() == VO_ROOTLEAFOBJINDEX )
96     {
97         ReadLeafData(xObjStrm.get());
98         ReadTimeTable(xObjStrm.get());
99         xObjStrm.reset();
100     }
101     else
102     {
103         ReadRootData(xObjStrm.get());
104         xObjStrm.reset();
105 
106         for (sal_uInt16 k = 0; k < m_nLeafCount; k++)
107         {
108             //Read leaf
109             sal_Int64 nPos = m_ChildIndex[k]+LwpSvStream::LWP_STREAM_BASE;
110             sal_Int64 nActualPos = pStrm->Seek(nPos);
111 
112             if (nPos != nActualPos)
113                 throw BadSeek();
114 
115             //Old Code
116             //ReadLeafIndex(pStrm);
117             //New Code
118             ReadObjIndex( pStrm );
119 
120             //Read object in root, these objects are between the leaf objects
121             if(k!=m_nLeafCount-1)
122             {
123                 m_ObjectKeys.push_back(m_RootObjs[k]);
124                 m_nKeyCount ++;
125             }
126         }
127         m_RootObjs.clear();
128     }
129 }
130 
131 /**
132  * @descr   Read data in VO_ROOTOBJINDEX
133  */
ReadRootData(LwpObjectStream * pObjStrm)134 void LwpIndexManager::ReadRootData(LwpObjectStream* pObjStrm)
135 {
136 
137     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
138     m_nLeafCount = KeyCount ? KeyCount + 1 : 0;
139 
140     if (m_nLeafCount > SAL_N_ELEMENTS(m_ChildIndex))
141         throw std::range_error("corrupt RootData");
142 
143     if (KeyCount)
144     {
145         //read object keys
146         LwpKey akey;
147         akey.id.Read(pObjStrm);
148         m_RootObjs.push_back(akey);
149 
150         sal_uInt16 k = 0;
151 
152         for (k = 1; k < KeyCount; k++)
153         {
154             akey.id.ReadCompressed(pObjStrm, m_RootObjs[k-1].id);
155             m_RootObjs.push_back(akey);
156         }
157 
158         for (k = 0; k < KeyCount; k++)
159             m_RootObjs[k].offset = pObjStrm->QuickReaduInt32();
160 
161         //read leaf index offset
162         for (k = 0; k < m_nLeafCount; k++)
163             m_ChildIndex[k] = pObjStrm->QuickReaduInt32();
164     }
165 
166     ReadTimeTable(pObjStrm);
167 
168 }
169 
170 //Add new method to handle ObjIndex data
171 /**
172  * @descr   Read data in VO_OBJINDEX
173  */
ReadObjIndexData(LwpObjectStream * pObjStrm)174 void LwpIndexManager::ReadObjIndexData(LwpObjectStream* pObjStrm)
175 {
176     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
177     sal_uInt16 LeafCount = KeyCount + 1;
178 
179     std::vector<LwpKey> vObjIndexs;
180 
181     if (KeyCount)
182     {
183         LwpKey akey;
184         akey.id.Read(pObjStrm);
185         vObjIndexs.push_back(akey);
186 
187         sal_uInt16 k = 0;
188 
189         for (k = 1; k < KeyCount; k++)
190         {
191             akey.id.ReadCompressed(pObjStrm, vObjIndexs[k-1].id);
192             vObjIndexs.push_back(akey);
193         }
194 
195         for (k = 0; k < KeyCount; k++)
196             vObjIndexs[k].offset = pObjStrm->QuickReaduInt32();
197 
198         for (k = 0; k < LeafCount; k++)
199             m_TempVec.at(k) = pObjStrm->QuickReaduInt32();
200     }
201 
202     for( sal_uInt16 j=0; j<LeafCount; j++ )
203     {
204         sal_Int64 nPos = m_TempVec.at(j) + LwpSvStream::LWP_STREAM_BASE;
205         sal_Int64 nActualPos = pObjStrm->GetStream()->Seek(nPos);
206 
207         if (nPos != nActualPos)
208             throw BadSeek();
209 
210         ReadLeafIndex(pObjStrm->GetStream());
211 
212         if(j!=LeafCount-1)
213         {
214             m_ObjectKeys.push_back(vObjIndexs[j]);
215 
216             m_nKeyCount ++;
217         }
218     }
219 
220     vObjIndexs.clear();
221     m_TempVec.clear();
222 }
223 
224 /**
225  * @descr   Read VO_OBJINDEX
226  */
ReadObjIndex(LwpSvStream * pStrm)227 void LwpIndexManager::ReadObjIndex( LwpSvStream *pStrm )
228 {
229 
230     LwpObjectHeader ObjHdr;
231     ObjHdr.Read(*pStrm);
232     LwpObjectStream aObjStrm(pStrm, ObjHdr.IsCompressed(),
233             static_cast<sal_uInt16>(ObjHdr.GetSize()) );
234 
235     if( sal_uInt32(VO_OBJINDEX) == ObjHdr.GetTag() )
236     {
237         ReadObjIndexData( &aObjStrm );
238     }
239     else if( sal_uInt32(VO_LEAFOBJINDEX) == ObjHdr.GetTag() )
240     {
241         ReadLeafData( &aObjStrm );
242     }
243 }
244 
245 /**
246  * @descr   Read VO_LEAFOBJINDEX
247  */
ReadLeafIndex(LwpSvStream * pStrm)248 void LwpIndexManager::ReadLeafIndex( LwpSvStream *pStrm )
249 {
250     LwpObjectHeader ObjHdr;
251     ObjHdr.Read(*pStrm);
252     LwpObjectStream aObjStrm( pStrm, ObjHdr.IsCompressed(),
253             static_cast<sal_uInt16>(ObjHdr.GetSize()) );
254 
255     ReadLeafData(&aObjStrm);
256 }
257 /**
258  * @descr   Read data in VO_LEAFOBJINDEX
259  */
ReadLeafData(LwpObjectStream * pObjStrm)260 void LwpIndexManager::ReadLeafData( LwpObjectStream *pObjStrm )
261 {
262     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
263 
264     if(KeyCount)
265     {
266         LwpKey akey;
267         //read object keys: id & offset
268         akey.id.Read(pObjStrm);
269         m_ObjectKeys.push_back(akey);
270 
271         for (sal_uInt16 k = 1; k < KeyCount; k++)
272         {
273             akey.id.ReadCompressed(pObjStrm, m_ObjectKeys.at(m_nKeyCount+k-1).id);
274             m_ObjectKeys.push_back(akey);
275         }
276 
277         for (sal_uInt16 j = 0; j < KeyCount; j++)
278             m_ObjectKeys.at(m_nKeyCount+j).offset = pObjStrm->QuickReaduInt32();
279     }
280     m_nKeyCount += KeyCount;
281 }
282 /**
283  * @descr   Read time table in VO_ROOTLEAFOBJINDEX and VO_ROOTOBJINDEX
284  */
ReadTimeTable(LwpObjectStream * pObjStrm)285 void LwpIndexManager::ReadTimeTable(LwpObjectStream *pObjStrm)
286 {
287     sal_uInt16 nTimeCount = pObjStrm->QuickReaduInt16();
288 
289     for(sal_uInt16 i=0; i<nTimeCount; ++i)
290     {
291         sal_uInt32 atime = pObjStrm->QuickReaduInt32();
292         m_TimeTable.push_back(atime);
293     }
294 }
295 /**
296  * @descr       get object offset per the object id
297  */
GetObjOffset(LwpObjectID objid)298 sal_uInt32 LwpIndexManager::GetObjOffset( LwpObjectID objid )
299 {
300 
301     //sal_uInt16 L, U, M;
302     sal_uInt32 L, U, M;
303 
304     L = 0;
305     U = m_nKeyCount;
306     while (L != U)
307     {
308         M = (L + U) >> 1;
309 
310         if (objid.GetLow() > m_ObjectKeys[M].id.GetLow())
311             L = M + 1;
312         else if (objid.GetLow() < m_ObjectKeys[M].id.GetLow())
313             U = M;
314         else if (objid.GetHigh() > m_ObjectKeys[M].id.GetHigh())
315             L = M + 1;
316         else if (objid.GetHigh() < m_ObjectKeys[M].id.GetHigh())
317             U = M;
318         else
319         {
320             return(m_ObjectKeys[M].offset);
321         }
322     }
323     return BAD_OFFSET;
324 }
325 
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
327