[ Boris B. @ 30.03.2009. 17:15 ] @
Zna li neko za brz i pouzdan nacin kako konvertovati PChar u Delphi (Long)String ako znam duzinu PChara?

Obicna ugradjena konverzija (String := PChar) ne radi ako PChar sadrzu NULL karaktere, tj dobijeni string je dug samo do prvog NULL-a. Meni u stvari treba nacin da u runtime-u konstruisem validni Delphi LongString iz niza bajtova koji se citaju iz streama, a hteo bi da izbegnem "izgradnju" stringa preko Str := Str + xxx zbog kazne u performansama usled konstante realokacije memorije.
[ savkic @ 30.03.2009. 17:57 ] @
> Obicna ugradjena konverzija (String := PChar) ne radi ako PChar sadrzu NULL karaktere, tj dobijeni string je dug samo do prvog NULL-a.

Pokušaj sa SetString, ako ne uspe onda SetLength pa kopiranje memorije sa Move.

> Meni u stvari treba nacin da u runtime-u konstruisem validni Delphi LongString iz niza bajtova koji se citaju iz streama, a hteo bi da izbegnem "izgradnju"
> stringa preko Str := Str + xxx zbog kazne u performansama usled konstante realokacije memorije.

Znaš li unapred dužinu strema? Ako da, onda alociraj na početku potreban string i ručno kopiraj delove na odgovarajuće pozicije.
[ Boris B. @ 30.03.2009. 23:48 ] @
>Pokušaj sa SetString
Hvala, izgleda da mi bas to treba.
A Ako ne bude radilo onda SetLength+Move ce sigurno, nisam znao da sa SetLength mozes da alociras stringove u runtime-u.
[ Rapaic Rajko @ 31.03.2009. 09:13 ] @
Zar nije brze (bolje) sa nizom karaktera?
Evo primera:

Code:

type
  TCharArray = array[1..128] of char;
  PCharArray = ^TCharArray;

...

procedure Test;
var
  sourS, destS: string;
  Arr: TCharArray;
  PArr: PCharArray;
begin
  FillChar(Arr, 128, 'A');  // prvo napucamo niz
  sourS := Arr; // dodela niz -> string  
  ShowMessage(sourS);

  PArr := @Arr[1];  // napucamo pointer niza na niz
  destS := PArr^;  // opet dodela niz(pointer) -> string 
  ShowMessage(destS);
end;


Rajko
[ Boris B. @ 31.03.2009. 19:53 ] @
@Rajko
>Zar nije brze (bolje) sa nizom karaktera?

Mislim da nije, jer su bar tri problema kod tog pristupa:
1. Moras da znas u designtime-u velicinu statickog vektora TCharArray, tako da njegova jedina primena bi bila da se koristi kao privremeni bafer fiksne velicine (npr 32k). Ne moze da bude rezultat funkcije koja npr. cita stream jer ima diskretnu duzinu.
2. Ne moze izbeci ni "izgradnja" stringa i ako bi ga koristio kao bafer, jer bi cepkao podatke na delove od 32k i onda opet ih sastavljao u izlazni string, sto sa sobom povlaci konstantno realociranje memorije, sto je i bio cilj izbeci.
3. Ne radi sa NULL karakterima, sto je osnovni cilj problema. Konverzija DestS := PArr^ ce iskopirati karaktere samo do prvog NULL-a jer Delphi vidi taj PCharArray kao PChar. Cak stavise, uposte nije potrebno imati taj PCharArray jer se zbog nasviranog kompajlera moze jednostavno napisati DestS := Arr bez indirektnog pristupa (mada to radi samo za staticke vektore, ne i za dinamicke tj. array of char).

Medjutim, ako se napise ovako:
Code:

var
  S: String;
  B: TBytes;   //Virtuelni stream
  Len: Integer;
begin
  Len := 128;
  SetLength(B, Len);
  FillChar(B[0], Len, 'A');

  SetLength(S, Len);
  Move(B[0], S[1], Len);

  S[3] := #0;
  ShowMessage(S);

  SetLength(S, 0);
  SetLength(B, 0);
end;

Ovim se dobije:
1. Varijabilna velicina izlaznog stringa, odnosno Len moze da bude parametar funkcije.
2. NULL-ovi u stringu su sacuvani. To se u ShowMessage-u ne vidi jer se string S prosledi windows API wrapperu koji ga castuje u PChar, cist Delphi kod bi video i posle NULL karaktera.

[Ovu poruku je menjao Boris B. dana 31.03.2009. u 21:06 GMT+1]
[ Rapaic Rajko @ 01.04.2009. 09:27 ] @
Au, vidis nisam ni probao gornji primer sa null karakterom; izvinjavam se.

Pa onda preostaje SetString(), probao sam i radi savrseno i sa null chars; jedino, kao sto si primetio, ostali karakteri posle null se ne vide u ShowMessage; ali po duzini (width) dijaloga se vidi da je to TO. Smatram da je uvek bolje umesto dve naredbe imati jednu ;) .
Pozdrav

Rajko