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