¿Cuál es el enfoque general para traducir glibcctype.h
a JavaScript? Creo que podría hacerlo, pero no encuentro las tablas y el bitshifting que los implementa en el código fuente de C. ¿Cuál es la técnica más óptima aquí?
isalnum(c)
isalpha(c)
iscntrl(c)
isdigit(c)
islower(c)
isgraph(c)
isprint(c)
ispunct(c)
isspace(c)
isupper(c)
isxdigit(c)
isblank(c)
Parece que están utilizando todo tipo de técnicas para generar estas funciones, tal vez dependiendo de la arquitectura. Pero, ¿cuál es la esencia de lo que se debe hacer para traducir esto manualmente a JavaScript? Parece que están usando tablas de algún tipo, pero tampoco puedo encontrarlas en la fuente.
Mirar la fuente de openbsd ctype.h me acerca un poco más, pero aún me faltan las tablas, y no estoy seguro de si ese es el enfoque más optimizado para usar con JavaScript. Por ejemplo:
__only_inline int isdigit(int _c)
{
return (_c == -1? 0: ((_ctype_ + 1)[(unsigned char)_c] & _N));
}
No veo de dónde lo sacan & _N
, y qué (_ctype_ + 1)[index]
significa o de dónde viene.
Ellos definen _ctype_
como:
extern const char *_ctype_;
Pero al no ser tan experto en C, no estoy seguro de cómo interpretar la extern
parte o dónde puedo encontrar la implementación de esta tabla. Tal vez lo sea ctype_.c
, pero aún no estoy seguro de qué hacer con él.
Solución del problema
Hablando sobre la implementación de OpenBSD:
Lo que ha encontrado es una tabla de búsqueda llena de máscaras de bits, con un tamaño que coincide con el rango de un unsigned char
(0-255), que abarca la tabla ASCII (0-127).
El rango superior (128-255) se rellena con ceros.
Tenga en cuenta que hay un byte anterior, que le da a todo un desplazamiento de +1
.
Las máscaras individuales se definen en la parte superior de 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
Tenga en cuenta que sus representaciones binarias son cada una un bit único y distinto.
isXXX
Las funciones reciben su argumento como int
, que, después de una prueba inicial de EOF
( -1
), se fija a un unsigned char
. Este valor decimal se usa para indexar la tabla de búsqueda, recuperando un valor que representa las cualidades de cada carácter ASCII.
Por ejemplo, los primeros 32 caracteres de la tabla ASCII son caracteres de control, indicados aquí con la máscara _C
.
LF, o salto de línea, es tanto un carácter de control como de espacio. Su valor decimal es 10
( 0xA
).
Al encontrar este índice en la tabla de búsqueda, vemos que la máscara está formada por OR bit a bit _C
con _S
, como en _C|_S
.
isXXX
las funciones comprueban las cualidades con AND bit a bit ( &
) y la máscara de bits adecuada.
Por ejemplo, isalnum
pruebas de mayúsculas, minúsculas y números con la máscara (_U|_L|_N)
.
El mismo enfoque se puede tomar en JavaScript. Aproximadamente:
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));
Tenga en cuenta que todo aquí es más o menos con respecto a la configuración regional "C". El cambio de configuración regional cambia el comportamiento de estas funciones ( man 7 locale
).
No hay comentarios.:
Publicar un comentario