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 <lwptools.hxx>
71 #include <memory>
72 
73 const sal_uInt8 LwpIndexManager::MAXOBJECTIDS = 255;
74 
LwpIndexManager()75 LwpIndexManager::LwpIndexManager()
76     : m_nKeyCount(0)
77     , m_nLeafCount(0)
78 {
79     m_TempVec.resize( LwpIndexManager::MAXOBJECTIDS );
80 
81 }
82 
83 /**
84  * @descr   Read all index records, VO_ROOTLEAFOBJINDEX, VO_ROOTOBJINDEX, VO_LEAFOBJINDEX
85  */
Read(LwpSvStream * pStrm)86 void LwpIndexManager::Read(LwpSvStream* pStrm)
87 {
88     //Read index obj
89     LwpObjectHeader ObjHdr;
90     ObjHdr.Read(*pStrm);
91     std::unique_ptr<LwpObjectStream> xObjStrm(new LwpObjectStream(pStrm, ObjHdr.IsCompressed(),
92             static_cast<sal_uInt16>(ObjHdr.GetSize())));
93 
94     if( ObjHdr.GetTag() == VO_ROOTLEAFOBJINDEX )
95     {
96         ReadLeafData(xObjStrm.get());
97         ReadTimeTable(xObjStrm.get());
98         xObjStrm.reset();
99     }
100     else
101     {
102         ReadRootData(xObjStrm.get());
103         xObjStrm.reset();
104 
105         for (sal_uInt16 k = 0; k < m_nLeafCount; k++)
106         {
107             //Read leaf
108             sal_Int64 nPos = m_ChildIndex[k]+LwpSvStream::LWP_STREAM_BASE;
109             sal_Int64 nActualPos = pStrm->Seek(nPos);
110 
111             if (nPos != nActualPos)
112                 throw BadSeek();
113 
114             //Old Code
115             //ReadLeafIndex(pStrm);
116             //New Code
117             ReadObjIndex( pStrm );
118 
119             //Read object in root, these objects are between the leaf objects
120             if(k!=m_nLeafCount-1)
121             {
122                 m_ObjectKeys.push_back(m_RootObjs[k]);
123                 m_nKeyCount ++;
124             }
125         }
126         m_RootObjs.clear();
127     }
128 }
129 
130 /**
131  * @descr   Read data in VO_ROOTOBJINDEX
132  */
ReadRootData(LwpObjectStream * pObjStrm)133 void LwpIndexManager::ReadRootData(LwpObjectStream* pObjStrm)
134 {
135 
136     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
137     m_nLeafCount = KeyCount ? KeyCount + 1 : 0;
138 
139     if (m_nLeafCount > SAL_N_ELEMENTS(m_ChildIndex))
140         throw std::range_error("corrupt RootData");
141 
142     if (KeyCount)
143     {
144         //read object keys
145         LwpKey akey;
146         akey.id.Read(pObjStrm);
147         m_RootObjs.push_back(akey);
148 
149         sal_uInt16 k = 0;
150 
151         for (k = 1; k < KeyCount; k++)
152         {
153             akey.id.ReadCompressed(pObjStrm, m_RootObjs[k-1].id);
154             m_RootObjs.push_back(akey);
155         }
156 
157         for (k = 0; k < KeyCount; k++)
158             m_RootObjs[k].offset = pObjStrm->QuickReaduInt32();
159 
160         //read leaf index offset
161         for (k = 0; k < m_nLeafCount; k++)
162             m_ChildIndex[k] = pObjStrm->QuickReaduInt32();
163     }
164 
165     ReadTimeTable(pObjStrm);
166 
167 }
168 
169 //Add new method to handle ObjIndex data
170 /**
171  * @descr   Read data in VO_OBJINDEX
172  */
ReadObjIndexData(LwpObjectStream * pObjStrm)173 void LwpIndexManager::ReadObjIndexData(LwpObjectStream* pObjStrm)
174 {
175     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
176     sal_uInt16 LeafCount = KeyCount + 1;
177 
178     std::vector<LwpKey> vObjIndexs;
179 
180     if (KeyCount)
181     {
182         LwpKey akey;
183         akey.id.Read(pObjStrm);
184         vObjIndexs.push_back(akey);
185 
186         sal_uInt16 k = 0;
187 
188         for (k = 1; k < KeyCount; k++)
189         {
190             akey.id.ReadCompressed(pObjStrm, vObjIndexs[k-1].id);
191             vObjIndexs.push_back(akey);
192         }
193 
194         for (k = 0; k < KeyCount; k++)
195             vObjIndexs[k].offset = pObjStrm->QuickReaduInt32();
196 
197         for (k = 0; k < LeafCount; k++)
198             m_TempVec.at(k) = pObjStrm->QuickReaduInt32();
199     }
200 
201     for( sal_uInt16 j=0; j<LeafCount; j++ )
202     {
203         sal_Int64 nPos = m_TempVec.at(j) + LwpSvStream::LWP_STREAM_BASE;
204         sal_Int64 nActualPos = pObjStrm->GetStream()->Seek(nPos);
205 
206         if (nPos != nActualPos)
207             throw BadSeek();
208 
209         ReadLeafIndex(pObjStrm->GetStream());
210 
211         if(j!=LeafCount-1)
212         {
213             m_ObjectKeys.push_back(vObjIndexs[j]);
214 
215             m_nKeyCount ++;
216         }
217     }
218 
219     vObjIndexs.clear();
220     m_TempVec.clear();
221 }
222 
223 /**
224  * @descr   Read VO_OBJINDEX
225  */
ReadObjIndex(LwpSvStream * pStrm)226 void LwpIndexManager::ReadObjIndex( LwpSvStream *pStrm )
227 {
228 
229     LwpObjectHeader ObjHdr;
230     ObjHdr.Read(*pStrm);
231     std::unique_ptr<LwpObjectStream> pObjStrm( new LwpObjectStream(pStrm, ObjHdr.IsCompressed(),
232             static_cast<sal_uInt16>(ObjHdr.GetSize()) ) );
233 
234     if( sal_uInt32(VO_OBJINDEX) == ObjHdr.GetTag() )
235     {
236         ReadObjIndexData( pObjStrm.get() );
237     }
238     else if( sal_uInt32(VO_LEAFOBJINDEX) == ObjHdr.GetTag() )
239     {
240         ReadLeafData( pObjStrm.get() );
241     }
242 }
243 
244 /**
245  * @descr   Read VO_LEAFOBJINDEX
246  */
ReadLeafIndex(LwpSvStream * pStrm)247 void LwpIndexManager::ReadLeafIndex( LwpSvStream *pStrm )
248 {
249     LwpObjectHeader ObjHdr;
250     ObjHdr.Read(*pStrm);
251     std::unique_ptr<LwpObjectStream> pObjStrm( new LwpObjectStream(pStrm, ObjHdr.IsCompressed(),
252             static_cast<sal_uInt16>(ObjHdr.GetSize()) ) );
253 
254     ReadLeafData(pObjStrm.get());
255 }
256 /**
257  * @descr   Read data in VO_LEAFOBJINDEX
258  */
ReadLeafData(LwpObjectStream * pObjStrm)259 void LwpIndexManager::ReadLeafData( LwpObjectStream *pObjStrm )
260 {
261     sal_uInt16 KeyCount = pObjStrm->QuickReaduInt16();
262 
263     if(KeyCount)
264     {
265         LwpKey akey;
266         //read object keys: id & offset
267         akey.id.Read(pObjStrm);
268         m_ObjectKeys.push_back(akey);
269 
270         for (sal_uInt16 k = 1; k < KeyCount; k++)
271         {
272             akey.id.ReadCompressed(pObjStrm, m_ObjectKeys.at(m_nKeyCount+k-1).id);
273             m_ObjectKeys.push_back(akey);
274         }
275 
276         for (sal_uInt16 j = 0; j < KeyCount; j++)
277             m_ObjectKeys.at(m_nKeyCount+j).offset = pObjStrm->QuickReaduInt32();
278     }
279     m_nKeyCount += KeyCount;
280 }
281 /**
282  * @descr   Read time table in VO_ROOTLEAFOBJINDEX and VO_ROOTOBJINDEX
283  */
ReadTimeTable(LwpObjectStream * pObjStrm)284 void LwpIndexManager::ReadTimeTable(LwpObjectStream *pObjStrm)
285 {
286     sal_uInt16 nTimeCount = pObjStrm->QuickReaduInt16();
287 
288     for(sal_uInt16 i=0; i<nTimeCount; ++i)
289     {
290         sal_uInt32 atime = pObjStrm->QuickReaduInt32();
291         m_TimeTable.push_back(atime);
292     }
293 }
294 /**
295  * @descr       get object offset per the object id
296  */
GetObjOffset(LwpObjectID objid)297 sal_uInt32 LwpIndexManager::GetObjOffset( LwpObjectID objid )
298 {
299 
300     //sal_uInt16 L, U, M;
301     sal_uInt32 L, U, M;
302 
303     L = 0;
304     U = m_nKeyCount;
305     while (L != U)
306     {
307         M = (L + U) >> 1;
308 
309         if (objid.GetLow() > m_ObjectKeys[M].id.GetLow())
310             L = M + 1;
311         else if (objid.GetLow() < m_ObjectKeys[M].id.GetLow())
312             U = M;
313         else if (objid.GetHigh() > m_ObjectKeys[M].id.GetHigh())
314             L = M + 1;
315         else if (objid.GetHigh() < m_ObjectKeys[M].id.GetHigh())
316             U = M;
317         else
318         {
319             return(m_ObjectKeys[M].offset);
320         }
321     }
322     return BAD_OFFSET;
323 }
324 
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
326