diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/euserhlexample_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/euserhlexample_8cpp-source.html Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,1308 @@ + + +TB10.1 Example Applications: examples/SysLibs/EUserHLExample/src/euserhlexample.cpp Source File + + + + +

examples/SysLibs/EUserHLExample/src/euserhlexample.cpp

00001 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+00002 // All rights reserved.
+00003 // This component and the accompanying materials are made available
+00004 // under the terms of "Eclipse Public License v1.0"
+00005 // which accompanies this distribution, and is available
+00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
+00007 //
+00008 // Initial Contributors:
+00009 // Nokia Corporation - initial contribution.
+00010 //
+00011 // Contributors:
+00012 //
+00013 // Description:
+00014 //
+00015 
+00016 #include <f32file.h>
+00017 #include <e32cons.h>
+00018 #include <euserhl.h>
+00019 
+00020 
+00021 _LIT(KTxtExample,"EUsableExample\n");
+00022 _LIT(KTxtPressAnyKeyToContinue,"Press any key to continue\n");
+00023 
+00024 CConsoleBase* gConsole;
+00025 
+00032 _LIT(KPath, "c:\\a\\b\\c");
+00033 _LIT(KOne, "One ");
+00034 _LIT(KTwo, "Two ");
+00035 _LIT(KTesting, "Testing ");
+00036 
+00037 void MaybeLeave()
+00038         {
+00039         // Some code that may leave
+00040         }
+00041 
+00042 HBufC* AllocateNameL(const TDesC& aDes)
+00043         {
+00044         return aDes.AllocL();
+00045         }
+00046 
+00047 void GetCurrentPath(TDes& aDes)
+00048         {
+00049         aDes = KPath;
+00050         }
+00051 
+00052 void GetCurrentPathString(LString& aString)
+00053         {
+00054         aString = KPath; // Will auto-grow if necessary, may leave
+00055         }
+00056 
+00057 LString AppendCurrentPathStringL(LString aString)
+00058         {
+00059         /*
+00060         This method accepts and returns LStrings by value. It works but
+00061         is not recommended due to the inherent inefficiencies.
+00062         */
+00063         LString result(aString);
+00064         result += KPath;
+00065         return result;
+00066         }
+00067 
+00068 class CTicker : public CBase
+00069         {
+00070 public:
+00071         void Tick() { ++iTicks; }
+00072         void Tock() { ++iTocks; }
+00073 
+00074         void Zap() { delete this; }
+00075 
+00076 public:
+00077         TInt iTicks;
+00078         TInt iTocks;
+00079         };
+00080 
+00081 // Defines a custom pointer cleanup policy that calls the Zap member
+00082 class TTickerZapStrategy
+00083         {
+00084 public:
+00085         static void Cleanup(CTicker* aPtr)
+00086                 {
+00087                 /*
+00088                 The general template/class scaffolding remains the same
+00089                 for all custom cleanups, just this cleanup body varies
+00090                 */
+00091                 aPtr->Zap();
+00092                 _LIT(KTxtPrintZapp, "Zapped CTicker\n");
+00093                 gConsole->Printf(KTxtPrintZapp);
+00094                 }
+00095         };
+00096 
+00097 void RegisterTicker(CTicker& aTicker)
+00098         {
+00099         (void)aTicker;
+00100         }
+00101 
+00102 void RegisterTickerPtr(CTicker* aTicker)
+00103         {
+00104         (void)aTicker;
+00105         }
+00106 
+00107 void TakeTickerOwnership(CTicker* aTicker)
+00108         {
+00109         delete aTicker;
+00110         }
+00111 
+00112 void RegisterTimer(RTimer& aTimer)
+00113         {
+00114         (void)aTimer;
+00115         }
+00116 
+00117 // Defines a custom handle cleanup policy that calls Cancel() then Close()
+00118 class TCancelClose
+00119         {
+00120 public:
+00121         template <class T>
+00122         static void Cleanup(T* aHandle)
+00123                 {
+00124                 /*
+00125                 The general template/class scaffolding remains the same
+00126                 for all custom cleanups, just this cleanup body varies
+00127                 */
+00128                 aHandle->Cancel();
+00129                 aHandle->Close();
+00130                 _LIT(KTxtCancel,"Cancel Closed RTimer\n");
+00131                 gConsole->Printf(KTxtCancel);
+00132                 }
+00133         };
+00134 
+00135 void BespokeCleanupFunction(TAny* /*aData*/)
+00136         {
+00137         _LIT(KTxtCleanup,"BespokeCleanupFunction\n");
+00138         gConsole->Printf(KTxtCleanup);
+00139         }
+00140 
+00141 // The walkthroughs themselves
+00142 
+00149 class CStringUserTwoPhase : public CBase
+00150         {
+00151 public:
+00152         static CStringUserTwoPhase* NewL(const TDesC& aName)
+00153                 {
+00154                 /*
+00155                 We can use the resource management utility classes in
+00156                 two-phase if we want.
+00157                 */
+00158                 LCleanedupPtr<CStringUserTwoPhase> self(new(ELeave) CStringUserTwoPhase);
+00159                 self->Construct(aName);
+00160                 /*
+00161                 Calling Unmanage() disables cleanup and yields the
+00162                 previously managed pointer so that it can be safely
+00163                 returned
+00164                 */
+00165                 return self.Unmanage(); 
+00166                 }
+00167 
+00168         virtual void Construct(const TDesC& aName)
+00169                 {
+00170                 /*
+00171                 This assignment may leave if LString fails to allocate a
+00172                 heap buffer large enough to hold the data in aName
+00173                 */
+00174                 iName = aName; 
+00175                 }
+00176 
+00177         ~CStringUserTwoPhase()
+00178                 {
+00179                 // The iName LString cleans up after itself automatically 
+00180                 }
+00181 
+00182         const TDesC& Name() 
+00183                 {
+00184                 // We can just return an LString directly as a const TDesC
+00185                 return iName; 
+00186                 }
+00187 
+00188 protected:
+00189         CStringUserTwoPhase()
+00190                 {
+00191                 /*
+00192                 Everything interesting happens in ConstructL in this
+00193                 version. 
+00194 
+00195                 Default initialization of the iName LString does not
+00196                 allocate a heap buffer, and so cannot leave. As long as
+00197                 initialization is deferred to ConstructL, LStrings can be
+00198                 used safely with two-phase construction.
+00199                 */
+00200                 }
+00201 
+00202 protected:
+00203         LString iName;
+00204         };
+00205 
+00217 class CStringUserSinglePhase : public CBase
+00218         {
+00219 public:
+00220         /*
+00221         This macro is necessary to ensure cleanup is correctly handled
+00222         in the event that a constructor may leave beneath a call to
+00223         new(ELeave)
+00224         */
+00225         CONSTRUCTORS_MAY_LEAVE
+00226 
+00227         static CStringUserSinglePhase* NewL(const TDesC& aName)
+00228                 {
+00229                 return new(ELeave) CStringUserSinglePhase(aName);
+00230                 }
+00231 
+00232         ~CStringUserSinglePhase()
+00233                 {
+00234                 // The iName LString cleans up after itself automatically
+00235                 }
+00236 
+00237         const TDesC& Name() 
+00238                 {
+00239                 // We can just return an LString directly as a const TDesC
+00240                 return iName;
+00241                 }
+00242 
+00243 protected:
+00244         CStringUserSinglePhase(const TDesC& aName)
+00245                 /*
+00246                 This initialization of iName may leave because LString
+00247                 needs to allocate a heap buffer to copy the aName string
+00248                 data into
+00249                 */
+00250                 : iName(aName) 
+00251                 {
+00252                 /*
+00253                 If iName initialization is successful but the constructor
+00254                 then goes on to leave later, iName (like all fields fully
+00255                 constructed at the point of a leave in a constructor) will
+00256                 be destructed, and so clean up after itself
+00257                 */
+00258                 MaybeLeave();
+00259                 }
+00260 
+00261 protected:
+00262         LString iName;
+00263         };
+00264 
+00265 
+00266 void WalkthroughStringsL()
+00267         {
+00268         _LIT(KTxtOption1,"Option1: String handling using EUser high level library\n");
+00269     gConsole->Printf(KTxtOption1);
+00270     _LIT(KTxtFormatString,"String %d");
+00271     _LIT(KTxtPrintString,"String %d = %S\n");
+00272        {
+00273                 // Trivially exercise the LString using classes defined above
+00274 
+00275                 LCleanedupPtr<CStringUserTwoPhase> one(CStringUserTwoPhase::NewL(KOne));
+00276                 _LIT(KTxtSinglePhaseConstructor,"Single phase name: %S\n");
+00277                 gConsole->Printf(KTxtSinglePhaseConstructor, &one->Name());
+00278 
+00279                 LCleanedupPtr<CStringUserSinglePhase> two(CStringUserSinglePhase::NewL(KTwo));
+00280                 _LIT(KTxtTwoPhaseConstructor,"Single phase name: %S\n");
+00281                 gConsole->Printf(KTxtTwoPhaseConstructor, &two->Name());
+00282 
+00283                 gConsole->Printf(KTxtPressAnyKeyToContinue);
+00284                 gConsole->Getch();
+00285                 // Both instances are automatically deleted as we go out of scope
+00286                 }
+00287 
+00288                 {
+00289                 /*
+00290                 A default constructed LString starts empty, doesn't
+00291                 allocate any memory on the heap, and therefore the
+00292                 following cannot leave
+00293                 */
+00294                 LString s;
+00295 
+00296                 /*
+00297                 But it will grow on demand if you assign to it, so it has
+00298                 enough space to hold the copied string data, and so
+00299                 assignment may leave
+00300                 */
+00301                 s = KOne;
+00302 
+00303                 /*
+00304                 Similarly if you append to it with the leaving variant of
+00305                 Append(), AppendL(), if may grow on demand
+00306                 */
+00307                 s.AppendL(KTwo);
+00308 
+00309                 // The += operator for LString also maps to AppendL()
+00310                 _LIT(KThree, "Three ");
+00311                 s += KThree;
+00312 
+00313                 /*
+00314                 You can also use new leaving format methods that also grow
+00315                 on demand
+00316                 */
+00317                 s.AppendFormatL(KTesting);
+00318 
+00319                 /*
+00320                 This general style of use of LString may be preferable to
+00321                 typical descriptor use for a number of reasons e.g. it
+00322                 avoids the common temptation to set an artificial maximum
+00323                 buffer size; it avoids massive conservative over-allocation
+00324                 when the average case length of a string is far less than
+00325                 the worst-case maximum; it will not surprise you (compared
+00326                 to the alternative of a large stack-allocated TBuf) by
+00327                 triggering stack overflow.
+00328                 */
+00329 
+00330                 // An LString can be printed the same way as any descriptor
+00331                 _LIT(KTxtValue,"Value: %S\n");
+00332                 gConsole->Printf(KTxtValue, &s);
+00333 
+00334                 // An LString can be compared the same way as any descriptor
+00335                 _LIT(KTxtLStringCompare," Comparing LString with a literal is successful\n");
+00336                 _LIT(KPhrase, "One Two Three Testing ");
+00337                 if(s == KPhrase)
+00338                         {
+00339                         gConsole->Printf(KTxtLStringCompare);
+00340                         }
+00341 
+00342                 // An LString supports all TDesC and TDes methods
+00343                 _LIT(KTxtLStringSupportedAPI1,"LString supports TDesC and TDes methods\n");
+00344                 if(s.Find(KTwo) == 4)
+00345                         {
+00346                         gConsole->Printf(KTxtLStringSupportedAPI1);     
+00347                         }
+00348                 // An LString supports all TDesC and TDes operators
+00349                 _LIT(KTxtLStringSupportedAPI2,"LString supports TDesC and TDes operators\n");
+00350                 if(s[4] == TChar('T'))
+00351                         {
+00352                         gConsole->Printf(KTxtLStringSupportedAPI2);
+00353                         }
+00354                 TInt untrimmed = s.Length();
+00355                 s.Trim();
+00356                 if(s.Length() == untrimmed - 1)
+00357                         {
+00358                         //LString supports Trim API
+00359                         }
+00360 
+00361                 s.UpperCase();
+00362                 _LIT(KTxtPrintUpperCase,"UpperCase: %S\n");
+00363                 gConsole->Printf(KTxtPrintUpperCase, &s);
+00364                 s.LowerCase();
+00365                 _LIT(KTxtPrintLowerCase,"UpperCase: %S\n");
+00366                 gConsole->Printf(KTxtPrintLowerCase, &s);
+00367                 gConsole->Printf(KTxtPressAnyKeyToContinue);
+00368                 gConsole->Getch();
+00369                 /*
+00370                 The underlying heap allocated buffer is released
+00371                 automatically when the LString goes out of scope, either
+00372                 normally or through a leave
+00373                 */
+00374                 }
+00375 
+00376                 {
+00377                 // You can initialize with a MaxLength value
+00378                 LString s(KMaxFileName); // This operation may leave
+00379                 if(s.MaxLength() == KMaxFileName)
+00380                         {       
+00381                         //LString supports MaxLength API
+00382                         }
+00383 
+00384                 /*
+00385                 And you can dynamically adjust MaxLength later using 
+00386                 SetMaxLengthL() if you want an exact allocated size.
+00387                 Setting MaxLength() on construction or via SetMaxLengthL() is
+00388                 exact; calling MaxLength() immediately afterwards is
+00389                 guaranteed to return exactly the value you specified.
+00390                 */
+00391                 s.SetMaxLengthL(2 * KMaxFileName);
+00392                 if(s.MaxLength() == 2 * KMaxFileName)
+00393                         {
+00394                         //MaxLength is successfully adjusted.
+00395                         }
+00396 
+00397                 /*
+00398                 Pre-setting MaxLength is important when passing an LString
+00399                 as a TDes to a library function, because the LString can't
+00400                 be auto-grown via the TDes API.
+00401                 */
+00402 
+00403                 }
+00404 
+00405                 {
+00406                 /*
+00407                 You can initialize from any descriptor (or literal) and the
+00408                 string data is copied into the LString
+00409                 */
+00410                 LString s(KOne); // From a literal
+00411                 s += KTwo;
+00412                 LString half(s.Left(s.Length() / 2)); // Left returns a TPtrC
+00413                 _LIT(KTxtPrintAllandHalf,"All: %S, Half: %S\n");
+00414                 gConsole->Printf(KTxtPrintAllandHalf, &s, &half);
+00415 
+00416                 /*
+00417                 On the other hand, you can initialize from a returned
+00418                 HBufC* and the LString automatically takes ownership
+00419                 */
+00420                 LString own(AllocateNameL(KTesting));
+00421                 _LIT(KTxtOwnedString,"What I own: %S\n");
+00422                 gConsole->Printf(KTxtOwnedString, &own);
+00423 
+00424                 /*
+00425                 Following that you can re-assign an HBufC to an existing
+00426                 string using the assignment operator 
+00427                 taking ownership of the new content. 
+00428                 */
+00429                 own = AllocateNameL(KTesting);
+00430                 
+00431                 /*
+00432                 Following that you can re-assign an HBufC to an existing
+00433                 string. The string destroys its original content before
+00434                 taking ownership of the new content. 
+00435                 */
+00436                 own.Assign(AllocateNameL(KTesting));
+00437                 
+00438                 /*
+00439                 The content of one string can similarly be assigned
+00440                 to another to avoid copying. In this example, the content 
+00441                 is detached from 's' and transfered to 'own'.
+00442                 */  
+00443                 own.Assign(s);
+00444                 
+00445                 /*
+00446                 The same content transfer can be achieved from an RBuf to a
+00447                 string. You may need to do this if a legacy method returns
+00448                 you an RBuf. The RBuf is emptied of its content.
+00449                 */
+00450                 RBuf16 buf;
+00451                 buf.CreateL(KOne);
+00452                 own.Assign(buf);
+00453         
+00454                 /*
+00455                 You can also assign a simple text array to a string as its
+00456                 new buffer. This method initialises the length to zero.
+00457                 */   
+00458                 own.Assign((TText*)User::Alloc(24*(TInt)sizeof(TText)), 24);
+00459                 
+00460                 /*
+00461                 If the buffer has already been filled with some characters
+00462                 then you supply the length in this alternative Assign() method.
+00463                 */   
+00464                 own.Assign((TText*)User::Alloc(24*(TInt)sizeof(TText)), 12,24);
+00465                 gConsole->Printf(KTxtPressAnyKeyToContinue);
+00466                 gConsole->Getch();
+00467                 /*
+00468                 Each Assign() destroys the old content before assuming ownership
+00469                 of the new.
+00470                 As usual the last content of the string is destroyed when the 
+00471                 LString goes out of scope
+00472                 */
+00473                 }
+00474 
+00475                 {
+00476                 /*
+00477                 You can reserve extra free space in preparation for an 
+00478                 operation that adds characters to the string. You may
+00479                 need to do this when you cannot use any of the auto-buffer
+00480                 extending LString methods to achieve your objective.
+00481                 */
+00482                 LString s(KOne);
+00483                 s.ReserveFreeCapacityL(4);
+00484                 if(s.Length() == 4)
+00485                         {
+00486                         //Length() API gives the current length of the string
+00487                         }
+00488                 if(s.MaxLength() >= 8)
+00489                         {
+00490                         //MaxLength() gives the maximum length supported by the string
+00491                         }
+00492 
+00493                 /*
+00494                 Almost all the methods that may extend the string buffer,
+00495                 including the explicit ReserveFreeCapacityL(), but excluding
+00496                 SetMaxLengthL(), attempt to grow the size exponentially. 
+00497                 The exponential growth pattern is expected to give better 
+00498                 performance at an amortised complexity of O(n) when adding n characters.
+00499                 If the exponential growth is less than the supplied extra size
+00500                 then the supplied size is used instead to save time.
+00501                 The exponential growth is used in anticipation of further additions
+00502                 to a string. This trades-off speed efficiency for space efficiency.
+00503                 If required you may be able to swap the oversized buffer for 
+00504                 a more compact one using:
+00505                 */
+00506                 s.Compress();
+00507                 if(s.MaxLength() >= 4)
+00508                         {
+00509                         //Compress() API is used to compress the unused memory.
+00510                         }
+00511                     
+00512                 /*
+00513                 Resize() attempts to re-allocate a smaller buffer to copy
+00514                 the content into. If the new memory cannot be allocated then the
+00515                 original string is left unaffected. 
+00516                 
+00517                 When you have finished using the content of a string you can
+00518                 get its buffer released without destroying the string itself. 
+00519                 You may want to do this when using member declared strings.
+00520                 Automatic strings are destroyed when they go out of scope.
+00521                 */
+00522                 s.Reset();
+00523                 if(s.Length() == 0)
+00524                         {
+00525                         //Buffer of the string is released, hence length is zero.
+00526                         }
+00527                 if(s.MaxLength() == 0)
+00528                         {
+00529                         //Buffer of the string is released, hence maximum length is zero.
+00530                         }
+00531                 
+00532                 }
+00533 
+00534                 {
+00535                 /*
+00536                 An LString can be passed directly to any function requiring
+00537                 a const TDesC&
+00538                 */
+00539                 TInt year = 2009;
+00540 
+00541                 LString s;
+00542                 _LIT(KTxtFormatYear1,"Happy New Year %d");
+00543                 s.FormatL(KTxtFormatYear1, year);
+00544                 // InfoPrint() takes a const TDesC&
+00545                 User::InfoPrint(s);
+00546 
+00547                 LString pattern;
+00548                 _LIT(KTxtFormatYear2,"*Year %d");
+00549                 pattern.FormatL(KTxtFormatYear2, year);
+00550                 // Match() takes a const TDesC& as a pattern
+00551                 TInt loc = s.Match(pattern);
+00552                 if(loc == 10)
+00553                         {
+00554                         //Match() API is demonstrated successfully.
+00555                         }
+00556                 }
+00557 
+00558                 {
+00559                 /*
+00560                 An LString can be passed directly to any function requiring
+00561                 a TDes& but care must always be taken to pre-set MaxLength()
+00562                 since LStrings can't be automatically grown via the TDes
+00563                 interface
+00564                 */
+00565 
+00566                 LString s;
+00567                 /*
+00568                 Calling GetCurrentPath(s) now would panic because LStrings
+00569                 are initialized by default to MaxLength 0.  Although s is
+00570                 an LString GetCurrentPath() takes a TDes& and so inside the function
+00571                 's' behaves as a TDes and would panic with USER 11 if the resulting 
+00572                 new length of s is greater than its maximum length.
+00573                 */
+00574                 if(s.MaxLength() == 0)
+00575                         {
+00576                         //LStrings are initialized by default to MaxLength 0
+00577                         }
+00578 
+00579                 /*
+00580                 Calling SetMaxLengthL() will automatically realloc the
+00581                 underlying buffer if required, and is guaranteed to leave
+00582                 MaxLength() equal to the specified value
+00583                 */
+00584                 s.SetMaxLengthL(KMaxFileName);
+00585                 GetCurrentPath(s);
+00586                 _LIT(KTxtPrintPath,"Path: %S\n");
+00587                 gConsole->Printf(KTxtPrintPath, &s);
+00588                 if(s == KPath)
+00589                         {
+00590                         //String comparison is successful
+00591                         }
+00592 
+00593                 /*
+00594                 If SetMaxLengthL() adjusts MaxLength() to be lower than the current
+00595                 Length(), the data is truncated to the new MaxLength() and
+00596                 Length() set to the new MaxLength().
+00597                 */
+00598                 s.SetMaxLengthL(s.Length() / 2);
+00599                 _LIT(KTxtTruncatedPath,"Truncated path: %S\n");
+00600                 gConsole->Printf(KTxtTruncatedPath, &s);
+00601                 if(s.Length() == s.MaxLength())
+00602                         {
+00603                         //String comparison is successful
+00604                         }
+00605 
+00606                 /*
+00607                 An initial MaxLength() can be specified when constructing an
+00608                 LString. Note that unlike the default constructor, this
+00609                 variant allocates and may leave.
+00610                 */
+00611                 LString s2(KMaxFileName);
+00612                 GetCurrentPath(s2);
+00613                 gConsole->Printf(KTxtPrintPath, &s2);
+00614                 if(s2 == KPath)
+00615                         {
+00616                         //String comparison is successful
+00617                         }
+00618 
+00619                 /*
+00620                 Your code and APIs can benefit from LString's auto-growth
+00621                 behaviour by accepting an LString to fill in as an output
+00622                 parameter. Using LString rather than TDes parameters means 
+00623                 that the function is able to safely increase the size of the 
+00624                 string as the LString will re-allocate as necessary
+00625                 */
+00626                 LString s3;
+00627                 // GetCurrentPathString() takes an LString&
+00628                 GetCurrentPathString(s3);
+00629                 gConsole->Printf(KTxtPrintPath, &s3);
+00630                 if(s3 == KPath)
+00631                         {
+00632                         //String comparison is successful
+00633                         }
+00634 
+00635                 /*
+00636                 As a well-defined value class, if you want to, LStrings can
+00637                 be passed and returned by value. This is relatively
+00638                 inefficient however due to the amount of copying and heap
+00639                 reallocation involved. 
+00640                 */
+00641                 LString s4(AppendCurrentPathStringL(s3));
+00642                 _LIT(KTxtAppendedPath,"Appended path: %S\n");
+00643                 gConsole->Printf(KTxtAppendedPath, &s4);
+00644                 if(s4.Length() == s3.Length() * 2)
+00645                         {
+00646                         //String comparison is successful
+00647                         }
+00648                 }
+00649 
+00650                 {
+00651                 /*
+00652                 LStrings can be allocated on the heap if necessary. 
+00653                 Then it can managed as part of an array of string pointers.
+00654                 */
+00655                 TInt n = 5;
+00656                 LCleanedupHandle<RPointerArray<LString>, TResetAndDestroy> sarray;
+00657                 
+00658                 for (TInt i = 0; i < n; ++i) 
+00659                         {
+00660                         LString* s = new(ELeave) LString;
+00661                         s->FormatL(KTxtFormatString, i);
+00662                         sarray->Append(s);
+00663                         }
+00664 
+00665                 for (TInt i = 0, n = sarray->Count(); i < n; ++i) 
+00666                         {
+00667                         LString tmp;
+00668                         tmp.FormatL(KTxtFormatString, i);
+00669                         if(tmp == *(*sarray)[i])
+00670                                 {
+00671                                 
+00672                                 }
+00673                         gConsole->Printf(KTxtPrintString, i, (*sarray)[i]);
+00674                         }
+00675 
+00676                 }
+00677 
+00678                 {
+00679                 /*
+00680                 Any allocation failure in new(ELeave)LString throws
+00681                 KErrNoMemory and cleans up fully after itself.
+00682                 */
+00683 
+00684                 __UHEAP_MARK;
+00685                 TRAPD(status, new(ELeave) LString(100 * 1024 * 1024));
+00686                 if(status == KErrNoMemory)
+00687                         {
+00688                         //cleans up after itself fully, there is no need to take any further action.
+00689                         }
+00690                 __UHEAP_MARKEND;
+00691                 }
+00692 
+00693                 {
+00694                 /*
+00695                 Native C arrays (both heap and stack allocated) of LStrings
+00696                 also work, although their use is not recommended.
+00697                 */
+00698 
+00699                 TInt n = 5;
+00700                 LCleanedupArray<LString> sarray(new(ELeave) LString[n]);
+00701 
+00702                 for (TInt i = 0; i < n; ++i) 
+00703                         {
+00704                         sarray[i].FormatL(KTxtFormatString, i);
+00705                         }
+00706 
+00707                 for (TInt i = 0; i < n; ++i) 
+00708                         {
+00709                         LString tmp;
+00710                         tmp.FormatL(KTxtFormatString, i);
+00711                         if(tmp == sarray[i])
+00712                                 {
+00713                                 //comparison of strings is successful
+00714                                 }
+00715                         gConsole->Printf(KTxtPrintString, i, &sarray[i]);
+00716                         }
+00717 
+00718                 }
+00719                 
+00720         }
+00721 
+00727 class CManagedUserTwoPhase : public CBase
+00728         {
+00729 public:
+00730         static CManagedUserTwoPhase* NewL(CTicker* aTicker)
+00731                 {
+00732                 /*
+00733                 We can use the resource management utility classes in
+00734                 two-phase if we want to.
+00735                 */
+00736                 LCleanedupPtr<CManagedUserTwoPhase> self(new(ELeave) CManagedUserTwoPhase);
+00737                 self->ConstructL(aTicker);
+00738                 /*
+00739                 Calling Unmanage() disables cleanup and yields the
+00740                 previously managed pointer so that it can be safely
+00741                 returned.
+00742                 */
+00743                 return self.Unmanage(); 
+00744                 }
+00745 
+00746         ~CManagedUserTwoPhase()
+00747                 {
+00748                 /*
+00749                 The iTicker manager will automatically delete the CTicker
+00750                 The iTimer manager will automatically Close() the RTimer.
+00751                 */
+00752                 }
+00753 
+00754         CTicker& Ticker()
+00755                 {
+00756                 // If we dereference the management object we get a CTicker&.
+00757                 return *iTicker;
+00758                 }
+00759 
+00760         RTimer& Timer()
+00761                 {
+00762                 // If we dereference the management object we get an RTimer&.
+00763                 return *iTimer;
+00764                 }
+00765 
+00766 private:
+00767         
+00768         virtual void ConstructL(CTicker* aTicker)
+00769                 {
+00770                 // Take ownership and manage aTicker.
+00771                 iTicker = aTicker; 
+00772 
+00773                 // Note use of -> to indirect through the management wrapper.
+00774                 iTimer->CreateLocal() OR_LEAVE; 
+00775                 }
+00776         
+00777         CManagedUserTwoPhase()
+00778                 {
+00779                 /*
+00780                 Everything interesting happens in ConstructL() in this
+00781                 version. 
+00782 
+00783                 Default initialization of the iName LString does not
+00784                 allocate a heap buffer, and so cannot leave. As long as
+00785                 initialization is deferred to ConstructL(), LStrings can be
+00786                 used safely with two-phase construction.
+00787                 */
+00788                 }
+00789 
+00790 private:
+00791         // We have to use LManagedXxx for fields, not LCleanedupXxx
+00792         LManagedPtr<CTicker> iTicker;
+00793         LManagedHandle<RTimer> iTimer;
+00794         };
+00795 
+00808 class CManagedUserSinglePhase : public CBase
+00809         {
+00810 public:
+00811         /*
+00812         This macro is necessary to ensure cleanup is correctly handled
+00813         in the event that a constructor may leave beneath a call to
+00814         new(ELeave)
+00815         */
+00816         CONSTRUCTORS_MAY_LEAVE
+00817 
+00818         static CManagedUserSinglePhase* NewL(CTicker* aTicker)
+00819                 {
+00820                 return new(ELeave) CManagedUserSinglePhase(aTicker);
+00821                 }
+00822 
+00823         ~CManagedUserSinglePhase()
+00824                 {
+00825                 /*
+00826                 The iTicker manager destructor will automatically Zap() the CTicker.
+00827                 The iTimer manager destructor will automatically Close() the RTimer.
+00828                 */
+00829                 }
+00830 
+00831         CTicker& Ticker()
+00832                 {
+00833                 // If we dereference the management object we get a CTicker&.
+00834                 return *iTicker;
+00835                 }
+00836 
+00837         RTimer& Timer()
+00838                 {
+00839                 // If we dereference the management object we get an RTimer&.
+00840                 return *iTimer;
+00841                 }
+00842 
+00843 private:
+00844         CManagedUserSinglePhase(CTicker* aTicker)
+00845                 /*
+00846                 Take ownership and manage aTicker. Note that initialization
+00847                 of the LManagedXxx classes does not actually leave, but
+00848                 initialization of the LCleanedupXxx classes can.
+00849                 */
+00850                 : iTicker(aTicker)
+00851                 {
+00852                 /*
+00853                 If iTicker initialization is successful but the constructor
+00854                 then goes on to leave later, iTicker (like all fields fully
+00855                 constructed at the point of a leave in a constructor) will
+00856                 be destructed, and the manager will cleanup the CTicker.
+00857 
+00858                 Note use of -> to indirect through the management wrapper.
+00859                 */
+00860                 iTimer->CreateLocal(); 
+00861 
+00862                 // Likewise if we leave here, both iTicker and iTimer will
+00863                 // undergo managed cleanup.
+00864                 MaybeLeave();
+00865                 }
+00866 
+00867 private:
+00868         // We have to use LManagedXxx for fields, not LCleanedupXxx.
+00869         LManagedPtr<CTicker, TTickerZapStrategy> iTicker;
+00870         LManagedHandle<RTimer> iTimer;
+00871         };
+00872 
+00873 //Class definition of trivial R-Class
+00874 class RSimple
+00875         {
+00876 public:
+00877         
+00878         RSimple(){iData = NULL;}
+00879         
+00880         //Open function sets value
+00881         void OpenL(TInt aValue)
+00882                 {
+00883                 iData = new(ELeave) TInt(aValue);
+00884                 }
+00885         
+00886         //Cleanup function – frees resource
+00887         void Close()
+00888                 {
+00889                 delete iData;
+00890                 iData = NULL;
+00891                 }
+00892 
+00893         //Cleanup function – frees resource
+00894         void Free()
+00895                 {
+00896                 delete iData;
+00897                 iData = NULL;
+00898                 }
+00899 
+00900         //Cleanup function – frees resource
+00901         void ReleaseData()
+00902                 {
+00903                 delete iData;
+00904                 iData = NULL;
+00905                 }
+00906         
+00907         //static cleanup function – frees aRSimple resources
+00908         static void Cleanup(TAny* aRSimple)
+00909                 {
+00910                 static_cast<RSimple*>(aRSimple)->Close();
+00911                 }
+00912 
+00913 
+00914 private:
+00915         TInt* iData;
+00916 
+00917         };
+00918 
+00919 
+00926 DEFINE_CLEANUP_FUNCTION(RSimple, ReleaseData);
+00927 
+00928 
+00929 void WalkthroughManagedL()
+00930         {
+00931         _LIT(KTxtOption2,"Option2: Object creation and resource management using EUser high level library\n");
+00932         gConsole->Printf(KTxtOption2);
+00933                 {
+00934                 // Trivially exercise the manager-using classes defined above.
+00935                 CTicker* ticker1 = new(ELeave) CTicker;
+00936                 LCleanedupPtr<CManagedUserTwoPhase> one(CManagedUserTwoPhase::NewL(ticker1));
+00937                 if(&one->Ticker() == ticker1)
+00938                         {
+00939                         _LIT(KTxtLCleanedupPtrDemo1,"Creating an instance of CTicker using LCleanedupPtr\n");
+00940                         gConsole->Printf(KTxtLCleanedupPtrDemo1);
+00941                         }
+00942                 one->Timer().Cancel(); // Just to check we can get at it
+00943 
+00944                 CTicker* ticker2 = new(ELeave) CTicker;
+00945                 LCleanedupPtr<CManagedUserSinglePhase> two(CManagedUserSinglePhase::NewL(ticker2));
+00946                 if(&two->Ticker() == ticker2)
+00947                         {
+00948                         _LIT(KTxtLCleanedupPtrDemo2,"Creating second instance of CTicker using LCleanedupPtr\n");
+00949                         gConsole->Printf(KTxtLCleanedupPtrDemo2);
+00950                         }
+00951                 two->Timer().Cancel(); // Just to check we can get at it
+00952         _LIT(KTxtLCleanedupPtr,"Both instances are automatically deleted as we go out of scope\n");
+00953         gConsole->Printf(KTxtLCleanedupPtr);
+00954         gConsole->Printf(KTxtPressAnyKeyToContinue);
+00955         gConsole->Getch();
+00956                 }
+00957 
+00958                 // Always use LCleanedupXxx for locals, not LManagedXxx
+00959 
+00960                 {
+00961                 /*
+00962                 Behind the scenes the LCleanedupXxx constructors push a
+00963                 cleanup item onto the cleanup stack and so may leave. If
+00964                 there is a leave during construction, the supplied pointer
+00965                 will still get cleaned up.
+00966                 */
+00967                 LCleanedupPtr<CTicker> t(new(ELeave) CTicker);
+00968 
+00969                 /*
+00970                 We can access CTicker's members via the management object
+00971                 using ->
+00972                 */
+00973                 t->Tick();
+00974                 t->Tock();
+00975                 if(t->iTicks == t->iTocks)
+00976                         {
+00977                         _LIT(KTxtLCleanedupPtrDemo3,"CTicker members access using LCleanedupPtr is successful\n");
+00978                         gConsole->Printf(KTxtLCleanedupPtrDemo3);
+00979                         gConsole->Printf(KTxtPressAnyKeyToContinue);
+00980                 gConsole->Getch();
+00981                         }
+00982 
+00983                 /*
+00984                 We can get at a reference to the managed object using *
+00985                 when we need to, e.g. if we need to pass it to a function.
+00986                 */
+00987                 RegisterTicker(*t); // Takes a CTicker&
+00988 
+00989                 /*
+00990                 If some unfriendly interface needs a pointer rather than a
+00991                 ref, we have a couple of options.
+00992                 */
+00993                 RegisterTickerPtr(&*t); // Takes a CTicker*
+00994                 RegisterTickerPtr(t.Get()); // Takes a CTicker*
+00995 
+00996                 /*
+00997                 Note the use of . in t.Get() above; this distinguishes
+00998                 operations on the managing type from operations on the
+00999                 managed object.
+01000                 
+01001                 When the management object goes out of scope, either
+01002                 normally or as the result of a leave, the managed object is
+01003                 automatically deleted.
+01004                 */
+01005                 }
+01006 
+01007                 {
+01008                 /*
+01009                 Sometimes you need to protect something temporarily before
+01010                 transferring ownership e.g. by returning the pointer or
+01011                 passing it to a function that takes ownership.
+01012                 */
+01013 
+01014                 LCleanedupPtr<CTicker> t(new(ELeave) CTicker);
+01015 
+01016                 // Protected while we do this
+01017                 MaybeLeave(); 
+01018 
+01019                 /*
+01020                 But now we want to hand it off, so we use Unmanage() to
+01021                 both return a pointer and break the management link
+01022                 */
+01023                 TakeTickerOwnership(t.Unmanage());
+01024                 
+01025                 /*
+01026                 Now when it goes out of scope, no cleanup action is
+01027                 performed.
+01028                 */
+01029                 }
+01030 
+01031                 {
+01032                 /*
+01033                 If needed, it is possible to reuse a manager by using = to
+01034                 assign it a new managed object.
+01035                 */
+01036 
+01037                 // Not managing anything to start with
+01038                 LCleanedupPtr<CTicker> t;
+01039                 if(t.Get() == NULL)
+01040                         {
+01041                         //Successfully initialised to NULL
+01042                         }
+01043                 if(&*t == NULL)
+01044                         {
+01045                         //CTicker* value is also NULL
+01046                         }
+01047 
+01048                 for (TInt i = 0; i < 10; ++i)
+01049                         {
+01050                         /*
+01051                         If an object is already being managed, it is cleaned up
+01052                         before taking ownership of the new object.
+01053                         */
+01054                         t = new(ELeave) CTicker;
+01055                         }
+01056                 /*
+01057                 We're left owning the final ticker instance, all prior
+01058                 instances having been automatically deleted.
+01059                 */
+01060                 }
+01061 
+01062                 {
+01063                 // If you have stateful code where a pointer can sometimes be NULL.
+01064                 LCleanedupPtr<CTicker> t(new(ELeave) CTicker);
+01065 
+01066                 // Does t refer to NULL?
+01067                 if (!t)
+01068                         {
+01069                         _LIT(KTxtNull,"LCleanedupPtr object refers to Null\n" );
+01070                         gConsole->Printf(KTxtNull);
+01071                         }
+01072 
+01073                 t = NULL; // Also releases the currently managed CTicker 
+01074 
+01075                 // Does t refer to a non-NULL pointer?
+01076                 if (t)
+01077                         {
+01078                         _LIT(KTxtNonNull,"LCleanedupPtr object refers to Non Null pointer\n" );
+01079                         gConsole->Printf(KTxtNonNull);
+01080                         }
+01081                 }
+01082 
+01083                 {
+01084                 // LCleanedupPtr uses delete to cleanup by default, but alternative cleanups can be specified
+01085 
+01086                 // We just want to free this one and not invoke the destructor
+01087                 LCleanedupPtr<CTicker, TPointerFree> t(static_cast<CTicker*>(User::AllocL(sizeof(CTicker))));
+01088 
+01089                 // Now User::Free() is called when t goes out of scope
+01090                 }
+01091 
+01092                 {
+01093                 /*
+01094                 As well as the stock options, custom cleanup policies can
+01095                 also be defined. See above for the definition of
+01096                 TTickerZap.
+01097                 */
+01098                 LCleanedupPtr<CTicker, TTickerZapStrategy> t(new(ELeave) CTicker);
+01099 
+01100                 // Now Zap() is called on the CTicker instance when t goes out of scope
+01101                 }
+01102 
+01103                 {
+01104                 /*
+01105                 LCleanedupHandle is very similar in behaviour to
+01106                 LCleanedupPtr, the main difference being that it can define
+01107                 and contain its own instance of a handle rather than
+01108                 being supplied one.
+01109                 */
+01110                 LCleanedupHandle<RTimer> t;
+01111 
+01112                 // Again, access to managed handle members is via ->
+01113                 t->CreateLocal() OR_LEAVE;
+01114                 t->Cancel();
+01115 
+01116                 //We can get a reference to the handle for passing to functions using *
+01117                 RegisterTimer(*t);
+01118 
+01119                 /*
+01120                 When the management object goes out of scope, either
+01121                 normally or as the result of a leave, the managed object is
+01122                 automatically cleanup by calling Close() on it.
+01123                 */
+01124                 }
+01125 
+01126                 {
+01127                 /*
+01128                 LCleanedupHandle calls Close() by default, but alternative
+01129                 cleanups can be specified.
+01130                 
+01131                 We want this RPointerArray cleanup with with
+01132                 ResetAndDestroy instead of Close().
+01133                 */
+01134                 LCleanedupHandle<RPointerArray<HBufC>, TResetAndDestroy> array;
+01135                 for (TInt i = 0; i < 10; ++i) 
+01136                         {
+01137                         array->AppendL(HBufC::NewL(5));
+01138                         }
+01139 
+01140                 //Now when array goes out of scope, ResetAndDestroy is called to clean it up.
+01141                 }
+01142 
+01143                 {
+01144                 /*
+01145                 As well as the stock options, custom cleanup policies can
+01146                 also be defined. See above for the definition of TCancelClose.
+01147                 */
+01148                 LCleanedupHandle<RTimer, TCancelClose> t;
+01149                 t->CreateLocal();
+01150 
+01151                 // Now Cancel() followed by Close() are called when t goes out of scope
+01152                 }
+01153 
+01154 
+01155                 {
+01156                 /*
+01157                 LCleanedupHandleRef calls Close() by default, but alternative
+01158                 cleanups can be specified.
+01159                 
+01160                 We want this RPointerArray cleanup with
+01161                 ResetAndDestroy instead of Close().
+01162                 */
+01163                 RPointerArray<HBufC> rar;
+01164                 // calls to functions that cannot leave here
+01165                 rar.Append(HBufC::NewL(5));
+01166                 rar.Append(HBufC::NewL(5));
+01167 
+01168 
+01169                 LCleanedupRef<RPointerArray<HBufC>, TResetAndDestroy> array(rar);
+01170                 // calls to functions that could leave here
+01171                 for (TInt i = 0; i < 10; ++i) 
+01172                         {
+01173                         array->AppendL(HBufC::NewL(5));
+01174                         }
+01175 
+01176                 // Now when array goes out of scope, ResetAndDestroy is called to clean it up
+01177                 }
+01178 
+01179                 {
+01180                 /*
+01181                 Never mix direct cleanup stack API calls with management
+01182                 class use within the same function, because their
+01183                 interaction can be confusing and counter-intuitive. Avoid
+01184                 the use of LC methods that leave objects on the cleanup
+01185                 stack, and use L methods instead.
+01186 
+01187                 If a badly-behaved API were to offer only an LC variant,
+01188                 you would have to use it as follows
+01189                 */
+01190                 HBufC* raw = HBufC::NewLC(5);
+01191                 // Must pop immediately to balance the cleanup stack, before instantiating the manager
+01192                 CleanupStack::Pop(); 
+01193                 LCleanedupPtr<HBufC> wrapped(raw);
+01194 
+01195                 /*
+01196                 Never do this:
+01197                 LCleanedupPtr<HBufC> buf(HBufC::NewLC(5));
+01198                 CleanupStack::Pop();
+01199                 because the manager will be popped (having been pushed
+01200                 last), not the raw buf pointer as you might have hoped
+01201 
+01202                 A cleaner alternative may be to write your own L function
+01203                 wrapper around the LC function supplied.
+01204 
+01205                 Luckily this situation (an LC method without a
+01206                 corresponding L method) is rare in practice.
+01207                 */
+01208                 }
+01209 
+01210                 {
+01211                 // Although rarely used on Symbian platform, C++ arrays are supported with a custom management class
+01212                 LCleanedupArray<CTicker> array(new CTicker[5]);
+01213 
+01214                 // The array is cleaned up with delete[] on scope exit
+01215                 }
+01216 
+01217                 {
+01218                 /*
+01219                 Although most cases are best covered by applying custom
+01220                 cleanup policies to the management classes already
+01221                 described, there is also a general TCleanupItem style
+01222                 cleanup option.
+01223                 */
+01224                 TAny* data = NULL; // But could be anything
+01225                 LCleanedupGuard guard1(BespokeCleanupFunction, data);
+01226                 // On scope exit BespokeCleanupFunction() is called on data.
+01227 
+01228                 LCleanedupGuard guard2(BespokeCleanupFunction, data);
+01229                 // But cleanup can also be disabled in this case, as follows:
+01230                 guard2.Dismiss();
+01231                 }
+01232                 
+01233                 {
+01234                 LCleanedupHandle<RFs> managedFs;
+01235                 managedFs->Connect();
+01236                 //default cleanup strategy is to call RFs::Close() on scope exit;
+01237                 }
+01238                 
+01239                 {
+01240                 LCleanedupHandle<RSimple, TFree> simple;
+01241                 simple->OpenL(23);
+01242                 //Specified cleanup strategy is to call RSimple::Free() on scope exit;
+01243                 }
+01244         
+01245                 /*
+01246                 Because the DEFINE_CLEANUP_FUNCTION is defined above, the default
+01247                 cleanup function for RSimple is RSimple::ReleaseData() rather than
+01248                 RSimple::Close()
+01249                 */
+01250                 {
+01251                 LCleanedupHandle<RSimple> simple;
+01252                 simple->OpenL(23);
+01253                 //Custom cleanup strategy is to call RSimple::ReleaseData() on scope exit
+01254                 }
+01255                 
+01256                 {
+01257                 RSimple simple;
+01258                 
+01259                 //The RSimple class above defines a static cleanup function
+01260                 //RSimple::Cleanup().
+01261                 LCleanedupGuard guard(RSimple::Cleanup, &simple);
+01262 
+01263                 simple.OpenL(10);
+01264                 
+01265                 //On scope exit RSimple::Cleanup() is called passing &simple.
+01266                 }
+01267         }
+01268 
+01269 void WalkthroughUsageL()
+01270         {
+01271         _LIT(KTxtOption3,"Option3: Memory used by EUser high level classes\n");
+01272         gConsole->Printf(KTxtOption3);
+01273         RFile file;
+01274         
+01275         _LIT(KTxtSizeofRFile,"Size of RFile = %d\n");
+01276         gConsole->Printf(KTxtSizeofRFile, sizeof(file));
+01277         
+01278         LCleanedupHandle<RFile> cFile;
+01279         
+01280         _LIT(KTxtSizeofLCleanedupHandleRFile,"Size of LCleanedupHandle<RFile> = %d\n");
+01281         gConsole->Printf(KTxtSizeofLCleanedupHandleRFile, sizeof(cFile));
+01282         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01283         gConsole->Getch();
+01284         
+01285         LCleanedupRef<RFile> crFile(file);      
+01286         _LIT(KTxtSizeofLCleanedupRefRFile,"Size of LCleanedupRef<RFile> = %d\n");
+01287         gConsole->Printf(KTxtSizeofLCleanedupRefRFile, sizeof(crFile));
+01288         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01289         gConsole->Getch();
+01290 
+01291         CTicker* tracker = new(ELeave) CTicker;
+01292         _LIT(KTxtSizeofCTracker,"Size of CTracker* = %d\n");
+01293         gConsole->Printf(KTxtSizeofCTracker, sizeof(tracker));
+01294         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01295         gConsole->Getch();
+01296         
+01297         LCleanedupPtr<CTicker> cTracker(tracker);
+01298         _LIT(KTxtSizeofLCleanedupHandleCTicker,"Size of LCleanedupPtr<CTicker> = %d\n");
+01299         gConsole->Printf(KTxtSizeofLCleanedupHandleCTicker, sizeof(LCleanedupPtr<CTicker>));
+01300         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01301         gConsole->Getch();
+01302         }
+01303 
+01304 TInt TestL()
+01305         {
+01306         gConsole=Console::NewL(KTxtExample,TSize(KConsFullScreen,KConsFullScreen));
+01307         CleanupStack::PushL(gConsole);
+01308         gConsole->Printf(KTxtExample);
+01309         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01310         gConsole->Getch();      
+01311         WalkthroughStringsL();
+01312         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01313         gConsole->Getch();
+01314         WalkthroughManagedL();
+01315         gConsole->Printf(KTxtPressAnyKeyToContinue);
+01316         gConsole->Getch();
+01317         WalkthroughUsageL();
+01318         _LIT(KTxtPressAnyKeyToExit,"\nPress any key to exit");
+01319         gConsole->Printf(KTxtPressAnyKeyToExit);
+01320         gConsole->Getch();
+01321         CleanupStack::PopAndDestroy(gConsole); // delete the gConsole
+01322         return KErrNone;
+01323         }
+01324 
+01325 TInt E32Main()
+01326         {       
+01327         __UHEAP_MARK;
+01328         CTrapCleanup* cleanup=CTrapCleanup::New(); // Create clean-up stack.
+01329         TInt status;
+01330         if(cleanup!=NULL)
+01331                 {
+01332             TRAP(status, TestL());
+01333                 __ASSERT_ALWAYS(!status,User::Panic(KTxtExample,status));
+01334                 }
+01335         delete cleanup; // Delete clean-up stack.       
+01336         __UHEAP_MARKEND;
+01337         
+01338         return status;
+01339         }
+01340 
+01341 
+01342 // eof
+

Generated on Thu Jan 21 10:33:00 2010 for TB10.1 Example Applications by  + +doxygen 1.5.3
+ +