Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 .. 16 17 18 19 20 21 22 [23] 24 25   вперед  Ctrl
 Re: goto address  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2663
Няшик
Найти NextGen в строках? О котором там не задумались

Чувак, да перестань ты бредить. Эта структура строк появилась в Delphi 2. В Delphi 2009 была немного модифицирована для поддержки CodePage aware strings. В Delphi XE2 была модифицирована ещё раз для паддинга в 64-битном режиме. А понятие NEXTGEN относится вообще к компилятору, в котором объекты стали управляемым типом.
29 авг 17, 23:00    [20757364]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
alekcvp
Ещё раз: StrRec имеет такое же отношение к NextGen, как и Boolean.


У тебя неправильное представление о NextGen. NextGen предоставляет новые возможности, в данном случае например не считать длину строки по новой, что несёт огромный прирост в коде, когда ты запихал в цикл Length

И прошу заметит - засунув в цикл length(str) это работает быстрее чем присвоить длину к переменной, и уже брать из переменной. Лично тестировал. Когда разбирался с этой лабудой.

alekcvp
Ок, передал ты строку в модуль c++, попробуй теперь оттуда вернуть другую строку, только через тип string, а не через pchar. Или изменить ту, что ты передал (чтобы длина новой была больше старой).


-_- Ну... Легко! Просто написать функцию которая создаёт тот же юникодный массив, только не создавать, а пометить область структуры на новую область массива символов, что бы в Delphi можно было сделать str[-4]




Kazantsev Alexey
Чувак, да перестань ты бредить. Эта структура строк появилась в Delphi 2. В Delphi 2009 была немного модифицирована для поддержки CodePage aware strings. В Delphi XE2 была модифицирована ещё раз для паддинга в 64-битном режиме. А понятие NEXTGEN относится вообще к компилятору, в котором объекты стали управляемым типом.


Что? Это вы бредите, приплетая то, о чём речь совершенно не шла. Я лично говорил о токио и берлине


Кстати, выдержка текста из Вики

в новых компиляторах строки стали индексироваться по нулевой базе, как и в семействе С-подобных языков(C++, C#, Java), при этом в «классических» компиляторах для Windows и Mac OS, парадигма единичной индексации была сохранена.
29 авг 17, 23:15    [20757385]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2663
Няшик
Я лично говорил о токио и берлине

Ага. Ты говорил о строках в сях, сузив, я так понимаю, все си до билдера. И ещё о каком-то nextgen в строках... Можешь не продолжать.

Няшик
Кстати, выдержка текста из Вики

А это к чему вообще? Базовый индекс это условность и не более.
29 авг 17, 23:26    [20757401]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Kazantsev Alexey
Ага. Ты говорил о строках в сях, сузив, я так понимаю, все си до билдера. И ещё о каком-то nextgen в строках... Можешь не продолжать.


Это вообще началось из какое кого, кто сказал что строки это не массив байта. А структура.

Хотя его слова рассыпаются когда обращаешься по индексу str[1] это кстати и для массивов аналогично.


Kazantsev Alexey
А это к чему вообще? Базовый индекс это условность и не более.


Это к тому, что если передать массив байт этот в другой язык, то там будет всё прекрасно работать, если в настройках включена двух байтовая кодировка, и используешь среду Delphi юникодную
29 авг 17, 23:42    [20757415]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2663
Няшик
Это вообще началось из какое кого, кто сказал что строки это не массив байта. А структура.

Длинные строки в дельфях всегда были структурами: заголовок + данные строки. Это не тупо массив с нулевым терминатором.

Няшик
Хотя его слова рассыпаются когда обращаешься по индексу str[1] это кстати и для массивов аналогично.

Семантика чтения данных не определяет внутреннго устройства.

Няшик
Это к тому, что если передать массив байт этот в другой язык, то там будет всё прекрасно работать, если в настройках включена двух байтовая кодировка, и используешь среду Delphi юникодную

1. Индексная база строки на это ни коим образом не влияет.
2. Передача управляемых типов, например строк (за исключением системной BSTR/WideString), в "другой язык" дело не самое простое, и без специальных приседаний работать не будет.
30 авг 17, 00:01    [20757426]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Присваивание обычной строки, к моему

 TBaseArray = array of char;


Увенчалась такой инструкцией

Project1.dpr.23: b := @str;
0041D573 C705B0584200A8584200 mov [$004258b0],$004258a8



+
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}
{$POINTERMATH ON}

uses
  System.SysUtils;

type
  PBaseArray = ^TBaseArray;
  TBaseArray = array of char;

var
  I: Integer;
  str: string;
  s: char;

  b: PBaseArray;

begin
  try
    str := 'TextText';
    b := @str;
    for I := 0 to High(str) do
      Writeln(b^[I]);

    for I := 0 to High(str) do
    begin
      s := char(PWord(str)[I]);
      Writeln(s);
    end;

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
30 авг 17, 00:03    [20757427]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2663
Няшик
Присваивание обычной строки, к моему

Няшик
Увенчалась такой инструкцией

А потом появляются такие топики Удачи, короче.
30 авг 17, 01:22    [20757478]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
SOFT FOR YOU
Member

Откуда:
Сообщений: 2418
Ребята, что происходит?
Почему обсуждают всё кроме парсинга и джита?

Няшик, ты сделал грамотную конкатенацию строк?
Или всё через обычные строки делаешь?
30 авг 17, 01:42    [20757487]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 2400
SOFT FOR YOU
Ребята, что происходит?
Почему обсуждают всё кроме парсинга и джита?

Няшик, ты сделал грамотную конкатенацию строк?
Или всё через обычные строки делаешь?
да ладно тебе, хоть что-то бы запускаемое сделал, уже неплохо бы было
30 авг 17, 08:27    [20757646]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
alekcvp
Member

Откуда:
Сообщений: 508
Няшик,

