/meaop

Automatically exported from code.google.com/p/meaop

Primary LanguagePascal

MeSDK Library
the MeSDK provides a light and small object implementation for core developing
it includes the MeObjects, MeRTTI, and MeAOP etc.

The MeAOP Library is Aspect Oriented Programming for delphi. IMO, the aspect is the general feature in fact. It's a helper for 
object-oriented programming to re-use the feature(function), such as the Login feature. Aspect Oriented Programming 
attempts to aid programmers in the separation of features, or the breaking down of a program into distinct parts that 
overlap in functionality as little as possible. 

  * distill/separate the general features from many classes;
  * many classes can share the feature, so it need not to modify many classes if the feature've been changed.
  * no necessary to modify the method when adding a new feature to the method.


* MeObjects *
MeObjects Library for Delphi is a light object extension to make object type small and powerful. It makes the object type
supports the ClassType, InheritsFrom and ClassName like the Class Type, but it's mini and faster than the delphi class type.
You can treat it as mini-class type. The MeObjects Library is the MeSDK core too.

** uMeObjects.pas **

TMeDynamicObject
summary: the abstract MeObject mini-class.

TMeNamedObject
  add the name property and assign virtual method.

TMeComponent
  set the name property will be added to GComponentNameList.

TMeInterfacedObject
  supports the FreeNotifies and Destroyed only when reference count < 0 

TMeContainer
  abstract data Container

TMeList
  Simple list of pointers. It is used instead of standard VCL TList.
  TMeList stores any kind data (or pointers to these ones). Can be created
  calling function New(PMeList, Create) or use as the record object directly. 

TMeStrings
  maintains a list of strings. 

TMeDynamicMemory
  supports the Dynamic Memory can auto increase the memory size

TMeStream
  abstract stream object

TMeNamedObjects
  maintains the PMeNamedObject list.

helper functions:

function NewMeObject(const aClass: TMeClass): PMeDynamicObject;
summary: create a instance by the aClass:TypeOf(TMeList).

