--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/srsf/sispeechrecognitiondata/src/nsssidataserialize.cpp Thu Dec 17 08:46:30 2009 +0200
@@ -0,0 +1,1528 @@
+/*
+* Copyright (c) 2004-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Serialization functions for CSIGrammar and CSILexicon
+*
+*/
+
+
+// INCLUDE FILES
+#include "nsssidataserialize.h"
+#include <s32mem.h> // RBuf[Read/Write]Stream
+
+// LOCAL CONSTANTS AND MACROS
+const TUint32 KNibble16Limit = 0xffff;
+const TUint32 KNibble4Limit = 0xf;
+
+// LOCAL FUNCTION PROTOTYPES
+void Externalize32bitArrayL( RWriteStream& aStream, RArray<TUint32>& aArray );
+void Internalize32bitArrayL( RReadStream& aStream, RArray<TUint32>& aArray );
+TInt IndexOrderForPhonemes( const TLexiconPhoneme& p1, const TLexiconPhoneme& p2 );
+TInt StringOrderForPhonemes( const TLexiconPhoneme& p1, const TLexiconPhoneme& p2 );
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// Externalize32bitArrayL
+// Writes an RArray with 32-bit entries to the stream.
+// Returns: None
+// -----------------------------------------------------------------------------
+//
+void Externalize32bitArrayL(
+ RWriteStream& aStream, // The stream where to store the array
+ RArray<TUint32>& aArray ) // The array; the entries must be 32-bit.
+ {
+ TInt count = aArray.Count();
+
+ aStream.WriteInt32L( count );
+
+ if ( count > 0 )
+ {
+ TInt* startPtr = (TInt*)&aArray[0];
+ aStream.WriteL( (TUint8*)startPtr, sizeof(TInt) * count );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Internalize32bitArrayL
+// Reads an array from the stream.
+// Returns: None
+// -----------------------------------------------------------------------------
+//
+void Internalize32bitArrayL(
+ RReadStream& aStream, // The stream to read from
+ RArray<TUint32>& aArray ) // The array to be populated
+ {
+ TInt count = aStream.ReadInt32L();
+ TInt err = KErrNone;
+
+ for ( TInt k( 0 ); k < count; k++ )
+ {
+ TInt value = aStream.ReadInt32L();
+ err |= aArray.Append( value );
+ }
+
+ User::LeaveIfError( err );
+ }
+
+// -----------------------------------------------------------------------------
+// IndexOrderForPhonemes
+//
+// -----------------------------------------------------------------------------
+//
+TInt IndexOrderForPhonemes( const TLexiconPhoneme& p1, const TLexiconPhoneme& p2 )
+ {
+ return( p1.iIndex - p2.iIndex );
+ }
+
+// -----------------------------------------------------------------------------
+// StringOrderForPhonemes
+//
+// -----------------------------------------------------------------------------
+//
+TInt StringOrderForPhonemes( const TLexiconPhoneme& p1, const TLexiconPhoneme& p2 )
+ {
+ return( p1.iPhoneme.Compare( p2.iPhoneme ) );
+ }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// Implementation of CSILexiconSerializer starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::CSILexiconSerializer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSILexiconSerializer::CSILexiconSerializer()
+ {
+ iPronunIDs = NULL;
+ iModelBankIDs = NULL;
+ iParamBuf = NULL;
+ iCount = 0;
+ iLexiconID = 0; // !!!! Change to KInvalidLexiconID.
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::~CSILexiconSerializer
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CSILexiconSerializer::~CSILexiconSerializer()
+ {
+ iPronunciations.ResetAndDestroy();
+ iIndexPronuns.ResetAndDestroy();
+
+ iConversionTable.Close();
+
+ delete iPronunIDs;
+ delete iModelBankIDs;
+ delete iParamBuf;
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::NextPhonemeL
+// Stores the next phoneme to phonemeBuf and increases the cursor.
+// Returns true if there are still more phonemes.
+// -----------------------------------------------------------------------------
+//
+bool CSILexiconSerializer::NextPhonemeL(
+ TDes8& phonemeBuf,
+ const TDesC8& phonemeSeq,
+ TInt& aReadIterator )
+ {
+ TInt length = phonemeSeq.Length();
+
+ // Out of phonemes?
+ if ( length == aReadIterator )
+ {
+ return( false );
+ }
+
+ // Cut those phonemes away, which have been processed already.
+ TPtrC8 unfinishedPhonemes = phonemeSeq.Right( length - aReadIterator );
+
+ // Make SeparatorLoc point to the end of the next phoneme.
+ TInt separatorLoc = unfinishedPhonemes.Locate( KPhonemeSeparator );
+
+ // Phoneme length is from [start of unprocessed string] to [separator]...
+ TInt phonemeLength = separatorLoc;
+
+ // ...unless we're dealing with the last phoneme. Then
+ // phonemeLength is from [start of unprocessed string] to [end of string].
+ if ( separatorLoc == KErrNotFound )
+ phonemeLength = length - aReadIterator;
+
+ // Check that the phoneme is not too long.
+ if ( phonemeLength > KMaxPhonemeLength )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ if ( phonemeLength == 0 )
+ {
+ return( false );
+ }
+
+ // Copy
+ phonemeBuf.Copy( unfinishedPhonemes.Ptr(), phonemeLength );
+
+ // Update iterator
+ aReadIterator += phonemeLength; // The phoneme
+ if ( aReadIterator < length ) // The separator
+ {
+ aReadIterator++;
+ }
+
+ return( true );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::SavePronunciationL
+// Converts the ASCII phoneme strings to internal index strings.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconSerializer::SavePronunciationL(CSIPronunciation* aPronun)
+ {
+ TLinearOrder<TLexiconPhoneme> order( StringOrderForPhonemes );
+
+ // This phoneme is used for searching
+ TLexiconPhoneme searchPhoneme;
+ TDes8& phonemeBuf = searchPhoneme.iPhoneme;
+
+ const TDesC8& phonemeSeq = aPronun->PhonemeSequence();
+
+ HBufC8* indexPronun = HBufC8::NewLC( phonemeSeq.Length() );
+
+ TInt phonemeReadIter = 0;
+
+ while( NextPhonemeL( phonemeBuf, phonemeSeq, phonemeReadIter ) )
+ {
+ // Search the phoneme from conversion table.
+ TInt loc = iConversionTable.FindInOrder( searchPhoneme, order );
+
+ // Not found? Add the phoneme as a new phoneme.
+ if ( loc == KErrNotFound )
+ {
+ searchPhoneme.iIndex = iConversionTable.Count();
+ User::LeaveIfError(
+ iConversionTable.InsertInOrder( searchPhoneme, order )
+ );
+
+ // Can't fail: the phoneme has just been added.
+ loc = iConversionTable.FindInOrder( searchPhoneme, order );
+
+ // Make sure that phoneme count fits in TUint8
+ if ( searchPhoneme.iIndex >= 250 )
+ {
+ User::Leave( KErrOverflow );
+ }
+ }
+
+ // Phoneme to index
+ // Case to TUint8 is safe - Checked 10 lines earlier.
+ TUint8 index = (TUint8)iConversionTable[ loc ].iIndex;
+ indexPronun->Des().Append( index );
+ }
+
+ // Add pronunciation to the list of "index-pronunciations"
+ User::LeaveIfError( iIndexPronuns.Append( indexPronun ) );
+ CleanupStack::Pop( indexPronun );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::Index2PhonemeLC
+// Restores an internal index string into ASCII phonemes.
+// -----------------------------------------------------------------------------
+//
+HBufC8* CSILexiconSerializer::Index2PhonemeLC(const TDesC8& aIndexSeq)
+ {
+ TLinearOrder<TLexiconPhoneme> order( IndexOrderForPhonemes );
+ iConversionTable.Sort( order );
+
+ TInt length = 0;
+
+ TInt k( 0 );
+ for( k = 0; k < aIndexSeq.Length(); k++ )
+ {
+ TInt index = aIndexSeq[ k ];
+ length += iConversionTable[ index ].iPhoneme.Length();
+ length++; // Separator ('-')
+ }
+
+ HBufC8* buf = HBufC8::NewLC( length );
+ TPtr8 ptr = buf->Des();
+
+ TInt lastK = aIndexSeq.Length() -1; // Index of the last character
+
+ for( k = 0; k < aIndexSeq.Length(); k++ )
+ {
+ TInt index = aIndexSeq[ k ];
+ ptr.Append( iConversionTable[ index ].iPhoneme );
+
+ // Add separator, except for the last phoneme
+ if ( k != lastK )
+ {
+ ptr.Append( KPhonemeSeparator );
+ }
+ }
+
+ return( buf );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSILexiconSerializer* CSILexiconSerializer::NewLC( const CSILexicon& aLexicon )
+ {
+ CSILexiconSerializer* me = new (ELeave) CSILexiconSerializer;
+ CleanupStack::PushL( me );
+
+ me->ConstructL( aLexicon );
+
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSILexiconSerializer* CSILexiconSerializer::NewLC( RReadStream& aStream )
+ {
+ CSILexiconSerializer* me = new (ELeave) CSILexiconSerializer;
+ CleanupStack::PushL( me );
+
+ me->InternalizeL( aStream );
+
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconSerializer::ConstructL( const CSILexicon& aLexicon )
+ {
+ iLexiconID = aLexicon.LexiconID();
+ iCount = aLexicon.Count();
+
+ iParamBuf = CBufFlat::NewL( 100 ); // Grow in 100 byte doses
+
+ RArray<TSIModelBankID> modelBankIDs;
+ RArray<TSIPronunciationID> pronunIDs;
+
+ CleanupClosePushL( modelBankIDs );
+ CleanupClosePushL( pronunIDs );
+
+ RBufWriteStream paramStream;
+ paramStream.Open( *iParamBuf );
+ CleanupClosePushL( paramStream );
+
+ // In serialization format, the 5 types of data in pronunciations
+ // are put to 4 piles. Then, the common properties of the data is exploited.
+ for ( TInt k = 0; k < aLexicon.Count(); k++ )
+ {
+ CSIPronunciation* pronun = &aLexicon.AtL( k );
+
+ // 4 types of pronunciation data
+ TInt err = KErrNone;
+
+ // This is a hack to get the modelid aligned to 4-byte boundary,
+ // for some reason this does not happen in winscw build if
+ // TSIModelBankID is taken from stack.
+ TSIModelBankID* modelid = new (ELeave) TSIModelBankID;
+ *modelid = pronun->ModelBankID();
+
+ err |= modelBankIDs.Append( *modelid );
+
+ // Delete temporary modelid
+ delete modelid;
+
+ err |= pronunIDs.Append( pronun->PronunciationID() );
+
+ User::LeaveIfError( err );
+
+ SavePronunciationL( pronun );
+
+ // Parameters
+ pronun->CSIParameters::ExternalizeL( paramStream );
+ }
+
+ // Code the piled values
+ // Casts are safe, as all variables are 32-bit (they are just called
+ // with many different names - int, unsigned long, unsigned int)
+ iPronunIDs = CNibble16Coder::NewL( pronunIDs );
+ iModelBankIDs = CRLECoder::NewL( modelBankIDs );
+
+ CleanupStack::PopAndDestroy( ¶mStream );
+
+ CleanupStack::PopAndDestroy( 2 ); // Close the RArrays
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::ExternalizeL
+// Stores the object to the stream.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconSerializer::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteInt32L( KBinaryLexiconID );
+
+ aStream.WriteInt32L( iLexiconID );
+ aStream.WriteInt32L( iCount );
+
+ // Write model bank IDs.
+ iModelBankIDs->ExternalizeL( aStream );
+ // Write pronunciation IDs
+ iPronunIDs->ExternalizeL( aStream );
+
+ // Write pronunciations (converted from phonemes to indices)
+ aStream.WriteInt32L( iIndexPronuns.Count() );
+
+ TInt k( 0 );
+ for ( k = 0; k < iIndexPronuns.Count(); k++ )
+ {
+ HBufC8* pronun = iIndexPronuns[ k ];
+
+ // There is no fixed limit on the length of a phoneme sequence.
+ // It's not even guaranteed that the length fits in 32 bits, damnit!
+ if ( pronun->Length() > 64000 )
+ {
+ User::Leave( KErrNotSupported );
+ }
+
+ aStream.WriteUint16L( pronun->Length() );
+ aStream.WriteL( pronun->Ptr(), pronun->Length() );
+ }
+
+ // Write parameters
+ aStream.WriteInt32L( iParamBuf->Size() );
+ aStream.WriteL( iParamBuf->Ptr(0) );
+
+ // Write phoneme<->index conversion table
+ aStream.WriteInt32L( iConversionTable.Count() );
+ for ( k = 0; k < iConversionTable.Count(); k++ )
+ {
+ aStream.WriteL( (TUint8*)&iConversionTable[k],
+ sizeof( TLexiconPhoneme ) );
+ }
+
+ // For corruption checking
+ aStream.WriteInt32L( KBinaryLexiconID );
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::InternalizeL
+// Restores the object from a stream
+// -----------------------------------------------------------------------------
+//
+void CSILexiconSerializer::InternalizeL(RReadStream& aStream)
+ {
+ if ( aStream.ReadInt32L() != KBinaryLexiconID )
+ User::Leave( KErrArgument );
+
+ iLexiconID = (TSILexiconID)aStream.ReadUint32L();
+ iCount = aStream.ReadInt32L();
+
+ // Read model bank IDs
+ iModelBankIDs = CRLECoder::NewL( aStream );
+ // Read pronunciation IDs
+ iPronunIDs = CNibble16Coder::NewL( aStream );
+
+ // Read pronunciations (converted from phonemes to indices)
+ TInt indexCount = aStream.ReadInt32L();
+
+ if ( indexCount != iCount )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ TInt k( 0 );
+ for ( k = 0; k < indexCount; k++ )
+ {
+ HBufC8* pronun = 0;
+
+ TUint16 length = aStream.ReadUint16L();
+ pronun = HBufC8::NewLC( length );
+
+ TPtr8 pronunPtr = pronun->Des();
+ aStream.ReadL( pronunPtr, length );
+
+ User::LeaveIfError( iIndexPronuns.Append( pronun ) );
+
+ CleanupStack::Pop( pronun );
+ }
+
+ // Read parameters
+ TInt size = aStream.ReadInt32L();
+ iParamBuf = CBufFlat::NewL( size+4 );
+ iParamBuf->ExpandL( 0, size );
+
+ TPtr8 paramBufPtr = iParamBuf->Ptr(0);
+ aStream.ReadL( paramBufPtr, size );
+
+ // Read phoneme<->index conversion table
+ TInt conversionCount = aStream.ReadInt32L();
+ for ( k = 0; k < conversionCount; k++ )
+ {
+ TLexiconPhoneme lexiconPhoneme;
+
+ aStream.ReadL( (TUint8*)&lexiconPhoneme,
+ sizeof( TLexiconPhoneme ) );
+
+ User::LeaveIfError( iConversionTable.Append( lexiconPhoneme ) );
+ }
+
+ // For corruption checking
+ if ( aStream.ReadInt32L() != KBinaryLexiconID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CSILexiconSerializer::RestoreL
+// Populates CSILexicon with the newly internalized data.
+// -----------------------------------------------------------------------------
+//
+void CSILexiconSerializer::RestoreL( CSILexicon& aLexicon, TSILexiconID& aLexiconID )
+ {
+ if ( aLexicon.Count() > 0 )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ TSIModelBankID modelBankID = 0;
+ TSIPronunciationID pronunID = 0;
+
+ RBufReadStream paramStream;
+ paramStream.Open( *iParamBuf );
+ CleanupClosePushL( paramStream );
+
+ iModelBankIDs->DecodeReset();
+ iPronunIDs->DecodeReset();
+
+ TInt iterPronunPos = 0;
+
+ for ( TInt pronunK = 0; pronunK < iCount; pronunK++ )
+ {
+ modelBankID = iModelBankIDs->NextL();
+ pronunID = iPronunIDs->NextL();
+
+ CSIPronunciation* pronun
+ = CSIPronunciation::NewLC( pronunID, modelBankID );
+
+ HBufC8* indexSequence = iIndexPronuns[ iterPronunPos ];
+ iterPronunPos++;
+
+ HBufC8* phonemeSequence = Index2PhonemeLC( *indexSequence );
+ pronun->SetPhonemeSequenceL( *phonemeSequence );
+ CleanupStack::PopAndDestroy( phonemeSequence );
+
+ pronun->CSIParameters::InternalizeL( paramStream );
+
+ aLexicon.AddL( pronun );
+ CleanupStack::Pop( pronun );
+ }
+
+ CleanupStack::PopAndDestroy( ¶mStream );
+
+ // LexiconID can't be written to CSILexicon with public API.
+ aLexiconID = iLexiconID;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CSIGrammarSerializer starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::CSIGrammarSerializer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarSerializer::CSIGrammarSerializer()
+ {
+ iGrammarID = KInvalidGrammarID;
+ iCount = 0;
+ iRuleIDs = NULL;
+ iRuleVariantCounts = NULL;
+ iRuleVariantIDs = NULL;
+ iRuleVariantLexiconIDs = NULL;
+ iRuleVariantLanguages = NULL;
+ iPronunIDSeqLengths = NULL;
+ iPronunIDSequences = NULL;
+ iParamBuf = NULL;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::~CSIGrammarSerializer
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarSerializer::~CSIGrammarSerializer()
+ {
+ delete iRuleIDs;
+ delete iRuleVariantCounts;
+ delete iRuleVariantIDs;
+ delete iRuleVariantLexiconIDs;
+ delete iRuleVariantLanguages;
+ delete iPronunIDSeqLengths;
+ delete iPronunIDSequences;
+ delete iParamBuf;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarSerializer* CSIGrammarSerializer::NewLC( const CSIGrammar& aGrammar )
+ {
+ CSIGrammarSerializer* me = new (ELeave) CSIGrammarSerializer();
+ CleanupStack::PushL( me );
+
+ me->ConstructL( aGrammar );
+
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarSerializer::ConstructL( const CSIGrammar& aGrammar )
+ {
+ iParamBuf = CBufFlat::NewL( 100 ); // Grow in 100 byte doses
+ RBufWriteStream paramStream;
+ paramStream.Open( *iParamBuf );
+ CleanupClosePushL( paramStream ); // Cleanp stack: param stream
+
+ RArray<TSIRuleID> ruleIDs;
+ RArray<TUint32> ruleVariantCounts;
+ RArray<TUint32> ruleVariantIDs;
+ RArray<TSILexiconID> ruleVariantLexiconIDs;
+ RArray<TUint32> ruleVariantLanguages;
+ RArray<TUint32> pronunIDSeqLengths;
+ RArray<TSIPronunciationID> pronunIDSequences;
+
+ CleanupClosePushL( ruleIDs );
+ CleanupClosePushL( ruleVariantCounts );
+ CleanupClosePushL( ruleVariantIDs );
+ CleanupClosePushL( ruleVariantLexiconIDs );
+ CleanupClosePushL( ruleVariantLanguages );
+ CleanupClosePushL( pronunIDSeqLengths );
+ CleanupClosePushL( pronunIDSequences ); // Cleanup stack: param stream, 7 tmp arrays
+
+ TInt err = KErrNone;
+
+ // Pile the data according to type (8 types)
+ for ( TInt ruleK( 0 ); ruleK < aGrammar.Count(); ruleK++ )
+ {
+ CSIRule& rule = aGrammar.AtL( ruleK );
+
+ err |= ruleIDs.Append( rule.RuleID() );
+ err |= ruleVariantCounts.Append( rule.Count() );
+
+ for ( TInt variantK( 0 ); variantK < rule.Count(); variantK++ )
+ {
+ CSIRuleVariant& variant = rule.AtL( variantK );
+
+ err |= ruleVariantIDs.Append( variant.RuleVariantID() );
+
+ // This is a hack to get the lexid aligned to 4-byte boundary,
+ // for some reason this does not happen in winscw build if
+ // TSILexiconID is taken from stack.
+ TSILexiconID* lexid = new (ELeave) TSILexiconID;
+ *lexid = variant.LexiconID();
+
+ err |= ruleVariantLexiconIDs.Append( *lexid );
+
+ delete lexid;
+
+ err |= ruleVariantLanguages.Append( variant.Language() );
+
+ TSIPronunciationIDSequence seq;
+ CleanupClosePushL( seq ); // Cleanup stack: param stream, 7 tmp arrays, seq
+
+ variant.GetPronunciationIDsL( seq );
+
+ err |= pronunIDSeqLengths.Append( seq.Count() );
+
+ for ( TInt k( 0 ); k < seq.Count(); k++ )
+ {
+ err |= pronunIDSequences.Append( seq[k] );
+ }
+
+ CleanupStack::PopAndDestroy( &seq );
+ // Cleanup stack: param stream, 7 tmp arrays
+
+ // Store parameters to a buffer.
+ variant.ExternalizeL( paramStream );
+ }
+
+ User::LeaveIfError( err );
+ }
+
+ // Code the arrays
+ iGrammarID = aGrammar.GrammarID();
+ iCount = aGrammar.Count();
+
+ iRuleIDs = CNibble16Coder::NewL( ruleIDs );
+ iRuleVariantCounts = CNibble4Coder::NewL( ruleVariantCounts );
+ iRuleVariantIDs = CNibble4Coder::NewL( ruleVariantIDs );
+ iRuleVariantLexiconIDs = CRLECoder::NewL( ruleVariantLexiconIDs );
+ // Cast is safe, since TLanguage is 32-bit
+ iRuleVariantLanguages = CNibble4Coder::NewL( ruleVariantLanguages );
+ iPronunIDSeqLengths = CNibble4Coder::NewL( pronunIDSeqLengths );
+ iPronunIDSequences = CNibble16Coder::NewL( pronunIDSequences );
+
+ CleanupStack::PopAndDestroy( 7 ); // Destory 7 tmp arrays
+ CleanupStack::PopAndDestroy( ¶mStream ); // Destroy parameter stream
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::ExternalizeL
+// Stores the object to the stream.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarSerializer::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteUint32L( ( TUint32 ) KBinaryGrammarID );
+ aStream.WriteUint32L( iGrammarID );
+ aStream.WriteUint32L( iCount );
+
+ iRuleIDs ->ExternalizeL( aStream );
+ iRuleVariantCounts ->ExternalizeL( aStream );
+ iRuleVariantIDs ->ExternalizeL( aStream );
+ iRuleVariantLexiconIDs->ExternalizeL( aStream );
+ iRuleVariantLanguages ->ExternalizeL( aStream );
+ iPronunIDSeqLengths ->ExternalizeL( aStream );
+ iPronunIDSequences ->ExternalizeL( aStream );
+
+ aStream.WriteInt32L( iParamBuf->Size() );
+ aStream.WriteL( iParamBuf->Ptr(0) );
+
+ aStream.WriteUint32L( ( TUint32 ) KBinaryGrammarID );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CSIGrammarSerializer* CSIGrammarSerializer::NewLC(RReadStream& aStream)
+ {
+ CSIGrammarSerializer* me = new (ELeave) CSIGrammarSerializer();
+ CleanupStack::PushL( me );
+
+ me->ConstructL( aStream );
+
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarSerializer::ConstructL( RReadStream& aStream )
+ {
+ if ( aStream.ReadInt32L() != KBinaryGrammarID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ iGrammarID = (TSIGrammarID)aStream.ReadUint32L();
+ iCount = aStream.ReadUint32L();
+
+ iRuleIDs = CNibble16Coder::NewL( aStream );
+ iRuleVariantCounts = CNibble4Coder::NewL( aStream );
+ iRuleVariantIDs = CNibble4Coder::NewL( aStream );
+ iRuleVariantLexiconIDs= CRLECoder::NewL( aStream );
+ iRuleVariantLanguages = CNibble4Coder::NewL( aStream );
+ iPronunIDSeqLengths = CNibble4Coder::NewL( aStream );
+ iPronunIDSequences = CNibble16Coder::NewL( aStream );
+
+ TInt32 paramSize = aStream.ReadInt32L();
+ iParamBuf = CBufFlat::NewL( paramSize + 4 );
+ iParamBuf->ExpandL( 0, paramSize );
+ TPtr8 paramBufPtr = iParamBuf->Ptr(0);
+ aStream.ReadL( paramBufPtr, paramSize );
+
+ if ( aStream.ReadInt32L() != KBinaryGrammarID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CSIGrammarSerializer::RestoreL
+// Populates the CSIGrammar with newly internalized data.
+// -----------------------------------------------------------------------------
+//
+void CSIGrammarSerializer::RestoreL( CSIGrammar& aGrammar, TSIGrammarID& aGrammarID )
+ {
+ if ( aGrammar.Count() != 0 )
+ {
+ User::Leave( KErrInUse );
+ }
+
+ aGrammarID = iGrammarID;
+
+ TBool ready = iRuleIDs && iRuleVariantCounts && iRuleVariantIDs &&
+ iRuleVariantLexiconIDs && iRuleVariantLanguages &&
+ iPronunIDSeqLengths && iPronunIDSequences;
+
+ if ( !ready )
+ {
+ User::Leave( KErrNotReady );
+ }
+
+ iRuleIDs->DecodeReset();
+ iRuleVariantCounts->DecodeReset();
+ iRuleVariantIDs->DecodeReset();
+ iRuleVariantLexiconIDs->DecodeReset();
+ iRuleVariantLanguages->DecodeReset();
+ iPronunIDSeqLengths->DecodeReset();
+ iPronunIDSequences->DecodeReset();
+
+ RBufReadStream paramStream;
+ CleanupClosePushL( paramStream );
+
+ paramStream.Open( *iParamBuf );
+
+ for ( TInt ruleK( 0 ); ruleK < iCount; ruleK++ )
+ {
+ CSIRule* rule = CSIRule::NewLC( iRuleIDs->NextL() );
+
+ TInt ruleVariantCount = iRuleVariantCounts->NextL();
+
+ for ( TInt variantK( 0 ); variantK < ruleVariantCount; variantK++ )
+ {
+ CSIRuleVariant* variant = CSIRuleVariant::NewLC(
+ (TSIRuleVariantID)iRuleVariantIDs->NextL(),
+ iRuleVariantLexiconIDs->NextL()
+ );
+
+ variant->SetLanguage(
+ (enum TLanguage)iRuleVariantLanguages->NextL() );
+
+ RArray<TSIPronunciationID> pronunIDSeq;
+ CleanupClosePushL( pronunIDSeq );
+
+ TInt seqLength = iPronunIDSeqLengths->NextL();
+ for ( TInt pronunIdK( 0 ); pronunIdK < seqLength; pronunIdK++ )
+ {
+ TInt err = pronunIDSeq.Append( iPronunIDSequences->NextL() );
+ User::LeaveIfError( err );
+ }
+
+ variant->SetPronunciationIDsL( pronunIDSeq );
+ CleanupStack::PopAndDestroy( &pronunIDSeq );
+
+ variant->CSIParameters::InternalizeL( paramStream );
+ rule->AddL( variant );
+ CleanupStack::Pop( variant );
+ }
+
+ aGrammar.AddL( rule );
+ CleanupStack::Pop( rule );
+ }
+
+ CleanupStack::PopAndDestroy( ¶mStream );
+ }
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CNibble16Coder starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CNibble16Coder::CNibble16Coder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CNibble16Coder::CNibble16Coder()
+: iMainArray(50),
+ iOverflowArray(10)
+ {
+ DecodeReset();
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::NewL
+// Two-phased constructor. Encodes the values given as the argument.
+// -----------------------------------------------------------------------------
+//
+CNibble16Coder* CNibble16Coder::NewL( const RArray<TUint32>& aPlainArray )
+ {
+ CNibble16Coder* me = new (ELeave) CNibble16Coder;
+ CleanupStack::PushL( me );
+
+ TInt count = aPlainArray.Count();;
+ TInt sizeNeeded = (count+1) / 2;
+
+ // Grow the array to be big enough
+ TInt k( 0 );
+ for ( k = 0; k < sizeNeeded; k++ )
+ {
+ User::LeaveIfError( me->iMainArray.Append( 0xffffffff ) );
+ }
+
+ TUint16* storagePtr = 0;
+
+ if ( count > 0 )
+ {
+ storagePtr = (TUint16*)&me->iMainArray[0];
+ }
+
+ for( k = 0; k < count; k++ )
+ {
+ TSIPronunciationID id = aPlainArray[ k ];
+ TBool overflow = false;
+
+ // If the 32-bit value doesn't fit to 16 bits:
+ // * Put overflow sign to main array
+ // * Put the real ID to overflow array
+ if ( id >= KNibble16Limit )
+ {
+ overflow = true;
+ id = KNibble16Limit;
+ }
+
+ // Write to the main array
+ // ([overflow sign] OR [id, which fits to 16 bits])
+ *(storagePtr++) = (TUint16)id;
+
+ // If it didn't fit to 16 bits, save it to the overflow array.
+ if ( overflow )
+ {
+ TInt err = me->iOverflowArray.Append( aPlainArray[k] );
+ User::LeaveIfError( err );
+ }
+ }
+
+ CleanupStack::Pop( me );
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::NewL
+// Two-phased constructor. Internalizes an array from stream.
+// -----------------------------------------------------------------------------
+//
+CNibble16Coder* CNibble16Coder::NewL( RReadStream& aStream )
+ {
+ CNibble16Coder* me = new (ELeave) CNibble16Coder;
+ CleanupStack::PushL( me );
+
+ if ( aStream.ReadInt32L() != KBinaryNibble16ID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ Internalize32bitArrayL( aStream, me->iMainArray );
+ Internalize32bitArrayL( aStream, me->iOverflowArray );
+
+ CleanupStack::Pop( me );
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::~CNibble16Coder
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CNibble16Coder::~CNibble16Coder()
+ {
+ iMainArray.Close();
+ iOverflowArray.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::DecodeReset
+// Moves cursor to the beginning of the array.
+// -----------------------------------------------------------------------------
+//
+void CNibble16Coder::DecodeReset()
+ {
+ iPosition = 0;
+ iOverflowPos = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::NextL
+// Returns a value in the array and moves the cursor forward.
+// -----------------------------------------------------------------------------
+//
+TUint32 CNibble16Coder::NextL()
+ {
+ if ( iPosition >= 2*iMainArray.Count() )
+ User::Leave( KErrOverflow );
+
+ TUint16* storagePtr = (TUint16*)&iMainArray[0];
+
+ // Get the [pronunciation ID] OR [overflow sign] from main array.
+ TSIPronunciationID id = storagePtr[ iPosition ];
+
+ // It was overflow sign; get whole 32-bit ID from overflow array
+ if ( id == KNibble16Limit ) // It was pronunciation ID
+ {
+ if ( iOverflowPos == iOverflowArray.Count() )
+ {
+ User::Leave( KErrOverflow );
+ }
+
+ id = iOverflowArray[ iOverflowPos ];
+ iOverflowPos++;
+ }
+
+ // Update iterator
+ iPosition++;
+
+ return( id );
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble16Coder::ExternalizeL
+// Externalizes the array into a stream.
+// -----------------------------------------------------------------------------
+//
+void CNibble16Coder::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteInt32L( KBinaryNibble16ID );
+ Externalize32bitArrayL( aStream, iMainArray );
+ Externalize32bitArrayL( aStream, iOverflowArray );
+ }
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CNibble4Coder starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CNibble4Coder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CNibble4Coder* CNibble4Coder::NewL( const RArray<TUint32>& aPlainArray )
+ {
+ CNibble4Coder* me = new (ELeave) CNibble4Coder;
+ CleanupStack::PushL( me );
+ me->DecodeReset();
+
+ TInt count = aPlainArray.Count();
+
+ for ( TInt k( 0 ); k < count; k++ )
+ {
+ TUint compactValue = aPlainArray[ k ];
+ TBool overflow = EFalse;
+
+ // If the value does not fit to 4 bytes, put an overflow sign to main
+ // array, and save the value to a separate overflow array.
+ if ( compactValue >= KNibble4Limit )
+ {
+ compactValue = KNibble4Limit;
+ overflow = true;
+ }
+
+ // Save the compact value
+ if ( me->iSlot == 0 )
+ {
+ User::LeaveIfError( me->iMainArray.Append( compactValue ) );
+ me->iSlot++;
+ }
+ else{
+ // We save 4-bit values to 32-bit variable. So, there are 8 slots
+ // in each 32-bit entry.
+
+ // Shift the value to correct slot.
+ // Earlier, we have made sure, that compactValue < 16.
+ compactValue = compactValue << (4 * me->iSlot);
+
+ // Put it to the array.
+ me->iMainArray[ me->iPosition ]
+ = compactValue | me->iMainArray[ me->iPosition ];
+
+ // Update iterator
+ me->iSlot++;
+ if ( me->iSlot == 8 )
+ {
+ me->iPosition++;
+ me->iSlot = 0;
+ }
+ }
+
+ // If the value didn't fit to 4 bits, save it to 32-bit overflow array.
+ if ( overflow )
+ {
+ TInt ret = me->iOverflowArray.Append( aPlainArray[ k ] );
+ User::LeaveIfError( ret );
+ }
+ }
+
+ // If the number of entries was not divisible by 8, we have
+ // uninitialized slots in the end. Initialize them with 0xf.
+
+ // If the decoder finds one of these 0xf's, it goes to overflow array,
+ // notices that all entries in the overflow array have been processed,
+ // and leaves.
+ if ( me->iSlot != 0 )
+ {
+ TUint unusedValue = 0xffffffff;
+ unusedValue = unusedValue << (4 * me->iSlot);
+
+ me->iMainArray[ me->iPosition ]
+ = unusedValue | me->iMainArray[ me->iPosition ];
+ }
+
+ me->DecodeReset();
+ CleanupStack::Pop( me );
+ return me;
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CNibble4Coder* CNibble4Coder::NewL( RReadStream& aStream )
+ {
+ CNibble4Coder* me = new (ELeave) CNibble4Coder;
+ CleanupStack::PushL( me );
+ me->DecodeReset();
+
+ if ( aStream.ReadInt32L() != KBinaryNibble4ID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ Internalize32bitArrayL( aStream, me->iMainArray );
+ Internalize32bitArrayL( aStream, me->iOverflowArray );
+
+ CleanupStack::Pop( me );
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::CNibble4Coder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CNibble4Coder::CNibble4Coder()
+: iMainArray(50),
+ iOverflowArray(10)
+ {
+ DecodeReset();
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::~CNibble4Coder
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CNibble4Coder::~CNibble4Coder()
+ {
+ iMainArray.Close();
+ iOverflowArray.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::DecodeReset
+// Moves cursor to the beginning of the array.
+// -----------------------------------------------------------------------------
+//
+void CNibble4Coder::DecodeReset()
+ {
+ iPosition = 0;
+ iSlot = 0;
+ iOverflowPos = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::NextL
+// Returns a value in the array and moves cursor forwards.
+// -----------------------------------------------------------------------------
+//
+TUint32 CNibble4Coder::NextL()
+ {
+ if ( iPosition >= iMainArray.Count() )
+ {
+ User::Leave( KErrOverflow );
+ }
+
+ TUint result = iMainArray[ iPosition ];
+
+ // In binary, the array entry is something like:
+ // hhhhhhhhhhhhhhhhrrrrllllllllllll (32 bits)
+ // r = result bits we're after
+ // h = higher bits
+ // l = lower bits
+
+ // Drop the lower bits
+ result = result >> (4 * iSlot );
+ // Drop the higher bits
+ result = result & 0xf;
+
+ // If the value didn't fit to 4 bits, get it from the overflow array.
+ if ( result >= KNibble4Limit )
+ {
+ if ( iOverflowPos >= iOverflowArray.Count() )
+ {
+ User::Leave( KErrOverflow );
+ }
+
+ result = iOverflowArray[ iOverflowPos ];
+ iOverflowPos++;
+ }
+
+ // Update iterator
+ iSlot++;
+ if ( iSlot == 8 )
+ {
+ iPosition++;
+ iSlot = 0;
+ }
+
+ return( result );
+ }
+
+// -----------------------------------------------------------------------------
+// CNibble4Coder::ExternalizeL
+// Stores the object to the stream.
+// -----------------------------------------------------------------------------
+//
+void CNibble4Coder::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteInt32L( KBinaryNibble4ID );
+ Externalize32bitArrayL( aStream, iMainArray );
+ Externalize32bitArrayL( aStream, iOverflowArray );
+ }
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CRLECoder starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CRLECoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CRLECoder* CRLECoder::NewL( const RArray<TUint16>& aPlainArray )
+ {
+ CRLECoder* me = new (ELeave) CRLECoder;
+ CleanupStack::PushL( me );
+ me->DecodeReset();
+
+ if ( aPlainArray.Count() == 0 )
+ {
+ CleanupStack::Pop();
+ return( me );
+ }
+
+ TInt count = aPlainArray.Count();
+
+ if ( count > 0 )
+ {
+ CRLECoder::TValueAndCount valueCount;
+
+ valueCount.iValue = aPlainArray[ 0 ];
+ valueCount.iCount = 1;
+
+ for ( TInt k( 1 ); k < count; k++ )
+ {
+ if ( aPlainArray[ k ] == valueCount.iValue )
+ {
+ valueCount.iCount++;
+ }
+ else{
+ User::LeaveIfError( me->iRleArray.Append( valueCount ) );
+
+ valueCount.iCount = 1;
+ valueCount.iValue = aPlainArray[ k ];
+ }
+ }
+
+ User::LeaveIfError( me->iRleArray.Append( valueCount ) );
+ }
+
+ CleanupStack::Pop( me );
+ return me;
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CRLECoder* CRLECoder::NewL( RReadStream& aStream )
+ {
+ CRLECoder* me = new (ELeave) CRLECoder;
+ CleanupStack::PushL( me );
+ me->DecodeReset();
+
+ if ( aStream.ReadInt32L() != KBinaryRLEID )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ TInt count = aStream.ReadInt32L();
+ TInt err = KErrNone;
+
+ TUint32 value;
+ CRLECoder::TValueAndCount* valuePtr = (CRLECoder::TValueAndCount*)&value;
+
+ for ( TInt k( 0 ); k < count; k++ )
+ {
+ value = aStream.ReadInt32L();
+ err |= me->iRleArray.Append( *valuePtr );
+ }
+
+ User::LeaveIfError( err );
+
+ CleanupStack::Pop( me );
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::CRLECoder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CRLECoder::CRLECoder()
+: iRleArray(50)
+ {
+ DecodeReset();
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::~CRLECoder
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CRLECoder::~CRLECoder()
+ {
+ iRleArray.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::DecodeReset
+// Moves cursor to the beginning of the array.
+// -----------------------------------------------------------------------------
+//
+void CRLECoder::DecodeReset()
+ {
+ iPosition = 0;
+ iRepetition = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::NextL
+// Returns a value in the array and moves cursor forwards.
+// -----------------------------------------------------------------------------
+//
+TUint16 CRLECoder::NextL()
+ {
+ if ( iPosition >= iRleArray.Count() )
+ {
+ User::Leave( KErrOverflow );
+ }
+
+ TUint16 result = iRleArray[iPosition].iValue;
+
+ iRepetition++;
+ TUint16 maxRepetitions = iRleArray[iPosition].iCount;
+
+ if ( iRepetition >= maxRepetitions )
+ {
+ iPosition++;
+ iRepetition = 0;
+ }
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CRLECoder::ExternalizeL
+// Stores the object to the stream.
+// -----------------------------------------------------------------------------
+//
+void CRLECoder::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteInt32L( KBinaryRLEID );
+ TInt count = iRleArray.Count();
+
+ aStream.WriteInt32L( count );
+
+ if ( count > 0 )
+ {
+ TValueAndCount* startPtr = &(iRleArray[0]);
+ aStream.WriteL( (TUint8*)startPtr, sizeof(TValueAndCount) * count );
+ }
+
+ }
+
+
+// -----------------------------------------------------------------------------
+// Implementation of CYesNoCoder starts from here.
+// -----------------------------------------------------------------------------
+//
+// -----------------------------------------------------------------------------
+// CYesNoCoder::DecodeReset
+// Moves cursor to the beginning of the array.
+// -----------------------------------------------------------------------------
+//
+void CYesNoCoder::DecodeReset()
+ {
+ iPosition = 0;
+ iMask = 0x00000001;
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::NextBit
+// Moves the cursor forwards.
+// -----------------------------------------------------------------------------
+//
+void CYesNoCoder::NextBit(void)
+ {
+ // Increase the iterator.
+ iMask <<= 1;
+ if ( iMask == 0 )
+ {
+ iPosition++;
+ iMask = 1;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CYesNoCoder* CYesNoCoder::NewL()
+ {
+ CYesNoCoder* me = new (ELeave) CYesNoCoder;
+
+ me->DecodeReset();
+
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CYesNoCoder* CYesNoCoder::NewL( RReadStream& aStream )
+ {
+ CYesNoCoder* me = new (ELeave) CYesNoCoder;
+ CleanupStack::PushL( me );
+ me->DecodeReset();
+
+ Internalize32bitArrayL( aStream, me->iStore );
+
+ CleanupStack::Pop( me );
+ return( me );
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::CYesNoCoder
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CYesNoCoder::CYesNoCoder()
+: iStore(10)
+ {
+ DecodeReset();
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::~CYesNoCoder
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CYesNoCoder::~CYesNoCoder()
+ {
+ iStore.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::EncodeL
+// Encodes a bit.
+// -----------------------------------------------------------------------------
+//
+void CYesNoCoder::EncodeL( TBool aValue )
+ {
+ // Do we need to grow the size of the array?
+ if ( iMask == 1 )
+ {
+ User::LeaveIfError( iStore.Append( 0 ) );
+ }
+
+ // Store the value, if it is 'yes'.
+ if ( aValue )
+ {
+ iStore[ iPosition ] |= iMask;
+ }
+
+ // Increase the iterator
+ NextBit();
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::NextL
+// Returns a value in the array and moves cursor forwards.
+// -----------------------------------------------------------------------------
+//
+TBool CYesNoCoder::NextL()
+ {
+ TBool result = iStore[ iPosition ] & iMask;
+
+ // Increase the iterator
+ NextBit();
+
+ return( result );
+ }
+
+// -----------------------------------------------------------------------------
+// CYesNoCoder::ExternalizeL
+// Stores the object to the stream.
+// (other items were commented in the headers)
+// -----------------------------------------------------------------------------
+//
+void CYesNoCoder::ExternalizeL( RWriteStream& aStream )
+ {
+ aStream.WriteInt32L( KBinaryYesNoID );
+ Externalize32bitArrayL( aStream, iStore );
+ }
+
+// End of File