Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Firebird, InterBase Новый топик    Ответить
 isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Есть код, по получению диалекта БД
function TIBDatabaseInfo.GetDBSQLDialect: Integer;
var
  local_buffer: array[0..IBLocalBufferLength - 1] of Byte;
  length: Integer;
  DatabaseInfoCommand: Byte;
begin
  DatabaseInfoCommand := Byte(isc_info_db_SQL_Dialect);
  Call(isc_database_info(StatusVector, @FDatabase.Handle, 1, @DatabaseInfoCommand,
                       IBLocalBufferLength, @local_buffer), True);
  if local_buffer[0] <> isc_info_db_SQL_dialect then
    result := 1
  else begin
    length := isc_vax_integer(@local_buffer[1], 2);
    result := isc_vax_integer(@local_buffer[3], length);
  end;
end;
Хочу перевести ее на новый API
function GetSQLDialect(AStatus: IStatus; AAttachment: IAttachment): Integer;
var
  LBuf: array[0..15] of Byte;
  LLen: Integer;
  LCmd: Byte;
begin
  LCmd := isc_info_db_SQL_Dialect;
  AAttachment.getInfo(AStatus, 1, @LCmd, Length(LBuf), @LBuf[0]);
  if LBuf[0] <> isc_info_db_SQL_dialect then
    result := 1
  else begin
//    LLen := isc_vax_integer(@LBuf[1], 2);
//    result := isc_vax_integer(@LBuf[3], LLen);
  end;
end;
Вопрос: чем можно заменить isc_vax_integer? Или его вообще не нужно вызывать и просто использовать прямой каст?

С уважением, Vasilisk
28 май 20, 13:30    [22141209]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418

Ответ: заменить его нечем. И не вызывать его нельзя из-за переменной длины данных.

Posted via ActualForum NNTP Server 1.5

28 май 20, 13:39    [22141226]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
Ответ: заменить его нечем. И не вызывать его нельзя из-за переменной длины данных.
Спасибо. Я где-то так и подумал
28 май 20, 13:49    [22141243]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418

И чуть не забыл: isc_vax_integer() устарела и будут проблемы с 64-х разрядными значениями,
надо использовать isc_portable_integer(). Хотя конкретно для диалекта, это, конечно же,
всё равно.

Posted via ActualForum NNTP Server 1.5

28 май 20, 13:53    [22141246]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Получилось так
function GetSQLDialect(AStatus: IStatus; AAttachment: IAttachment): Integer;
type
  TBuffer = packed record
    Cmd: Byte;
    case Len: SmallInt of
      1: (v1: ShortInt);
      2: (v2: SmallInt);
      4: (v4: Integer);
      8: (v8: Int64);
      -1: (reserved: array[0..12] of Byte);
  end;
var
  LBuf: TBuffer;
  LCmd: Byte;
  Li: Integer;
begin
  LCmd := isc_info_db_SQL_Dialect;
  AAttachment.getInfo(AStatus, 1, @LCmd, SizeOf(LBuf), @LBuf);
  if LBuf.Cmd <> isc_info_db_SQL_dialect then
    Result := 1
  else begin
    case LBuf.Len of
      SizeOf(LBuf.v1): Result := LBuf.v1;
      SizeOf(LBuf.v2): Result := LBuf.v2;
      SizeOf(LBuf.v4): Result := LBuf.v4;
      SizeOf(LBuf.v8): Result := LBuf.v8;
    else
      Result := 0;
      for Li := LBuf.Len - 1 downto 0 do
        Result := (Result shl 8) or LBuf.reserved[Li]
    end;
  end;
end;


Сообщение было отредактировано: 28 май 20, 13:55
28 май 20, 13:57    [22141252]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
надо использовать isc_portable_integer()
Это я знаю. Но isc_portable_integer все равно же в новом API нет
28 май 20, 13:58    [22141256]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418

_Vasilisk_
Получилось так

Тебе будет большой сюрприз когда кто-нибудь пришлёт три байта. Или пять.

Posted via ActualForum NNTP Server 1.5

28 май 20, 14:00    [22141263]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
Тебе будет большой сюрприз
Почему?
_Vasilisk_
    else
      Result := 0;
      for Li := LBuf.Len - 1 downto 0 do
        Result := (Result shl 8) or LBuf.reserved[Li]
28 май 20, 14:24    [22141293]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418
Извиняюсь, не заметил. Но там будет другой сюрприз, с отрицательными числами. Знак последнего байта надо расширять.

