2 * Copyright (c) 2010, Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 // char * strstr(const char *s1, const char *s2);
26 // If s2 is empty, s1 is returned.
27 // If s2 does not occur in s1, NULL is returned.
28 // Otherwise, a pointer to the first character of the first occurrence of s2
31 // We use a hand-tuned version of the naive quadratic time algorithm; we have
32 // experimented with more sophisticated algorithms, however they have been
33 // found wanting. The increased startup cost combines with the frequency of
34 // calls to strstr with small strings to swamp the gains from improved
35 // asymptotic complexity.
37 #define CLEAR_FRAME_AND_RETURN \
49 // Throughout this function, I will refer to the string in which we are
50 // searching as "string" and the string for which we are searching as "word".
51 // Using s1 and s2 is too confusing. Thus, we want to return a pointer to
52 // the first occurrence of "word" in "string".
56 // We begin by calling strlen to find the length of "word". We also handle
57 // two special cases here: we early-out if word is an empty string (length
58 // zero), and we call strchr if word is only a single character.
64 // Load the first character of word
67 L_lookForFirstCharacter:
68 // Load the first character from string. If it is equal to the first
69 // character of word, or is a zero byte, then we do more processing;
70 // otherwise, proceed to the next character.
74 bne L_lookForFirstCharacter
76 // The byte that we loaded from string either matched the first character
77 // of word, or was a zero byte. If it was a zero byte, then we have reached
78 // the end of string without finding a match of word. Otherwise, we fall
79 // into a loop that checks additional characters to see if we have a match.
83 // We have found a match for the first character of word; we want to read
84 // characters from this point on to see if we have a match for the entirety
85 // of word. We want to be sure to preserve the state of the outside loop,
88 // r0: length(word) - 1
89 // r4: pointer to the next character in string
90 // r5: pointer to the first character in word
91 // ip: first character in word
93 // The registers r1-r3, r6, and lr are available as scratch. We set them up
94 // for the inner loop as follows:
96 // r1: remaining length to be matched
97 // r2: pointer to next character of string to match
98 // r3: pointer to next character of word to match
99 // r6: current character from string
100 // lr: current character from word
106 // Load the next byte from both the candidate match and from word. If they
107 // are not equal, jump back to the outer loop. If they are equal, decrement
108 // the length, and continue the inner loop if we have not yet found a
111 // We don't need to worry about looking for null bytes in this loop; we know
112 // that we won't load a null byte from word, because we computed it's length
113 // earlier, and are using that as a termination condition. If we hit a null
114 // byte in string, the comparison will fail (because the corresponding byte
115 // in word is non-null), and we will return to the outer loop, where the
116 // null byte will be detected and handled properly.
120 bne L_lookForFirstCharacter
124 // We have exhausted the length of word without finding a mismatched character
125 // so we have found a match. Return a pointer to the beginning of the match
126 // string. (This pointer is r4 - 1 because r4 was auto-incremented when we
127 // loaded the first character).
129 CLEAR_FRAME_AND_RETURN
132 // No match was found; return NULL.
134 CLEAR_FRAME_AND_RETURN
137 // "word" is either empty or a single character. If it is a single character,
138 // translate strstr into a call to the (more efficient) strchr.
143 CLEAR_FRAME_AND_RETURN
146 // "word" is empty; return "string".
148 CLEAR_FRAME_AND_RETURN