Кстати, если ты передашь в Cи переменную-строку у которой RefCount > 1 по ссылке, а потом в исходном коде попытаешься попытаешься изменить её значение, типа Str[3] := 'Z', ожидая увидеть эти изменения в C-шном коде, то тебя ждёт сюрприз :)
30 авг 17, 08:54    [20757689]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Да речь в общем то шла что это массив байт, а не какая то особая конструкция языка. =_=

SOFT FOR YOU
Няшик, ты сделал грамотную конкатенацию строк?
Или всё через обычные строки делаешь?


Давно ещё сделал, первым делом

+

procedure TBox.AppendString(const Value: string);
var
  a: Cardinal;
  p, pp: Pointer;
begin
  Hash := 0;
  if _Type = SString then
  begin
    a := System.Length(Value);

    with TStrBox^ do
    begin
      FLength := FLength + a;
      if FLength > tmpLength then
      begin
        tmpLength := tmpLength + 32;

        if FLength > tmpLength then
          tmpLength := FLength + 32;

        if tmpLength > MaxInt then
          tmpLength := MaxInt;

        if tmpLength < 0 then
          tmpLength := FLength;

        System.SetLength(FData, tmpLength);
      end;
    end;
    Move(PChar(Value)^, TStrBox^.FData[TStrBox^.FLength - a], a * sizeof(Char));
  end
  else
  begin
    case _Type of
      SUInt16:
        Dispose(TWord);
      SUInt32:
        Dispose(TCardinal);
      SUInt64:
        Dispose(TUInt64);
      SInt8:
        Dispose(TShortInt);
      SInt16:
        Dispose(TSmallInt);
      SInt32:
        Dispose(TInteger);
      SInt64:
        Dispose(TInt64);
      SSingle:
        Dispose(TSingle);
      SDouble:
        Dispose(TDouble);
      SExtended:
        Dispose(TExtended);
      SCurrency:
        Dispose(TCurrency);
    end;

    _Type := SNULL;

    SetString(Value);

  end;

end;




