Здравствуйте, SaZ, Вы писали:
SaZ>Нормальная архитектура с заказчикозависимым кодом в отдельном классе.
Когда реализация предполагает отдельный класс — само собой. А во многих местах заказчикозависимый код состоит всего из нескольких строк, вставляемых по условию, и делающих дополнительные проверки или мелкие операции. Городить для таких добавок/уточнений отдельные классы — лишь загромождать реализацию.
Re[3]: Утилита для удаления из текста C++ блоков #if с подходящими условиями
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Здравствуйте, SaZ, Вы писали:
SaZ>>Нормальная архитектура с заказчикозависимым кодом в отдельном классе.
ЕМ>Когда реализация предполагает отдельный класс — само собой. А во многих местах заказчикозависимый код состоит всего из нескольких строк, вставляемых по условию, и делающих дополнительные проверки или мелкие операции. Городить для таких добавок/уточнений отдельные классы — лишь загромождать реализацию.
Вы не правы. Как раз таки наоборот — вам требуется разная логика с одинаковым интерфейсом, в зависимости от каких-либо условий (заказчикозависимость). Имеет смысл её вынести в отдельные сущности. Это же основы ООП. И более чистый код.
Если вам не нравится ООП подход, который тут отлично ложится, то тогда удачи с другими парадигмами — городите простыни из неконтролируемых #ifdef/endif.
Re: Утилита для удаления из текста C++ блоков #if с подходящими условиями
и от каких-либо условий (заказчикозависимость). Имеет смысл её вынести в отдельные сущности. Это же основы ООП. И более чистый код. SaZ>Если вам не нравится ООП подход, который тут отлично ложится, то тогда удачи с другими парадигмами — городите простыни из неконтролируемых #ifdef/endif.
Зачем #ifdef/endif? Можно вполне через шаблоны сделать. PS: ожидаем rg45... Попкорном могу поделиться, уважаемые коллеги
Здравствуйте, SaZ, Вы писали:
SaZ>Это же основы ООП.
Ну давайте, расскажите мне, как с помощью знания "основ ООП" условно добавить в константную таблицу (массив структур) дополнительную структуру в зависимости от условия. И так, чтобы это не выглядело по-идиотски и монстроидально, и не требовало отдельного описания для понимания того, как и зачем это сделано.
SaZ>И более чистый код.
"Чистый код ради идеи чистого кода" — это тупое сектантство. Если код после преобразования к "чистому" виду теряет прозрачность и понятность — значит, с идеей "чистоты" что-то не так.
SaZ>Если вам не нравится ООП подход, который тут отлично ложится
Мне нравится ООП-подход, я его регулярно использую, но только там, куда он ложится естественно, а не путем натягивания.
SaZ>городите простыни из неконтролируемых #ifdef/endif.
Вы в состоянии представить себе что-то промежуточное между "полное отсутствие #if" и "простыни из #if"?
Re[5]: Утилита для удаления из текста C++ блоков #if с подходящими условиями
Здравствуйте, Евгений Музыченко, Вы писали: M>>Сам пиши за такие деньги ЕМ>Мне лень. Это из разряда "неплохо бы...".
Когда мне хочется, я пишу, а не ною
Скрытый текст
umba-2c
Генерирует исходник на C для входного файла. Пердназначен для генерации кроссплатформенных "ресурсов"
для приложения.
Изначально была реализована для того, чтобы зашить в прошивку самодельного веб-сервера для микроконтроллера
статичные странички и картинки, отсюда опции добавления mime-type'а и last-modified, но потом идея понравилась,
и стала применяться и для обычных исполняемых файлов.
Умеет форматировать ресурс в виде строки (использует C-escape), в виде массива char'ов, hex/dec.
Ресурс двоичный/текстовый, для текстовых может делаться замена перевода строки и сжатие пробелов,
возможно наверно надо добавить коррекцию/конвертацию Tab'ов/в Tab'ы, нормализацию отступов (как в umba-tabtool).
Умеет кодировать данные в base64, умеет простецкое "шифрование" XOR'ом - длина XOR ключа 1/2/4 байта,
стартовый seed и increment. Предназначено, чтобы скрывать в EXE текстовые данные от простого просмотра.
umba-2rcfs
Сканирует заданные каталоги, генерирует единый файл для регистрации builtin ресурсов во встроенной в EXE файловой системе.
Пользователь должен определить макросы CUSTOM_UMBA_RCFS_REGISTER_RESOURSE/CUSTOM_UMBA_RCFS_REGISTER_RESOURSE_XORED.
Xor-шифрует как данные, так и имена файлов ресурсов, если указано.
Тип входного файла bin/text - определяется масками, если не подходит ни под одну - используется заданная по умолчанию.
Во многом повторяет umba-2c утилиту.
Идея в том, что необходимые ресурсы проще носить с собой в EXE, чем хранить где-то в файловой системе пользователя.
Если нужна пользовательская кастомизация, то тогда просто ищутся и подсасываются пользовательские файлы
во встроенную RCFS, при этом можно проверять корректность синтаксиса пользователских файлов - например - JSON-конфиги,
вне зависимости от их далее интерпретируемого содержимого.
Умеет в XOR-шифрование как для данных, так и для имен файлов ресурсов.
Имена файлов ресурсов указываются относительно скан-корня - если в разных скан-корнях будет файл с одинаковым подпутём/именем
- будет ошибка компиляции сгенерированного сишника.
umba-brief-scanner
Производит сканирование заданных каталогов на предмет поиска файлов по маске (include/exclude files)
В каждом файле производит поиск комментария специального вида:
/*(*|!) (\|@)file
(\|@)brief Brief desription of the file
*/
Производится поиск entry points типа main/DllMain/etc, --entry-name=... задает имя и тип возвращаемых значений
В результирующий отчет (txt|html) выводится список файлов с их описанием, файлы с entry points идут первыми.
Есть возможность группировки по пути.
Основные опции
--main - генерировать только entry points в отчёте.
--update[=FILE] - в выходном txt файле можно дописывать описания файлов, и если оно не появляется в сорцах
- берётся из предыдущей версии brief-файла
--split-group - группирует/делит на группы
umba-enum-gen
Генератор enum'ов. На входе - задаём имена абы как, хоть в параметре командной строки, хоть в .txt файле,
на выходе - отформатированно по всем правилам - PascalCase, camelCase etc.
Сериализация и десериализация значений, как и наборов значений, enum-флаги, для флагов - bitwise операторы.
Шаблоны для генерации - user/custom/base (builtins) варианты для lang/template версий.
Автоматически производится поиск файла с опциями 'umba-enum-gen-flags.txt', который обрабатывается
после встроенных файлов опций, но перед всеми непосредственно указанными опциями.
umba-make-headers
Простая утилита.
Генерирует include файлы согласно namelist.txt (который пишется руками), со ссылкой на C++/Qt документацию.
Сгенерированное надо подсовывать среде, которая умеет в это.
std::back_inserter лежит в <iterator>, но помнить это никто не делает.
Просто пишем в среде '#include "std/ba' - среда подсказывает, '#include "std/back_inserter'
В свою очередь, в файле 'std/back_inserter' лежит #include на <iterator>, и комментарий со ссылкой на cppreference
(или на кутишные доки).
Ссылка на доку в 95% случаев работает.
Готовченко тут:
https://github.com/al-martyn1/_std_headers
https://github.com/al-martyn1/_qt_headers
https://github.com/al-martyn1/_qt5_headers
https://github.com/al-martyn1/_qt6_headers
Примеры namelist.txt там же, для каждого случая.
umba-pretty-headers
Парсит заданные входные файлы, для каждого типа или свободной функции или дефайна создаёт include-файл в output каталоге.
Развитие утилиты umba-make-headers. Используется Clang-tooling. Текущая версия Win32/64 собрана на MSVC2019,
если студия нужной версии/Clang не установлены, то могут быть проблемы (проблемы могут быть, даже если всё в
порядке вроде бы - как решать - хз, но у меня работает, на предыдущей работе не работало, но я уволился)
Неплоха, чтобы посмотреть, что вообще в проекте с типами и иерархиями имен и пространств имён творится, и что есть что.
umba-sort-headers
Сортировка incude'ов. Ничего не трогает, в тч кодировку. Макс попортятся переводы строк, но и тут мы старались делать нежно.
Пробелы и пустые строки игнорируются. Все иное, в тч пустой комент - это брик для сортировки иклудов,
инклуды сортируются только в рамках блока без бриков. Всякие #ifdef'ы - тоже брики.
Можно задавать приоритет сортировки - "user" и <system>
Хорошая практика - в хидере сортировать всё, в файле реализации - первым идёт его хидер (чтобы проверить его самододостаточность),
затем - отсортированные внешние зависимости - чтобы проще ориентироваться.
umba-subst-macros
Задаём макросы в командной строке. Парсим файл, подставляем - профит. Макросы похожи на макросы проектов VisualStudio - $(MacroName).
Неизвестные макросы можно пропускать как есть, либо вырезать.
Ключик --raw позоляет делать замены без макросов - тупая текстовая подстановка. Из конкретного файла делаем шаблон в --raw режиме,
потом шаблон используем для генерации по шаблону при помощи макросов. Профит.
umba-tabtool
--check - только проверки с выводом отчета. Возвращает не нулевой код возврата, можно использовать при коммита в хуках, например.
Конвертит TAB'ы в пробелы и наоборот.
Нормализация TAB'ов - конвертит пробелы в TAB'ы, потом наоборот, потом опять наоборот, с учетом TAB-дельты.
Умеет исправлять некратное табам количество пробелов, так, 3 пробела дополняются до четырёх при -tab-delta=1, а 2 и меньше - обрезаются.
umba-tr
Поддержка легковесной системы перевода (локализации) сообщений в стиле Qt - marty_tr.
Собирает файлы из дерева каталогов/файлов в единый файл перевода в формате JSON. Иерархия трёх уровневая - LangTag/Category/MessageId,
где MessageId - собственно сам текст сообщения (на англиском). LangTag может быть как в формате локали en-US, так и в виде виндового
LangId - 0x0409/0x409/0409/409. Если категория в файле не задана (пустая), то подставляется путь конкретного файла относительно корня поиска.
Единый JSON-файл перевода затем следует добавить в ресурсы приложения при помощи umba-2c и использовать с использованием библиотеки
https://github.com/al-martyn1/marty_tr
Ты так остроумно иронизируешь по поводу шаблонов, что может показаться, что ты собаку съел по этой теме.
А вот, как ты считаешь, есть вообще что-нибудь, что следовало бы делать через шаблоны? Не мог бы ты поподробнее рассказать о своем опыте (если таковой есть)?
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Carc, Вы писали:
C>>PS: ожидаем rg45... Попкорном могу поделиться, уважаемые коллеги
R>А я не приду. Надоел он мне хуже горькой редьки.
Не-е-е-е, так не пойдет! Попкорн закуплен, билеты распроданы, на подветки подписаны... Ждём-съ (ц)
PS: а если шутки в сторону, то весьма интересно наблюдать за вашим спором. И не без практической выгоды (пару-тройку интересных и новых мыслей уже попадалось, из разряда "а с такой стороны задачу я не разглядывал" ).
Здравствуйте, vsb, Вы писали:
vsb>А в чём проблема написать самому? Я может что-то не понимаю, но вроде задача на час от силы. Или там какие-то сверх-сложные условия в if, которые самописным парсером не разобрать?
там не только if надо разбирать но и define, undefine, макросы, логические и арифметические операторы и выражения
Re: Утилита для удаления из текста C++ блоков #if с подходящими условиями
. Тогда посоветовали cpp-partial, но он не подошел — понимает только #ifdef/#ifndef, а у меня все условия на #if, чтобы не нарываться на проблемы из-за ошибок в написании имен.
Если не пытаться сделать универсальный всемогутор, — то такая штука пишется на скриптовом языке за пару часов. Ну, за день.
Только надо с самого начала договориться об определённом стиле кода.
Условно говоря,
// ZAKAZCHIK - параметр, приезжающий из настроек проекта
// константы заказчиков - все с одним и тем же префиксом#define ZAKAZCHIK_XXX 1
#define ZAKAZCHIK_YYY 2
#define ZAKAZCHIK_PIDORAS 321 // это имя мы не должны показывать, естественно#if ZAKAZCHIK == ZAKAZCHIK_XXX // допускается только ==
...
#elif ZAKAZCHIK == ZAKAZCHIK_YYY || ZAKAZCHIK == ZAKAZCHIK_ZZZ // допускаются только дизъюнкции
...
#else// ZAKAZCHIK - комментарий обязателен (ну или давайте, играйте в разбор деревьев if/def/ndef-elif-else-endif)
...
#endif// ZAKAZCHIK
static_assert(ZAKAZCHIK != ZAKAZCHIK_PIDORAS); // нужно сделать подстановки констант при рендеринге проекта для заказчика
Забег по строкам файла
def cleanup(lines, prefix, values_dict, actual_value):
# prefix = 'ZAKAZCHIK'
# values_dict = {'ZAKAZCHIK_XXX':1, 'ZAKAZCHIK_YYY':2, 'ZAKAZCHIK_PIDORAS':321}
# actual_value = 'ZAKAZCHIK_PIDORAS'
ifs_stack = [] # стек if-ов и значение условий в них (пары: "уже встретили true" и "прямо сейчас true")
right_now = True # текущее состояние - "выводить строку или нет?"
define update_right_now():
nonlocal right_now, ifs_stack
right_now = all(now for _,now in ifs_stack)
for line in lines:
# обмажь регекспами потом, а пока приколотим количество пробелов гвоздямиif line.startswith(f'#define {prefix}'): # #define ZAKAZCHIK...continue# выкидываем такие дефайныif line.startswith(f'#if {prefix}'):
cond = eval_condition(line, prefix, values_dict, actual_value)
ifs_stack.append((cond,cond))
update_right_now()
continue
elif line.startswith(f'#elif {prefix}'):
assert ifs_stack
was, now = ifs_stack[-1]
cond = not was and eval_condition(line, prefix, values_dict, actual_value)
ifs_stack[-1] = was or cond, cond
update_right_now()
continue
elif line.startswith(f'#else // {prefix}'):
assert ifs_stack
was, now = ifs_stack[-1]
cond = not was
ifs_stack[-1] = was or cond, cond
update_right_now()
continue
elif line.startswith(f'#endif // {prefix}'):
assert ifs_stack
ifs_stack.pop()
update_right_now()
continue
if not right_now:
continue
if prefix not in line:
yield line
else:
yield substitute_appearances(line, prefix, values_dict, actual_value)
И т.д.
Понятное дело, выше — говнокод. Его можно вылизать и ускорить в разы, но это уже стоит денег.
Перекуём баги на фичи!
Re[3]: Утилита для удаления из текста C++ блоков #if с подхо
Здравствуйте, CRT, Вы писали:
vsb>>А в чём проблема написать самому? Я может что-то не понимаю, но вроде задача на час от силы. Или там какие-то сверх-сложные условия в if, которые самописным парсером не разобрать?
CRT>там не только if надо разбирать но и define, undefine, макросы, логические и арифметические операторы и выражения
И директивы #include тоже, причем, с двумя видами скобок-кавычек. Какие-то макроопределения могут же находиться в других заголовочных файлах. Нужно будет правильно работать с относительными путями и правильно учесть приоритеты при обходе директорий. А перед тем, как грызть директивы препроцессора нужно еще правильно очистить весть текст от комментариев. Директивы препроцессора могут же быть и закомментированы, правда? Задачка не на часик, явно. Но за 14 лет можно было сделать. Причем, совсем не обязательно на плюсах. Лично я бы делал на шарпе — это реально быстрее получается, просто эмпирически.