Discussions related to Visual Prolog
kingchris
Active Member
Posts: 28 Joined: 26 Sep 2005 9:35
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: 354 Joined: 14 Nov 2002 0:01
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 = '\u 0000' 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: 28 Joined: 26 Sep 2005 9:35
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.
Thomas Linder Puls
VIP Member
Posts: 1466 Joined: 28 Feb 2000 0:01
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: 354 Joined: 14 Nov 2002 0:01
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: 354 Joined: 14 Nov 2002 0:01
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: 28 Joined: 26 Sep 2005 9:35
Post
by kingchris » 3 Jul 2020 14:44
Will do