И другая полная работа с базовыми типами
+
    procedure SetString(const Value: string); // inline;
    procedure SetByte(Value: Byte); inline;
    procedure SetWord(Value: Word); inline;
    procedure SetCardinal(Value: Cardinal); inline;
    procedure SetUInt64(Value: UInt64); inline;
    procedure SetShortInt(Value: ShortInt); inline;
    procedure SetSmallInt(Value: SmallInt); inline;
    procedure SetInteger(Value: Integer); inline;
    procedure SetInt64(Value: Int64); inline;
    procedure SetSingle(Value: Single); inline;
    procedure SetDouble(Value: Double); inline;
    procedure SetExtended(Value: Extended); inline;
    procedure SetCurrency(Value: Currency); inline;
    procedure SetPointer(Value: Pointer); inline;

    procedure SetValue(var Value: TBox; Copy: Boolean = false); overload; //inline;

    procedure SetValue(const Value: string); overload; inline;
    procedure SetValue(Value: Byte); overload; inline;
    procedure SetValue(Value: Word); overload; inline;
    procedure SetValue(Value: Cardinal); overload; inline;
    procedure SetValue(Value: UInt64); overload; inline;
    procedure SetValue(Value: ShortInt); overload; inline;
    procedure SetValue(Value: SmallInt); overload; inline;
    procedure SetValue(Value: Integer); overload; inline;
    procedure SetValue(Value: Int64); overload; inline;
    procedure SetValue(Value: Single); overload; inline;
    procedure SetValue(Value: Double); overload; inline;
    procedure SetValue(Value: Extended); overload; inline;
    procedure SetValue(Value: Currency); overload; inline;
    procedure SetValue(Value: Pointer); overload; inline;

    function GetByte: Byte; inline;
    function GetWord: Word; inline;
    function GetCardinal: Cardinal; inline;
    function GetUInt64: UInt64; inline;
    function GetShortInt: ShortInt; inline;
    function GetSmallInt: SmallInt; inline;
    function GetInteger: Integer; inline;
    function GetInt64: Int64; inline;
    function GetSingle: Single; inline;
    function GetDouble: Double; inline;
    function GetExtended: Extended; inline;
    function GetCurrency: Currency; inline;
    function GetPointer: Pointer; inline;
    function GetString: string; inline;
    function GetLength: Cardinal; inline;

    function IsEqual(Value: Byte): Boolean; overload; inline;
    function IsEqual(Value: Word): Boolean; overload; inline;
    function IsEqual(Value: Cardinal): Boolean; overload; inline;
    function IsEqual(Value: UInt64): Boolean; overload; inline;
    function IsEqual(Value: ShortInt): Boolean; overload; inline;
    function IsEqual(Value: SmallInt): Boolean; overload; inline;
    function IsEqual(Value: Integer): Boolean; overload; inline;
    function IsEqual(Value: Int64): Boolean; overload; inline;
    function IsEqual(Value: Single): Boolean; overload; inline;
    function IsEqual(Value: Double): Boolean; overload; inline;
    function IsEqual(Value: Extended): Boolean; overload; inline;
    function IsEqual(Value: Currency): Boolean; overload; inline;
    function IsEqual(Value: Pointer): Boolean; overload; inline;

    function IsNULL: Boolean; inline;
    function IsByte: Boolean; inline;
    function IsWord: Boolean; inline;
    function IsCardinal: Boolean; inline;
    function IsUInt64: Boolean; inline;
    function IsShortInt: Boolean; inline;
    function IsSmallInt: Boolean; inline;
    function IsInteger: Boolean; inline;
    function IsInt64: Boolean; inline;
    function IsSingle: Boolean; inline;
    function IsDouble: Boolean; inline;
    function IsExtended: Boolean; inline;
    function IsCurrency: Boolean; inline;
    function IsPointer: Boolean; inline;

    function GetType: Byte; inline;

    procedure SetNull; inline;

    procedure increment; inline;
    procedure decrement; inline;

    procedure AppendString(const Value: string);
    procedure AppendPlus(Value: Byte); overload; inline;
    procedure AppendPlus(Value: Word); overload; inline;
    procedure AppendPlus(Value: Cardinal); overload; inline;
    procedure AppendPlus(Value: UInt64); overload; inline;
    procedure AppendPlus(Value: ShortInt); overload; inline;
    procedure AppendPlus(Value: SmallInt); overload; inline;
    procedure AppendPlus(Value: Integer); overload; inline;
    procedure AppendPlus(Value: Int64); overload; inline;
    procedure AppendPlus(Value: Single); overload; inline;
    procedure AppendPlus(Value: Double); overload; inline;
    procedure AppendPlus(Value: Extended); overload; inline;
    procedure AppendPlus(Value: Currency); overload; inline;
    procedure AppendPlus(Value: Pointer); overload; inline;

    procedure AppendMinus(Value: Byte); overload; inline;
    procedure AppendMinus(Value: Word); overload; inline;
    procedure AppendMinus(Value: Cardinal); overload; inline;
    procedure AppendMinus(Value: UInt64); overload; inline;
    procedure AppendMinus(Value: ShortInt); overload; inline;
    procedure AppendMinus(Value: SmallInt); overload; inline;
    procedure AppendMinus(Value: Integer); overload; inline;
    procedure AppendMinus(Value: Int64); overload; inline;
    procedure AppendMinus(Value: Single); overload; inline;
    procedure AppendMinus(Value: Double); overload; inline;
    procedure AppendMinus(Value: Extended); overload; inline;
    procedure AppendMinus(Value: Currency); overload; inline;
    procedure AppendMinus(Value: Pointer); overload; inline;

    procedure AppendDIV(Value: Byte); overload; inline;
    procedure AppendDIV(Value: Word); overload; inline;
    procedure AppendDIV(Value: Cardinal); overload; inline;
    procedure AppendDIV(Value: UInt64); overload; inline;
    procedure AppendDIV(Value: ShortInt); overload; inline;
    procedure AppendDIV(Value: SmallInt); overload; inline;
    procedure AppendDIV(Value: Integer); overload; inline;
    procedure AppendDIV(Value: Int64); overload; inline;
    procedure AppendDIV(Value: Single); overload; inline;
    procedure AppendDIV(Value: Double); overload; inline;
    procedure AppendDIV(Value: Extended); overload; inline;
    procedure AppendDIV(Value: Currency); overload; inline;
    procedure AppendDIV(Value: Pointer); overload; inline;

    procedure AppendMUL(Value: Byte); overload; inline;
    procedure AppendMUL(Value: Word); overload; inline;
    procedure AppendMUL(Value: Cardinal); overload; inline;
    procedure AppendMUL(Value: UInt64); overload; inline;
    procedure AppendMUL(Value: ShortInt); overload; inline;
    procedure AppendMUL(Value: SmallInt); overload; inline;
    procedure AppendMUL(Value: Integer); overload; inline;
    procedure AppendMUL(Value: Int64); overload; inline;
    procedure AppendMUL(Value: Single); overload; inline;
    procedure AppendMUL(Value: Double); overload; inline;
    procedure AppendMUL(Value: Extended); overload; inline;
    procedure AppendMUL(Value: Currency); overload; inline;
    procedure AppendMUL(Value: Pointer); overload; inline;

    procedure AppendMOD(Value: Byte); overload; inline;
    procedure AppendMOD(Value: Word); overload; inline;
    procedure AppendMOD(Value: Cardinal); overload; inline;
    procedure AppendMOD(Value: UInt64); overload; inline;
    procedure AppendMOD(Value: ShortInt); overload; inline;
    procedure AppendMOD(Value: SmallInt); overload; inline;
    procedure AppendMOD(Value: Integer); overload; inline;
    procedure AppendMOD(Value: Int64); overload; inline;
    procedure AppendMOD(Value: Single); overload; inline;
    procedure AppendMOD(Value: Double); overload; inline;
    procedure AppendMOD(Value: Extended); overload; inline;
    procedure AppendMOD(Value: Currency); overload; inline;
    procedure AppendMOD(Value: Pointer); overload; inline;

    procedure AppendPOW(Value: Byte); overload; inline;
    procedure AppendPOW(Value: Word); overload; inline;
    procedure AppendPOW(Value: Cardinal); overload; inline;
    procedure AppendPOW(Value: UInt64); overload; inline;
    procedure AppendPOW(Value: ShortInt); overload; inline;
    procedure AppendPOW(Value: SmallInt); overload; inline;
    procedure AppendPOW(Value: Integer); overload; inline;
    procedure AppendPOW(Value: Int64); overload; inline;
    procedure AppendPOW(Value: Single); overload; inline;
    procedure AppendPOW(Value: Double); overload; inline;
    procedure AppendPOW(Value: Extended); overload; inline;
    procedure AppendPOW(Value: Currency); overload; inline;
    procedure AppendPOW(Value: Pointer); overload; inline;

    procedure free; inline;
30 авг 17, 10:07    [20757886]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
alekcvp
Member

Откуда:
Сообщений: 508
Няшик,

Свой .Free без override (а он вроде вообще не виртуальный) - тебя в будущем ждёт много сюрпризов
30 авг 17, 10:11    [20757897]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
alekcvp
Няшик,

Свой .Free без override (а он вроде вообще не виртуальный) - тебя в будущем ждёт много сюрпризов


Это структура, не какой - то там класс там.

+
procedure TBox.free;
begin
  case _Type of
    SString:
      begin
        TStrBox^.FLength := 0;
        System.SetLength(TStrBox^.FData, 0);
        Dispose(TStrBox);
      end;
    SUInt8:
        TByte := 0;
    SUInt16:
      begin
        Dispose(TWord);
        TWord := nil;
      end;
    SUInt32:
      begin
        Dispose(TCardinal);
        TCardinal := nil;
      end;
    SUInt64:
      begin
        Dispose(TUInt64);
        TUInt64 := nil;
      end;
    SInt8:
      begin
        Dispose(TShortInt);
        TShortInt := nil;
      end;
    SInt16:
      begin
        Dispose(TSmallInt);
        TSmallInt := nil;
      end;
    SInt32:
      begin
        Dispose(TInteger);
        TInteger := nil;
      end;
    SInt64:
      begin
        Dispose(TInt64);
        TInt64 := nil;
      end;
    SSingle:
      begin
        Dispose(TSingle);
        TSingle := nil;
      end;
    SDouble:
      begin
        Dispose(TDouble);
        TDouble := nil;
      end;
    SExtended:
      begin
        Dispose(TExtended);
        TExtended := nil;
      end;
    SCurrency:
      begin
        Dispose(TCurrency);
        TCurrency := nil;
      end;
    SPointer:
        TPointer := nil;
  end;
    _Type := SNULL;
