08-22-2022, 12:59 AM
So, if there's a few absolute things that I've learned about what folks say about QB64 from over the years, two of the most prevalent have to be:
1) MEM IS HARD!! IT'S NOT FOR BEGINNERS!!
2) Opening files for INPUT and OUTPUT is the most basic of BASIC. *EVERYONE* knows how to do this -- if not, then they'll learn it by the second lesson on learning QB64...
Now, I'm not saying I agree with point 1 -- I truly don't think that mem is all that hard to learn and use, which is why I've made videos and written a bazillion words on how to help folks understand it. BUT, even after all that, the general consensus is "Mem is hard and not for beginners!"
But... What if I told you guys that I was working on a way to bring those two concepts together?? That I was making a means so that one could use _MEM just as easily as they can use LINE INPUT and PRINT??
Don't believe it??
Then let me present.... Dum Dum De Dummmm:
Here's the main code of relevance for the end user -- see how it'd compare to a normal file being opened in QB64:
The very first line here is a wee bit odd, but think of it as: handle = FREEFILE It basically gives you a free handle and readies a block of memory for you to make use of.
PRINT #1, "Hello World"
PRINT #1, "My name is Steve"
Hopefully you can see where the next lines would match up to a simple file PRINT statement? That , 1 at the end there is basically the way of telling the program what file ending we want, or if we want to toss a comma at the end of this data, for CSVs. (Think of it as being PRINT #1, "Hello World", <-- do we put that comma there at the end, or not??) ,1 says we're going with a normal CHR$(10) file ending at the end of the data.
The MemSeek is basically the same as the SEEK statement, with the exception that we start at position 0 rather than position 1. (I may adjust this later, if folks feel its necessary.)
DO UNTIL EOF(1)
LINE INPUT #1, temp$
PRINT temp$
LOOP
And the next few lines should definitely be noticeably comparable to the file LINE INPUT method. Right?
It's all in mem... but it's simple PRINT and LINE INPUT style commands...
Is your mind blown yet??
Yet to do:
There needs to be a CLOSE statement to close the files and free the memory for good.
I also want to add 2 quick commands : MemFileSave -- to save the mem block to disk. MemFileLoad -- to load the file back into memory.
And what's the purpose to such a system?? Besides trying to make use of the speed of using mem?
To reduce disk reads and writes as much as possible and save wear and usage of SSDs. Load the whole file at once. Save the whole file at once. Otherwise, just read and write to a mem block exactly as you normally would a file! No need to track offsets. No _memget or _memput.... Just simple PRINT and INPUT file access like folks are used to doing already.
Any and all comments and feedback is appreciated. Post questions and suggestions galore! Honestly, I'd say this is already 90% finished. If anyone has any specific user requests, get them in *now*, before I wrap this up in the next day or so, and move on to something else.
1) MEM IS HARD!! IT'S NOT FOR BEGINNERS!!
2) Opening files for INPUT and OUTPUT is the most basic of BASIC. *EVERYONE* knows how to do this -- if not, then they'll learn it by the second lesson on learning QB64...
Now, I'm not saying I agree with point 1 -- I truly don't think that mem is all that hard to learn and use, which is why I've made videos and written a bazillion words on how to help folks understand it. BUT, even after all that, the general consensus is "Mem is hard and not for beginners!"
But... What if I told you guys that I was working on a way to bring those two concepts together?? That I was making a means so that one could use _MEM just as easily as they can use LINE INPUT and PRINT??
Don't believe it??
Then let me present.... Dum Dum De Dummmm:
Code: (Select All)
Type Mem_File_Type
inUse As Integer
EOF_Marker As _Offset
Current_Pos As _Offset
Content As _MEM
End Type
Dim Shared MemFile(1 To 100) As Mem_File_Type
'BI HEADER INFO BEFORE THIS
handle = MemFileOpen
MemPrint handle, "Hello World", 1
MemPrint handle, "My name is Steve", 1
MemSeek handle, 0
Do Until MemEOF(handle)
MemLineInput handle, temp$
Print temp$
Loop
'BM FOOTER INFO AFTER THIS
Function MemFileOpen
'Error codes for MemFileOpen
'1: No mem files available. (All 100 are in use! Free some to use more!)
For i = 1 To 100
If MemFile(i).inUse = 0 Then Exit For
Next
If i > 100 Then MemFileOpen = 0 'can't open any more memfiles!
MemFileOpen = i
MemFile(i).inUse = -1 'TRUE
MemFile(i).EOF_Marker = 0 'nothing is written in the file to begin with
MemFile(i).Current_Pos = 0 'and we're at the start of our nothing in the file
MemFile(i).Content = _MemNew(1000000) '1mb memfile by default
$Checking:Off
_MemFill MemFile(i).Content, MemFile(i).Content.OFFSET, MemFile(i).Content.SIZE, 0 As _UNSIGNED _BYTE
'make certain to blank the file when opening it for the first time so we don't have unwanted characters in it.
$Checking:On
End Function
Function MemEOF (memfile)
If MemFile(memfile).inUse = 0 Then Error 53: Exit Function 'File Not Found Error message
If MemFile(memfile).Current_Pos >= MemFile(memfile).EOF_Marker Then MemEOF = -1
End Function
Sub MemSeek (memfile, position As _Offset)
If MemFile(memfile).inUse = 0 Then Error 53: Exit Sub 'File Not Found Error message
If position < 0 Then Error 5: Exit Sub 'Invalid Function Call
If position > MemFile(memfile).EOF_Marker Then Error 5: Exit Sub 'Invalid Function Call
MemFile(memfile).Current_Pos = position
End Sub
Sub MemLineInput (memfile, what$)
'only valid line endings here are CHR$(10), chr$(13), and chr$(13) + chr$(10)
If MemFile(memfile).inUse = 0 Then Error 53: Exit Sub 'File Not Found Error message
Dim As _Offset CP, EP, Size, L
Dim tempM As _MEM
tempM = MemFile(memfile).Content 'it's just much shorter to type!
CP = MemFile(memfile).Current_Pos
EP = MemFile(memfile).EOF_Marker
If CP >= EP Then Error 62: Exit Sub 'INPUT PAST END OF FILE error
Size = tempM.SIZE
Do
a$ = _MemGet(tempM, tempM.OFFSET + CP, String * 1)
Select Case a$
Case Chr$(13)
a1$ = _MemGet(tempM, tempM.OFFSET + CP + 1, String * 1)
If al$ = Chr$(10) Then CP = CP + 1 'move the Current Pointer past the 2nd character in a windows CRLF ending
finished = -1
Case Chr$(10)
finished = -1
Case Else
temp$ = temp$ + a$
End Select
CP = CP + 1
If CP >= EP Then finished = -1
Loop Until finished
MemFile(memfile).Current_Pos = CP
what$ = temp$
End Sub
Sub MemPrint (memfile, what$, EOL_Type As Integer)
'memfile is the memfile handle to print to
'what$ is what we want to print
'EOL_Type is the type of line ending we want after this print statement
'1: This is a CHR$(10) line ending (Linux style line ending)
'2: This is a CHR$(13) line ending (Old Mac style line ending)
'3: This is a CHR$(13) + CHR$(10) line ending (Old Windows style line ending)
'4: This is a COMMA line ending. Use this if writing continous CSV fields.
' (Think PRINT #1, stuff$, <-- see the comma there at the end of the print statement??)
If MemFile(memfile).inUse = 0 Then Error 53: Exit Sub 'File Not Found Error message
Dim CRLF As String
Dim As _Offset CP, EP, Size, L
Select Case EOL_Type
Case 1: CRLF = Chr$(10)
Case 2: CRLF = Chr$(13)
Case 3: CRLF = Chr$(13) + Chr$(10)
Case 4: CRLF = ","
End Select
CP = MemFile(memfile).Current_Pos
EP = MemFile(memfile).EOF_Marker
Size = MemFile(memfile).Content.SIZE
L = Len(what$) + Len(CRLF)
If CP + L > Size Then 'we're writing beyond the bounds of our reserved memory!
Dim tempM As _MEM
recheck:
If Size <= 100000000 Then 'resize our memblock (to the limit) to save our data
tempM = _MemNew(Size * 10)
_MemCopy MemFile(memfile).Content, MemFile(memfile).Content.OFFSET, Size To tempM, tempM.OFFSET
_MemFree MemFile(memfile).Content
MemFile(memfile).Content = tempM
Size = Size * 10
GoTo recheck 'just to make certain that our reserved memory is now large enough to hold our data
Else
Error 61 'DISK FULL ERROR MESSAGE
Exit Sub 'I'm coding a hard size limit of 1GB for each memfile opened!
' Anything larger than that, and I'm tossing a Disk Full Error
End If
End If
_MemPut MemFile(memfile).Content, MemFile(memfile).Content.OFFSET + CP, what$ + CRLF
MemFile(memfile).Current_Pos = CP + L
If CP + L > EP Then MemFile(memfile).EOF_Marker = CP + L
End Sub
Here's the main code of relevance for the end user -- see how it'd compare to a normal file being opened in QB64:
Code: (Select All)
handle = MemFileOpen
MemPrint handle, "Hello World", 1
MemPrint handle, "My name is Steve", 1
MemSeek handle, 0
Do Until MemEOF(handle)
MemLineInput handle, temp$
Print temp$
Loop
The very first line here is a wee bit odd, but think of it as: handle = FREEFILE It basically gives you a free handle and readies a block of memory for you to make use of.
PRINT #1, "Hello World"
PRINT #1, "My name is Steve"
Hopefully you can see where the next lines would match up to a simple file PRINT statement? That , 1 at the end there is basically the way of telling the program what file ending we want, or if we want to toss a comma at the end of this data, for CSVs. (Think of it as being PRINT #1, "Hello World", <-- do we put that comma there at the end, or not??) ,1 says we're going with a normal CHR$(10) file ending at the end of the data.
The MemSeek is basically the same as the SEEK statement, with the exception that we start at position 0 rather than position 1. (I may adjust this later, if folks feel its necessary.)
DO UNTIL EOF(1)
LINE INPUT #1, temp$
PRINT temp$
LOOP
And the next few lines should definitely be noticeably comparable to the file LINE INPUT method. Right?
It's all in mem... but it's simple PRINT and LINE INPUT style commands...
Is your mind blown yet??
Yet to do:
There needs to be a CLOSE statement to close the files and free the memory for good.
I also want to add 2 quick commands : MemFileSave -- to save the mem block to disk. MemFileLoad -- to load the file back into memory.
And what's the purpose to such a system?? Besides trying to make use of the speed of using mem?
To reduce disk reads and writes as much as possible and save wear and usage of SSDs. Load the whole file at once. Save the whole file at once. Otherwise, just read and write to a mem block exactly as you normally would a file! No need to track offsets. No _memget or _memput.... Just simple PRINT and INPUT file access like folks are used to doing already.
Any and all comments and feedback is appreciated. Post questions and suggestions galore! Honestly, I'd say this is already 90% finished. If anyone has any specific user requests, get them in *now*, before I wrap this up in the next day or so, and move on to something else.