Compare commits

...

151 Commits

Author SHA1 Message Date
3bdf4ceda3 Требуемая версия myx-cmake поднята для 0.4.5 2021-12-29 13:36:44 +03:00
1e635fc7bb Чистка проекта 2021-12-24 15:09:46 +03:00
6f2d2361fd Обновление для совместимости с новой версией myx-cmake 2021-12-24 14:30:39 +03:00
6c1728bce0 Преобразование проекта 2021-12-12 22:55:05 +03:00
6dbde42d6f Удаление лишних зависимостей 2021-12-10 15:08:52 +03:00
023b493eff Удаление лишних зависимостей 2021-12-10 15:08:44 +03:00
31a3fc3dc7 Удаление лишних зависимостей 2021-12-10 15:08:38 +03:00
52c618c590 Удаление лишних зависимостей 2021-12-10 15:08:04 +03:00
ece9b7cf70 Обновление подмодулей 2021-10-07 09:19:51 +03:00
bb580c0938 Правка сигнатуры для компиляции в Smolensk 1.5 2021-09-20 11:41:14 +03:00
547a127956 Исправлен деструктор 2021-09-20 11:35:36 +03:00
554ab7efdf Ещё вариант 2021-09-20 11:34:33 +03:00
7319a202c3 Новый вариант 2021-09-20 11:32:28 +03:00
c1235edaa9 Правка для Smolensk 1.5 2021-09-20 11:24:37 +03:00
a4ea9864be Правка для Smolensk 1.5 2021-09-20 11:22:05 +03:00
347ef3d46d Классы и пример для журналирования (простой вывод и в syslog) 2021-09-17 14:35:10 +03:00
b21def5945 Обновление подмодулей 2021-08-02 18:00:55 +03:00
cfe4fe8a2e Обновление подмодулей 2021-08-02 14:34:42 +03:00
11c572a96c Merge branch 'master' of gitlab.2:f1x1t/myxlib 2021-07-27 13:30:27 +03:00
e3d5243f80 Обновление CMLib 2021-07-27 13:30:01 +03:00
3f633ee15c Обновление подмодулей 2021-07-06 05:35:28 +03:00
458dcd82c6 Обновление подмодулей 2021-07-06 05:00:46 +03:00
a4b181a838 Поддержка версии Elbrus-D 2021-07-05 13:43:04 +03:00
2261982479 Определение параметров текущей ОС во время выполнения 2021-07-05 13:11:00 +03:00
d159417bbb Обновление подмодулей 2021-07-05 10:58:56 +03:00
66ddb8a1fb Merge branch 'master' of gitlab.2:f1x1t/myxlib 2021-07-02 10:50:25 +03:00
dd1010a826 Обновление подмодулей 2021-07-02 10:50:18 +03:00
35ad2e1db8 Обновление подмодулей 2021-06-30 16:54:16 +03:00
7d0c2f68d6 Обновление подмодулей 2021-06-30 10:48:29 +03:00
7396f77054 Модули для поиска с помощью CMake 2021-06-24 11:38:58 +03:00
3d3690ca64 Цель для установки заголовочных файлов 2021-06-24 11:36:53 +03:00
105ed96f5f Обновление подмодулей 2021-06-24 10:39:43 +03:00
5645c5ea31 Примеры скриптов для поиска через find_package 2021-06-22 17:35:13 +03:00
e63e6a4c8a Обновление подмодулей 2021-06-21 13:02:54 +03:00
a017ca6814 Поддержка использования внешней CMLib 2021-06-18 01:16:37 +03:00
8114675c1c Удалён подмодуль cmake/doc 2021-06-18 00:59:05 +03:00
d839fa6ed4 Обновление CMLib 2021-06-17 15:51:28 +03:00
a368091252 Инициализация по умолчанию в конструкторе 2021-06-16 11:43:13 +03:00
9468f95dd3 Обновление CMLib 2021-06-15 10:46:37 +03:00
56a0b595d2 Merge branch 'master' of gitlab.2:f1x1t/myxlib 2021-06-12 14:52:34 +03:00
716545e49c Обновление подмодулей 2021-06-12 14:52:25 +03:00
b575634554 Обновление подмодулей 2021-06-11 09:52:58 +03:00
299dabf295 Путь к общему каталогу для темы (работы) 2021-06-11 08:52:57 +03:00
a29cea6f61 Упрощение и правка автоопределения в /opt 2021-06-11 08:21:00 +03:00
360b2b41d1 Переименования 2021-06-10 07:21:54 +03:00
297b04bd56 Обновление логики поиска и формирования стандартных каталогов 2021-06-09 17:34:52 +03:00
3b2332a82f Merge branch 'master' of git.246060.ru:f1x1t/myxlib into temp 2021-06-09 13:32:06 +03:00
2d1537a9b8 Обновление CMLib 2021-06-08 19:47:03 +03:00
77683831b9 Исправлена ошибка при установке myx/core 2021-06-08 19:43:11 +03:00
c1c0325bce Тест 2 2021-06-07 16:49:04 +03:00
5d2098b4fc Тест 1 2021-06-04 16:03:01 +03:00
feda5be3ba Изменены правила для /usr/local/ORG 2021-06-04 13:16:29 +03:00
29b56561ca Исправлена работа с автогенерируемыми заголовочными файлами 2021-06-01 14:24:25 +03:00
b2cb06853e Название организации 2021-05-31 00:31:29 +03:00
fcac4dd4fe Правка предупреждений 2021-05-30 22:52:44 +03:00
9f62d67135 Исправлена работа с типом void_t для стандартов новее 17 2021-05-30 22:19:03 +03:00
d1fbeb9400 Исправлено условие для подключения <span> 2021-05-30 21:14:34 +03:00
4024029944 Переименованы стандартные каталоги для данных (data->share, lib->var) 2021-05-25 15:07:25 +03:00
5dff256613 Исправлено возвращаемое значение 2021-03-26 11:09:58 +03:00
668af95136 Функции для создания каталогов, используемых по умолчанию 2021-03-26 10:39:51 +03:00
82b7c2ea51 Правило для проверки форматирования 2021-02-19 11:15:15 +03:00
15e19333a0 Обновление 2020-12-23 11:11:17 +03:00
f152ba8017 Обновление подмодулей 2020-12-23 09:37:34 +03:00
1fb71f4481 Форматирование кода 2020-12-21 16:09:29 +03:00
6aeedb2bd1 Обновление подмодулей 2020-12-07 17:10:49 +03:00
39b264628c Merge branch 'master' of git.246060.ru:f1x1t/myxlib 2020-12-07 16:04:29 +03:00
ac6ae7b24d Форматирование кода 2020-12-07 16:04:06 +03:00
cb6a82d9b5 Форматирование кода 2020-12-02 21:24:11 +03:00
827f153c2e Merge branch 'master' of gitlab.2:f1x1t/myxlib 2020-12-01 19:56:37 +03:00
1af27eaf54 Обновление подмодулей 2020-12-01 19:56:25 +03:00
1abebc0be6 Обновление подмодулей 2020-11-13 11:39:16 +03:00
0a544a773d Merge branch 'master' of gitlab.2:f1x1t/myxlib 2020-10-15 06:57:48 +03:00
661b63f963 Обновление подмодулей 2020-10-15 06:57:40 +03:00
7c2d52172c Обновление подмодулей 2020-10-12 16:47:42 +03:00
c5a9b5118b Обновление подмодулей 2020-09-24 13:12:23 +03:00
ee681940c5 Обновление подмодулей 2020-08-03 15:19:05 +03:00
7b0128dfe3 Обновление подмодулей 2020-07-23 10:25:25 +03:00
c418aa8df0 Обновление подмодулей 2020-07-23 10:23:42 +03:00
d951fd81cb Убраны предупреждения 2020-07-22 15:57:41 +03:00
078732d308 Мелкие правки 2020-07-10 15:29:51 +03:00
3c628659bc Дополнительные вызовы для инициализации путей 2020-07-10 15:28:26 +03:00
4519190768 Ещё правка 2020-07-10 11:13:02 +03:00
f59e96bcaf Правка совместимости с Смоленск 1.5 2020-07-10 11:08:33 +03:00
f3c7ff25cf Отмена установки примеров (временно) 2020-07-09 15:46:50 +03:00
1053e70360 Правки 2020-07-09 15:46:02 +03:00
ec720ff8f4 Правка условий 2020-07-09 15:45:32 +03:00
e97025a81e Корректное подключение макроса QT_VERSION 2020-07-09 15:17:23 +03:00
de1c396a5e make_unique 2020-07-09 15:05:59 +03:00
11866bf3ba Ещё правка для Смоленск 1.5 2020-07-02 16:00:35 +03:00
bad24e34c7 Правка для Смоленск 1.5 2020-07-02 15:58:28 +03:00
d124aeb9dd Правка для Эльбруса 2020-07-02 15:53:31 +03:00
6358fe0820 Переделана структура проекта 2020-06-30 20:04:26 +03:00
cf52aba9a3 Заголовочный файл 2020-06-29 22:26:51 +03:00
3cb5cbd6c1 Инициализация 2020-06-29 22:24:15 +03:00
a4d00ed80b Библиотека требует сборки в объектный файл (из-за moc) 2020-06-28 09:52:03 +03:00
ca83f98484 PosixSignalWatcher 2020-06-27 10:04:56 +03:00
44cd25464f Обновление подмодулей 2020-06-27 06:36:31 +03:00
0557003117 Добавлены правила для Сирены 2020-06-25 04:22:30 +03:00
5f3831c935 Исправлено возвращаемое значение 2020-06-24 09:44:19 +03:00
57118ea2bb Обновление подмодулей 2020-06-15 15:56:47 +03:00
b86cf01973 Обновлён алгоритм работы с каталогами 2020-06-03 12:20:59 +03:00
395ffb080a Добавлены операторы 2020-05-25 17:24:27 +03:00
d96ee1ee57 Правка правил автосборки 2020-05-17 10:57:25 +03:00
dbf287e2e9 Исправлена ошибка 2020-05-15 20:24:44 +03:00
e0c9e2f551 Чистка кода 2020-05-15 20:14:21 +03:00
27b3f4182a Пример endian 2020-05-15 20:12:52 +03:00
24cb2afb8e endian_types использует span 2020-05-15 19:03:14 +03:00
dfaa03647f Включение простейшего span из boost 2020-05-15 17:38:52 +03:00
ab09914434 Исправлено имя 2020-05-15 15:55:11 +03:00
dfacad2da1 Правка условий поиска каталогов 2020-05-15 15:54:31 +03:00
c503edfe49 Переписаны условия для формирования имён каталогов 2020-05-15 13:17:50 +03:00
d9881f92b3 Значения возвращаются как const QString& 2020-05-15 11:13:26 +03:00
09d1e12a44 Добавлен файл с типами для прозрачного преобразования порядка байтов 2020-05-14 10:43:38 +03:00
f845b2fda1 Убрано предупреждение 2020-05-06 18:03:51 +03:00
87f4c854d8 Обновление подмодулей 2020-05-06 17:59:39 +03:00
00be8cd00f Математические функции перенесены в отдельную библиотеку 2020-04-27 11:13:15 +03:00
d264077648 Обновление 2020-04-27 10:25:29 +03:00
94616ba6bc Библиотека Redis вынесена в отдельный проект 2020-04-27 08:59:52 +03:00
b41f17a9b2 Добавлен клиент Redis 2020-04-26 21:38:35 +03:00
c1740b2223 Пример клиента для Redis 2020-04-26 20:42:43 +03:00
63cd7ff613 Орфография 2020-04-26 20:07:03 +03:00
14b9c97bb2 Исправлены ошибки компоновки 2020-04-26 19:52:20 +03:00
c321076f96 Правка параметров проекта 2020-04-26 18:57:17 +03:00
ea58c525eb Чистка кода 2020-04-26 18:56:49 +03:00
477cebf235 Обновление 2020-04-25 14:51:04 +03:00
5936bf96f0 Новая библиотека для Redis 2020-04-25 11:41:19 +03:00
37fd015311 Первое приближение для новой библиотеки Redis 2020-04-25 08:45:05 +03:00
e6253e777f Ключи для сборки проекта 2020-04-24 22:41:55 +03:00
a88d8acf9e Сборка пакетов 2020-04-24 22:36:33 +03:00
9264e46152 Обновление подмодулей 2020-04-24 20:53:08 +03:00
407d073f23 Обновление подмодулей 2020-04-24 20:41:27 +03:00
f3ba15d64d Ошибка в порождении сигнала 2020-04-24 18:14:01 +03:00
b16bab5fed Закончена основа библиотеки для работы с Redis 2020-04-24 17:13:33 +03:00
8ff24d264c Пример Redis 2020-04-24 14:27:19 +03:00
ab825123f2 Дополнительные проверки 2020-04-24 14:26:58 +03:00
0b6132d692 Убрана константность 2020-04-24 12:30:25 +03:00
2bf177affe Исправлены правила для сборки примеров 2020-04-24 12:19:59 +03:00
d06bc7644d Почти исправлена система сборки 2020-04-24 12:09:57 +03:00
71e8dd0202 Пример Redis 2020-04-23 23:36:49 +03:00
8744da7759 config 2020-04-23 20:22:57 +03:00
dd015a3143 Корректная работа при работе с moc 2020-04-23 20:21:43 +03:00
36a2a1d2c6 Ещё удалены конструкторы и операторы присвоения по умолчанию 2020-04-23 14:17:08 +03:00
d244c67cba Функции помечены как inline 2020-04-23 14:05:17 +03:00
45fa0f4f73 Удалены конструкторы и операторы присвоения по умолчанию 2020-04-23 13:59:29 +03:00
d7968819b7 Рефакторинг Redis 2020-04-23 13:59:14 +03:00
16b6b5b322 Рефакторинг Redis 2020-04-23 13:14:15 +03:00
b242a96259 Рефакторинг Redis 2020-04-23 12:49:49 +03:00
f308e935fb Игнорирование каталога создаваемого Qt Creator 2020-04-23 12:13:08 +03:00
cde0cf76a7 Разные правки 2020-04-23 12:11:03 +03:00
8d9a5590d7 Рефакторинг библиотеки для Redis 2020-04-23 12:10:15 +03:00
aa1f06b306 Правка работы с pkg-config 2020-04-22 22:28:14 +03:00
114 changed files with 6290 additions and 3089 deletions

View File

@ -18,6 +18,8 @@ portability-*,
-readability-else-after-return,
-modernize-use-trailing-return-type,
-modernize-avoid-c-arrays,
-modernize-use-nodiscard,
-modernize-concat-nested-namespaces,
-performance-no-automatic-move,
'
@ -37,7 +39,7 @@ CheckOptions:
- key: readability-identifier-naming.ClassConstantCase
value: CamelCase
- key: readability-identifier-naming.ClassConstantPrefix
value: 'k_'
value: 'k'
- key: readability-identifier-naming.ClassConstantSuffix
value: ''
- key: readability-identifier-naming.ClassMemberCase
@ -55,7 +57,7 @@ CheckOptions:
- key: readability-identifier-naming.ConstantCase
value: CamelCase
- key: readability-identifier-naming.ConstantPrefix
value: 'k_'
value: 'k'
- key: readability-identifier-naming.ConstantSuffix
value: POST
- key: readability-identifier-naming.ConstantMemberCase
@ -91,7 +93,7 @@ CheckOptions:
- key: readability-identifier-naming.ConstexprVariableCase
value: CamelCase
- key: readability-identifier-naming.ConstexprVariablePrefix
value: 'k_'
value: 'k'
- key: readability-identifier-naming.ConstexprVariableSuffix
value: ''
- key: readability-identifier-naming.EnumCase
@ -119,7 +121,7 @@ CheckOptions:
- key: readability-identifier-naming.GlobalConstantSuffix
value: ''
- key: readability-identifier-naming.GlobalConstantPointerCase
value: lower_case
value: CamelCase
- key: readability-identifier-naming.GlobalConstantPointerPrefix
value: ''
- key: readability-identifier-naming.GlobalConstantPointerSuffix
@ -142,6 +144,8 @@ CheckOptions:
value: ''
- key: readability-identifier-naming.GlobalVariableSuffix
value: ''
- key: readability-identifier-naming.IgnoreMainLikeFunctions
value: 1
- key: readability-identifier-naming.InlineNamespaceCase
value: lower_case
- key: readability-identifier-naming.InlineNamespacePrefix
@ -223,7 +227,7 @@ CheckOptions:
- key: readability-identifier-naming.ProtectedMemberCase
value: camelBack
- key: readability-identifier-naming.ProtectedMemberPrefix
value: ''
value: 'm_'
- key: readability-identifier-naming.ProtectedMemberSuffix
value: ''
- key: readability-identifier-naming.ProtectedMethodCase
@ -245,15 +249,15 @@ CheckOptions:
- key: readability-identifier-naming.PublicMethodSuffix
value: ''
- key: readability-identifier-naming.StaticConstantCase
value: camelBack
value: CamelCase
- key: readability-identifier-naming.StaticConstantPrefix
value: 'k_'
value: 'k'
- key: readability-identifier-naming.StaticConstantSuffix
value: ''
- key: readability-identifier-naming.StaticVariableCase
value: camelBack
value: CamelCase
- key: readability-identifier-naming.StaticVariablePrefix
value: ''
value: 's'
- key: readability-identifier-naming.StaticVariableSuffix
value: ''
- key: readability-identifier-naming.StructCase

248
.cmake-format.py Normal file
View File

