fix(utils): ExtractFirstArgument -- разделители и остаток без пробелов - #3812
Closed
bylins wants to merge 1 commit into
Closed
fix(utils): ExtractFirstArgument -- разделители и остаток без пробелов#3812bylins wants to merge 1 commit into
bylins wants to merge 1 commit into
Conversation
Три правки в разборе аргументов на std::string. Разделителем считался только пробел, а one_argument режет по a_isspace. Табуляция между аргументами склеивала два поля в одно: "frozen\t30 спам" давал слово "frozen\t30". Достижимо не в теории -- функция разбирает строку dgaffect прямо из текста триггера, где табуляцию поставить несложно. Остаток начинался с пробелов: substr(pos + 1) пропускал ровно один. Каждый вызывающий подчищал сам -- в dg_misc через Trim, в setall через TrimLeft. Теперь остаток отдаётся уже без ведущих пробелов, лишние Trim у вызывающих просто становятся холостыми. Комментарий утверждал, что "если нет пробелов то строки пустые". На деле строка из одного слова возвращает это слово и пустой остаток. Заодно описано, чем функция НЕ является: one_argument вдобавок понижает регистр и пропускает служебные слова (in, from, with, the, on, at, to), здесь ни того, ни другого нет. Это и есть причина, по которой при переносе кода с half_chop приходится звать to_lower руками. Восемь тестов: разбиение, табуляция, чистый остаток, одно слово, пустой ввод, сохранение регистра и служебных слов, разбор в цикле через одну переменную, многобайтные буквы. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XUwDWDnYdXrJdvjDVd36QH
Owner
Author
|
Собрано вместе с остальными в #3813 — там все три темы одним PR, потому что |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Доделка моей же правки
c0675a229(март 2026): тогда я чинил алиасингExtractFirstArgument(str, str), закрыл симптом и не посмотрел вокруг. Заодно комментарий «аналог one_argument для string» — тоже мой, и он неточен.1. Разделителем был только пробел
one_argumentрежет поa_isspace— это ещё\t \n \v \f \r. Здесь стоялоs.find(' '):Достижимо не в теории: функция разбирает строку
dgaffect <цель> <свойство> <значение> <длительность>прямо из текста триггера (dg_misc.cpp:289), а там табуляцию поставить несложно — два аргумента склеятся в один.2. Остаток начинался с пробелов
remains = s.substr(space_pos + 1)пропускал ровно один пробел. Каждый вызывающий дочищал сам: вdg_miscчерезTrim, вsetallя дописалTrimLeft. Теперь остаток отдаётся уже подчищенным — как и делаетskip_spacesвнутриhalf_chop.3. Комментарий врал
«если нет пробелов то строки пустые» — неправда: строка из одного слова возвращает это слово и пустой остаток. Переписан; отдельно сказано, чем функция не является:
one_argumentпонижает регистр слова, эта — нет;one_argumentпропускает служебные слова (in from with the on at to, см.fill_word), эта — нет:Это не баг, а разные задачи: пропуск служебных слов нужен разбору команд игрока и вреден при разборе триггера. Но при переносе кода с
half_chopна эту функцию про регистр надо помнить — иначе, например, почта вsetallперестанет находиться (она сверяется сplayer_tableподстрокой).Что проверял
Алиасинг (
ExtractFirstArgument(str, str)— основной способ применения, ради него и был фикс #3037). Во всех трёх ветках слово копируется до записи вremains, а последнее чтениеsидёт раньше присваивания; в тернарнике обе половины создают временную строку. Есть отдельный тест на разбор в цикле через одну переменную.Многобайтные буквы. Набор разделителей чисто ASCII, а продолжающие байты UTF-8 всегда ≥ 0x80 — внутри русской буквы «разделитель» не найдётся. Тест есть.
Изменение поведения у существующих вызывающих. Оно одно: значение с ведущими пробелами.
dg_scripts.cpp:3517/3557хранят переменные какимя + " " + значение, и раньше остаток отдавался со всеми пробелами кроме одного:Считаю это правильным: строка перед разбором уже прошла
Split, который делаетTrimLeft, то есть ведущие пробелы там и так не сохраняются — а после имени переменной они были артефактом формата, не данными. Но если для DG-переменных важно хранить значение байт в байт, лучше менять формат хранения, а не разбор — скажи, вынесу отдельно.Тесты
Восемь новых в
tests/utils.string.cpp: разбиение, табуляция как разделитель, чистый остаток, одно слово, пустой ввод, сохранение регистра и служебных слов, разбор в цикле через одну переменную, многобайтные буквы. Всего 681 тест, сборка чистая.🤖 Generated with Claude Code
https://claude.ai/code/session_01XUwDWDnYdXrJdvjDVd36QH