Page 1 of 2
Problem with PeekS()
Posted: Sat Sep 21, 2024 2:09 pm
by Psychophanta
When I tried to assign an ascii string to a variable, not success using PeekS(), so I have to take the ugly way : CopyMemory()
Test yourself
Code: Select all
var$=PeekS(Ascii(#CRLF$),2,#PB_Ascii); <- Not Ok ??
debug peekB(@var$)
debug peekB(@var$+1)
debug "-----------"
CopyMemory(Ascii(#CRLF$),@var$,2); <- Ok
debug peekB(@var$)
debug peekB(@var$+1)
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 2:23 pm
by jacdelad
Is Peek officially allowed for constants?
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 2:36 pm
by the.weavster
*deleted... not useful

Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 2:42 pm
by breeze4me
Code: Select all
var$=PeekS(Ascii(#CRLF$),2,#PB_Ascii)
As a result of the execution of the above line, a Unicode string is stored in the var$ variable. Therefore, it should be read with PeekC, not PeekB.
Code: Select all
var$=PeekS(Ascii(#CRLF$),2,#PB_Ascii)
Debug PeekC(@var$)
Debug PeekC(@var$+ SizeOf(Character))
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 3:27 pm
by Psychophanta
@breeze4me,
Code: Select all
var$=PeekS(Ascii(#CRLF$),2,#PB_Ascii)
should not store unicode, but ascii, isn't it?
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 3:40 pm
by breeze4me
Unless you're using an older version that supports ASCII compilation mode, strings are only stored in variables as Unicode.
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 6:18 pm
by AZJIO
Code: Select all
var$=PeekS(Ascii(#CRLF$), 1) ; -1
Debug PeekB(@var$)
Debug PeekB(@var$+1)
Psychophanta wrote: Sat Sep 21, 2024 3:27 pm
should not store unicode, but ascii, isn't it?
Reads ascii, converts to unicode
There are 2 bytes here.
Read 2 bytes, treating each byte as #PB_Ascii. The output in Unicode will be 4 bytes.
Reading 4 bytes with a +1 shift will not get the expected result.
If you use #PB_Unicode (default), you will get the same value of 2 bytes, but as one character.
Code: Select all
var$=PeekS(Ascii(#CRLF$),1) ; -1
Debug Asc(var$)
Debug Len(var$)
ShowMemoryViewer(@var$, 2)
Debug $0D
Debug $0A
Edit: corrected to the correct value 2->1
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 6:58 pm
by breeze4me
@AZJIO
The number of characters to read should be 1, not 2.
The buffer size allocated by Ascii(#CRLF$) is three bytes, so reading two characters in Unicode format is reading four bytes, which can cause problems.
13 10 (Unicode 1 chr) / 0 + x (Unicode 1 chr)
*Buffer = Ascii(String$)
......
The buffer includes a null-terminated character.
Code: Select all
;;var$=PeekS(Ascii(#CRLF$), 2) ; Read 2 characters (=4 bytes) in Unicode format from that memory.
var$=PeekS(Ascii(#CRLF$), 1) ; Read 1 character (=2 bytes) in Unicode format from that memory.
; var$=PeekS(Ascii(#CRLF$), 1, #PB_Unicode) ; same
Debug PeekB(@var$)
Debug PeekB(@var$+1)
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 8:58 pm
by Mijikai
Sometimes i do something like this (ASM backend):
Code: Select all
EnableExplicit
Global str.s
str = PeekS(?hello,-1,#PB_Ascii)
Debug str
DataSection
hello:
!db 'Hello World',0
EndDataSection
Re: Problem with PeekS()
Posted: Sat Sep 21, 2024 9:22 pm
by STARGÅTE
A string variable like var$ stores its content always in unicode (UTF16) format.
The #PB_Ascii flag in PeekS is just for the source format.
Using CopyMemory is incorrect. It leads to IMAs, is the string was not allocated before in a sufficient length.
Re: Problem with PeekS()
Posted: Mon Sep 23, 2024 7:45 am
by Psychophanta
@Mijikai
Not good idea; to see it, please just replace 'Debug str' in your code by 'ShowMemoryViewer(@str,Len(str))'
STARGÅTE wrote: Sat Sep 21, 2024 9:22 pm
Using CopyMemory is incorrect. It leads to IMAs, is the string was not allocated before in a sufficient length.
CopyMemory(Ascii(#CRLF$),@var$,Len(#CRLF$)+1); <- Ok
In general:
viewtopic.php?t=85410
Re: Problem with PeekS()
Posted: Mon Sep 23, 2024 5:21 pm
by Mijikai
Ok, give this a try (no CopyMemory):
Code: Select all
EnableExplicit
Global *test.String
Global *memory
Global length.i
Procedure.i AsciiAlloc(String.s);<- some black magic
Protected *str.Integer
Protected *eod.Ascii
*str = Ascii(Space(SizeOf(Integer)) + String + ".")
If *str
*str\i = *str + SizeOf(Integer)
*eod = *str + MemorySize(*str) - 2
*eod\a = 0
ProcedureReturn *str
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i AsciiDebug(*String.Integer);<- only for debugging
ShowMemoryViewer(*String\i,MemorySize(*String) - SizeOf(Integer) - 1)
ProcedureReturn #Null
EndProcedure
Procedure.i AsciiMemory(*String.Integer,*Length.Integer = #Null);<- get information about the memory
If *Length
*Length\i = MemorySize(*String) - SizeOf(Integer) - 2
EndIf
ProcedureReturn *String\i
EndProcedure
Procedure.i AsciiFree(*String)
FreeMemory(*String)
ProcedureReturn #Null
EndProcedure
*test = AsciiAlloc("Hello World")
*memory = AsciiMemory(*test,@length)
Debug *test\s ;<- assigned to string...
Debug *memory ;<- ascii string in memory
Debug length ;<- ascii string length
AsciiDebug(*test) ;<- show ascii string in memory
AsciiFree(*test) ;<- free ascii string
End
Re: Problem with PeekS()
Posted: Mon Sep 23, 2024 7:19 pm
by Psychophanta
@Mijikai
That's correct. Just it has to be stored in a string variable instead of pointer, like this one, which i think this is totally safe:
Code: Select all
Procedure$ AsignarCadenaAscii(cadena$)
;Carga una cadena de caracteres ascii extendido en una variable
Protected size.i=2*Round((Len(cadena$)+1)/2,#PB_Round_Up)
Protected *mem.byte=AllocateMemory(size,#PB_Memory_NoClear)
*mem=Ascii(cadena$)
ProcedureReturn PeekS(*mem,size)
EndProcedure
c$="Hello World !"
var$=AsignarCadenaAscii(c$)
debug var$
ShowMemoryViewer(@var$,2*Round((Len(c$)+1)/2,#PB_Round_Up))
Re: Problem with PeekS()
Posted: Mon Sep 23, 2024 8:25 pm
by Mijikai
@Psychophanta you leak *mem.
Due to the nature of the String representation in PB we should probably both still accomodate a 2nd zero (& alignment).
Also i think your version is still unsafe and only works because AllocateMemory internally reserves a bigger block.
PeekS will read 2 bytes per char regardless (not only 14 bytes).
Using var$/var.s (instead of a struct) may interfere with the internal memory management of Strings.
Btw. what will be the use for this Ascii.s thing?
Re: Problem with PeekS()
Posted: Mon Sep 23, 2024 10:54 pm
by Demivec
Psychophanta wrote: Mon Sep 23, 2024 7:19 pm
@Mijikai
That's correct. Just it has to be stored in a string variable instead of pointer, like this one, which i think this is totally safe:
Code: Select all
Procedure$ AsignarCadenaAscii(cadena$)
;Carga una cadena de caracteres ascii extendido en una variable
Protected size.i=2*Round((Len(cadena$)+1)/2,#PB_Round_Up)
Protected *mem.byte=AllocateMemory(size,#PB_Memory_NoClear)
*mem=Ascii(cadena$)
ProcedureReturn PeekS(*mem,size)
EndProcedure
c$="Hello World !"
var$=AsignarCadenaAscii(c$)
debug var$
ShowMemoryViewer(@var$,2*Round((Len(c$)+1)/2,#PB_Round_Up))
The following code has a memory leak:
Code: Select all
Procedure$ AsignarCadenaAscii(cadena$)
;Carga una cadena de caracteres ascii extendido en una variable
Protected size.i=2*Round((Len(cadena$)+1)/2,#PB_Round_Up)
Protected *mem.byte=AllocateMemory(size,#PB_Memory_NoClear) ; <<<< this memory is never freed after the address is list on the next statement
*mem=Ascii(cadena$) ;<<<< this memory is never freed, only copied
ProcedureReturn PeekS(*mem,size)
EndProcedure