@ -0,0 +1,248 @@
#!/usr/bin/env python3
# ----------------------------------
# Options affecting listfile parsing
# ----------------------------------
with section("parse"):
# Specify structure for custom cmake functions
additional_commands = {
'add_doxygen': { 'flags' : [],
'kwargs': { 'LATEX': 1,
'HTML': 1,
'COMMENT': 1}},
'add_breathe': { 'flags' : [],
'kwargs': { 'COMMENT': 1}},
'add_common_library': { 'flags' : [],
'kwargs': { 'OUTPUT_NAME': 1,
'SOURCES': '*',
'TARGET': 1}},
'qt5_translation': { 'flags' : [],
'kwargs': { 'OUTPUT_DIR': 1,
'LANGUAGES': '*',
'SOURCES': '*',
'BASE_NAME': 1}},
'pvs_studio_add_target': { 'flags' : [ 'COMPILE_COMMANDS',
'OUTPUT',
'HIDE_HELP'],
'kwargs': { 'ARGS': '*',
'CONFIG': '*',
'DEPENDS': '*',
'FORMAT': '*',
'MODE': '*',
'TARGET': 1}},
'write_compiler_detection_header': { 'flags' : [],
'kwargs': { 'COMPILERS': '*',
'FEATURES': '*',
'FILE': '*',
'PREFIX': '*'}}}
# Specify variable tags.
vartags = []
# Specify property tags.
proptags = []
# -----------------------------
# Options affecting formatting.
# -----------------------------
with section("format"):
# How wide to allow formatted cmake files
line_width = 110
# How many spaces to tab for indent
tab_size = 2
# If an argument group contains more than this many sub-groups (parg or kwarg
# groups) then force it to a vertical layout.
max_subgroups_hwrap = 3
# If a positional argument group contains more than this many arguments, then
# force it to a vertical layout.
max_pargs_hwrap = 5
# If a cmdline positional group consumes more than this many lines without
# nesting, then invalidate the layout (and nest)
max_rows_cmdline = 2
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on its own line.
dangle_parens = False
# If the trailing parenthesis must be 'dangled' on its on line, then align it
# to this reference: `prefix`: the start of the statement, `prefix-indent`:
# the start of the statement, plus one indentation level, `child`: align to
# the column of the arguments
dangle_align = 'prefix'
# If the statement spelling length (including space and parenthesis) is
# smaller than this amount, then force reject nested layouts.
min_prefix_chars = 4
# If the statement spelling length (including space and parenthesis) is larger
# than the tab width by more than this amount, then force reject un-nested
# layouts.
max_prefix_chars = 2
# If a candidate layout is wrapped horizontally but it exceeds this many
# lines, then reject the layout.
max_lines_hwrap = 2
# What style line endings to use in the output.
line_ending = 'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = 'canonical'
# Format keywords consistently as 'lower' or 'upper' case
keyword_case = 'upper'
# A list of command names which should always be wrapped
always_wrap = []
# If true, the argument lists which are known to be sortable will be sorted
# lexicographicall
enable_sort = True
# If true, the parsers may infer whether or not an argument list is sortable
# (without annotation).
autosort = False
# By default, if cmake-format cannot successfully fit everything into the
# desired linewidth it will apply the last, most agressive attempt that it
# made. If this flag is True, however, cmake-format will print error, exit
# with non-zero status code, and write-out nothing
require_valid_layout = False
# A dictionary mapping layout nodes to a list of wrap decisions. See the
# documentation for more information.
layout_passes = {}
# ------------------------------------------------
# Options affecting comment reflow and formatting.
# ------------------------------------------------
with section("markup"):
# What character to use for bulleted lists
bullet_char = '*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = '.'
# If comment markup is enabled, don't reflow the first comment block in each
# listfile. Use this to preserve formatting of your copyright/license
# statements.
first_comment_is_literal = False
# If comment markup is enabled, don't reflow any comment block which matches
# this (regex) pattern. Default is `None` (disabled).
literal_comment_pattern = None
# Regular expression to match preformat fences in comments default=
# ``r'^\s*([`~]{3}[`~]*)(.*)$'``
fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$'
# Regular expression to match rulers in comments default=
# ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'``
ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$'
# If a comment line matches starts with this pattern then it is explicitly a
# trailing comment for the preceeding argument. Default is '#<'
explicit_trailing_pattern = '#<'
# If a comment line starts with at least this many consecutive hash
# characters, then don't lstrip() them off. This allows for lazy hash rulers
# where the first hash char is not separated by space
hashruler_min_length = 10
# If true, then insert a space between the first hash char and remaining hash
# chars in a hash ruler, and normalize its length to fill the column
canonicalize_hashrulers = True
# enable comment markup parsing and reflow
enable_markup = False
# ----------------------------
# Options affecting the linter
# ----------------------------
with section("lint"):
# a list of lint codes to disable
disabled_codes = ['C0113']
# regular expression pattern describing valid function names
function_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid macro names
macro_pattern = '[0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope
global_var_pattern = '[0-9A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with global
# scope (but internal semantic)
internal_var_pattern = '_[0-9A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for variables with local
# scope
local_var_pattern = '[0-9a-z_]+'
# regular expression pattern describing valid names for privatedirectory
# variables
private_var_pattern = '_[0-9a-z_]+'
# regular expression pattern describing valid names for publicdirectory
# variables
public_var_pattern = '[0-9A-Z][0-9A-Z_]+'
# regular expression pattern describing valid names for keywords used in
# functions or macros
keyword_pattern = '[0-9A-Z_]+'
# In the heuristic for C0201, how many conditionals to match within a loop in
# before considering the loop a parser.
max_conditionals_custom_parser = 2
# Require at least this many newlines between statements
min_statement_spacing = 1
# Require no more than this many newlines between statements
max_statement_spacing = 2
max_returns = 6
max_branches = 12
max_arguments = 5
max_localvars = 15
max_statements = 50
# -------------------------------
# Options affecting file encoding
# -------------------------------
with section("encode"):
# If true, emit the unicode byte-order mark (BOM) at the start of the file
emit_byteorder_mark = False
# Specify the encoding of the input file. Defaults to utf-8
input_encoding = 'utf-8'
# Specify the encoding of the output file. Defaults to utf-8. Note that cmake
# only claims to support utf-8 so be careful when using anything else
output_encoding = 'utf-8'
# -------------------------------------
# Miscellaneous configurations options.
# -------------------------------------
with section("misc"):
# A dictionary containing any per-command configuration overrides. Currently
# only `command_case` is supported.
per_command = {}

240
.gitignore vendored
View File

