summaryrefslogtreecommitdiff
path: root/libc/inet/ether_addr.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-12-22 01:01:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-12-22 01:01:40 +0000
commit4274e516239b34c5cd9ea2c60c11802e28244c99 (patch)
tree4fa9f8d784803d3927757f7eaa6e95ad5ae5ca5e /libc/inet/ether_addr.c
parentc6df9c945232b76340e298946b51684441f549fc (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.c52
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;
}