end;
30 авг 17, 10:39    [20757989]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
SOFT FOR YOU
Member

Откуда:
Сообщений: 2418
Няшик,

Какое-то ты неприятное ощущение оставляешь
Сама тематика интересная, глубокая. Но отношение какое-то безответственное. Как к своему труду, так и к форумчанам

Ну вот возьмём конкатенацию. У тебя конкатенация происходит за одну операцию за раз. На практике конкатенация объединяет в себе множество "слагаемых". А ты постоянно проводишь реаллок. Наверняка если конкатенация идёт с числами - ты сначала число переводишь в строку. Это всё жутко медленно. Конкатенация должна быть буферизированной и объединять в себе всю цепочку вычислений. Ты приводил пример, что в твоём языке обращение внутри массива может быть по строке, точнее по результату конкатенации. Так вот необходимости в использовании строк как таковых нет. Может быть буфер в режиме эмуляции строки; он заполняется - и по нему ищешь элемент. Ты же выделяешь, изменяешь и удаляешь строки - поэтому у тебя всё тормозит.

Ну а Box твой. Это же жесть. Ты хочешь сказать, что для каждого инта ты дёргаешь менеджер памяти?
Это бред. Для коротких типов делают union-ы и задействуют память "на стеке". Нафиг менеджер каждый раз дёргать

Ну и в остальном. Я тебе показал, как ускорить парсинг минимум в 2-3 раза. Ты заюзал эти идеи? Нет
Делаешь сравнение строк в хеше. SSE зачем-то приплёл. Это не то чтобы плохо, просто возникает ощущение, что ты понтуешься, вместо того чтобы делать реально хороший продукт. А знаний мало, поэтому понты тоже дешёвые получаются, не интересные.

Вообще ключевая часть твоей реализации, как мне кажется, должна быть JIT. Ты хотя бы начал думать, как реализовать исполнение? Не в интерпретации, а именно в машинных командах?
1 сен 17, 13:26    [20764452]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
alekcvp
Member

Откуда:
Сообщений: 508
SOFT FOR YOU
Делаешь сравнение строк в хеше. SSE зачем-то приплёл.

Но но но, попрошу! SSE я приплёл! И не зачем-то, а чисто из спортивного интереса
1 сен 17, 15:21    [20764885]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
SOFT FOR YOU
Member

Откуда:
Сообщений: 2418
alekcvp,

SSE тема, особенно когда адреса выровнены на 16 байт
Но Няшику надо проверять 6-8 символов. Лучше пусть хеш функцию модифицирует, и то толку будет больше )
1 сен 17, 17:09    [20765324]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
SOFT FOR YOU,

Ты чего - то не так понял, скажу я тебе. Конкатенация тут вообще не причём, к тому же в PHP строки не фиксированные, по этому должен быть внутри неё увлечение исходной строки. Пример

$str  =" Устанавливаем строку ";

$str .= ' Тут она увеличивается! Очень много текст. И внутреннего баффера не хватает что бы это уместить. По этому мы увеличиваем в функции конкатенации размер буффера, что бы этот текст склеить с первым текстом.  ';


Насчёт чисел не понял, ты имел введу это?

$str = '438895484'  + 43546;


Даг оно на стадии компиляции превращается в 438939030

....

Насчёт new я знаю, что нужно заменить GetMem но пока руки не дошли.

А вот SSE важный элемент! Так как он позволил поднять скорость, как самого кода. Так и компиляции, потому что позволяет быстро находить дубликаты переменных, и вставлять туда адреса.

К тому же, я уже запилил всю арифметику на SSE
1 сен 17, 19:06    [20765544]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
И ещё немножечко дополню,

Когда в своём языке я пишу

 $NewVar = 24546; // Тут мы создаём Box и выделяем для него int64 (он работает к слову в структуре, так же как и int) 

$NewVar += 395; // Тут мы уже просто добавляем к 24546;


Это работает очень быстро, так быстро, что если бы ты написал это в коде Delphi, она выполнилось по скорости так же, но на 0,000030 медленнее примерно. Но не более
1 сен 17, 19:18    [20765573]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Kazantsev Alexey
Няшик
А в сях и delphi нет ?

В FPC и Oxygene есть, но к делу это не относится.

Няшик
А вот если будут коллизии, то придётся делать cmpstr и проверять второй хэш

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


Кхм... =_= Вообще то у меня есть счётчик ссылок на одинаковые переменные.

Но мы не можем полагаться что придёт - то, что в базе.

Кстати, сделала замеры бокса

+
[: TestSBox             Min: 0,126649, Max: 0,162100 :]
[: TestNative           Min: 0,068610, Max: 0,072159 :]

 2 | 0.1535 - 2.22 | 0.0692 - 1.00 -> TestNative
 4 | 0.1557 - 2.25 | 0.0692 - 1.00 -> TestNative
 6 | 0.1275 - 1.83 | 0.0697 - 1.00 -> TestNative
 8 | 0.1354 - 1.97 | 0.0688 - 1.00 -> TestNative
