Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Virtual Memory Stream (https://www.delphipraxis.net/150363-virtual-memory-stream.html)

himitsu 14. Apr 2010 22:32


Virtual Memory Stream
 
Liste der Anhänge anzeigen (Anzahl: 2)
Tachchen,

ich weiß nicht, ob es irgendwo schon etwas Gleichartiges gibt,
aber da ich nichts fand [add](vergessen, daß es hier was kleines gab)[/add] und sowas brauchte, ist Dieses entstanden.
Nun hab ich's halt auch mal aus meinem Projekt ausgebaut und da isses. :-D

Hier erstmal der wichtigste Header:
(ist nicht viel, aber so viel braucht man ja auch nicht)
Delphi-Quellcode:
TVMSState = (msNone, msCopy, msCopyAndFreeMem, msOnlyFree);
TVMSOnResize = Procedure(Sender: TVirtualMemoryStream; RequiredSize: LongInt;
  Var Memory: Pointer; Var MaxSize: LongInt; Var State: TVMSState) of Object;
TVirtualMemoryStream = Class(TStream)
Private
  FMemory:        Pointer;
  FMaxSize, FSize: LongInt;
  FPosition:      LongInt;
  FOnResize:      TVMSOnResize;
  FTemp:          Record P: Pointer; I: LongInt; S: TVMSState; O: TVMSOnResize; End;
  Procedure OnChangeMemory(Sender: TVirtualMemoryStream; RequiredSize: LongInt;
    Var Memory: Pointer; Var MaxSize: LongInt; Var State: TVMSState);
Protected
  Function GetSize: Int64;                         Override;
  Procedure SetSize(NewSize: LongInt);    Overload; Override;
  Procedure SetSize(Const NewSize: Int64); Overload; Override;
  Procedure SetMem(Memory: Pointer; MaxSize: LongInt); Virtual;
Public
  Constructor Create(Memory: Pointer; MaxSize: LongInt; Size: LongInt = 0);
  Destructor Destroy; Override;

  Function Read (Var  Buffer; Count: LongInt): LongInt; Override;
  Function Write(Const Buffer; Count: LongInt): LongInt; Override;
  Function Seek (Offset: LongInt;    Origin: Word):       LongInt; Overload; Override;
  Function Seek (Const Offset: Int64; Origin: TSeekOrigin): Int64;  Overload; Override;

  Procedure SetPointer (Memory:   Pointer; MaxSize:   LongInt; Size: LongInt = 0);
  Function ChangeMemory(NewMemory: Pointer; NewMaxSize: LongInt;
    OldMemState: TVMSState = msCopyAndFreeMem): Pointer{old Memory};

  Property Memory:  Pointer     Read FMemory;
  Property MaxSize: LongInt     Read FMaxSize;
  Property OnResize: TVMSOnResize Read FOnResize Write FOnResize;
End;
Es handelt sich im Prinzip um eine Art MemoryStream, welcher allerdings keine eigene Speicherverwaltung besitzt.

TStaticMemoryStream wird beim Erstellen ein Speicherbereich und dessen Größe mitgegeben
und nun kann man auf diesen Speicher über den Stream zugreifen.

Ist dem OnResize-Ereignis etwas zugewiesen, macht die Klasse Selbe, allerdings kann hier der Speicher nachträglich getauscht, bzw in dessen Größe verändert werden.
So kann man den Stream mit jeder Art von Speicherstrukturen versorgen und diese sogar dynamisch ändern lassen, wenn es nötig ist.

Tja, und nun noch ein kleines Beispielprojektchen.

Delphi-Quellcode:
Program Project1;

Uses Classes, Dialogs, StatMemStream;

Var Data: Array[0..1023] of Byte;
  Stream: TStream;
  I:     LongInt;
  S:     AnsiString;

Begin
  Move(PAnsiChar('Das ist ein ')^, Data, 12);
  Stream := TStaticMemoryStream.Create(@Data, SizeOf(Data), 12);
  Stream.Position := 12;
  i := $74736554;
  Stream.WriteBuffer(i, 4);
  i := $002E;
  Stream.WriteBuffer(i, 2);
  Stream.Position := 0;
  SetLength(S, Stream.Size);
  Stream.ReadBuffer(S[1], Length(S));
  Stream.Free;
  ShowMessage(S);
  ShowMessage(PAnsiChar(@Data));
End.
Ich glaub der Speicher-Callback war nicht sonderlich gut geglückt und ich werde ihn wohl noch auftrennen (quasi in Callbacks für Get, Free und Realoc).


Der Stream ist natürlich nicht threadsicher (wie viele andere Streams auch), aber im Notfall kann man ja mehrere Streams auf den selben Speicher zeigen lassen.

[edit]
- der OnResize-Callback wurde etwas geändert
- die beiden Klassen wurden vereint
- und die Property wurden in einer Custom-Klasse versteckt

Neutral General 14. Apr 2010 22:50

Re: Static Memory Stream
 
Hi,

Habs mir noch nicht angeguckt. Schau es mir vllt. mal morgen an (jetzt erstmal schlafen gehn^^), aber es gibt sowas schon:

TVirtualStream:
http://www.delphipraxis.net/internal...059&highlight=

:mrgreen:

himitsu 14. Apr 2010 23:40

Re: Static Memory Stream
 
ups, den virtuellen hab'sch ganz vergessen. :oops:

SirThornberry 15. Apr 2010 07:14

Re: Static Memory Stream
 
Du hast vergessen den originalen Constructor zu überschrieben, oder?
Was passiert wenn jemand diesen aufruft? Deine privaten Variablen bleiben uninitialisiert und eine aussagekräftige Fehlermeldung kommt auch nicht. Die Fehler kommen erst wenn man später auf die jeweiligen Methoden zugreift.

[Edit]
Ich nehme meine Aussage zurück. Ich habe gerade bei TFileStream geschaut und da ist es genauso. Und wenn man versucht den Standardconstructor aufzurufen kommt ein Fehler das es keinen Constructor gibt der mit diesem übereinstimmt.
Delphi-Quellcode:
var
  lStream: TFileStream;
begin
  lStream := TFileStream.Create(); // = There is no overloaded Version of Create that can be called with these arguments
Das verwirrt mich allerdings denn letzendlich ist TFilestream über zig Umwege von TObject abgeleitet und dort existiert eben jener Constructor :gruebel: Warum funktioniert das also nicht?!

himitsu 15. Apr 2010 07:27

Re: Static Memory Stream
 
Der Original-Constructor würde das Selbe machen, wie .Create(nil,0) .
Er verhält sich also wie ein leerer Stream, mit der Maximalgröße von 0.
Eine unbeabsichtigte Zugriffsverletzung/Fehler sollte nicht auftreten, denn immerhin werden die Felder mit 0 initialisiert.

Die einzigen Fehler, welche auftreten können, wären
- ein ungültiger Pointer
- MaxSize größer als der Speicherblock

Ich könnte zwar prüfen ob der Speicherblock lesbar/schreibbar ist, aber da ich nicht sicherstellen kann, daß der Speicherblock wirklich für diesen Zugriff gedacht ist, hab ich diesbezüglich keine Prüfung verbaut.

SirThornberry 15. Apr 2010 07:28

Re: Static Memory Stream
 
Stimmt. Ich bin derzeit insgesamt wohl etwas verwirrt :duck:

himitsu 15. Apr 2010 18:36

Re: Virtual Memory Stream
 
Ups, jetzt hätt ich beinah vergessen zu antworten.

@Bärchen: macht ja nix http://fnse.de/S05/1L9.gif


Joar und was gibt es sonst noch.
Hab's doch noch schnell etwas geändert
und hab mir mal des Generals Klassen-Name gemopst. :oops:

Aber Aufgrund der besseren Bereichsprüfung laß ich meinen Code dennoch hier. :mrgreen:

Neutral General 15. Apr 2010 18:42

Re: Virtual Memory Stream
 
Zitat:

Zitat von himitsu
und hab mir mal des Generals Klassen-Name gemopst. :oops:

:shock:

Copyright, Urheberrecht und so! TVirtualStream™ ! :evil:

:mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz