bufferToHex method

String bufferToHex({
  1. bool writeStartAddr = true,
  2. EOLStyle eolstyle = EOLStyle.native,
  3. int byteCount = 16,
})

Write data to file f in HEX format.

f filename or file-like object for writing writeStartAddr enable or disable writing start address record to file (enabled by default). If there is no start address in obj, nothing will be written regardless of this setting. eolstyle can be used to force CRLF line-endings for output file on different platforms. Supported eol styles: 'native', 'CRLF'. byteCount number of bytes in the data field

Implementation

String bufferToHex({bool writeStartAddr = true, EOLStyle eolstyle = EOLStyle.native, int byteCount = 16}){
  if (byteCount > 255 || byteCount < 1){
    throw("wrong byteCount value: $byteCount");
  }

  String eol = IntelHex._getEolTextfile(eolstyle);
  String fwrite = '';
  // # Translation table for uppercasing hex ascii string.
  // # timeit shows that using hexstr.translate(table)
  // # is faster than hexstr.upper():
  // # 0.452ms vs. 0.652ms (translate vs. upper)
  // if sys.version_info[0] >= 3
  //     # Python 3
  //     table = bytes(range_l(256)).upper()
  // else:
  //     # Python 2
  //     table = ''.join(chr(i).upper() for i in range_g(256))



  // # start address record if any
  if (startAddress != null && writeStartAddr){
    List<String> keys = startAddress!.keys.toList();
    keys.sort();
    Uint8List bin = Uint8List(9);//array('B', asbytes('\0'*9));
    if(keys == ['CS','IP']){
      // Start Segment Address Record
      bin[0] = 4;      //# reclen
      bin[1] = 0;      //# offset msb
      bin[2] = 0;      //# offset lsb
      bin[3] = 3;      //# rectyp
      int cs = startAddress!['CS']!;
      bin[4] = (cs >> 8) & 0x0FF;
      bin[5] = cs & 0x0FF;
      int ip = startAddress!['IP']!;
      bin[6] = (ip >> 8) & 0x0FF;
      bin[7] = ip & 0x0FF;
      bin[8] = -Struct.sum(bin) & 0x0FF;    //# chksum
      fwrite += ':${hexlify(bin)}$eol';//.translate(table)
    }
    else if(keys == ['EIP']){
      // # Start Linear Address Record
      bin[0] = 4;      //# reclen
      bin[1] = 0;      //# offset msb
      bin[2] = 0;      //# offset lsb
      bin[3] = 5;      //# rectyp
      int eip = startAddress!['EIP']!;
      bin[4] = (eip >> 24) & 0x0FF;
      bin[5] = (eip >> 16) & 0x0FF;
      bin[6] = (eip >> 8) & 0x0FF;
      bin[7] = eip & 0x0FF;
      bin[8] = -Struct.sum(bin) & 0x0FF;    //# chksum
      fwrite += ':${hexlify(bin)}$eol';//.translate(table)
    }
    else{
      logger?.verbose('InvalidStartAddressValueError(start_addr=start_addr)');
    }
  }

  // # data
  List<int> addresses = buffer.keys.toList();
  addresses.sort();
  int addrLength = addresses.length;
  if(addrLength > 0){
    int minAddr = addresses[0];
    int maxAddr = addresses[addresses.length-1];
    bool needOffsetRecord = maxAddr > 65535?true:false;
    int highOFS = 0;
    int curAddress = minAddr;
    int curIX = 0;

    while (curAddress <= maxAddr){
      if (needOffsetRecord){
        Uint8List bin = Uint8List(7);//array('B', asbytes('\0'*7));
        bin[0] = 2;      // # reclen
        bin[1] = 0;      // # offset msb
        bin[2] = 0;      // # offset lsb
        bin[3] = 4;      // # rectyp
        highOFS = curAddress>>16;
        List<int> b = Struct.divmod(highOFS, 256);
        bin[4] = b[0];   //# msb of highOFS
        bin[5] = b[1];   //# lsb of highOFS
        bin[6] = -Struct.sum(bin) & 0x0FF;    //# chksum
        fwrite += ':${hexlify(bin)}$eol';//.translate(table)
      }

      while(true){
        //# produce one record
        int lowAddress = curAddress & 0x0FFFF;
        //# chainLength off by 1
        int chainLength = min(min(byteCount-1, 65535-lowAddress), maxAddr-curAddress);

        //# search continuous chain
        int stopAddress = curAddress + chainLength;
        if (chainLength != 0){
          int ix = bisect_right(addresses, stopAddress,lo: curIX, hi: min(curIX+chainLength+1, addrLength));
          chainLength = ix - curIX;     //# real chainLength
          // # there could be small holes in the chain
          // # but we will catch them by try-except later
          // # so for big continuous files we will work
          // # at maximum possible speed
        }
        else{
          chainLength = 1;               //# real chainLength
        }

        Uint8List bin = Uint8List(5+chainLength);//array('B', asbytes('\0'*(5+chainLength)));
        List<int> b = Struct.divmod(lowAddress, 256);
        bin[1] = b[0];   //# msb of lowAddress
        bin[2] = b[1];   //# lsb of lowAddress
        bin[3] = 0;      //# rectype
        int i = 0;
        try{    //# if there is small holes we'll catch them
          for(i = 0; i < chainLength;i++){// i in range_g(chainLength):
            bin[4+i] = buffer[curAddress+i]!;
          }
        }
        catch(e){
          //# we catch a hole so we should shrink the chain
          chainLength = i;
          bin = bin.sublist(0,5+i);//bin[:5+i];
        }
        bin[0] = chainLength;
        bin[4+chainLength] = -Struct.sum(bin) & 0x0FF;    //# chksum
        fwrite += ':${hexlify(bin)}$eol';//.translate(table)

        //# adjust curAddress/curIX
        curIX += chainLength;
        if (curIX < addrLength){
          curAddress = addresses[curIX];
        }
        else{
          curAddress = maxAddr + 1;
          break;
        }
        int highAddress = curAddress>>16;
        if (highAddress > highOFS){
          break;
        }
      }
    }
  }

  //# end-of-file record
  fwrite += ":00000001FF$eol";
  return fwrite;
}