10 | 0.1291 - 1.79 | 0.0722 - 1.00 -> TestNative
12 | 0.1573 - 2.26 | 0.0695 - 1.00 -> TestNative
14 | 0.1276 - 1.85 | 0.0690 - 1.00 -> TestNative
16 | 0.1381 - 1.98 | 0.0698 - 1.00 -> TestNative
18 | 0.1313 - 1.89 | 0.0695 - 1.00 -> TestNative
20 | 0.1621 - 2.33 | 0.0697 - 1.00 -> TestNative
22 | 0.1290 - 1.87 | 0.0688 - 1.00 -> TestNative
24 | 0.1308 - 1.90 | 0.0688 - 1.00 -> TestNative
26 | 0.1266 - 1.81 | 0.0698 - 1.00 -> TestNative
28 | 0.1555 - 2.23 | 0.0696 - 1.00 -> TestNative
30 | 0.1273 - 1.84 | 0.0691 - 1.00 -> TestNative
32 | 0.1307 - 1.88 | 0.0694 - 1.00 -> TestNative
34 | 0.1272 - 1.85 | 0.0689 - 1.00 -> TestNative
36 | 0.1567 - 2.28 | 0.0686 - 1.00 -> TestNative
38 | 0.1274 - 1.85 | 0.0691 - 1.00 -> TestNative
40 | 0.1301 - 1.85 | 0.0702 - 1.00 -> TestNative
42 | 0.1313 - 1.90 | 0.0692 - 1.00 -> TestNative
44 | 0.1544 - 2.25 | 0.0686 - 1.00 -> TestNative
46 | 0.1281 - 1.83 | 0.0701 - 1.00 -> TestNative
48 | 0.1321 - 1.91 | 0.0693 - 1.00 -> TestNative
50 | 0.1278 - 1.85 | 0.0690 - 1.00 -> TestNative
52 | 0.1563 - 2.28 | 0.0686 - 1.00 -> TestNative
54 | 0.1269 - 1.83 | 0.0692 - 1.00 -> TestNative
56 | 0.1306 - 1.87 | 0.0697 - 1.00 -> TestNative
58 | 0.1270 - 1.84 | 0.0690 - 1.00 -> TestNative
60 | 0.1545 - 2.22 | 0.0695 - 1.00 -> TestNative


Медленнее чем полагал... Вот код теста

+
program MyPHPX;

{$R *.res}

uses
  math, windows, SysUtils, Utils, PHPLexer, StringCASE, ValueBox;

type
  TTestData = record
    ProcName: string;
    Times: array of Single;
    Diffs: array of Single;
  end;

  TMinData = record
    ProcName: string;
    BestTime: Single;
  end;

var
  TestArray: array of TTestData;
  BaseArray: array of TMinData;
  NumProcs: Integer = 0;

const
  MAXLEN = 30;

procedure TestFunction(Proc: Pointer; Name: string);
type
  TestProc = function: Boolean;
var
  MaxTime, MinTime: Single;
  Len, Round: Integer;
  a, b: string;
  TimeVal: Single;
  StartTime, StopTime: Int64;
  iCounterPerSec: Int64;
begin
  TestArray[NumProcs].ProcName := Name;
  MinTime := 90000;
  MaxTime := 0;
  SetLength(TestArray[NumProcs].Times, MAXLEN);
  SetLength(TestArray[NumProcs].Diffs, MAXLEN);
  if Length(BaseArray) = 0 then
    SetLength(BaseArray, MAXLEN);
  for Len := 0 to MAXLEN - 1 do
  begin
    a := StringOfChar('X', Succ(Len) * 2);
    b := Copy(a, 1);
    if QueryPerformanceCounter(StartTime) then
    begin
      for Round := 0 to 10000000 do
        TestProc(Proc)();
      if QueryPerformanceCounter(StopTime) and QueryPerformanceFrequency(iCounterPerSec) then
      begin
        TimeVal := (StopTime - StartTime) / iCounterPerSec;
        TestArray[NumProcs].Times[Len] := TimeVal;
        if (BaseArray[Len].BestTime = 0) or (BaseArray[Len].BestTime > TimeVal) then
        begin
          BaseArray[Len].ProcName := Name;
          BaseArray[Len].BestTime := TimeVal;
        end;
        if MaxTime < TimeVal then
          MaxTime := TimeVal;
        if MinTime > TimeVal then
          MinTime := TimeVal;
      end;
    end;
  end;
  Inc(NumProcs);
  Writeln(Format('[: %-20s Min: %.6f, Max: %.6f :]', [Name, MinTime, MaxTime]));
end;

procedure PrintResults;
var
  Idx: Integer;
  Len: Integer;
begin
  Writeln;
  for Len := 0 to MAXLEN - 1 do
  begin
    for Idx := 0 to NumProcs - 1 do
      TestArray[Idx].Diffs[Len] := TestArray[Idx].Times[Len] / BaseArray[Len].BestTime;
    Write((Succ(Len) * 2):2, ' | ');
    for Idx := 0 to NumProcs - 1 do
    begin
      if Idx > 0 then
        Write(' | ');
      Write(TestArray[Idx].Times[Len]:5:4, ' - ', TestArray[Idx].Diffs[Len]:3:2);
    end;
    Writeln(' -> ', BaseArray[Len].ProcName);
  end;
end;

procedure TestSBox();
var
  ss: TBox;
  I: Cardinal;
begin
  ss.SetInt64(10);
  for I := 0 to 5 do
    ss.AppendPlus(I);
end;

procedure TestNative();
var
  ss: Int64;
  I: Cardinal;
begin
  ss := 10;
  for I := 0 to 5 do
    Inc(ss, I);
end;

begin
  try
    System.SetMinimumBlockAlignment(mba16Byte);
    SetLength(TestArray, 2);
    TestFunction(@TestSBox, 'TestSBox');
    TestFunction(@TestNative, 'TestNative');
    PrintResults;


    Readln;
  except
    on e: Exception do
    begin
      Writeln(e.ClassName, ': ', e.Message);
      Readln;
    end;
  end;

end.
1 сен 17, 19:44    [20765638]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
SOFT FOR YOU
Member

Откуда:
Сообщений: 2418
Няшик,

Байтовый парсинг с таблицами есть?
Нет
JIT есть?
Нет
Бокс "на стеке" есть?
Нет
Умная конкатенация есть?
Нет

