examples/ForumNokia/Symbian_OS_End-to-End_Sockets_API_Example/SocketTaskManager_S60/engine/Response.cpp

00001 /*
00002 * ============================================================================
00003 *  Name     : CResponse from Response.cpp
00004 *  Part of  : TaskManager
00005 *  Created  : 15/03/2006 by Forum Nokia
00006 *  Version  : 1.2
00007 *  Copyright: Nokia Corporation
00008 * ============================================================================
00009 */
00010 
00011 // INCLUDE FILES
00012 #include "Response.h"
00013 #include "TaskManager.pan"
00014 
00015 // CONSTANTS
00016 _LIT(KError, "#Error:");
00017 _LIT(KOkMessage, "#OK");
00018 _LIT(KTab, "\t");
00019 _LIT(KSeparator, "#");
00020 
00021 // ================= MEMBER FUNCTIONS =======================
00022 
00023 // constructor
00024 CResponse::CResponse()
00025 : iMessageBuffer( NULL ), iExpectedPackageSize( 0 ), iState( ENotComplete )
00026         {
00027         }
00028         
00029 // destructor   
00030 CResponse::~CResponse()
00031         {
00032         iIds.Close();
00033         delete iDescriptions;
00034         delete iMessageBuffer;
00035         }
00036 
00037 // ----------------------------------------------------
00038 // CResponse::NewL()
00039 // Two-phased constructor.
00040 // ----------------------------------------------------
00041 //      
00042 CResponse* CResponse::NewL()
00043         {
00044         CResponse* self = CResponse::NewLC();
00045         CleanupStack::Pop(self);
00046         return self;
00047         }
00048 
00049 // ----------------------------------------------------
00050 // CResponse::NewLC()
00051 // Two-phased constructor.
00052 // ----------------------------------------------------
00053 //      
00054 CResponse* CResponse::NewLC()
00055         {
00056         CResponse* self = new (ELeave) CResponse;
00057         CleanupStack::PushL(self);
00058         self->ConstructL();
00059         return self;
00060         }
00061 
00062 // ----------------------------------------------------
00063 // CResponse::ConstructL()
00064 // Symbian OS default constructor can leave.
00065 // ----------------------------------------------------
00066 //      
00067 void CResponse::ConstructL()
00068         {
00069         iDescriptions = new (ELeave) CDesCArrayFlat(1);
00070     iMessageBuffer = HBufC::NewL(0);
00071         }
00072 
00073 // ----------------------------------------------------
00074 // CResponse::InputDataL()
00075 // This functions constructs a response object from the 
00076 // data received from the server. E.g. if aData contains 
00077 // tasks, tasks are parsed to arrays, where they can be 
00078 // easily fetched. 
00079 // ----------------------------------------------------
00080 //      
00081 void CResponse::ParseDataL( TDesC& aData )
00082         {
00083         // error occurred in the server side (i.e. the aData begins #Error: ).
00084         if (KError() == aData.Left(7))
00085                 {
00086                 iState = EError;
00087                 // remove the #-character.
00088                 iError = aData.Mid(1);
00089                 return;
00090                 }
00091         
00092         // response for completing task.
00093         if (aData.Find(KOkMessage) != KErrNotFound)
00094                 {
00095                 iResponseType = ETaskComplete;
00096                 return;
00097                 }
00098                 
00099         TLex lex(aData);
00100         TTaskReadStatus status = EStart;
00101         
00102         // Tasks are in form: #id#description#id#description#
00103         while (!lex.Eos())
00104                 {
00105                 if (lex.Peek() == TChar(KSeparator()[0]))
00106                         {
00107                         switch (status)
00108                                 {
00109                                 // first #-character found
00110                                 case EStart:
00111                                         {
00112                                         status = EReadId;
00113                                         break;
00114                                         }
00115                                 // read the id of the tasks.
00116                                 case EReadId:
00117                                         {
00118                                         status = EReadTask;
00119                                         TInt id;
00120                                         TLex tmp(lex.MarkedToken());
00121                                         User::LeaveIfError(tmp.Val(id));
00122                                         User::LeaveIfError(iIds.Append(id));
00123                                         break;
00124                                         }
00125                                 // read the description of the task.
00126                                 case EReadTask:
00127                                         {
00128                                         status = EReadId;
00129                                         TPtrC task = lex.MarkedToken();
00130                                         iDescriptions->AppendL(task);
00131                                         break;
00132                                         }
00133                                 }
00134                         lex.Inc();
00135                         lex.Mark();
00136                         }
00137                 else
00138                         {
00139                         lex.Inc();      
00140                         }
00141                 }       
00142         }
00143 
00144 // ----------------------------------------------------
00145 // CResponse::HasError()
00146 // Returns whether errors occurred in the server side 
00147 // or not.
00148 // ----------------------------------------------------
00149 //      
00150 TBool CResponse::HasError() const
00151         {
00152         TBool retval = EFalse;
00153         if (iError.Length() > 0)
00154                 {
00155                 retval = ETrue;
00156                 }
00157         return retval;
00158         }
00159 
00160 // ----------------------------------------------------
00161 // CResponse::Error()
00162 // Returns the error description. 
00163 // ----------------------------------------------------
00164 //      
00165 TBuf<KMaxError> CResponse::Error() const
00166         {
00167         return iError;
00168         }
00169 
00170 // ----------------------------------------------------
00171 // CResponse::TaskCount()
00172 // Returns the amount of tasks received from the server. 
00173 // ----------------------------------------------------
00174 //      
00175 TInt CResponse::TaskCount() const
00176         {
00177         return iIds.Count();
00178         }
00179 
00180 // ----------------------------------------------------
00181 // CResponse::TaskDescription()
00182 // Returns a task description. 
00183 // ----------------------------------------------------
00184 //      
00185 TBuf<KMaxTaskLength> CResponse::TaskDescription(const TInt& aIndex) const
00186         {
00187         if (aIndex >= iDescriptions->Count() || 0 > aIndex)
00188                 {
00189                 Panic(ETaskManagerInvalidTaskIndex);
00190                 }
00191                 
00192         return (*iDescriptions)[aIndex];
00193         }
00194 
00195 // ----------------------------------------------------
00196 // CResponse::TaskId()
00197 // Returns a task id. 
00198 // ----------------------------------------------------
00199 //      
00200 TInt CResponse::TaskId(const TInt& aIndex) const
00201         {
00202         if (aIndex >= iDescriptions->Count() || 0 > aIndex)
00203                 {
00204                 Panic(ETaskManagerInvalidTaskIndex);
00205                 }
00206 
00207         return iIds[aIndex];
00208         }
00209 
00210 // ----------------------------------------------------
00211 // CResponse::ResponseType()
00212 // Returns the type of this response. 
00213 // ----------------------------------------------------
00214 //      
00215 CResponse::TResponseType CResponse::ResponseType() const
00216         {
00217         return iResponseType;
00218         }
00219 
00220 // ----------------------------------------------------
00221 // CResponse::InputDataL()
00222 // Makes it possible to store a part of the data into the
00223 // CResponse class.
00224 // ----------------------------------------------------
00225 //      
00226 void CResponse::InputDataL( const TDesC8& aData )
00227     {
00228     iMessageBuffer = iMessageBuffer->ReAllocL(iMessageBuffer->Length() + aData.Length());
00229     HBufC* newData = HBufC::NewLC(aData.Length());
00230     newData->Des().Copy(aData);
00231     iMessageBuffer->Des() += newData->Des();
00232     CleanupStack::PopAndDestroy(newData);
00233     
00234     DoCheck();
00235     }
00236 
00237 // ----------------------------------------------------
00238 // CResponse::DoCheck()
00239 // Does a check on the received package and sets the state
00240 // that determines what the engine should do next.
00241 // ----------------------------------------------------
00242 //      
00243 void CResponse::DoCheck()
00244     {
00245         if( iExpectedPackageSize == 0 )
00246                 {
00247                 // We try to extract the size of the package, which should be found in the beginning
00248                 // of the package, before the first separator character
00249                 TInt separatorIndex = iMessageBuffer->Find( KSeparator );
00250 
00251                 if( separatorIndex == KErrNotFound )
00252                         { // The size of the package can't be read before the first separator sign is found
00253             iState = ENotComplete;
00254             return;
00255                         }
00256 
00257         // Extracted size is converted into TInt
00258                 TPtrC sizePtr = iMessageBuffer->Left( separatorIndex );
00259 
00260                 TLex converter( sizePtr );
00261                 if( converter.Val( iExpectedPackageSize ) != KErrNone )
00262                         { // conversion failed
00263             iState = EError;
00264             return;
00265                         }
00266                 }
00267 
00268     TBuf<6> asciiSize;
00269     asciiSize.Num( iExpectedPackageSize );
00270 
00271     if( iMessageBuffer->Length() - asciiSize.Length() < iExpectedPackageSize )
00272         { // The entire package hasn't been received
00273         iState = ENotComplete;
00274         return;
00275         }
00276 
00277     iExpectedPackageSize = 0;
00278 
00279     // The size component is cut from the message
00280     TPtrC data = iMessageBuffer->Right( iMessageBuffer->Length() -
00281                                         iMessageBuffer->Find( KSeparator ) );
00282     
00283         TRAPD(error, ParseDataL( data );)
00284         PanicIfError(error);
00285         
00286         iState = EComplete;
00287     }
00288 
00289 // ----------------------------------------------------
00290 // CResponse::GetState()
00291 // Returns the state to the engine.
00292 // ----------------------------------------------------
00293 //      
00294 CResponse::TResponseState CResponse::GetState() const
00295     {
00296     return iState;
00297     }
00298 
00299 // End of file

Generated by  doxygen 1.6.2