Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2014-07

Method for write string into TStream

16 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

LacaK

Hi,
When I work with f.e. TFileStream I need often write string into stream. Now I use:

  Stream1.WriteBuffer(s[1], length(s));
I think, that for convenience it will be useful having something like:
procedure TStream.WriteString(const s: string);
  begin
    WriteBuffer(s[1], length(s)*sizeof(char);
  end;

In FPC we now have for user convenience also WriteByte, WriteWord, WriteQWord (which all calls WriteBuffer)
and Delphi has lot of overloaded WriteData (but none of them takes as parameter string):

http://docwiki.embarcadero.com/Libraries/XE3/en/System.Classes.TStream.WriteData

Do you think, that something similar can be added also in FPC ? Thanks
-Laco.

Reply by email

Sven Barth
to LacaK
"LacaK" wrote 13 lines
Hi, When I work with f.e. TFileStream I need often write string into stream. Now I use: Stream1.WriteBuffer(s[1], length(s)); I think, that for convenience it will be useful having something like: procedure TStream.WriteString(const s: string); begin WriteBuffer(s[1], length(s)*sizeof(char); end; In FPC we now have for user convenience also WriteByte, WriteWord,

WriteQWord (which all calls WriteBuffer)

and Delphi has lot of overloaded WriteData (but none of them takes as

parameter string):

http://docwiki.embarcadero.com/Libraries/XE3/en/System.Classes.TStream.WriteData

Do you think, that something similar can be added also in FPC ?

There is already a WriteAnsiString (
http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html ) with the difference that it also writes out the length. Adding an additional overload (especially with a name like WriteString) would IMHO be confusing because of this.

Nothing stops you though from writing a class helper that adds a WriteString method to TStream.

Regards,
Sven

Reply by email

Marco van de Voort
to Sven Barth

In our previous episode, Sven Barth said:

Show quoted text 10 lines
> Do you think, that something similar can be added also in FPC ? There is already a WriteAnsiString ( http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html ) with the difference that it also writes out the length. Adding an additional overload (especially with a name like WriteString) would IMHO be confusing because of this. Nothing stops you though from writing a class helper that adds a WriteString method to TStream.

(Except the fact that you can only have one class helper per class?)

Maybe writebinansistring would be a good name.

Reply by email

LacaK
to Sven Barth: WriteQWord (which all calls WriteBuffer) parameter string):…

Sven Barth wrote / napísal(a):

Show quoted text 28 lines
Am 21.07.2014 10:29 schrieb "LacaK" < >: > > Hi, > When I work with f.e. TFileStream I need often write string into stream. > Now I use: > Stream1.WriteBuffer(s[1], length(s)); > > I think, that for convenience it will be useful having something like: > procedure TStream.WriteString(const s: string); > begin > WriteBuffer(s[1], length(s)*sizeof(char); > end; > > In FPC we now have for user convenience also WriteByte, WriteWord, WriteQWord (which all calls WriteBuffer) > and Delphi has lot of overloaded WriteData (but none of them takes as parameter string): > http://docwiki.embarcadero.com/Libraries/XE3/en/System.Classes.TStream.WriteData > > Do you think, that something similar can be added also in FPC ? There is already a WriteAnsiString ( http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html ) with the difference that it also writes out the length.

Yes I know, and I do not want write length only content of string

Adding an additional overload (especially with a name like WriteString) would IMHO be confusing because of this.

Yes without looking into documentation at first look it can by confusable (what about WriteRawString then) ?

Nothing stops you though from writing a class helper that adds a WriteString method to TStream.

Yes, I can create also own descendant etc. ... but I am asking for general solution, which will be useful for all.

Thanks
-Laco.

Reply by email

Michael Van Canneyt
to LacaK
LacaK wrote 33 lines
Sven Barth  wrote / napísal(a): Am 21.07.2014 10:29 schrieb "LacaK" : > > Hi, > When I work with f.e. TFileStream I need often write string into stream. > Now I use: >  Stream1.WriteBuffer(s[1], length(s)); > > I think, that for convenience it will be useful having something like: > procedure TStream.WriteString(const s: string); >  begin >    WriteBuffer(s[1], length(s)*sizeof(char); >  end; > > In FPC we now have for user convenience also WriteByte, WriteWord, WriteQWord (which all calls WriteBuffer) > and Delphi has lot of overloaded WriteData (but none of them takes as parameter string): >  http://docwiki.embarcadero.com/Libraries/XE3/en/System.Classes.TStream.WriteData > > Do you think, that something similar can be added also in FPC ? There is already a WriteAnsiString ( http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html ) with the difference that it also writes out the length. Yes I know, and I do not want write length only content of string Adding an additional overload (especially with a name like WriteString) would IMHO be confusing because of this. Yes without looking into documentation at first look it can by confusable (what about WriteRawString then) ? Nothing stops you though from writing a class helper that adds a WriteString method to TStream. Yes, I can create also own descendant etc. ... but I am asking for general solution, which will be useful for all.

Sure:
We can simply add a boolean parameter 'WriteLength : Boolean = True' to the existing call. It keeps backwards compatibility, and allows you to write the strings with or without length.

Another option is to add a WriteLn() with various overloaded variants. It should be clear then that this will write a textual representation.

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt

In our previous episode, Michael Van Canneyt said:

Show quoted text 7 lines
> Nothing stops you though from writing a class helper that adds a WriteString method to TStream. > > Yes, I can create also own descendant etc. ... but I am asking for general solution, which will be useful for all. Sure: We can simply add a boolean parameter 'WriteLength : Boolean = True' to the existing call. It keeps backwards compatibility, and allows you to write the strings with or without length.

(If so I would make it an enum selecting 0,2,4 bytes length or so)

Reply by email

LacaK
to Marco van de Voort

Marco van de Voort wrote / napísal(a):

Show quoted text 13 lines
In our previous episode, Michael Van Canneyt said: >> Nothing stops you though from writing a class helper that adds a WriteString method to TStream. >> >> Yes, I can create also own descendant etc. ... but I am asking for general solution, which will be useful for all. >> > Sure: > We can simply add a boolean parameter 'WriteLength : Boolean = True' to the existing call. > It keeps backwards compatibility, and allows you to write the strings with or without length. > (If so I would make it an enum selecting 0,2,4 bytes length or so)

Both variants are Ok for me.
But If we will extend WriteAnsiString, then we must IMO also extend ReadAnsiString, and in case where length is not a part of streamed data then it must be explicitly given as parameter to method call (not only enum)

So IMO simpler will be introduce new methods (like):
  procedure WriteRawString(const s: string);
  function ReadRawString(Len: integer)
or alter existing AnsiString methods to something like:
  type TLengthPrefix = (lenNone, lenWord, lenDWord);
  procedure WriteAnsiString(const s: string; WriteLength: TLengthPrefix
= lenDWord);
  function ReadAnsiString(ReadLength: TLengthPrefix=lenDWord; Len:
integer=0);

-Laco.

Reply by email

Dmitry Boyarintsev
to Marco van de Voort: In our previous episode, Sven Barth said: (Except the fact that you can only have one…

How about introducing a default parameter?
The parameter keeps the method backward compatible, allowing write a string without the prefix.

public procedure TStream.WriteAnsiString(
  const S: string;
  withLength: Boolean = true;
);

thanks,
Dmitry

Marco van de Voort wrote 21 lines
In our previous episode, Sven Barth said: > > Do you think, that something similar can be added also in FPC ? > > There is already a WriteAnsiString ( > http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html > ) with the difference that it also writes out the length. Adding an > additional overload (especially with a name like WriteString) would IMHO be > confusing because of this. > > Nothing stops you though from writing a class helper that adds a > WriteString method to TStream. (Except the fact that you can only have one class helper per class?) Maybe writebinansistring would be a good name. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Sven Barth
to Marco van de Voort: In our previous episode, Sven Barth said: (Except the fact that you can only have one…
"Marco van de Voort" wrote 6 lines
In our previous episode, Sven Barth said: > > Do you think, that something similar can be added also in FPC ? > > There is already a WriteAnsiString ( >

http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html

> ) with the difference that it also writes out the length. Adding an > additional overload (especially with a name like WriteString) would

IMHO be

Show quoted text 6 lines
> confusing because of this. > > Nothing stops you though from writing a class helper that adds a > WriteString method to TStream. (Except the fact that you can only have one class helper per class?)

Doesn't stop him from writing the helper, only from using it :P

Regards,
Sven

Reply by email

LacaK
to LacaK: Marco van de Voort wrote / napísal(a): Both variants are Ok for me. But If we will…

Recap:

Way 1: Introduce new method(s), leave Write/ReadAnsiString as is.
1.1
  procedure WriteRawString(const s: string);
  function ReadRawString(Len: integer)
1.2 (ready for future when string will be UnicodeString)
  procedure WriteString(const s: string);
  function ReadString(Len: integer)
1.3 (create superior of Write/ReadAnsiString)
  type TStringLengthPrefix = (lenNone, lenWord, lenDWord);
  procedure WriteString(const s: string; WriteLength:
TStringLengthPrefix = lenNone);
  function ReadString(ReadLength: TStringLengthPrefix=lenNone; Len:
integer=0);
Way 2: Extend existing Write/ReadAnsiString (keeping backward compatibility)
2.1
  type TStringLengthPrefix = (lenNone, lenWord, lenDWord);
  procedure WriteAnsiString(const s: string; WriteLength:
TStringLengthPrefix = lenDWord);
  function ReadAnsiString(ReadLength: TStringLengthPrefix=lenDWord; Len:
integer=0);
(but IMO in future, when string becomes unicodestring, then "Ansi" in
name will sound strange if parameter does not change from "string" to
"ansistring")

Way 3: Do nothing ;-)
If nobody else consider it as useful. ;-)

-Laco.

Reply by email

Unknown author
to Hans-Peter Diettrich: How should a string without a length be read back? DoDi

A case for ternary computing is not really a bad idea ;)

Hans-Peter Diettrich wrote 16 lines
Dmitry Boyarintsev schrieb: > How about introducing a default parameter? > The parameter keeps the method backward compatible, allowing write a > string without the prefix. > > public procedure TStream.WriteAnsiString( > const S: string; > withLength: Boolean = true; How should a string without a length be read back? DoDi _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Unknown author
to LacaK: When I work with f.e. TFileStream I need often write string into stream. Now I use:…

You can always use KOL for that ;)
But anyway: we implemented that at the cost of read-back speed and looking for zero termination, which is flawed anyway for object pascal strings, since it can contain zero's.
It can be done through RTTI with my usual complaints about that sort of shit.

A (abstract) stream can not know if the length is stored or not...without rtti.

If you accept polymorhism this is not a good idea. I may be wrong (again)

LacaK wrote 25 lines
Hi, When I work with f.e. TFileStream I need often write string into stream. Now I use: Stream1.WriteBuffer(s[1], length(s)); I think, that for convenience it will be useful having something like: procedure TStream.WriteString(const s: string); begin WriteBuffer(s[1], length(s)*sizeof(char); end; In FPC we now have for user convenience also WriteByte, WriteWord, WriteQWord (which all calls WriteBuffer) and Delphi has lot of overloaded WriteData (but none of them takes as parameter string): http://docwiki.embarcadero.com/Libraries/XE3/en/System.Classes.TStream.WriteData Do you think, that something similar can be added also in FPC ? Thanks -Laco. _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Dmitry Boyarintsev
to Unknown author: A case for ternary computing is not really a bad idea ;)
Show quoted text 20 lines
A case for ternary computing is not really a bad idea ;) On 21-7-2014 21:42, Hans-Peter Diettrich wrote: > Dmitry Boyarintsev schrieb: > > How about introducing a default parameter? >> The parameter keeps the method backward compatible, allowing write a >> string without the prefix. >> >> public procedure TStream.WriteAnsiString( >> const S: string; >> withLength: Boolean = true; >> > > How should a string without a length be read back? > > DoDi > > I didn't see DoDi's email anywhere in the thread, though it seems like

there're two threads anyway:
"Re: [fpc-devel] Method for write string into TStream" and "[fpc-devel] Method for write string into TStream"

Anyways, answering DoDi's question.
It definitely won't be able to read a string without a size, but it doesn't mean that the string size should immediately precede the string content. So maybe a modification like this could help

procedure TStream.ReadAnsiString(knownsize: Integer=-1)
   if knownsize<0 then
     TheSize := ...readsize
  else
     TheSize := knownsize

thanks,
Dmitry

Reply by email

Unknown author
to Dmitry Boyarintsev

What I was a little bit more than hinting at in my previous answers is that it is impossible for an abstract read stream to know that there's a string to read. There is at least one higher level of implementation necessary: one that recognizes a string.
That means probably something like storing the length and storing a string marker and/or use RTTI for strings, to be consistent.

In practice, I use json for that kind of streaming. And that is already in place.

Dmitry Boyarintsev wrote 47 lines
On Tue, Jul 22, 2014 at 6:46 AM, < > wrote: A case for ternary computing is not really a bad idea ;) On 21-7-2014 21:42, Hans-Peter Diettrich wrote: Dmitry Boyarintsev schrieb: How about introducing a default parameter? The parameter keeps the method backward compatible, allowing write a string without the prefix. public procedure TStream.WriteAnsiString( const S: string; withLength: Boolean = true; How should a string without a length be read back? DoDi I didn't see DoDi's email anywhere in the thread, though it seems like there're two threads anyway: "Re: [fpc-devel] Method for write string into TStream" and "[fpc-devel] Method for write string into TStream" Anyways, answering DoDi's question. It definitely won't be able to read a string without a size, but it doesn't mean that the string size should immediately precede the string content. So maybe a modification like this could help procedure TStream.ReadAnsiString(knownsize: Integer=-1) if knownsize<0 then TheSize := ...readsize else TheSize := knownsize thanks, Dmitry _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Dmitry Boyarintsev
to Unknown author
Show quoted text 7 lines
What I was a little bit more than hinting at in my previous answers is that it is impossible for an abstract read stream to know that there's a string to read. There is at least one higher level of implementation necessary: one that recognizes a string. That means probably something like storing the length and storing a string marker and/or use RTTI for strings, to be consistent.

Actually after rereading both threads (with "Re" and without "Re" in the subject), it's quite clear to me that I should have not posted to it at all :)

My only other 2 cents would be - lets not modify the base class, but rather create a task-convenient wrappers in forms of (inline) functions or class-helpers. These wrappers would be stored in a project or a developer's library, rather being added to the base RTL.

thanks,
Dmitry

Reply by email