Что есть и что ты пытаешься нам доказать?
2 сен 17, 13:20    [20766668]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
[quot SOFT FOR YOU]
Байтовый парсинг с таблицами есть?
Нетquot]

=_= И с золотыми колошами.

SOFT FOR YOU
JIT есть?


Что бы полноценного - нету. Но есть умная компиляция, которая умеет находить неиспользуемый код. Удалять лишние переменные, и оптимизировать выражения.

Так же вставляет в упоминания переменных их адрес контейнера, если это не магия. Так же делает с функциями и константами до прочей приблуды с классами.


SOFT FOR YOU
Бокс "на стеке" есть?


Каком стеке ???? У меня структура такая

Структура функции {
- Аргументы функции { ... }
- Переменные которые должны быть созданы { ... }
- Деструктурор который удаляет локальные переменные Address
- Блок Аст дерева, который был получен после компиляции { ... }
}

Всё.

SOFT FOR YOU
Умная конкатенация есть?


Что в твоём понимание умная ? Бред несёшь ведь. Она и так умная - увеличиваем тогда, когда строка превышает порог контейнера.

Что значит "умная" ? ... То что я на 32 символа только увеличиваю ? Так это я значение осматривал, что бы не было просадок не на ком количестве. А делать Size это только вред. На память пофиг, если съест лишние 2 мб

SOFT FOR YOU

Что есть и что ты пытаешься нам доказать?


Я не пытаюсь, я показываю - что что бокс мой лучше любого что есть в Delphi.
2 сен 17, 13:45    [20766692]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
SOFT FOR YOU
Member

Откуда:
Сообщений: 2418
Няшик,

Что значит полноценный или не полноценный JIT?
JIT это способ исполнения команд. Ты интерпретируешь. Это не JIT
"На стеке" означает, что ты для коротких типов не дёргаешь менеджер памяти, а используешь юнион

Заколебал ты короче
Идею поддерживаю, делай, но реализация студенческая. Уровень поделки
2 сен 17, 19:20    [20767151]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
white_nigger
Member

Откуда: Тула
Сообщений: 1610
SOFT FOR YOU
Идею поддерживаю, делай, но реализация студенческая. Уровень поделки
Лучше бы доделал свою менеджер памяти и предложил человеку, может ему быстродействия с головой хватило бы
2 сен 17, 20:15    [20767208]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Ок, значит JIT есть. Я же писал, притом давно что файлы не компилируются по новой, если в них не было изменений. Я их сливаю в файлик, и потом исполняю напрямую.

Насчёт выделения для типов была вынужденной мерой, так как если бы там был не Pointer. То данные выравнивались в этом union что приводила к фатальным просадкам.

....

Менеджер я тестировал, он не быстрый из за огорода лесного. Та и тут люди есть, который могут и по лучше написать на том же SSE в мелких подробностях(hash,strcmp, memcopy,, ...). Но никогда почему то этого делать не станут - наверно не глупые потому что..
2 сен 17, 21:32    [20767300]     Ответить | Цитировать Сообщить модератору
 Re: goto address  [new]
Няшик
Member

Откуда: Екатеринбург
Сообщений: 728
Переписал немного в лучшую сторону функцию SSESameString2. И добавил комментарии

А так - же, добавил простую функцию CmpMem которая сверяет по 16 байт, по byte

SSESameString vs cmp
+
Debug 32Bit
[: SSESameString        Min: 0,053051, Max: 0,148990 :]
[: cmp                  Min: 0,052557, Max: 0,145203 :]

 2 | 0.05305 - 1.01 | 0.05256 - 1.00 -> cmp
 4 | 0.06450 - 1.05 | 0.06143 - 1.00 -> cmp
 6 | 0.06465 - 1.07 | 0.06033 - 1.00 -> cmp
 8 | 0.06417 - 1.14 | 0.05636 - 1.00 -> cmp
10 | 0.06442 - 1.14 | 0.05651 - 1.00 -> cmp
12 | 0.07647 - 1.19 | 0.06426 - 1.00 -> cmp
14 | 0.07675 - 1.06 | 0.07234 - 1.00 -> cmp
16 | 0.07229 - 1.12 | 0.06447 - 1.00 -> cmp
18 | 0.07258 - 1.13 | 0.06445 - 1.00 -> cmp
20 | 0.09119 - 1.07 | 0.08502 - 1.00 -> cmp
22 | 0.08862 - 1.05 | 0.08458 - 1.00 -> cmp
24 | 0.08432 - 1.00 | 0.08457 - 1.00 -> SSESameString
26 | 0.08510 - 1.11 | 0.07664 - 1.00 -> cmp
28 | 0.10101 - 1.05 | 0.09666 - 1.00 -> cmp
30 | 0.10071 - 1.04 | 0.09668 - 1.00 -> cmp
32 | 0.09632 - 1.09 | 0.08851 - 1.00 -> cmp
34 | 0.09703 - 1.09 | 0.08872 - 1.00 -> cmp
36 | 0.11292 - 1.04 | 0.10833 - 1.00 -> cmp
38 | 0.11270 - 1.04 | 0.10881 - 1.00 -> cmp
40 | 0.10865 - 1.00 | 0.10823 - 1.00 -> cmp
42 | 0.10841 - 1.07 | 0.10130 - 1.00 -> cmp
44 | 0.12505 - 1.04 | 0.12042 - 1.00 -> cmp
46 | 0.12527 - 1.04 | 0.12049 - 1.00 -> cmp
48 | 0.12225 - 1.09 | 0.11257 - 1.00 -> cmp
50 | 0.12060 - 1.07 | 0.11261 - 1.00 -> cmp
52 | 0.13667 - 1.03 | 0.13281 - 1.00 -> cmp
54 | 0.13712 - 1.02 | 0.13442 - 1.00 -> cmp
56 | 0.13533 - 1.02 | 0.13278 - 1.00 -> cmp
58 | 0.13296 - 1.06 | 0.12582 - 1.00 -> cmp
60 | 0.14899 - 1.03 | 0.14520 - 1.00 -> cmp


