Sign in Join

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

Mailing lists / fpc-pascal / 2012-02

TStringStream.DataString returns garbage?

17 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

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

Graeme Geldenhuys

Hi,

What am I doing wrong in the following code? It always fails on test number 2. The DataString property is returning garbage, and not the value equal to the 'Graeme Geldenhuys' string.

----------------------------------------------
var
  srcstream: TStringStream;
  s, f: string;
  i: integer;
begin
  s := 'Graeme Geldenhuys';
  srcstream := TStringStream.Create('');
  { I purposely do this, because in my real-world code TStringStream will
    be populated with many .Write() statements. }
  i := srcstream.Write(s, Length(s));
  CheckEquals(i, Length(s), 'failed on length of string');    // passes
  srcstream.Seek(0, soFromBeginning); // not sure if needed
  f := srcstream.DataString;
  CheckEquals(s, f, 'Failed on string content 2');    // Fails!
  srcstream.Free;
end;
----------------------------------------------
Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net
Mattias Gaertner
to Graeme Geldenhuys
Show quoted text 11 lines
Hi, What am I doing wrong in the following code? It always fails on test number 2. The DataString property is returning garbage, and not the value equal to the 'Graeme Geldenhuys' string. ---------------------------------------------- var srcstream: TStringStream; s, f: string;

I guess string is an ansistring?

Show quoted text 7 lines
i: integer; begin s := 'Graeme Geldenhuys'; srcstream := TStringStream.Create(''); { I purposely do this, because in my real-world code TStringStream will be populated with many .Write() statements. } i := srcstream.Write(s, Length(s));

if s'' then // this if is not needed in this case
srcstream.Write(s[1], Length(s))

Show quoted text 7 lines
CheckEquals(i, Length(s), 'failed on length of string'); // passes srcstream.Seek(0, soFromBeginning); // not sure if needed f := srcstream.DataString; CheckEquals(s, f, 'Failed on string content 2'); // Fails! srcstream.Free; end; ----------------------------------------------

Mattias

Michael Van Canneyt
to Graeme Geldenhuys: What am I doing wrong in the following code? It always fails on test number 2. The…
Graeme Geldenhuys wrote 18 lines
Hi, What am I doing wrong in the following code? It always fails on test number 2. The DataString property is returning garbage, and not the value equal to the 'Graeme Geldenhuys' string. ---------------------------------------------- var srcstream: TStringStream; s, f: string; i: integer; begin s := 'Graeme Geldenhuys'; srcstream := TStringStream.Create(''); { I purposely do this, because in my real-world code TStringStream will be populated with many .Write() statements. } i := srcstream.Write(s, Length(s));

Ehm.. this should be S[1], now you're writing the pointer.

Michael.

Graeme Geldenhuys
to Mattias Gaertner: On Thu, 2 Feb 2012 00:03:15 +0200 I guess string is an ansistring? if s'' then // this if…

Thanks Mattias for replying so quickly.

Mattias Gaertner wrote 5 lines
> var >   srcstream: TStringStream; >   s, f: string; I guess string is an ansistring?

Yes.

if s'' then // this if is not needed in this case  srcstream.Write(s[1], Length(s))

Argh, rookie mistake! :-/ How did I miss that. Many thanks, my code is working now. :-D

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net
Graeme Geldenhuys
to Michael Van Canneyt: Ehm.. this should be S[1], now you're writing the pointer. Michael.
Michael Van Canneyt wrote
Ehm.. this should be S[1], now you're writing the pointer.

Thank you. That's what happens if you have too many very late nights programming - sleep deprivation catches up and one overlooks the simple mistakes.

Regards,   - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net
Lars
to Graeme Geldenhuys
Graeme Geldenhuys wrote 11 lines
On 2 February 2012 00:14, Michael Van Canneyt wrote: > > Ehm.. this should be S[1], now you're writing the pointer. Thank you. That's what happens if you have too many very late nights programming - sleep deprivation catches up and one overlooks the simple mistakes.

