Sign in Join

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

Mailing lists / fpc-pascal / 2000-09

Strings vs. Ansistrings

9 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Unknown author

For go32 and Win32 targets... are strings read/written differently when compiling with {$H-} and {$H+}? I have a file viewer that uses an array of ^string. When compiled with {$H-}, shortstrings, the strings are read from the file and displayed on the screen perfectly. But, when I compile with ($H+}, ansistrings, the strings are displayed as garbage characters (without making any other changes to the code). According to the byte count I calculate while reading the file both short and ansistrings are reading the exact same amount of data, but the displayed characters are all garbled only when using ansistrings.

I can't find anything in the docs that seem to point to this problem. Any help would be appreciated. Thanks.

Jim

Carlo Kok
to Unknown author
I don't know if it is the same as in delphi, but in delphi, you can not save
Ansistrings directly to a file, because ansistring is a pointer. that's why
you receive garbage. You can save an ansi string like this:
var
  l: Longint
begin
  L := Length(MyAnsiString);
  BlockWrite(f, l, sizeof(L));
  BlockWrite(f, MyAnsiString[1], L);
end;
  and read it like this:
var
  l: Longint;
begin
  BlockRead(f, L, sizeof(L));
  SetLEngth(MyAnsiString, l);
  BlockRead(f, MyAnsiString[1], L);
end;l

Greetings
Carlo Kok (born: 16-08-1984)
ICQ: 73059433
Volendam; The Netherlands

Earlier message 29 lines
----- Original Message ----- From: To: Sent: Monday, September 18, 2000 9:18 PM Subject: [fpc-pascal]Strings vs. Ansistrings > For go32 and Win32 targets... are strings read/written differently when > compiling with {$H-} and {$H+}? I have a file viewer that uses an array of > ^string. When compiled with {$H-}, shortstrings, the strings are read from > the file and displayed on the screen perfectly. But, when I compile with > ($H+}, ansistrings, the strings are displayed as garbage characters > (without making any other changes to the code). According to the byte count > I calculate while reading the file both short and ansistrings are reading > the exact same amount of data, but the displayed characters are all garbled > only when using ansistrings. > > I can't find anything in the docs that seem to point to this problem. Any > help would be appreciated. Thanks. > > Jim > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal >
Carlo Kok
to Unknown author: For go32 and Win32 targets... are strings read/written differently when compiling with…

