На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Модификачия функции POSEx
    Здраствуйте, нашё модификацию функции POS, называется PosEx.
    Говорят что работает быстрее старой плюс есть возможность указывать на начало позиции поиска, но есть одно но
    эта функция игнорирует Регистр букв.

    Помогите модифицировать данную функцию так что бы была опциональная возможность поиска с учетом регистра. примерно
    так function PosEx2(const substr : AnsiString; const s : AnsiString; StartPos : Cardinal; CaseSense : Boolean) : Integer;

    ExpandedWrap disabled
      function PosEx(const substr : AnsiString; const s : AnsiString; StartPos : Cardinal) : Integer;
      type
        StrRec = packed record
          allocSiz: Longint;
          refCnt: Longint;
          length: Longint;
        end;
      const
        skew = sizeof(StrRec);
      asm
      {     ->EAX     Pointer to substr               }
      {       EDX     Pointer to string               }
      {     <-EAX     Position of substr in s or 0    }
              TEST    EAX,EAX
              JE      @@noWork
       
              TEST    EDX,EDX
              JE      @@stringEmpty
       
              PUSH    EBX
              PUSH    ESI
              PUSH    EDI
       
              MOV     ESI,EAX                         { Point ESI to substr           }
              MOV     EDI,EDX                         { Point EDI to s                }
       
              MOV     EAX,ECX
              MOV     ECX,[EDI-skew].StrRec.length    { ECX = Length(s)               }
              ADD     EDI,EAX
              SUB     ECX,EAX
       
              PUSH    EDI                             { remember s position to calculate index        }
       
              MOV     EDX,[ESI-skew].StrRec.length    { EDX = Length(substr)          }
       
              DEC     EDX                             { EDX = Length(substr) - 1              }
              JS      @@fail                          { < 0 ? return 0                        }
              MOV     AL,[ESI]                        { AL = first char of substr             }
              INC     ESI                             { Point ESI to 2'nd char of substr      }
       
              SUB     ECX,EDX                         { #positions in s to look at    }
                                                      { = Length(s) - Length(substr) + 1      }
              JLE     @@fail
      @@loop:
              REPNE   SCASB
              JNE     @@fail
              MOV     EBX,ECX                         { save outer loop counter               }
              PUSH    ESI                             { save outer loop substr pointer        }
              PUSH    EDI                             { save outer loop s pointer             }
       
              MOV     ECX,EDX
              REPE    CMPSB
              POP     EDI                             { restore outer loop s pointer  }
              POP     ESI                             { restore outer loop substr pointer     }
              JE      @@found
              MOV     ECX,EBX                         { restore outer loop counter    }
              JMP     @@loop
       
      @@fail:
              POP     EDX                             { get rid of saved s pointer    }
              XOR     EAX,EAX
              JMP     @@exit
       
      @@stringEmpty:
              XOR     EAX,EAX
              JMP     @@noWork
       
      @@found:
              POP     EDX                             { restore pointer to first char of s    }
              MOV     EAX,EDI                         { EDI points of char after match        }
              SUB     EAX,EDX                         { the difference is the correct index   }
      @@exit:
              POP     EDI
              POP     ESI
              POP     EBX
      @@noWork:
      end;
    Сообщение отредактировано: Ableton -
      из d2006
      ExpandedWrap disabled
        function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer;
        asm
               test  eax, eax
               jz    @Nil
               test  edx, edx
               jz    @Nil
               dec   ecx
               jl    @Nil
         
               push  esi
               push  ebx
         
               mov   esi, [edx-4]  //Length(Str)
               mov   ebx, [eax-4]  //Length(Substr)
               sub   esi, ecx      //effective length of Str
               add   edx, ecx      //addr of the first char at starting position
               cmp   esi, ebx
               jl    @Past         //jump if EffectiveLength(Str)<Length(Substr)
               test  ebx, ebx
               jle   @Past         //jump if Length(Substr)<=0
         
               add   esp, -12
               add   ebx, -1       //Length(Substr)-1
               add   esi, edx      //addr of the terminator
               add   edx, ebx      //addr of the last char at starting position
               mov   [esp+8], esi  //save addr of the terminator
               add   eax, ebx      //addr of the last char of Substr
               sub   ecx, edx      //-@Str[Length(Substr)]
               neg   ebx           //-(Length(Substr)-1)
               mov   [esp+4], ecx  //save -@Str[Length(Substr)]
               mov   [esp], ebx    //save -(Length(Substr)-1)
               movzx ecx, byte ptr [eax] //the last char of Substr
         
        @Loop:
               cmp   cl, [edx]
               jz    @Test0
        @AfterTest0:
               cmp   cl, [edx+1]
               jz    @TestT
        @AfterTestT:
               add   edx, 4
               cmp   edx, [esp+8]
               jb   @Continue
        @EndLoop:
               add   edx, -2
               cmp   edx, [esp+8]
               jb    @Loop
        @Exit:
               add   esp, 12
        @Past:
               pop   ebx
               pop   esi
        @Nil:
               xor   eax, eax
               ret
        @Continue:
               cmp   cl, [edx-2]
               jz    @Test2
               cmp   cl, [edx-1]
               jnz   @Loop
        @Test1:
               add   edx,  1
        @Test2:
               add   edx, -2
        @Test0:
               add   edx, -1
        @TestT:
               mov   esi, [esp]
               test  esi, esi
               jz    @Found
        @String:
               movzx ebx, word ptr [esi+eax]
               cmp   bx, word ptr [esi+edx+1]
               jnz   @AfterTestT
               cmp   esi, -2
               jge   @Found
               movzx ebx, word ptr [esi+eax+2]
               cmp   bx, word ptr [esi+edx+3]
               jnz   @AfterTestT
               add   esi, 4
               jl    @String
        @Found:
               mov   eax, [esp+4]
               add   edx, 2
         
               cmp   edx, [esp+8]
               ja    @Exit
         
               add   esp, 12
               add   eax, edx
               pop   ebx
               pop   esi
        end;
        Цитата Ableton @
        Говорят что работает быстрее старой плюс есть возможность указывать на начало позиции поиска, но есть одно но
        эта функция игнорирует Регистр букв.

        Не игнорирует, а как раз при сравнении учитывают регистр букв!
        Самый простой способ сделать так, чтобы не учитывали (при сравнении), это:
        ExpandedWrap disabled
          p := Pos(AnsiLowerCase(substr), AnsiLowerCase(s));
          p := PosEx(AnsiLowerCase(substr), AnsiLowerCase(s), startPos);

        Т.е., например, можно сделать такую функцию:
        ExpandedWrap disabled
          function PosEx(const substr, s: string; startPos: integer = 1; caseSense: boolean=true): integer;
          begin
            if caseSense then
              result := SysUtils.PosEx(substr, s, startPos)
            else
              result := SysUtils.PosEx(AnsiLowerCase(substr), AnsiLowerCase(s), startPos);
          end;

        Функция AnsiLowerCase понижает регистр букв, учитывая язык. Скорость такой функии можно поднять. если составить таблицу трансляции, и использовать её вместо вызовов AnsiLowerCase:
        ExpandedWrap disabled
          function str2lower_init(s: string): string; forward;
          var
            str2lower_func: pointer = @str2lower_init;
            str2lower_xlat: PChar; // таблица трансляции
          function str2lower_code(s: string): string;
          asm
              mov   ecx,edx
              mov   edx,str2lower_xlat
              jmp   StrXLat
          end;
          function InitStr2Lower: boolean;
          var
            lock: TRTLCriticalSection;
            i: integer;
            p: pbyte;
          begin
            InitializeCriticalSection(lock);
            result := false;
            if TryEnterCriticalSection(lock) then try
              GetMem(str2lower_xlat, 256);
              p := str2lower_xlat;
              for i := 0 to 255 do begin
                p^ := i;
                inc(p);
              end;
              CharLowerBuff(str2lower_xlat, 256); // заполняем таблицу трансляции
              str2lower_func := @str2lower_code;
              result := true;
            except
              LeaveCriticalSection(lock);
            end;
            DeleteCriticalSection(lock);
          end;
          function str2lower(s: string): string;
          asm
              jmp str2lower_func
          end;
          function str2lower_init(s: string): string;
          begin
            if InitStr2Lower then
              result := str2lower(s) else
              result := AnsiLowerCase(s);
          end;

        По тестам str2lower опережает AnsiLowerCase по скорости на 100-300%.
        Сообщение отредактировано: ors_archangel -
          user posted image
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,0296 ]   [ 16 queries used ]   [ Generated: 20.04.24, 08:18 GMT ]