diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/euserhlexample_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/euserhlexample_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1308 +0,0 @@ - - -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
- -