Also the link of a ShortString is 255 (that's the same as string in $H- mode). De sizeof an ansistring is unlimited (Sizeof(Memory) - Sizeof(Os)) Greetings
Carlo Kok (born: 16-08-1984)
ICQ: 73059433
Volendam; The Netherlands

Earlier message 29 lines
----- Original Message ----- From: To: Sent: Monday, September 18, 2000 9:18 PM Subject: [fpc-pascal]Strings vs. Ansistrings > For go32 and Win32 targets... are strings read/written differently when > compiling with {$H-} and {$H+}? I have a file viewer that uses an array of > ^string. When compiled with {$H-}, shortstrings, the strings are read from > the file and displayed on the screen perfectly. But, when I compile with > ($H+}, ansistrings, the strings are displayed as garbage characters > (without making any other changes to the code). According to the byte count > I calculate while reading the file both short and ansistrings are reading > the exact same amount of data, but the displayed characters are all garbled > only when using ansistrings. > > I can't find anything in the docs that seem to point to this problem. Any > help would be appreciated. Thanks. > > Jim > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal >
Michael Van Canneyt
to Carlo Kok: I don't know if it is the same as in delphi, but in delphi, you can not save Ansistrings…
Carlo Kok wrote
I don't know if it is the same as in delphi, but in delphi, you can not save Ansistrings directly to a file, because ansistring is a pointer.

This is also true for Free Pascal.

Michael.

Show quoted text 60 lines
that's why you receive garbage. You can save an ansi string like this: var l: Longint begin L := Length(MyAnsiString); BlockWrite(f, l, sizeof(L)); BlockWrite(f, MyAnsiString[1], L); end; and read it like this: var l: Longint; begin BlockRead(f, L, sizeof(L)); SetLEngth(MyAnsiString, l); BlockRead(f, MyAnsiString[1], L); end;l Greetings Carlo Kok (born: 16-08-1984) ICQ: 73059433 Volendam; The Netherlands ----- Original Message ----- From: To: Sent: Monday, September 18, 2000 9:18 PM Subject: [fpc-pascal]Strings vs. Ansistrings > For go32 and Win32 targets... are strings read/written differently when > compiling with {$H-} and {$H+}? I have a file viewer that uses an array of > ^string. When compiled with {$H-}, shortstrings, the strings are read from > the file and displayed on the screen perfectly. But, when I compile with > ($H+}, ansistrings, the strings are displayed as garbage characters > (without making any other changes to the code). According to the byte count > I calculate while reading the file both short and ansistrings are reading > the exact same amount of data, but the displayed characters are all garbled > only when using ansistrings. > > I can't find anything in the docs that seem to point to this problem. Any > help would be appreciated. Thanks. > > Jim > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Unknown author
Also the link of a ShortString is 255 (that's the same as string in $H- mode). De sizeof an ansistring is unlimited (Sizeof(Memory) - Sizeof(Os))

I don't suspect that it's a size issue; I'm loading a file that's 1.3 meg, but I have 320 meg of RAM in this computer. Also, you're previous reply eluded to a problem writing a file using ^string if they're ansistrings, but that's not the problem either in this case (but how does one write ^ansistrings to a file anyway?). Where I seem to be running into difficulties is when trying to writeln to the screen. Then, I get nothing but garbage. If I compile with {$H-} everything works fine, but {$H+} causes garbage to be written to the screen for both go32 and win32 targets. Weird...

Another thing I found; clreol doesn't seem to work too well with win32 (console mode) targets. Again, I can compile the identical source code and clreol works fine on go32 executables, but often leaves behind characters when with win32 executables. FWIW, I use the window () function to set window sizes, and it's within these windows that clreol seems to have the most problems.

Regards,
Jim Wilson

Carlo Kok
to Unknown author

There are different ways of storing an ansistring, like first save the size, them the data (See previous mail) or save it as a Pchar. May I ask what kind of program needs to read an array of strings from a file? If you want to read a text-file you should use TStringList (FCL?) or something else, but you can not load it directly.

Greetings
Carlo Kok (born: 16-08-1984)
ICQ: 73059433
Volendam; The Netherlands

Earlier message 38 lines
----- Original Message ----- From: To: Sent: Tuesday, September 19, 2000 5:09 PM Subject: Re: [fpc-pascal]Strings vs. Ansistrings > > > Also the link of a ShortString is 255 (that's the same as string in $H- > > mode). De sizeof an ansistring is unlimited (Sizeof(Memory) - Sizeof(Os)) > > I don't suspect that it's a size issue; I'm loading a file that's 1.3 meg, > but I have 320 meg of RAM in this computer. Also, you're previous reply > eluded to a problem writing a file using ^string if they're ansistrings, > but that's not the problem either in this case (but how does one write > ^ansistrings to a file anyway?). Where I seem to be running into > difficulties is when trying to writeln to the screen. Then, I get nothing > but garbage. If I compile with {$H-} everything works fine, but {$H+} > causes garbage to be written to the screen for both go32 and win32 targets. > Weird... > > Another thing I found; clreol doesn't seem to work too well with win32 > (console mode) targets. Again, I can compile the identical source code and > clreol works fine on go32 executables, but often leaves behind characters > when with win32 executables. FWIW, I use the window () function to set > window sizes, and it's within these windows that clreol seems to have the > most problems. > > Regards, > Jim Wilson > > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal >
Unknown author
There are different ways of storing an ansistring, like first save the

size,

them the data (See previous mail) or save it as a Pchar. May I ask what

kind

of program needs to read an array of strings from a file? If you want to read a text-file you should use TStringList (FCL?) or something else, but you can not load it directly.

I don't use TStringList because it's unique to FPC. I try to make all my source code 'portable' to other compilers (primarily TMT, but maybe I'll start playing around with the new VP as well). This way, if I have a problem I can verify it on another platform, but if I use something proprietary to one or the other it becomes a nightmare to trace. Now, it's impossible to not have some differences so I do use a few $ifdefs, but that's about it.

The program I'm (re)writting is a console mode text file viewer. I've written a number of file viewers in my life time; some proprietary and for a specific need, some generic for virtually any type of file. One of the challenges I decided to undertake was to completely rewrite, from the ground up, a program that looked and acted like one of my generic file viewers, but with expanded capabilities (multi-megabyte files, unlimited line lengths, long file names, etc). I have always used ^string for the data structure and just naturally assumed that this would be the best method to do it again. Is there a better way to do it?

BTW; do you know of another way to send text to the screen (for go32 targets) then write and writeln? One of the functions of the file viewer is to be able to read/display binary files. When you try to use write to display data from a binary file (which was read from the file using blockread) everything after a cr/lf pair is ignored. Would assigncrt help at all?

TIA...

Jim

Unknown author
to Unknown author

From:
Subject: Re: [fpc-pascal]Strings vs. Ansistrings To:
Date sent: Wed, 20 Sep 2000 10:29:20 -0400
Send reply to:

Show quoted text 6 lines
BTW; do you know of another way to send text to the screen (for go32 targets) then write and writeln? One of the functions of the file viewer is to be able to read/display binary files. When you try to use write to display data from a binary file (which was read from the file using blockread) everything after a cr/lf pair is ignored. Would assigncrt help at all?

No, it wouldn't. What you have to do depends on your idea how results should look like. If you want to write contents of the buffer directly to the screen, you have to parse it as individual lines (ending with CR/LF) and output these instead. If you want something like a hex dump (i.e. one column with hexadecimal values and another with their character representations, you have to filter special values (like #13 and #10) out and replace them with your chosen representation of non-printable characters. The same should be done _at_least_ for #7 (bell) and #8 (backspace) as well, otherwise you might quickly get a terrible beeping monster that hides (eats) many regularly printable characters after viewing a "well-chosen" binary file. Should you want to display semi-graphics characters assigned to those special characters as well, then your only possibility is direct memory access (or video memory buffers on non-DOS platforms). For DOS (GO32v2) it means e.g. using the TP-compatible mem[] array. However, this cannot be done in a portable manner, every platform has its special tools for doing such special things.

Have a nice day

Tomas Hajny, on Internet
in urgent cases

Jonas Maebe
Show quoted text 7 lines
I *have* read the reference guide section on ansistrings, many times actually (I've never used them before, so I wanted to familiarize myself before writing any code). That's where I got the impression that short strings and ansistrings could be used in a similar fashion. To paraphrase the guide: "Whatever the actual type, ansistrings and short strings can be use interchangeably". This statement made me think that there weren't any glaring differences, and that I could use one just like the other.

This is only when using standard functions (like pos, length, copy, delete, the "+" sign for concatenating etc.). If you start working around the standard constructs (ie. by using 'move' instead of using a normal assignment), this is not true anymore.

The reason is that an ansistring is a pointer to a record which contains the current length, the amount of references to this record, the current maximum length and an array of char (which has a size equal to the current maximum length) which contains the actual string.

The ansistring pointer points to this array of char, and in the 12 preceding bytes the length, maxlength and refcount are stored as longints (since they aren't meant to be accessed directly).

Suppose you have something like

var
  s1, s2: ansistring;
begin
  readln(s1);
  s2 := s1
end.

After the readln is executed, s1 has a refcount of 1 (the only ansistring that points to the string is s1), maxlength of minimum 255 (default), length is the actual length of the string and the array of char contains the string you typed in with an extra terminating #0 char (because, since the ansistring points to the array of char, you can perfectly typecast an ansistring to a pchar this way).

Now, when you assign s1 to s2, the following happens:

a) it is checked whether s2 already points to a string. In this case, that obviously isn't so, but otherwise the reference count of the string s2 points to would be decreased (since after the assignment, s2 wouldn't point anymore to that string) and if the reference count of that string was zero afterwards, the memory it occupied would be freed b) it is checked whether s1 already points to a string (an empty ansistring = nil). That's the case here, so the reference count of the string s1 points to is increased by one, since after the assignment, there are now two ansistrings pointing to that string c) the pointer in s1 is copied to s2

Now, if you'd do something like

var
  s1, s2: ansistring;
begin
  readln(s1);
  move(s1,s2,sizeof(s1));
end.

then the compiler doesn't see anymore you are assigning one ansistring to another (the compiler doesn't know what the move procedure exactly does, it just sees it as a procedure with three parameters of which the first two are untyped and the last one is a longint). This means the decreasing/increasing of the reference counting doesn't happen, and as such you afterwards have two ansistrings (s1 and s2) pointing to the same string (the one read using readln), while the refcount is only 1.

This means that if you afterwards assign a new value to s1 or s2 (e.g. by using readln again), the reference count is decreased and becomes 0! The program then thinks that no other ansistrings are pointing anymore to this string and realeases/reuses the memory for a new string.

In your program, you're doing something like

move(s1,array_var[index]^,length(s1));

Since s1 is a pointer, you are moving way too much data this way as well (in addition to not have the program update the reference count).

Show quoted text 6 lines
> Ansistrings provide some very nice features (like the reference > couting, automatic (de)allocation of memory etc, but for them > to work you have to play by the rules. I'd love to 'play by the rules', if that's what makes ansistrings work as advertised. Where can I find these rules?

They are not explicitely in the manual, but in general you could say: don't confuse the compiler by removing the type of a variable (e.g. the move() procedure takes two untyped var parameters, so inside the move() procedure the compiler doesn't know anymore it's working with ansistrings) before modifying or copying their contents, unless you know how things internally work.

> There's probably a bug in the windows crt unit. I don't have > windows though, so I can't check it. Anything I can do to help track it down?

I don't know. Here's the current clreol routine from the windows crt unit, but I don't see anythign wrong in it at first sight:

***
procedure ClrEol;
{
  Clear from current position to end of line.
}
var Temp: Dword;
    CharInfo: Char;
    Coord: TCoord;
    X,Y: Longint;
begin
  GetScreenCursor(x,y);
  CharInfo := #32;
  Coord.X := X - 1;
  Coord.Y := Y - 1;
  FillConsoleOutputCharacter(OutHandle, CharInfo, WinMaxX - (X + 01),
Coord, @Temp);
end;
***

Jonas