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  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include "db.hxx"
22 
23 #include <cstring>
24 
25 #include <com/sun/star/io/XSeekable.hpp>
26 
27 using namespace com::sun::star::uno;
28 using namespace com::sun::star::io;
29 
30 namespace helpdatafileproxy {
31 
copyToBuffer(const char * pSrcData,int nSize)32 void HDFData::copyToBuffer( const char* pSrcData, int nSize )
33 {
34     m_nSize = nSize;
35     m_pBuffer.reset( new char[m_nSize+1] );
36     memcpy( m_pBuffer.get(), pSrcData, m_nSize );
37     m_pBuffer[m_nSize] = 0;
38 }
39 
40 
41 // Hdf
42 
implReadLenAndData(const char * pData,int & riPos,HDFData & rValue)43 bool Hdf::implReadLenAndData( const char* pData, int& riPos, HDFData& rValue )
44 {
45     bool bSuccess = false;
46 
47     // Read key len
48     const char* pStartPtr = pData + riPos;
49     char* pEndPtr;
50     sal_Int32 nKeyLen = strtol( pStartPtr, &pEndPtr, 16 );
51     if( pEndPtr == pStartPtr )
52         return bSuccess;
53     riPos += (pEndPtr - pStartPtr) + 1;
54 
55     const char* pKeySrc = pData + riPos;
56     rValue.copyToBuffer( pKeySrc, nKeyLen );
57     riPos += nKeyLen + 1;
58 
59     bSuccess = true;
60     return bSuccess;
61 }
62 
createHashMap(bool bOptimizeForPerformance)63 void Hdf::createHashMap( bool bOptimizeForPerformance )
64 {
65     releaseHashMap();
66     if( bOptimizeForPerformance )
67     {
68         if( m_pStringToDataMap != nullptr )
69             return;
70         m_pStringToDataMap.reset(new StringToDataMap);
71     }
72     else
73     {
74         if( m_pStringToValPosMap != nullptr )
75             return;
76         m_pStringToValPosMap.reset(new StringToValPosMap);
77     }
78 
79     Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
80     if( xIn.is() )
81     {
82         Sequence< sal_Int8 > aData;
83         sal_Int32 nSize = m_xSFA->getSize( m_aFileURL );
84         sal_Int32 nRead = xIn->readBytes( aData, nSize );
85 
86         const char* pData = reinterpret_cast<const char*>(aData.getConstArray());
87         int iPos = 0;
88         while( iPos < nRead )
89         {
90             HDFData aDBKey;
91             if( !implReadLenAndData( pData, iPos, aDBKey ) )
92                 break;
93 
94             OString aOKeyStr = aDBKey.getData();
95 
96             // Read val len
97             const char* pStartPtr = pData + iPos;
98             char* pEndPtr;
99             sal_Int32 nValLen = strtol( pStartPtr, &pEndPtr, 16 );
100             if( pEndPtr == pStartPtr )
101                 break;
102 
103             iPos += (pEndPtr - pStartPtr) + 1;
104 
105             if( bOptimizeForPerformance )
106             {
107                 const char* pValSrc = pData + iPos;
108                 OString aValStr( pValSrc, nValLen );
109                 (*m_pStringToDataMap)[aOKeyStr] = aValStr;
110             }
111             else
112             {
113                 // store value start position
114                 (*m_pStringToValPosMap)[aOKeyStr] = std::pair<int,int>( iPos, nValLen );
115             }
116             iPos += nValLen + 1;
117         }
118 
119         xIn->closeInput();
120     }
121 }
122 
releaseHashMap()123 void Hdf::releaseHashMap()
124 {
125     m_pStringToDataMap.reset();
126     m_pStringToValPosMap.reset();
127 }
128 
129 
~Hdf()130 Hdf::~Hdf()
131 {
132 }
133 
getValueForKey(const OString & rKey,HDFData & rValue)134 bool Hdf::getValueForKey( const OString& rKey, HDFData& rValue )
135 {
136     bool bSuccess = false;
137     if( !m_xSFA.is() )
138         return bSuccess;
139 
140     try
141     {
142 
143     if( m_pStringToDataMap == nullptr && m_pStringToValPosMap == nullptr )
144     {
145         createHashMap( false/*bOptimizeForPerformance*/ );
146     }
147 
148     if( m_pStringToValPosMap != nullptr )
149     {
150         StringToValPosMap::const_iterator it = m_pStringToValPosMap->find( rKey );
151         if( it != m_pStringToValPosMap->end() )
152         {
153             const std::pair<int,int>& rValPair = it->second;
154             int iValuePos = rValPair.first;
155             int nValueLen = rValPair.second;
156 
157             Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
158             if( xIn.is() )
159             {
160                 Reference< XSeekable > xXSeekable( xIn, UNO_QUERY );
161                 if( xXSeekable.is() )
162                 {
163                     xXSeekable->seek( iValuePos );
164 
165                     Sequence< sal_Int8 > aData;
166                     sal_Int32 nRead = xIn->readBytes( aData, nValueLen );
167                     if( nRead == nValueLen )
168                     {
169                         const char* pData = reinterpret_cast<const sal_Char*>(aData.getConstArray());
170                         rValue.copyToBuffer( pData, nValueLen );
171                         bSuccess = true;
172                     }
173                 }
174                 xIn->closeInput();
175             }
176         }
177     }
178 
179     else if( m_pStringToDataMap != nullptr )
180     {
181         StringToDataMap::const_iterator it = m_pStringToDataMap->find( rKey );
182         if( it != m_pStringToDataMap->end() )
183         {
184             const OString& rValueStr = it->second;
185             int nValueLen = rValueStr.getLength();
186             const char* pData = rValueStr.getStr();
187             rValue.copyToBuffer( pData, nValueLen );
188             bSuccess = true;
189         }
190     }
191 
192     }
193     catch( Exception & )
194     {
195         bSuccess = false;
196     }
197 
198     return bSuccess;
199 }
200 
startIteration()201 bool Hdf::startIteration()
202 {
203     bool bSuccess = false;
204 
205     sal_Int32 nSize = m_xSFA->getSize( m_aFileURL );
206 
207     Reference< XInputStream > xIn = m_xSFA->openFileRead( m_aFileURL );
208     if( xIn.is() )
209     {
210         m_nItRead = xIn->readBytes( m_aItData, nSize );
211         if( m_nItRead == nSize )
212         {
213             bSuccess = true;
214             m_pItData = reinterpret_cast<const char*>(m_aItData.getConstArray());
215             m_iItPos = 0;
216         }
217         else
218         {
219             stopIteration();
220         }
221     }
222 
223     return bSuccess;
224 }
225 
getNextKeyAndValue(HDFData & rKey,HDFData & rValue)226 bool Hdf::getNextKeyAndValue( HDFData& rKey, HDFData& rValue )
227 {
228     bool bSuccess = false;
229 
230     if( m_iItPos < m_nItRead )
231     {
232         if( implReadLenAndData( m_pItData, m_iItPos, rKey ) )
233         {
234             if( implReadLenAndData( m_pItData, m_iItPos, rValue ) )
235                 bSuccess = true;
236         }
237     }
238 
239     return bSuccess;
240 }
241 
stopIteration()242 void Hdf::stopIteration()
243 {
244     m_aItData = Sequence<sal_Int8>();
245     m_pItData = nullptr;
246     m_nItRead = -1;
247     m_iItPos = -1;
248 }
249 
250 } // end of namespace helpdatafileproxy
251 
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
253