Creare con i Memory Stream un'area di memoria simile ad una Struttura avente come membro un'altra Struttura

Da Gambas-it.org - Wikipedia.

Come si sa, una Struttura non è altro, in fin dei conti, che un'area riservata di memoria, avente una dimensione pari al tipo di dati al quale appartiene ciascun membro della Struttura medesima compresi gli eventuali allineamenti dei membri.

E' dunque possibile creare mediante i Memory Stream un'area di memoria analoga ad una Struttura. In questa pagina vederemo come realizzare una semplice Struttura innestata, ossia una Struttura in cui almeno un suo membro è un'altra Struttura.

Va precisato che in Gambas, in via generale, il membro di una Struttura (innestata), contenente il riferimento ad un'altra Struttura (innesto), non contiene altro che l'indirizzo di memoria (e pertanto sarà un dato di tipo Puntatore) di detta sub-Struttura innesto. Bisognerà ricordare, dunque, che nell'area di memoria della "simil-Struttura", che andiamo a costruire con i Memory Stream, ove inserire il riferimento alla sub-Struttura (cioè della Struttura innesto che è membro della Struttura principale innestata), dovremo scrivere l'indirizzo di memoria di questa sub-Struttura innesto.

Dunque, come esempio, l'obiettivo è quello di costruire una Struttura (innestata), comprensiva di sub-Struttura "innesto", come quella che di seguito avremmo in Gambas:

Public Struct Struttura_Innesto
  b As Byte
  sh As Short
  i As Integer
End Struct

Public Struct STRUTTURA_INNESTATA
  b As Byte
  sh As Short
  i As Integer
  subStru As Struct Struttura_Innesto
  ii As Integer
End Struct


Tale Struttura innestata, compresa quella innesto, verrà con i Memory Stream così sviluppata:

Public Sub Main()

  Dim struttura, substruttura, legge_Pointer As Pointer
  Dim st, subs As Stream
  Dim legge_Byte, sub_b As Byte
  Dim legge_Short, sub_sh As Short
  Dim legge_Integer, sub_i As Integer

' Allochiamo la necessaria memoria coerente con la somma delle dimensioni dei vari dati componenti le due "Strutture" anche tenuto conto degli eventuali "allineamenti dei dati":
  struttura = Alloc(SizeOf(gb.Byte), 24)
  substruttura = Alloc(SizeOf(gb.Byte), 8)

' Scriviamo dei valori all'interno dell'area di memoria riservata della "Struttura" principale, quella "innestata", ovviamente sulla base della quantità di memoria occupata dai tipi di dati previsti e degli eventuali "allineamenti dei dati".

' Cominciamo con l'assegnare dei valori alla sub-Struttura, ossia l'innesto:
  subs = Memory substruttura For Write
    Write #subs, 44 As Byte
    Seek #subs, 2
    Write #subs, 444 As Short
    Write #subs, 44444 As Integer
  subs.Close
   
  st = Memory struttura For Read Write

' Scriviamo i dati nella "Struttura" principale, quella "innestata":
  Write #st, 99 As Byte
  Seek #st, 2
  Write #st, 999 As Short
  Write #st, 99999 As Integer
' Ora creiamo il riferimento alla Struttura "innesto", scrivendo l'indirizzo di memoria:
  Write #st, substruttura As Pointer
' Poiché il puntatore occupa 8 byte, ci spostiamo al byte n. 16 (ossia il 17°):
  Seek #st, 16
  Write #st, 999999 As Integer

 
' Come verifica del nostro esperimento, leggiamo i dati in base al tipo che è stato assegnato:
  Seek #st, 0
  Read #st, legge_Byte
  Print "struttura: "; legge_Byte
  Seek #st, 2
  Read #st, legge_Short
  Print "struttura: "; legge_Short
  Read #st, legge_Integer
  Print "struttura: "; legge_Integer
' Ora "trasferiamo" la nostra lettura nell'area di memoria della sub-Struttura "innesto", acquisendo innanzitutto il suo indirizzo di memoria:
  Read #st, legge_Pointer
    subs = Memory legge_Pointer For Read
      Read #subs, sub_b
      Print "  substruttura: "; sub_b
      Seek #subs, 2
      Read #subs, sub_sh
      Print "  substruttura: "; sub_sh
      Read #subs, sub_i
      Print "  substruttura: "; sub_i
    subs.Close
' Torniamo a leggere i dati (l'ultimo) nella Struttura principale (quella "innestata").
' Poiché il puntatore occupa 8 byte, ci spostiamo al byte n. 16 (ossia il 17°):
  Seek #st, 16
  Read #st, legge_Integer
  Print "struttura: "; legge_Integer
   
  st.Close
   
  Free(substruttura)
  Free(struttura)

End