It's actually a common mistake. Also @s vs "s", and @s[1], it can be confusing.

It's one thing I don't like about unsafe languages, pointers, and such stuff. It's as if we are programming in advanced C, or C++. Common, pointer mistakes? this is C? Really? Can't we make it safer? LOL.

What could be done to make this safer? I don't know. What does java do in a situation like this? Could we learn from it?

If somehow the compiler could statically check that only s[1] is allowed, and not S, that would be good.

Jorge Aldo G. de F. Junior
to Lars

I would vote for a new function on all stream types to allow writing strings in the expected way. Everybody hits that problem once.

2012/2/1 Lars :

Show quoted text 28 lines
Graeme Geldenhuys wrote: > On 2 February 2012 00:14, Michael Van Canneyt  wrote: >> >> Ehm.. this should be S[1], now you're writing the pointer. > > > Thank you. That's what happens if you have too many very late nights > programming - sleep deprivation catches up and one overlooks the > simple mistakes. > > > It's actually a common mistake. Also @s vs "s", and @s[1], it can be confusing. It's one thing I don't like about unsafe languages, pointers, and such stuff. It's as if we are programming in advanced C, or C++. Common, pointer mistakes? this is C? Really? Can't we make it safer? LOL. What could be done to make this safer? I don't know. What does java do in a situation like this? Could we learn from it? If somehow the compiler could statically check that only s[1] is allowed, and not S, that would be good. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Giuliano Colla
to Lars: It's actually a common mistake. Also @s vs "s", and @s[1], it can be confusing. It's one…

Lars ha scritto:

Show quoted text 9 lines
It's actually a common mistake. Also @s vs "s", and @s[1], it can be confusing. It's one thing I don't like about unsafe languages, pointers, and such stuff. It's as if we are programming in advanced C, or C++. Common, pointer mistakes? this is C? Really? Can't we make it safer? LOL. What could be done to make this safer? I don't know. What does java do in a situation like this? Could we learn from it?

The only "clean" solution I'm aware of is is the one used in old times by PLM, which completely banned the "implicit pointer" born with C language.

If you just have a local string (or data structure), the name must be "qualified". If /s/ is a string you must either use to indicate the pointer to the string or /s[n]/ to indicate an element of the string. If /b/ is a structure, /b.something/ is valid is valid, but the usage of /s/ or /b/ alone is not allowed.

Whenever you're not dealing with local, static data, then you have the "based" construct, which allows to reserve storage for a pointer, and describes what the pointer points to, providing both strong type checking, and an easy way to dereference when required. Again any ambiguity is impossible.

An example of the PLM syntax is:

Declare p pointer;
Declare s based p (256) Byte;
     and also, if required,
Declare w based p(128) Word;

I've implemented an extension of FPC to support the "based" construct, which I find very useful, to get rid of the c-style p^something, and to make the code more readable and easier to maintain. However I've never submitted my personal patch, because when I proposed it, it didn't rise any interest, and I'm always two steps behind with FPC versions....

Lars
to Jorge Aldo G. de F. Junior: I would vote for a new function on all stream types to allow writing strings in the…
Jorge Aldo G. de F. Junior wrote
I would vote for a new function on all stream types to allow writing strings in the expected way. Everybody hits that problem once.

I think there is a class.WriteString function instead of class.Write()

Similar to a DEPRECATED; directive, there could be an UNSAFE; directive warning the user that he is using untyped pointer or something.

Problem is that adding more things like this to the langage make the compiler more complex.

In oberon there is a way to mark a module UNSAFE if you are linking to C code and such.

Unknown author
to Marco van de Voort
Marco van de Voort wrote 8 lines
In our previous episode, Jorge Aldo G. de F. Junior said: > I would vote for a new function on all stream types to allow writing > strings in the expected way There is no default way to stream a string. On textfiles you only stream contents, on binary files usually a length field (which can be 1,2,4 bytes depending on format) + contents.

The latter exists:

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

We could make an optional parameter "AsText : Boolean = False" which would then write the former.

