如何在 JavaScript 中实现 ctype.h 功能?
How to implement ctype.h functionality in JavaScript?
将 glibc ctype.h
翻译成 JavaScript 的一般方法是什么?我想我可以做到,但我没有在 C 源代码中找到实现这些的 tables 和位移位。这里最优化的技术是什么?
isalnum(c)
isalpha(c)
iscntrl(c)
isdigit(c)
islower(c)
isgraph(c)
isprint(c)
ispunct(c)
isspace(c)
isupper(c)
isxdigit(c)
isblank(c)
看来他们正在使用各种技术来生成这些函数,这些函数可能取决于体系结构。但是,将其手动翻译成 JavaScript 需要做什么的要点是什么?看来他们正在使用某种 tables,但我似乎也无法在源代码中找到它们。
查看 openbsd ctype.h source 让我更接近一点,但仍然缺少 table,并且不确定这是否是用于 JavaScript 的最优化方法。例如:
__only_inline int isdigit(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _N));
}
我不知道他们从哪里得到 & _N
,以及 (_ctype_ + 1)[index]
的含义或来源。
他们将 _ctype_
定义为:
extern const char *_ctype_;
但不是 C 方面的专家,我不确定如何解释 extern
部分,或者我在哪里可以找到这个 table 实现。可能是 ctype_.c
,但还不确定该怎么做。
关于 OpenBSD 实现的发言:
您发现的是一个充满位掩码的查找 table,其大小与 unsigned char
(0-255) 的范围相匹配,其中包含 ASCII table (0-127).
上限 (128-255) 用零填充。
请注意前面有一个字节,它为所有内容提供了 +1
的偏移量。
各个掩码定义在 ctype.h
的顶部:
#define _U 0x01
#define _L 0x02
#define _N 0x04
#define _S 0x08
#define _P 0x10
#define _C 0x20
#define _X 0x40
#define _B 0x80
请注意,它们的二进制表示都是一个单独的、不同的位。
isXXX
函数将其参数接收为 int
,在对 EOF
(-1
) 进行初始测试后,它被限制为 unsigned char
.此十进制值用于索引查找 table,检索表示每个 ASCII 字符质量的值。
例如,ASCII table 的前 32 个字符是 control 字符,此处用掩码 _C
.
表示
LF 或 line-feed 既是 control 又是space个字符。它的十进制值为10
(0xA
).
在查找 table 中找到这个索引,我们看到掩码是由按位 ORing _C
和 _S
形成的,如下所示在 _C|_S
.
isXXX
函数使用位 AND (&
) 和适当的位掩码来测试质量。
例如,isalnum
测试 U 大写、L 小写和 N带掩码的数字 (_U|_L|_N)
.
可以在 JavaScript 中采用相同的方法。大致:
const _U = 0x01;
const _L = 0x02;
const _N = 0x04;
/* ... */
const _X = 0x40;
const lookup = {
'A': _U | _X,
/* ... */
'0': _N,
/* ... */
'e': _L | _X,
'p': _L,
};
const get = c => lookup[c] ?? 0;
const isupper = c => get(c) & _U;
const isxdigit = c => get(c) & (_N | _X);
for (let letter of "Apple0")
console.log(isupper(letter), isxdigit(letter));
请注意,此处的所有内容或多或少都与“C”有关locale. Switching locales changes the behaviour of these functions (man 7 locale
)。
将 glibc ctype.h
翻译成 JavaScript 的一般方法是什么?我想我可以做到,但我没有在 C 源代码中找到实现这些的 tables 和位移位。这里最优化的技术是什么?
isalnum(c)
isalpha(c)
iscntrl(c)
isdigit(c)
islower(c)
isgraph(c)
isprint(c)
ispunct(c)
isspace(c)
isupper(c)
isxdigit(c)
isblank(c)
看来他们正在使用各种技术来生成这些函数,这些函数可能取决于体系结构。但是,将其手动翻译成 JavaScript 需要做什么的要点是什么?看来他们正在使用某种 tables,但我似乎也无法在源代码中找到它们。
查看 openbsd ctype.h source 让我更接近一点,但仍然缺少 table,并且不确定这是否是用于 JavaScript 的最优化方法。例如:
__only_inline int isdigit(int _c)
{
return (_c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)_c] & _N));
}
我不知道他们从哪里得到 & _N
,以及 (_ctype_ + 1)[index]
的含义或来源。
他们将 _ctype_
定义为:
extern const char *_ctype_;
但不是 C 方面的专家,我不确定如何解释 extern
部分,或者我在哪里可以找到这个 table 实现。可能是 ctype_.c
,但还不确定该怎么做。
关于 OpenBSD 实现的发言:
您发现的是一个充满位掩码的查找 table,其大小与 unsigned char
(0-255) 的范围相匹配,其中包含 ASCII table (0-127).
上限 (128-255) 用零填充。
请注意前面有一个字节,它为所有内容提供了 +1
的偏移量。
各个掩码定义在 ctype.h
的顶部:
#define _U 0x01
#define _L 0x02
#define _N 0x04
#define _S 0x08
#define _P 0x10
#define _C 0x20
#define _X 0x40
#define _B 0x80
请注意,它们的二进制表示都是一个单独的、不同的位。
isXXX
函数将其参数接收为 int
,在对 EOF
(-1
) 进行初始测试后,它被限制为 unsigned char
.此十进制值用于索引查找 table,检索表示每个 ASCII 字符质量的值。
例如,ASCII table 的前 32 个字符是 control 字符,此处用掩码 _C
.
LF 或 line-feed 既是 control 又是space个字符。它的十进制值为10
(0xA
).
在查找 table 中找到这个索引,我们看到掩码是由按位 ORing _C
和 _S
形成的,如下所示在 _C|_S
.
isXXX
函数使用位 AND (&
) 和适当的位掩码来测试质量。
例如,isalnum
测试 U 大写、L 小写和 N带掩码的数字 (_U|_L|_N)
.
可以在 JavaScript 中采用相同的方法。大致:
const _U = 0x01;
const _L = 0x02;
const _N = 0x04;
/* ... */
const _X = 0x40;
const lookup = {
'A': _U | _X,
/* ... */
'0': _N,
/* ... */
'e': _L | _X,
'p': _L,
};
const get = c => lookup[c] ?? 0;
const isupper = c => get(c) & _U;
const isxdigit = c => get(c) & (_N | _X);
for (let letter of "Apple0")
console.log(isupper(letter), isxdigit(letter));
请注意,此处的所有内容或多或少都与“C”有关locale. Switching locales changes the behaviour of these functions (man 7 locale
)。