TStringStream.DataString returns garbage?

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

TStringStream.DataString returns garbage?

Graeme Geldenhuys-2
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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Mattias Gaertner
On Thu, 2 Feb 2012 00:03:15 +0200
Graeme Geldenhuys <[hidden email]> wrote:

> 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?

>   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))

>   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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Michael Van Canneyt
In reply to this post by Graeme Geldenhuys-2


On Thu, 2 Feb 2012, Graeme Geldenhuys wrote:

> 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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Graeme Geldenhuys-2
In reply to this post by Mattias Gaertner
Thanks Mattias for replying so quickly.


On 2 February 2012 00:10, Mattias Gaertner  wrote:
>> 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Graeme Geldenhuys-2
In reply to this post by Michael Van Canneyt
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.



--
Regards,
  - Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://fpgui.sourceforge.net
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

noreply
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  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Jorge Aldo G. de F. Junior
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 <[hidden email]>:

> 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  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Giuliano Colla
In reply to this post by noreply
Lars ha scritto:
> 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 /@s/ 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 and/@b/ 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....

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

noreply
In reply to this post by Jorge Aldo G. de F. Junior
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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Marco van de Voort
In reply to this post by Jorge Aldo G. de F. Junior
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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

michael.vancanneyt


On Fri, 3 Feb 2012, Marco van de Voort wrote:

> 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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Marco van de Voort
In our previous episode, [hidden email] 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 :-)

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

michael.vancanneyt


On Fri, 3 Feb 2012, Marco van de Voort wrote:

> In our previous episode, [hidden email] 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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Felipe Monteiro de Carvalho
In reply to this post by michael.vancanneyt
On Fri, Feb 3, 2012 at 9:39 AM,  <[hidden email]> wrote:
> 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
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

Marco van de Voort
In reply to this post by michael.vancanneyt
In our previous episode, [hidden email] said:
> > 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.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

noreply
In reply to this post by michael.vancanneyt
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?
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: TStringStream.DataString returns garbage?

noreply
Lars wrote:
> 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
);



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal