WritePreferenceString() with string contains line feed

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

WritePreferenceString() with string contains line feed

Post by uwekel »

Hi,

if you use the WritePreferencesString() function with a string containing a line feed, the structure of the settings file will be damaged. Also the original value will not be restored, because it is cut-off at the position of the first line feed.

I propose to encode the line feeds with a special character and automatically decode them again when using the ReadPreferenceString().

Regards
Uwe
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: WritePreferenceString() with string contains line feed

Post by Michael Vogel »

+1

Another, tiny thing with preference files which could be optimized (for Mr.Monk and me) - please remove the first empty line on the top of a preference file (which uses the #PB_Preference_GroupSeparator flag).
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: WritePreferenceString() with string contains line feed

Post by Dude »

Preference strings are meant to be single-line only, by the very definition of the INI file format.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: WritePreferenceString() with string contains line feed

Post by Michael Vogel »

Dude wrote:Preference strings are meant to be single-line only, by the very definition of the INI file format.
So if more mean the same thing, PB may support this meaning, too. Than it would be nice if only such strings would be written. So if PB handles this, it would be standardized and creates preference files which are compatible with other systems.

Otherwise there are some tons of possibilities to deal with it:
- special tricks could be used to convert the strings when writing/reading: "line 1"+x0D+"line 2" or "line 1\nline 2"
- strings are cutted at the position of the first illegal character: "line 1"
- the readpreferencestring function will get more intelligence (good luck)
- and so on.
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: WritePreferenceString() with string contains line feed

Post by Danilo »

Dude wrote:Preference strings are meant to be single-line only, by the very definition of the INI file format.
I think so, too.

Anyway, some simple ReplaceString will do, if somebody really requires this functionality.
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: WritePreferenceString() with string contains line feed

Post by uwekel »

I think there is nothing bad if the restored string is exactly the same as the stored one. I came across it, when saving and restoring the input of an editor gadget. It could be more simple if the preferences function would take it into account. And linefeeds are not the same on all systems, so you have to take care of it, too.
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: WritePreferenceString() with string contains line feed

Post by Little John »

uwekel wrote:I think there is nothing bad if the restored string is exactly the same as the stored one.
That's a very general statement, and it's true.

However, as Dude wrote, this file format is not designed for storing line feeds.
If in the future INI or PREFS files would exist with line feeds as part of the data, those files could not be read correctly by existing programs. Such a situation is undesirable and would cause unnecessary confusion.
uwekel wrote: I came across it, when saving and restoring the input of an editor gadget.
For this purpose, you can use other file formats that are also supported by PureBasic, for instance XML.
Maybe JSON also allows to store line feeds, I don't know.

You can also design an own file format, e.g.
[ASectionName]
Some text
with line breaks

[AnotherSectionName]
More text ...
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: WritePreferenceString() with string contains line feed

Post by uwekel »

Little John wrote:For this purpose, you can use other file formats that are also supported by PureBasic, for instance XML.
I prefer to put this setting together with all other settings to the preferences file. Temporarily, i encode it this way:

Code: Select all

ReplaceString(ReplaceString(MyStringWithLinefeed$, #CR$, "#CR$"), #LF$, "#LF$")
But it is not 100% error proof :(
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: WritePreferenceString() with string contains line feed

Post by Michael Vogel »

Just one (quick and dirty) non-standard approach to handle LF and CR (coded it for ascii, only few adjustments have to be done for unicode).

But...
... it's proprietary, so only usable within your own solutions
... you can't use Chr(1) and Chr(2) anymore (who cares, Chr(0) can't be used either)

Code: Select all

Procedure Mem(*mem1,*mem2,lines=5)

	Protected i,j
	Protected b1,b2
	Protected s.s

	While i<lines
		s=RSet(Hex(i<<4),4,"0")+" "
		For j=0 To 15
			b1=PeekB(*mem1+i<<4+j)&$FF
			b2=PeekB(*mem2+i<<4+j)&$FF
			s+RSet(Hex(b1),2,"0")
			If b1=b2
				s+" "
			Else
				s+"!"
				EndIf
			Next j
			s+"  |   "
		For j=0 To 15
			c=PeekB(*mem1+i<<4+j)
			If c>=' ' And c<='z'
				s+Chr(c)
			Else
				s+"."
			EndIf
		Next j
		Debug s
		i+1
	Wend
	Debug ":"

EndProcedure
Procedure.s AngryBird(s.s,mode)
	
	#Q=#DOUBLEQUOTE$
	#NewLF=1
	#NewCR=2

	Protected c,n

	n=Len(s)
	While n
		n-1
		c=PeekC(@s+n)
		Select c
		Case #LF
			If mode : PokeC(@s+n,#NewLF) : EndIf
		Case #CR
			If mode : PokeC(@s+n,#NewCR) : EndIf
		Case #NewLF
			If mode=0 : PokeC(@s+n,#LF) : EndIf
		Case #NewCR
			If mode=0 : PokeC(@s+n,#CR) : EndIf
		EndSelect
	Wend
	
	If mode
		If PeekC(@s)<>'"' : s=#Q+s+#Q : EndIf
	Else
		If PeekC(@s)='"' : s=Mid(s,2,Len(s)-2) : EndIf
	EndIf
		
	ProcedureReturn s

EndProcedure

sonderbar.s

For i=3 To 255
	sonderbar+RSet(Str(i%100),2,"0")+Chr(i)+" "
Next i

CreatePreferences("sonderbar.ini")
WritePreferenceString("standard",#Q+sonderbar+#Q)
WritePreferenceString("modified",AngryBird(sonderbar,#True))
ClosePreferences()

OpenPreferences("sonderbar.ini")
seltsam.s=ReadPreferenceString("standard","")
wundersam.s=AngryBird(ReadPreferenceString("modified",""),#False)
ClosePreferences()

Mem(@sonderbar,@seltsam)
If sonderbar=seltsam
	Debug "ok"
EndIf

Mem(@sonderbar,@wundersam)
If sonderbar=wundersam
	Debug "ok"
EndIf
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: WritePreferenceString() with string contains line feed

Post by Danilo »

uwekel wrote:Temporarily, i encode it this way:

Code: Select all

ReplaceString(ReplaceString(MyStringWithLinefeed$, #CR$, "#CR$"), #LF$, "#LF$")
You may want to cover #CRLF$ as well. It is one line break on some electronic typewriters.
Your current solution would probably make 2 line breaks out of one #CRLF$.
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: WritePreferenceString() with string contains line feed

Post by uwekel »

I now changed the code a bit, and use Chr(1) and Chr(2) as Michael proposed.

Encoding:

Code: Select all

ReplaceString(MyStringWithLinefeeds$, #LF$, Chr(1), #PB_String_InPlace)
ReplaceString(MyStringWithLinefeeds$, #CR$, Chr(2), #PB_String_InPlace)
Decoding:

Code: Select all

ReplaceString(MyStringWithLinefeeds$, Chr(1), #LF$, #PB_String_InPlace)
ReplaceString(MyStringWithLinefeeds$, Chr(2), #CR$, #PB_String_InPlace)
In most cases, Chr(1) and Chr(2) won't be typed into an editor gadget.

Btw, #PB_String_Inplace is really cool!
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
Post Reply