@ -1,7 +1,243 @@
CMakeLists.txt.user*
# Каталог для результатов сборки проекта
_build
build
# Каталог для тестирования установки
_output
*.autosave
# Файлы настроек, редактируемые во время отладки,
# за исключением шаблонных файлов
files/etc/*.conf
!files/etc/*.example.conf
# Каталоги, в которые разрешена запись данных во время работы программы
files/lib/*
files/log/*
!.gitkeep
!.gitignore
###
### Общие настройки для C, C++, Fortran, Qt, CMake, Ninja, LaTeX и редакторов
###
###
### Временные файлы текстовых редакторов
###
*.bak
*.gho
*.tmp
*.dotdropbak
###
### LyX
###
*.lyx~
*.lyx#
###
### Vim
###
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Project
.vimprj
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
###
### C++
###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
###
### CMake
###
CMakeLists.txt.user*
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
### CMake Patch ###
# External projects
*-prefix/
###
### Ninja
###
.ninja_deps
.ninja_log
###
### GCC coverage testing tool files
###
*.gcno
*.gcda
*.gcov
###
### Qt
###
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator local machine specific files for imported projects
*creator.user*
*_qmlcache.qrc
### KDevelop4 ###
*.kdev4
.kdev4/
### vscode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
### Eclipse ###
.metadata
.settings/
.recommenders/
# TeXlipse
.texlipse
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
###
### Latex
###
*.acn
*.acr
*.alg
*.aux
*.bbl
*.blg
*.dvi
*.fdb_latexmk
*.fls
*.glg
*.glo
*.gls
*.idx
*.ilg
*.ind
*.ist
*.lof
*.log
*.lot
*.maf
*.mtc
*.mtc0
*.nav
*.nlo
*.out
*.pdfsync
*.ps
*.snm
*.synctex.gz
*.toc
*.vrb
*.xdv
*.xdy
*.tdo

View File

@ -1,5 +1,7 @@
include:
- local: .gitlab-ci/scheduled.yml
- project: 'f1x1t/gitlab-ci'
ref: master
file: 'scheduled.yml'
smolensk15-nightly:
extends: .scheduled-smolensk15
@ -16,3 +18,7 @@ focal-nightly:
elbrus-nightly:
extends: .scheduled-elbrus
check-format-sources:
only:
- merge_requests
extends: .check-format-sources

View File

@ -1,78 +0,0 @@
variables:
GIT_SUBMODULE_STRATEGY: recursive
GET_SOURCES_ATTEMPTS: 10
.scheduled-test:
only:
refs:
- schedules
cache:
paths: ['*.status']
before_script:
- >
if [ -f "${CI_JOB_NAME}.status" ]; then
if [ "$(cat ${CI_JOB_NAME}.status)" == "${CI_COMMIT_SHA}" ]; then
echo "=== Commit ${CI_COMMIT_SHORT_SHA} already tested with job ${CI_JOB_NAME} ==="
exit 0
fi
fi
- >
if [ -n "${APT_UPDATE_CMD}" ]; then
${APT_UPDATE_CMD}
fi
- >
if [ -n "${APT_INSTALL_CMD}" ]; then
${APT_INSTALL_CMD}
fi
script:
- >
if [ -f "${CI_JOB_NAME}.status" ]; then
if [ "$(cat ${CI_JOB_NAME}.status)" == "${CI_COMMIT_SHA}" ]; then
echo "=== Commit ${CI_COMMIT_SHORT_SHA} already tested with job ${CI_JOB_NAME} ==="
exit 0
fi
fi
- rm -f ${CI_JOB_NAME}.status
- mkdir build
- cd build
- cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=_output -DCPACK_PACKAGING_INSTALL_PREFIX=/opt/rtis ..
- ninja
- >
if [ -z "${CI_SHARED_ENVIRONMENT+x}" ]; then
ninja install
ninja package
ninja package_source
fi
- echo "${CI_COMMIT_SHA}" > "../${CI_JOB_NAME}.status"
artifacts:
paths:
- build/*.xz
- build/*.deb
when: on_success
expire_in: 10 days
.scheduled-smolensk15:
extends: .scheduled-test
image: smolensk15-dev
tags: ['docker']
.scheduled-orel212:
extends: .scheduled-test
image: orel212-dev
tags: ['docker']
.scheduled-bionic:
extends: .scheduled-test
image: bionic-dev
tags: ['docker']
.scheduled-focal:
extends: .scheduled-test
image: focal-dev
tags: ['docker']
.scheduled-elbrus:
extends: .scheduled-test
tags: ['elbrus']

15
.gitmodules vendored
View File

@ -1,15 +0,0 @@
[submodule "cmake/etc/uncrustify"]
path = cmake/etc/uncrustify
url = ../../f1x1t/uncrustify-config.git
[submodule "cmake/cmlib"]
path = cmake/cmlib
url = ../../f1x1t/cmlib
[submodule "cmake/find"]
path = cmake/find
url = ../../f1x1t/cmake-find
[submodule "cmake/generators"]
path = cmake/generators
url = ../../f1x1t/cmake-generators
[submodule "cmake/doc"]
path = cmake/doc
url = ../../f1x1t/cmake-doc

3371
.uncrustify.cfg Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,15 +3,13 @@ cmake_minimum_required(VERSION 3.3)
cmake_policy(VERSION 3.0.2..3.7)
# Название проекта
project(myx VERSION 0.4.0 LANGUAGES C CXX)
project(myx VERSION 0.9.0 LANGUAGES C CXX)
# В каталоге cmake/lib находятся файлы с библиотечными функциями
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib)
else()
message(FATAL_ERROR "CMake library directory not exists")
endif()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/find)
# Обязательные переменные
set(MYX_CMAKE_ORGANIZATION_NAME "ECS5" CACHE STRING "")
set(MYX_CMAKE_AUTHOR_NAME "Андрей Астафьев" CACHE STRING "")
set(MYX_CMAKE_AUTHOR_EMAIL "dev@246060.ru" CACHE STRING "")
set(MYX_CMAKE_DESCRIPTION "Разные функции" CACHE STRING "")
if(NOT DEFINED MYXLIB_MASTER_PROJECT)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
@ -21,13 +19,10 @@ if(NOT DEFINED MYXLIB_MASTER_PROJECT)
endif()
endif()
include(CMLibCommon)
find_package(MyxCMake 0.4.5 REQUIRED)
option(MYXLIB_BUILD_LIBRARIES "Build libraries" OFF)
if(MYXLIB_BUILD_LIBRARIES)
option(MYXLIB_BUILD_EXAMPLES "Build examples" OFF)
endif()
option(MYXLIB_BUILD_EXAMPLES_HO "Build examples using header only version" OFF)
#cmlib_set_cxx_standard(11)
option(MYXLIB_BUILD_EXAMPLES "Build examples" OFF)
# Поиск библиотек с помощью pkgconfig
find_package(PkgConfig REQUIRED)
@ -39,18 +34,28 @@ find_package(Threads REQUIRED)
# Qt5
find_package(Qt5 COMPONENTS Core Network REQUIRED)
myx_cmake_generate_private_config_header()
# Библиотеки
add_subdirectory(src/myx/base)
add_subdirectory(src/myx/backports/compiler)
add_subdirectory(src/myx/backports/cpp)
add_subdirectory(src/myx/backports/qt)
add_subdirectory(src/myx/core)
add_subdirectory(src/myx/filesystem)
add_subdirectory(src/myx/qt)
add_subdirectory(src/myx/math)
# add_subdirectory(src/myx/redis)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(myxlib-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=dev -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
# Примеры
if(MYXLIB_BUILD_EXAMPLES OR MYXLIB_BUILD_EXAMPLES_HO)
if(MYXLIB_BUILD_EXAMPLES)
add_subdirectory(examples/core)
add_subdirectory(examples/filesystem)
add_subdirectory(examples/qt)
add_custom_target(examples example-core-endian example-filesystem-paths example-qt-tranlators
example-qt-posix-signal-watcher)
endif()
# Документация
add_subdirectory(cmake/doc)
myx_cmake_doc_doxygen(LATEX YES HTML YES)
myx_cmake_doc_breathe()

Submodule cmake/cmlib deleted from 197e5b3939

Submodule cmake/doc deleted from acdfb6a9dd

View File

@ -1,14 +0,0 @@
set(ORGANIZATION_NAME "RTIS")
set(AUTHOR_NAME "Андрей Астафьев")
set(DOXYGEN_PROJECT_TITLE "MyXLib")
set(DOXYGEN_GENERATE_LATEX YES)
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_GENERATE_SQLITE YES)
set(CPACK_COMPONENTS_ALL EXAMPLES)
set(CPACK_GENERATOR "TXZ;DEB")
set(CPACK_PACKAGE_CONTACT "Andrei Astafev <dev@246060.ru>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Mixed functions")
set(CMLIB_GENERATED_HEADERS_PATH ${CMAKE_BINARY_DIR}/include/myx/base)

Submodule cmake/find deleted from d0bc6e71e9

Submodule cmake/generators deleted from 74d499b9cb

View File

@ -0,0 +1,21 @@
# Название основной цели в текущем каталоге
set(TRGT example-core-endian)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/endian.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME endian-minimal)
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,24 @@
#include <myx/core/config.hpp>
#include <myx/core/endian_types.hpp>
#include <QDebug>
//NOLINTNEXTLINE
#define CMLIB_PROJECT_NAME "myxlib"
int main( int argc, char** argv )
{
(void)argc;
(void)argv;
beint64 bi = 1;
int64_t bii = reinterpret_cast< int64_t* >( &bi )[0]; //NOLINT
qDebug() << hex << bi << bii;
leint64 li = 1;
int64_t lii = reinterpret_cast< int64_t* >( &li )[0]; //NOLINT
qDebug() << hex << li << lii;
return( 0 );
} // main

View File

@ -0,0 +1,21 @@
# Название основной цели в текущем каталоге
set(TRGT example-core-current-system)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/current_system.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME current-system-minimal)
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,23 @@
#include <myx/core/config.hpp>
#include <myx/core/current_system.hpp>
#include <QDebug>
//NOLINTNEXTLINE
#define CMLIB_PROJECT_NAME "myxlib"
namespace MC = myx::core;
int main( int argc, char** argv )
{
(void)argc;
(void)argv;
MC::CurrentSystem& currentSystem = MC::CurrentSystem::instance();
qDebug() << "Current OS: " << QString::fromStdString( currentSystem.os() );
qDebug() << "OS distrib: " << QString::fromStdString( currentSystem.distribution() );
qDebug() << "OS variant: " << QString::fromStdString( currentSystem.variant() );
qDebug() << "OS version: " << QString::fromStdString( currentSystem.version() );
return( 0 );
} // main

View File

@ -0,0 +1,2 @@
add_subdirectory(01_endian)
add_subdirectory(02_current-system)

View File

@ -1,76 +0,0 @@
# Название основной цели в текущем каталоге
set(TRGT example-filesystem-minimal)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/minimal.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Путь поиска библиотек внутри проекта
link_directories(${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp})
target_include_directories(${TRGT} PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
add_dependencies(${TRGT} base_static filesystem_static)
target_link_libraries(${TRGT} myx-filesystem)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME filesystem-minimal)
add_sanitizers(${TRGT})
cotire(${TRGT})
add_dependencies(${TRGT} create_auxilary_symlinks)
# Правила для установки
install(TARGETS ${TRGT} COMPONENT examples RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(MYXLIB_BUILD_EXAMPLES_HO)
# Цель для создания исполняемого файла
add_executable(${TRGT}-ho ${TRGT_cpp} ${TRGT_qrc})
common_target_properties(${TRGT}-ho)
target_include_directories(${TRGT}-ho PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${TRGT}-ho SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT}-ho base-header-only filesystem-header-only)
target_link_libraries(${TRGT}-ho Qt5::Core)
target_link_libraries(${TRGT}-ho Threads::Threads)
# Имя выходного файла для цели
set_target_properties(${TRGT}-ho PROPERTIES OUTPUT_NAME filesystem-minimal-ho)
add_sanitizers(${TRGT}-ho)
cotire(${TRGT}-ho)
add_dependencies(${TRGT}-ho create_auxilary_symlinks)
# Правила для установки
install(TARGETS ${TRGT}-ho COMPONENT examples RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()

View File

@ -1,37 +0,0 @@
#include <myx/base/config.hpp>
#include <myx/filesystem/paths.hpp>
#include <myx/filesystem/paths_mt.hpp>
#include <QCoreApplication>
#include <QDebug>
#define CMLIB_PROJECT_NAME "myxlib"
namespace MF = myx::filesystem;
// Переменные для защиты экземпляра класса MF::PathsMT
std::atomic< MF::PathsMT* > MF::PathsMT::mInstance;
std::mutex MF::PathsMT::mMutex;
int main( int argc, char** argv )
{
(void)argc;
(void)argv;
QCoreApplication::setApplicationName( QStringLiteral( CMLIB_PROJECT_NAME ) );
MF::PathsMT& pathsMT = MF::PathsMT::instance();
MF::Paths& paths = MF::Paths::instance();
pathsMT.init( QStringLiteral( CMLIB_PROJECT_NAME ), QStringLiteral( "conf" ) );
pathsMT.findConfigFile( QStringLiteral( "test" ) );
qDebug() << pathsMT.systemLogDirectory().path();
qDebug() << pathsMT.systemConfigDirectory().path();
paths.init( QStringLiteral( CMLIB_PROJECT_NAME ), QStringLiteral( "conf" ) );
paths.findConfigFile( QStringLiteral( "test" ) );
qDebug() << paths.systemConstDataDirectory().path();
qDebug() << paths.configFileName();
return( 0 );
}

View File

@ -0,0 +1,22 @@
# Название основной цели в текущем каталоге
set(TRGT example-filesystem-paths)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME filesystem-minimal)
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core filesystem)
target_link_libraries(${TRGT} filesystem-static)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,40 @@
#include <myx/core/config.hpp>
#include <myx/filesystem/paths.hpp>
#include <QCoreApplication>
#include <QDebug>
//NOLINTNEXTLINE
#define CMLIB_PROJECT_NAME "myxlib"
namespace MF = myx::filesystem;
int main( int argc, char** argv )
{
(void)argc;
(void)argv;
QCoreApplication::setApplicationName( QStringLiteral( CMLIB_PROJECT_NAME ) );
MF::Paths& paths = MF::Paths::instance();
qDebug() << "prefixDirectory : " << paths.projectDirectory();
qDebug() << "executableName : " << paths.executableName();
qDebug() << "executableFilePath : " << paths.executableFilePath();
qDebug() << "executableDirectory : " << paths.executableDirectory() << endl;
qDebug() << "systemThemeDirectory : " << paths.systemThemeDirectory();
qDebug() << "systemConfigDirectory : " << paths.systemConfigDirectory();
qDebug() << "systemConstDataDirectory : " << paths.systemConstDataDirectory();
qDebug() << "systemVarDataDirectory : " << paths.systemVarDataDirectory();
qDebug() << "systemLogDirectory : " << paths.systemLogDirectory() << endl;
qDebug() << "userThemeDirectory : " << paths.userThemeDirectory();
qDebug() << "userConfigDirectory : " << paths.userConfigDirectory();
qDebug() << "userConstDataDirectory : " << paths.userConstDataDirectory();
qDebug() << "userVarDataDirectory : " << paths.userVarDataDirectory();
qDebug() << "userLogDirectory : " << paths.userLogDirectory();
return( 0 );
} // main

View File

@ -1 +1 @@
add_subdirectory(01_minimal)
add_subdirectory(01_paths)

View File

@ -4,80 +4,26 @@ set(TRGT example-qt-translators)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/translators.cpp)
qt5_translation(
myx_cmake_qt5_translation(
TRGT_qrc
OUTPUT_DIR ${CMAKE_SOURCE_DIR}/l10n
BASE_NAME ${TRGT}
LANGUAGES ru_RU)
if(MYXLIB_BUILD_EXAMPLES)
# Путь поиска библиотек внутри проекта
link_directories(${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp} ${TRGT_qrc})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp})
# Qt5
target_include_directories(${TRGT} PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_HEADER_ONLY)
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_dependencies(${TRGT} base qt)
target_link_libraries(${TRGT} Qt5::Core)
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME qt-translators)
add_sanitizers(${TRGT})
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core qt)
cotire(${TRGT})
target_link_libraries(${TRGT} qt-static)
add_dependencies(${TRGT} create_auxilary_symlinks)
# Правила для установки
install(TARGETS ${TRGT} COMPONENT examples RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
if(MYXLIB_BUILD_EXAMPLES_HO)
# Цель для создания исполняемого файла
add_executable(${TRGT}-ho ${TRGT_cpp} ${TRGT_qrc})
common_target_properties(${TRGT}-ho)
target_include_directories(${TRGT}-ho PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${TRGT}-ho SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT}-ho base-header-only qt-header-only)
target_link_libraries(${TRGT}-ho Qt5::Core)
target_link_libraries(${TRGT}-ho Threads::Threads)
# Имя выходного файла для цели
set_target_properties(${TRGT}-ho PROPERTIES OUTPUT_NAME qt-translators-ho)
add_sanitizers(${TRGT}-ho)
cotire(${TRGT}-ho)
add_dependencies(${TRGT}-ho create_auxilary_symlinks)
# Правила для установки
install(TARGETS ${TRGT}-ho COMPONENT examples RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,23 @@
# Название основной цели в текущем каталоге
set(TRGT example-qt-posix-signal-watcher)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/posix_signal_watcher.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME qt-posix-signal-watcher)
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core qt)
target_link_libraries(${TRGT} qt-static)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,21 @@
#include <myx/qt/posix_signal_watcher.hpp>
#include <QCoreApplication>
#include <QDebug>
namespace MQ = myx::qt;
int main( int argc, char* argv[] )
{
QCoreApplication app( argc, argv );
qDebug() << "Hello from process" << QCoreApplication::applicationPid();
MQ::PosixSignalWatcher sigwatch;
sigwatch.watchForSignal( SIGINT );
sigwatch.watchForSignal( SIGTERM );
QObject::connect( &sigwatch, &MQ::PosixSignalWatcher::posixSignal, &app, &QCoreApplication::quit );
int exitcode = QCoreApplication::exec();
qDebug() << "Goodbye";
return( exitcode );
}

View File

@ -0,0 +1,23 @@
# Название основной цели в текущем каталоге
set(TRGT example-qt-message-logger)
# Список файлов исходных текстов
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/message_logger.cpp)
if(MYXLIB_BUILD_EXAMPLES)
# Цель для создания исполняемого файла
add_executable(${TRGT} ${TRGT_cpp})
myx_cmake_common_target_properties(${TRGT})
# Имя выходного файла для цели
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME qt-message-logger)
# Qt5
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_dependencies(${TRGT} core qt)
target_link_libraries(${TRGT} qt-static)
target_link_libraries(${TRGT} Qt5::Core)
target_link_libraries(${TRGT} Threads::Threads)
endif()

View File

@ -0,0 +1,29 @@
#include <myx/qt/message_logger_default.hpp>
#include <myx/qt/message_logger_handler.hpp>
#include <myx/qt/message_logger_syslog.hpp>
#include <QCoreApplication>
#include <QDebug>
namespace MQ = myx::qt;
int main( int argc, char* argv[] )
{
QCoreApplication app( argc, argv );
auto mld = QSharedPointer< MQ::MessageLoggerDefault >( new MQ::MessageLoggerDefault );
MQ::messageLoggersList.append( mld );
MQ::messageLoggersList.append( mld );
auto mls = QSharedPointer< MQ::MessageLoggerSyslog >( new MQ::MessageLoggerSyslog );
MQ::messageLoggersList.append( mls );
qInstallMessageHandler( MQ::message_logger_handler );
qDebug() << "Hello from process:" << QCoreApplication::applicationPid();
qWarning() << "Warning";
qInstallMessageHandler( nullptr );
qDebug() << "Reset user handlers";
qWarning() << "Goodbye";
return( 0 );
}

View File

@ -1 +1,3 @@
add_subdirectory(01_translators)
add_subdirectory(02_posix-signal-watcher)
add_subdirectory(03_message-logger)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

0
files/var/.gitkeep Normal file
View File

View File

@ -1,17 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>QObject</name>
<message>
<location filename="../examples/qt/01_translators/translators.cpp" line="16"/>
<source>Yes</source>
<translation>Да</translation>
</message>
<message>
<location filename="../examples/qt/01_translators/translators.cpp" line="18"/>
<source>Cancel</source>
<translation>Отмена</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,21 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT backports-compiler)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/gcc.hpp
)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT} INTERFACE)
target_sources(${TRGT} INTERFACE ${TRGT_cpp} ${TRGT_headers})
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/backports/compiler)

View File

@ -0,0 +1,29 @@
#ifndef MYX_BACKPORTS_COMPILER_GCC_HPP_
#define MYX_BACKPORTS_COMPILER_GCC_HPP_
#pragma once
#ifdef __GNUC__
// NOLINTNEXTLINE
#define GCC_VERSION ( __GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ )
#if GCC_VERSION <= 40702
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif
#if ( __cplusplus < 201103L )
#define constexpr
#endif
#define override
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif // if GCC_VERSION <= 40702
#endif // ifdef __GNUC__
#endif // ifndef MYX_BACKPORTS_COMPILER_GCC_HPP_

View File

@ -0,0 +1,22 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT backports-cpp)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/helpers.hpp
${CMAKE_CURRENT_SOURCE_DIR}/span.hpp
)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT} INTERFACE)
target_sources(${TRGT} INTERFACE ${TRGT_cpp} ${TRGT_headers})
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/backports/cpp)

View File

@ -0,0 +1,46 @@
#ifndef MYX_BACKPORTS_CPP_HELPERS_HPP_
#define MYX_BACKPORTS_CPP_HELPERS_HPP_
#pragma once
#if ( __cplusplus >= 201103L )
#include <memory>
#include <type_traits>
#endif
#if ( __cplusplus >= 201103L ) && ( __cplusplus < 201402L )
namespace std
{
template< class T >
using underlying_type_t = typename std::underlying_type< T >::type;
template< typename T, typename ... Args >
std::unique_ptr< T > make_unique( Args&&... args )
{
return( std::unique_ptr< T >( new T( std::forward< Args >( args )... ) ) );
}
} // namespace std
#endif
#if ( ( __cplusplus >= 201103L ) && ( __cplusplus < 201402L ) ) || \
( ( __cplusplus >= 201402L ) && ( __cplusplus < 201702L ) && defined( __STRICT_ANSI__ ) )
namespace std
{
template< typename ... Ts > struct make_void { typedef void type; };
#ifndef __cpp_lib_void_t
template< typename ... Ts > using void_t = typename make_void< Ts... >::type;
#endif
} // namespace std
#endif
#endif // ifndef MYX_BACKPORTS_CPP_HELPERS_HPP_

View File

@ -0,0 +1,231 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef MYX_BACKPORTS_CPP_SPAN_HPP_
#define MYX_BACKPORTS_CPP_SPAN_HPP_
#pragma once
#if ( __cplusplus > 201703L )
#include <span>
#else
#include <myx/backports/cpp/helpers.hpp>
#include <algorithm>
#include <iterator>
#include <string>
#include <type_traits>
namespace std { //-V1061
template< class T, class E, class = void >
struct is_contiguous_container : std::false_type {}; // NOLINT
template< class T, class E >
struct is_contiguous_container< T, E, void_t<
decltype(
std::declval< std::size_t& >() = std::declval< T const& >().size(),
std::declval< E*& >() = std::declval< T& >().data() ),
typename std::enable_if<
std::is_same<
typename std::remove_cv< E >::type,
typename std::remove_cv<
typename std::remove_pointer<
decltype( std::declval< T& >().data() )
>::type
>::type
>::value
>::type > > : std::true_type
{};
/** A range of bytes expressed as a ContiguousContainer
This class implements a non-owning reference to a storage
area of a certain size and having an underlying integral
type with size of 1.
@tparam T The type pointed to by span iterators
*/
template< class T >
class span // NOLINT
{
T* m_data = nullptr;
std::size_t m_size = 0;
public:
/// The type of value, including cv qualifiers
using ElementType = T;
/// The type of value of each span element
using ValueType = typename std::remove_const< T >::type;
/// The type of integer used to index the span
using IndexType = std::ptrdiff_t;
/// A pointer to a span element
using Pointer = T*;
/// A reference to a span element
using Reference = T&;
/// The iterator used by the container
using Iterator = Pointer;
/// The const pointer used by the container
using ConstPointer = T const*;
/// The const reference used by the container
using ConstReference = T const&;
/// The const iterator used by the container
using ConstIterator = ConstPointer;
/// Constructor
span() = default;
/// Constructor
span( span const& ) = default;
/// Assignment
span& operator=( span const& ) = default;
/** Constructor
* @param data A pointer to the beginning of the range of elements
* @param size The number of elements pointed to by `data`
*/
span( T* data, std::size_t size ) :
m_data( data ),
m_size( size )
{
}
/** Constructor
* @param container The container to construct from
*/
template< class ContiguousContainer,
class = typename std::enable_if<
is_contiguous_container<
ContiguousContainer, T >::value >::type
>
explicit
span( ContiguousContainer&& container ) :
m_data( container.data() ),
m_size( container.size() )
{
}
template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator >& s ) :
m_data( &s[0] ),
m_size( s.size() )
{
}
template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator > const& s ) :
m_data( s.data() ),
m_size( s.size() )
{
}
/** Assignment
* @param container The container to assign from
*/
template< class ContiguousContainer >
typename std::enable_if< is_contiguous_container< //NOLINT
ContiguousContainer, T >::value,
span& >::type
operator=( ContiguousContainer&& container )
{
m_data = container.data();
m_size = container.size();
return( *this );
}
template< class CharT, class Traits, class Allocator >
span&
operator=( std::basic_string<
CharT, Traits, Allocator >& s )
{
m_data = &s[0];
m_size = s.size();
return( *this );
}
template< class CharT, class Traits, class Allocator >
span&
operator=( std::basic_string<
CharT, Traits, Allocator > const& s )
{
m_data = s.data();
m_size = s.size();
return( *this );
}
/// Returns `true` if the span is empty
bool
empty() const
{
return( m_size == 0 );
}
/// Returns a pointer to the beginning of the span
T*
data() const
{
return( m_data );
}
/// Returns the number of elements in the span
std::size_t
size() const
{
return( m_size );
}
/// Returns an iterator to the beginning of the span
Iterator
begin() const
{
return( m_data );
}
/// Returns an iterator to the beginning of the span
ConstIterator
cbegin() const
{
return( m_data );
}
/// Returns an iterator to one past the end of the span
Iterator
end() const
{
return( m_data + m_size );
}
/// Returns an iterator to one past the end of the span
ConstIterator
cend() const
{
return( m_data + m_size );
}
}; // class span
} // namespace std
#endif // if ( __cplusplus > 201703L )
#endif // ifndef MYX_BACKPORTS_CPP_SPAN_HPP_

View File

@ -0,0 +1,21 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT backports-qt)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/common.hpp
)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT} INTERFACE)
target_sources(${TRGT} INTERFACE ${TRGT_cpp} ${TRGT_headers})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/backports/qt)
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})

View File

@ -1,14 +1,13 @@
#ifndef MYX_QT_BACKPORTS_HPP_
#define MYX_QT_BACKPORTS_HPP_
#ifndef MYX_BACKPORTS_QT_COMMON_HPP_
#define MYX_BACKPORTS_QT_COMMON_HPP_
#pragma once
#if ( defined ( TARGET_LSB_ID_AstraLinuxSE ) && defined ( TARGET_LSB_CODENAME_smolensk ) )
#define override
#if QT_VERSION <= 0x050700
#if !defined( QT_VERSION )
#include <QtGlobal>
#endif
#if ( QT_VERSION <= 0x050700 )
template< typename ... Args >
struct QOverload
{
@ -31,8 +30,6 @@ Q_DECL_CONSTEXPR typename std::add_const< T >::type& qAsConst( T& t ) noexcept
template < typename T >
void qAsConst( const T&& ) = delete;
#endif // if QT_VERSION <= 0x050700
#endif // if ( defined ( TARGET_LSB_ID_AstraLinuxSE ) && defined ( TARGET_LSB_CODENAME_smolensk ) )
#endif // MYX_QT_BACKPORTS_HPP_
#endif // MYX_BACKPORTS_QT_COMMON_HPP_

View File

@ -1,59 +0,0 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT base)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/config.hpp
${CMAKE_CURRENT_SOURCE_DIR}/config-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/limits.hpp
${CMAKE_CURRENT_SOURCE_DIR}/enum_bitmask_operations.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT}-header-only INTERFACE)
target_include_directories(
${TRGT}-header-only SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
if(MYXLIB_BUILD_LIBRARIES)
add_common_library(${TRGT} OUTPUT_NAME myx-${TRGT} SOURCES ${TRGT_cpp} ${TRGT_headers})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp} ${TRGT_headers})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
install(TARGETS ${TRGT}_static COMPONENT libs-dev ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_SHARED_LIBS)
install(TARGETS ${TRGT}_shared COMPONENT main LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif()
install(FILES ${TRGT_headers} ${CMAKE_BINARY_DIR}/include/myx/base/compiler_features.hpp COMPONENT headers
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT headers DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(${TRGT}-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=headers -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")

View File

@ -1,10 +0,0 @@
#ifndef MYX_BASE_CONFIG_INL_HPP_
#define MYX_BASE_CONFIG_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/base/config.hpp>
#endif
#endif // MYX_BASE_CONFIG_INL_HPP_

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include "config.hpp"

View File

@ -1,18 +0,0 @@
#ifndef MYX_BASE_CONFIG_HPP_
#define MYX_BASE_CONFIG_HPP_
#pragma once
#ifdef MYXLIB_BUILD_LIBRARIES
#undef MYXLIB_HEADER_ONLY
#define MYXLIB_INLINE inline
#else
#define MYXLIB_HEADER_ONLY
#define MYXLIB_INLINE inline
#endif
#ifdef MYXLIB_HEADER_ONLY
#include "config-inl.hpp"
#endif
#endif // MYX_BASE_CONFIG_HPP_

View File

@ -1,57 +0,0 @@
#ifndef MYX_BASE_ENUM_BITWISE_OPERATIONS_HPP_
#define MYX_BASE_ENUM_BITWISE_OPERATIONS_HPP_
#pragma once
#include <type_traits>
namespace myx {
namespace base {
template< typename Enum >
struct EnableBitMaskOperators
{
static const bool k_Enable = false;
};
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::k_Enable, Enum >::type
operator |( Enum lhs, Enum rhs )
{
using Underlying = typename std::underlying_type< Enum >::type;
return( static_cast< Enum >(
static_cast< Underlying >( lhs ) |
static_cast< Underlying >( rhs )
) );
}
} // namespace base
} // namespace myx
/**
* @brief Макрос, предоставляющий возможность выполнять битовые операции в enum class
*
* Источник: http://blog.bitwigglers.org/using-enum-classes-as-type-safe-bitmasks/
* Пример использования:
*
* namespace ns {
* enum class Permissions
* {
* Readable = 0x4,
* Writeable = 0x2,
* Executable = 0x1
* };
* }
* ENABLE_BITMASK_OPERATORS(ns::Permissions)
*/
#define ENABLE_BITMASK_OPERATORS( x ) \
template<> \
struct myx::base::EnableBitMaskOperators< x > \
{ \
static const bool k_Enable = true; \
};
#endif // ifndef MYX_BASE_ENUM_BITWISE_OPERATIONS_HPP_

View File

@ -0,0 +1,26 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT core)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/config.hpp
${CMAKE_CURRENT_SOURCE_DIR}/limits.hpp
${CMAKE_CURRENT_SOURCE_DIR}/current_system.hpp
${CMAKE_CURRENT_SOURCE_DIR}/endian_types.hpp
${CMAKE_CURRENT_SOURCE_DIR}/enum_bitmask_operations.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT} INTERFACE)
target_sources(${TRGT} INTERFACE ${TRGT_cpp} ${TRGT_headers})
target_include_directories(${TRGT} INTERFACE ${CMAKE_SOURCE_DIR}/src)
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})

