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 <stdio.h>
21 : #include <svtools/svparser.hxx>
22 : #include <tools/stream.hxx>
23 : #include <tools/debug.hxx>
24 : #include <rtl/textcvt.h>
25 : #include <rtl/tencinfo.h>
26 :
27 : // Struktur, um sich die akt. Daten zumerken
28 1 : struct SvParser_Impl
29 : {
30 : String aToken; // gescanntes Token
31 : sal_uLong nFilePos; // akt. Position im Stream
32 : sal_uLong nlLineNr; // akt. Zeilen Nummer
33 : sal_uLong nlLinePos; // akt. Spalten Nummer
34 : long nTokenValue; // zusaetzlicher Wert (RTF)
35 : sal_Bool bTokenHasValue; // indicates whether nTokenValue is valid
36 : int nToken; // akt. Token
37 : sal_Unicode nNextCh; // akt. Zeichen
38 :
39 : int nSaveToken; // das Token vom Continue
40 :
41 : rtl_TextToUnicodeConverter hConv;
42 : rtl_TextToUnicodeContext hContext;
43 :
44 1 : SvParser_Impl() :
45 1 : nSaveToken(0), hConv( 0 ), hContext( (rtl_TextToUnicodeContext)1 )
46 : {
47 1 : }
48 :
49 : };
50 :
51 :
52 :
53 : // Konstruktor
54 1 : SvParser::SvParser( SvStream& rIn, sal_uInt8 nStackSize )
55 : : rInput( rIn )
56 : , nlLineNr( 1 )
57 : , nlLinePos( 1 )
58 : , pImplData( 0 )
59 : , nTokenValue( 0 )
60 : , bTokenHasValue( false )
61 : , eState( SVPAR_NOTSTARTED )
62 : , eSrcEnc( RTL_TEXTENCODING_DONTKNOW )
63 : , bDownloadingFile( sal_False )
64 : , nTokenStackSize( nStackSize )
65 1 : , nTokenStackPos( 0 )
66 : {
67 1 : bUCS2BSrcEnc = bSwitchToUCS2 = sal_False;
68 1 : eState = SVPAR_NOTSTARTED;
69 1 : if( nTokenStackSize < 3 )
70 0 : nTokenStackSize = 3;
71 1 : pTokenStack = new TokenStackType[ nTokenStackSize ];
72 1 : pTokenStackPos = pTokenStack;
73 1 : }
74 :
75 2 : SvParser::~SvParser()
76 : {
77 1 : if( pImplData && pImplData->hConv )
78 : {
79 : rtl_destroyTextToUnicodeContext( pImplData->hConv,
80 1 : pImplData->hContext );
81 1 : rtl_destroyTextToUnicodeConverter( pImplData->hConv );
82 : }
83 :
84 1 : delete pImplData;
85 :
86 1 : delete [] pTokenStack;
87 1 : }
88 :
89 0 : void SvParser::ClearTxtConvContext()
90 : {
91 0 : if( pImplData && pImplData->hConv )
92 0 : rtl_resetTextToUnicodeContext( pImplData->hConv, pImplData->hContext );
93 0 : }
94 :
95 2 : void SvParser::SetSrcEncoding( rtl_TextEncoding eEnc )
96 : {
97 :
98 2 : if( eEnc != eSrcEnc )
99 : {
100 2 : if( pImplData && pImplData->hConv )
101 : {
102 : rtl_destroyTextToUnicodeContext( pImplData->hConv,
103 1 : pImplData->hContext );
104 1 : rtl_destroyTextToUnicodeConverter( pImplData->hConv );
105 1 : pImplData->hConv = 0;
106 1 : pImplData->hContext = (rtl_TextToUnicodeContext )1;
107 : }
108 :
109 2 : if( rtl_isOctetTextEncoding(eEnc) ||
110 : RTL_TEXTENCODING_UCS2 == eEnc )
111 : {
112 2 : eSrcEnc = eEnc;
113 2 : if( !pImplData )
114 1 : pImplData = new SvParser_Impl;
115 2 : pImplData->hConv = rtl_createTextToUnicodeConverter( eSrcEnc );
116 : DBG_ASSERT( pImplData->hConv,
117 : "SvParser::SetSrcEncoding: no converter for source encoding" );
118 2 : if( !pImplData->hConv )
119 0 : eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
120 : else
121 : pImplData->hContext =
122 2 : rtl_createTextToUnicodeContext( pImplData->hConv );
123 : }
124 : else
125 : {
126 : DBG_ASSERT( !this,
127 : "SvParser::SetSrcEncoding: invalid source encoding" );
128 0 : eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
129 : }
130 : }
131 2 : }
132 :
133 0 : void SvParser::RereadLookahead()
134 : {
135 0 : rInput.Seek(nNextChPos);
136 0 : nNextCh = GetNextChar();
137 0 : }
138 :
139 229 : sal_Unicode SvParser::GetNextChar()
140 : {
141 229 : sal_Unicode c = 0U;
142 :
143 : // When reading muliple bytes, we don't have to care about the file
144 : // position when we run inti the pending state. The file position is
145 : // maintained by SaveState/RestoreState.
146 : sal_Bool bErr;
147 229 : if( bSwitchToUCS2 && 0 == rInput.Tell() )
148 : {
149 : sal_uChar c1, c2;
150 1 : sal_Bool bSeekBack = sal_True;
151 :
152 1 : rInput >> c1;
153 1 : bErr = rInput.IsEof() || rInput.GetError();
154 1 : if( !bErr )
155 : {
156 1 : if( 0xff == c1 || 0xfe == c1 )
157 : {
158 0 : rInput >> c2;
159 0 : bErr = rInput.IsEof() || rInput.GetError();
160 0 : if( !bErr )
161 : {
162 0 : if( 0xfe == c1 && 0xff == c2 )
163 : {
164 0 : eSrcEnc = RTL_TEXTENCODING_UCS2;
165 0 : bUCS2BSrcEnc = sal_True;
166 0 : bSeekBack = sal_False;
167 : }
168 0 : else if( 0xff == c1 && 0xfe == c2 )
169 : {
170 0 : eSrcEnc = RTL_TEXTENCODING_UCS2;
171 0 : bUCS2BSrcEnc = sal_False;
172 0 : bSeekBack = sal_False;
173 : }
174 : }
175 : }
176 : }
177 1 : if( bSeekBack )
178 1 : rInput.Seek( 0 );
179 :
180 1 : bSwitchToUCS2 = sal_False;
181 : }
182 :
183 229 : nNextChPos = rInput.Tell();
184 :
185 229 : if( RTL_TEXTENCODING_UCS2 == eSrcEnc )
186 : {
187 0 : sal_Unicode cUC = USHRT_MAX;
188 : sal_uChar c1, c2;
189 :
190 0 : rInput >> c1 >> c2;
191 0 : if( 2 == rInput.Tell() &&
192 0 : !(rInput.IsEof() || rInput.GetError()) &&
193 : ( (bUCS2BSrcEnc && 0xfe == c1 && 0xff == c2) ||
194 0 : (!bUCS2BSrcEnc && 0xff == c1 && 0xfe == c2) ) )
195 0 : rInput >> c1 >> c2;
196 :
197 0 : bErr = rInput.IsEof() || rInput.GetError();
198 0 : if( !bErr )
199 : {
200 0 : if( bUCS2BSrcEnc )
201 0 : cUC = (sal_Unicode(c1) << 8) | c2;
202 : else
203 0 : cUC = (sal_Unicode(c2) << 8) | c1;
204 : }
205 :
206 0 : if( !bErr )
207 : {
208 0 : c = cUC;
209 : }
210 : }
211 : else
212 : {
213 229 : sal_Size nChars = 0;
214 229 : do
215 : {
216 : sal_Char c1; // signed, that's the text converter expects
217 229 : rInput >> c1;
218 229 : bErr = rInput.IsEof() || rInput.GetError();
219 229 : if( !bErr )
220 : {
221 227 : if (
222 : RTL_TEXTENCODING_DONTKNOW == eSrcEnc ||
223 : RTL_TEXTENCODING_SYMBOL == eSrcEnc
224 : )
225 : {
226 : // no convserion shall take place
227 0 : c = (sal_Unicode)c1;
228 0 : nChars = 1;
229 : }
230 : else
231 : {
232 : DBG_ASSERT( pImplData && pImplData->hConv,
233 : "no text converter!" );
234 :
235 : sal_Unicode cUC;
236 227 : sal_uInt32 nInfo = 0;
237 : sal_Size nCvtBytes;
238 : nChars = rtl_convertTextToUnicode(
239 : pImplData->hConv, pImplData->hContext,
240 : &c1, 1, &cUC, 1,
241 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
242 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
243 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
244 227 : &nInfo, &nCvtBytes);
245 227 : if( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
246 : {
247 : // The conversion wasn't successfull because we haven't
248 : // read enough characters.
249 0 : if( pImplData->hContext != (rtl_TextToUnicodeContext)1 )
250 : {
251 0 : while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
252 : {
253 0 : rInput >> c1;
254 0 : bErr = rInput.IsEof() || rInput.GetError();
255 0 : if( bErr )
256 0 : break;
257 :
258 : nChars = rtl_convertTextToUnicode(
259 : pImplData->hConv, pImplData->hContext,
260 : &c1, 1, &cUC, 1,
261 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
262 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
263 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
264 0 : &nInfo, &nCvtBytes);
265 : }
266 0 : if( !bErr )
267 : {
268 0 : if( 1 == nChars && 0 == nInfo )
269 : {
270 0 : c = cUC;
271 : }
272 0 : else if( 0 != nChars || 0 != nInfo )
273 : {
274 : DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
275 : "source buffer is to small" );
276 : DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
277 : "there is a conversion error" );
278 : DBG_ASSERT( 0 == nChars,
279 : "there is a converted character, but an error" );
280 : // There are still errors, but nothing we can
281 : // do
282 0 : c = (sal_Unicode)'?';
283 0 : nChars = 1;
284 : }
285 : }
286 : }
287 : else
288 : {
289 : sal_Char sBuffer[10];
290 0 : sBuffer[0] = c1;
291 0 : sal_uInt16 nLen = 1;
292 0 : while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 &&
293 : nLen < 10 )
294 : {
295 0 : rInput >> c1;
296 0 : bErr = rInput.IsEof() || rInput.GetError();
297 0 : if( bErr )
298 0 : break;
299 :
300 0 : sBuffer[nLen++] = c1;
301 : nChars = rtl_convertTextToUnicode(
302 : pImplData->hConv, 0, sBuffer, nLen, &cUC, 1,
303 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
304 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
305 : RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
306 0 : &nInfo, &nCvtBytes);
307 : }
308 0 : if( !bErr )
309 : {
310 0 : if( 1 == nChars && 0 == nInfo )
311 : {
312 : DBG_ASSERT( nCvtBytes == nLen,
313 : "no all bytes have been converted!" );
314 0 : c = cUC;
315 : }
316 : else
317 : {
318 : DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
319 : "source buffer is to small" );
320 : DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
321 : "there is a conversion error" );
322 : DBG_ASSERT( 0 == nChars,
323 : "there is a converted character, but an error" );
324 :
325 : // There are still errors, so we use the first
326 : // character and restart after that.
327 0 : c = (sal_Unicode)sBuffer[0];
328 0 : rInput.SeekRel( -(nLen-1) );
329 0 : nChars = 1;
330 : }
331 : }
332 : }
333 : }
334 227 : else if( 1 == nChars && 0 == nInfo )
335 : {
336 : // The conversion was successfull
337 : DBG_ASSERT( nCvtBytes == 1,
338 : "no all bytes have been converted!" );
339 227 : c = cUC;
340 : }
341 0 : else if( 0 != nChars || 0 != nInfo )
342 : {
343 : DBG_ASSERT( 0 == nChars,
344 : "there is a converted character, but an error" );
345 : DBG_ASSERT( 0 != nInfo,
346 : "there is no converted character and no error" );
347 : // #73398#: If the character could not be converted,
348 : // because a conversion is not available, do no conversion at all.
349 0 : c = (sal_Unicode)c1;
350 0 : nChars = 1;
351 :
352 : }
353 : }
354 : }
355 : }
356 : while( 0 == nChars && !bErr );
357 : }
358 229 : if( bErr )
359 : {
360 2 : if( ERRCODE_IO_PENDING == rInput.GetError() )
361 : {
362 0 : eState = SVPAR_PENDING;
363 0 : return c;
364 : }
365 : else
366 2 : return sal_Unicode(EOF);
367 : }
368 :
369 227 : if( c == '\n' )
370 : {
371 8 : IncLineNr();
372 8 : SetLinePos( 1L );
373 : }
374 : else
375 219 : IncLinePos();
376 227 : return c;
377 : }
378 :
379 36 : int SvParser::GetNextToken()
380 : {
381 36 : int nRet = 0;
382 :
383 36 : if( !nTokenStackPos )
384 : {
385 36 : aToken.Erase(); // Token-Buffer loeschen
386 36 : nTokenValue = -1; // Kennzeichen fuer kein Value gelesen
387 36 : bTokenHasValue = false;
388 :
389 36 : nRet = _GetNextToken();
390 36 : if( SVPAR_PENDING == eState )
391 0 : return nRet;
392 : }
393 :
394 36 : ++pTokenStackPos;
395 36 : if( pTokenStackPos == pTokenStack + nTokenStackSize )
396 12 : pTokenStackPos = pTokenStack;
397 :
398 : // vom Stack holen ??
399 36 : if( nTokenStackPos )
400 : {
401 0 : --nTokenStackPos;
402 0 : nTokenValue = pTokenStackPos->nTokenValue;
403 0 : bTokenHasValue = pTokenStackPos->bTokenHasValue;
404 0 : aToken = pTokenStackPos->sToken;
405 0 : nRet = pTokenStackPos->nTokenId;
406 : }
407 : // nein, dann das aktuelle auf den Stack
408 36 : else if( SVPAR_WORKING == eState )
409 : {
410 35 : pTokenStackPos->sToken = aToken;
411 35 : pTokenStackPos->nTokenValue = nTokenValue;
412 35 : pTokenStackPos->bTokenHasValue = bTokenHasValue;
413 35 : pTokenStackPos->nTokenId = nRet;
414 : }
415 1 : else if( SVPAR_ACCEPTED != eState && SVPAR_PENDING != eState )
416 0 : eState = SVPAR_ERROR; // irgend ein Fehler
417 :
418 36 : return nRet;
419 : }
420 :
421 0 : int SvParser::SkipToken( short nCnt ) // n Tokens zurueck "skippen"
422 : {
423 0 : pTokenStackPos = GetStackPtr( nCnt );
424 0 : short nTmp = nTokenStackPos - nCnt;
425 0 : if( nTmp < 0 )
426 0 : nTmp = 0;
427 0 : else if( nTmp > nTokenStackSize )
428 0 : nTmp = nTokenStackSize;
429 0 : nTokenStackPos = sal_uInt8(nTmp);
430 :
431 : // und die Werte zurueck
432 0 : aToken = pTokenStackPos->sToken;
433 0 : nTokenValue = pTokenStackPos->nTokenValue;
434 0 : bTokenHasValue = pTokenStackPos->bTokenHasValue;
435 :
436 0 : return pTokenStackPos->nTokenId;
437 : }
438 :
439 0 : SvParser::TokenStackType* SvParser::GetStackPtr( short nCnt )
440 : {
441 0 : sal_uInt8 nAktPos = sal_uInt8(pTokenStackPos - pTokenStack );
442 0 : if( nCnt > 0 )
443 : {
444 0 : if( nCnt >= nTokenStackSize )
445 0 : nCnt = (nTokenStackSize-1);
446 0 : if( nAktPos + nCnt < nTokenStackSize )
447 0 : nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
448 : else
449 : nAktPos = sal::static_int_cast< sal_uInt8 >(
450 0 : nAktPos + (nCnt - nTokenStackSize));
451 : }
452 0 : else if( nCnt < 0 )
453 : {
454 0 : if( -nCnt >= nTokenStackSize )
455 0 : nCnt = -nTokenStackSize+1;
456 0 : if( -nCnt <= nAktPos )
457 0 : nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
458 : else
459 : nAktPos = sal::static_int_cast< sal_uInt8 >(
460 0 : nAktPos + (nCnt + nTokenStackSize));
461 : }
462 0 : return pTokenStack + nAktPos;
463 : }
464 :
465 : // wird fuer jedes Token gerufen, das in CallParser erkannt wird
466 0 : void SvParser::NextToken( int )
467 : {
468 0 : }
469 :
470 :
471 : // fuers asynchrone lesen aus dem SvStream
472 :
473 0 : int SvParser::GetSaveToken() const
474 : {
475 0 : return pImplData ? pImplData->nSaveToken : 0;
476 : }
477 :
478 71 : void SvParser::SaveState( int nToken )
479 : {
480 : // aktuellen Status merken
481 71 : if( !pImplData )
482 : {
483 0 : pImplData = new SvParser_Impl;
484 0 : pImplData->nSaveToken = 0;
485 : }
486 :
487 71 : pImplData->nFilePos = rInput.Tell();
488 71 : pImplData->nToken = nToken;
489 :
490 71 : pImplData->aToken = aToken;
491 71 : pImplData->nlLineNr = nlLineNr;
492 71 : pImplData->nlLinePos = nlLinePos;
493 71 : pImplData->nTokenValue= nTokenValue;
494 71 : pImplData->bTokenHasValue = bTokenHasValue;
495 71 : pImplData->nNextCh = nNextCh;
496 71 : }
497 :
498 0 : void SvParser::RestoreState()
499 : {
500 : // alten Status wieder zurueck setzen
501 0 : if( pImplData )
502 : {
503 0 : if( ERRCODE_IO_PENDING == rInput.GetError() )
504 0 : rInput.ResetError();
505 0 : aToken = pImplData->aToken;
506 0 : nlLineNr = pImplData->nlLineNr;
507 0 : nlLinePos = pImplData->nlLinePos;
508 0 : nTokenValue= pImplData->nTokenValue;
509 0 : bTokenHasValue=pImplData->bTokenHasValue;
510 0 : nNextCh = pImplData->nNextCh;
511 :
512 0 : pImplData->nSaveToken = pImplData->nToken;
513 :
514 0 : rInput.Seek( pImplData->nFilePos );
515 : }
516 0 : }
517 :
518 0 : void SvParser::Continue( int )
519 : {
520 0 : }
521 :
522 0 : void SvParser::BuildWhichTbl( std::vector<sal_uInt16> &rWhichMap,
523 : sal_uInt16 *pWhichIds,
524 : sal_uInt16 nWhichIds )
525 : {
526 : sal_uInt16 aNewRange[2];
527 :
528 0 : for( sal_uInt16 nCnt = 0; nCnt < nWhichIds; ++nCnt, ++pWhichIds )
529 0 : if( *pWhichIds )
530 : {
531 0 : aNewRange[0] = aNewRange[1] = *pWhichIds;
532 0 : sal_Bool bIns = sal_True;
533 :
534 : // Position suchen
535 0 : for ( sal_uInt16 nOfs = 0; rWhichMap[nOfs]; nOfs += 2 )
536 : {
537 0 : if( *pWhichIds < rWhichMap[nOfs] - 1 )
538 : {
539 : // neuen Range davor
540 0 : rWhichMap.insert( rWhichMap.begin() + nOfs, aNewRange, aNewRange + 2 );
541 0 : bIns = sal_False;
542 0 : break;
543 : }
544 0 : else if( *pWhichIds == rWhichMap[nOfs] - 1 )
545 : {
546 : // diesen Range nach unten erweitern
547 0 : rWhichMap[nOfs] = *pWhichIds;
548 0 : bIns = sal_False;
549 0 : break;
550 : }
551 0 : else if( *pWhichIds == rWhichMap[nOfs+1] + 1 )
552 : {
553 0 : if( rWhichMap[nOfs+2] != 0 && rWhichMap[nOfs+2] == *pWhichIds + 1 )
554 : {
555 : // mit dem naechsten Bereich mergen
556 0 : rWhichMap[nOfs+1] = rWhichMap[nOfs+3];
557 0 : rWhichMap.erase( rWhichMap.begin() + nOfs + 2,
558 0 : rWhichMap.begin() + nOfs + 4 );
559 : }
560 : else
561 : // diesen Range nach oben erweitern
562 0 : rWhichMap[nOfs+1] = *pWhichIds;
563 0 : bIns = sal_False;
564 0 : break;
565 : }
566 : }
567 :
568 : // einen Range hinten anhaengen
569 0 : if( bIns )
570 : {
571 0 : rWhichMap.insert( rWhichMap.begin() + rWhichMap.size() - 1,
572 0 : aNewRange, aNewRange + 2 );
573 : }
574 : }
575 0 : }
576 :
577 :
578 0 : IMPL_STATIC_LINK( SvParser, NewDataRead, void*, EMPTYARG )
579 : {
580 0 : switch( pThis->eState )
581 : {
582 : case SVPAR_PENDING:
583 : // Wenn gerade ein File geladen wird duerfen wir nicht weiterlaufen,
584 : // sondern muessen den Aufruf ignorieren.
585 0 : if( pThis->IsDownloadingFile() )
586 0 : break;
587 :
588 0 : pThis->eState = SVPAR_WORKING;
589 0 : pThis->RestoreState();
590 :
591 0 : pThis->Continue( pThis->pImplData->nToken );
592 :
593 0 : if( ERRCODE_IO_PENDING == pThis->rInput.GetError() )
594 0 : pThis->rInput.ResetError();
595 :
596 0 : if( SVPAR_PENDING != pThis->eState )
597 0 : pThis->ReleaseRef(); // ansonsten sind wir fertig!
598 0 : break;
599 :
600 : case SVPAR_WAITFORDATA:
601 0 : pThis->eState = SVPAR_WORKING;
602 0 : break;
603 :
604 : case SVPAR_NOTSTARTED:
605 : case SVPAR_WORKING:
606 0 : break;
607 :
608 : default:
609 0 : pThis->ReleaseRef(); // ansonsten sind wir fertig!
610 0 : break;
611 : }
612 :
613 0 : return 0;
614 : }
615 :
616 : /*========================================================================
617 : *
618 : * SvKeyValueIterator.
619 : *
620 : *======================================================================*/
621 :
622 : /*
623 : * SvKeyValueIterator.
624 : */
625 680 : SvKeyValueIterator::SvKeyValueIterator (void)
626 680 : : m_pList (new SvKeyValueList_Impl),
627 1360 : m_nPos (0)
628 : {
629 680 : }
630 :
631 : /*
632 : * ~SvKeyValueIterator.
633 : */
634 795 : SvKeyValueIterator::~SvKeyValueIterator (void)
635 : {
636 318 : delete m_pList;
637 477 : }
638 :
639 : /*
640 : * GetFirst.
641 : */
642 341 : sal_Bool SvKeyValueIterator::GetFirst (SvKeyValue &rKeyVal)
643 : {
644 341 : m_nPos = m_pList->size();
645 341 : return GetNext (rKeyVal);
646 : }
647 :
648 : /*
649 : * GetNext.
650 : */
651 682 : sal_Bool SvKeyValueIterator::GetNext (SvKeyValue &rKeyVal)
652 : {
653 682 : if (m_nPos > 0)
654 : {
655 341 : rKeyVal = (*m_pList)[--m_nPos];
656 341 : return sal_True;
657 : }
658 : else
659 : {
660 : // Nothing to do.
661 341 : return sal_False;
662 : }
663 : }
664 :
665 : /*
666 : * Append.
667 : */
668 340 : void SvKeyValueIterator::Append (const SvKeyValue &rKeyVal)
669 : {
670 340 : m_pList->push_back(new SvKeyValue(rKeyVal));
671 340 : }
672 :
673 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|