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