17
src/myx/core/config.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef MYX_CORE_CONFIG_HPP_
#define MYX_CORE_CONFIG_HPP_
#pragma once
#if defined( _WIN32 ) && defined( MYXLIB_SHARED_LIB )
#ifdef myxlib_EXPORTS
#define MYXLIB_API __declspec( dllexport )
#else
#define MYXLIB_API __declspec( dllimport )
#endif
#else
#define MYXLIB_API
#endif
#define MYXLIB_INLINE
#endif // MYX_CORE_CONFIG_HPP_

View File

@ -0,0 +1,109 @@
#ifndef MYX_CORE_CURRENT_SYSTEM_HPP_
#define MYX_CORE_CURRENT_SYSTEM_HPP_
#pragma once
#include <algorithm>
#include <limits>
#include <fstream>
#include <string>
namespace myx {
namespace core {
class CurrentSystem
{
public:
CurrentSystem( const CurrentSystem& ) = delete;
CurrentSystem& operator=( const CurrentSystem& ) = delete;
CurrentSystem( CurrentSystem&& ) = delete;
CurrentSystem& operator=( CurrentSystem&& ) = delete;
/**
* @brief instance
* @return Уникальный экземпляр класса CurrentSystem
*/
static CurrentSystem& instance()
{
static CurrentSystem sCurrentSystem;
return( sCurrentSystem );
}
std::string os() const { return( m_os ); }
std::string distribution() const { return( m_distribution ); }
std::string variant() const { return( m_variant ); }
std::string version() const { return( m_version ); }
protected:
CurrentSystem() :
m_os
(
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __NT__ )
"windows"
#elif __linux__
"linux"
#else
#error "Unknown OS"
#endif
)
{
#if defined( __e2k__ )
m_distribution = "debian";
m_variant = "elbrus";
std::ifstream file( "/etc/mcst_version" );
if ( file.is_open() )
{
std::getline( file, m_version );
file.close();
}
#else
std::ifstream file( "/etc/os-release" );
if ( file.is_open() )
{
std::string line;
while ( std::getline( file, line ) )
{
std::size_t pos = line.find( "ID=" );
if ( pos == 0 )
{
m_distribution = line.replace( pos, sizeof( "ID=" ) - 1, "" );
}
pos = line.find( "VARIANT_ID=" );
if ( pos != std::string::npos )
{
m_variant = line.replace( pos, sizeof( "VARIANT_ID=" ) - 1, "" );
}
pos = line.find( "VERSION_ID=" );
if ( pos != std::string::npos )
{
m_version = line.replace( pos, sizeof( "VERSION_ID=" ) - 1, "" );
while ( ( pos = m_version.find( '"' ) ) != std::string::npos )
{
m_version.erase( pos, sizeof( '"' ) );
}
}
}
file.close();
}
#endif // if defined( __e2k__ )
}
~CurrentSystem() = default;
private:
std::string m_os;
std::string m_distribution;
std::string m_variant;
std::string m_version;
}; // class CurrentSystem
// class CurrentSystem
} // namespace core
} // namespace myx
#endif // MYX_CORE_CURRENT_SYSTEM_HPP_

View File

@ -0,0 +1,189 @@
#ifndef MYX_BASE_ENDIAN_TYPES_HPP_
#define MYX_BASE_ENDIAN_TYPES_HPP_
#pragma once
#include <myx/backports/cpp/span.hpp>
#include <cassert>
#include <cstdint>
#include <iostream>
#ifdef QT_CORE_LIB
#include <QDebug>
#endif
// Основа здесь: https://github.com/tatewake/endian-template/
namespace myx {
namespace core {
template< typename T >
class EndianTypesBase
{
protected:
#if defined( _MSC_VER )
#pragma warning ( push )
#endif
static T swapBytes( const T& b )
{
T n;
std::span< uint8_t > sn( reinterpret_cast< uint8_t* >( &n ), sizeof( T ) ); //NOLINT
std::span< const uint8_t > sb( reinterpret_cast< const uint8_t* >( &b ), sizeof( T ) ); //NOLINT
std::reverse_copy( sb.begin(), sb.end(), sn.begin() );
return( n );
} // swapBytes
#if defined( _MSC_VER )
#pragma warning ( pop )
#endif
}; // class EndianTypesBase
template< typename T >
class LittleEndianType : public EndianTypesBase< T >
{
protected:
T m_data; //NOLINT
static T transform( const T& b )
{
const uint16_t k_i = 1;
return( ( reinterpret_cast< const char& >( k_i ) == 1 ) ? b : EndianTypesBase< T >::swapBytes( b ) ); //NOLINT
}
public:
// Constructors
LittleEndianType() = default;
// If we endian swap, it happens in two places:
// 1. Set an OE from a PE
// 2. Get a PE from an OE
// Storage in
// NOLINTNEXTLINE
LittleEndianType( const T& b ) :
m_data( transform( b ) )
{}
template < typename U > explicit LittleEndianType( U const& b ) :
m_data( transform( T( b ) ) )
{}
// Storage out
template < typename U > explicit operator U() const { return( U( transform( m_data ) ) ); }
explicit operator T() const { return( transform( m_data ) ); }
template < typename U > bool operator==( U const& o ) { return( U( *this ) == o ); }
template < typename U > bool operator!=( U const& o ) { return( U( *this ) != o ); }
// Arithmetic assignment operators
LittleEndianType& operator++() /* prefix */ { *this = T( *this ) + T( 1 ); return( *this ); }
LittleEndianType operator++( int ) /* suffix */ { LittleEndianType t( *this ); *this = T( *this ) + T( 1 ); return( t ); }
LittleEndianType& operator--() /* prefix */ { *this = T( *this ) - T( 1 ); return( *this ); }
LittleEndianType operator--( int ) /* suffix */ { LittleEndianType t( *this ); *this = T( *this ) - T( 1 ); return( t ); }
// Compound assignment operators
LittleEndianType& operator+=( const T& b ) { *this = T( *this ) + b; return( *this ); }
LittleEndianType& operator-=( const T& b ) { *this = T( *this ) - b; return( *this ); }
LittleEndianType& operator*=( const T& b ) { *this = T( *this ) * b; return( *this ); }
LittleEndianType& operator/=( const T& b ) { *this = T( *this ) / b; return( *this ); }
LittleEndianType& operator%=( const T& b ) { *this = T( *this ) % b; return( *this ); }
LittleEndianType& operator&=( const T& b ) { *this = T( *this ) & b; return( *this ); }
LittleEndianType& operator|=( const T& b ) { *this = T( *this ) | b; return( *this ); }
LittleEndianType& operator^=( const T& b ) { *this = T( *this ) ^ b; return( *this ); }
LittleEndianType& operator<<=( const T& b ) { *this = T( T( *this ) << b ); return( *this ); }
LittleEndianType& operator>>=( const T& b ) { *this = T( T( *this ) >> b ); return( *this ); }
friend std::ostream& operator<<( std::ostream& out, const LittleEndianType &b ) { out << T( b ); return( out ); }
friend std::istream& operator>>( std::istream& in, LittleEndianType& b ) { T val; in >> val; b = val; return( in ); }
std::string toStdString() { return( std::to_string( transform( m_data ) ) ); }
#ifdef QT_CORE_LIB
friend QDebug& operator<<( QDebug& out, const LittleEndianType< T > &b ) { out << T( b ); return( out ); }
QString toQString() { return( QString::number( transform( m_data ) ) ); }
#endif
}; // class LittleEndianType
template< typename T >
class BigEndianType : public EndianTypesBase< T >
{
protected:
T m_data; //NOLINT
static T transform( const T& b )
{
const uint16_t k_i = 1;
return( ( reinterpret_cast< const char& >( k_i ) == 1 ) ? EndianTypesBase< T >::swapBytes( b ) : b ); //NOLINT
}
public:
// Constructors
BigEndianType() = default;
// If we endian swap, it happens in two places:
// 1. Set an OE from a PE
// 2. Get a PE from an OE
// Storage in
// NOLINTNEXTLINE
BigEndianType( const T& b ) :
m_data( transform( b ) )
{}
template < typename U > explicit BigEndianType( U const& b ) :
m_data( transform( T( b ) ) )
{}
// Storage out
template < typename U > explicit operator U() const { return( U( transform( m_data ) ) ); }
explicit operator T() const { return( transform( m_data ) ); }
template < typename U > bool operator==( U const& o ) { return( U( *this ) == o ); }
template < typename U > bool operator!=( U const& o ) { return( U( *this ) != o ); }
// Arithmetic assignment operators
BigEndianType& operator++() /* prefix */ { *this = T( *this ) + 1; return( *this ); }
BigEndianType operator++( int ) /* suffix */ { BigEndianType t( *this ); *this = T( *this ) + 1; return( t ); }
BigEndianType& operator--() /* prefix */ { *this = T( *this ) - 1; return( *this ); }
BigEndianType operator--( int ) /* suffix */ { BigEndianType t( *this ); *this = T( *this ) - 1; return( t ); }
// Compound assignment operators
BigEndianType& operator+=( const T& b ) { *this = T( *this ) + b; return( *this ); }
BigEndianType& operator-=( const T& b ) { *this = T( *this ) - b; return( *this ); }
BigEndianType& operator*=( const T& b ) { *this = T( *this ) * b; return( *this ); }
BigEndianType& operator/=( const T& b ) { *this = T( *this ) / b; return( *this ); }
BigEndianType& operator%=( const T& b ) { *this = T( *this ) % b; return( *this ); }
BigEndianType& operator&=( const T& b ) { *this = T( *this ) & b; return( *this ); }
BigEndianType& operator|=( const T& b ) { *this = T( *this ) | b; return( *this ); }
BigEndianType& operator^=( const T& b ) { *this = T( *this ) ^ b; return( *this ); }
BigEndianType& operator<<=( const T& b ) { *this = T( T( *this ) << b ); return( *this ); }
BigEndianType& operator>>=( const T& b ) { *this = T( T( *this ) >> b ); return( *this ); }
friend std::ostream& operator<<( std::ostream& out, const BigEndianType &b ) { out << T( b ); return( out ); }
friend std::istream& operator>>( std::istream& in, BigEndianType& b ) { T val; in >> val; b = val; return( in ); }
std::string toStdString() { return( std::to_string( transform( m_data ) ) ); }
#ifdef QT_CORE_LIB
friend QDebug& operator<<( QDebug& out, const BigEndianType< T > &b ) { out << T( b ); return( out ); }
QString toQString() { return( QString::number( transform( m_data ) ) ); }
#endif
}; // class BigEndianType
} // namespace core
} // namespace myx
using leint16 = myx::core::LittleEndianType< int16_t >; //NOLINT
using leint32 = myx::core::LittleEndianType< int32_t >; //NOLINT
using leint64 = myx::core::LittleEndianType< int64_t >; //NOLINT
using leuint16 = myx::core::LittleEndianType< uint16_t >; //NOLINT
using leuint32 = myx::core::LittleEndianType< uint32_t >; //NOLINT
using leuint64 = myx::core::LittleEndianType< uint64_t >; //NOLINT
using lefloat = myx::core::LittleEndianType< float >; //NOLINT
using ledouble = myx::core::LittleEndianType< double >; //NOLINT
using beint16 = myx::core::BigEndianType< int16_t >; //NOLINT
using beint32 = myx::core::BigEndianType< int32_t >; //NOLINT
using beint64 = myx::core::BigEndianType< int64_t >; //NOLINT
using beuint16 = myx::core::BigEndianType< uint16_t >; //NOLINT
using beuint32 = myx::core::BigEndianType< uint32_t >; //NOLINT
using beuint64 = myx::core::BigEndianType< uint64_t >; //NOLINT
using befloat = myx::core::BigEndianType< float >; //NOLINT
using bedouble = myx::core::BigEndianType< double >; //NOLINT
#endif // MYX_BASE_ENDIAN_TYPES_HPP_

View File

@ -0,0 +1,93 @@
#ifndef MYX_CORE_ENUM_BITWISE_OPERATIONS_HPP_
#define MYX_CORE_ENUM_BITWISE_OPERATIONS_HPP_
#pragma once
#include <type_traits>
namespace myx {
namespace core {
template< typename Enum >
struct EnableBitMaskOperators
{
static const bool kEnable = false;
};
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::kEnable, Enum >::type
operator~( Enum e )
{
using Underlying = typename std::underlying_type< Enum >::type;
return( static_cast< Enum >( ~static_cast< Underlying >( e ) ) );
}
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::kEnable, Enum >::type
operator|( Enum lhs, Enum rhs )
{
using Underlying = typename std::underlying_type< Enum >::type;
return( static_cast< Enum >( static_cast< Underlying >( lhs ) | static_cast< Underlying >( rhs ) ) );
}
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::kEnable, typename std::add_lvalue_reference< Enum >::type >::type
operator|=( Enum& lhs, Enum rhs )
{
using Underlying = typename std::underlying_type< Enum >::type;
lhs = static_cast< Enum >( static_cast< Underlying >( lhs ) | static_cast< Underlying >( rhs ) );
return( lhs );
}
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::kEnable, Enum >::type
operator&( Enum lhs, Enum rhs )
{
using Underlying = typename std::underlying_type< Enum >::type;
return( static_cast< Enum >( static_cast< Underlying >( lhs ) & static_cast< Underlying >( rhs ) ) );
}
template< typename Enum >
typename std::enable_if< EnableBitMaskOperators< Enum >::kEnable, typename std::add_lvalue_reference< Enum >::type >::type
operator&=( Enum& lhs, Enum rhs )
{
using Underlying = typename std::underlying_type< Enum >::type;
lhs = static_cast< Enum >( static_cast< Underlying >( lhs ) & static_cast< Underlying >( rhs ) );
return( lhs );
}
} // namespace core
} // namespace myx
/**
* @brief Макрос, предоставляющий возможность выполнять битовые операции в enum class
*
* Источник: http://blog.bitwigglers.org/using-enum-classes-as-type-safe-bitmasks/
* Пример использования:
*
* namespace ns {
* enum class Permissions
* {
* Readable = 0x4,
* Writeable = 0x2,
* Executable = 0x1
* };
* }
* ENABLE_BITMASK_OPERATORS(ns::Permissions)
*/
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define ENABLE_BITMASK_OPERATORS( x ) \
template<> \
struct myx::core::EnableBitMaskOperators< x > \
{ \
static const bool kEnable = true; \
};
#endif // ifndef MYX_CORE_ENUM_BITWISE_OPERATIONS_HPP_

View File

@ -1,5 +1,6 @@
#ifndef MYX_BASE_LIMITS_HPP_
#define MYX_BASE_LIMITS_HPP_
#ifndef MYX_CORE_LIMITS_HPP_
#define MYX_CORE_LIMITS_HPP_
#pragma once
@ -7,25 +8,25 @@
namespace myx {
namespace base {
namespace core {
/**
* @brief Константа, представляющая значение, не являющееся числом, для типа float
*/
constexpr float k_FloatNAN { std::numeric_limits< float >::quiet_NaN() };
constexpr float kFloatNAN { std::numeric_limits< float >::quiet_NaN() };
/**
* @brief Константа, представляющая значение, не являющееся числом, для типа double
*/
constexpr double k_DoubleNAN { std::numeric_limits< double >::quiet_NaN() };
constexpr double kDoubleNAN { std::numeric_limits< double >::quiet_NaN() };
/**
* @brief Константа, представляющая значение, не являющееся числом, для типа long double
*/
constexpr double k_LongDoubleNAN { std::numeric_limits< long double >::quiet_NaN() };
constexpr double kLongDoubleNAN { std::numeric_limits< long double >::quiet_NaN() };
} // namespace base
} // namespace core
} // namespace myx
#endif // MYX_BASE_LIMITS_HPP_
#endif // MYX_CORE_LIMITS_HPP_

View File

@ -3,62 +3,23 @@ set(TRGT filesystem)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/current_executable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp
${CMAKE_CURRENT_SOURCE_DIR}/paths_mt.cpp)
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/current_executable.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths_mt.hpp
${CMAKE_CURRENT_SOURCE_DIR}/current_executable-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths_mt-inl.hpp)
set(TRGT_hpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT}-header-only INTERFACE)
target_include_directories(
${TRGT}-header-only SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
#add_library(${TRGT} ${TRGT_cpp} ${TRGT_headers})
add_library(${TRGT} OBJECT ${TRGT_cpp} ${TRGT_headers})
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME myx-${TRGT})
myx_cmake_common_target_properties(${TRGT})
myx_cmake_add_static_library(${TRGT})
myx_cmake_add_shared_library(${TRGT})
if(MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
add_common_library(${TRGT} OUTPUT_NAME myx-${TRGT} SOURCES ${TRGT_cpp} ${TRGT_headers})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp} ${TRGT_headers})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
cotire(${TRGT})
install(TARGETS ${TRGT}_static COMPONENT libs-dev ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_SHARED_LIBS)
install(TARGETS ${TRGT}_shared COMPONENT main LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif()
install(FILES ${TRGT_headers} COMPONENT DEV DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT DEV DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(${TRGT}-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=DEV -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})

View File

@ -1,41 +0,0 @@
#ifndef MYX_BASE_CURRENT_EXECUTABLE_INL_HPP_
#define MYX_BASE_CURRENT_EXECUTABLE_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/filesystem/current_executable.hpp>
#endif
#include <myx/base/config.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
#if !defined ( __linux__ )
error "Class CurrentExecutable is supported only in Linux"
#endif
MYXLIB_INLINE CurrentExecutable::CurrentExecutable() :
m_procFilePath( QStringLiteral( "/proc/self/exe" ) )
{
m_canonicalFilePath = m_procFilePath.canonicalFilePath();
}
MYXLIB_INLINE const QFileInfo& CurrentExecutable::canonicalFilePath() const
{
return( m_canonicalFilePath );
}
} // namespace filesystem
} // namespace myx
#endif // MYX_BASE_CURRENT_EXECUTABLE_INL_HPP_

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/filesystem/current_executable-inl.hpp>

View File