CmpMem
+
Debug 32Bit
[: CmpMem               Min: 0,040282, Max: 0,128543 :]
[: cmp                  Min: 0,052786, Max: 0,140978 :]

 2 | 0.04081 - 1.00 | 0.05279 - 1.29 -> CmpMem
 4 | 0.04520 - 1.00 | 0.05643 - 1.25 -> CmpMem
 6 | 0.04521 - 1.00 | 0.05630 - 1.25 -> CmpMem
 8 | 0.04042 - 1.00 | 0.05613 - 1.39 -> CmpMem
10 | 0.04028 - 1.00 | 0.05684 - 1.41 -> CmpMem
12 | 0.05887 - 1.00 | 0.06921 - 1.18 -> CmpMem
14 | 0.05854 - 1.00 | 0.06986 - 1.19 -> CmpMem
16 | 0.05235 - 1.00 | 0.06438 - 1.23 -> CmpMem
18 | 0.05263 - 1.00 | 0.06423 - 1.22 -> CmpMem
20 | 0.06828 - 1.00 | 0.08041 - 1.18 -> CmpMem
22 | 0.06836 - 1.00 | 0.08085 - 1.18 -> CmpMem
24 | 0.06471 - 1.00 | 0.08072 - 1.25 -> CmpMem
26 | 0.06434 - 1.00 | 0.07704 - 1.20 -> CmpMem
28 | 0.08066 - 1.00 | 0.09259 - 1.15 -> CmpMem
30 | 0.08047 - 1.00 | 0.09250 - 1.15 -> CmpMem
32 | 0.07689 - 1.00 | 0.09053 - 1.18 -> CmpMem
34 | 0.07627 - 1.00 | 0.08874 - 1.16 -> CmpMem
36 | 0.09222 - 1.00 | 0.10653 - 1.16 -> CmpMem
38 | 0.09254 - 1.00 | 0.10492 - 1.13 -> CmpMem
40 | 0.08856 - 1.00 | 0.10466 - 1.18 -> CmpMem
42 | 0.08875 - 1.00 | 0.10081 - 1.14 -> CmpMem
44 | 0.10679 - 1.00 | 0.11722 - 1.10 -> CmpMem
46 | 0.10444 - 1.00 | 0.11705 - 1.12 -> CmpMem
48 | 0.10119 - 1.00 | 0.11270 - 1.11 -> CmpMem
50 | 0.10076 - 1.00 | 0.11280 - 1.12 -> CmpMem
52 | 0.11684 - 1.00 | 0.12947 - 1.11 -> CmpMem
54 | 0.11767 - 1.00 | 0.12886 - 1.10 -> CmpMem
56 | 0.11410 - 1.00 | 0.12832 - 1.12 -> CmpMem
58 | 0.11252 - 1.00 | 0.12543 - 1.11 -> CmpMem
60 | 0.12854 - 1.00 | 0.14098 - 1.10 -> CmpMem



Сам код.
+
program StrTest;

{$APPTYPE CONSOLE}

uses
  math, windows, SysUtils;

{ ---===[: Код для проведения тестирования :]===--- }

type
  TTestData = record
    ProcName: string;
    Times: array of Single;
    Diffs: array of Single;
  end;

  TMinData = record
    ProcName: string;
    BestTime: Single;
  end;

var
  TestArray: array of TTestData;
  BaseArray: array of TMinData;
  NumProcs: integer = 0;

const
  MAXLEN = 30;

procedure TestFunction(Proc: Pointer; Name: string; mem: Boolean = false);
type
  TestProc = function(A, B: Pointer): Boolean;
  TestProc2 = function(A, B: Pointer; len: integer): Boolean;
var
  MaxTime, MinTime: Single;
  len, Round: integer;
  A, B: string;
  TimeVal: Single;
  StartTime, StopTime: Int64;
  iCounterPerSec: Int64;
  ken, ken2: integer;
begin
  TestArray[NumProcs].ProcName := Name;
  MinTime := 90000;
  MaxTime := 0;
  SetLength(TestArray[NumProcs].Times, MAXLEN);
  SetLength(TestArray[NumProcs].Diffs, MAXLEN);
  if Length(BaseArray) = 0 then
    SetLength(BaseArray, MAXLEN);
  for len := 0 to MAXLEN - 1 do
  begin
    ken := Succ(len) * 2;
    ken2 := ken * 2;
    A := StringOfChar('X', ken);
    B := Copy(A, 1);
    if QueryPerformanceCounter(StartTime) then
    begin
      if mem then
      begin
        for Round := 0 to 10000000 do
          if not TestProc2(Proc)(Pointer(A), Pointer(B), ken2) then
          begin
            Writeln('Error at string lengh ', ken, ' ', A);
            Break;
          end;
      end
      else
      begin
        for Round := 0 to 10000000 do
          if not TestProc(Proc)(Pointer(A), Pointer(B)) then
          begin
            Writeln('Error at string lengh ', ken, ' ', A);
            Break;
          end;
      end;
      if QueryPerformanceCounter(StopTime) and QueryPerformanceFrequency(iCounterPerSec) then
      begin
        TimeVal := (StopTime - StartTime) / iCounterPerSec;
        TestArray[NumProcs].Times[len] := TimeVal;
        if (BaseArray[len].BestTime = 0) or (BaseArray[len].BestTime > TimeVal) then
        begin
          BaseArray[len].ProcName := Name;
          BaseArray[len].BestTime := TimeVal;
        end;
        if MaxTime < TimeVal then
          MaxTime := TimeVal;
        if MinTime > TimeVal then
          MinTime := TimeVal;
      end;
    end;
  end;
  inc(NumProcs);
  Writeln(Format('[: %-20s Min: %.6f, Max: %.6f :]', [Name, MinTime, MaxTime]));
end;

procedure PrintResults;
var
  Idx: integer;
  len: integer;
