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