Levent Tulun
Levent Tulun

Reputation: 711

TIdTCPClient Read Bytes

Seg Parameters:

  liBinID       : LongInt;
  liAux         : LongInt;
  classID       : TJPIPDatabinClass;
  liCodestreamID: LongInt;
  iOffset       : Integer;
  iLength       : Integer;
  arrData       : TBytes;
  isFinal       : Boolean;
  isEOR         : Boolean;
  isComplete    : Boolean;

error function:

function TJPIPDataInputStream.readSegment: TJPIPDataSegment;
var
  m   : Integer;
  id  : LongInt;
  seg : TJPIPDataSegment;
  B   : Byte;
begin
  id:= readVBAS;
  if id < 0 then
  begin
    Result:= nil;
    Exit;
  end;
  seg:= TJPIPDataSegment.Create;
  seg.liBinID:= id;

  if vbasFstByte = 0 then
  begin
    seg.isEOR:= true;
    seg.liBinID:= formMain.client.IOHandler.ReadByte;
    if seg.liBinID < 0 then
      ShowMessage('EOF reached before completing EOR message');
    seg.iLength:= Integer(readVBAS);
  end
  else
  begin
    seg.isEOR:= false;
    seg.liBinID:= seg.liBinID and (not LongInt($70 shl ((vbasLength - 1) * 7)));
    seg.isFinal:= ((vbasFstByte and $10) <> 0);
    m:= (vbasFstByte and $7F) shr 5;
    if m = 0 then
      ShowMessage('Invalid Bin-ID value format')
    else if m >= 2 then
    begin
      classId:= readVBAS;
      if m > 2 then
        codestream:= readVBAS;
    end;
    seg.liCodestreamID:= codestream;


    if classId = jpipdatabinclass.FPRECINCT_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FPRECINCT_DATABIN
    else if classId = jpipdatabinclass.FTILE_HEADER_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FTILE_HEADER_DATABIN
    else if classId = jpipdatabinclass.FTILE_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FTILE_DATABIN
    else if classId = jpipdatabinclass.FMAIN_HEADER_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FMAIN_HEADER_DATABIN
    else if classId = jpipdatabinclass.FMETA_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FMETA_DATABIN;


    if seg.classID = nil then
      ShowMessage('Invalid databin classID');

    seg.iOffset:= Integer(readVBAS);
    seg.iLength:= Integer(readVBAS);

    if (classId = EXTENDED_PRECINCT_DATA_BIN_CLASS) or (classId = EXTENDED_TILE_DATA_BIN_CLASS) then
      seg.liAux:= readVBAS;
  end;

  if seg.iLength > 0 then
  begin
    if seg.arrData = nil then
      SetLength(seg.arrData, seg.iLength);

    if Length(seg.arrData) < seg.iLength then
      SetLength(seg.arrData, seg.iLength);

    formMain.client.IOHandler.ReadBytes(TIdBytes(seg.arrData), Length(seg.arrData));
//    if inStream.read(seg.data, 0, seg.alength) <> seg.alength then
//      ShowMessage('EOF reached before read' + IntToStr(seg.alength) + ' bytes');
  end;
  Result:= seg;
end;

arrData is TBytes;

iLength is Integer;

And iLength = 12;

Also arrData length is 12 too.

I debugged it and output length is 24. First 12 elements are 0 and the other 12 elements are true values. But i couldn' t understand, i set the length of arrData to 12 but after read, it returns length 24 of arrData.

Edit it always give x2 length of what i give.

Upvotes: 0

Views: 2045

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596226

TIdIOHandler.ReadBytes() has an optional AAppend parameter that is True by default:

procedure ReadBytes(var VBuffer: TIdBytes; AByteCount: Integer; AAppend: Boolean = True);

That means any bytes read will be appended to the end of the existing array. Since you are pre-allocating the array, that is why it ends up being twice the size.

You need to either:

  1. remove the pre-allocation and let ReadBytes() allocate the array for you:

    seg.arrData := nil;
    if seg.iLength > 0 then
    begin
      formMain.client.IOHandler.ReadBytes(TIdBytes(seg.arrData), seg.iLength);
    end;
    
  2. keep the pre-allocation and set AAppend to False so ReadBytes() will fill the existing memory instead of appending to it:

    seg.arrData := nil;
    if seg.iLength > 0 then
    begin
      SetLength(seg.arrData, seg.iLength);
      formMain.client.IOHandler.ReadBytes(TIdBytes(seg.arrData), seg.iLength, False);
    end;
    

Upvotes: 2

Related Questions