Files associated with a UDT

General FreeBASIC programming questions.
Post Reply
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Files associated with a UDT

Post by deltarho[1859] »

Suppose we have

Code: Select all

Type a
  Declare Constructor
  Declare Destructor
  As Ulong b
End Type
 
Dim As a c
What I want is a file to exist associated with 'c' such that it's filename has 'c' within it so that the Constructor can look in the program's directory to see if such a file exists. The file will be created by the Destructor with the filename based on 'c'.

We could then have
Dim As a d, e, f

with files existing associated with d, e, and f.

I have a feeling that the solution may make use of 'This' but I cannot see it.
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: Files associated with a UDT

Post by angros47 »

I fear you cannot : "c", "d", "e" and "f" are names that are processed by the compiler and the linker, and replaced with numeric memory address. So their name will appear nowhere in the compiled code, and without them, constructor won't be able to know the file name anymore
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

@angros47

Thanks. You are absolutely right. Sometimes we cannot see the wood for the trees.

Each UDT assignment needs a unique ID that we can put it into the filename. Perhaps the OS can help here, but I want to avoid relying on Windows, for example.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

OK, suppose we have 'As String ID' in the UDT. The Destructor creates a random alphanumeric key for ID and uses that as the filename. The Constructor reads the ID and looks for the file. A bit simple but it may work. Yes?

Added: If the string has at least 22 characters, then its entropy will exceed 128 bits, more than the 112 bits recommended by the NIST for passwords.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

Image
ID does not persist between application sessions, so will always be empty when the Constructor checks it. Sad thing is I had to write code for that penny to drop.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

I am flogging a dead horse. It is straightforward with one UDT but not possible with two or more.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Files associated with a UDT

Post by fxm »

Why not a principle of this kind?

Code: Select all

Type a
  Public:
    Declare Constructor()
    Declare Destructor()
    As Ulong b
  Private:
    As Ubyte st
End Type

Constructor a()
  static As Ubyte ct = Asc("b")
  ct += 1
  This.st = ct
  Print "file#" & Chr(This.st) & " to read"
  '.....
End Constructor

Destructor a()
  Print "file#" & Chr(This.st) & " to write"
  '.....
End destructor

Scope
  Dim As a c
  Dim As a d
  Dim As a e
  Dim As a f
  Print
End Scope

Sleep
Lost Zergling
Posts: 534
Joined: Dec 02, 2011 22:51
Location: France

Re: Files associated with a UDT

Post by Lost Zergling »

A list using lzle could do the job. Just specify cessionId and/or password as key, filename in tag, and udt into listcontainer, or a pointer to your udt. It is also possible to directly specify path and filename as key. You'd have to follow howmany open files a same time. Advantages are : you could follow max number of open files, you could parse and follow active or inactive udt, you could manage udt queuing and udt requests, it'd be not very hatd to save and reload a cession of cessions so stored in a list.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Files associated with a UDT

Post by dodicat »

Try to keep the udt minimal, not using the empty constructor, but using (any) to bypass the need:

Code: Select all



 #Include "file.bi"
 
 Type udt
  Declare Constructor(as long, as string, as long=0)
  'declare constructor
  Declare Destructor
  As Ulong b
End Type

#define refresh 1
#define basefile "testfile"

function flag() byref as string
static as string s
return s
end function

function exists() byref as boolean
static as boolean s
return s
end function

sub savefile(filename As String,p As udt)
    Dim As long n=freefile
    If Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,p
        Close
    Else
        Print "Unable to save " + filename:sleep:end
    End If
End sub

sub loadfile(file as string,k as udt) 
	If FileExists(file)=0 Then Print file;" not found":Sleep:end
   dim as long  f=freefile
    Open file For Binary Access Read As #f
      Get #f, , k
    Close #f
end sub


constructor udt(n as long,s as string,refreshflag as long)
b=n
flag()=s
if refreshflag=0 then
if fileexists(basefile+s) then exists()=true 
end if
end constructor

'constructor udt
'exists()=false
'flag()=""
'end constructor

destructor udt
 if exists()=false then savefile(basefile+flag(),this)
 exists()=false
 flag()=""
end destructor
 
 scope
Dim As udt c=any
c=type(20,"c")
end scope

scope
dim as udt d=any
d=type(30,"d")
end scope

print "Exists?"
print fileexists(basefile+"c")
print fileexists(basefile+"d")
print

dim as udt e=any,f=any
loadfile(basefile+"c",e)
print e.b
loadfile(basefile+"d",f)
print f.b
print

scope
Dim As udt c=any
c=type(80,"c",refresh)'value can be refreshed
end scope

scope
dim as udt d=any
d=type(90,"d",refresh)'value can be refreshed
end scope


loadfile(basefile+"c",e)
print e.b
loadfile(basefile+"d",f)
print f.b
print

scope
Dim As udt c=any
c=type(8000000,"c")' not refreshed so not used
end scope

scope
dim as udt d=any 
d=type(9000000,"d",refresh)
end scope

loadfile(basefile+"c",e)
print e.b
loadfile(basefile+"d",f)
print f.b




print "Exists?"
kill basefile+"c"
kill basefile+"d"
print fileexists(basefile+"c")
print fileexists(basefile+"d")
sleep

 
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

Both fxm and dodicat have food for thought there. I'd need to play around with them.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

OK, I reckon that dodicat's solution is overly complicated and requires the user to do a fair amount of coding and dependent upon how many instances of the UDT we use in addition to understanding how it works.

