我把一个C写的解压文件的一些函数改写成Delphi的函数,编译没问题,但结果没达到理想.我基本是一行行的改写的,但对于C的指针我不是很了解,不明白具体错在哪儿,调试了N次仍不得要领,想请教论坛里高手,帮我看看问题所在.
(我在Delphi 2010下编译)
附:C的代码及我改写的Delphi代码,省略了一些不影响读的部分
#define RNC_FILE_IS_NOT_RNC    -1
#define RNC_HUF_DECODE_ERROR   -2
#define RNC_FILE_SIZE_MISMATCH -3
#define RNC_PACKED_CRC_ERROR   -4
#define RNC_UNPACKED_CRC_ERROR -5
#define RNC_HEADER_VAL_ERROR   -6
#define RNC_HUF_EXCEEDS_RANGE  -7
#define RNC_SIGNATURE 0x524E4301       /* "RNC\001" */typedef struct {
  unsigned long bitbuf;        
  int bitcount;        
} bit_stream;typedef struct {
  int num;        
  struct {
    unsigned long code;
    int codelen;
    int value;
  } table[32];
} huf_table;long rnc_unpack (void *packed, void *unpacked)
{
  unsigned char *input = packed;
  unsigned char *output = unpacked;
  unsigned char *inputend, *outputend;
  bit_stream bs;
  huf_table raw, dist, len;
  unsigned long ch_count;
  unsigned long ret_len, inp_len;  if (blong(input) != RNC_SIGNATURE)
    return RNC_HEADER_VAL_ERROR;
  ret_len = blong (input+4);
  inp_len = blong (input+8);
  input += 18;        
  outputend = output + ret_len;
  inputend = input + inp_len;
  bitread_init (&bs, &input, inputend);
  bit_advance (&bs, 2, &input, inputend); 
  while (output < outputend)
  {
    if (inputend-input<6)
      return RNC_HUF_EXCEEDS_RANGE;
    read_huftable (&raw,  &bs, &input, inputend);
    read_huftable (&dist, &bs, &input, inputend);
    read_huftable (&len,  &bs, &input, inputend);
    ch_count = bit_read (&bs, 0xFFFF, 16, &input, inputend);
    while (1)
    {
      long length, posn;
      length = huf_read (&raw, &bs, &input,inputend);
      if (length < 0)
        return RNC_HUF_DECODE_ERROR;
      if (length)
      {
         while (length--)
         {
           if ((input>=inputend)||(output>=outputend))
             return RNC_HUF_EXCEEDS_RANGE;
           *output++ = *input++;
         }
         bitread_fix (&bs, &input, inputend);
      }
      if (--ch_count <= 0)
        break;
      posn = huf_read (&dist, &bs, &input,inputend);
      if (posn == -1)
        return RNC_HUF_DECODE_ERROR;
      length = huf_read (&len, &bs, &input,inputend);
      if (length < 0)
        return RNC_HUF_DECODE_ERROR;
      posn += 1;
      length += 2;
      while (length--)
      {
        if ((((void *)output-posn)<unpacked)||((output-posn)>outputend)||
           (((void *)output)<unpacked)||((output)>outputend))
               return RNC_HUF_EXCEEDS_RANGE;
        *output = output[-posn];
output++;
      }
    }
  }
  if (outputend != output)
  {
    if (!(flags&RNC_IGNORE_FILE_SIZE_MISMATCH))
      return RNC_FILE_SIZE_MISMATCH;
  }
  return ret_len;
}static void read_huftable (huf_table *h, bit_stream *bs, unsigned char **p, unsigned char *pend)
{
  int i, j, k, num;
  int leaflen[32];
  int leafmax;
  unsigned long codeb;  num = bit_read (bs, 0x1F, 5, p, pend);
  if (!num)
    return;
  leafmax = 1;
  for (i=0; i<num; i++)
  {
    leaflen[i] = bit_read (bs, 0x0F, 4, p, pend);
    if (leafmax < leaflen[i])
      leafmax = leaflen[i];
  }
  codeb = 0L;
  k = 0;
  for (i=1; i<=leafmax; i++)
  {
    for (j=0; j<num; j++)
      if (leaflen[j] == i)
      {
        h->table[k].code = mirror (codeb, i);
        h->table[k].codelen = i;
        h->table[k].value = j;
        codeb++;
        k++;
      }
      codeb <<= 1;
  }
  h->num = k;
}static unsigned long huf_read (huf_table *h, bit_stream *bs, unsigned char **p,unsigned char *pend)
{
  int i;
  unsigned long val;  for (i=0; i<h->num; i++)
  {
    unsigned long mask = (1 << h->table[i].codelen) - 1;
    if (bit_peek(bs, mask) == h->table[i].code)
      break;
  }
  if (i == h->num)
    return -1;
  bit_advance (bs, h->table[i].codelen, p, pend);
  val = h->table[i].value;
  if (val >= 2)
  {
    val = 1 << (val-1);
    val |= bit_read (bs, val-1, h->table[i].value - 1, p, pend);
  }
  return val;
}static void bitread_init (bit_stream *bs, unsigned char **p, unsigned char *pend)
{
  if (pend-(*p) >= 0)
    bs->bitbuf = lword (*p);
  else
    bs->bitbuf = 0;
  bs->bitcount = 16;
}static void bitread_fix (bit_stream *bs, unsigned char **p, unsigned char *pend)
{
  bs->bitcount -= 16;
  bs->bitbuf &= (1<<bs->bitcount)-1;
  if (pend-(*p) >= 0)
    bs->bitbuf |= (lword(*p)<<bs->bitcount);
  bs->bitcount += 16;
}static unsigned long bit_peek (bit_stream *bs, unsigned long mask)
{
  return bs->bitbuf & mask;
}static void bit_advance (bit_stream *bs, int n, unsigned char **p, unsigned char *pend)
{
  bs->bitbuf >>= n;
  bs->bitcount -= n;
  if (bs->bitcount < 16)
  {
    (*p) += 2;
    if (pend-(*p) >= 0)
      bs->bitbuf |= (lword(*p)<<bs->bitcount);
    bs->bitcount += 16;
  }
}static unsigned long bit_read (bit_stream *bs, unsigned long mask,int n, unsigned char **p, unsigned char *pend)
{
  unsigned long result = bit_peek (bs, mask);
  bit_advance (bs, n, p, pend);
  return result;
}static unsigned long mirror (unsigned long x, int n)
{
  unsigned long top = 1 << (n-1), bottom = 1;
  while (top > bottom)
  {
    unsigned long mask = top | bottom;
    unsigned long masked = x & mask;
    if (masked != 0 && masked != mask)
      x ^= mask;
    top >>= 1;
    bottom <<= 1;
  }
  return x;
}static unsigned long blong (unsigned char *p)
{
  unsigned long n;
  n = p[0];
  n = (n << 8) + p[1];
  n = (n << 8) + p[2];
  n = (n << 8) + p[3];
  return n;
}static unsigned long llong (unsigned char *p)
{
  unsigned long n;
  n = p[3];
  n = (n << 8) + p[2];
  n = (n << 8) + p[1];
  n = (n << 8) + p[0];
  return n;
}static unsigned long bword (unsigned char *p)
{
  unsigned long n;
  n = p[0];
  n = (n << 8) + p[1];
  return n;
}static unsigned long lword (unsigned char *p)
{
  unsigned long n;
  n = p[1];
  n = (n << 8) + p[0];
  return n;
}

