tags:

views:

110

answers:

4

HI, I using a compression delphi library that receives a pAnsiChar as parameter. But i want to store a word array in the compressed file. The prototype function is:

MyArray: TWordDynArray;
function lzopas_compress(in_p: PAnsiChar; in_len: integer; out_p: PAnsiChar): integer;

And i want to pass MyArray to the function. How do I do that?

Thanks

+2  A: 

The obvious way to accomplish this would be with a pointer cast. The input "string" would be PAnsiChar(@MyArray[0]), and pass Length(MyArray) * sizeof(word) as the length parameter. But this is one of those times when the obvious solution is wrong. It may work, but since TWordDynArray is defined as an array of word and not a packed array of word, element packing issues could throw off the length calculation, and it could vary between Delphi versions. Also, this will raise a bounds check error if Length(MyArray) = 0.

A safer way would be to create an AnsiString, set its length to Length(MyArray) * sizeof(word), and then use a loop like this:

for i := 0 to high(MyArray) do
  Move(MyArray[i], MyString[(i * sizeof(word)) + 1], sizeof(word));

And then pass your string, cast to a PAnsiChar, and the Length() of your string.

Mason Wheeler
A lot will break if arrays are not packed anymore. Given the avg codebases it is no use preparing for this case.
Marco van de Voort
A: 

Try to use TCompressionStream/TDecompressionStream.

dwrbudr
A: 

My advice is to change library. You can easily find Delphi libraries that will allow you to compress generic TStream or buffers. Using PChars to pass buffers as parameters in Delphi only indicates a bad design and little knowledge of Delphi (unless that function has a good reason to work on AnsiStrings). AFAIK LZO is a block compression algorithm, really no need to work on PChar type, it looks it could be a blind port from a C/C++ library where given there is no "byte" type many library could use array of chars. That's not the way it should be done in Delphi.

ldsandon
Till D2009 there was no way to overindex any type but pchar.
Marco van de Voort
A: 

Simply use

if length(myarr)>0 then
  begin
     outlen:=lzopas_compress(pansichar(@myarr[0]),length(myarr)*sizeof(word),out_p); 
  end
else
  outlen:=0;

However you must lookup the algorithms, and find an expression for how big the output buffer must be. (since often data can become larger due to compression for e.g. small input buffers).

Marco van de Voort