Сообщение было отредактировано: 28 май 20, 14:33
28 май 20, 14:34    [22141308]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
Знак последнего байта надо расширять.
Так?
function PortableInteger(APtr: Pointer; ASize: Integer): Int64;
type
  TValue = record
  case Byte of
    1: (v1: ShortInt);
    2: (v2: SmallInt);
    4: (v4: Integer);
    8: (v8: Int64);
    255: (reserved: array[0..7] of ShortInt);
  end;
var
  LValue: ^TValue absolute APtr;
  Li: Integer;
begin
  case ASize of
    SizeOf(LValue^.v1): Result := LValue^.v1;
    SizeOf(LValue^.v2): Result := LValue^.v2;
    SizeOf(LValue^.v4): Result := LValue^.v4;
    SizeOf(LValue^.v8): Result := LValue^.v8;
  else
    if LValue^.reserved[ASize - 1] < 0 then
      Result := -1
    else
      Result := 0;
    for Li := ASize - 1 downto 0 do
      Result := (Result shl 8) or LValue^.reserved[Li]
  end;
end;
28 май 20, 14:56    [22141324]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418

_Vasilisk_
Так?

Я бы написал немного иначе:
     Result := LValue^.reserved[ASize - 1];
     for Li := ASize - 2 downto 0 do
       Result := (Result shl 8) or LValue^.reserved[Li]

И надо бы обработать случай ASize = 0.

Ну и вообще я сомневаюсь, что весь case нужен. Подозреваю, что на переходы по его
вариантам уйдёт больше тактов, чем на просто цикл.

Posted via ActualForum NNTP Server 1.5

28 май 20, 15:11    [22141338]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
hvlad
Member

Откуда:
Сообщений: 10961
Dimitry Sibiryakov
Ну и вообще я сомневаюсь, что весь case нужен
Он просто вреден, ибо не правилен.

Сообщение было отредактировано: 28 май 20, 15:19
28 май 20, 15:21    [22141350]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
Я бы написал немного иначе
Да. Ты прав. Так лучше.
Dimitry Sibiryakov
И надо бы обработать случай ASize = 0.
Так тоже бывает? Учту. Спасибо
28 май 20, 15:21    [22141351]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
hvlad
ибо не правилен
Чем? Порядок байт инвертируется корректно
28 май 20, 15:22    [22141352]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
hvlad
Member

Откуда:
Сообщений: 10961
_Vasilisk_
hvlad
ибо не правилен
Чем? Порядок байт инвертируется корректно
Где он инвертируется ?
28 май 20, 15:23    [22141354]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
hvlad
Где он инвертируется ?
При касте
type
  TValue = record
  case Byte of
    1: (v1: ShortInt);
    2: (v2: SmallInt);
    4: (v4: Integer);
    8: (v8: Int64);
    255: (reserved: array[0..7] of ShortInt);
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  LBuf: TValue;
begin
  LBuf.reserved[0] := 1;
  LBuf.reserved[1] := 2;
  LBuf.reserved[2] := 3;
  LBuf.reserved[3] := 4;
  ShowMessage(IntToHex(LBuf.v4));
end;


К сообщению приложен файл. Размер - 1Kb
28 май 20, 16:07    [22141409]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
hvlad
Member

Откуда:
Сообщений: 10961
Ну так где порядок байт инвертируется-то ? :)

Его же не надо инвертировать для LE - тут я промазал, признаюсь :)
28 май 20, 16:35    [22141452]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 50418

Dimitry Sibiryakov
Result := (Result shl 8) or LValue^.reserved[Li]


Вот эту строчку надо бы потестить, потому что если знак расширится перед применением ИЛИ -
будет неприятный сюрприз.

Posted via ActualForum NNTP Server 1.5

30 май 20, 22:28    [22142890]     Ответить | Цитировать Сообщить модератору
 Re: isc_vax_integer и IAttachment  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 11914
Dimitry Sibiryakov
Вот эту строчку надо бы потестить, потому что если знак расширится перед применением ИЛИ -
Ты прав. Нужно так
Result := (Result shl 8) or (LValue^.reserved[Li] and $FF)

Dimitry Sibiryakov
Ну и вообще я сомневаюсь, что весь case нужен. Подозреваю, что на переходы по его вариантам уйдёт больше тактов, чем на просто цикл.
Проверил на миллиарде итераций для длин 1, 2, 4, 8 байт с case и только циклом. Получились такие времена
Case: 1: 2312, 2: 2328, 4: 2312, 8: 2360, 
Loop: 1: 2344, 2: 4485, 4: 8484, 8: 16640,
Так, что case смысл имеет

Сообщение было отредактировано: 1 июн 20, 17:25
1 июн 20, 17:27    [22143879]     Ответить | Цитировать Сообщить модератору
Все форумы / Firebird, InterBase Ответить