find_applet_by_name: add an example of faster linear search code
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
8b0f459af7
commit
a93e4fd376
@ -141,10 +141,28 @@ void FAST_FUNC bb_show_usage(void)
|
|||||||
|
|
||||||
int FAST_FUNC find_applet_by_name(const char *name)
|
int FAST_FUNC find_applet_by_name(const char *name)
|
||||||
{
|
{
|
||||||
unsigned i, max;
|
unsigned i, j, max;
|
||||||
int j;
|
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
|
/* The commented-out word-at-a-time code is ~40% faster, but +160 bytes.
|
||||||
|
* "Faster" here saves ~0.5 microsecond of real time - not worth it.
|
||||||
|
*/
|
||||||
|
#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
|
||||||
|
uint32_t n32;
|
||||||
|
|
||||||
|
/* Handle all names < 2 chars long early */
|
||||||
|
if (name[0] == '\0')
|
||||||
|
return -1; /* "" is not a valid applet name */
|
||||||
|
if (name[1] == '\0') {
|
||||||
|
if (!ENABLE_TEST)
|
||||||
|
return -1; /* 1-char name is not valid */
|
||||||
|
if (name[0] != ']')
|
||||||
|
return -1; /* 1-char name which isn't "[" is not valid */
|
||||||
|
/* applet "[" is always applet #0: */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
p = applet_names;
|
p = applet_names;
|
||||||
i = 0;
|
i = 0;
|
||||||
#if KNOWN_APPNAME_OFFSETS <= 0
|
#if KNOWN_APPNAME_OFFSETS <= 0
|
||||||
@ -166,7 +184,62 @@ int FAST_FUNC find_applet_by_name(const char *name)
|
|||||||
//bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max);
|
//bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Open-coding without strcmp/strlen calls for speed */
|
/* Open-coded linear seatch without strcmp/strlen calls for speed */
|
||||||
|
|
||||||
|
#if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/
|
||||||
|
/* skip "[\0" name, it's surely not it */
|
||||||
|
if (ENABLE_TEST && LONE_CHAR(p, '['))
|
||||||
|
i++, p += 2;
|
||||||
|
/* All remaining applet names in p[] are at least 2 chars long */
|
||||||
|
/* name[] is also at least 2 chars long */
|
||||||
|
|
||||||
|
n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16);
|
||||||
|
while (i < max) {
|
||||||
|
uint32_t p32;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
/* Quickly check match of the first 3 bytes */
|
||||||
|
move_from_unaligned32(p32, p);
|
||||||
|
p += 3;
|
||||||
|
if ((p32 & 0x00ffffff) != n32) {
|
||||||
|
/* Most likely case: 3 first bytes do not match */
|
||||||
|
i++;
|
||||||
|
if ((p32 & 0x00ff0000) == '\0')
|
||||||
|
continue; // p[2] was NUL
|
||||||
|
p++;
|
||||||
|
if ((p32 & 0xff000000) == '\0')
|
||||||
|
continue; // p[3] was NUL
|
||||||
|
/* p[0..3] aren't matching and none is NUL, check the rest */
|
||||||
|
while (*p++ != '\0')
|
||||||
|
continue;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlikely branch: first 3 bytes ([0..2]) match */
|
||||||
|
if ((p32 & 0x00ff0000) == '\0') {
|
||||||
|
/* name is 2-byte long, it is full match */
|
||||||
|
//bb_error_msg("found:'%s' i:%u", name, i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/* Check remaining bytes [3..NUL] */
|
||||||
|
ch = (p32 >> 24);
|
||||||
|
j = 3;
|
||||||
|
while (ch == name[j]) {
|
||||||
|
if (ch == '\0') {
|
||||||
|
//bb_error_msg("found:'%s' i:%u", name, i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
ch = *++p;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
/* Not a match. Skip it, including NUL */
|
||||||
|
while (ch != '\0')
|
||||||
|
ch = *++p;
|
||||||
|
p++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
while (i < max) {
|
while (i < max) {
|
||||||
char ch;
|
char ch;
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -189,6 +262,7 @@ int FAST_FUNC find_applet_by_name(const char *name)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user