It is currently Tue Mar 09, 2021 9:26 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: FileFormatID - OOP
PostPosted: Wed Oct 28, 2020 9:29 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello everyone,

Something I came up with to solve the binary file format identification in order to avoid some file reading issues.
The use of a Magic Number

And I have made a tiny lib just for that, may be little extreme but it do the job. Use it if it fit your needs.

See the source code for the example of use.

Best regards
StarBootics

Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Object - V1.1.0
; Project name : FileFormatID
; File name : FileFormatID - OOP.pb
; File Version : 1.0.1
; Programmation : OK
; Programmed by : StarBootics
; Creation Date : October 24th, 2020
; Last update : October 29th, 2020
; Coded for PureBasic : V5.72
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Programming notes
;
; When we create binary file for some data (example a
; Bitmap Font Format) it could be necessary to make sure
; the file we are reading is the right file format.
;
; Otherwise we can try to read wrong data in the file and
; our program may crash in some cases.
;
; Inspired by ID Software who write a Magic Number (Long
; Value = 860898377) at the beging of the file to identify
; the MD3 file format. By the way it's not the only
; software developer doing that. Search the web for "File 
; Format Magic Number" or take a look at :
;
; https://en.wikipedia.org/wiki/File_format#Magic_number
;
; See the example at the end of this file to see how
; this library can be used.
;
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule FileFormatID
 
  Interface FileFormatID
   
    GetMagicNumber.l()
    SetMagicNumber(Char00.a, Char01.a, Char02.a, Char03.a)
    Compare.b(*Other)
    ReadFileFormatID(FileID.i)
    WriteFileFormatID(FileID.i)
    Free()
   
  EndInterface
 
  Declare.i New(Char00.a = 0, Char01.a = 0, Char02.a = 0, Char03.a = 0)
 
EndDeclareModule

Module FileFormatID
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structure declaration <<<<<

  Structure Private_Members
   
    VirtualTable.i
    MagicNumber.l
   
  EndStructure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The observators <<<<<

  Procedure.l GetMagicNumber(*This.Private_Members)
   
    ProcedureReturn *This\MagicNumber
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The mutators <<<<<

  Procedure SetMagicNumber(*This.Private_Members, Char00.a, Char01.a, Char02.a, Char03.a)
   
    *This\MagicNumber = Char03 << 24 + Char02 << 16 + Char01 << 8 + Char00
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Compare operator <<<<<

  Procedure.b Compare(*This.Private_Members, *Other)
   
    ProcedureReturn CompareMemory(*This, *Other, SizeOf(Private_Members))
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Read in Binary file <<<<<

  Procedure ReadFileFormatID(*This.Private_Members, FileID.i)
   
    *This\MagicNumber = ReadLong(FileID)
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Write in Binary file <<<<<

  Procedure WriteFileFormatID(*This.Private_Members, FileID.i)
   
    WriteLong(FileID, *This\MagicNumber)
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Destructor <<<<<

  Procedure Free(*This.Private_Members)
   
    FreeStructure(*This)
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Constructor <<<<<

  Procedure.i New(Char00.a = 0, Char01.a = 0, Char02.a = 0, Char03.a = 0)
   
    *This.Private_Members = AllocateStructure(Private_Members)
    *This\VirtualTable = ?START_METHODS
   
    SetMagicNumber(*This, Char00, Char01, Char02, Char03)
   
    ProcedureReturn *This
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Virtual Table Entries <<<<<

  DataSection
    START_METHODS:
    Data.i @GetMagicNumber()
    Data.i @SetMagicNumber()
    Data.i @Compare()
    Data.i @ReadFileFormatID()
    Data.i @WriteFileFormatID()
    Data.i @Free()
    END_METHODS:
  EndDataSection
 
EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.001 seconds (129000.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

CompilerIf #PB_Compiler_IsMainFile
 
 Debug "The MD3 file format (ID Software)"
 
 IDP3.FileFormatID::FileFormatID = FileFormatID::New('I', 'D', 'P', '3')
 Debug Str(IDP3\GetMagicNumber()) + " (Should be : 860898377)"
 IDP3\Free()
 
 Debug ""
 Debug "Bitmap Font File example"
 Debug ""
 
  #Bitmap_Font_Format_V0 = 809911874
 
  If CreateFile(0, "MyFont.bff")
   
    FFID00.FileFormatID::FileFormatID = FileFormatID::New('B', 'F', 'F', '0')
    FFID00\WriteFileFormatID(0)
   
    ; Then we proceed with the rest of the stuff we need to write on the file
   
    CloseFile(0)
    FFID00\Free()
   
  EndIf
 
  If ReadFile(1, "MyFont.bff")
   
    ExpectedFFID.FileFormatID::FileFormatID = FileFormatID::New('B', 'F', 'F', '1')
    FromFileFFID.FileFormatID::FileFormatID = FileFormatID::New()
   
    FromFileFFID\ReadFileFormatID(1)
   
    If ExpectedFFID\Compare(FromFileFFID) = 1
     
      Debug "FileFormatID OK, We proceed with the rest of the stuff we need to read from the file"
     
    Else
     
      Debug "FileFormatID Not OK, Check for old version just in case"
      Debug ""
     
      Select FromFileFFID\GetMagicNumber()
         
        Case #Bitmap_Font_Format_V0
          Debug "FileFormatID correspond to Version 0"
          Debug "Pop a message about this or put the"
          Debug "read instructions for that version."
         
        Default
          Debug "Unknown file format !"
         
      EndSelect
     
    EndIf
   
    CloseFile(1)
    ExpectedFFID\Free()
    FromFileFFID\Free()
   
    ; The delete file is for the example only
    DeleteFile("MyFont.bff")
   
  EndIf
 
CompilerEndIf

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<

_________________
The Stone Age did not end due to a shortage of stones !


Last edited by StarBootics on Thu Oct 29, 2020 8:32 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: FileFormatID - OOP
PostPosted: Thu Oct 29, 2020 9:03 am 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2890
Location: Germany
Hi,

you don't need ClearStructure. FreeStructure do this internal ...
:wink:

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: FileFormatID - OOP
PostPosted: Thu Oct 29, 2020 12:43 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2890
Location: Germany
Why is it not necessary to specify a structure in FreeStructure?!

PB stores the pointer to the structure information. If it does not contain any data that needs to be solved additionally, the pointer is zero
Code:
Structure sBase
  *vt
  refcnt.i
EndStructure

Structure sObject Extends sBase
  iVal.i
  List Text.s()
EndStructure

*mem = AllocateStructure(sObject)
*p_struct = PeekI(*mem - SizeOf(Integer))
If *p_struct
  Debug "Structure ..."
  Repeat
    info = PeekI(*p_struct)
    Debug info
    *p_struct + SizeOf(Integer)
  Until info = -1
EndIf
FreeStructure(*mem)

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: FileFormatID - OOP
PostPosted: Thu Oct 29, 2020 3:13 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello mk-soft,

Run this code you will see the reason why II have put ClearStructure() inside the destructor.

Code:
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Object - V1.2.0
; Project name : Demonstration OOP Style with PB
; File name : MyObject Destruction.pb
; File Version : 1.0.0
; Programmation : Problem demontration
; Programmed by : StarBootics
; Creation Date : 29-10-2020
; Last update : 29-10-2020
; Coded for PureBasic : V5.73 beta 2
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule MyObject
 
  Interface MyObject
   
    GetMyField.s()
    SetMyField(P_MyField.s)
    Free()
    Free2()
   
  EndInterface
 
  Declare.i New(P_MyField.s = "")
 
EndDeclareModule

Module MyObject
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structure declaration <<<<<

  Structure Private_Members
   
    VirtualTable.i
    MyField.s
   
  EndStructure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The observators <<<<<

  Procedure.s GetMyField(*This.Private_Members)
   
    ProcedureReturn *This\MyField
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The mutators <<<<<

  Procedure SetMyField(*This.Private_Members, P_MyField.s)
   
    *This\MyField = P_MyField
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Destructor <<<<<

  Procedure Free(*This.Private_Members)
   
    ; ClearStructure(*This, Private_Members)
    FreeStructure(*This)
   
  EndProcedure
 
  Procedure Free2(*This.Private_Members)
   
    ClearStructure(*This, Private_Members)
    FreeStructure(*This)
   
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Constructor <<<<<

  Procedure.i New(P_MyField.s = "")
   
    *This.Private_Members = AllocateStructure(Private_Members)
    *This\VirtualTable = ?START_METHODS
   
    *This\MyField = P_MyField
   
    ProcedureReturn *This
  EndProcedure
 
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Virtual Table Entries <<<<<

  DataSection
    START_METHODS:
    Data.i @GetMyField()
    Data.i @SetMyField()
    Data.i @Free()
    Data.i @Free2()
    END_METHODS:
  EndDataSection
 
EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.001 seconds (97000.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

MyObject00.MyObject::MyObject = MyObject::New("Tomato")
MyObject01.MyObject::MyObject = MyObject::New("Potato")

Debug MyObject00\GetMyField()

MyObject00\Free()

Debug MyObject00\GetMyField() ; Still working on some unknown memory


Debug MyObject01\GetMyField()

MyObject01\Free2()

Debug MyObject01\GetMyField() ; Here we have an invalid memory access
                              ; and it's normal and desirable to avoid
                              ; some hard to find bugs

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<


So you are telling me the destructor should look like that :
Code:
Procedure Free(*This.Private_Members)
 
  *This\VirtualTable = #Null
  FreeStructure(*This)
 
EndProcedure


instead of that :
Code:
Procedure Free(*This.Private_Members)
 
  ClearStructure(*This, Private_Members)
  FreeStructure(*This)
 
EndProcedure


Is that what you are saying ?

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Top
 Profile  
Reply with quote  
 Post subject: Re: FileFormatID - OOP
PostPosted: Thu Oct 29, 2020 5:59 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2890
Location: Germany
With the object method Free() the object is actually invalid and access to it is no longer allowed. Unfortunately, there is no control for this and the memory area could already be used for something else and thus the pointer to the VirtualTable could already be bent.

So it does not help to set the pointer to the VirtualTable to NULL or to call ClearStructure.

So with FreeStructure it is enough to delete the resources for strings, lists, maps, etc. in the structure and free the memory.

It is up to the programmer to ensure that a released object is no longer used.

The same applies to object oriented programming in other languages. Some of them have a memory mangment, which gives the error that the object no longer exists.

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: FileFormatID - OOP
PostPosted: Thu Oct 29, 2020 8:31 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jul 07, 2013 11:35 am
Posts: 587
Location: Canada
Hello mk-soft,

Thanks for the explanation, i will make modification inside of my Dev-Object code generator. That being said this discussion should have taken place in the Dev-Object topic.

Because it's way off topic for something related to FileFormatID stuff.

Best regards
StarBootics

_________________
The Stone Age did not end due to a shortage of stones !


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye