delphi4arab منتديات دلفي للعرب
دالة FastCharPos - نسخة قابلة للطباعة

+- delphi4arab منتديات دلفي للعرب (https://delphi4arab.net/forum)
+-- قسم : منتديات دلفي للعرب التعليمية (https://delphi4arab.net/forum/forumdisplay.php?fid=3)
+--- قسم : دروس دلفي للمبتدئين (https://delphi4arab.net/forum/forumdisplay.php?fid=13)
+--- الموضوع : دالة FastCharPos (/showthread.php?tid=5019)



دالة FastCharPos - SMP3 - 15-03-2013

السلام عليكم ورحمة الله وبركاته
اليوم وجدت بعض الوقت , لذلك أحببت أن أتسلى قليلا مع الأسمبلي Smile
هذه دالة تعمل على جلب موقع char في سلسلة نصية :
البرامتر :
Str : السلسلة النصية التي تحتوي على المحرف المراد البحث عن مكانه
chr : المحرف الذي تريد البحث عنه ضمن السلسلة النصية
IgnoreCase :حساسية الأحرف , تكون True ان لم ترد التفريق بين المحرف الكبير و الصغير
مثلا : m=M , تكون False اذا أردت التفريق بين المحرف الكبير و الصغير
offset : مكان بدأ عمل الدالة في السلسلة النصية
Return Value :
اذا نجحت الدالة ستعود بقيمة لمكان تواجد المحرف في السلسلة النصية
اذا لم تنجح الدالة أو لم يتم العثور على المحرف فتعود بصفر

PHP كود :
///    <summary>
  ///      FastCharPos function developed by SMP3
  ///    </summary>
  ///    <param name="Str">
  ///      Is a*string* that contains the sequence to be found .
  ///    </param>
  ///    <param name="chr">
  ///      Is a character to be searched.
  ///    </param>
  ///    <param name="IgnoreCase">
  ///      Set to True if you wana ignore case
  /// <para> <c> Ex: </c> </para>
  /// <para> IF IgnoreCase is True  : 'M' and 'm' are the same char .</para>
  ///    <para> IF IgnoreCase is False : 'M' and 'm' are not the same char.</para>
  ///    </param>
  ///    <param name="offset">
  ///      Start from specific place or char .
  ///    </param>
  ///    <returns>
  ///      <para>
  ///        If the function succeeds, the return value is the char index in str.
  ///      </para>
  ///      <para>
  ///        If the function fails, the return value is zero.
  ///      </para>
  ///    </returns>
 
function TForm1.FastCharPos(Str:String;const chr :char;const IgnoreCase:BOOL;const offset :integer=0 ):Integer;assembler;
 
asm
    PUSH EBX
    PUSH ESI
    MOV ESI
,DWORD PTR SS:[ebp+7]
    
ROR ESI,8
    PUSH ESI
  
{$IFDEF UNICODE}
    
IMUL ESI,2
  
{$ENDIF}
    
ADD EAX,ESI
    POP ESI
    
XOR EDI,EDI
    TEST EAX
,EAX
    JE 
@RFALSE
 
@LOOP:
    
MOV BL,BYTE PTR DS:[EAX]
    
CMP BL,DL
    JE 
@EQU
    TEST ECX
,ECX
    JNE 
@IGNORECASE
    JMP 
@CASE
 @
IGNORECASE:
    
MOV BH,BL
    CMP BH
,DL
    JLE 
@LESS
    SUB BH
,DL
    JMP 
@GREAT
 
@LESS:
    
PUSH EDX
    SUB DL
,BH
    MOV BH
,DL
    POP EDX
 
@GREAT:
    
CMP BH,32
    JE 
@EQU
 
@CASE:
    
INC ESI
  
{$IFDEF UNICODE}
    
ADD EAX,2
  
{$ELSE}
    
INC EAX
  
{$ENDIF}
    
TEST BL,BL
    JNE 
@LOOP
    JMP 
@RFALSE
 
@EQU:
    
MOV EAX,ESI
    JMP 
@FIN
 
@RFALSE:
    
MOV EAX ,-1
 
@FIN:
    
INC EAX
    POP ESI
    POP EBX
 end
; 

مثال للاستعمال :


PHP كود :
ShowMessage(IntToStr(FastCharPos('Assembly','S',True)));
ShowMessage(IntToStr(FastCharPos('Assembly','S',False)));
ShowMessage(IntToStr(FastCharPos('Assembly','s',False,2))); 



دالة FastCharPos - syscall - 16-03-2013

وعليكم السلام

طيب ايهما اسرع الدالة التي وضعتها ام التي صنعها Peter Morris في وحدته FastStrings.pas

PHP كود :
//NOTE : FastCharPos and FastCharPosNoCase do not require you to pass the length
// of the string, this was only done in FastPos and FastPosNoCase because
// they are used by FastReplace many times over, thus saving a LENGTH()
// operation each time. I can't see you using these two routines for the
// same purposes so I didn't do that this time !
function FastCharPos(const aSource : string; const C: Char; StartPos : Integer) : Integer;
var
L : Integer;
begin
//If this assert failed, it is because you passed 0 for StartPos, lowest value is 1 !!
Assert(StartPos > 0);

Result := 0;
L := Length(aSource);
if 
L = 0 then exit;
if 
StartPos > L then exit;
Dec(StartPos);
asm
PUSH EDI 
//Preserve this register

mov EDI, aSource //Point EDI at aSource
add EDI, StartPos
mov ECX
, L //Make a note of how many chars to search through
sub ECX, StartPos
mov AL
, C //and which char we want
@Loop:
cmp Al, [EDI] //compare it against the SourceString
jz @Found
inc EDI
dec ECX
jnz 
@Loop
jmp 
@NotFound
@Found:
sub EDI, aSource //EDI has been incremented, so EDI-OrigAdress = Char pos !
inc EDI
mov Result
, EDI
@NotFound:

POP EDI
end
;
end;

function 
FastCharPosNoCase(const aSource : string; C: Char; StartPos : Integer) : Integer;
var
L : Integer;
begin
Result 
:= 0;
L := Length(aSource);
if 
L = 0 then exit;
if 
StartPos > L then exit;
Dec(StartPos);
if 
StartPos < 0 then StartPos := 0;

asm
PUSH EDI 
//Preserve this register
PUSH EBX
mov EDX
, GUpcaseLUT

mov EDI
, aSource //Point EDI at aSource
add EDI, StartPos
mov ECX
, L //Make a note of how many chars to search through
sub ECX, StartPos

xor EBX, EBX
mov BL
, C
mov AL
, [EDX+EBX]
@
Loop:
mov BL, [EDI]
inc EDI
cmp Al
, [EDX+EBX]
jz @Found
dec ECX
jnz 
@Loop
jmp 
@NotFound
@Found:
sub EDI, aSource //EDI has been incremented, so EDI-OrigAdress = Char pos !
mov Result, EDI
@NotFound:

POP EBX
POP EDI
end
;
end; 

وهذا رابط الوحده بشكلها الكامل
http://code.google.com/p/ljbvcltools/source/browse/trunk/%E8%B6%85%E7%BA%A7%E5%87%BD%E6%95%B0%E4%BB%A3%E7%A0%81%E5%BA%93SRTL/FastStrings.pas?spec=svn11&r=11


دالة FastCharPos - SMP3 - 16-03-2013

السلام عليكم ورحمة الله وبركاته
أولا شكرا على مشاركتك أخي syscall Smile
في الحقيقة لن أستطيع الاجابة عن سؤالك .. لماذا ؟ لعدة أسباب
أولا الدالتين التي وضعتهما لا تدعمان اليونيكود على غرار الدالة التي كتبتها فهي تدعم اليونيكود
للدالتين برامتر مختلفة ..

الدالة التي كتبتها تعمل عمل الدالتين FastCharPos +FastCharPosNoCase في آن واحد .. + مبرمجة كامل بالأسمبلي => Full Optimization