Page 1 of 1

Replace nulls in ::string

Posted: 2 Jul 2020 10:27
by kingchris
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

Re: Replace nulls in ::string

Posted: 2 Jul 2020 18:41
by Martin Meyer
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).

Re: Replace nulls in ::string

Posted: 3 Jul 2020 5:10
by kingchris
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.

Re: Replace nulls in ::string

Posted: 3 Jul 2020 12:11
by Thomas Linder Puls
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

Re: Replace nulls in ::string

Posted: 3 Jul 2020 13:59
by Martin Meyer
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?

Re: Replace nulls in ::string

Posted: 3 Jul 2020 14:29
by Martin Meyer
@Chris: For the learning curve check the implementation of fromMsStringSeq/1-> in windowsAPI.pro, it is done there more efficient than in my code.

Re: Replace nulls in ::string

Posted: 3 Jul 2020 14:44
by kingchris
Will do