解决方案 »

  1.   

    //-----------------Delphi-------------------
    const
      RNC_FILE_IS_NOT_RNC    =-1;
      RNC_HUF_DECODE_ERROR   =-2;
      RNC_FILE_SIZE_MISMATCH =-3;
      RNC_PACKED_CRC_ERROR   =-4;
      RNC_UNPACKED_CRC_ERROR =-5;
      RNC_HEADER_VAL_ERROR   =-6;
      RNC_HUF_EXCEEDS_RANGE  =-7;
      RNC_SIGNATURE  =$524E4301;    
    type
      PByte=^Byte;
      bit_stream=record
        bitbuf:longword; 
        bitcount:integer;
      end;
      huf_table=record
        num:integer;     
        table:array [0..31] of
          record
            code:longword;
            codelen:integer;
            value:integer;
          end;
      end;implementationfunction rnc_unpack (var _packed, unpacked:TMemoryStream):longint;
    var
      inPos,outPos,inEnd,outEnd,tp:PByte;
      bs:bit_stream;
      raw, dist, len:huf_table;
      ch_count:longword;
      ret_len, inp_len:longword;
      length, posn:longint;
    begin
      inPos:=PByte(_packed.Memory);
      if (blong(inPos) <> RNC_SIGNATURE) then
      begin
        Result:=RNC_HEADER_VAL_ERROR;
        exit;
      end;
      inc(inPos,4);
      ret_len := blong(inPos);
      inc(inPos,4);
      inp_len := blong(inPos);
      inc(inPos,10);
      unpacked.SetSize(ret_len);
      outPos:=PByte(unpacked.Memory);
      outEnd := outPos;
      inc(outEnd, ret_len);
      inEnd := inPos;
      inc(inEnd, inp_len);
      bitread_init (bs, inPos, inEnd);
      bit_advance (bs, 2, inPos, inEnd);
      while (longword(@outPos) < longword(@outEnd)) do
      begin
        if longword(@InEnd)-longword(@inPos)<6 then
        begin
          Result:=RNC_HUF_EXCEEDS_RANGE;
          exit;
        end;
        read_huftable (raw,  bs, inPos, inEnd);
        read_huftable (dist, bs, inPos, inEnd);
        read_huftable (len,  bs, inPos, inEnd);
        ch_count := bit_read (bs, $FFFF, 16, inPos, inEnd);
        while (True) do
        begin
          length := huf_read (raw, bs, inPos, inEnd);
          if (length < 0) then
          begin
            Result:=RNC_HUF_DECODE_ERROR;
            exit;
          end;
          if (length>0) then
          begin
            while (length>0) do
            begin
              outPos^:=inPos^;
              inc(outPos);
              inc(inPos);          dec(length);
            end;
            bitread_fix (bs, inPos, inEnd);
          end;
          dec(ch_count);
          if (ch_count <= 0) then
            break;
          posn := huf_read (dist, bs, inPos, inEnd);
          if (posn = -1) then
          begin
            Result:=RNC_HUF_DECODE_ERROR;
            exit;
          end;
          length := huf_read (len, bs, inPos, inEnd);
          if (length < 0) then
          begin
            Result:=RNC_HUF_DECODE_ERROR;
            exit;
          end;
          inc(posn);
          inc(length,2);
          while (length>0) do
          begin
            if (((longword(@output)-posn)<longword(@unpacked.Memory))
               or ((longword(@output)-posn)>longword(@outEnd))
               or (longword(@output)<longword(@unpacked.Memory))
               or (longword(@output)>longword(@outEnd))) then
            begin
              Result:=RNC_HUF_EXCEEDS_RANGE;
              exit;
            end;
            tp:=outPos;
            dec(tp,posn);
            outPos^:=tp^;        inc(outPos);
            dec(length);
          end;
        end; 
      end;
      if (longword(@outPos) <> longword(@outEnd)) then
      begin
        Result:=RNC_FILE_SIZE_MISMATCH;
        exit;
      end;
      Result:=ret_len;
    end;procedure read_huftable (var h:huf_table;var bs:bit_stream;var p,pend:PByte);
    var
      i, j, k, num:integer;
      leaflen:array [0..31] of integer;
      leafmax:integer;
      codeb:longword; 
    begin
      num := bit_read (bs, $1F, 5, p, pend);
      if (num=0) then
        exit;
      leafmax := 1;
      for i:=0 to num-1 do
      begin
        leaflen[i] := bit_read (bs, $0F, 4, p, pend);
        if (leafmax < leaflen[i]) then
          leafmax := leaflen[i];
      end;
      codeb := 0;
      k := 0;
      for i:=1 to leafmax do
      begin
        for j:=0 to num-1 do
          if (leaflen[j] = i) then
          begin
            h.table[k].code := mirror (codeb, i);
            h.table[k].codelen := i;
            h.table[k].value := j;
            inc(codeb);
            inc(k);
          end;
        codeb := codeb shl 1;
      end;
      h.num := k;
    end;function huf_read (var h:huf_table;var bs:bit_stream;var p,pend:PByte):longint;
    var
      i:integer;
      val,mask:longword;
    begin
      for i:=0 to h.num-1 do
      begin
        mask := (1 shl h.table[i].codelen) - 1;
        if (bit_peek(bs, mask) = h.table[i].code) then
          break;
      end;
      if (i = h.num) then
      begin
        Result:=-1;
        exit;
      end;
      bit_advance (bs, h.table[i].codelen, p, pend);
      val := h.table[i].value;
      if (val >= 2) then
      begin
        val := 1 shl (val-1);
        val :=val or (bit_read (bs, val-1, h.table[i].value - 1, p, pend));
      end;
      Result:=val;
    end;procedure bitread_init (var bs:bit_stream;var p,pend:PByte);
    begin
      if (longword(@pend)-longword(@p))>=0 then
        bs.bitbuf := lword(p)
      else
        bs.bitbuf:=0;
      bs.bitcount := 16;
    end;procedure bitread_fix (var bs:bit_stream;var p,pend:PByte);
    begin
      bs.bitcount := bs.bitcount - 16;
      bs.bitbuf := bs.bitbuf and ((1 shl bs.bitcount)-1);
      if (longword(@pend)-longword(@p))>=0 then
        bs.bitbuf := bs.bitbuf or (lword( p ) shl bs.bitcount);
      bs.bitcount := bs.bitcount + 16;
    end;function bit_peek (var bs:bit_stream; mask:longword):longword;
    begin
      Result:=bs.bitbuf and mask;
    end;procedure bit_advance (var bs:bit_stream; n:integer;var p,pend:PByte);
    begin
      bs.bitbuf:=bs.bitbuf shr n;
      bs.bitcount:=bs.bitcount - n;
      if (bs.bitcount < 16) then
      begin
        inc(p,2);
        if (longword(@pend)-longword(@p))>=0 then
          bs.bitbuf := bs.bitbuf or (lword( p ) shl bs.bitcount);
        bs.bitcount := bs.bitcount + 16;
      end;
    end;function bit_read (var bs:bit_stream; mask:longword; n:integer;var p,pend:PByte):longword;
    begin
      Result := bit_peek (bs, mask);
      bit_advance (bs, n, p, pend);
    end;function mirror(x:longword; n:integer):longword;
    var
      top,bottom,mask,masked:longword;
    begin
      top := 1 shl (n-1);
      bottom := 1;
      while (top > bottom) do
      begin
        mask := top or bottom;
        masked := x and mask;
        if ((masked <> 0) and (masked <> mask)) then
          x :=x xor mask;
        top :=top shr 1;
        bottom :=bottom shl 1;
      end;
      Result:=x;
    end;function bword(pb:PByte):word;
    var
      b1,b2:byte;
    begin
      b1:=pb^;
      inc(pb);
      b2:=pb^;
      result:=(word(b1) shl 8) or word(b2);
    end;function lword(pb:PByte):word;
    var
      b1,b2:byte;
    begin
      b2:=pb^;
      inc(pb);
      b1:=pb^;
      result:=(word(b1) shl 8) or word(b2);
    end;function blong(pb:PByte):longword;
    var
      b:array [0..3] of byte;
      i:integer;
    begin
      for i := 0 to 3 do
      begin
        b[i]:=pb^;
        inc(pb);
      end;
      Result:=(longword(b[0]) shl 24) or (longword(b[1]) shl 16)
              or (longword(b[2]) shl 8) or longword(b[3]);
    end;function llong(pb:PByte):longword;
    var
      b:array [0..3] of byte;
      i:integer;
    begin
      for i := 3 downto 0 do
      begin
        b[i]:=pb^;
        inc(pb);
      end;
      Result:=(longword(b[0]) shl 24) or (longword(b[1]) shl 16)
              or (longword(b[2]) shl 8) or longword(b[3]);
    end;end.
      

  2.   

    delphi的record为了加快访问速度,会“补齐”参见下面的测试代码,但愿对你有所帮助unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;type test1= record
            a: byte;
            b: byte;
            c: integer;
    end;type test2= packed record
            a: byte;
            b: byte;
            c: integer;
    end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
            t1: test1;
            t2: test2;
    begin
            showmessage(IntToStr(sizeof(t1)));
            showmessage(IntToStr(sizeof(t2)));
    end;end.