UNIT Unit2_functions;
INTERFACE
USES Classes, Dialogs, SysUtils, StrUtils, Math,
      Unit3_data;

TYPE
  TExportSet=SET OF (DO_dat,DO_raw,DO_convert,DO_toone);

FUNCTION BoolToStr(bool:Boolean):String;
FUNCTION HexToLong(hex:String):LongWord;
FUNCTION Decode_Int(buffer:Tdata):LongWord;
FUNCTION Encode_Int(input:LongWord):Tdata;
FUNCTION Decode_Float(buffer:Tdata):Single;
FUNCTION Encode_Float(input:Single):Tdata;
FUNCTION DataToBin(data:Tdata):String;
FUNCTION BinToInt(bin:String):Byte;

FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;

FUNCTION StringSmaller(string1,string2:String):Boolean;

FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
FUNCTION FormatFileSize(size:LongWord):String;
FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
FUNCTION DecodeHexString(hex:String):Tdata;
FUNCTION GetWinFileName(name:String):String;
FUNCTION GetExtractPath:String;

FUNCTION Explode(_string:String; delimiter:Char):TStringArray;


IMPLEMENTATION
USES Unit4_Exporters, Unit15_Classes;

TYPE
  TValueSwitcher=Record
    CASE IsFloat: Boolean OF
      True: (ValueFloat:Single);
      False: (ValueInt:LongWord);
  END;

FUNCTION BoolToStr(bool:Boolean):String;
  BEGIN
    IF bool THEN
      Result:='true'
    ELSE
      Result:='false';
  END;

FUNCTION HexToLong(hex:String):LongWord;
  FUNCTION NormalizeHexString(VAR hex:String):Boolean;
    VAR
      i:Byte;
    BEGIN
      IF hex[1]='$' THEN BEGIN
        FOR i:=1 TO Length(hex)-1 DO BEGIN
          hex[i]:=hex[i+1];
        END;
        SetLength(hex, Length(hex)-1);
      END;
      IF (hex[1]='0') AND (UpCase(hex[2])='X') THEN BEGIN
        FOR i:=1 TO Length(hex)-2 DO BEGIN
          hex[i]:=hex[i+2];
        END;
        SetLength(hex, Length(hex)-2);
      END;
      IF Length(hex)=0 THEN
        Result:=False
      ELSE
        Result:=True;
    END;
  VAR
    i:Byte;
  BEGIN
    IF NormalizeHexString(hex) THEN BEGIN
      hex:=UpperCase(hex);
      Result:=0;
      FOR i:=1 TO Length(hex) DO BEGIN
        Result:=Result SHL 4;
        CASE hex[i] OF
          '0'..'9': Result:=Result+Ord(hex[i])-48;
          'A'..'F': Result:=Result+Ord(hex[i])-55;
        ELSE
          Result:=0;
          Exit;
        END;
      END;
    END ELSE BEGIN
      Result:=0;
    END;
  END;

FUNCTION Decode_Int(buffer:Tdata):LongWord;
  BEGIN
    Result:=buffer[0]+buffer[1]*256+buffer[2]*256*256+buffer[3]*256*256*256;
  END;
FUNCTION Encode_Int(input:LongWord):Tdata;
  BEGIN
    SetLength(Result,4);
    Result[0]:=input MOD 256;
    input:=input DIV 256;
    Result[1]:=input MOD 256;
    input:=input DIV 256;
    Result[2]:=input MOD 256;
    input:=input DIV 256;
    Result[3]:=input MOD 256;
  END;
FUNCTION Decode_Float(buffer:Tdata):Single;
  VAR _valueswitcher:TValueSwitcher;
  BEGIN
    _valueswitcher.ValueInt:=Decode_Int(buffer);
    Result:=_valueswitcher.ValueFloat;
    IF IsNAN(Result) THEN Result:=0.0;
  END;
FUNCTION Encode_Float(input:Single):Tdata;
  VAR _valueswitcher:TValueSwitcher;
  BEGIN
    _valueswitcher.ValueFloat:=input;
    Result:=Encode_Int(_valueswitcher.ValueInt);
  END;

FUNCTION DataToBin(data:Tdata):String;
  VAR
    i,j:Byte;
    singlebyte:Byte;
    bytepart:String;
  BEGIN
    SetLength(bytepart,8);
    Result:='';
    FOR i:=0 TO High(data) DO BEGIN
      singlebyte:=data[i];
      FOR j:=7 DOWNTO 0 DO BEGIN
        bytepart[j+1]:=Char((singlebyte AND $01)+48);
        singlebyte:=singlebyte SHR 1;
      END;
      Result:=Result+bytepart+' ';
    END;
  END;
FUNCTION BinToInt(bin:String):Byte;
  VAR
    Add: Integer;
    i: Byte;
  BEGIN
    Result:=0;
    IF Length(bin)<>8 THEN Exit;
    Add:=1;
    FOR i:=8 DOWNTO 1 DO BEGIN
      IF NOT (bin[i] IN ['0','1']) THEN Exit;
      IF bin[i] = '1' THEN Inc(Result,Add);
      Add:=Add SHL 1;
    END;
  END;



FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
  BEGIN
    Result:=AnsiReplaceStr(Format('%'+IntToStr(width)+'u',[value]),' ',leadingzeros);
  END;

FUNCTION FormatFileSize(size:LongWord):String;
  BEGIN
    IF size>=1000*1024*1024 THEN BEGIN
      Result:=FloatToStrF(size/1024/1024/1024,ffFixed,5,1)+' GB';
    END ELSE BEGIN
      IF size>=1000*1024 THEN BEGIN
        Result:=FloatToStrF(size/1024/1024,ffFixed,5,1)+' MB';
      END ELSE BEGIN
        IF size>=1000 THEN BEGIN
          Result:=FloatToStrF(size/1024,ffFixed,5,1)+' KB';
        END ELSE BEGIN
          Result:=IntToStr(size)+' B';
        END;
      END;
    END;
  END;

FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
  VAR
    string_build,ascii_version:String;
    i:LongWord;
  BEGIN
    string_build:='';
    ascii_version:='';
    FOR i:=0 TO High(data) DO BEGIN
      IF NOT HexOnly THEN
        IF (i MOD 16)=0 THEN
          string_build:=string_build+'0x'+IntToHex(i,6)+'  ';
      string_build:=string_build+IntToHex(data[i],2);
      IF NOT HexOnly THEN BEGIN
        IF data[i]>=32 THEN ascii_version:=ascii_version+Chr(data[i])
        ELSE ascii_version:=ascii_version+'.';
        IF ((i+1) MOD 2)=0 THEN string_build:=string_build+#32;
        IF ((i+1) MOD 16)=0 THEN BEGIN
          string_build:=string_build+#32+ascii_version+CrLf;
          ascii_version:='';
        END;
      END;
    END;
    Result:=string_build;
  END;

FUNCTION DecodeHexString(hex:String):Tdata;
  VAR
    i:LongWord;
  BEGIN
    SetLength(Result, Length(hex) DIV 2);
    FOR i:=0 TO Length(Result) DO BEGIN
      Result[i]:=0;
      CASE UpCase(hex[1+i*2]) OF
        '0'..'9': Result[i]:=(Ord(UpCase(hex[1+i*2]))-48)*16;
        'A'..'F': Result[i]:=(Ord(UpCase(hex[1+i*2]))-55)*16;
      END;
      CASE UpCase(hex[1+i*2+1]) OF
        '0'..'9': Result[i]:=Result[i]+(Ord(UpCase(hex[1+i*2+1]))-48);
        'A'..'F': Result[i]:=Result[i]+(Ord(UpCase(hex[1+i*2+1]))-55);
      END;
    END;
  END;



FUNCTION StringSmaller(string1,string2:String):Boolean;
  VAR
    i:Integer;
    len:Integer;
  BEGIN
    len:=Min(Length(string1),Length(string2));
    FOR i:=1 TO len DO
      IF Ord(string1[i])<>Ord(string2[i]) THEN BEGIN
        Result:=Ord(string1[i])<Ord(string2[i]);
        Exit;
      END;
    Result:=Length(string1)<Length(string2);
  END;




FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
  VAR
    i:Byte;
    extension:String;
    rawlist:TRawList;
  BEGIN
    Result:=export_noerror;
    extension:=RightStr(filename,4);
    IF DO_toone IN settings THEN BEGIN
      ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
    END ELSE BEGIN
      IF DO_dat IN settings THEN ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
      IF DO_raw IN settings THEN BEGIN
        rawlist:=OniDataConnection.GetRawList(fileid);
        IF Length(rawlist)>0 THEN BEGIN
          FOR i:=0 TO High(rawlist) DO BEGIN
            ExportRawFile(fileid,rawlist[i].src_offset,path+'\'+GetWinFileName(filename));
          END;
        END;
      END;
    END;
  END;

FUNCTION Explode(_string:String; delimiter:Char):TStringArray;
  VAR
    start,len:Word;
  BEGIN
    SetLength(Result, 0);
    start:=1;
    WHILE PosEx(delimiter,_string,start)>0 DO BEGIN
      len:=PosEx(delimiter,_string,start)-start;
      SetLength(Result, Length(Result)+1);
      Result[High(Result)]:=MidStr(_string,start,len);
      start:=start+len+1;
    END;
    SetLength(Result, Length(Result)+1);
    Result[High(Result)]:=MidStr(_string,start,Length(_string)-start+1);
  END;

FUNCTION GetWinFileName(name:String):String;
  BEGIN
    Result:=name;
    Result:=AnsiReplaceStr(Result,'\','__');
    Result:=AnsiReplaceStr(Result,'/','__');
    Result:=AnsiReplaceStr(Result,'>','__');
    Result:=AnsiReplaceStr(Result,'<','__');
  END;

FUNCTION GetExtractPath:String;
  BEGIN
    Result:=ExtractFilePath(OniDataConnection.FileName)+'\extracted_'+ExtractFileName(OniDataConnection.Filename);
  END;


END.
