Написать о том как использование "шаблонов" и "примесей" избавляет от "косвенности" и лишнего распределения памяти.
На примере Tm3HeaderStream.
Можно ведь так:
А можно так:
Мне кажется, что второй вариант - "вкуснее".
Смежные темы:
- Абстрактные контейнеры
- Абстрактные контейнеры. Часть 2
- Пояснение про контейнеры
- Выводим конкретные атомарные контейнеры из абстрактных
- Конкретные контейнеры. Часть 2
- Стандартная библиотека шаблонов
- Коротко. САМОЕ удивительное знание, которое я вынес из книг о программировании
- ToDo. Написать про массивы, списки и итераторы
- Про скрипты, итераторы и обработку исключений. Черновик
Старый код Tm3HeaderStream:
Новый код, я вскоре выложу.
Он НА ПОРЯДОК - короче и читабельнее.
Вот уж как "быдло-код" становится "просто кодом" (
- http://programmingmindstream.blogspot.ru/2014/08/blog-post_59.html
- http://programmingmindstream.blogspot.ru/2014/08/mindstream-firemonkey.html?showComment=1407782559954#c112802013383687686
- http://programmingmindstream.blogspot.ru/2014/08/di-service-locator.html
).
На примере Tm3HeaderStream.
Можно ведь так:
type TA = class private fData : Pointer; private procedure AllocData; protected function DataSize: Integer; virtual; abstract; end;//TA ... TC = record ... end;//TC TB = class(TA) protected function DataSize: Integer; override; end;//TB ... procedure TA.AllocData; begin GetMem(fData, DataSize); end; ... function TB.DataSize: Integer; override; begin Result := SizeOf(TC); end;
А можно так:
type TA<T> = class private fData : T; end;/TA ... TC = record ... end;/TC TB = class(TA<TC>) end;//TB
Мне кажется, что второй вариант - "вкуснее".
Смежные темы:
- Абстрактные контейнеры
- Абстрактные контейнеры. Часть 2
- Пояснение про контейнеры
- Выводим конкретные атомарные контейнеры из абстрактных
- Конкретные контейнеры. Часть 2
- Стандартная библиотека шаблонов
- Коротко. САМОЕ удивительное знание, которое я вынес из книг о программировании
- ToDo. Написать про массивы, списки и итераторы
- Про скрипты, итераторы и обработку исключений. Черновик
Старый код Tm3HeaderStream:
type
Tm3CustomHeaderStream= class(Tm3CustomStream)
{* Поток с заголовком-идентификатором. }
private
_Status: LongWord;
function InitProc00000001 (const ABitMask: LongWord
): LongWord;
procedure DoneProc00000001 (
);
function InitProc00000002 (const ABitMask: LongWord
): LongWord;
procedure DoneProc00000002 (
);
function InitProc00000004 (const ABitMask: LongWord
): LongWord;
procedure DoneProc00000004 (
);
function InitProc00000008 (const ABitMask: LongWord
): LongWord;
procedure DoneProc00000008 (
);
function InitProc00000010 (const ABitMask: LongWord
): LongWord;
procedure DoneProc00000010 (
);
protected
procedure CreateContext (
); override;
private
FHeaderData: Pointer;
FHeaderDataCompare: Pointer;
FHeaderDataSize: LongInt;
FHeaderFullSize: LongInt;
FHeaderSize: LongInt;
FHeaderLoaded: LongInt;
FHeaderLocked: LongInt;
protected
procedure Cleanup;
override;
{-}
property _HeaderData: Pointer read FHeaderData;
function InitHeaderData (
): Pointer; virtual; abstract;
function InitHeaderDataSize (
): LongInt; virtual; abstract;
function InitHeaderFullSize (
): LongInt; virtual; abstract;
procedure DefaultInitAction (
); virtual;
procedure DefaultDoneAction (
); virtual;
procedure Read (ABuff: Pointer;
ASize: LongInt;
var AResult: LongInt;
var AReturn: HRESULT
); override;
procedure Write (ABuff: Pointer;
ASize: LongInt;
var AResult: LongInt;
var AReturn: HRESULT
); override;
procedure Seek (AOffset : Int64;
AOrigin : TSeekOrigin;
var AResult : Int64;
var AReturn : HRESULT
); override;
procedure SetSize (ASize: Int64;
var AReturn: HRESULT
); override;
procedure LockRegion (AOffset: Int64;
ASize: Int64;
ALockType: LongInt;
var AReturn: HRESULT
); override;
procedure UnlockRegion (AOffset: Int64;
ASize: Int64;
ALockType: LongInt;
var AReturn: HRESULT
); override;
function pm_GetSize: Int64;
override;
{-}
function pm_GetLocksSupported: Longint;
override;
{-}
procedure StatStgName(var AResult : PWideChar;
var AReturn : HRESULT);
override;
{-}
public
class function HeaderID (
): TCLSID; virtual; abstract;
constructor Create (const AStream: IStream;
const AAccess: LongInt
);
{* - создает поток c заголовком вокруг потока aStream. }
procedure LoadHeader (
);
{* - загружает заголовок в память. }
procedure SaveHeader (const AForcedSave: LongBool = False
);
{* - сохраняет заголовок. }
procedure LockHeader (
);
{* - закрывает заголовок. }
procedure UnlockHeader (
);
{* - открывает заголовок. }
end;//Tm3CustomHeaderStream
...
// start class Tm3CustomHeaderStream
function Tm3CustomHeaderStream.InitProc00000001(const ABitMask: LongWord): LongWord;
begin
{$IfDef m3UseL3Memory}
m3HeaderBuffers^.AllocItem(FHeaderData, FHeaderFullSize, InitHeaderData, FHeaderDataSize);
{$Else m3UseL3Memory}
m2MEMAllocBuff(FHeaderData,FHeaderFullSize,InitHeaderData,FHeaderDataSize);
{$EndIf m3UseL3Memory}
Result:=ABitMask;
end;
procedure Tm3CustomHeaderStream.DoneProc00000001;
begin
{$IfDef m3UseL3Memory}
m3HeaderBuffers^.FreeItem(FHeaderData);
{$Else m3UseL3Memory}
m2MEMFree(FHeaderData);
{$EndIf m3UseL3Memory}
end;
function Tm3CustomHeaderStream.InitProc00000002(const ABitMask: LongWord): LongWord;
begin
if not ReadOnly then
{$IfDef m3UseL3Memory}
m3HeaderBuffers^.AllocItem(FHeaderDataCompare, FHeaderFullSize, InitHeaderData, FHeaderDataSize);
{$Else m3UseL3Memory}
m2MEMAllocBuff(FHeaderDataCompare,FHeaderFullSize,InitHeaderData,FHeaderDataSize);
{$EndIf m3UseL3Memory}
Result:=ABitMask;
end;
procedure Tm3CustomHeaderStream.DoneProc00000002;
begin
{$IfDef m3UseL3Memory}
m3HeaderBuffers^.FreeItem(FHeaderDataCompare);
{$Else m3UseL3Memory}
m2MEMFree(FHeaderDataCompare);
{$EndIf m3UseL3Memory}
end;
function Tm3CustomHeaderStream.InitProc00000004(const ABitMask: LongWord): LongWord;
begin
{$IFDEF _m3AUTOCREATEHEADER1}
if (_Stream <> nil) then begin
LockHeader;
try
if (m2COMGetSize(_Stream) = 0) then begin
Assert(m2COMCheckAccess(m2COMModeAccess(m2COMGetStatStgMode(_Stream)),STGM_WRITE));
FHeaderLoaded:=1;
SaveHeader(True);
end;//m2COMGetSize(_Stream) = 0
finally
UnlockHeader;
end;
end;//_Stream <> nil
{$ENDIF}
Result:=ABitMask;
end;
procedure Tm3CustomHeaderStream.DoneProc00000004;
begin
end;
function Tm3CustomHeaderStream.InitProc00000008(const ABitMask: LongWord): LongWord;
begin
DefaultInitAction;
Result:=ABitMask;
end;
procedure Tm3CustomHeaderStream.DoneProc00000008(
);
begin
DefaultDoneAction;
end;
function Tm3CustomHeaderStream.InitProc00000010(const ABitMask: LongWord): LongWord;
begin
if (_Stream <> nil) AND (m2COMGetStatStgMode(_Stream) AND STGM_WRITE = 0) then
m2COMSetPosition(Int64(FHeaderSize),_Stream);
Result:=ABitMask;
end;
procedure Tm3CustomHeaderStream.DoneProc00000010;
begin
end;
procedure Tm3CustomHeaderStream.CreateContext;
begin
inherited;
FHeaderDataSize:=InitHeaderDataSize;
FHeaderFullSize:=InitHeaderFullSize;
FHeaderSize:=CAnyGUIDLength+SizeOf(LongInt)+SizeOf(FHeaderFullSize)+FHeaderFullSize;
end;
procedure Tm3CustomHeaderStream.DefaultInitAction;
begin
LoadHeader;
end;
procedure Tm3CustomHeaderStream.DefaultDoneAction;
begin
SaveHeader;
end;
procedure Tm3CustomHeaderStream.Read(ABuff: Pointer;
ASize: LongInt;
var AResult: LongInt;
var AReturn: HRESULT
);
begin
if SUCCEEDED(AReturn) then
AReturn:=_Stream.Read(ABuff,ASize,@AResult);
end;
procedure Tm3CustomHeaderStream.Write(ABuff: Pointer;
ASize: LongInt;
var AResult: LongInt;
var AReturn: HRESULT
);
begin
if SUCCEEDED(AReturn) then
AReturn:=_Stream.Write(ABuff,ASize,@AResult);
end;
procedure Tm3CustomHeaderStream.Seek(AOffset : Int64;
AOrigin : TSeekOrigin;
var AResult : Int64;
var AReturn : HRESULT);
var
LOffset : Int64;
begin
if SUCCEEDED(AReturn) then
begin
if (AOrigin = soBeginning) then
LOffset:=AOffset+Int64(FHeaderSize)
else
if (AOrigin = soEnd) then
begin
Assert(false, 'Если это всплывёт, то можно этот Assert временно закомментирровать');
LOffset := AOffset;
end//AOrigin = soEnd
else
LOffset := AOffset;
AResult:=m2COMSeek(_Stream,LOffset,Ord(AOrigin))-Int64(FHeaderSize);
end;//SUCCEEDED(AReturn)
end;
procedure Tm3CustomHeaderStream.SetSize(ASize: Int64;
var AReturn: HRESULT);
begin
if SUCCEEDED(AReturn) then
AReturn:=_Stream.SetSize(ASize+Int64(FHeaderSize));
end;
procedure Tm3CustomHeaderStream.LockRegion(AOffset: Int64;
ASize: Int64;
ALockType: LongInt;
var AReturn: HRESULT);
begin
if SUCCEEDED(AReturn) then
AReturn:=_Stream.LockRegion(Int64(FHeaderSize)+AOffset,ASize,ALockType);
end;
procedure Tm3CustomHeaderStream.UnlockRegion(AOffset: Int64;
ASize: Int64;
ALockType: LongInt;
var AReturn: HRESULT);
begin
if SUCCEEDED(AReturn) then
AReturn:=_Stream.UnlockRegion(Int64(FHeaderSize)+AOffset,ASize,ALockType);
end;
function Tm3CustomHeaderStream.pm_GetSize: Int64;
//override;
{-}
begin
Result:=m2COMGetStatStgSize(_Stream)-Int64(FHeaderSize);
end;
function Tm3CustomHeaderStream.pm_GetLocksSupported: Longint;
//override;
{-}
begin
Result:=m2COMGetStatStgLocks(_Stream);
end;
procedure Tm3CustomHeaderStream.StatStgName(var AResult : PWideChar;
var AReturn : HRESULT);
//override;
{-}
begin
if SUCCEEDED(AReturn) then
try
aResult := m2COMGetStatStgName(_Stream);
except
on E: EOleSysError do aReturn := E.ErrorCode;
end;//try..except
end;
constructor Tm3CustomHeaderStream.Create(const AStream: IStream;
const AAccess: LongInt);
begin
inherited;
m2InitOperation(_Status,InitProc00000001($00000001));
m2InitOperation(_Status,InitProc00000002($00000002));
m2InitOperation(_Status,InitProc00000004($00000004));
m2InitOperation(_Status,InitProc00000008($00000008));
m2InitOperation(_Status,InitProc00000010($00000010));
end;
procedure Tm3CustomHeaderStream.Cleanup;
begin
m2DoneOperation(_Status,$00000010,DoneProc00000010);
m2DoneOperation(_Status,$00000008,DoneProc00000008);
m2DoneOperation(_Status,$00000004,DoneProc00000004);
m2DoneOperation(_Status,$00000002,DoneProc00000002);
m2DoneOperation(_Status,$00000001,DoneProc00000001);
inherited;
FHeaderData := nil;// Pointer;
FHeaderDataCompare := nil;// Pointer;
FHeaderDataSize := 0;// LongInt;
FHeaderFullSize := 0;// LongInt;
FHeaderSize := 0;// LongInt;
FHeaderLoaded := 0;// LongInt;
FHeaderLocked := 0;// LongInt;
_Status := 0;
end;
procedure Tm3CustomHeaderStream.LoadHeader(
);
var
LBodyCRC : LongInt;
LHeaderID : AnsiString;
LHeaderFullSize : LongInt;
LPosition : Int64;
begin
if (FHeaderLoaded = 0) then
begin
if (_Stream <> nil) AND (m2COMGetStatStgMode(_Stream) AND STGM_WRITE = 0) then
begin
// - мы не можем считать Header - значит он уже должен быть у нас
LPosition:=m2COMGetPosition(_Stream);
try
m2COMSetPosition(0,_Stream);
m2COMCLSIDFromStream(_Stream,LHeaderID);
m2COMReadBuffer(_Stream,LBodyCRC,SizeOf(LBodyCRC));
m2COMReadBuffer(_Stream,LHeaderFullSize,SizeOf(LHeaderFullSize));
m2CheckValue((LHeaderID = GUIDToString(HeaderID)) and
(LHeaderFullSize = FHeaderFullSize));
m2COMReadBuffer(_Stream,FHeaderData^,FHeaderFullSize);
finally
m2COMSetPosition(LPosition,_Stream);
end;//try..finally
m2MEMCopy(FHeaderDataCompare,FHeaderData,FHeaderDataSize);
end;//_Stream <> nil..
end;//FHeaderLoaded = 0
Inc(FHeaderLoaded);
end;
procedure Tm3CustomHeaderStream.SaveHeader(const AForcedSave: LongBool);
var
LBodyCRC : LongInt;
LPosition : Int64;
l_Fake : Int64;
begin
Dec(FHeaderLoaded);
if (FHeaderLoaded = 0) AND (_Stream <> nil) AND not ReadOnly then
begin
if AForcedSave or
(m2MEMCompare(FHeaderData,FHeaderDataCompare,FHeaderDataSize) <> 0) then
begin
m2MEMCopy(FHeaderDataCompare,FHeaderData,FHeaderDataSize);
LPosition:=m2COMGetPosition(_Stream);
try
LBodyCRC := 0;
if AForcedSave then
begin
if l3IFail(_Stream.Seek(0, STREAM_SEEK_SET, l_Fake)) then
Exit;
m2COMCLSIDToStream(_Stream,GUIDToString(HeaderID));
end//AForcedSave
else
if l3IFail(_Stream.Seek(CAnyGUIDLength, STREAM_SEEK_SET, l_Fake)) then
Exit;
m2COMWriteBuffer(_Stream,LBodyCRC,SizeOf(LBodyCRC));
m2COMWriteBuffer(_Stream,FHeaderFullSize,SizeOf(FHeaderFullSize));
m2COMWriteBuffer(_Stream,FHeaderData^,FHeaderFullSize);
finally
_Stream.Seek(lPosition, STREAM_SEEK_SET, l_Fake);
end;//try..finally
end;//AForcedSave..
end;//FHeaderLoaded = 0..
end;
procedure Tm3CustomHeaderStream.LockHeader;
begin
if ((FHeaderLocked = 0) and m2COMIsLocksSupported(_Stream)) then
m2COMTimeLock(_Stream,CAnyGUIDLength,Int64(FHeaderSize)-CAnyGUIDLength);
Inc(FHeaderLocked);
end;
procedure Tm3CustomHeaderStream.UnlockHeader;
begin
Dec(FHeaderLocked);
if ((FHeaderLocked = 0) and m2COMIsLocksSupported(_Stream)) then
m2COMTimeUnlock(_Stream,CAnyGUIDLength,Int64(FHeaderSize)-CAnyGUIDLength);
end;
...
Новый код, я вскоре выложу.
Он НА ПОРЯДОК - короче и читабельнее.
Вот уж как "быдло-код" становится "просто кодом" (
- http://programmingmindstream.blogspot.ru/2014/08/blog-post_59.html
- http://programmingmindstream.blogspot.ru/2014/08/mindstream-firemonkey.html?showComment=1407782559954#c112802013383687686
- http://programmingmindstream.blogspot.ru/2014/08/di-service-locator.html
).
Комментариев нет:
Отправить комментарий