On the other hand, fxm's solution is simplicity itself and works equally well for one or more instances of the UDT. It is described as a principle and seems to me can easily be expanded upon.

I was thinking of saving/loading state vectors of a PRNG.

However, the more I think about it the more I wonder of the benefit of saving/loading the state vectors in the first place. I don't think that I have many bad ideas, but I think that this may be one of them. So, I have decided to put it to one side unless a benefit sneaks up on me in the future; unless someone can think of a benefit.

Of course, fxm's solution may be useful for applications which have nothing to do with PRNGs.

Thanks, guys. Image
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Files associated with a UDT

Post by dodicat »

You wouldn't be able to save anything OOP with regards to use of the vtable or polymorphism anyway in an ascii file, you would have to use a static library at minimum.
Saying that, a simple udt without class (extending object) or an array of the same are easy enough to handle, prepend, append or what have you.
Using a destructor to write to a file to me seems a little odd anyway, why not use simple functions, check is the file exists, write a new file, delete a file e.t.c .. e.t.c.
dafhi
Posts: 1641
Joined: Jun 04, 2005 9:51

Re: Files associated with a UDT

Post by dafhi »

i wouldnt discount dodicat's solution so quickly. Both he and fxm know the compiler quite well. dodicat's skills almost look like they came from nowhere :D

depends what your in the mood for of course
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Files associated with a UDT

Post by dodicat »

Thanks for your confidence Dafhi, I wish I had it!
Deltarho
Instead of a plethora of files for your state vectors, why do you not save an array of them to a single file and pluck out what you need?

Code: Select all



#include "file.bi"

Type udt 
      As Ulong x
      As Ulongint y
End Type

Sub printout(u() As udt,n As Long)
      Print u(n).x,u(n).y
End Sub

Sub load(file As String,u() As udt)
      Var  f=Freefile
      If Fileexists(file)=0 Then Print file;"  not found":Return
      Open file For Binary Access Read As #f
      If Lof(f) > 0 Then
            Get #f, ,u()
      End If
      Close #f
End Sub

Sub save(file As String,u() As udt)
      Var h=Freefile
      Open file For Binary Access Write As #h
      Put #h, ,u()
      Close #h
End Sub

Sub arrayinsert(a() As udt,index As Long,insert As udt)
      If index>=Lbound(a) And index<=Ubound(a)+1 Then
            Var index2=index-Lbound(a)
            Redim Preserve a(Lbound(a) To  Ubound(a)+1)
            For x As Integer= Ubound(a) To Lbound(a)+index2+1 Step -1
                  Swap a(x),a(x-1)
            Next x
            a(Lbound(a)+index2)=insert
      End If
End Sub

Sub arraydelete(a() As udt,index As Long)
      If index>=Lbound(a) And index<=Ubound(a) Then
            For x As Integer=index To Ubound(a)-1
                  a(x)=a(x+1)
            Next x
            Redim Preserve a(Lbound(a) To Ubound(a)-1)
      End If
End Sub

'keep all arrays 1 based, it is easier.
Dim As udt x(1 To 10)

For n As Long=Lbound(x) To Ubound(x)
      With x(n)
            .x=Rnd*100000
            .y=Rnd*1000000000000
      End With
Next n

Print "ORIGINAL"
For n As Long=Lbound(x) To Ubound(x)
      Print n;Tab(20);:printout(x(),n)
Next

save("data",x())

'===================== All is on file now  ==========================

Var N=Filelen("data")\Sizeof(udt) 'get the number of elements to load

Redim As udt y(1 To N)
load("data",y())
Print
Print
Print "============= I WANT ELEMENT 4 FROM FILE ============="

printout(y(),4)
Print "======================================================"
print
Print "Insert a new udt into array at position 4 and save"

Randomize

arrayinsert(y(),4,Type(100,Rnd*1000000000000))
save("data",y())
Print "Reload the new array from file"
N=Filelen("data")\Sizeof(udt)
Redim y(1 To N)
load("data",y())

For n As Long=Lbound(y) To Ubound(y)
      Print n;Tab(20);:printout(y(),n)
Next


Sleep
Kill "data"

 
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Files associated with a UDT

Post by deltarho[1859] »

Thanks, dodicat. You are coming at the problem from a very different angle. I have kept a copy of your code should I need it in the future. However, as I mentioned above, "the more I wonder of the benefit of saving/loading the state vectors in the first place."

The way I initialize PRNGs it is highly unlikely to see an initial state repeated with another instance of the PRNG. Seeing a sequence overlap is another story. If we saved the state vectors on an application's closure and restored them on an application's opening, then that would guarantee no overlap.

With a 2^64 period if we used 2^32 random numbers ( 4,294,967,296 ) numbers per application session and did a save/load then there would be 2^64 - 2^32 left of the sequence available.

From 2^64 - k * 2^32 = 0 with one application session per day, it would take more than 11 million years for the sequence to 'run out'. Of course, on the second application session, the chance of an overlap without a save/load facility would be 2^32 to 1 against. So for non-power users, an overlap would not be an issue.

This may surprise you, but there seems to be a recommendation that we should not request more than the square root of a generator's period because of overlap possibilities. Ideally, then, we should request less than 2^32 random numbers from a 2^64 period. For more than 2^32 requests, a better period would be 2^128; such as xoroshiro128**.

I am now struggling to think of another reason to have a save/load facility for a PRNG. There may be a few applications that would benefit from a save/load facility, but not a PRNG for the most part; I reckon.
Post Reply