
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1565 8e941d3f-bd1b-0410-a28a-d453659cc2b4
980 lines
27 KiB
ObjectPascal
980 lines
27 KiB
ObjectPascal
(*******************************************************************
|
|
*
|
|
* TTFile.Pas 1.2
|
|
*
|
|
* File I/O Component (specification)
|
|
*
|
|
* Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg
|
|
*
|
|
* This file is part of the FreeType project, and may only be used
|
|
* modified and distributed under the terms of the FreeType project
|
|
* license, LICENSE.TXT. By continuing to use, modify or distribute
|
|
* this file you indicate that you have read the license and
|
|
* understand and accept it fully.
|
|
*
|
|
* NOTES :
|
|
*
|
|
*
|
|
* Changes from 1.1 to 1.2 :
|
|
*
|
|
* - Changes the stream operations semantics. See changes.txt
|
|
*
|
|
* - stream records are now allocated on demand in the heap
|
|
*
|
|
* - introduced the 'frame cache' to avoid Allocating/Freeing
|
|
* each frame, even tiny ones..
|
|
*
|
|
* - support for thread-safety and re-entrancy
|
|
*
|
|
* ( re-entrancy is there for information only.. )
|
|
*
|
|
* Changes from 1.0 to 1.1 :
|
|
*
|
|
* - defined the type TT_Stream for file handles
|
|
* - renamed ( and cleaned ) the API.
|
|
*
|
|
* - caching and memory-mapped files use the same API :
|
|
*
|
|
* TT_Access_Frame to notify
|
|
*
|
|
* - only the interface was really rewritten. This component still
|
|
* only supports one opened file at a time.
|
|
*
|
|
******************************************************************)
|
|
|
|
Unit TTFile;
|
|
|
|
interface
|
|
|
|
{$I TTCONFIG.INC}
|
|
|
|
uses FreeType,
|
|
TTTypes,
|
|
TTError;
|
|
|
|
function TTFile_Init : TError;
|
|
procedure TTFile_Done;
|
|
|
|
(*********************************************************************)
|
|
(* *)
|
|
(* Stream Functions *)
|
|
(* *)
|
|
(*********************************************************************)
|
|
|
|
function TT_Open_Stream( name : String;
|
|
var stream : TT_Stream ) : TError;
|
|
(* Open a file and return a stream handle for it *)
|
|
(* should only be used for a new typeface object's main stream *)
|
|
|
|
procedure TT_Close_Stream( var stream : TT_Stream );
|
|
(* closes, then discards a stream, when it becomes unuseful *)
|
|
(* should only be used for a typeface object's main stream *)
|
|
|
|
function TT_Use_Stream( org_stream : TT_Stream;
|
|
var stream : TT_Stream ) : TError;
|
|
(* notices the component that we're going to use the file *)
|
|
(* opened in 'org_stream', and report errors to the 'error' *)
|
|
(* variable. the 'stream' variable is untouched, except in *)
|
|
(* re-entrant buids. *)
|
|
|
|
(* in re-entrant builds, the original file handle is duplicated *)
|
|
(* to a new stream which reference is passed to the 'stream' *)
|
|
(* variable.. thus, each thread can have its own file cursor to *)
|
|
(* access the same file concurrently.. *)
|
|
|
|
procedure TT_Flush_Stream( stream : TT_Stream );
|
|
(* closes a stream's font handle. This is useful to save *)
|
|
(* system resources. *)
|
|
|
|
procedure TT_Done_Stream( stream : TT_Stream );
|
|
(* notice the file component that we don't need to perform *)
|
|
(* file ops on the stream 'stream' anymore.. *)
|
|
(* *)
|
|
(* in re-entrant builds, should also discard the stream *)
|
|
|
|
(*********************************************************************)
|
|
(* *)
|
|
(* File Functions *)
|
|
(* *)
|
|
(* the following functions perform file operations on the *)
|
|
(* currently 'used' stream. In thread-safe builds, only one *)
|
|
(* stream can be used at a time. Synchronisation is performed *)
|
|
(* through the Use_Stream/Done_Stream functions *)
|
|
(* *)
|
|
(* Note: *)
|
|
(* re-entrant versions of these functions are only available *)
|
|
(* in the C source tree. There, a macro is used to add a 'stream' *)
|
|
(* parameter to each of these routines.. *)
|
|
(* *)
|
|
(*********************************************************************)
|
|
|
|
function TT_Read_File( var ABuff; ACount : Int ) : TError;
|
|
(* Read a chunk of bytes directly from the file *)
|
|
|
|
function TT_Seek_File( APos : LongInt ) : TError;
|
|
(* Seek a new file position *)
|
|
|
|
function TT_Skip_File( ADist : LongInt ) : TError;
|
|
(* Skip to a new file position *)
|
|
|
|
function TT_Read_At_File( APos : Long; var ABuff; ACount : Int ) : TError;
|
|
(* Seek and read a chunk of bytes *)
|
|
|
|
function TT_File_Size : Longint;
|
|
|
|
function TT_File_Pos : Longint;
|
|
|
|
function TT_Stream_Size( stream : TT_Stream ) : longint;
|
|
|
|
(*********************************************************************)
|
|
(* *)
|
|
(* Frame Functions *)
|
|
(* *)
|
|
(*********************************************************************)
|
|
|
|
function TT_Access_Frame( aSize : Int ) : TError;
|
|
(* Access the next aSize bytes *)
|
|
|
|
function TT_Check_And_Access_Frame( aSize : Int ) : TError;
|
|
(* Access the next min(aSize,file_size-file_pos) bytes *)
|
|
|
|
function TT_Forget_Frame : TError;
|
|
(* Forget the previously cached frame *)
|
|
|
|
(* The four following functions should only be used after a *)
|
|
(* TT_Access_Frame and before a TT_Forget_Frame *)
|
|
|
|
(* They do not provide error handling, intentionnaly, and are much faster *)
|
|
(* moreover, they could be converted to MACROS in the C version *)
|
|
|
|
function GET_Byte : Byte;
|
|
function GET_Char : ShortInt;
|
|
function GET_Short : Short;
|
|
function GET_UShort : UShort;
|
|
function GET_Long : Long;
|
|
function GET_ULong : ULong;
|
|
function GET_Tag4 : ULong;
|
|
|
|
implementation
|
|
|
|
uses
|
|
TTMemory;
|
|
|
|
(* THREADS: TTMutex, *)
|
|
|
|
const
|
|
frame_cache_size = 2048;
|
|
(* we allocate a single block where we'll place all of our frames *)
|
|
(* instead of allocating an new block on each access. Note that *)
|
|
(* frames that are bigger than this constant are effectively *)
|
|
(* allocated in the heap.. *)
|
|
|
|
type
|
|
PString = ^string;
|
|
PFile = ^FILE;
|
|
PError = ^TT_Error;
|
|
|
|
PStream_Rec = ^TStream_Rec;
|
|
TStream_Rec = record
|
|
name : PString; (* file pathname *)
|
|
open : Boolean; (* is the stream currently opened *)
|
|
font : PFILE; (* file handle for opened stream *)
|
|
base : Longint; (* base offset for embedding *)
|
|
size : Longint; (* size of font in resource *)
|
|
posit : Longint; (* current offset for closed streams *)
|
|
end;
|
|
|
|
var
|
|
(* THREADS: File_Mutex : TMutex *)
|
|
|
|
font_file : PFile;
|
|
cur_stream : PStream_Rec;
|
|
|
|
current_frame : PByte;
|
|
frame_cursor : Longint;
|
|
frame_size : LongInt;
|
|
|
|
dummy_error : TT_Error;
|
|
|
|
frame_cache : PByte;
|
|
|
|
function TT_File_Size : Longint;
|
|
begin
|
|
TT_File_Size := FileSize( font_file^ );
|
|
end;
|
|
|
|
function TT_File_Pos : Longint;
|
|
begin
|
|
TT_File_Pos := FilePos( font_file^ );
|
|
end;
|
|
|
|
function TT_Stream_Size( stream : TT_Stream ) : longint;
|
|
var
|
|
rec : PStream_Rec;
|
|
begin
|
|
rec := PStream_Rec(stream);
|
|
if rec = nil then
|
|
TT_Stream_Size := 0
|
|
else
|
|
TT_Stream_Size := rec^.size;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TTFile_Init
|
|
*
|
|
* Description : Init the file component
|
|
*
|
|
* - create a file mutex for thread-safe builds
|
|
*
|
|
******************************************************************)
|
|
|
|
function TTFile_Init : TError;
|
|
begin
|
|
(* empty current file *)
|
|
font_file := nil;
|
|
cur_stream := nil;
|
|
|
|
(* empty frame *)
|
|
current_frame := nil;
|
|
frame_cursor := 0;
|
|
frame_size := 0;
|
|
|
|
(* create frame cache *)
|
|
GetMem( frame_cache, frame_cache_size );
|
|
|
|
TTFile_Init := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TTFile_Done
|
|
*
|
|
* Description : Finalize the file component
|
|
*
|
|
* - destroys the file mutex for thread-safe builds
|
|
*
|
|
******************************************************************)
|
|
|
|
procedure TTFile_Done;
|
|
begin
|
|
(* empty current file *)
|
|
font_file := nil;
|
|
cur_stream := nil;
|
|
|
|
(* empty frame *)
|
|
current_frame := nil;
|
|
frame_cursor := 0;
|
|
frame_size := 0;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : Stream_New
|
|
*
|
|
* Description : allocates a new stream record
|
|
*
|
|
* Input : stream : the target stream variable
|
|
*
|
|
* Output : True on sucess.
|
|
*
|
|
******************************************************************)
|
|
|
|
function Stream_New( pathname : string;
|
|
var stream : PStream_Rec ) : TError;
|
|
var
|
|
font : PFile;
|
|
name : PString;
|
|
len : Integer;
|
|
label
|
|
Fail_Memory;
|
|
begin
|
|
name := nil;
|
|
font := nil;
|
|
stream := nil;
|
|
len := length(pathname)+1;
|
|
|
|
(* allocate a new stream_rec in the heap *)
|
|
if Alloc( pointer(stream), sizeof(TStream_Rec) ) or
|
|
Alloc( pointer(font), sizeof(FILE) ) or
|
|
Alloc( pointer(name), len ) then
|
|
goto Fail_Memory;
|
|
|
|
move( pathname, name^, len );
|
|
|
|
stream^.font := font;
|
|
stream^.name := name;
|
|
stream^.open := false;
|
|
stream^.base := 0;
|
|
stream^.size := 0;
|
|
stream^.posit := 0;
|
|
|
|
Stream_New := Success;
|
|
exit;
|
|
|
|
Fail_Memory:
|
|
Free( pointer(name) );
|
|
Free( pointer(font) );
|
|
Free( pointer(stream) );
|
|
Stream_New := Failure;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : Stream_Activate
|
|
*
|
|
* Description : activates a stream, if it needs it
|
|
*
|
|
* Input : stream : the target stream variable
|
|
*
|
|
* Output : Error condition
|
|
*
|
|
******************************************************************)
|
|
|
|
function Stream_Activate( stream : PStream_Rec ) : TError;
|
|
var
|
|
old_filemode : Long;
|
|
begin
|
|
Stream_Activate := Failure;
|
|
if stream = nil then exit;
|
|
|
|
with stream^ do
|
|
begin
|
|
Stream_Activate := Success;
|
|
if open then exit;
|
|
|
|
old_filemode := System.FileMode;
|
|
System.FileMode := 0;
|
|
(* read-only mode *)
|
|
|
|
Assign( font^, name^ );
|
|
{$I-}
|
|
Reset( font^, 1 );
|
|
{$I+}
|
|
|
|
System.FileMode := old_filemode;
|
|
|
|
if IOResult <> 0 then
|
|
begin
|
|
error := TT_Err_Could_Not_Open_File;
|
|
Stream_Activate := Failure;
|
|
exit;
|
|
end;
|
|
|
|
open := true;
|
|
base := 0;
|
|
if size = -1 then size := FileSize(font^);
|
|
|
|
if posit <> 0 then
|
|
Seek( font^, posit );
|
|
end;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : Stream_Deactivate
|
|
*
|
|
* Description : closes an active stream
|
|
*
|
|
* Input : stream : the target stream variable
|
|
*
|
|
* Output : Error condition
|
|
*
|
|
******************************************************************)
|
|
|
|
function Stream_Deactivate( stream : PStream_Rec ) : TError;
|
|
begin
|
|
Stream_Deactivate := Failure;
|
|
if stream = nil then exit;
|
|
|
|
Stream_Deactivate := Success;
|
|
if not stream^.open then exit;
|
|
|
|
stream^.posit := FilePos( stream^.font^ );
|
|
close( stream^.font^ );
|
|
stream^.open := false;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : Stream_Done
|
|
*
|
|
* Description : frees an active stream_rec
|
|
*
|
|
* Input : stream : the target stream variable
|
|
*
|
|
* Output : True on sucess.
|
|
*
|
|
* Notes : 'stream' is set to nil on exit..
|
|
*
|
|
******************************************************************)
|
|
|
|
function Stream_Done( var stream : PStream_Rec ) : TError;
|
|
begin
|
|
Stream_Deactivate( stream );
|
|
|
|
Free( pointer(stream^.name) );
|
|
Free( pointer(stream^.font) );
|
|
Free( pointer(stream) );
|
|
|
|
Stream_Done := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Open_Stream
|
|
*
|
|
* Description : opens the font file in a new stream
|
|
*
|
|
* Input : stream : target stream variable
|
|
* name : file pathname
|
|
* error : the variable that will be used to
|
|
* report stream errors
|
|
*
|
|
* Output : True on sucess.
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Open_Stream( name : String;
|
|
var stream : TT_Stream ) : TError;
|
|
var
|
|
rec : PStream_Rec;
|
|
font : PFile;
|
|
|
|
old_filemode : Long;
|
|
begin
|
|
TT_Open_Stream := Failure;
|
|
|
|
if Stream_New( name, rec ) or
|
|
Stream_Activate( rec ) then
|
|
begin
|
|
stream.z := nil;
|
|
exit;
|
|
end;
|
|
|
|
cur_stream := rec;
|
|
font_file := rec^.font;
|
|
stream := TT_Stream(rec);
|
|
|
|
TT_Open_Stream := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Close_Stream
|
|
*
|
|
* Description : Closes the font file and releases memory buffer
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : True ( always )
|
|
*
|
|
******************************************************************)
|
|
|
|
procedure TT_Close_Stream( var stream : TT_Stream );
|
|
begin
|
|
if stream.z = nil then exit;
|
|
|
|
Stream_Done( PStream_Rec(stream) );
|
|
font_file := nil;
|
|
cur_stream := nil;
|
|
stream.z := nil;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Use_Stream
|
|
*
|
|
* Description : Acquire the file mutex (blocking call)
|
|
*
|
|
* Input : org_stream : original stream to use
|
|
* stream : duplicate stream (in re-entrant builds)
|
|
* set to 'org_stream' otherwise
|
|
* error : error report variable
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Use_Stream( org_stream : TT_Stream;
|
|
var stream : TT_Stream ) : TError;
|
|
var
|
|
rec : PStream_Rec;
|
|
begin
|
|
TT_Use_Stream := Failure;
|
|
|
|
stream := org_stream;
|
|
if org_stream.z = nil then exit;
|
|
|
|
rec := PStream_Rec(stream);
|
|
Stream_Activate(rec);
|
|
cur_stream := rec;
|
|
font_file := rec^.font;
|
|
|
|
TT_Use_Stream := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Flush_Stream
|
|
*
|
|
* Description : closes a stream
|
|
*
|
|
* Input : stream : the stream
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
******************************************************************)
|
|
|
|
procedure TT_Flush_Stream( stream : TT_Stream );
|
|
begin
|
|
if stream.Z <> nil then
|
|
Stream_Deactivate( PStream_Rec(stream.z) );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Done_Stream
|
|
*
|
|
* Description : Release the file mutex on a stream
|
|
*
|
|
* Input : stream : the stream
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
******************************************************************)
|
|
|
|
procedure TT_Done_Stream( stream : TT_Stream );
|
|
begin
|
|
if stream.z <> cur_stream then exit;
|
|
cur_stream := nil;
|
|
font_file := nil;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Seek_File
|
|
*
|
|
* Description : Seek the file cursor to a different position
|
|
*
|
|
* Input : APos new position on file
|
|
*
|
|
* Output : True on success. False if out of range
|
|
*
|
|
* Notes : Does not set the error variable
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Seek_File( APos : LongInt ) : TError;
|
|
begin
|
|
{$I-}
|
|
Seek( Font_File^, APos );
|
|
{$I+}
|
|
if IOResult <> 0 then
|
|
begin
|
|
error := TT_Err_Invalid_File_Offset;
|
|
TT_Seek_File := Failure;
|
|
exit;
|
|
end;
|
|
|
|
TT_Seek_File := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Skip_File
|
|
*
|
|
* Description : Skip forward the file cursor
|
|
*
|
|
* Input : ADist number of bytes to skip
|
|
*
|
|
* Output : see Seek_Font_File
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Skip_File( ADist : LongInt ) : TError;
|
|
begin
|
|
TT_Skip_File := TT_Seek_File( FilePos(Font_File^)+ADist );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Read_File
|
|
*
|
|
* Description : Reads a chunk of the file and copy it to memory
|
|
*
|
|
* Input : ABuff target buffer
|
|
* ACount length in bytes to read
|
|
*
|
|
* Output : True if success. False if out of range
|
|
*
|
|
* Notes : Current version prints an error message even if the
|
|
* debug state isn't on.
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Read_File( var ABuff; ACount : Int ) : TError;
|
|
begin
|
|
TT_Read_File := Failure;
|
|
{$I-}
|
|
BlockRead( Font_File^, ABuff, ACount );
|
|
{$I+}
|
|
|
|
if IOResult <> 0 then
|
|
begin
|
|
error := TT_Err_Invalid_File_Read;
|
|
exit;
|
|
end;
|
|
|
|
TT_Read_File := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Read_At_File
|
|
*
|
|
* Description : Read file at a specified position
|
|
*
|
|
* Input : APos position to seek to before read
|
|
* ABuff target buffer
|
|
* ACount number of bytes to read
|
|
*
|
|
* Output : True on success. False if error.
|
|
*
|
|
* Notes : prints an error message if seek failed.
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Read_At_File( APos : Long; var ABuff; ACount : Int ) : TError;
|
|
begin
|
|
TT_Read_At_File := Failure;
|
|
|
|
if TT_Seek_File( APos ) or
|
|
TT_Read_File( ABuff, ACount ) then exit;
|
|
|
|
TT_Read_At_File := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Access_Frame
|
|
*
|
|
* Description : Notifies the component that we're going to read
|
|
* aSize bytes from the current file position.
|
|
* This function should load/cache/map these bytes
|
|
* so that they will be addressed by the GET_xxx
|
|
* functions easily.
|
|
*
|
|
* Input : aSize number of bytes to access.
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
* The function fails is the byte range is not within the
|
|
* the file, or if there is not enough memory to cache
|
|
* the bytes properly ( which usually means that aSize is
|
|
* too big in both cases ).
|
|
*
|
|
* It will also fail if you make two consecutive calls
|
|
* to TT_Access_Frame, without a TT_Forget_Frame between
|
|
* them.
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Access_Frame( aSize : Int ) : TError;
|
|
var
|
|
readBytes : Longint;
|
|
begin
|
|
TT_Access_Frame := Failure;
|
|
|
|
if current_frame <> nil then
|
|
begin
|
|
error := TT_Err_Nested_Frame_Access;
|
|
exit;
|
|
end;
|
|
(* We already are accessing one frame *)
|
|
|
|
if aSize > frame_cache_size then
|
|
GetMem( current_frame, aSize )
|
|
else
|
|
current_frame := frame_cache;
|
|
|
|
if TT_Read_File( current_frame^, aSize ) then
|
|
begin
|
|
if aSize > frame_cache_size then
|
|
FreeMem( current_frame, aSize );
|
|
|
|
current_frame := nil;
|
|
exit;
|
|
end;
|
|
|
|
frame_size := aSize;
|
|
frame_cursor := 0;
|
|
|
|
TT_Access_Frame := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Check_And_Access_Frame
|
|
*
|
|
* Description : Notifies the component that we're going to read
|
|
* aSize bytes from the current file position.
|
|
* This function should load/cache/map these bytes
|
|
* so that they will be addressed by the GET_xxx
|
|
* functions easily.
|
|
*
|
|
* Input : aSize number of bytes to access.
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
* The function fails is the byte range is not within the
|
|
* the file, or if there is not enough memory to cache
|
|
* the bytes properly ( which usually means that aSize is
|
|
* too big in both cases ).
|
|
*
|
|
* It will also fail if you make two consecutive calls
|
|
* to TT_Access_Frame, without a TT_Forget_Frame between
|
|
* them.
|
|
*
|
|
*
|
|
* NOTE : The only difference with TT_Access_Frame is that we check
|
|
* that the frame is within the current file. We otherwise
|
|
* truncate it..
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Check_And_Access_Frame( aSize : Int ) : TError;
|
|
var
|
|
readBytes : Longint;
|
|
begin
|
|
TT_Check_And_Access_Frame := Failure;
|
|
|
|
if current_frame <> nil then
|
|
begin
|
|
error := TT_Err_Nested_Frame_Access;
|
|
exit;
|
|
end;
|
|
(* We already are accessing one frame *)
|
|
|
|
readBytes := TT_File_Size - TT_File_Pos;
|
|
if aSize > readBytes then aSize := readBytes;
|
|
|
|
if aSize > frame_cache_size then
|
|
GetMem( current_frame, aSize )
|
|
else
|
|
current_frame := frame_cache;
|
|
|
|
if TT_Read_File( current_frame^, aSize ) then
|
|
begin
|
|
if aSize > frame_cache_size then
|
|
FreeMem( current_frame, aSize );
|
|
exit;
|
|
end;
|
|
|
|
frame_size := aSize;
|
|
frame_cursor := 0;
|
|
|
|
TT_Check_And_Access_Frame := Success;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : TT_Forget_Frame
|
|
*
|
|
* Description : Releases a cached frame after reading
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : True on success. False on failure
|
|
*
|
|
******************************************************************)
|
|
|
|
function TT_Forget_Frame : TError;
|
|
begin
|
|
TT_Forget_Frame := Failure;
|
|
|
|
if current_frame = nil then exit;
|
|
|
|
if frame_size > frame_cache_size then
|
|
FreeMem( current_frame, frame_size );
|
|
|
|
frame_size := 0;
|
|
current_frame := nil;
|
|
frame_cursor := 0;
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_Byte
|
|
*
|
|
* Description : Extracts a byte from the current file frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted Byte.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_Byte : Byte;
|
|
begin
|
|
GET_Byte := current_frame^[frame_cursor];
|
|
inc( frame_cursor );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_Char
|
|
*
|
|
* Description : Extracts a signed byte from the current file frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted char.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_Char : ShortInt;
|
|
begin
|
|
GET_Char := ShortInt( current_frame^[frame_cursor] );
|
|
inc( frame_cursor );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_Short
|
|
*
|
|
* Description : Extracts a short from the current file frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted short.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_Short : Short;
|
|
begin
|
|
GET_Short := (Short(current_frame^[ frame_cursor ]) shl 8) or
|
|
Short(current_frame^[frame_cursor+1]);
|
|
inc( frame_cursor, 2 );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_UShort
|
|
*
|
|
* Description : Extracts an unsigned short from the frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted ushort.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_UShort : UShort;
|
|
begin
|
|
GET_UShort := (UShort(current_frame^[ frame_cursor ]) shl 8) or
|
|
UShort(current_frame^[frame_cursor+1]);
|
|
inc( frame_cursor, 2 );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_Long
|
|
*
|
|
* Description : Extracts a long from the frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted long.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_Long : Long;
|
|
begin
|
|
GET_Long := (Long(current_frame^[ frame_cursor ]) shl 24) or
|
|
(Long(current_frame^[frame_cursor+1]) shl 16) or
|
|
(Long(current_frame^[frame_cursor+2]) shl 8 ) or
|
|
(Long(current_frame^[frame_cursor+3]) );
|
|
inc( frame_cursor, 4 );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_ULong
|
|
*
|
|
* Description : Extracts an unsigned long from the frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted ulong.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_ULong : ULong;
|
|
begin
|
|
GET_ULong := (ULong(current_frame^[ frame_cursor ]) shl 24) or
|
|
(ULong(current_frame^[frame_cursor+1]) shl 16) or
|
|
(ULong(current_frame^[frame_cursor+2]) shl 8 ) or
|
|
(ULong(current_frame^[frame_cursor+3]) );
|
|
inc( frame_cursor, 4 );
|
|
end;
|
|
|
|
(*******************************************************************
|
|
*
|
|
* Function : GET_Tag4
|
|
*
|
|
* Description : Extracts a Tag from the frame
|
|
*
|
|
* Input : None
|
|
*
|
|
* Output : Extracted 4 byte Tag.
|
|
*
|
|
* NOTES : We consider that the programmer is intelligent enough
|
|
* not to try to get a byte that is out of the frame. Hence,
|
|
* we provide no bounds check here. (A misbehaving client
|
|
* could easily page fault using this call).
|
|
*
|
|
******************************************************************)
|
|
|
|
function GET_Tag4 : ULong;
|
|
var
|
|
C : array[0..3] of Byte;
|
|
begin
|
|
move ( current_frame^[frame_cursor], c, 4 );
|
|
inc( frame_cursor, 4 );
|
|
|
|
GET_Tag4 := ULong(C);
|
|
end;
|
|
|
|
end.
|