begin
  Writeln;
  for len := 0 to MAXLEN - 1 do
  begin
    for Idx := 0 to NumProcs - 1 do
      TestArray[Idx].Diffs[len] := TestArray[Idx].Times[len] / BaseArray[len].BestTime;
    Write((Succ(len) * 2):2, ' | ');
    for Idx := 0 to NumProcs - 1 do
    begin
      if Idx > 0 then
        Write(' | ');
      Write(TestArray[Idx].Times[len]:5:5, ' - ', TestArray[Idx].Diffs[len]:3:2);
    end;
    Writeln(' -> ', BaseArray[len].ProcName);
  end;
end;

function SSESameString(const A, B: string): Boolean;
// in: eax - A, edx - B; out: eax - Result
asm
  push    ebx
  cmp     edx, eax
  jz      @@true

  test    eax, eax
  jz      @@exit // eax = 0 -> result = false

  test    edx, edx
  jz      @@false

  mov     ecx, dword ptr [eax - 4]
  cmp     ecx, dword ptr [edx - 4]
  jnz     @@false
  sub     edx, eax
  // -- unaligned 2x character test
  mov     ebx, [eax]
  xor     ebx, [eax + edx]
  jnz     @@false
  dec     ecx
  jz      @@true
  dec     ecx
  jz      @@true
  lea     eax, [eax + 4]
  // -- aligned 8x character loop
@@l8c:
  movdqa  xmm1, dqword ptr [eax]
  pcmpeqw xmm1, dqword ptr [eax + edx]
  pmovmskb ebx, xmm1
  cmp     ebx, $FFFF
  jnz     @@tail
  lea     eax, [eax + $10]
  sub     ecx, 8
  ja      @@l8c
@@true:
  xor     eax, eax
  setz    al
  pop     ebx
  ret
@@false:
  xor     eax, eax
  pop     ebx
  ret
  // -- check partial mask
@@mask:
  dw $000F, $003F, $00FF, $03FF, $0FFF, $3FFF
@@tail:
  xor     eax, eax
  cmp     ecx, 7
  jae     @@exit
  movzx   edx, word ptr [@@mask + ecx * 2 - 2]
  and     ebx, edx
  cmp     ebx, edx
  setz    al
@@exit:
  pop     ebx
end;

function cmp(const Str, Str2: string): Boolean;
asm
  push    ebx
  cmp     edx, eax // Str = Str2 to true
  jz      @@true
  test    eax, eax // not eax to false
  jz      @@false
  test    edx, edx // not edx to false
  jz      @@false
  mov ecx, DWORD PTR [eax-4]  // LenStr <> LenStr2 to false
  cmp DWORD PTR [edx-4], ecx
  jne @@false
  sub edx, eax  // Str2 := Str2 - Str;
  mov     ebx, [eax]   // Cmp 4 byte
  xor     ebx, [eax + edx]
  jnz     @@false
  sub ecx, 2
  jbe      @@true
  lea     eax, [eax + 4] // Next 4 byte
@@To1:
  movdqa xmm1, DQWORD PTR [eax]  // _mm_load_si128(eax)
  pcmpeqw xmm1, DQWORD PTR [eax+edx] // _mm_cmpeq_epi16(xmm1, _mm_load_si128 :: eax+edx)
  pmovmskb ebx, xmm1 // _mm_movemask_epi8(xmm1)
  cmp ebx, 65535  // ebx <> 65535
  jne @@Final  // to goto Final
  add eax, 16 // To next 16 byte
  sub ecx, 8  // dec(ecx - (16 / SizeOf(WideChar)))
  ja @@To1 // ecx > 0 to goto  To1

@@true: // Result true
  mov eax, 1
  pop ebx
  ret

@@false:  // Result false
  mov eax, 0
  pop ebx
  ret

@@Final:
  cmp     ecx, 7
  jae     @@false
  movzx ecx, word ptr @@mask[ecx * 2 - 2]  // mask[len]
  and ebx, ecx  // ecx & ecx
  cmp ebx, ecx  // ebx = ecx
  // return ((ebx & mask[len]) == mask[len])
  sete al
  pop ebx
  ret
@@mask:
  dw $000F, $003F, $00FF, $03FF, $0FFF, $3FFF
end;

function CmpMem(const P1, P2: Pointer; len: integer): Boolean;
asm
  push    ebx
  sub edx, eax
  mov     ebx, [eax]
  xor     ebx, [eax + edx]
  jnz     @@false
  sub ecx, 4
  jbe      @@true
  lea     eax, [eax + 4]
@@To1:
  movdqa xmm1, DQWORD PTR [eax]
  pcmpeqw xmm1, DQWORD PTR [eax+edx]
  pmovmskb ebx, xmm1
  cmp ebx, 65535
  jne @@Final
  add eax, 16
  sub ecx, 16
  ja @@To1

@@true:
  mov eax, 1
  pop ebx
  ret

@@false:
  mov eax, 0
  pop ebx
  ret

@@Final:
  cmp     ecx, 15
  jae     @@false
  movzx ecx, word ptr @@mask[ecx * 2 - 2]  // mask[len]
  and ebx, ecx
  cmp ebx, ecx
  sete al
  pop ebx
  ret
@@mask:
  dw 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383
end;

var
  Str, Str2: string;

begin
{$IFNDEF DEBUG}
  Write('Release');
{$ELSE}
  Write('Debug');
{$ENDIF}
{$IF Defined(CPUX64) or Defined(CPUARM64)}
  Writeln(' 64bit');
{$ELSE}
  Writeln(' 32Bit');
{$IFEND}
  try
    System.SetMinimumBlockAlignment(mba16Byte);
    SetLength(TestArray, 2);
    // TestFunction(@CmpMem, 'CmpMem', true);
    TestFunction(@SSESameString, 'SSESameString');
    TestFunction(@cmp, 'cmp');
    PrintResults;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




Кстати, вот решение самого первого моего вопроса!

+
Картинка с другого сайта.
25 сен 17, 23:38    [20822185]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 .. 16 17 18 19 20 21 22 [23] 24 25   вперед  Ctrl
Все форумы / Delphi Ответить