@ -1,51 +0,0 @@
/**
* @file current_executable.hpp
* @brief Параметры исполняемого файла
*/
#ifndef MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_
#define MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <QDir>
#include <QFileInfo>
#include <QString>
namespace myx {
namespace filesystem {
class CurrentExecutable
{
/// @brief Путь к символической ссылке, указывающей на текущий исполняемый файл
QFileInfo m_procFilePath;
/// @brief Канонический путь к текущему исполняемому файлу
QFileInfo m_canonicalFilePath;
friend class Paths;
public:
/**
* @brief Конструктор, собирающий информацию о текущем исполняемом файле.
*/
CurrentExecutable();
/**
* @brief Канонический путь к текущему исполняемому файлу
*/
const QFileInfo& canonicalFilePath() const;
}; // class CurrentExecutable
} // namespace filesystem
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "current_executable-inl.hpp"
#endif
#endif // MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_

View File

@ -1,359 +0,0 @@
#ifndef MYX_BASE_PATHS_INL_HPP_
#define MYX_BASE_PATHS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/filesystem/paths.hpp>
#endif
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
MYXLIB_INLINE Paths::Paths() = default;
MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
{
QRegExp binUnityRegexp( "/s*bin/unity$" );
QRegExp binRegexp( "/s*bin$" );
auto binaryDir = m_currentExecutable.m_canonicalFilePath.canonicalPath();
if ( binUnityRegexp.indexIn( binaryDir ) >= 0 )
{
binaryDir.remove( binUnityRegexp );
QFileInfo etcDirInfo { binaryDir + "/etc" };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { binaryDir + "/files/data" };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { binaryDir + "/files/lib" };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { binaryDir + "/files/log" };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return ( HierarchyType::kDevelopment );
}
if ( binRegexp.indexIn( binaryDir ) == -1 )
{
return ( HierarchyType::kFlat );
}
QRegExp optRegexp( "^/opt(/|/.+/)" + m_projectName + "/" );
if ( optRegexp.indexIn( binaryDir ) >= 0 )
{
binaryDir.remove( binRegexp );
QFileInfo etcDirInfo { binaryDir + "/etc" };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { binaryDir + "/files/data" };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { binaryDir + "/files/lib" };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { binaryDir + "/files/log" };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return ( HierarchyType::kOpt );
}
if ( binaryDir.startsWith( QStringLiteral( "/usr/local" ) ) )
{
QFileInfo etcDirInfo { "/usr/local/etc/" + m_projectName };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { "/usr/local/share/" + m_projectName };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { "/var/lib/" + m_projectName };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { "/var/log/" + m_projectName };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return ( HierarchyType::kUsr );
}
if ( binaryDir.startsWith( QStringLiteral( "/usr" ) ) )
{
QFileInfo etcDirInfo { "/etc/" + m_projectName };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { "/usr/share/" + m_projectName };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { "/var/lib/" + m_projectName };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { "/var/log/" + m_projectName };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return ( HierarchyType::kUsr );
}
if ( binaryDir.startsWith( m_homeDirectory.canonicalPath() + "/.local/bin" ) ||
binaryDir.startsWith( m_homeDirectory.canonicalPath() + "/bin" ) )
{
QFileInfo etcDirInfo { m_userConfigDirectory.canonicalPath() };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { m_userConstDataDirectory.canonicalPath() };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { m_userVarDataDirectory.canonicalPath() };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { m_userLogDirectory.canonicalPath() };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return( HierarchyType::kHome );
}
binaryDir.remove( binRegexp );
QFileInfo etcDirInfo { binaryDir + "/etc" };
if ( !etcDirInfo.isDir() || !etcDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo constDataDirInfo { binaryDir + "/files/data" };
if ( !constDataDirInfo.isDir() || !constDataDirInfo.isReadable() ) { return( HierarchyType::kFlat ); }
QFileInfo varDataDirInfo { binaryDir + "/files/lib" };
if ( !varDataDirInfo.isDir() || !varDataDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
QFileInfo logDirInfo { binaryDir + "/files/log" };
if ( !logDirInfo.isDir() || !logDirInfo.isWritable() ) { return( HierarchyType::kFlat ); }
m_systemConfigDirectory = etcDirInfo.canonicalFilePath();
m_systemConstDataDirectory = constDataDirInfo.canonicalFilePath();
m_systemVarDataDirectory = varDataDirInfo.canonicalFilePath();
m_systemLogDirectory = logDirInfo.canonicalFilePath();
return ( HierarchyType::kDevelopment );
} // Paths::getHierarchyType
MYXLIB_INLINE bool Paths::init( const QString& projectDir, const QString& configFileExtension )
{
m_projectName = projectDir.isEmpty() ? m_currentExecutable.m_canonicalFilePath.fileName()
: projectDir;
m_configFileExtension = configFileExtension.isEmpty() ? QStringLiteral( "conf" )
: configFileExtension;
m_configFileName = m_projectName + "." + m_configFileExtension;
m_homeDirectory = QDir::homePath();
m_tempDirectory = QDir::tempPath();
auto configHome = QString::fromLocal8Bit( qgetenv( "XDG_CONFIG_HOME" ) );
if ( configHome.isEmpty() )
{
configHome = m_homeDirectory.canonicalPath() + "/.config";
}
m_userConfigDirectory = configHome + "/" + m_projectName;
auto dataHome = QString::fromLocal8Bit( qgetenv( "XDG_DATA_HOME" ) );
if ( dataHome.isEmpty() )
{
dataHome = m_homeDirectory.canonicalPath() + "/.local/share";
}
dataHome += "/" + m_projectName;
m_userConstDataDirectory = dataHome + "/data";
m_userVarDataDirectory = dataHome + "/lib";
m_userLogDirectory = dataHome + "/log";
m_hierarchyType = getHierarchyType();
if ( m_hierarchyType == HierarchyType::kFlat )
{
m_systemConstDataDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath();
m_systemVarDataDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath();
m_systemConfigDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath();
m_systemLogDirectory = m_currentExecutable.m_canonicalFilePath.canonicalPath();
}
m_configFilePath = m_systemConfigDirectory.canonicalPath() + "/" + m_configFileName;
return( true );
} // Paths::updatePaths
MYXLIB_INLINE bool Paths::makeDefaultDirectories()
{
bool status = true;
if ( !m_userConfigDirectory.mkpath( m_userConfigDirectory.absolutePath() ) ) { status = false; }
if ( !m_userVarDataDirectory.mkpath( m_userVarDataDirectory.absolutePath() ) ) { status = false; }
if ( !m_userConstDataDirectory.mkpath( m_userConstDataDirectory.absolutePath() ) ) { status = false; }
if ( !m_userLogDirectory.mkpath( m_userLogDirectory.absolutePath() ) ) { status = false; }
return( status );
}
MYXLIB_INLINE QString Paths::findConfigFile( const QString& defaultConfigFile )
{
if ( !defaultConfigFile.isEmpty() && QFileInfo( defaultConfigFile ).isReadable() )
{
m_configFilePath = defaultConfigFile;
return( defaultConfigFile );
}
auto fileName = QString::fromLocal8Bit( qgetenv( QCoreApplication::applicationName()
.toUpper().toUtf8() + "_CONFIG" ) );
if ( QFileInfo( fileName ).isReadable() )
{
m_configFilePath = fileName;
return( fileName );
}
if ( QFileInfo( m_configFilePath ).isReadable() )
{
return( m_configFilePath.absoluteFilePath() );
}
return( QString() );
} // Paths::findConfigFile
MYXLIB_INLINE QDir Paths::executableFileDirectory() const
{
return( m_currentExecutable.m_canonicalFilePath.dir() );
}
MYXLIB_INLINE const QDir& Paths::userConfigDirectory() const
{
return( m_userConfigDirectory );
}
MYXLIB_INLINE const QDir& Paths::systemConfigDirectory() const
{
return( m_systemConfigDirectory );
}
MYXLIB_INLINE const QFileInfo& Paths::configFilePath() const
{
return( m_configFilePath );
}
MYXLIB_INLINE const QString& Paths::configFileName() const
{
return( m_configFileName );
}
MYXLIB_INLINE const QString& Paths::configFileExtension() const
{
return( m_configFileExtension );
}
MYXLIB_INLINE const QDir& Paths::userVarDataDirectory() const
{
return( m_userVarDataDirectory );
}
MYXLIB_INLINE const QDir& Paths::systemVarDataDirectory() const
{
return( m_systemVarDataDirectory );
}
MYXLIB_INLINE const QDir& Paths::userConstDataDirectory() const
{
return( m_userConstDataDirectory );
}
MYXLIB_INLINE const QDir& Paths::systemConstDataDirectory() const
{
return( m_systemConstDataDirectory );
}
MYXLIB_INLINE const QDir& Paths::userLogDirectory() const
{
return( m_userLogDirectory );
}
MYXLIB_INLINE const QDir& Paths::systemLogDirectory() const
{
return( m_systemLogDirectory );
}
MYXLIB_INLINE const QDir& Paths::tempDirectory() const
{
return( m_tempDirectory );
}
MYXLIB_INLINE const QDir& Paths::homeDirectory() const
{
return( m_homeDirectory );
}
MYXLIB_INLINE const QString& Paths::projectName() const
{
return( m_projectName );
}
MYXLIB_INLINE QString Paths::executableFileName() const
{
return( m_currentExecutable.m_canonicalFilePath.fileName() );
}
MYXLIB_INLINE const QFileInfo& Paths::executableFilePath() const
{
return( m_currentExecutable.m_canonicalFilePath );
}
} // namespace filesystem
} // namespace myx
#endif // MYX_BASE_PATHS_INL_HPP_

View File

@ -1,5 +1,485 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#ifndef MYX_CORE_PATHS_CPP_
#define MYX_CORE_PATHS_CPP_
#include <myx/filesystem/paths-inl.hpp>
#include <myx/core/config.hpp>
#include <myx/filesystem/paths.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
MYXLIB_INLINE Paths::Paths() :
m_binDirRegex ( QStringLiteral( "/s*bin$" ) ),
m_unityBinDirRegex( QStringLiteral( "/bin/unity$" ) )
{
QFileInfo procSelfExe( QStringLiteral( "/proc/self/exe" ) );
QFileInfo currentExecutable = procSelfExe.canonicalFilePath();
m_executableName = currentExecutable.fileName();
m_executableFilePath = currentExecutable.absoluteFilePath();
m_executableDirectory = currentExecutable.absolutePath();
// Инициализация значениями по умолчанию
init();
}
MYXLIB_INLINE bool Paths::init( bool autodetect )
{
m_autodetect = autodetect;
m_homeDirectory = QDir::homePath();
m_tempDirectory = QDir::tempPath();
m_configDirectory = QString::fromLocal8Bit( qgetenv( "XDG_CONFIG_HOME" ) );
if ( m_configDirectory.isEmpty() )
{
m_configDirectory = m_homeDirectory + "/.config";
}
m_dataDirectory = QString::fromLocal8Bit( qgetenv( "XDG_DATA_HOME" ) );
if ( m_dataDirectory.isEmpty() )
{
m_dataDirectory = m_homeDirectory + "/.local/share";
}
if ( m_projectName.isEmpty() )
{
m_projectName = m_executableName;
}
m_hierarchyType = getHierarchyType();
calculatePaths( m_hierarchyType );
return( true );
} // Paths::init
MYXLIB_INLINE void Paths::setupSystemDirectories( const QString& projectDir,
const QString& etcDir,
const QString& constDataDir,
const QString& varDataDir,
const QString& logDir )
{
QFileInfo prefixDirInfo { projectDir };
if ( prefixDirInfo.isDir() && prefixDirInfo.isReadable() )
{
m_projectDirectory = projectDir;
}
else
{
m_projectDirectory = QStringLiteral( "." );
}
QFileInfo etcDirInfo { etcDir };
if ( etcDirInfo.isDir() && etcDirInfo.isReadable() )
{
m_systemConfigDirectory = etcDir;
}
else
{
m_systemConfigDirectory = m_userConfigDirectory;
}
QFileInfo constDataDirInfo { constDataDir };
if ( constDataDirInfo.isDir() && constDataDirInfo.isReadable() )
{
m_systemConstDataDirectory = constDataDir;
}
else
{
m_systemConstDataDirectory = m_userConstDataDirectory;
}
QFileInfo varDataDirInfo { varDataDir };
if ( varDataDirInfo.isDir() && varDataDirInfo.isWritable() )
{
m_systemVarDataDirectory = varDataDir;
}
else
{
m_systemVarDataDirectory = m_userVarDataDirectory;
}
QFileInfo logDirInfo { logDir };
if ( logDirInfo.isDir() && logDirInfo.isWritable() )
{
m_systemLogDirectory = logDir;
}
else
{
m_systemLogDirectory = m_userLogDirectory;
}
if ( !m_organizationName.isEmpty() && !m_themeName.isEmpty() )
{
m_systemThemeDirectory = "/opt/" + m_organizationName + "-" + m_themeName;
}
} // Paths::setupSystemDirectories
MYXLIB_INLINE void Paths::setupUserDirectories()
{
QString prefix;
if ( !m_organizationName.isEmpty() )
{
prefix = "/" + m_organizationName;
if ( !m_themeName.isEmpty() )
{
prefix.append( "-" + m_themeName );
m_userThemeDirectory = m_dataDirectory + prefix;
}
}
prefix.append( "/" + m_projectName );
m_userConfigDirectory = m_configDirectory + prefix;
m_userConstDataDirectory = m_dataDirectory + prefix + "/share";
m_userVarDataDirectory = m_dataDirectory + prefix + "/var";
m_userLogDirectory = m_dataDirectory + prefix + "/log";
}
MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
{
if ( m_unityBinDirRegex.match( m_executableDirectory ).hasMatch() )
{
return ( HierarchyType::kDevelopment );
}
if ( !m_binDirRegex.match( m_executableDirectory ).hasMatch() )
{
return ( HierarchyType::kFlat );
}
if ( m_executableDirectory.startsWith( QStringLiteral( "/opt/" ) ) )
{
return ( HierarchyType::kOpt );
}
if ( m_executableDirectory.startsWith( QStringLiteral( "/usr/local/bin/" ) ) )
{
return ( HierarchyType::kUsrLocal );
}
if ( m_executableDirectory.startsWith( QStringLiteral( "/usr/local/" ) ) )
{
return ( HierarchyType::kUsrLocalOrg );
}
if ( m_executableDirectory.startsWith( QStringLiteral( "/usr/bin/" ) ) )
{
return ( HierarchyType::kUsr );
}
if ( m_executableDirectory.startsWith( m_homeDirectory + "/.local/bin/" ) ||
m_executableDirectory.startsWith( m_homeDirectory + "/bin/" ) )
{
return( HierarchyType::kHome );
}
return ( HierarchyType::kDevelopment );
} // Paths::getHierarchyType
MYXLIB_INLINE void Paths::calculatePaths( HierarchyType hType )
{
auto directory = m_executableDirectory;
setupUserDirectories();
switch ( hType )
{
case HierarchyType::kFlat:
setupSystemDirectories( directory, directory, directory, directory, directory );
break;
case HierarchyType::kOpt:
processOptHierarhy();
break;
case HierarchyType::kUsr:
setupSystemDirectories( QStringLiteral( "/usr" ),
"/etc/" + m_projectName,
"/usr/share/" + m_projectName,
"/var/lib/" + m_projectName,
"/var/log/" + m_projectName );
break;
case HierarchyType::kUsrLocal:
setupSystemDirectories( QStringLiteral( "/usr/local" ),
"/usr/local/etc/" + m_projectName,
"/usr/local/share/" + m_projectName,
"/var/lib/" + m_projectName,
"/var/log/" + m_projectName );
break;
case HierarchyType::kUsrLocalOrg:
directory.remove( m_binDirRegex );
setupSystemDirectories( directory,
directory + "/etc",
directory + "/share",
directory + "/var",
directory + "/log" );
break;
case HierarchyType::kHome:
setupSystemDirectories( m_homeDirectory,
m_userConfigDirectory,
m_userConstDataDirectory,
m_userVarDataDirectory,
m_userLogDirectory );
break;
case HierarchyType::kDevelopment:
directory.remove( m_unityBinDirRegex );
directory.remove( m_binDirRegex );
setupSystemDirectories( directory,
directory + "/etc",
directory + "/share",
directory + "/var",
directory + "/log" );
break;
case HierarchyType::kUndefined:
;
} // switch
setupUserDirectories();
} // Paths::calculatePaths
MYXLIB_INLINE void Paths::processOptHierarhy()
{
auto directory = m_executableDirectory;
if ( m_autodetect )
{
QRegularExpression regex( QStringLiteral( "^/opt/(.+?)/(.+?)/" ) );
QRegularExpressionMatch match = regex.match( m_executableDirectory );
if ( match.hasMatch() )
{
m_organizationName = match.captured( 1 );
m_projectName = match.captured( 2 );
QRegularExpression themeRegex( QStringLiteral( "(.+?)-(.+)" ) );
QRegularExpressionMatch themeMatch = themeRegex.match( m_organizationName );
if ( themeMatch.hasMatch() )
{
m_themeName = themeMatch.captured( 2 );
m_organizationName = themeMatch.captured( 1 );
}
QRegularExpression versionRegex( QStringLiteral( "(.+?)\\.(.+)" ) );
QRegularExpressionMatch versionMatch = versionRegex.match( m_projectName );
if ( versionMatch.hasMatch() )
{
m_projectName = versionMatch.captured( 1 );
m_version = versionMatch.captured( 2 );
}
}
}
directory.remove( m_binDirRegex );
setupSystemDirectories( directory,
directory + "/etc",
directory + "/share",
directory + "/var",
directory + "/log" );
setupUserDirectories();
} // Paths::processOptHierarhy
MYXLIB_INLINE bool Paths::makeDefaultSystemDirectories()
{
bool status = true;
QDir dir;
if ( !dir.mkpath( m_systemConstDataDirectory ) ) { status = false; }
if ( !dir.mkpath( m_systemLogDirectory ) ) { status = false; }
if ( !dir.mkpath( m_systemConfigDirectory ) ) { status = false; }
if ( !dir.mkpath( m_systemVarDataDirectory ) ) { status = false; }
return( status );
}
MYXLIB_INLINE bool Paths::makeDefaultUserDirectories()
{
bool status = true;
QDir dir;
if ( !dir.mkpath( m_userConstDataDirectory ) ) { status = false; }
if ( !dir.mkpath( m_userLogDirectory ) ) { status = false; }
if ( !dir.mkpath( m_userConfigDirectory ) ) { status = false; }
if ( !dir.mkpath( m_userVarDataDirectory ) ) { status = false; }
return( status );
}
MYXLIB_INLINE bool Paths::makeDefaultDirectories()
{
return ( makeDefaultSystemDirectories() && makeDefaultUserDirectories() );
}
MYXLIB_INLINE QString Paths::findConfigFile( const QString& configFileName )
{
if ( !configFileName.isEmpty() && QFileInfo( configFileName ).isReadable() )
{
return( configFileName );
}
auto fileName = QString::fromLocal8Bit( qgetenv( QCoreApplication::applicationName()
.toUpper().toUtf8() + "_CONFIG" ) );
if ( QFileInfo( fileName ).isReadable() )
{
return( fileName );
}
QString autoConfigFile = m_systemConfigDirectory + "/" + m_executableName;
if ( QFileInfo( autoConfigFile ).isReadable() )
{
return( configFileName );
}
return( QString() );
} // Paths::findConfigFile
MYXLIB_INLINE const QString& Paths::userConfigDirectory() const
{
return( m_userConfigDirectory );
}
MYXLIB_INLINE const QString& Paths::systemConfigDirectory() const
{
return( m_systemConfigDirectory );
}
MYXLIB_INLINE const QString& Paths::userThemeDirectory() const
{
return( m_userThemeDirectory );
}
MYXLIB_INLINE const QString& Paths::systemThemeDirectory() const
{
return( m_systemThemeDirectory );
}
MYXLIB_INLINE const QString& Paths::userVarDataDirectory() const
{
return( m_userVarDataDirectory );
}
MYXLIB_INLINE const QString& Paths::systemVarDataDirectory() const
{
return( m_systemVarDataDirectory );
}
MYXLIB_INLINE const QString& Paths::userConstDataDirectory() const
{
return( m_userConstDataDirectory );
}
MYXLIB_INLINE const QString& Paths::systemConstDataDirectory() const
{
return( m_systemConstDataDirectory );
}
MYXLIB_INLINE const QString& Paths::userLogDirectory() const
{
return( m_userLogDirectory );
}
MYXLIB_INLINE const QString& Paths::systemLogDirectory() const
{
return( m_systemLogDirectory );
}
MYXLIB_INLINE const QString& Paths::tempDirectory() const
{
return( m_tempDirectory );
}
MYXLIB_INLINE const QString& Paths::homeDirectory() const
{
return( m_homeDirectory );
}
MYXLIB_INLINE const QString& Paths::projectName() const
{
return( m_projectName );
}
MYXLIB_INLINE void Paths::setProjectName( const QString& name )
{
m_projectName = name;
}
MYXLIB_INLINE const QString& Paths::organizationName() const
{
return( m_organizationName );
}
MYXLIB_INLINE void Paths::setOrganizationName( const QString& name )
{
m_organizationName = name;
}
MYXLIB_INLINE const QString& Paths::themeName() const
{
return( m_themeName );
}
MYXLIB_INLINE void Paths::setThemeName( const QString& name )
{
m_themeName = name;
}
MYXLIB_INLINE const QString& Paths::executableName() const
{
return( m_executableName );
}
MYXLIB_INLINE const QString& Paths::executableFilePath() const
{
return( m_executableFilePath );
}
MYXLIB_INLINE const QString& Paths::executableDirectory() const
{
return( m_executableDirectory );
}
MYXLIB_INLINE const QString& Paths::projectDirectory() const
{
return( m_projectDirectory );
}
} // namespace filesystem
} // namespace myx
#endif // MYX_CORE_PATHS_CPP_

