Line data Source code
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 : #include <svtools/svparser.hxx>
21 : #include <tools/stream.hxx>
22 : #include <tools/debug.hxx>
23 : #include <rtl/textcvt.h>
24 : #include <rtl/tencinfo.h>
25 :
26 : #include <boost/ptr_container/ptr_vector.hpp>
27 :
28 : // structure to store the actuel data
29 17 : struct SvParser_Impl
30 : {
31 : OUString aToken; // gescanntes Token
32 : sal_uLong nFilePos; // actual position in stream
33 : sal_uLong nlLineNr; // actual line number
34 : sal_uLong nlLinePos; // actual column number
35 : long nTokenValue; // extra value (RTF)
36 : bool bTokenHasValue; // indicates whether nTokenValue is valid
37 : int nToken; // actual Token
38 : sal_Unicode nNextCh; // actual character
39 : int nSaveToken; // the token from Continue
40 :
41 : rtl_TextToUnicodeConverter hConv;
42 : rtl_TextToUnicodeContext hContext;
43 :
44 17 : SvParser_Impl()
45 : : nFilePos(0)
46 : , nlLineNr(0)
47 : , nlLinePos(0)
48 : , nTokenValue(0)
49 : , bTokenHasValue(false)
50 : , nToken(0)
51 : , nNextCh(0)
52 : , nSaveToken(0)
53 : , hConv( 0 )
54 17 : , hContext( reinterpret_cast<rtl_TextToUnicodeContext>(1) )
55 : {
56 17 : }
57 :
58 : };
59 :
60 :
61 :
62 : // Construktor
63 17 : SvParser::SvParser( SvStream& rIn, sal_uInt8 nStackSize )
64 : : rInput( rIn )
65 : , nlLineNr( 1 )
66 : , nlLinePos( 1 )
67 : , pImplData( 0 )
68 : , nTokenValue( 0 )
69 : , bTokenHasValue( false )
70 : , eState( SVPAR_NOTSTARTED )
71 : , eSrcEnc( RTL_TEXTENCODING_DONTKNOW )
72 : , nNextChPos(0)
73 : , nNextCh(0)
74 : , bDownloadingFile(false)
75 : , bUCS2BSrcEnc(false)
76 : , bSwitchToUCS2(false)
77 : , bRTF_InTextRead(false)
78 : , nTokenStackSize( nStackSize )
79 17 : , nTokenStackPos( 0 )
80 : {
81 17 : eState = SVPAR_NOTSTARTED;
82 17 : if( nTokenStackSize < 3 )
83 0 : nTokenStackSize = 3;
84 17 : pTokenStack = new TokenStackType[ nTokenStackSize ];
85 17 : pTokenStackPos = pTokenStack;
86 17 : }
87 :
88 34 : SvParser::~SvParser()
89 : {
90 17 : if( pImplData && pImplData->hConv )
91 : {
92 : rtl_destroyTextToUnicodeContext( pImplData->hConv,
93 17 : pImplData->hContext );
94 17 : rtl_destroyTextToUnicodeConverter( pImplData->hConv );
95 : }
96 :
97 17 : delete pImplData;
98 :
99 17 : delete [] pTokenStack;
100 17 : }
101 :
102 12 : void SvParser::ClearTxtConvContext()
103 : {
104 12 : if( pImplData && pImplData->hConv )
105 12 : rtl_resetTextToUnicodeContext( pImplData->hConv, pImplData->hContext );
106 12 : }
107 :
108 29 : void SvParser::SetSrcEncoding( rtl_TextEncoding eEnc )
109 : {
110 :
111 29 : if( eEnc != eSrcEnc )
112 : {
113 18 : if( pImplData && pImplData->hConv )
114 : {
115 : rtl_destroyTextToUnicodeContext( pImplData->hConv,
116 1 : pImplData->hContext );
117 1 : rtl_destroyTextToUnicodeConverter( pImplData->hConv );
118 1 : pImplData->hConv = 0;
119 1 : pImplData->hContext = reinterpret_cast<rtl_TextToUnicodeContext>(1);
120 : }
121 :
122 18 : if( rtl_isOctetTextEncoding(eEnc) ||
123 : RTL_TEXTENCODING_UCS2 == eEnc )
124 : {
125 18 : eSrcEnc = eEnc;
126 18 : if( !pImplData )
127 17 : pImplData = new SvParser_Impl;
128 18 : pImplData->hConv = rtl_createTextToUnicodeConverter( eSrcEnc );
129 : DBG_ASSERT( pImplData->hConv,
130 : "SvParser::SetSrcEncoding: no converter for source encoding" );
131 18 : if( !pImplData->hConv )
132 0 : eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
133 : else
134 : pImplData->hContext =
135 18 : rtl_createTextToUnicodeContext( pImplData->hConv );
136 : }
137 : else
138 : {
139 : DBG_ASSERT( false,
140 : "SvParser::SetSrcEncoding: invalid source encoding" );
141 0 : eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
142 : }
143 : }
144 29 : }
145 :
146 0 : void SvParser::RereadLookahead()
147 : {
148 0 : rInput.Seek(nNextChPos);
149 0 : nNextCh = GetNextChar();
150 0 : }
151 :
152 109911 : sal_Unicode SvParser::GetNextChar()
153 : {
154 109911 : sal_Unicode c = 0U;
155 :
156 : // When reading muliple bytes, we don't have to care about the file
157 : // position when we run inti the pending state. The file position is
158 : // maintained by SaveState/RestoreState.
159 : bool bErr;
160 109911 : if( bSwitchToUCS2 && 0 == rInput.Tell() )
161 : {
162 : unsigned char c1, c2;
163 17 : bool bSeekBack = true;
164 :
165 17 : rInput.ReadUChar( c1 );
166 17 : bErr = rInput.IsEof() || rInput.GetError();
167 17 : if( !bErr )
168 : {
169 17 : if( 0xff == c1 || 0xfe == c1 )
170 : {
171 0 : rInput.ReadUChar( c2 );
172 0 : bErr = rInput.IsEof() || rInput.GetError();
173 0 : if( !bErr )
174 : {
175 0 : if( 0xfe == c1 && 0xff == c2 )
176 : {
177 0 : eSrcEnc = RTL_TEXTENCODING_UCS2;
178 0 : bUCS2BSrcEnc = true;
179 0 : bSeekBack = false;
180 : }
181 0 : else if( 0xff == c1 && 0xfe == c2 )
182 : {
183 0 : eSrcEnc = RTL_TEXTENCODING_UCS2;
184 0 : bUCS2BSrcEnc = false;
185 0 : bSeekBack = false;
186 : }
187 : }
188 : }
189 17 : else if( 0xef == c1 || 0xbb == c1 ) // check for UTF-8 BOM
190 : {
191 0 : rInput.ReadUChar( c2 );
192 0 : bErr = rInput.IsEof() || rInput.GetError();
193 0 : if( !bErr )
194 : {
195 0 : if( ( 0xef == c1 && 0xbb == c2 ) || ( 0xbb == c1 && 0xef == c2 ) )
196 : {
197 0 : unsigned char c3(0);
198 0 : rInput.ReadUChar( c3 );
199 0 : bErr = rInput.IsEof() || rInput.GetError();
200 0 : if( !bErr && ( 0xbf == c3 ) )
201 : {
202 0 : eSrcEnc = RTL_TEXTENCODING_UTF8;
203 0 : bSeekBack = false;
204 : }
205 : }
206 : }
207 : }
208 : }
209 17 : if( bSeekBack )
210 17 : rInput.Seek( 0 );
211 :
212 17 : bSwitchToUCS2 = false;
213 : }
214 :
215 109911 : nNextChPos = rInput.Tell();
216 :
217 109911 : if( RTL_TEXTENCODING_UCS2 == eSrcEnc )
218 : {
219 0 : sal_Unicode cUC = USHRT_MAX;
220 : unsigned char c1, c2;
221 :
222 0 : rInput.ReadUChar( c1 ).ReadUChar( c2 );
223 0 : if( 2 == rInput.Tell() &&
224 0 : !(rInput.IsEof() || rInput.GetError()) &&
225 0 : ( (bUCS2BSrcEnc && 0xfe == c1 && 0xff == c2) ||
226 0 : (!bUCS2BSrcEnc && 0xff == c1 && 0xfe == c2) ) )
227 0 : rInput.ReadUChar( c1 ).ReadUChar( c2 );
228 :
229 0 : bErr = rInput.IsEof() || rInput.GetError();
230 0 : if( !bErr )
231 : {
232 0 : if( bUCS2BSrcEnc )
233 0 : cUC = (sal_Unicode(c1) << 8) | c2;
234 : else
235 0 : cUC = (sal_Unicode(c2) << 8) | c1;
236 : }
237 :
238 0 : if( !bErr )
239 : {
240 0 : c = cUC;
241 : }
242 : }
243 : else
244 : {
245 109911 : sal_Size nChars = 0;
246 109911 : do
247 : {
248 : sal_Char c1; // signed, that's the text converter expects
249 109911 : rInput.ReadChar( c1 );
250 109911 : bErr = rInput.IsEof() || rInput.GetError();
251 109911 : if( !bErr )
252 : {
253 109885 : if (
254 219770 : RTL_TEXTENCODING_DONTKNOW == eSrcEnc ||
255 109885 : RTL_TEXTENCODING_SYMBOL == eSrcEnc
256 : )
257 : {
258 : // no convserion shall take place
259 0 : c = (sal_Unicode)c1;
260 0 : nChars = 1;
261 : }
262 : else
263 : {
264 : assert(pImplData && pImplData->hConv && "no text converter!");
265 :
266 : sal_Unicode cUC;
267 109885 : sal_uInt32 nInfo = 0;
268 : sal_Size nCvtBytes;
269 : nChars = rtl_convertTextToUnicode(
270 : pImplData->hConv, pImplData->hContext,
271 : &c1, 1, &cUC, 1,
272 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
273 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
274 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
275 109885 : &nInfo, &nCvtBytes);
276 109885 : if( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
277 : {
278 : // The conversion wasn't successful because we haven't
279 : // read enough characters.
280 2 : if( pImplData->hContext != reinterpret_cast<rtl_TextToUnicodeContext>(1) )
281 : {
282 6 : while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
283 : {
284 2 : rInput.ReadChar( c1 );
285 2 : bErr = rInput.IsEof() || rInput.GetError();
286 2 : if( bErr )
287 0 : break;
288 :
289 : nChars = rtl_convertTextToUnicode(
290 : pImplData->hConv, pImplData->hContext,
291 : &c1, 1, &cUC, 1,
292 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
293 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
294 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
295 2 : &nInfo, &nCvtBytes);
296 : }
297 2 : if( !bErr )
298 : {
299 2 : if( 1 == nChars && 0 == nInfo )
300 : {
301 0 : c = cUC;
302 : }
303 2 : else if( 0 != nChars || 0 != nInfo )
304 : {
305 : DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
306 : "source buffer is to small" );
307 : DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
308 : "there is a conversion error" );
309 : DBG_ASSERT( 0 == nChars,
310 : "there is a converted character, but an error" );
311 : // There are still errors, but nothing we can
312 : // do
313 2 : c = (sal_Unicode)'?';
314 2 : nChars = 1;
315 : }
316 : }
317 : }
318 : else
319 : {
320 : sal_Char sBuffer[10];
321 0 : sBuffer[0] = c1;
322 0 : sal_uInt16 nLen = 1;
323 0 : while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 &&
324 : nLen < 10 )
325 : {
326 0 : rInput.ReadChar( c1 );
327 0 : bErr = rInput.IsEof() || rInput.GetError();
328 0 : if( bErr )
329 0 : break;
330 :
331 0 : sBuffer[nLen++] = c1;
332 : nChars = rtl_convertTextToUnicode(
333 : pImplData->hConv, 0, sBuffer, nLen, &cUC, 1,
334 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
335 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
336 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
337 0 : &nInfo, &nCvtBytes);
338 : }
339 0 : if( !bErr )
340 : {
341 0 : if( 1 == nChars && 0 == nInfo )
342 : {
343 : DBG_ASSERT( nCvtBytes == nLen,
344 : "no all bytes have been converted!" );
345 0 : c = cUC;
346 : }
347 : else
348 : {
349 : DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
350 : "source buffer is to small" );
351 : DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
352 : "there is a conversion error" );
353 : DBG_ASSERT( 0 == nChars,
354 : "there is a converted character, but an error" );
355 :
356 : // There are still errors, so we use the first
357 : // character and restart after that.
358 0 : c = (sal_Unicode)sBuffer[0];
359 0 : rInput.SeekRel( -(nLen-1) );
360 0 : nChars = 1;
361 : }
362 : }
363 : }
364 : }
365 109883 : else if( 1 == nChars && 0 == nInfo )
366 : {
367 : // The conversion was successful
368 : DBG_ASSERT( nCvtBytes == 1,
369 : "no all bytes have been converted!" );
370 109856 : c = cUC;
371 : }
372 27 : else if( 0 != nChars || 0 != nInfo )
373 : {
374 : DBG_ASSERT( 0 == nChars,
375 : "there is a converted character, but an error" );
376 : DBG_ASSERT( 0 != nInfo,
377 : "there is no converted character and no error" );
378 : // #73398#: If the character could not be converted,
379 : // because a conversion is not available, do no conversion at all.
380 27 : c = (sal_Unicode)c1;
381 27 : nChars = 1;
382 :
383 : }
384 : }
385 : }
386 : }
387 26 : while( 0 == nChars && !bErr );
388 : }
389 109911 : if( bErr )
390 : {
391 26 : if( ERRCODE_IO_PENDING == rInput.GetError() )
392 : {
393 0 : eState = SVPAR_PENDING;
394 0 : return c;
395 : }
396 : else
397 26 : return sal_Unicode(EOF);
398 : }
399 :
400 109885 : if( c == '\n' )
401 : {
402 1942 : IncLineNr();
403 1942 : SetLinePos( 1L );
404 : }
405 : else
406 107943 : IncLinePos();
407 109885 : return c;
408 : }
409 :
410 3513 : int SvParser::GetNextToken()
411 : {
412 3513 : int nRet = 0;
413 :
414 3513 : if( !nTokenStackPos )
415 : {
416 3493 : aToken.clear(); // empty token buffer
417 3493 : nTokenValue = -1; // marker for no value read
418 3493 : bTokenHasValue = false;
419 :
420 3493 : nRet = _GetNextToken();
421 3493 : if( SVPAR_PENDING == eState )
422 0 : return nRet;
423 : }
424 :
425 3513 : ++pTokenStackPos;
426 3513 : if( pTokenStackPos == pTokenStack + nTokenStackSize )
427 1160 : pTokenStackPos = pTokenStack;
428 :
429 : // pop from stack ??
430 3513 : if( nTokenStackPos )
431 : {
432 20 : --nTokenStackPos;
433 20 : nTokenValue = pTokenStackPos->nTokenValue;
434 20 : bTokenHasValue = pTokenStackPos->bTokenHasValue;
435 20 : aToken = pTokenStackPos->sToken;
436 20 : nRet = pTokenStackPos->nTokenId;
437 : }
438 : // no, now push actual value on stack
439 3493 : else if( SVPAR_WORKING == eState )
440 : {
441 3476 : pTokenStackPos->sToken = aToken;
442 3476 : pTokenStackPos->nTokenValue = nTokenValue;
443 3476 : pTokenStackPos->bTokenHasValue = bTokenHasValue;
444 3476 : pTokenStackPos->nTokenId = nRet;
445 : }
446 17 : else if( SVPAR_ACCEPTED != eState && SVPAR_PENDING != eState )
447 0 : eState = SVPAR_ERROR; // an error occurred
448 :
449 3513 : return nRet;
450 : }
451 :
452 20 : int SvParser::SkipToken( short nCnt ) // "skip" n Tokens backward
453 : {
454 20 : pTokenStackPos = GetStackPtr( nCnt );
455 20 : short nTmp = nTokenStackPos - nCnt;
456 20 : if( nTmp < 0 )
457 0 : nTmp = 0;
458 20 : else if( nTmp > nTokenStackSize )
459 0 : nTmp = nTokenStackSize;
460 20 : nTokenStackPos = sal_uInt8(nTmp);
461 :
462 : // restore values
463 20 : aToken = pTokenStackPos->sToken;
464 20 : nTokenValue = pTokenStackPos->nTokenValue;
465 20 : bTokenHasValue = pTokenStackPos->bTokenHasValue;
466 :
467 20 : return pTokenStackPos->nTokenId;
468 : }
469 :
470 20 : SvParser::TokenStackType* SvParser::GetStackPtr( short nCnt )
471 : {
472 20 : sal_uInt8 nAktPos = sal_uInt8(pTokenStackPos - pTokenStack );
473 20 : if( nCnt > 0 )
474 : {
475 0 : if( nCnt >= nTokenStackSize )
476 0 : nCnt = (nTokenStackSize-1);
477 0 : if( nAktPos + nCnt < nTokenStackSize )
478 0 : nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
479 : else
480 : nAktPos = sal::static_int_cast< sal_uInt8 >(
481 0 : nAktPos + (nCnt - nTokenStackSize));
482 : }
483 20 : else if( nCnt < 0 )
484 : {
485 20 : if( -nCnt >= nTokenStackSize )
486 0 : nCnt = -nTokenStackSize+1;
487 20 : if( -nCnt <= nAktPos )
488 19 : nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
489 : else
490 : nAktPos = sal::static_int_cast< sal_uInt8 >(
491 1 : nAktPos + (nCnt + nTokenStackSize));
492 : }
493 20 : return pTokenStack + nAktPos;
494 : }
495 :
496 : // is called for each token which is recognised by CallParser
497 0 : void SvParser::NextToken( int )
498 : {
499 0 : }
500 :
501 :
502 : // to read asynchronous from SvStream
503 :
504 0 : int SvParser::GetSaveToken() const
505 : {
506 0 : return pImplData ? pImplData->nSaveToken : 0;
507 : }
508 :
509 7587 : void SvParser::SaveState( int nToken )
510 : {
511 : // save actual status
512 7587 : if( !pImplData )
513 : {
514 0 : pImplData = new SvParser_Impl;
515 0 : pImplData->nSaveToken = 0;
516 : }
517 :
518 7587 : pImplData->nFilePos = rInput.Tell();
519 7587 : pImplData->nToken = nToken;
520 :
521 7587 : pImplData->aToken = aToken;
522 7587 : pImplData->nlLineNr = nlLineNr;
523 7587 : pImplData->nlLinePos = nlLinePos;
524 7587 : pImplData->nTokenValue= nTokenValue;
525 7587 : pImplData->bTokenHasValue = bTokenHasValue;
526 7587 : pImplData->nNextCh = nNextCh;
527 7587 : }
528 :
529 0 : void SvParser::RestoreState()
530 : {
531 : // restore old status
532 0 : if( pImplData )
533 : {
534 0 : if( ERRCODE_IO_PENDING == rInput.GetError() )
535 0 : rInput.ResetError();
536 0 : aToken = pImplData->aToken;
537 0 : nlLineNr = pImplData->nlLineNr;
538 0 : nlLinePos = pImplData->nlLinePos;
539 0 : nTokenValue= pImplData->nTokenValue;
540 0 : bTokenHasValue=pImplData->bTokenHasValue;
541 0 : nNextCh = pImplData->nNextCh;
542 :
543 0 : pImplData->nSaveToken = pImplData->nToken;
544 :
545 0 : rInput.Seek( pImplData->nFilePos );
546 : }
547 0 : }
548 :
549 0 : void SvParser::Continue( int )
550 : {
551 0 : }
552 :
553 32 : void SvParser::BuildWhichTable( std::vector<sal_uInt16> &rWhichMap,
554 : sal_uInt16 *pWhichIds,
555 : sal_uInt16 nWhichIds )
556 : {
557 : sal_uInt16 aNewRange[2];
558 :
559 592 : for( sal_uInt16 nCnt = 0; nCnt < nWhichIds; ++nCnt, ++pWhichIds )
560 560 : if( *pWhichIds )
561 : {
562 560 : aNewRange[0] = aNewRange[1] = *pWhichIds;
563 560 : bool bIns = true;
564 :
565 : // search position
566 3904 : for ( sal_uInt16 nOfs = 0; rWhichMap[nOfs]; nOfs += 2 )
567 : {
568 3744 : if( *pWhichIds < rWhichMap[nOfs] - 1 )
569 : {
570 : // new range before
571 144 : rWhichMap.insert( rWhichMap.begin() + nOfs, aNewRange, aNewRange + 2 );
572 144 : bIns = false;
573 144 : break;
574 : }
575 3600 : else if( *pWhichIds == rWhichMap[nOfs] - 1 )
576 : {
577 : // extend range downwards
578 48 : rWhichMap[nOfs] = *pWhichIds;
579 48 : bIns = false;
580 48 : break;
581 : }
582 3552 : else if( *pWhichIds == rWhichMap[nOfs+1] + 1 )
583 : {
584 208 : if( rWhichMap[nOfs+2] != 0 && rWhichMap[nOfs+2] == *pWhichIds + 1 )
585 : {
586 : // merge with next field
587 96 : rWhichMap[nOfs+1] = rWhichMap[nOfs+3];
588 192 : rWhichMap.erase( rWhichMap.begin() + nOfs + 2,
589 288 : rWhichMap.begin() + nOfs + 4 );
590 : }
591 : else
592 : // extend range upwards
593 112 : rWhichMap[nOfs+1] = *pWhichIds;
594 208 : bIns = false;
595 208 : break;
596 : }
597 : }
598 :
599 : // append range
600 560 : if( bIns )
601 : {
602 320 : rWhichMap.insert( rWhichMap.begin() + rWhichMap.size() - 1,
603 480 : aNewRange, aNewRange + 2 );
604 : }
605 : }
606 32 : }
607 :
608 :
609 0 : IMPL_LINK_NOARG( SvParser, NewDataRead )
610 : {
611 0 : switch( eState )
612 : {
613 : case SVPAR_PENDING:
614 : // if file is loaded we are not allowed to continue
615 : // instead should ignore the call.
616 0 : if( IsDownloadingFile() )
617 0 : break;
618 :
619 0 : eState = SVPAR_WORKING;
620 0 : RestoreState();
621 :
622 0 : Continue( pImplData->nToken );
623 :
624 0 : if( ERRCODE_IO_PENDING == rInput.GetError() )
625 0 : rInput.ResetError();
626 :
627 0 : if( SVPAR_PENDING != eState )
628 0 : ReleaseRef(); // ready otherwise!
629 0 : break;
630 :
631 : case SVPAR_WAITFORDATA:
632 0 : eState = SVPAR_WORKING;
633 0 : break;
634 :
635 : case SVPAR_NOTSTARTED:
636 : case SVPAR_WORKING:
637 0 : break;
638 :
639 : default:
640 0 : ReleaseRef(); // ready otherwise!
641 0 : break;
642 : }
643 :
644 0 : return 0;
645 : }
646 :
647 : /*========================================================================
648 : *
649 : * SvKeyValueIterator.
650 : *
651 : *======================================================================*/
652 :
653 : typedef boost::ptr_vector<SvKeyValue> SvKeyValueList_Impl;
654 :
655 5896 : struct SvKeyValueIterator::Impl
656 : {
657 : SvKeyValueList_Impl maList;
658 : sal_uInt16 mnPos;
659 :
660 5928 : Impl() : mnPos(0) {}
661 : };
662 :
663 5928 : SvKeyValueIterator::SvKeyValueIterator() : mpImpl(new Impl) {}
664 :
665 14740 : SvKeyValueIterator::~SvKeyValueIterator()
666 : {
667 5896 : delete mpImpl;
668 8844 : }
669 :
670 2996 : bool SvKeyValueIterator::GetFirst (SvKeyValue &rKeyVal)
671 : {
672 2996 : mpImpl->mnPos = mpImpl->maList.size();
673 2996 : return GetNext (rKeyVal);
674 : }
675 :
676 5999 : bool SvKeyValueIterator::GetNext (SvKeyValue &rKeyVal)
677 : {
678 5999 : if (mpImpl->mnPos > 0)
679 : {
680 3003 : rKeyVal = mpImpl->maList[--mpImpl->mnPos];
681 3003 : return true;
682 : }
683 : else
684 : {
685 : // Nothing to do.
686 2996 : return false;
687 : }
688 : }
689 :
690 2960 : void SvKeyValueIterator::Append (const SvKeyValue &rKeyVal)
691 : {
692 2960 : mpImpl->maList.push_back(new SvKeyValue(rKeyVal));
693 2960 : }
694 :
695 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|