diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-22 01:01:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-12-22 01:01:40 +0000 |
commit | 4274e516239b34c5cd9ea2c60c11802e28244c99 (patch) | |
tree | 4fa9f8d784803d3927757f7eaa6e95ad5ae5ca5e /libc/inet/ether_addr.c | |
parent | c6df9c945232b76340e298946b51684441f549fc (diff) |
docs/defines.txt: document _extern_inline
libc/inet/ether_addr.c: optimize tolower, we ever use it on 0-9a-f
libc/inet/ntop.c: optimize tolower, we ever use it on 0-9a-f
with locale support on, code size change is:
text data bss dec hex filename
- 396 0 24 420 1a4 libc/inet/ether_addr.os
+ 306 0 24 330 14a libc/inet/ether_addr.os
- 1453 0 0 1453 5ad libc/inet/ntop.os
+ 1430 0 0 1430 596 libc/inet/ntop.os
Diffstat (limited to 'libc/inet/ether_addr.c')
-rw-r--r-- | libc/inet/ether_addr.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/libc/inet/ether_addr.c b/libc/inet/ether_addr.c index 82b067157..621c62989 100644 --- a/libc/inet/ether_addr.c +++ b/libc/inet/ether_addr.c @@ -31,49 +31,45 @@ #include <netinet/ether.h> #include <netinet/if_ether.h> -/* libc_hidden_proto(ether_ntoa_r) */ -/* libc_hidden_proto(sprintf) */ -#ifdef __UCLIBC_HAS_XLOCALE__ -/* libc_hidden_proto(__ctype_b_loc) */ -/* libc_hidden_proto(__ctype_tolower_loc) */ -#elif defined __UCLIBC_HAS_CTYPE_TABLES__ -/* libc_hidden_proto(__ctype_b) */ -/* libc_hidden_proto(__ctype_tolower) */ -#endif - struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr) { - size_t cnt; + /* asc is "X:XX:XX:x:xx:xX" */ + int cnt; for (cnt = 0; cnt < 6; ++cnt) { - unsigned int number; + unsigned char number; char ch; - ch = _tolower(*asc++); + /* | 0x20 is cheap tolower(), valid for letters/numbers only */ + ch = (*asc++) | 0x20; if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return NULL; - number = isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); - - ch = _tolower(*asc); - if ((cnt < 5 && ch != ':') - || (cnt == 5 && ch != '\0' && !isspace(ch))) { - ++asc; + number = !(ch > '9') ? (ch - '0') : (ch - 'a' + 10); + + ch = *asc++; + if ((cnt != 5 && ch != ':') /* not last group */ + /* What standard says ASCII ether address representation + * may also finish with whitespace, not only NUL? + * We can get rid of isspace() otherwise */ + || (cnt == 5 && ch != '\0' /*&& !isspace(ch)*/) + ) { + ch |= 0x20; /* cheap tolower() */ if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) return NULL; - number <<= 4; - number += isdigit(ch) ? (ch - '0') : (ch - 'a' + 10); + number = (number << 4) + (!(ch > '9') ? (ch - '0') : (ch - 'a' + 10)); - ch = *asc; - if (cnt < 5 && ch != ':') - return NULL; + if (cnt != 5) { + ch = *asc++; + if (ch != ':') + return NULL; + } } /* Store result. */ - addr->ether_addr_octet[cnt] = (unsigned char) number; - - /* Skip ':'. */ - ++asc; + addr->ether_addr_octet[cnt] = number; } + /* Looks like we allow garbage after last group? + * "1:2:3:4:5:66anything_at_all"? */ return addr; } |