View File

@ -1,226 +1,232 @@
/**
* @file paths.hpp
* @brief Стандартные пути к каталогам и файлам
*/
/** @file paths.hpp
* @brief Стандартные пути к каталогам и файлам
*/
#ifndef MYX_FILESYSTEM_PATHS_HPP_
#define MYX_FILESYSTEM_PATHS_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <myx/core/config.hpp>
#include <QDir>
#include <QFileInfo>
#include <QRegularExpression>
#include <QString>
namespace myx {
namespace filesystem {
/// @brief Класс, предоставляющий методы для получения стандартных путей к каталогам и файлам
//* @brief Класс, предоставляющий методы для получения стандартных путей к каталогам и файлам
class Paths
{
enum class HierarchyType : intptr_t
{
/// @brief Тип расположения файлов не определён
//* @brief Тип расположения файлов не определён
kUndefined = 0x00,
/// @brief Не определено ни одно из типовых размещений файлов
/// @details Если исполняемый файл не находится в каталоге bin или не найдены
/// необходимые сопутствующие каталоги, то предполается,
/// что все файлы находятся в одном каталоге с исполняемым файлом
/** @brief Не определено ни одно из типовых размещений файлов
* @details Если исполняемый файл не находится в каталоге bin или не найдены
* необходимые сопутствующие каталоги, то предполается,
* что все файлы находятся в одном каталоге с исполняемым файлом
*/
kFlat = 0x01,
/// @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /opt
//* @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /opt
kOpt = 0x02,
/// @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /usr
kUsr = 0x04,
/// @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /usr/local
kUsrLocal = 0x08,
/// @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /home
kHome = 0x10,
/// @brief Исполняемый файл и сопутствующие каталоги находятся в каталоге программного проекта
kDevelopment = 0x20
//* @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии / usr
kUsr = 0x03,
//* @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /usr/local
kUsrLocal = 0x04,
//* @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /usr/local/ORG (используется для работ в проекте Сирена)
kUsrLocalOrg = 0x05,
//* @brief Исполняемый файл и сопутствующие каталоги находятся в иерахии /home
kHome = 0x06,
//* @brief Исполняемый файл и сопутствующие каталоги находятся в каталоге программного проекта
kDevelopment = 0x07
};
/// @brief Тип расположения файлов по каталогам
HierarchyType m_hierarchyType { HierarchyType::kFlat };
/// @brief Параметры текущего исполняемого файла
CurrentExecutable m_currentExecutable;
/// @brief Имя проекта, которое используется при формировании имён файлов и каталогов
QString m_projectName;
/// @brief Путь к каталогу с временными файлами
QDir m_tempDirectory;
/// @brief Путь к домашнему каталогу текущего пользователя
QDir m_homeDirectory;
/// @brief Путь к пользовательскому каталогу с изменяемыми файлами
QDir m_userVarDataDirectory;
/// @brief Путь к системному каталогу с изменяемыми файлами
QDir m_systemVarDataDirectory;
/// @brief Путь к пользовательскому каталогу с неизменяемыми файлами
QDir m_userConstDataDirectory;
/// @brief Путь к системному каталогу с неизменяемыми файлами
QDir m_systemConstDataDirectory;
/// @brief Путь к пользовательскому каталогу с журналами работы
QDir m_userLogDirectory;
/// @brief Путь к системному каталогу с журналами работы
QDir m_systemLogDirectory;
/// @brief Путь к пользовательскому каталогу с файлами настройки
QDir m_userConfigDirectory;
/// @brief Путь к системному каталогу с файлами настройки
QDir m_systemConfigDirectory;
/// @brief Полный путь к файлу настройки
QFileInfo m_configFilePath;
/// @brief Имя файла настройки
QString m_configFileName;
/// @brief Расширение для файла настройки
QString m_configFileExtension;
HierarchyType getHierarchyType();
protected:
Paths();
~Paths() = default;
Paths( const Paths& ) = delete; // NOLINT
Paths& operator=( const Paths& ) = delete; // NOLINT
public:
Paths( const Paths& ) = delete;
Paths& operator=( const Paths& ) = delete;
Paths( Paths&& ) = delete;
Paths& operator=( Paths&& ) = delete;
/**
* @brief getInstance
* @return Уникальный экземпляр класса Paths
*/
static Paths& instance()
{
static Paths p;
return( p );
static Paths sPaths;
return( sPaths );
}
//* @brief Обновление путей с учётом расположения исполняемого файла
bool init( bool autodetect = true );
/**
* @brief Обновление путей с учётом расположения исполняемого файла
*/
bool init( const QString& projectDir, const QString& configFileExtension = QStringLiteral("conf") );
//* @brief Создание стандартных системных каталогов
bool makeDefaultSystemDirectories();
/**
* @brief Создание стандартных каталогов
*/
//* @brief Создание стандартных пользовательских каталогов
bool makeDefaultUserDirectories();
//* @brief Создание стандартных каталогов
bool makeDefaultDirectories();
/**
* @brief Поиск существующего файла настойки.
* Поиск выполняется до тех пор пока не будет найден файл в следующем порядке:
* 1. Имя файла, указанное в качестве параметра функции
* 2. Имя файла, заданное переменной окружения вида PROJECT_NAME_CONFIG
* 3. Имя файла, полученное из внутренней переменной класса
* Если файл настройки не будет найден, то будет возвращена пустая строка
/** @brief Поиск существующего файла настойки.
* Поиск выполняется до тех пор пока не будет найден файл в следующем порядке:
* 1. Имя файла, указанное в качестве параметра функции
* 2. Имя файла, заданное переменной окружения вида EXECUTABLE_NAME_CONFIG
* 3. Имя файла, полученное из имени каталога системных настроек и имени исполняемого файла
* Если файл настройки не будет найден, то будет возвращена пустая строка
*/
QString findConfigFile( const QString& defaultConfigFile = QLatin1String("") );
QString findConfigFile( const QString& configFileName = QLatin1String( "" ) );
/**
* @brief Полный путь к базовому каталогу
*/
const QDir& prefixDirectory() const;
//* @brief Имя исполняемого файла
const QString& executableName() const;
/**
* @brief Полный путь к каталогу с исполняемым файлом
*/
QDir executableFileDirectory() const;
//* @brief Полный путь к исполняемому файлу
const QString& executableFilePath() const;
/**
* @brief Полный путь к пользовательскому каталогу с файлами настройки
*/
const QDir& userConfigDirectory() const;
//* @brief Полный путь к каталогу с исполняемым файлом
const QString& executableDirectory() const;
/**
* @brief Полный путь к системному каталогу с файлами настройки
*/
const QDir& systemConfigDirectory() const;
//* @brief Путь к общему пользовательскому каталогу для файлов работы (темы)
const QString& userThemeDirectory() const;
/**
* @brief Полный путь к файлу настройки
*/
const QFileInfo& configFilePath() const;
//* @brief Путь к общему системному каталогу для файлов работы (темы)
const QString& systemThemeDirectory() const;
/**
* @brief Имя файла настройки
*/
const QString& configFileName() const;
//* @brief Полный путь к пользовательскому каталогу с файлами настройки
const QString& userConfigDirectory() const;
/**
* @brief Расширение у файла настройки
*/
const QString& configFileExtension() const;
//* @brief Полный путь к системному каталогу с файлами настройки
const QString& systemConfigDirectory() const;
/**
* @brief Полный путь к пользовательскому каталогу с изменяемыми файлами
*/
const QDir& userVarDataDirectory() const;
//* @brief Полный путь к пользовательскому каталогу с изменяемыми файлами
const QString& userVarDataDirectory() const;
/**
* @brief Полный путь к системному каталогу с изменяемыми файлами
*/
const QDir& systemVarDataDirectory() const;
//* @brief Полный путь к системному каталогу с изменяемыми файлами
const QString& systemVarDataDirectory() const;
/**
* @brief Полный путь к пользовательскому каталогу с неизменяемыми файлами
*/
const QDir& userConstDataDirectory() const;
//* @brief Полный путь к пользовательскому каталогу с неизменяемыми файлами
const QString& userConstDataDirectory() const;
/**
* @brief Полный путь к системному каталогу с неизменяемыми файлами
*/
const QDir& systemConstDataDirectory() const;
//* @brief Полный путь к системному каталогу с неизменяемыми файлами
const QString& systemConstDataDirectory() const;
/**
* @brief Полный путь к пользовательскому каталогу с журналами работы
*/
const QDir& userLogDirectory() const;
//* @brief Полный путь к пользовательскому каталогу с журналами работы
const QString& userLogDirectory() const;
/**
* @brief Полный путь к системному каталогу с журналами работы
*/
const QDir& systemLogDirectory() const;
//* @brief Полный путь к системному каталогу с журналами работы
const QString& systemLogDirectory() const;
/**
* @brief Полный путь к каталогу с временными файлами
*/
const QDir& tempDirectory() const;
//* @brief Полный путь к каталогу с временными файлами
const QString& tempDirectory() const;
/**
* @brief Полный путь к домашнему каталогу текущего пользователя
*/
const QDir& homeDirectory() const;
//* @brief Полный путь к домашнему каталогу текущего пользователя
const QString& homeDirectory() const;
/**
* @brief Имя подкаталога для проекта
*/
//* @brief Имя каталога для проекта
const QString& projectDirectory() const;
//* @brief Название организации
const QString& organizationName() const;
void setOrganizationName( const QString& name );
//* @brief Название работы (темы)
const QString& themeName() const;
void setThemeName( const QString& name );
//* @brief Название программного проекта
const QString& projectName() const;
void setProjectName( const QString& name );
/**
* @brief Имя исполняемого файла
*/
QString executableFileName() const;
protected:
Paths();
~Paths() = default;
/**
* @brief Полный путь к исполняемому файлу
private:
//* @brief Тип расположения файлов по каталогам
HierarchyType m_hierarchyType { HierarchyType::kFlat };
/** @brief Автоматически определять значения organizationName, themeName и projectName
* @details Если true, то пытаться автоматически определять значения переменных
* на основании полного пути к исполняемому файлу.
* Иначе использовать значения переменных, указанные пользователем.
*/
const QFileInfo& executableFilePath() const;
bool m_autodetect { true };
//* @brief Название организации
QString m_organizationName;
//* @brief Название работы (темы)
QString m_themeName;
//* @brief Номер версии установленного пакета
QString m_version;
//* @brief Имя проекта, которое используется при формировании имён файлов и каталогов
QString m_projectName;
QString m_executableName;
QString m_executableFilePath;
QString m_executableDirectory;
//* @brief Общий каталог для файлов проекта
QString m_projectDirectory;
//* @brief Путь к каталогу с временными файлами
QString m_tempDirectory;
//* @brief Путь к домашнему каталогу текущего пользователя
QString m_homeDirectory;
//* @brief Путь к общему пользовательскому каталогу настроек
QString m_configDirectory;
//* @brief Путь к общему пользовательскому каталогу данных
QString m_dataDirectory;
//* @brief Путь к общему пользовательскому каталогу для файлов работы (темы)
QString m_userThemeDirectory;
//* @brief Путь к общему системному каталогу для файлов работы (темы)
QString m_systemThemeDirectory;
//* @brief Путь к пользовательскому каталогу с изменяемыми файлами
QString m_userVarDataDirectory;
//* @brief Путь к системному каталогу с изменяемыми файлами
QString m_systemVarDataDirectory;
//* @brief Путь к пользовательскому каталогу с неизменяемыми файлами
QString m_userConstDataDirectory;
//* @brief Путь к системному каталогу с неизменяемыми файлами
QString m_systemConstDataDirectory;
//* @brief Путь к пользовательскому каталогу с журналами работы
QString m_userLogDirectory;
//* @brief Путь к системному каталогу с журналами работы
QString m_systemLogDirectory;
//* @brief Путь к пользовательскому каталогу с файлами настройки
QString m_userConfigDirectory;
//* @brief Путь к системному каталогу с файлами настройки
QString m_systemConfigDirectory;
QRegularExpression m_binDirRegex;
QRegularExpression m_unityBinDirRegex;
void setupSystemDirectories( const QString& projectDir,
const QString& etcDir,
const QString& constDataDir,
const QString& varDataDir,
const QString& logDir );
void setupUserDirectories();
HierarchyType getHierarchyType();
void calculatePaths( HierarchyType hType );
void processOptHierarhy();
}; // class Paths
} // namespace filesystem
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "paths-inl.hpp"
#endif
#endif // MYX_FILESYSTEM_PATHS_HPP_

View File

@ -1,44 +0,0 @@
#ifndef MYX_BASE_PATHS_MT_INL_HPP_
#define MYX_BASE_PATHS_MT_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/filesystem/paths_mt.hpp>
#endif
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
MYXLIB_INLINE PathsMT::PathsMT() = default;
MYXLIB_INLINE PathsMT& PathsMT::instance()
{
volatile PathsMT* localInstance = mInstance.load( std::memory_order_acquire );
if ( localInstance == nullptr )
{
std::lock_guard< std::mutex > myLock( mMutex );
localInstance = mInstance.load( std::memory_order_relaxed );
if ( localInstance == nullptr ) // -V1036
{
localInstance = new PathsMT();
mInstance.store( const_cast< PathsMT* >( localInstance ), std::memory_order_release ); // NOLINT
}
}
return( const_cast< PathsMT& >( *localInstance ) ); // NOLINT
}
} // namespace filesystem
} // namespace myx
#endif // MYX_BASE_PATHS_MT_INL_HPP_

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/filesystem/paths_mt-inl.hpp>

View File