procedure MeFreeAndNil(var Obj); {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
summary: Frees an object reference and replaces the reference with nil.

function MeTypeOf(const aObj: TMeVMTHelper): TMeClass; {$IFDEF PUREPASCAL}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{$ENDIF}
 MeTypeOf(aObj) = TypeOf(aObj) = TMeClass(aObj) 
 It Should cast the aObj directly !! the MeTypeOf is not useful!

function MeSizeOf(const aObj: TMeVMTHelper): Integer; {$IFDEF PUREPASCAL}{$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}{$ENDIF}
summary return the size of aObj.

function MeInheritsFrom(aClass: TMeClass; const aParentClass: TMeClass): Boolean;
Summary: Determines the relationship of two object types.
Use InheritsFrom to determine if a particular class type or object is an instance of a class or one of its descendants. InheritsFrom returns true if the object type specified in the aClass parameter is an ancestor of the object type or the type of the object itself. Otherwise, it returns false.

function SetMeVirtualMethod(const aClass: TMeClass; const Offset: Integer; const Method: Pointer): Pointer;
summary: replace the VirtualMethod of the MeObject to new Method Pointer. return the original method entry pointer.
Note: first you must set the proper parent class type via SetMeVirtualMethod in the initiliazation section:
  SetMeVirtualMethod(TypeOf(TMeInterfacedObject), ovtVmtParent, TypeOf(TMeDynamicObject));

function FindMeComponent(const Name: String): PMeComponent;

function GComponentNameList: PMeList;

procedure SortIntegerArray(var A : array of Integer);
Summary procedure to sort array of integers. 

procedure SortDwordArray(var A : array of LongWord);
Summary Procedure to sort array of unsigned 32-bit integers.

procedure SortData(const Data: Pointer; const aCount: LongWord; const CompareFun: TCompareEvent;
                    const SwapProc: TSwapEvent);
Summary Call it to sort any array of data of any kind, passing total
   number of items in an array and two defined (regular) function
   and procedure to perform custom compare and swap operations.
   First procedure parameter is to pass it to callback function
   CompareFun and procedure SwapProc. Items are enumerated from
   0 to aCount-1.

procedure FillListIn(List: TMeList; FromIdx, Count, Value: Integer);
Summary Very fast fill Value to List elements from List[FromIdx] to List[FromIdx+Count-1].
   Given elements must exist. Count must be > 0.


** uMeStream.pas **
the stream objects It is used instead of standard VCL Stream class.
TMeFileStream
TMeMemoryStream

** uMeLog.pas **
the Logging of Application class.

TMeCustomLogger
the abstract logger class for logging .
  TMeCustomLogger is an abstract class that
  defines a framework for logging general
  purposed information.

TMeRootLogger
the singleton root logger class for logging
  AddLogger the logger object here. the logging message can be sent to the AddLoggered logger.

TMeStringsLogger
  for logging information to the MeStrings.

TMeStreamLogger
  abstract stream logger for logging information to the MeStream.

TMeDebugLogger
  for logging information to the DebugOutput stream.
  extends the framework for logging information to the DebugOutput stream.
  
  TMeDebugLogger provides a flexible means of selecting 
  the destination of log messages. Messages can be 
  written to either a file or the WIN32 API Debug 
  Output stream.
  
  TMeDebugLogger is very useful for capturing information 
  for debugging, trouble-shooting, and general 
  feedback purposes.


function GLogger: PMeRootLogger;

how to usage:
  // do not free these loggers added to the GLogger will do this for u..
  GLogger.AddLogger(New(PMeStringsLogger, Create(vStrs)));
  GLogger.AddLogger(New(PMeDebugLogger, Create));

  GLogger.Info(aText);

** uMeLoggerEx **
the extented logger objects.

TMeFileLogger
Summary for logging information to the file.


** uMeCoroutine **
implements the coroutine object. (main algo code come from sjrd (based on an idea of Bart van der Werf))
    CoRoutines management classes CoRoutines provides two main classes. TMeCustomCoRoutine is the base class for CoRoutine management. TMeCoRoutineEnumerator is a derived class, specialised in Delphi 2005 enumerators implementation. This unit needs tests under Windows 95/98/Me, in case of growth of the stack, because PAGE_GUARD is not supported under these versions.

TMeCustomCoRoutine
CoRoutine support class
    The Resume method can't be executed twice at the same moment. It can't be
    called simultaneously in two separate threads ; nor can it be called from
    Execute (which should cause recursive call).
    However, it can be called successively by two separate threads.

    The Execute method shoud test for the Terminating property after each call
    to Yield, and terminate itself gracefully if Terminating is True. It will
    be set so when the TMeCustomCoRoutine object must release itself, before running
    the CoRoutine again. If you call Yield when Terminating is True, an
    ECoRoutineTerminating exception will be raised in order to ensure that
    Execute ends immediately.

    The amount of simultaneous instances of TMeCustomCoRoutine must never exceed 32 K,
    because each one must reserve a virtual memory range of 64 Ko minimum.

TMeCoRoutine

TMeCoRoutineEnumerator
the abstract enumerator running in a CoRoutine
    In order to obtain a concrete enumerator, you must override the Execute and
    SetNextValue methods, and define a Current property. The Execute method can
    call Yield many times with any value as a parameter. The SetNextValue must
    store this value, and the Current property should read it.
    @author sjrd, based on an idea of Sergey Antonov
    @version 1.0


** uMeYield.pas **
the another CoRoutine implementation(no switch stack) (main algo code come from Sergey Antonov.)

TMeCustomCoRoutine
TMeCoRoutineEnumerator

** uRegExpr.pas **
  The Initial Developers of the Original Code are Andrey V. Sorokin(RegExpr).
 v. 0.948+ 2003-12-17 by riceball
  + SubExprName define and parse: "():SubExprName:"
  + property MatchStrPos, MatchStrLen, MatchStr by SubExprName index.
  + function GetSubExprIndexByName
  + property SubExprNames to get the SubExprName by integer index.
  + Subtitute the SubExprName by : $[SubExprName].
  * the SubExprName is CaseSensitive!
 v. 0.980 2008-5-30 by riceball
  * more speedup for a large-text search.
    * remove Length(aPChar) in ExecPrim 
      //len := Length(aPChar); it will be very slow on a large pchar.
  + procedure SetSubjectStr(const Value: RegExprString);
  + procedure SetSubjectStr(const Value: PRegExprChar);
      it do not assigned the InputString, just point it directly. so u must do not free the string(be careful)!!
  + keep the more compatible with the Perl RegExpr: (?:....)
      the non-capuring Group, but not whole impl it.
  + \-[1..9]: means prev SubExpr in Expression.
    (['|"])\S+\-1
    match: 'dddd', "word".
  + add more compatible with the Perl RegExpr:  (?<name>...) or (?'name'...)
  + add compatible with the Python RegExpr:  (?P<name>...)

** uMeRegExpr.pas **
the RegExpr extension object 

** uMeRegExprCoRoutine.pas **
the CoRountine object of the MeRegExpr 


** uMeThread.pas **
the Thread object for the MeSDK Core.

TMeAbstractThread
  used to instead of the Borland Thread Class 

TMeTask
  the abstract task object

TMeCustomThread
  the abstract thread with task

TMeThread
  the thread with task supported.
    the task can be schedule task. the task can be destroyed when thread free.
    One thread can run a task again and again until stop.
      a task: beforeRun, Run, afterRun Cleanup
      you can change task after Cleanup.
    One thread can run different task one by one.
    Thread.Terminate: Terminate the thread. the thread can not be re-used.
    thread.Stop: if the StopMode is smSuspend then it can be re-used.
                 it always be sure the AfterRun can be executed.

    
    aThread := NewThreadTask(myTask);
    aThread.Start;

TMeThreadMgrTask
    the TMeThreadMgrTask task uses manage the threads with pool(if set the FMaxThreads is greater than 0).
    the task will be free automatic after done if FreeTask is true.
    note: if the exception occur even the FreeTask is false, it will still free the task when thread free.
    unless override the task.HandleException method and set the aThread.task := nil;
      
  
    Usage: 
     FThreadForMgr := New(PMeThread, Create(New(PMeThreadMgr, Create)));
     //FThreadForMgr.Name := 'The Thread For Mgr'; //need check the compiler directive: NamedThread!

    vMgr := PMeThreadMgr(FThreadForMgr.Task);
    for i := 1 to 3 do
    begin
      New(vTask, Create);
      vTask.Id := i;
      vTask.Count := i;
      vMgr.Add(vTask); //the task can be added after running too.
    end;
    FThreadMgr.Start;
    Writeln('Run....');
    Sleep(3000);
    FThreadForMgr.TerminateAndWaitFor;
    MeFreeAndNil(FThreadForMgr);


TMeThreadMgr
  the thread run the the TMeThreadMgrTask task.

function NewThreadTask(const aTask: PMeTask): PMeThread;
Summary: create a thread instance with aTask.

procedure EnterMainThread;
procedure LeaveMainThread;
   EnterMainThread/LeaveMainThread can be used to temporary switch to the
   main thread. The code that should be synchonized (blocking) has to be put
   into a try/finally block and the LeaveMainThread() function must be called
   from the finally block. A missing try/finally will lead to an access violation.
   
   * All local variables can be used. (EBP points to the thread's stack while
     ESP points the the main thread's stack)
   * Unhandled exceptions are passed to the surrounding thread.
   * The integrated Debugger is not able to follow the execution flow. You have
     to use break points instead of "Step over/in".
   * Nested calls to EnterMainThread/LeaveMainThread are ignored. But they must
     strictly follow the try/finally structure.

   Example:

     procedure MyThreadProc;
     var
       S: string;
     begin
       Assert(GetCurrentThreadId <> MainThreadId);
       S := 'Hallo, I''m executed in the main thread';

       EnterMainThread;
       try
         Assert(GetCurrentThreadId = MainThreadId);
         ShowMessage(S);
       finally
         LeaveMainThread;
       end;

       Assert(GetCurrentThreadId <> MainThreadId);
     end;
    @author  Andreas Hausladen

** uMeSyncObjs.pas **
collects the thread synchronization objects instead of the standard SyncObjs of Delphi.


TMeEvent

TMeMutex

TMeCriticalSection


** uMeSysUtils.pas **
some helper functions and classes.

TMeThreadSafeList
Summary: represents a thread-safe list.

procedure AddFreeNotification(const aInstance : TObject; const aProc : TFreeNotifyProc);
 Summary: Ensures that aProc is notified that the aInstance is going to be destroyed.}
 Desccription: Use AddFreeNotification to register aProc that should be notified when the aInstance is about to be destroyed. 

procedure RemoveFreeNotification(const aInstance : TObject; const aProc : TFreeNotifyProc);
 Summary: Disables destruction notification that was enabled by AddFreeNotification.}
 Description: RemoveFreeNotification removes the NotificationProc specified by the aProc parameter
    from the internal list of procedures to be notified that the aInstance is about to be destroyed. 
    aProc is added to this list by a previous call to the AddFreeNotification function.

//the thread safe version:
function FormatDateTimeS(const Format: string; aDateTime: TDateTime): string;
function FormatS(const aFormat: string; const Args: array of const): string;
function TimeToStrS(const aTime: TDateTime): string;
function DateToStrS(const aDate: TDateTime): string;
function DateTimeToStrS(const aDateTime: TDateTime): string;

procedure GetDefaultFormatSettings(var Result: TFormatSettings);

//return GMT now.
function GMTNow: TDateTime;


** uMeInjector **
the method(procedure) Code Injector
  Provide the lightest and simplest injector object -- TMeInjector.
  This object do not use any virtual method, so you can use it directly.
  Each injector only take 36 bytes about in the memory. One injector 
  maintains the one injected method(procedure) only. Call the InjectXXX 
  Method to inject. The injector object is the smallest, simplest and 
  fastest object in the MeAOP .

TMeInjector
Provide the lightest and simplest injector object to inject function or method.
  This object do not use any virtual method, so you can use it directly.
  Each injector only take 36 bytes about in the memory. One injector 
  maintains the one injected method(procedure) only. Call the InjectXXX 
  Method to inject. The injector object is the smallest, simplest and 
  fastest object in the MeAOP .

Usage:
var
  OldMessageBoxFunc: function (hWnd: HWND; lpText, lpCaption: PChar;
    uType: UINT): Integer; stdcall = nil;

function NewMessageBoxFunc(hWnd: HWND; lpText, lpCaption: PChar;
  uType: UINT): Integer; stdcall;
var
  S: String;
begin
  S := UpperCase(lpText);
  Result := OldMessageBoxFunc(hWnd, PChar(S), PChar('MeInjector:'+lpCaption), uType)
end;

var
  vMsgBoxInjector: TMeInjector;

begin
  vMsgBoxInjector.InjectProcedure(@MessageBox, @NewMessageBoxFunc);
  @OldMessageBoxFunc := vMsgBoxInjector.OriginalProc

  //the string 'the injected message box' should be UpperCase now.
  MessageBox(0, 'the injected message box','Demo2', 0);

  vMsgBoxInjector.Enabled := False;
end.


** uMeURI.pas **
Represents the Uniform Resource Identifier object.

** uMeURL.pas **
the abstract Uniform/Universal Resource Accessor class and factory.


* MeRTTI *
the Mini Run-time Type Infomation of Object. the MeType is stream-able.

* MeAOP *
The MeAOP Library is Aspect Oriented Programming for delphi. IMO, the aspect is the general feature in fact. It's a helper for 
object-oriented programming to re-use the feature(function), such as the Login feature. Aspect Oriented Programming 
attempts to aid programmers in the separation of features, or the breaking down of a program into distinct parts that 
overlap in functionality as little as possible. 

  * distill/separate the general features from many classes;
  * many classes can share the feature, so it need not to modify many classes if the feature've been changed.
  * no necessary to modify the method when adding a new feature to the method.

I treat the Aspect Oriented Programming as Feature Oriented Programming.

* MeRemote *
The MeRemote Features Library is the remote function and remote object Library for delphi. It's the feature-layer of the MeAOP.

* MeService *
The MeService Library is a mini general SOA(service(plugin)-oriented architecture) system framework. 

* MeScript *
the MeSDK Script Engine Core. It's the functional language script engine. but not ready yet.