1

Тема: INIConsole(пример использования LibIni)

Работаем с файлом настроек system.ini
Выводим в консоль названия секций, ключей и их значения шрифтом определённого цвета.
misc.php?action=pun_attachment&item=118&download=0
Функции для перебора всех секций и ключей(ini_enum_sections и ini_enum_keys) принимают в качестве аргумента функции обратного вызова(Callback), затем эти функции будут вызваны библиотекой для каждого ключа\секции.
В нашем примере внутри этих функций как раз и происходит вывод значений в консоль.

program INIConsole;

uses
  KolibriOS, CRT;

function MemoryAllocate(Bytes: LongWord): Pointer; stdcall;
asm
        push ecx
        push ebx
        mov eax, 68
        mov ebx, 12
        mov ecx, Bytes
        int 64
        pop ebx
        pop ecx
end;

function MemoryReallocate(MemPtr: Pointer; Bytes: LongWord): Pointer; stdcall;
asm
        push ebx
        push ecx
        push edx
        mov eax, 68
        mov ebx, 20
        mov ecx, Bytes
        mov edx, MemPtr
        int 64
        pop edx
        pop ecx
        pop ebx
end;

function MemoryFree(MemPtr: Pointer): LongWord; stdcall;
asm
        push ecx
        push ebx
        mov eax, 68
        mov ebx, 13
        mov ecx, MemPtr
        int 64
        pop ebx
        pop ecx
end;

type
  Proc = procedure;

procedure InitLibrary(LibInit: Proc); stdcall;
const
  LIB_PATH = '/sys/lib/';

type
  PNameAddr = ^TNameAddr;
  TNameAddr = packed record
    Name: PAnsiChar;
    Addr: Pointer;
  end;

  PAddrName = ^TAddrName;
  TAddrName = packed record
    Addr: Pointer;
    Name: PAnsiChar;
  end;

  function StrEqual(Str1, Str2: PAnsiChar): Boolean;
  begin
    while (Str1^ = Str2^) and (Str1^ <> #0) do
    begin
      Inc(Str1);
      Inc(Str2);
    end;
    Result := Str1^ = Str2^;
  end;

  procedure StrCopy(StrFrom, StrTo: PAnsiChar);
  begin
    while (StrFrom^ <> #0) do
    begin
      StrTo^ := StrFrom^;
      Inc(StrFrom);
      Inc(StrTo);
    end;
  end;

  function DLLLoad(ImportTable: PAddrName): LongInt; stdcall;
  var
    ExportTable: PNameAddr;
    ProcAddr: Pointer;
    Name: PPAnsiChar;
    LibPath: array [0..32] of AnsiChar;
  begin
    Result := 1;
    StrCopy(LIB_PATH, LibPath);
    while ImportTable.Addr <> nil do
    begin
      StrCopy(ImportTable.Name, Pointer(LongInt(@LibPath) + Length(LIB_PATH)));
      ExportTable := LoadLibrary(LibPath);
      if ExportTable = nil then
        Exit;
      Name := PPAnsiChar(ImportTable.Addr);
      while Name^ <> nil do
      begin
        ProcAddr := GetProcAddress(ExportTable, Name^);
        if ProcAddr <> nil then
          Pointer(Name^) := ProcAddr
        else
          Exit;
        Inc(Name);
      end;
      if StrEqual(ExportTable.Name, 'lib_init') then
        InitLibrary(ExportTable.Addr);
      Inc(ImportTable);
    end;
    Result := 0;
  end;
asm
  pushad
  mov eax, offset MemoryAllocate
  mov ebx, offset MemoryFree
  mov ecx, offset MemoryReallocate
  mov edx, offset DLLLoad
  call LibInit
  popad
end;

type
  TIniKeyCallback = procedure(FileName, SectionName, KeyName, KeyValue: PAnsiChar); stdcall;
  TIniSectionCallback = procedure(FileName, SectionName: PAnsiChar); stdcall;

var
  LibIni: Pointer;
  LibIniLibInit: procedure;
  ini_enum_sections: function(FileName: PAnsiChar; Callback: TIniSectionCallback): LongInt; stdcall;
  ini_enum_keys: function(FileName, SectionName: PAnsiChar; Callback: TIniKeyCallback): LongInt; stdcall;

procedure IniKeyCallback(FileName, SectionName, KeyName, KeyValue: PAnsiChar); stdcall;
begin
  TextColor(LightCyan);
  Write('  ', KeyName);
  TextColor(LightGray);
  Write(' = ');
  TextColor(White);
  WriteLn(KeyValue);
end;

procedure IniSectionCallback(FileName, SectionName: PAnsiChar); stdcall;
begin
  TextColor(Yellow);
  WriteLn(SectionName);
  ini_enum_keys(FileName, SectionName, IniKeyCallback);
end;

begin
  InitConsole('INI Test');
  LibIni            := LoadLibrary('/sys/lib/libini.obj');
  LibIniLibInit     := GetProcAddress(LibIni, 'lib_init');
  ini_enum_sections := GetProcAddress(LibIni, 'ini_enum_sections');
  ini_enum_keys     := GetProcAddress(LibIni, 'ini_enum_keys');

  InitLibrary(LibIniLibInit);

  ini_enum_sections('/sys/settings/system.ini', IniSectionCallback);
end.

Прикладываю также скомпилированный пример INIConsole.kex.

Если нам не нужно перебирать все секции и ключи, а нужно просто узнать значение конкретного ключа, то можно воспользоваться функциями ini_get_str и ini_get_int

var
  ini_get_int: function(FileName, SecName, KeyName: PAnsiChar; DefVal: LongInt): LongInt; stdcall;
...............................
ini_get_int := GetProcAddress(LibIni, 'ini_get_int');
...............................
// присваиваем переменной MouseSpeed значение ключа speed из секции mouse файла system.ini
MouseSpeed := ini_get_int('/sys/settings/system.ini', 'mouse', 'speed', 0);
WriteLn('MouseSpeed = ', MouseSpeed);
Post's attachments

Иконка вложений INIConsole.kex 1.29 Кб, 65 скачиваний с 2021-12-26 

Иконка вложений INIConsole.PNG 17.51 Кб, 28 скачиваний с 2021-12-26