[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master d666269 2/3: Convert hex digits more systematically
From: |
Paul Eggert |
Subject: |
[Emacs-diffs] master d666269 2/3: Convert hex digits more systematically |
Date: |
Wed, 5 Jul 2017 21:59:37 -0400 (EDT) |
branch: master
commit d6662694d05be03fdd070353637dd22a324c8b7a
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>
Convert hex digits more systematically
This makes the code a bit smaller and presumably faster, as
it substitutes a single lookup for conditional jumps.
* src/character.c (hexdigit): New constant.
(syms_of_character) [HEXDIGIT_IS_CONST]: Initialize it.
* src/character.h (HEXDIGIT_CONST, HEXDIGIT_IS_CONST): New macros.
(hexdigit): New decl.
(char_hexdigit): New inline function.
* src/charset.c: Do not include c-ctype.h.
* src/charset.c (read_hex):
* src/editfns.c (styled_format):
* src/image.c (xbm_scan):
* src/lread.c (read_escape):
* src/regex.c (ISXDIGIT) [emacs]:
Use char_hexdigit insted of doing it by hand.
---
src/character.c | 17 +++++++++++++++++
src/character.h | 18 ++++++++++++++++++
src/charset.c | 12 ++++++------
src/editfns.c | 6 ++----
src/image.c | 9 ++-------
src/lread.c | 25 ++++++-------------------
src/regex.c | 4 +---
7 files changed, 52 insertions(+), 39 deletions(-)
diff --git a/src/character.c b/src/character.c
index cf46054..1c6020e 100644
--- a/src/character.c
+++ b/src/character.c
@@ -1050,9 +1050,26 @@ blankp (int c)
return XINT (category) == UNICODE_CATEGORY_Zs; /* separator, space */
}
+signed char HEXDIGIT_CONST hexdigit[UCHAR_MAX + 1] =
+ {
+#if HEXDIGIT_IS_CONST
+ [0 ... UCHAR_MAX] = -1,
+#endif
+ ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4,
+ ['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9,
+ ['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15,
+ ['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15
+ };
+
void
syms_of_character (void)
{
+#if !HEXDIGIT_IS_CONST
+ /* Set the non-hex digit values to -1. */
+ for (int i = 0; i <= UCHAR_MAX; i++)
+ hexdigit[i] -= i != '0' && !hexdigit[i];
+#endif
+
DEFSYM (Qcharacterp, "characterp");
DEFSYM (Qauto_fill_chars, "auto-fill-chars");
diff --git a/src/character.h b/src/character.h
index 62d252e..b073a0d 100644
--- a/src/character.h
+++ b/src/character.h
@@ -700,6 +700,24 @@ char_table_translate (Lisp_Object obj, int ch)
return CHARACTERP (obj) ? XINT (obj) : ch;
}
+#if defined __GNUC__ && !defined __STRICT_ANSI__
+# define HEXDIGIT_CONST const
+# define HEXDIGIT_IS_CONST true
+#else
+# define HEXDIGIT_CONST
+# define HEXDIGIT_IS_CONST false
+#endif
+extern signed char HEXDIGIT_CONST hexdigit[];
+
+/* If C is a hexadecimal digit ('0'-'9', 'a'-'f', 'A'-'F'), return its
+ value (0-15). Otherwise return -1. */
+
+INLINE int
+char_hexdigit (int c)
+{
+ return 0 <= c && c <= UCHAR_MAX ? hexdigit[c] : -1;
+}
+
INLINE_HEADER_END
#endif /* EMACS_CHARACTER_H */
diff --git a/src/charset.c b/src/charset.c
index d0840f7..9c3b8db 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -33,7 +33,6 @@ along with GNU Emacs. If not, see
<http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
-#include <c-ctype.h>
#include "lisp.h"
#include "character.h"
#include "charset.h"
@@ -434,14 +433,15 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
return 0;
}
n = 0;
- while (c_isxdigit (c = getc_unlocked (fp)))
+ while (true)
{
+ c = getc_unlocked (fp);
+ int digit = char_hexdigit (c);
+ if (digit < 0)
+ break;
if (INT_LEFT_SHIFT_OVERFLOW (n, 4))
*overflow = 1;
- n = ((n << 4)
- | (c - ('0' <= c && c <= '9' ? '0'
- : 'A' <= c && c <= 'F' ? 'A' - 10
- : 'a' - 10)));
+ n = (n << 4) + digit;
}
if (c != EOF)
ungetc (c, fp);
diff --git a/src/editfns.c b/src/editfns.c
index da99c05..d599fcf 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -4704,10 +4704,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool
message)
char src0 = src[0];
int exponent_bytes = 0;
bool signedp = src0 == '-' || src0 == '+' || src0 == ' ';
- if (zero_flag
- && ((src[signedp] >= '0' && src[signedp] <= '9')
- || (src[signedp] >= 'a' && src[signedp] <= 'f')
- || (src[signedp] >= 'A' && src[signedp] <= 'F')))
+ unsigned char after_sign = src[signedp];
+ if (zero_flag && 0 <= char_hexdigit (after_sign))
{
leading_zeros += padding;
padding = 0;
diff --git a/src/image.c b/src/image.c
index 07c4769..6b748ba 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2595,13 +2595,8 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
while (*s < end)
{
c = *(*s)++;
- if (c_isdigit (c))
- digit = c - '0';
- else if (c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
- else
+ digit = char_hexdigit (c);
+ if (digit < 0)
break;
value = 16 * value + digit;
}
diff --git a/src/lread.c b/src/lread.c
index 182f962..7c554ba 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2426,25 +2426,13 @@ read_escape (Lisp_Object readcharfun, bool stringp)
while (1)
{
c = READCHAR;
- if (c >= '0' && c <= '9')
- {
- i *= 16;
- i += c - '0';
- }
- else if ((c >= 'a' && c <= 'f')
- || (c >= 'A' && c <= 'F'))
- {
- i *= 16;
- if (c >= 'a' && c <= 'f')
- i += c - 'a' + 10;
- else
- i += c - 'A' + 10;
- }
- else
+ int digit = char_hexdigit (c);
+ if (digit < 0)
{
UNREAD (c);
break;
}
+ i = (i << 4) + digit;
/* Allow hex escapes as large as ?\xfffffff, because some
packages use them to denote characters with modifiers. */
if ((CHAR_META | (CHAR_META - 1)) < i)
@@ -2474,11 +2462,10 @@ read_escape (Lisp_Object readcharfun, bool stringp)
c = READCHAR;
/* `isdigit' and `isalpha' may be locale-specific, which we don't
want. */
- if (c >= '0' && c <= '9') i = (i << 4) + (c - '0');
- else if (c >= 'a' && c <= 'f') i = (i << 4) + (c - 'a') + 10;
- else if (c >= 'A' && c <= 'F') i = (i << 4) + (c - 'A') + 10;
- else
+ int digit = char_hexdigit (c);
+ if (digit < 0)
error ("Non-hex digit used for Unicode escape");
+ i = (i << 4) + digit;
}
if (i > 0x10FFFF)
error ("Non-Unicode character: 0x%x", i);
diff --git a/src/regex.c b/src/regex.c
index 240a91f..fb48765 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -306,9 +306,7 @@ enum syntaxcode { Swhitespace = 0, Sword = 1, Ssymbol = 2 };
/* In Emacs, these are only used for single-byte characters. */
# define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
# define ISCNTRL(c) ((c) < ' ')
-# define ISXDIGIT(c) (((c) >= '0' && (c) <= '9') \
- || ((c) >= 'a' && (c) <= 'f') \
- || ((c) >= 'A' && (c) <= 'F'))
+# define ISXDIGIT(c) (0 <= char_hexdigit (c))
/* The rest must handle multibyte characters. */