Downside is that the 'read' operation will not be able to read the text form.

Michael.

Marco van de Voort
to Unknown author

In our previous episode, said:

Show quoted text 11 lines
> On textfiles you only stream contents, on binary files usually a length > field (which can be 1,2,4 bytes depending on format) + contents. The latter exists: http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html We could make an optional parameter "AsText : Boolean = False" which would then write the former. Downside is that the 'read' operation will not be able to read the text form.

If necessary I would simply add a separate version "writetext", and not multiplex it on writeansistring. But as said this is all a slippery slope, specially with unicode profileration ahead. We are going writeunicodestring sooner or later :-)

Unknown author
to Marco van de Voort
Marco van de Voort wrote 17 lines
In our previous episode, said: >> On textfiles you only stream contents, on binary files usually a length >> field (which can be 1,2,4 bytes depending on format) + contents. > > The latter exists: > > http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html > > We could make an optional parameter "AsText : Boolean = False" which would > then write the former. > > Downside is that the 'read' operation will not be able to read the text form. If necessary I would simply add a separate version "writetext", and not multiplex it on writeansistring. But as said this is all a slippery slope, specially with unicode profileration ahead. We are going writeunicodestring sooner or later :-)

Exactly the reason for multiplexing it. It reduces proliferation.

But I'm not exactly convinced that this kind of call is needed.

Michael.

Felipe Monteiro de Carvalho
to Unknown author: The latter exists: http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring…
http://www.freepascal.org/docs-html/rtl/classes/tstream.writeansistring.html We could make an optional parameter "AsText : Boolean = False" which would then write the former.

I think this would be a nice addition. One thing I would suggest is using a more clear wording. "AsText" might be hard to understand what the author ment. Either with the length or without it is still text in a certain way. A more clear wording could be: AWriteTextContentsOnly: Boolean = False or AWriteStringLength: Boolean = True

Felipe Monteiro de Carvalho
Marco van de Voort
to Unknown author: Exactly the reason for multiplexing it. It reduces proliferation. But I'm not exactly…

In our previous episode, said:

Show quoted text 6 lines
> If necessary I would simply add a separate version "writetext", and not > multiplex it on writeansistring. But as said this is all a slippery slope, > specially with unicode profileration ahead. We are going writeunicodestring > sooner or later :-) Exactly the reason for multiplexing it. It reduces proliferation.

Not really. You try to hide it, and only frustrate smartlinking in the process. I would rather introduce a default parameter for the length size (leaving it at 4, for legacy) and endianess.

But I'm not exactly convinced that this kind of call is needed.

I've thought about it several times, but the trouble is that once you start to think of it, the number gets out of hand so fast.

Lars
to Unknown author: Exactly the reason for multiplexing it. It reduces proliferation. But I'm not exactly…

it seems

http://docwiki.embarcadero.com/VCL/XE2/en/Classes.TStringStream.WriteString

in delphi the WriteString() function accepts a strongly typed string.

This might be a compatibility problem in delphi mode since in fpc, writestring accepts a untyped pointer if i am not mistaken.

Different behaviors, right? A strongly typed string parameter wouldn't send in the length of the string AFAIK, it would just send the string contents.

so if someone was porting code from delphi, wouldn't this produce different behavior in fpc?

Lars
to Lars
Lars wrote 8 lines
it seems http://docwiki.embarcadero.com/VCL/XE2/en/Classes.TStringStream.WriteString in delphi the WriteString() function accepts a strongly typed string. This might be a compatibility problem in delphi mode since in fpc, writestring accepts a untyped pointer if i am not mistaken.

Actually I think there is just a problem with the FPDOC system:

http://www.freepascal.org/docs-html/rtl/classes/tstringstream.writestring.html

Says:

public procedure TStringStream.WriteString(
const AString:
);

I thought const AString was untyped due to that doc page, not the fpc sources.

Shouldn't the docs generate a page that says:

const astring: string;

i.e.

public procedure TStringStream.WriteString(
const AString: string
);