Replace nulls in ::string

Discussions related to Visual Prolog
kingchris
Active Member
Posts: 26
Joined: 26 Sep 2005 9:35

Replace nulls in ::string

Unread post by kingchris » 2 Jul 2020 10:27

I am writing a system volume crawler.
One of the Win32 functions is

Code: Select all

Vols = string::create(256), Count =  fileSystem_native::getLogicalDriveStrings(256, Vols),
The 256 buffer space is overkill for now I know.

The result is not a string but a series of strings separated by a null then the whole string is terminated by null null.
c:\<null>d:\<null><null>

After two days on and off looking at various ways to parse this data. result in only the C:\null being seen.
So my question is: how to replace all single nulls in this PDC Prolog wide string with say ";". The normal string::replace does not like the nulls.

Then I can parse the string using ";" as the seperator

Martin Meyer
VIP Member
Posts: 280
Joined: 14 Nov 2002 0:01

Re: Replace nulls in ::string

Unread post by Martin Meyer » 2 Jul 2020 18:41

Maybe there is a problem in memory::getString/2->. Because when I replaced it by my own version, it has worked out:

Code: Select all

    open core   class predicates     getLogicalDriveStrings : (charCount BufLen, unsigned Result [out]) -> string_list Str_list. clauses     getLogicalDriveStrings(BufLen, Result) = getLogicalDriveStrings1(uncheckedConvert(pointer, Buf)) :-         Buf = memory::allocStringBuffer(BufLen, memory::contextType_string),         Result = fileSystem_native::getLogicalDriveStrings(convert(unsigned, BufLen), Buf).   class predicates     getLogicalDriveStrings1 : (pointer PStr) -> string_list Str_list. clauses     getLogicalDriveStrings1(PStr) = if Str = "" then [] else [Str | getLogicalDriveStrings1(After)] end if :-         %Str = memory::getString(PStr, After).         Str = getString(PStr, After).   class predicates     getString : (pointer Ptr, pointer After [out]) -> string Str. clauses     getString(Ptr, After) = getString1(Ptr, OutStream, After) :-         OutStream = outputStream_string::new().   class predicates     getString1 : (pointer Ptr, outputStream_string OutStream, pointer After [out]) -> string Str. clauses     getString1(Ptr, OutStream, After) = Str :-         Char = memory::getChar(Ptr, AfterChar),         if Char = '\u0000' then             After = AfterChar,             Str = OutStream:getString()         else             OutStream:write(Char),             Str = getString1(AfterChar, OutStream, After)         end if.   clauses     run() :-         StrList = getLogicalDriveStrings(256),         stdIO::write(StrList).
Regards Martin

kingchris
Active Member
Posts: 26
Joined: 26 Sep 2005 9:35

Re: Replace nulls in ::string

Unread post by kingchris » 3 Jul 2020 5:10

Thank you Martin Meyer. I will use it.

I had a lot of trouble converting the string to binary via direct functions or binary_outputstreams, as any conversion from strings would not read after the first null, but seeing how your method works will assist in the old learning curve.

Again. Much appreciated.

User avatar
Thomas Linder Puls
VIP Member
Posts: 1176
Joined: 28 Feb 2000 0:01

Re: Replace nulls in ::string

Unread post by Thomas Linder Puls » 3 Jul 2020 12:11

The result you show looks like the thing we have called a msStringSeq (Microsoft String Sequence).

There are predicates in the windowsApi class for converting to and from such "sequences":

Code: Select all

domains     msStringSeq = pointer.     % @short A sequence of null (two bytes) terminated Unicode strings.     % The sequence is ended by an empty string (same as two consecutive nulls = 4 x null).     % @end   predicates     toMsStringSeq : (string* StringList) -> msStringSeq Sequence.     fromMsStringSeq : (msStringSeq Sequence) -> string* StringList.     % @short Conversion between string #Sequence and list of string #StringList.     % @end
Regards Thomas Linder Puls
PDC

Martin Meyer
VIP Member
Posts: 280
Joined: 14 Nov 2002 0:01

Re: Replace nulls in ::string

Unread post by Martin Meyer » 3 Jul 2020 13:59

ah, thank you Thomas! So, we should do it like

Code: Select all

class predicates     getLogicalDriveStrings : (charCount BufLen, unsigned Result [out]) -> string_list Str_list. clauses     getLogicalDriveStrings(BufLen, Result) = windowsAPI::fromMsStringSeq(uncheckedConvert(windowsAPI::msStringSeq, Buf)) :-         Buf = memory::allocStringBuffer(BufLen, memory::contextType_string),         Result = fileSystem_native::getLogicalDriveStrings(convert(unsigned, BufLen), Buf).
Have I used (the outcommented) memory::getString/2-> wrong before or does it actually have a problem?
Regards Martin

Martin Meyer
VIP Member
Posts: 280
Joined: 14 Nov 2002 0:01

Re: Replace nulls in ::string

Unread post by Martin Meyer » 3 Jul 2020 14:29

@Chris: For the learning curve check the implementation of fromMsStringSeq/1-> in windowsAPI.pro, it is done there more efficient than in my code.
Regards Martin

kingchris
Active Member
Posts: 26
Joined: 26 Sep 2005 9:35

Re: Replace nulls in ::string

Unread post by kingchris » 3 Jul 2020 14:44

Will do

Post Reply