Problem with PeekS()

Just starting out? Need help? Post your questions and find answers here.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Problem with PeekS()

Post 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)
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
jacdelad
Addict
Addict
Posts: 2031
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Problem with PeekS()

Post by jacdelad »

Is Peek officially allowed for constants?
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
the.weavster
Addict
Addict
Posts: 1581
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Problem with PeekS()

Post by the.weavster »

*deleted... not useful :D
Last edited by the.weavster on Sat Sep 21, 2024 2:59 pm, edited 1 time in total.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Problem with PeekS()

Post 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))
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: Problem with PeekS()

Post by Psychophanta »

@breeze4me,

Code: Select all

var$=PeekS(Ascii(#CRLF$),2,#PB_Ascii)
should not store unicode, but ascii, isn't it?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Problem with PeekS()

Post by breeze4me »

Unless you're using an older version that supports ASCII compilation mode, strings are only stored in variables as Unicode.
AZJIO
Addict
Addict
Posts: 2225
Joined: Sun May 14, 2017 1:48 am

Re: Problem with PeekS()

Post 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.

Code: Select all

Ascii(#CRLF$)
Read 2 bytes, treating each byte as #PB_Ascii. The output in Unicode will be 4 bytes.

Code: Select all

),2,#PB_Ascii
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
Last edited by AZJIO on Sat Sep 21, 2024 7:11 pm, edited 1 time in total.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Problem with PeekS()

Post 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)
User avatar
Mijikai
Addict
Addict
Posts: 1520
Joined: Sun Sep 11, 2016 2:17 pm

Re: Problem with PeekS()

Post 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
User avatar
STARGÅTE
Addict
Addict
Posts: 2259
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Problem with PeekS()

Post 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.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: Problem with PeekS()

Post 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
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Mijikai
Addict
Addict
Posts: 1520
Joined: Sun Sep 11, 2016 2:17 pm

Re: Problem with PeekS()

Post 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
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: Problem with PeekS()

Post 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))
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Mijikai
Addict
Addict
Posts: 1520
Joined: Sun Sep 11, 2016 2:17 pm

Re: Problem with PeekS()

Post 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?
User avatar
Demivec
Addict
Addict
Posts: 4281
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Problem with PeekS()

Post 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
Post Reply