@ -1,55 +0,0 @@
/**
* @file paths.hpp
* @brief Стандартные пути к каталогам и файлам
*/
#ifndef MYX_FILESYSTEM_PATHS_MT_HPP_
#define MYX_FILESYSTEM_PATHS_MT_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <myx/filesystem/paths.hpp>
#include <QDir>
#include <QFileInfo>
#include <QString>
#include <atomic>
#include <future>
#include <mutex>
#include <thread>
namespace myx {
namespace filesystem {
/// @brief Потокобезопасная версия класса myx::filesystem::Paths
class PathsMT : public Paths
{
PathsMT();
~PathsMT() = default;
PathsMT( const PathsMT& ) = delete; // NOLINT
PathsMT& operator=( const PathsMT& ) = delete; // NOLINT
static std::atomic< PathsMT* > mInstance;
static std::mutex mMutex;
public:
/**
* @brief getInstance
* @return Уникальный экземпляр класса PathsMT
*/
static PathsMT& instance();
}; // class PathsMT
} // namespace filesystem
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "paths_mt-inl.hpp"
#endif
#endif // MYX_FILESYSTEM_PATHS_MT_HPP_

View File

@ -1,75 +0,0 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT math)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative.cpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative_and_abs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps.cpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps_and_abs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/constants.cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/all.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative_and_abs.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_relative_and_abs-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps_and_abs.hpp
${CMAKE_CURRENT_SOURCE_DIR}/almost_equal_ulps_and_abs-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/constants.hpp
${CMAKE_CURRENT_SOURCE_DIR}/constants-inl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/float_cmp_types.hpp
${CMAKE_CURRENT_SOURCE_DIR}/functions.hpp
${CMAKE_CURRENT_SOURCE_DIR}/radar.hpp
${CMAKE_CURRENT_SOURCE_DIR}/units.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT}-header-only INTERFACE)
target_sources(${TRGT}-header-only INTERFACE ${TRGT_headers})
target_include_directories(
${TRGT}-header-only SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
if(MYXLIB_BUILD_LIBRARIES)
add_common_library(${TRGT} OUTPUT_NAME myx-${TRGT} SOURCES ${TRGT_cpp} ${TRGT_headers})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_sources} ${TRGT_headers})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_sources} ${TRGT_headers})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_sources} ${TRGT_headers})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_sources} ${TRGT_headers})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
cotire(${TRGT})
install(TARGETS ${TRGT}_static COMPONENT DEV ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_SHARED_LIBS)
install(TARGETS ${TRGT}_shared COMPONENT DEV LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif()
install(FILES ${TRGT_headers} COMPONENT DEV DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT DEV DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(${TRGT}-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=DEV -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")

View File

@ -1,15 +0,0 @@
#ifndef MYX_MATH_ALL_HPP_
#define MYX_MATH_ALL_HPP_
#pragma once
#include <myx/math/almost_equal_relative.hpp>
#include <myx/math/almost_equal_relative_and_abs.hpp>
#include <myx/math/almost_equal_ulps.hpp>
#include <myx/math/almost_equal_ulps_and_abs.hpp>
#include <myx/math/constants.hpp>
#include <myx/math/functions.hpp>
#include <myx/math/radar.hpp>
#include <myx/math/units.hpp>
#endif

View File

@ -1,51 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_INL_HPP_
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/math/almost_equal_relative.hpp>
#endif
#include <cmath>
namespace myx {
namespace math {
MYXLIB_INLINE bool almost_equal_relative( const float a, const float b,
const float maxRelDiff )
{
float diff = fabsf( a - b );
float aN = fabsf( a );
float bN = fabsf( b );
float largest = ( bN > aN ) ? bN : aN;
if ( diff <= largest * maxRelDiff )
{
return( true );
}
return( false );
}
MYXLIB_INLINE bool almost_equal_relative( const double a, const double b,
const double maxRelDiff )
{
double diff = fabs( a - b );
double aN = fabs( a );
double bN = fabs( b );
double largest = ( bN > aN ) ? bN : aN;
if ( diff <= largest * maxRelDiff )
{
return( true );
}
return( false );
}
} // namespace math
} // namespace myx
#endif

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/math/almost_equal_relative-inl.hpp>

View File

@ -1,39 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <cfloat>
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
namespace myx {
namespace math {
/**
* @brief Проверка на равенство двух аргументов типа float.
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
* при которой аргументы считаются равными.
*/
bool almost_equal_relative( float a, float b,
float maxRelDiff = FLT_EPSILON );
/**
* @brief Проверка на равенство двух аргументов типа double.
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
* при которой аргументы считаются равными.
*/
bool almost_equal_relative( double a, double b,
double maxRelDiff = DBL_EPSILON );
} // namespace math
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "almost_equal_relative-inl.hpp"
#endif
#endif // MYX_MATH_ALMOST_EQUAL_RELATIVE_HPP_

View File

@ -1,65 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_INL_HPP_
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/math/almost_equal_relative_and_abs.hpp>
#endif
#include <cmath>
namespace myx {
namespace math {
MYXLIB_INLINE bool almost_equal_relative_and_abs( const float a, const float b,
const float maxAbsDiff, const float maxRelDiff )
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
float diff = fabsf( a - b );
if ( diff <= maxAbsDiff )
{
return( true );
}
float aN = fabsf( a );
float bN = fabsf( b );
float largest = ( bN > aN ) ? bN : aN;
if ( diff <= largest * maxRelDiff )
{
return( true );
}
return( false );
}
MYXLIB_INLINE bool almost_equal_relative_and_abs( const double a, const double b,
const double maxAbsDiff, const double maxRelDiff )
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
double diff = fabs( a - b );
if ( diff <= maxAbsDiff )
{
return( true );
}
double aN = fabs( a );
double bN = fabs( b );
double largest = ( bN > aN ) ? bN : aN;
if ( diff <= largest * maxRelDiff )
{
return( true );
}
return( false );
}
} // namespace math
} // namespace myx
#endif

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/math/almost_equal_relative_and_abs-inl.hpp>

View File

@ -1,39 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_
#define MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <cfloat>
namespace myx {
namespace math {
/**
* @brief Проверка на равенство двух аргументов типа float.
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
* при которой аргументы считаются равными.
*/
bool almost_equal_relative_and_abs( float a, float b,
float maxAbsDiff, float maxRelDiff = FLT_EPSILON );
/**
* @brief Проверка на равенство двух аргументов типа double.
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
* Параметр maxRelDiff определяет максимальную относительную допустимую разницу,
* при которой аргументы считаются равными.
*/
bool almost_equal_relative_and_abs( double a, double b,
double maxAbsDiff, double maxRelDiff = DBL_EPSILON );
} // namespace math
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "almost_equal_relative_and_abs-inl.hpp"
#endif
#endif // MYX_MATH_ALMOST_EQUAL_RELATIVE_AND_ABS_HPP_

View File

@ -1,93 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_INL_HPP_
#define MYX_MATH_ALMOST_EQUAL_ULPS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/math/almost_equal_ulps.hpp>
#endif
#include <myx/math/float_cmp_types.hpp>
#include <cmath>
namespace myx {
namespace math {
MYXLIB_INLINE bool almost_equal_ulps( const float a, const float b,
const int maxUlpsDiff )
{
FloatCmp uA( a );
FloatCmp uB( b );
// Если знаки разные, то числа не равны.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
if ( uA.negative() != uB.negative() )
{
// Кроме случая, когда +0==-0
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if ( a == b ) // -V550
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
{
return( true );
}
return( false );
}
// Разница в младших битах.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
auto ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps
MYXLIB_INLINE bool almost_equal_ulps( const double a, const double b,
const int maxUlpsDiff )
{
DoubleCmp uA( a );
DoubleCmp uB( b );
// Если знаки разные, то числа не равны.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
if ( uA.negative() != uB.negative() )
{
// Кроме случая, когда +0==-0
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if ( a == b ) // -V550
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
{
return( true );
}
return( false );
}
// Разница в младших битах.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
auto ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps
} // namespace math
} // namespace myx
#endif

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/math/almost_equal_ulps-inl.hpp>

View File

@ -1,38 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
#define MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <myx/math/float_cmp_types.hpp>
#include <cmath>
namespace myx {
namespace math {
/**
* @brief Проверка на равенство двух аргументов типа float.
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
* при которой они считаются равными.
*/
bool almost_equal_ulps( float a, float b,
int maxUlpsDiff );
/**
* @brief Проверка на равенство двух аргументов типа double.
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
* при которой они считаются равными.
*/
bool almost_equal_ulps( double a, double b,
int maxUlpsDiff );
} // namespace math
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "almost_equal_ulps-inl.hpp"
#endif
#endif // MYX_MATH_ALMOST_EQUAL_ULPS_HPP_

View File

@ -1,87 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_INL_HPP_
#define MYX_MATH_ALMOST_EQUAL_ULPS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/math/almost_equal_ulps_and_abs.hpp>
#endif
#include <myx/math/float_cmp_types.hpp>
#include <cmath>
namespace myx {
namespace math {
MYXLIB_INLINE bool almost_equal_ulps_and_abs( const float a, const float b,
const float maxAbsDiff, const int maxUlpsDiff )
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
float absDiff = fabsf( a - b );
if ( absDiff <= maxAbsDiff )
{
return( true );
}
FloatCmp uA( a );
FloatCmp uB( b );
// Different signs means they do not match.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
if ( uA.negative() != uB.negative() )
{
return( false );
}
// Find the difference in ULPs.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
int ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps_and_abs
MYXLIB_INLINE bool almost_equal_ulps_and_abs( const double a, const double b,
const double maxAbsDiff, const int maxUlpsDiff )
{
// Check if the numbers are really close -- needed
// when comparing numbers near zero.
double absDiff = fabs( a - b );
if ( absDiff <= maxAbsDiff )
{
return( true );
}
DoubleCmp uA( a );
DoubleCmp uB( b );
// Different signs means they do not match.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
if ( uA.negative() != uB.negative() )
{
return( false );
}
// Find the difference in ULPs.
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access)
auto ulpsDiff = std::abs( uA.i - uB.i );
if ( ulpsDiff <= maxUlpsDiff )
{
return( true );
}
return( false );
} // almost_equal_ulps_and_abs
} // namespace math
} // namespace myx
#endif

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/math/almost_equal_ulps_and_abs-inl.hpp>

View File

@ -1,37 +0,0 @@
#ifndef MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
#define MYX_MATH_ALMOST_EQUAL_ULPS_HPP_
#pragma once
#include <myx/base/config.hpp>
namespace myx {
namespace math {
/**
* @brief Проверка на равенство двух аргументов типа float.
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
* при которой они считаются равными.
*/
bool almost_equal_ulps_and_abs( float a, float b,
float maxAbsDiff, int maxUlpsDiff );
/**
* @brief Проверка на равенство двух аргументов типа double.
* Параметр maxAbsDiff определяет максимальную абсолютную допустимую разницу.
* Параметр maxUlpsDiff определяет максимальную разницу между аргументами,
* при которой они считаются равными.
*/
bool almost_equal_ulps_and_abs( double a, double b,
double maxAbsDiff, int maxUlpsDiff );
} // namespace math
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "almost_equal_ulps_and_abs-inl.hpp"
#endif
#endif // MYX_MATH_ALMOST_EQUAL_ULPS_HPP_

View File

@ -1,18 +0,0 @@
#ifndef MYX_MATH_CONSTANTS_INL_HPP_
#define MYX_MATH_CONSTANTS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/math/constants.hpp>
#endif
namespace myx {
namespace math {
} // namespace math
} // namespace myx
#endif

View File

@ -1,5 +0,0 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#include <myx/math/constants-inl.hpp>

View File

@ -1,25 +0,0 @@
#ifndef MYX_MATH_CONSTANTS_HPP_
#define MYX_MATH_CONSTANTS_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <cmath>
#include <type_traits>
namespace myx {
namespace math {
const auto ImpedanceOfFreeSpace = (M_PI * 119.9169832);
} // namespace math
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "constants-inl.hpp"
#endif
#endif // MYX_MATH_CONSTANTS_HPP_

View File

@ -1,56 +0,0 @@
#ifndef MYX_MATH_FLOAT_CMP_TYPES_HPP_
#define MYX_MATH_FLOAT_CMP_TYPES_HPP_
#pragma once
#include <cstdint>
/**
* @brief Объединение для получения знака аргумента типа float.
*/
union FloatCmp
{
int32_t i;
float f;
/**
* @brief Инициализация.
*/
explicit FloatCmp( float num = 0.0F ) : f( num )
{
}
/**
* @brief Функция, возращающая true, если значение отрицательное
*/
bool negative() const
{
return( i < 0 );
}
};
/**
* @brief Объединение для получения знака аргумента типа double.
*/
union DoubleCmp
{
int64_t i;
double d;
/**
* @brief Инициализация.
*/
explicit DoubleCmp( double num = 0.0L ) : d( num )
{
}
/**
* @brief Функция, возращающая true, если значение отрицательное
*/
bool negative() const
{
return( i < 0 );
}
};
#endif // MYX_MATH_FLOAT_CMP_TYPES_HPP_

View File

@ -1,30 +0,0 @@
#ifndef MYX_MATH_FUNCTIONS_HPP_
#define MYX_MATH_FUNCTIONS_HPP_
#pragma once
#include <boost/math/special_functions/pow.hpp>
#include <cmath>
#include <type_traits>
namespace myx {
namespace math {
/*!
* \brief pow2 Возведение в квадрат
* \param value Значение
* \return Квадрат значения
*/
template < typename T >
auto pow2( T const& value ) -> decltype( boost::math::pow< 2 >( value ) )
{
return( boost::math::pow< 2 >( value ) );
}
} // namespace math
} // namespace myx
#endif // MYX_MATH_FUNCTIONS_HPP_

View File

@ -1,48 +0,0 @@
#ifndef MYX_MATH_RADAR_HPP_
#define MYX_MATH_RADAR_HPP_
#pragma once
#include <cmath>
#include <type_traits>
namespace myx {
namespace math {
/*!
* \brief geometric_target_visibility Геометрическая видимость цели
* \param earthRadius Радиус Земли
* \param antennaHeight Высота антенны
* \param targetHeight Высота цели
* \return Максимальная дальность видимости цели
*/
template < typename T >
T geometric_target_visibility( const T& earthRadius, const T& antennaHeight, const T& targetHeight )
{
// static_assert( std::is_arithmetic< T >::value || std::is_same< T, quantity< length_d > >::value, "Arithmetic type is required." );
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return ( sqrt( 2 * earthRadius * antennaHeight ) + sqrt( 2 * earthRadius * targetHeight ) );
}
/*!
* \brief radar_target_visibility Видимость цели по лучу
* \param earthRadius Радиус Земли
* \param antennaHeight Высота антенны
* \param targetHeight Высота цели
* \return Максимальная дальность видимости цели
*/
template < typename T >
T radar_target_visibility( T effectiveEarthRadius, T antennaHeight, T targetHeight )
{
// static_assert( std::is_arithmetic< T >::value || std::is_same< T, quantity< length_d > >::value, "Arithmetic type is required." );
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return ( sqrt( 2 * effectiveEarthRadius * antennaHeight ) + sqrt( 2 * effectiveEarthRadius * targetHeight ) );
}
} // namespace math
} // namespace myx
#endif // MYX_MATH_RADAR_HPP_

View File

@ -1,93 +0,0 @@
#ifndef MYX_MATH_UNITS_HPP_
#define MYX_MATH_UNITS_HPP_
#pragma once
#include <cmath>
#include <type_traits>
namespace myx {
namespace math {
/*!
* \brief radians_to_degrees Перевод из радиан в градусы
* \param radians Значение в радианах
* \return Значение в градусах
*/
template < typename T >
T radians_to_degrees( const T& radians, typename std::enable_if< std::is_floating_point< T >::value >::type* /*unused*/ = 0 )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( radians * M_1_PI * 180.0 );
}
/*!
* \brief degrees_to_radians Перевод из градусов в радианы
* \param degrees Значение в градусах
* \return Значение в радианах
*/
template < typename T >
T degrees_to_radians( const T& degrees, typename std::enable_if< std::is_floating_point< T >::value >::type* /*unused*/ = 0 )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( degrees * M_PI / 180.0 );
}
/*!
* \brief decibel_to_power Перевод из децибелов в мощность $y = 10^{db / 10}$
* \param db Децибелы
* \return Мощность
*/
template < typename T >
T decibel_to_power( T const& db )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( std::pow( 10, db / 10.0 ) );
}
/*!
* \brief power_to_decibel Перевод из мощности в децибелы по формуле $y = 10 * \log(x)$
* \param power Мощность
* \return Децибелы
*/
template < typename T >
T power_to_decibel( T const& power )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( 10 * std::log( power ) );
}
/*!
* \brief decibel_to_power Перевод из децибелов в амплитуду $y = 10^{db / 20}$
* \param db Децибелы
* \return Амплитуда
*/template < typename T >
T decibel_to_magnitude( T const& db )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( std::pow( 10, db / 20.0 ) );
}
/*!
* \brief magnitude_to_decibel Перевод из амплитуды в децибелы по формуле $y = 20 * \log(x)$
* \param magnitude Амплитуда
* \return Децибелы
*/
template < typename T >
T magnitude_to_decibel( T const& magnitude )
{
static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." );
return( 20 * std::log( magnitude ) );
}
} // namespace math
} // namespace myx
#endif // MYX_MATH_UNITS_HPP_

View File

@ -3,59 +3,43 @@ set(TRGT qt)
# cmake-format: off
# Список файлов исходных текстов
if(NOT MYXLIB_HEADER_ONLY)
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/translators.cpp)
endif()
${CMAKE_CURRENT_SOURCE_DIR}/posix_signal_watcher.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translators.cpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_default.cpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_handler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_syslog.cpp
)
set(TRGT_moc_hpp
${CMAKE_CURRENT_SOURCE_DIR}/posix_signal_watcher.hpp
)
set(TRGT_moc_private_hpp
${CMAKE_CURRENT_SOURCE_DIR}/posix_signal_watcher_p.hpp
)
# Список заголовочных файлов (используется для установки)
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/backports.hpp
${CMAKE_CURRENT_SOURCE_DIR}/translators.hpp
${CMAKE_CURRENT_SOURCE_DIR}/translators-inl.hpp)
${CMAKE_CURRENT_SOURCE_DIR}/message_logger.hpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_default.hpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_handler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/message_logger_syslog.hpp
)
set(TRGT_headers ${TRGT_hpp})
set(TRGT_headers ${TRGT_moc_hpp} ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT}-header-only INTERFACE)
target_include_directories(
${TRGT}-header-only SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
qt5_wrap_cpp(TRGT_moc_cpp ${TRGT_moc_private_hpp} ${TRGT_moc_hpp})
if(MYXLIB_BUILD_LIBRARIES)
add_common_library(${TRGT} OUTPUT_NAME myx-${TRGT} SOURCES ${TRGT_cpp} ${TRGT_headers})
common_target_properties(${TRGT})
add_library(${TRGT} OBJECT ${TRGT_cpp} ${TRGT_moc_cpp} ${TRGT_moc_private_hpp} ${TRGT_headers})
set_target_properties(${TRGT} PROPERTIES OUTPUT_NAME myx-${TRGT})
myx_cmake_common_target_properties(${TRGT})
myx_cmake_add_static_library(${TRGT})
myx_cmake_add_shared_library(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp} ${TRGT_headers})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
cotire(${TRGT})
install(TARGETS ${TRGT}_static COMPONENT libs-dev ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_SHARED_LIBS)
install(TARGETS ${TRGT}_shared COMPONENT main LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif()
install(FILES ${TRGT_headers} COMPONENT headers
myx_cmake_generate_pkgconfig(${TRGT} BASENAME myx-${TRGT} INSTALL_LIBRARY ${MYXLIB_BUILD_LIBRARIES})
install(FILES ${TRGT_headers} COMPONENT dev
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT headers DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(${TRGT}-install-headers COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=headers -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")

View File

@ -0,0 +1,44 @@
#ifndef MYX_QT_MESSAGE_LOGGER_HPP_
#define MYX_QT_MESSAGE_LOGGER_HPP_
#pragma once
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <QList>
#include <QMessageLogContext>
#include <QSharedPointer>
#include <QString>
namespace myx {
namespace qt {
class MessageLogger
{
public:
virtual ~MessageLogger() noexcept ( true ) = default;
virtual void debug( const QMessageLogContext& context, const QString& ) = 0;
virtual void info( const QMessageLogContext& context, const QString& ) = 0;
virtual void warning( const QMessageLogContext& context, const QString& ) = 0;
virtual void critical( const QMessageLogContext& context, const QString& ) = 0;
virtual void fatal( const QMessageLogContext& context, const QString& ) = 0;
void setEnabled( bool v = true ) { m_enabled = v; }
bool isEnabled() { return( m_enabled ); }
protected:
bool m_enabled { true };
};
using MessageLoggersList = QList< QSharedPointer< MessageLogger > >;
extern MessageLoggersList messageLoggersList;
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_MESSAGE_LOGGER_HPP_

View File

@ -0,0 +1,46 @@
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger_default.hpp>
#include <QtDebug>
namespace myx {
namespace qt {
void MessageLoggerDefault::debug( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
fprintf( stderr, "D: %s\n", msg.toUtf8().data() );
}
void MessageLoggerDefault::info( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
fprintf( stderr, "I: %s\n", msg.toUtf8().data() );
}
void MessageLoggerDefault::warning( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
fprintf( stderr, "W: %s\n", msg.toUtf8().data() );
}
void MessageLoggerDefault::critical( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
}
void MessageLoggerDefault::fatal( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
}
} // namespace qt
} // namespace myx

View File

@ -0,0 +1,31 @@
#ifndef MYX_QT_MESSAGE_LOGGER_DEFAULT_HPP_
#define MYX_QT_MESSAGE_LOGGER_DEFAULT_HPP_
#pragma once
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger.hpp>
namespace myx {
namespace qt {
class MessageLoggerDefault : public MessageLogger
{
public:
virtual ~MessageLoggerDefault() noexcept ( true ) = default;
void debug( const QMessageLogContext& context, const QString& msg ) override;
void info( const QMessageLogContext& context, const QString& msg ) override;
void warning( const QMessageLogContext& context, const QString& msg ) override;
void critical( const QMessageLogContext& context, const QString& msg ) override;
void fatal( const QMessageLogContext& context, const QString& msg ) override;
};
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_MESSAGE_LOGGER_DEFAULT_HPP_

View File

@ -0,0 +1,81 @@
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger.hpp>
#include <QtDebug>
namespace myx {
namespace qt {
MessageLoggersList messageLoggersList;
void message_logger_handler( QtMsgType type, const QMessageLogContext& context, const QString& msg )
{
if ( messageLoggersList.isEmpty() )
{
QByteArray localMsg = msg.toLocal8Bit();
const char* file = context.file != nullptr ? context.file : "";
const char* function = context.function != nullptr ? context.function : "";
switch ( type )
{
case QtDebugMsg:
#ifndef QT_NO_DEBUG_OUTPUT
// fprintf( stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function );
fprintf( stderr, "%s\n", localMsg.constData() );
#endif
break;
case QtInfoMsg:
#ifndef QT_NO_INFO_OUTPUT
// fprintf( stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function );
fprintf( stderr, "%s\n", localMsg.constData() );
#endif
break;
case QtWarningMsg:
#ifndef QT_NO_WARNING_OUTPUT
// fprintf( stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function );
fprintf( stderr, "%s\n", localMsg.constData() );
#endif
break;
case QtCriticalMsg:
// fprintf( stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function );
// fprintf( stderr, "%s\n", localMsg.constData() );
// break;
case QtFatalMsg:
// fprintf( stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function );
fprintf( stderr, "%s\n", localMsg.constData() );
break;
} // switch
}
else
{
switch ( type )
{
case QtDebugMsg:
for ( const auto& m: qAsConst( messageLoggersList ) )
{ if ( m->isEnabled() ) { m->debug( context, msg ); } }
break;
case QtInfoMsg:
for ( const auto& m: qAsConst( messageLoggersList ) )
{ if ( m->isEnabled() ) { m->info( context, msg ); } }
break;
case QtWarningMsg:
for ( const auto& m: qAsConst( messageLoggersList ) )
{ if ( m->isEnabled() ) { m->warning( context, msg ); } }
break;
case QtCriticalMsg:
for ( const auto& m: qAsConst( messageLoggersList ) )
{ if ( m->isEnabled() ) { m->critical( context, msg ); } }
break;
case QtFatalMsg:
for ( const auto& m: qAsConst( messageLoggersList ) )
{ if ( m->isEnabled() ) { m->fatal( context, msg ); } }
break;
} // switch
}
} // message_logger_handler
} // namespace qt
} // namespace myx

View File

@ -0,0 +1,20 @@
#ifndef MYX_QT_MESSAGE_LOGGER_HANDLER_HPP_
#define MYX_QT_MESSAGE_LOGGER_HANDLER_HPP_
#pragma once
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger.hpp>
namespace myx {
namespace qt {
void message_logger_handler( QtMsgType type, const QMessageLogContext& context, const QString& msg );
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_MESSAGE_LOGGER_HANDLER_HPP_

View File

@ -0,0 +1,61 @@
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger_syslog.hpp>
#include <syslog.h>
namespace myx {
namespace qt {
MessageLoggerSyslog::MessageLoggerSyslog() :
MessageLogger()
{
// openlog( nullptr, LOG_ODELAY, LOG_USER );
}
MessageLoggerSyslog::~MessageLoggerSyslog() noexcept ( true )
{
closelog();
}
void MessageLoggerSyslog::debug( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
syslog( LOG_DEBUG, "%s\n", msg.toUtf8().data() );
}
void MessageLoggerSyslog::info( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
syslog( LOG_INFO, "%s\n", msg.toUtf8().data() );
}
void MessageLoggerSyslog::warning( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
syslog( LOG_WARNING, "%s\n", msg.toUtf8().data() );
}
void MessageLoggerSyslog::critical( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
syslog( LOG_CRIT, "%s\n", msg.toUtf8().data() );
}
void MessageLoggerSyslog::fatal( const QMessageLogContext& context, const QString& msg )
{
Q_UNUSED( context )
syslog( LOG_EMERG, "%s\n", msg.toUtf8().data() );
}
} // namespace qt
} // namespace myx

View File

@ -0,0 +1,32 @@
#ifndef MYX_QT_MESSAGE_LOGGER_SYSLOG_HPP_
#define MYX_QT_MESSAGE_LOGGER_SYSLOG_HPP_
#pragma once
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/message_logger.hpp>
namespace myx {
namespace qt {
class MessageLoggerSyslog : public MessageLogger
{
public:
MessageLoggerSyslog();
virtual ~MessageLoggerSyslog() noexcept ( true );
void debug( const QMessageLogContext& context, const QString& msg ) override;
void info( const QMessageLogContext& context, const QString& msg ) override;
void warning( const QMessageLogContext& context, const QString& msg ) override;
void critical( const QMessageLogContext& context, const QString& msg ) override;
void fatal( const QMessageLogContext& context, const QString& msg ) override;
};
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_MESSAGE_LOGGER_SYSLOG_HPP_

View File

@ -0,0 +1,131 @@
#ifndef MYX_QT_POSIX_SIGNAL_WATCHER_CPP_
#define MYX_QT_POSIX_SIGNAL_WATCHER_CPP_
#include <myx/backports/cpp/helpers.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/posix_signal_watcher.hpp>
#include <myx/qt/posix_signal_watcher_p.hpp>
namespace myx {
namespace qt {
std::array< int, 2 > PosixSignalWatcherPrivate::mSockpair { { 0, 0 } }; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
PosixSignalWatcherPrivate::~PosixSignalWatcherPrivate() = default;
PosixSignalWatcherPrivate::PosixSignalWatcherPrivate( PosixSignalWatcher* q ) :
q_ptr( q )
{
#ifdef Q_OS_UNIX
// Create socket pair
if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, mSockpair.data() ) != 0 )
{
qDebug() << "PosixSignalWatcher: socketpair: " << ::strerror( errno );
return;
}
#endif
// Create a notifier for the read end of the pair
// m_notifier.reset( new QSocketNotifier( mSockpair[1], QSocketNotifier::Read ) );
m_notifier = std::make_unique< QSocketNotifier >( mSockpair[1], QSocketNotifier::Read );
// Called when the signal handler has written to the socket pair.
// Emits the Posix signal as a Qt signal.
connect( m_notifier.get(), &QSocketNotifier::activated, q, [this]( int sockfd ) {
Q_Q( PosixSignalWatcher );
int signal = 0;
(void)::read( sockfd, &signal, sizeof( signal ) );
qDebug() << "Caught signal: " << ::strsignal( signal );
Q_EMIT q->posixSignal( signal );
} );
m_notifier->setEnabled( true );
}
/*!
* Registers a handler for the given Posix \a signal. The handler will write to
* a socket pair, the other end of which is connected to a QSocketNotifier.
* This provides a way to break out of the asynchronous context from which the
* signal handler is called and back into the Qt event loop.
*/
MYXLIB_INLINE void PosixSignalWatcherPrivate::watchForSignal( int signal )
{
if ( m_watchedSignals.contains( signal ) )
{
qDebug() << "Already watching for signal " << signal;
return;
}
#ifdef Q_OS_UNIX
// Register a sigaction which will write to the socket pair
struct sigaction sigact; //NOLINT
sigact.sa_handler = PosixSignalWatcherPrivate::signalHandler; //NOLINT
sigact.sa_flags = 0;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags |= SA_RESTART;
sigact.sa_restorer = nullptr;
if ( ::sigaction( signal, &sigact, nullptr ) != 0 )
{
qDebug() << "PosixSignalWatcher: sigaction: " << ::strerror( errno );
return;
}
#endif
m_watchedSignals.append( signal );
} // PosixSignalWatcherPrivate::watchForSignal
/*!
* Called when a Posix \a signal is received. Write to the socket to wake up the
* QSocketNotifier.
*/
MYXLIB_INLINE void PosixSignalWatcherPrivate::signalHandler( int signal )
{
(void)::write( mSockpair[0], &signal, sizeof( signal ) );
}
/*!
* Create a new PosixSignalWatcher as a child of the given \a parent.
*/
MYXLIB_INLINE PosixSignalWatcher::PosixSignalWatcher( QObject* parent ) :
QObject( parent ),
d_ptr ( new PosixSignalWatcherPrivate( this ) )
{
}
/*!
* Register a signal handler for the given \a signal.
*
* After calling this method you can \c connect() to the POSIXSignal() Qt signal
* to be notified when the Posix signal is received.
*/
MYXLIB_INLINE void PosixSignalWatcher::watchForSignal( int signal )
{
Q_D( PosixSignalWatcher );
d->watchForSignal( signal );
}
/*!
* \fn void PosixSignalWatcher::posixSignal(int signal)
* Emitted when the given Posix \a signal is received.
*
* watchForSignal() must be called for each Posix signal that you want to receive
* via the POSIXSignal() Qt signal. If a watcher is watching multiple signals,
* POSIXSignal() will be emitted whenever *any* of the watched Posix signals are
* received, and the \a signal argument can be inspected to find out which one
* was actually received.
*/
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_POSIX_SIGNAL_WATCHER_CPP_

View File

@ -0,0 +1,49 @@
#ifndef MYX_QT_POSIX_SIGNAL_WATCHER_HPP_
#define MYX_QT_POSIX_SIGNAL_WATCHER_HPP_
#pragma once
#include <myx/core/config.hpp>
#include <QObject>
#include <csignal>
namespace myx {
namespace qt {
class PosixSignalWatcherPrivate;
#if defined( Q_OS_WIN )
const int SIGINT = 2;
const int SIGTERM = 15;
#endif
/*!
* \brief The PosixSignalWatcher class converts Posix signals to Qt signals.
*
* To watch for a given signal, e.g. \c SIGINT, call \c watchForSignal(SIGINT)
* and \c connect() your handler to posixSignal().
*/
class PosixSignalWatcher : public QObject
{
Q_OBJECT
public:
explicit PosixSignalWatcher( QObject* parent = nullptr );
void watchForSignal( int signal );
Q_SIGNAL void posixSignal( int signal );
private:
PosixSignalWatcherPrivate* const d_ptr = nullptr;
Q_DECLARE_PRIVATE( PosixSignalWatcher ) //NOLINT
}; // class PosixSignalWatcher
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_POSIX_SIGNAL_WATCHER_HPP_

View File

@ -0,0 +1,58 @@
#ifndef MYX_QT_POSIX_SIGNAL_WATCHER_P_HPP_
#define MYX_QT_POSIX_SIGNAL_WATCHER_P_HPP_
#pragma once
#include <myx/core/config.hpp>
#include <myx/qt/posix_signal_watcher.hpp>
#include <QMap>
#include <QObject>
#include <QSocketNotifier>
#include <QtDebug>
#include <array>
#include <memory>
#ifdef Q_OS_UNIX
#include <cerrno>
#include <csignal>
#include <sys/socket.h>
#include <unistd.h>
#endif
namespace myx {
namespace qt {
/*!
* \brief The PosixSignalWatcherPrivate class implements the back-end signal
* handling for the PosixSignalWatcher.
*
* \see http://qt-project.org/doc/qt-5.0/qtdoc/POSIX-signals.html
*/
class PosixSignalWatcherPrivate : public QObject
{
Q_OBJECT
public:
explicit PosixSignalWatcherPrivate( PosixSignalWatcher* q );
~PosixSignalWatcherPrivate();
void watchForSignal( int signal );
static void signalHandler( int signal );
private:
Q_DECLARE_PUBLIC( PosixSignalWatcher )
PosixSignalWatcher* const q_ptr = nullptr;
static std::array< int, 2 > mSockpair;
std::unique_ptr< QSocketNotifier > m_notifier;
QList< int > m_watchedSignals;
}; // class PosixSignalWatcherPrivate
} // namespace qt
} // namespace myx
#endif // ifndef MYX_QT_POSIX_SIGNAL_WATCHER_P_HPP_

View File

@ -1,67 +0,0 @@
#ifndef MYX_QT_TRANSLATORS_INL_HPP_
#define MYX_QT_TRANSLATORS_INL_HPP_
#pragma once
#ifndef MYXLIB_HEADER_ONLY
#include <myx/qt/translators.hpp>
#endif
#include <myx/base/config.hpp>
#include <QCoreApplication>
#include <QLibraryInfo>
#include <QLocale>
namespace myx {
namespace qt {
MYXLIB_INLINE void append_translators( QTranslatorsList& translators, const QString& appName )
{
auto* translator = new QTranslator( qApp );
if ( translator->load( QLocale(),
appName, QStringLiteral( "_" ), QStringLiteral( ":/qm" ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
translator = new QTranslator( qApp );
if ( translator->load( QLocale::system(),
QStringLiteral( "qt" ), QStringLiteral( "_" ),
QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
translator = new QTranslator( qApp );
if ( translator->load( "qtbase_" + QLocale::system().name(),
QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
for ( auto* i : qAsConst( translators ) )
{
qApp->installTranslator( i );
}
} // append_translators
} // namespace qt
} // namespace myx
#endif // MYX_QT_TRANSLATORS_INL_HPP_

View File

@ -1,5 +1,64 @@
#ifndef MYXLIB_BUILD_LIBRARIES
#error Define MYXLIB_BUILD_LIBRARIES to compile this file.
#endif
#ifndef MYX_QT_TRANSLATORS_CPP_
#define MYX_QT_TRANSLATORS_CPP_
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <myx/qt/translators.hpp>
#include <QCoreApplication>
#include <QLibraryInfo>
#include <QLocale>
namespace myx {
namespace qt {
MYXLIB_INLINE void append_translators( QTranslatorsList& translators, const QString& appName )
{
auto* translator = new QTranslator( qApp );
if ( translator->load( QLocale(),
appName, QStringLiteral( "_" ), QStringLiteral( ":/qm" ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
translator = new QTranslator( qApp );
if ( translator->load( QLocale::system(),
QStringLiteral( "qt" ), QStringLiteral( "_" ),
QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
translator = new QTranslator( qApp );
if ( translator->load( "qtbase_" + QLocale::system().name(),
QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
{
translators.append( translator );
}
else
{
translator->deleteLater();
}
for ( auto* i: qAsConst( translators ) )
{
qApp->installTranslator( i );
}
} // append_translators
} // namespace qt
} // namespace myx
#endif // MYX_QT_TRANSLATORS_CPP_

View File

@ -3,8 +3,8 @@
#pragma once
#include <myx/base/config.hpp>
#include <myx/qt/backports.hpp>
#include <myx/backports/qt/common.hpp>
#include <myx/core/config.hpp>
#include <QTranslator>
@ -20,8 +20,4 @@ void append_translators( QTranslatorsList& translators, const QString& appName )
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "translators-inl.hpp"
#endif
#endif // ifndef MYX_QT_TRANSLATORS_HPP_

View File

@ -1,66 +0,0 @@
# Название основной цели и имя библиотеки в текущем каталоге
set(TRGT redis)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp
${CMAKE_CURRENT_SOURCE_DIR}/lexer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/parser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/request.cpp)
# Список заголовочных файлов (используется для установки)
set(TRGT_moc_hpp
${CMAKE_CURRENT_SOURCE_DIR}/client.hpp
${CMAKE_CURRENT_SOURCE_DIR}/config.hpp
${CMAKE_CURRENT_SOURCE_DIR}/lexer.hpp
${CMAKE_CURRENT_SOURCE_DIR}/parser.hpp
${CMAKE_CURRENT_SOURCE_DIR}/reply.hpp
${CMAKE_CURRENT_SOURCE_DIR}/request.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on
add_library(${TRGT}-header-only INTERFACE)
target_include_directories(
${TRGT}-header-only SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
if(MYXLIB_BUILD_LIBRARIES)
add_common_library(${TRGT} OUTPUT_NAME myx-${TRGT} SOURCES ${TRGT_cpp} ${TRGT_headers})
common_target_properties(${TRGT})
# Создание цели для проверки утилитой clang-tidy
add_clang_tidy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clang-analyze
add_clang_analyze_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой clazy
add_clazy_check(${TRGT} ${TRGT_cpp} ${TRGT_headers})
# Создание цели для проверки утилитой pvs-studio
add_pvs_check(${TRGT})
# Создание цели для автоматического форматирования кода
add_format_sources(${TRGT} ${TRGT_cpp} ${TRGT_headers})
target_compile_definitions(${TRGT} PUBLIC MYXLIB_BUILD_LIBRARIES)
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PUBLIC ${Qt5Network_INCLUDE_DIRS})
target_include_directories(${TRGT} SYSTEM PRIVATE ${CMAKE_SOURCE_DIR}/src)
cotire(${TRGT})
install(TARGETS ${TRGT}_static COMPONENT DEV ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(BUILD_SHARED_LIBS)
install(TARGETS ${TRGT}_shared COMPONENT DEV LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endif()
install(FILES ${TRGT_headers} COMPONENT DEV DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${TRGT})
install(FILES ${CMAKE_BINARY_DIR}/${TRGT}.pc COMPONENT DEV DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# Цель, используемая только для установки заголовочных файлов без компиляции проекта
add_custom_target(${TRGT}-install-headers COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_COMPONENT=DEV -P
"${CMAKE_BINARY_DIR}/cmake_install.cmake")

Some files were not shown because too many files have changed in this diff Show More