2016-07-28 90 views
1

我想做一个地址簿的应用程序,需要添加搜索功能。 我希望搜索功能可以支持字符串匹配,并且我在NSString类中找到[NSString containString:]这个函数。 为了高效,我想使用一个良好的字符串匹配算法来实现它,就像KMP一样。所以我想知道在这个函数中使用了什么算法。我在哪里可以查看NSString函数的源代码?ObjC中的[NSString containsString:]这个函数使用了什么算法?

Thx。

回答

1

的组件如下:

Foundation`-[NSString containsString:]: 
-> 0x10a128954 <+0>: pushq %rbp 
    0x10a128955 <+1>: movq %rsp, %rbp 
    0x10a128958 <+4>: pushq %r15 
    0x10a12895a <+6>: pushq %r14 
    0x10a12895c <+8>: pushq %rbx 
    0x10a12895d <+9>: pushq %rax 
    0x10a12895e <+10>: movq %rdx, %r14 
    0x10a128961 <+13>: movq %rdi, %rbx 
    0x10a128964 <+16>: movq 0x1836d5(%rip), %rsi  ; "length" 
    0x10a12896b <+23>: movq 0x19ddee(%rip), %r15  ; (void *)0x000000010a4bb800: objc_msgSend 
    0x10a128972 <+30>: callq *%r15 
    0x10a128975 <+33>: movq 0x185dc4(%rip), %rsi  ; "rangeOfString:options:range:locale:" 
    0x10a12897c <+40>: movq $0x0, (%rsp) 
    0x10a128984 <+48>: xorl %ecx, %ecx 
    0x10a128986 <+50>: xorl %r8d, %r8d 
    0x10a128989 <+53>: movq %rbx, %rdi 
    0x10a12898c <+56>: movq %r14, %rdx 
    0x10a12898f <+59>: movq %rax, %r9 
    0x10a128992 <+62>: callq *%r15 
    0x10a128995 <+65>: movabsq $0x7fffffffffffffff, %rcx ; imm = 0x7FFFFFFFFFFFFFFF 
    0x10a12899f <+75>: cmpq %rcx, %rax 
    0x10a1289a2 <+78>: setne %al 
    0x10a1289a5 <+81>: addq $0x8, %rsp 
    0x10a1289a9 <+85>: popq %rbx 
    0x10a1289aa <+86>: popq %r14 
    0x10a1289ac <+88>: popq %r15 
    0x10a1289ae <+90>: popq %rbp 
    0x10a1289af <+91>: retq 

它本质上是下面的算法:

- (bool)containsString:(NSString *)stringToFind { 

    if (stringToFind && stringToFind.length < self) { 
     return (typeof(NSNotFound))[self rangeOfString:stringToFind options:NSLiteralSearch range:NSMakeRange(0, self.length) locale:nil].location != NSNotFound; 
    } 
    return false; 
} 

P.S.它不检查字符串是否为零或检查其长度。它确切地:

- (bool)containsString:(NSString *)stringToFind { 

    return (typeof(NSNotFound))[self rangeOfString:stringToFind options:NSLiteralSearch range:NSMakeRange(0, self.length) locale:nil].location != NSNotFound; 
} 

没有安全检查。我不知道为什么我决定添加检查,但瓦特/电子..

字符串的范围有以下组件:

Foundation`-[NSString rangeOfString:options:range:locale:]: 
-> 0x10a031cfd <+0>: pushq %rbp 
    0x10a031cfe <+1>: movq %rsp, %rbp 
    0x10a031d01 <+4>: pushq %r15 
    0x10a031d03 <+6>: pushq %r14 
    0x10a031d05 <+8>: pushq %r13 
    0x10a031d07 <+10>: pushq %r12 
    0x10a031d09 <+12>: pushq %rbx 
    0x10a031d0a <+13>: subq $0x48, %rsp 
    0x10a031d0e <+17>: movq %r9, %r15 
    0x10a031d11 <+20>: movq %r8, %r14 
    0x10a031d14 <+23>: movq %rcx, -0x40(%rbp) 
    0x10a031d18 <+27>: movq %rdx, %r13 
    0x10a031d1b <+30>: movq %rsi, -0x48(%rbp) 
    0x10a031d1f <+34>: movq %rdi, %r12 
    0x10a031d22 <+37>: movq 0x27a317(%rip), %rsi  ; "length" 
    0x10a031d29 <+44>: movq 0x294a30(%rip), %rbx  ; (void *)0x000000010a4bb800: objc_msgSend 
    0x10a031d30 <+51>: movq %r13, %rdi 
    0x10a031d33 <+54>: callq *%rbx 
    0x10a031d35 <+56>: movq %rax, -0x50(%rbp) 
    0x10a031d39 <+60>: movq 0x27a300(%rip), %rsi  ; "length" 
    0x10a031d40 <+67>: movq %r12, %rdi 
    0x10a031d43 <+70>: callq *%rbx 
    0x10a031d45 <+72>: movq %rax, %rbx 
    0x10a031d48 <+75>: subq %r15, %rax 
    0x10a031d4b <+78>: jb  0x10a031d56    ; <+89> 
    0x10a031d4d <+80>: cmpq %r14, %rax 
    0x10a031d50 <+83>: jae 0x10a031e07    ; <+266> 
    0x10a031d56 <+89>: callq 0x10a239912    ; symbol stub for: __CFStringNoteErrors 
    0x10a031d5b <+94>: testb %al, %al 
    0x10a031d5d <+96>: je  0x10a031e07    ; <+266> 
    0x10a031d63 <+102>: movl $0x6, %edi 
    0x10a031d68 <+107>: callq 0x10a2396b4    ; symbol stub for: _CFExecutableLinkedOnOrAfter 
    0x10a031d6d <+112>: testb %al, %al 
    0x10a031d6f <+114>: je  0x10a031dc5    ; <+200> 
    0x10a031d71 <+116>: movq 0x281420(%rip), %rax  ; (void *)0x000000010ac5a358: NSException 
    0x10a031d78 <+123>: movq %rax, -0x58(%rbp) 
    0x10a031d7c <+127>: movq 0x294325(%rip), %rax  ; (void *)0x000000010ac74b38: NSRangeException 
    0x10a031d83 <+134>: movq (%rax), %rax 
    0x10a031d86 <+137>: movq %rax, -0x60(%rbp) 
    0x10a031d8a <+141>: movq %r12, %rdi 
    0x10a031d8d <+144>: movq -0x48(%rbp), %rsi 
    0x10a031d91 <+148>: callq 0x10a11f7e0    ; _NSMethodExceptionProem 
    0x10a031d96 <+153>: movq %rax, %r8 
    0x10a031d99 <+156>: movq 0x27a288(%rip), %rsi  ; "raise:format:" 
    0x10a031da0 <+163>: movq %rbx, 0x8(%rsp) 
    0x10a031da5 <+168>: movq %r15, (%rsp) 
    0x10a031da9 <+172>: leaq 0x2a4e40(%rip), %rcx  ; @"%@: Range {%lu, %lu} out of bounds; string length %lu" 
    0x10a031db0 <+179>: xorl %eax, %eax 
    0x10a031db2 <+181>: movq -0x58(%rbp), %rdi 
    0x10a031db6 <+185>: movq -0x60(%rbp), %rdx 
    0x10a031dba <+189>: movq %r14, %r9 
    0x10a031dbd <+192>: callq *0x29499d(%rip)   ; (void *)0x000000010a4bb800: objc_msgSend 
    0x10a031dc3 <+198>: jmp 0x10a031e07    ; <+266> 
    0x10a031dc5 <+200>: movb 0x29326d(%rip), %al  ; rangeOfString:options:range:locale:.warnonce 
    0x10a031dcb <+206>: testb %al, %al 
    0x10a031dcd <+208>: jne 0x10a031e07    ; <+266> 
    0x10a031dcf <+210>: movb $0x1, 0x293262(%rip)  ; compare:options:range:locale:.localeClass + 7 
    0x10a031dd6 <+217>: movq %r12, %rdi 
    0x10a031dd9 <+220>: movq -0x48(%rbp), %rsi 
    0x10a031ddd <+224>: callq 0x10a11f7e0    ; _NSMethodExceptionProem 
    0x10a031de2 <+229>: movq %rax, %rbx 
    0x10a031de5 <+232>: movq %r14, %rdi 
    0x10a031de8 <+235>: movq %r15, %rsi 
    0x10a031deb <+238>: callq 0x10a1212f0    ; NSStringFromRange 
    0x10a031df0 <+243>: movq %rax, %rcx 
    0x10a031df3 <+246>: leaq 0x2a4e36(%rip), %rdi  ; @"*** %@: Invalid range %@; this will become an exception for apps linked on SnowLeopard. Warning shown once per app execution." 
    0x10a031dfa <+253>: xorl %eax, %eax 
    0x10a031dfc <+255>: movq %rbx, %rsi 
    0x10a031dff <+258>: movq %rcx, %rdx 
    0x10a031e02 <+261>: callq 0x10a06c78a    ; NSLog 
    0x10a031e07 <+266>: testq %r13, %r13 
    0x10a031e0a <+269>: jne 0x10a031e5e    ; <+353> 
    0x10a031e0c <+271>: callq 0x10a239912    ; symbol stub for: __CFStringNoteErrors 
    0x10a031e11 <+276>: testb %al, %al 
    0x10a031e13 <+278>: je  0x10a031e5e    ; <+353> 
    0x10a031e15 <+280>: movq 0x28137c(%rip), %rax  ; (void *)0x000000010ac5a358: NSException 
    0x10a031e1c <+287>: movq %rax, -0x58(%rbp) 
    0x10a031e20 <+291>: movq 0x294241(%rip), %rax  ; (void *)0x000000010ac74b40: NSInvalidArgumentException 
    0x10a031e27 <+298>: movq (%rax), %rax 
    0x10a031e2a <+301>: movq %rax, -0x60(%rbp) 
    0x10a031e2e <+305>: movq %r12, %rdi 
    0x10a031e31 <+308>: movq -0x48(%rbp), %rsi 
    0x10a031e35 <+312>: callq 0x10a11f7e0    ; _NSMethodExceptionProem 
    0x10a031e3a <+317>: movq %rax, %rbx 
    0x10a031e3d <+320>: movq 0x27a1e4(%rip), %rsi  ; "raise:format:" 
    0x10a031e44 <+327>: leaq 0x2a4dc5(%rip), %rcx  ; @"%@: nil argument" 
    0x10a031e4b <+334>: xorl %eax, %eax 
    0x10a031e4d <+336>: movq -0x58(%rbp), %rdi 
    0x10a031e51 <+340>: movq -0x60(%rbp), %rdx 
    0x10a031e55 <+344>: movq %rbx, %r8 
    0x10a031e58 <+347>: callq *0x294902(%rip)   ; (void *)0x000000010a4bb800: objc_msgSend 
    0x10a031e5e <+353>: movq 0x10(%rbp), %r9 
    0x10a031e62 <+357>: movq -0x40(%rbp), %rcx 
    0x10a031e66 <+361>: testb $0x4, %ch 
    0x10a031e69 <+364>: jne 0x10a031ebe    ; <+449> 
    0x10a031e6b <+366>: movabsq $0x7fffffffffffffff, %rbx ; imm = 0x7FFFFFFFFFFFFFFF 
    0x10a031e75 <+376>: xorl %edx, %edx 
    0x10a031e77 <+378>: testq %r15, %r15 
    0x10a031e7a <+381>: je  0x10a031ede    ; <+481> 
    0x10a031e7c <+383>: cmpq $0x0, -0x50(%rbp) 
    0x10a031e81 <+388>: je  0x10a031ede    ; <+481> 
    0x10a031e83 <+390>: leaq (,%rcx,8), %r8 
    0x10a031e8b <+398>: notl %r8d 
    0x10a031e8e <+401>: andq $0x10, %r8 
    0x10a031e92 <+405>: orq %rcx, %r8 
    0x10a031e95 <+408>: leaq -0x38(%rbp), %rax 
    0x10a031e99 <+412>: movq %rax, (%rsp) 
    0x10a031e9d <+416>: movq %r12, %rdi 
    0x10a031ea0 <+419>: movq %r13, %rsi 
    0x10a031ea3 <+422>: movq %r14, %rdx 
    0x10a031ea6 <+425>: movq %r15, %rcx 
    0x10a031ea9 <+428>: callq 0x10a239354    ; symbol stub for: CFStringFindWithOptionsAndLocale 
    0x10a031eae <+433>: xorl %edx, %edx 
    0x10a031eb0 <+435>: testb %al, %al 
    0x10a031eb2 <+437>: je  0x10a031ede    ; <+481> 
    0x10a031eb4 <+439>: movq -0x38(%rbp), %rbx 
    0x10a031eb8 <+443>: movq -0x30(%rbp), %rdx 
    0x10a031ebc <+447>: jmp 0x10a031ede    ; <+481> 
    0x10a031ebe <+449>: movq 0x27c873(%rip), %rsi  ; "_rangeOfRegularExpressionPattern:options:range:locale:" 
    0x10a031ec5 <+456>: movq %r9, (%rsp) 
    0x10a031ec9 <+460>: movq %r12, %rdi 
    0x10a031ecc <+463>: movq %r13, %rdx 
    0x10a031ecf <+466>: movq %r14, %r8 
    0x10a031ed2 <+469>: movq %r15, %r9 
    0x10a031ed5 <+472>: callq *0x294885(%rip)   ; (void *)0x000000010a4bb800: objc_msgSend 
    0x10a031edb <+478>: movq %rax, %rbx 
    0x10a031ede <+481>: movq %rbx, %rax 
    0x10a031ee1 <+484>: addq $0x48, %rsp 
    0x10a031ee5 <+488>: popq %rbx 
    0x10a031ee6 <+489>: popq %r12 
    0x10a031ee8 <+491>: popq %r13 
    0x10a031eea <+493>: popq %r14 
    0x10a031eec <+495>: popq %r15 
    0x10a031eee <+497>: popq %rbp 
    0x10a031eef <+498>: retq 

它运行正则表达式来检查,如果一个串有另一个AND它有安全检查..

0

iOS基金会是Apple的专有代码,因此您很少有机会可以合法查看NSString实施代码。

我会做你的情况是:

  • 生成并运行一些基准为[NSString的containString:]功能(串/模式对一个体面的列表)。

  • 如果结果不适合您 - 尝试寻找字符串搜索的替代实现方式(有很多开源C代码),在该实现上运行相同的基准测试并与原始结果进行比较。