Created
June 14, 2024 11:36
-
-
Save Stmol/e48175a1b12b3a2a7ce8354a0a928d05 to your computer and use it in GitHub Desktop.
test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type ValueType = number | |
| const InvalidValue: ValueType = 1 << 0, | |
| StringValue: ValueType = 1 << 1, | |
| NumberValue: ValueType = 1 << 2, | |
| NilValue: ValueType = 1 << 3, | |
| BoolValue: ValueType = 1 << 4, | |
| ArrayValue: ValueType = 1 << 5, | |
| ObjectValue: ValueType = 1 << 6 | |
| let hexDigits: Uint8Array | |
| let valueTypes: ValueType[] | |
| function init() { | |
| hexDigits = new Uint8Array(256) | |
| hexDigits.fill(255) | |
| // blah blah | |
| // .... | |
| } | |
| type Iterator = { | |
| buf: Uint8Array | |
| head: number | |
| tail: number | |
| depth: number | |
| captureStartedAt?: number | |
| captured?: number | |
| Error?: Error | |
| Attachment?: any | |
| } | |
| export function NewIterator(cfg: any): Iterator { | |
| return { | |
| buf: new Uint8Array(), | |
| head: 0, | |
| tail: 0, | |
| depth: 0, | |
| } | |
| } | |
| function skipWhitespacesWithoutLoadMore(iter: Iterator): boolean { | |
| for (let i = iter.head; i < iter.tail; i++) { | |
| let c = String(iter.buf[i]) | |
| switch (c) { | |
| case ' ': | |
| case '\n': | |
| case '\t': | |
| case '\r': | |
| continue | |
| } | |
| iter.head = i | |
| return false | |
| } | |
| return true | |
| } | |
| export function ReportError(iter: Iterator, operation: string, msg: string): void { | |
| if (iter.Error !== undefined) { | |
| if (iter.Error instanceof Error) { // io.EOF type | |
| return | |
| } | |
| } | |
| let peekStart = iter.head - 10 | |
| if (peekStart < 0) { | |
| peekStart = 0 | |
| } | |
| // blah blah | |
| iter.Error = new Error( | |
| `${operation}: ${operation} error found in ${msg} byte of ...|${iter.head}|...` | |
| ) | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Этот код представляет собой основу для написания низкоуровневого парсера (лексера). Скорее всего, это часть библиотеки для разбора формата данных (например, JSON) или собственного текстового протокола. Код оптимизирован для работы с байтами (бинарными данными), а не строками, что указывает на упор в производительность.
Давай разберем каждую часть детально.
1. Битовые маски для типов данных
Что здесь происходит:
Здесь используется битовый сдвиг (
<<) для создания уникальных флагов.1 << 0— это0000001в двоичном виде)1 << 1— это0000010)1 << 2— это0000100)Зачем это нужно:
Это классический паттерн Bitmask (Битовая маска). Использование чисел вместо строк (например,
"String","Number") работает намного быстрее и занимает меньше памяти. Также это позволяет комбинировать типы, если нужно (хотя здесь они выглядят взаимоисключающими).2. Инициализация и глобальные таблицы
Что здесь происходит:
Uint8Array— это типизированный массив, который хранит только байты (целые числа от 0 до 255). Это самый эффективный способ работы с бинарными данными в JS/TS.hexDigits.fill(255)— заполняет массив значением 255 (часто используется как маркер "невалидного значения"). Обычно такие массивы используются как Lookup Table (таблица поиска), чтобы мгновенно проверять, является ли символ цифрой, буквой или разделителем, не используя медленныеif/elseили RegEx.3. Структура Итератора (Iterator)
Что здесь происходит:
Это сердце парсера. Представь ленту с данными (
buf).head(Голова): Указывает, какой байт мы читаем прямо сейчас.tail(Хвост): Указывает, где заканчиваются данные, которые мы загрузили.Функция
NewIteratorпросто создает новый пустой итератор.4. Логика пропуска пробелов
Что здесь происходит:
Функция бежит по буферу, пропуская "пустые" символы, которые не несут смысловой нагрузки (пробелы, переводы строк).
В строке
let c = String(iter.buf[i])есть странность.iter.buf[i]возвращает число (код символа, например, 32 для пробела).String(32)вернет строку"32".case ' 'проверяет именно символ пробела.bufкаким-то чудом не хранит строки (чтоUint8Arrayделать не умеет).Обычно в таких парсерах пишут так:
switch (iter.buf[i]) { case 32: ... case 10: ... }(сравнивают числовые ASCII коды). Возможно, это псевдокод или специфическая реализация приведения типов.5. Обработка ошибок (ReportError)
Суть:
Эта функция нужна для "мягкого" падения. Она не выбрасывает
throw(что остановило бы программу сразу), а записывает ошибку в состояние итератора. Это позволяет вызывающему коду самому решить, когда остановить обработку.Итог
Этот код реализует курсорный подход к чтению данных.
Это типичный паттерн для высокопроизводительных библиотек (например, для быстрого парсинга JSON, Protobuf или XML).