Compare commits
10 Commits
b871b9dd46
...
4e08d985c9
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e08d985c9 | |||
| 652fbd0890 | |||
| b1df84a87f | |||
|
|
5df3dcf596 | ||
|
|
07cf211b3d | ||
| 86bb53d358 | |||
|
|
97b908838c | ||
| 6352865610 | |||
| 593a914d8d | |||
| 5b4456d6ef |
746
.qtcreator/CMakeLists.txt.user.25c9513
Normal file
746
.qtcreator/CMakeLists.txt.user.25c9513
Normal file
@@ -0,0 +1,746 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<!-- Written by QtCreator 18.0.1, 2026-02-10T08:36:52. -->
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>EnvironmentId</variable>
|
||||||
|
<value type="QByteArray">{25c95133-c398-49ba-8aa0-e9daf4073ad0}</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
|
<value type="qlonglong">0</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||||
|
<value type="QString" key="language">Cpp</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||||
|
<value type="QString" key="language">QmlJS</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||||
|
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||||
|
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||||
|
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||||
|
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||||
|
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||||
|
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||||
|
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="ClangTools">
|
||||||
|
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||||
|
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||||
|
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||||
|
<value type="int" key="ClangTools.ParallelJobs">4</value>
|
||||||
|
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||||
|
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ClangdSettings">
|
||||||
|
<value type="bool" key="blockIndexing">true</value>
|
||||||
|
<value type="bool" key="useGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="RcSync">0</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="DeviceType">Desktop</value>
|
||||||
|
<value type="bool" key="HasPerBcDcs">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{0a48682c-1ff4-4142-9b6d-ae2f5a4dfc82}</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||||
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||||
|
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||||
|
-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||||
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
|
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Debug</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/timur/PROGRAMS/C++/mcc/build/Desktop-Debug</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Отладка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings">
|
||||||
|
<value type="bool" key="AndroidBuildTargetDirSupport">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ApplicationmanagerPackageTargets"/>
|
||||||
|
<value type="bool" key="UseAndroidBuildTargetDir">false</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_telemetry_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_coord_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.2">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_pzone_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">3</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_telemetry_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_coord_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.2">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_pzone_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">3</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.1</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="DeviceType">Desktop</value>
|
||||||
|
<value type="bool" key="HasPerBcDcs">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clang</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clang</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{609869bc-d303-4485-8b34-3f43a08cec9e}</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">3</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||||
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||||
|
-DCMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}
|
||||||
|
-DCMAKE_GENERATOR:STRING=Ninja
|
||||||
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
|
-DCMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX}
|
||||||
|
-DQT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable}
|
||||||
|
-DCMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Debug</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/timur/PROGRAMS/C++/mcc/build/Clang-Debug</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Отладка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">3</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings">
|
||||||
|
<value type="bool" key="AndroidBuildTargetDirSupport">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ApplicationmanagerPackageTargets"/>
|
||||||
|
<value type="bool" key="UseAndroidBuildTargetDir">false</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">exe</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_telemetry_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.2">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_coord_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.3">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_pzone_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">4</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||||
|
<value type="QString"></value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Собрать</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||||
|
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">exe</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_telemetry_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.2">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_coord_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.3">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">mcc_pzone_test</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">4</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||||
|
<value type="qlonglong">2</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
366
CMakeLists.txt
366
CMakeLists.txt
@@ -1,11 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
|
set(QT_CREATOR_SKIP_MAINTENANCE_TOOL_PROVIDER ON)
|
||||||
|
|
||||||
# ******* MOUNT CONTROL COMPONENTS *******
|
# ******* MOUNT CONTROL COMPONENTS *******
|
||||||
|
|
||||||
project(mcc LANGUAGES C CXX Fortran VERSION 0.1)
|
project(mcc LANGUAGES C CXX Fortran VERSION 0.1)
|
||||||
|
|
||||||
|
|
||||||
# set(CMAKE_BUILD_TYPE Release)
|
# set(CMAKE_BUILD_TYPE Release)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
@@ -13,13 +13,27 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
|
||||||
# ******* LIBRARY OPTIONS *******
|
# ******* LIBRARY OPTIONS *******
|
||||||
|
|
||||||
option(USE_SPDLOG "Use of SPDLOG library (add implementation of logger class based on this library)" ON)
|
option(
|
||||||
option(USE_ERFA "Use of ERFA library (add implementation of CCTE based on this library)" ON)
|
USE_SPDLOG
|
||||||
|
"Use of SPDLOG library (add implementation of logger class based on this library)"
|
||||||
|
ON
|
||||||
|
)
|
||||||
|
|
||||||
|
option(
|
||||||
|
USE_ERFA
|
||||||
|
"Use of ERFA library (add implementation of CCTE based on this library)"
|
||||||
|
ON
|
||||||
|
)
|
||||||
|
|
||||||
option(USE_BSPLINE_PCM "Use of FITPACK bivariate splines for PCM" ON)
|
option(USE_BSPLINE_PCM "Use of FITPACK bivariate splines for PCM" ON)
|
||||||
|
|
||||||
|
option(
|
||||||
|
USE_ASIO
|
||||||
|
"Use of ASIO-library (add generic implementation of network capabilities)"
|
||||||
|
ON
|
||||||
|
)
|
||||||
|
|
||||||
option(BUILD_TESTS "Build tests" ON)
|
option(BUILD_TESTS "Build tests" ON)
|
||||||
|
|
||||||
@@ -30,153 +44,220 @@ include(ExternalProject)
|
|||||||
|
|
||||||
# ******* SPDLOG LIBRARY *******
|
# ******* SPDLOG LIBRARY *******
|
||||||
|
|
||||||
if (USE_SPDLOG)
|
if(USE_SPDLOG)
|
||||||
set(SPDLOG_USE_STD_FORMAT ON CACHE INTERNAL "Use of C++20 std::format")
|
set(SPDLOG_USE_STD_FORMAT ON CACHE INTERNAL "Use of C++20 std::format")
|
||||||
set(SPDLOG_FMT_EXTERNAL OFF CACHE INTERNAL "Turn off external fmt library")
|
set(SPDLOG_FMT_EXTERNAL OFF CACHE INTERNAL "Turn off external fmt library")
|
||||||
|
|
||||||
find_package(spdlog CONFIG)
|
find_package(spdlog CONFIG)
|
||||||
if (NOT ${spdlog_FOUND})
|
if(NOT ${spdlog_FOUND})
|
||||||
FetchContent_Declare(spdlog
|
message(STATUS "\tfetch spdlog-lib ...")
|
||||||
GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
|
FetchContent_Declare(
|
||||||
GIT_TAG "v1.15.1"
|
spdlog
|
||||||
GIT_SHALLOW TRUE
|
GIT_REPOSITORY "https://github.com/gabime/spdlog.git"
|
||||||
GIT_SUBMODULES ""
|
GIT_TAG "v1.15.1"
|
||||||
GIT_PROGRESS TRUE
|
GIT_SHALLOW TRUE
|
||||||
CMAKE_ARGS "-DSPDLOG_USE_STD_FORMAT=ON -DSPDLOG_FMT_EXTERNAL=OFF"
|
GIT_SUBMODULES ""
|
||||||
OVERRIDE_FIND_PACKAGE
|
GIT_PROGRESS TRUE
|
||||||
|
CMAKE_ARGS
|
||||||
|
"-DSPDLOG_USE_STD_FORMAT=ON -DSPDLOG_FMT_EXTERNAL=OFF"
|
||||||
|
OVERRIDE_FIND_PACKAGE
|
||||||
)
|
)
|
||||||
find_package(spdlog CONFIG)
|
find_package(spdlog REQUIRED CONFIG)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# ******* ERFA LIBRARY *******
|
# ******* ERFA LIBRARY *******
|
||||||
|
|
||||||
find_program(MESON_PROG NAMES meson HINTS ENV PATHS)
|
|
||||||
|
|
||||||
if (NOT MESON_PROG)
|
|
||||||
message(FATAL "meson executable can not be found!!!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_program(NINJA_PROG NAMES ninja ninja-build)
|
|
||||||
|
|
||||||
if (NOT NINJA_PROG)
|
|
||||||
message(FATAL "ninja executable can not be found!!!")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
pkg_check_modules(ERFALIB IMPORTED_TARGET GLOBAL erfa)
|
if(USE_ERFA)
|
||||||
|
|
||||||
if (NOT ERFALIB_FOUND)
|
|
||||||
message(STATUS "\tfetch erfa-lib ...")
|
|
||||||
# ExternalProject_Add(erfalib
|
|
||||||
# PREFIX ${CMAKE_BINARY_DIR}/erfa_lib
|
|
||||||
# GIT_REPOSITORY "https://github.com/liberfa/erfa.git"
|
|
||||||
# GIT_TAG "v2.0.1"
|
|
||||||
# UPDATE_COMMAND ""
|
|
||||||
# PATCH_COMMAND ""
|
|
||||||
# LOG_CONFIGURE 1
|
|
||||||
# CONFIGURE_COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release
|
|
||||||
# -Dprefix=${CMAKE_BINARY_DIR}/erfa_lib -Dlibdir= -Dincludedir= -Ddatadir= <SOURCE_DIR>
|
|
||||||
# BUILD_COMMAND ninja -C <BINARY_DIR>
|
|
||||||
# INSTALL_COMMAND meson install -C <BINARY_DIR>
|
|
||||||
# BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a
|
|
||||||
# )
|
|
||||||
|
|
||||||
# add_library(PkgConfig::ERFALIB STATIC IMPORTED GLOBAL)
|
|
||||||
# set_target_properties(PkgConfig::ERFALIB PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a)
|
|
||||||
# set_target_properties(PkgConfig::ERFALIB PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_BINARY_DIR}/erfa_lib)
|
|
||||||
# add_dependencies(PkgConfig::ERFALIB erfalib)
|
|
||||||
|
|
||||||
# set(CACHE{ERFALIB_INCLUDE_DIRS} TYPE PATH VALUE "${CMAKE_BINARY_DIR}/erfa_lib")
|
|
||||||
# set(CACHE{ERFALIB_LIBRARY_DIRS} TYPE PATH VALUE "${CMAKE_BINARY_DIR}/erfa_lib")
|
|
||||||
# set(CACHE{ERFALIB_LIBRARIES} TYPE STRING VALUE "erfa;m")
|
|
||||||
|
|
||||||
|
|
||||||
FetchContent_Declare(erfalib_project
|
|
||||||
GIT_REPOSITORY "https://github.com/liberfa/erfa.git"
|
|
||||||
GIT_TAG "v2.0.1"
|
|
||||||
GIT_SHALLOW TRUE
|
|
||||||
GIT_PROGRESS TRUE
|
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(erfalib_project)
|
|
||||||
# message(STATUS "ERFA: ${erfalib_project_SOURCE_DIR}")
|
|
||||||
|
|
||||||
message(STATUS "\tbuild erfa-lib ...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release
|
|
||||||
-Dprefix=${CMAKE_BINARY_DIR}/erfa_lib -Dlibdir= -Dincludedir= -Ddatadir= ${CMAKE_BINARY_DIR}/erfa_lib ${erfalib_project_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/erfa_lib
|
|
||||||
COMMAND ninja -C ${CMAKE_BINARY_DIR}/erfa_lib
|
|
||||||
)
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/erfa_lib
|
|
||||||
COMMAND meson install -C ${CMAKE_BINARY_DIR}/erfa_lib
|
|
||||||
)
|
|
||||||
|
|
||||||
set(ENV{PKG_CONFIG_PATH} "${CMAKE_BINARY_DIR}/erfa_lib/pkgconfig")
|
|
||||||
pkg_check_modules(ERFALIB IMPORTED_TARGET GLOBAL erfa)
|
pkg_check_modules(ERFALIB IMPORTED_TARGET GLOBAL erfa)
|
||||||
|
|
||||||
|
if(NOT ERFALIB_FOUND)
|
||||||
|
message(STATUS "\tfetch erfa-lib ...")
|
||||||
|
# ExternalProject_Add(erfalib
|
||||||
|
# PREFIX ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
# GIT_REPOSITORY "https://github.com/liberfa/erfa.git"
|
||||||
|
# GIT_TAG "v2.0.1"
|
||||||
|
# UPDATE_COMMAND ""
|
||||||
|
# PATCH_COMMAND ""
|
||||||
|
# LOG_CONFIGURE 1
|
||||||
|
# CONFIGURE_COMMAND meson setup --reconfigure -Ddefault_library=static -Dbuildtype=release
|
||||||
|
# -Dprefix=${CMAKE_BINARY_DIR}/erfa_lib -Dlibdir= -Dincludedir= -Ddatadir= <SOURCE_DIR>
|
||||||
|
# BUILD_COMMAND ninja -C <BINARY_DIR>
|
||||||
|
# INSTALL_COMMAND meson install -C <BINARY_DIR>
|
||||||
|
# BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a
|
||||||
|
# )
|
||||||
|
|
||||||
|
# add_library(PkgConfig::ERFALIB STATIC IMPORTED GLOBAL)
|
||||||
|
# set_target_properties(PkgConfig::ERFALIB PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/erfa_lib/liberfa.a)
|
||||||
|
# set_target_properties(PkgConfig::ERFALIB PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_BINARY_DIR}/erfa_lib)
|
||||||
|
# add_dependencies(PkgConfig::ERFALIB erfalib)
|
||||||
|
|
||||||
|
# set(CACHE{ERFALIB_INCLUDE_DIRS} TYPE PATH VALUE "${CMAKE_BINARY_DIR}/erfa_lib")
|
||||||
|
# set(CACHE{ERFALIB_LIBRARY_DIRS} TYPE PATH VALUE "${CMAKE_BINARY_DIR}/erfa_lib")
|
||||||
|
# set(CACHE{ERFALIB_LIBRARIES} TYPE STRING VALUE "erfa;m")
|
||||||
|
|
||||||
|
find_program(MESON_PROG NAMES meson HINTS ENV PATHS)
|
||||||
|
|
||||||
|
if(NOT MESON_PROG)
|
||||||
|
message(FATAL "meson executable can not be found!!!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(NINJA_PROG NAMES ninja ninja-build)
|
||||||
|
|
||||||
|
if(NOT NINJA_PROG)
|
||||||
|
message(FATAL "ninja executable can not be found!!!")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
erfalib_project
|
||||||
|
GIT_REPOSITORY "https://github.com/liberfa/erfa.git"
|
||||||
|
GIT_TAG "v2.0.1"
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(erfalib_project)
|
||||||
|
# message(STATUS "ERFA: ${erfalib_project_SOURCE_DIR}")
|
||||||
|
|
||||||
|
message(STATUS "\tbuild erfa-lib ...")
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
meson setup --reconfigure -Ddefault_library=static
|
||||||
|
-Dbuildtype=release -Dprefix=${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
-Dlibdir= -Dincludedir= -Ddatadir= ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
${erfalib_project_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
COMMAND ninja -C ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
COMMAND meson install -C ${CMAKE_BINARY_DIR}/erfa_lib
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ENV{PKG_CONFIG_PATH} "${CMAKE_BINARY_DIR}/erfa_lib/pkgconfig")
|
||||||
|
pkg_check_modules(ERFALIB IMPORTED_TARGET GLOBAL erfa)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "ERFA LIBS: ${ERFALIB_LIBRARIES}")
|
||||||
|
message(STATUS "ERFA LIB PATHS: ${ERFALIB_LIBRARY_DIRS}")
|
||||||
|
message(STATUS "ERFA INC PATHS: ${ERFALIB_INCLUDE_DIRS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(USE_ASIO)
|
||||||
|
pkg_check_modules(ASIOLIB IMPORTED_TARGET GLOBAL asio)
|
||||||
|
|
||||||
message(STATUS "ERFA LIBS: ${ERFALIB_LIBRARIES}")
|
if(NOT ASIOLIB_FOUND)
|
||||||
message(STATUS "ERFA LIB PATHS: ${ERFALIB_LIBRARY_DIRS}")
|
message(STATUS "\tfetch asio-lib ...")
|
||||||
message(STATUS "ERFA INC PATHS: ${ERFALIB_INCLUDE_DIRS}")
|
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
asiolib_project
|
||||||
|
PREFIX
|
||||||
|
${CMAKE_BINARY_DIR}/asio
|
||||||
|
GIT_REPOSITORY "https://github.com/chriskohlhoff/asio.git"
|
||||||
|
GIT_TAG "asio-1-36-0"
|
||||||
|
GIT_SHALLOW 1
|
||||||
|
)
|
||||||
|
|
||||||
if (USE_BSPLINE_PCM)
|
FetchContent_MakeAvailable(asiolib_project)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${asiolib_project_SOURCE_DIR}/asio
|
||||||
|
COMMAND ./autogen.sh
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${asiolib_project_SOURCE_DIR}/asio
|
||||||
|
COMMAND ./configure --prefix=${asiolib_project_SOURCE_DIR}/asio
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ENV{PKG_CONFIG_PATH} "${asiolib_project_SOURCE_DIR}/asio")
|
||||||
|
pkg_check_modules(ASIOLIB IMPORTED_TARGET GLOBAL asio)
|
||||||
|
|
||||||
|
message(STATUS "ASIO INC PATHS: ${ASIOLIB_INCLUDE_DIRS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(USE_BSPLINE_PCM)
|
||||||
# fitpack by P. Dierckx
|
# fitpack by P. Dierckx
|
||||||
add_subdirectory(fitpack)
|
add_subdirectory(fitpack)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(MCC_SRC mcc_concepts.h mcc_constants.h mcc_epoch.h mcc_angle.h mcc_coordinate.h mcc_error.h
|
set(MCC_SRC
|
||||||
mcc_traits.h mcc_utils.h mcc_ccte_iers.h mcc_ccte_iers_default.h mcc_ccte_erfa.h mcc_pzone.h
|
mcc_concepts.h
|
||||||
mcc_pzone_container.h mcc_pcm.h mcc_telemetry.h mcc_serializer.h)
|
mcc_constants.h
|
||||||
|
mcc_epoch.h
|
||||||
|
mcc_angle.h
|
||||||
|
mcc_coordinate.h
|
||||||
|
mcc_error.h
|
||||||
|
mcc_traits.h
|
||||||
|
mcc_utils.h
|
||||||
|
mcc_pzone.h
|
||||||
|
mcc_pzone_container.h
|
||||||
|
mcc_pcm.h
|
||||||
|
mcc_telemetry.h
|
||||||
|
mcc_serialization_common.h
|
||||||
|
mcc_deserializer.h
|
||||||
|
mcc_serializer.h
|
||||||
|
)
|
||||||
|
|
||||||
if (USE_SPDLOG)
|
if(USE_SPDLOG)
|
||||||
list(APPEND MCC_SRC mcc_spdlog.h)
|
list(APPEND MCC_SRC mcc_spdlog.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(USE_ERFA)
|
||||||
|
list(APPEND MCC_SRC mcc_ccte_iers.h mcc_ccte_iers_default.h mcc_ccte_erfa.h)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(USE_ASIO)
|
||||||
|
list(
|
||||||
|
APPEND MCC_SRC
|
||||||
|
mcc_netserver_endpoint.h
|
||||||
|
mcc_netserver_proto.h
|
||||||
|
mcc_netserver.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} INTERFACE ${MCC_SRC})
|
add_library(${PROJECT_NAME} INTERFACE ${MCC_SRC})
|
||||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23)
|
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23)
|
||||||
target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ERFALIB)
|
|
||||||
# target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ERFALIB fitpack)
|
if(USE_ERFA)
|
||||||
target_include_directories(
|
target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ERFALIB)
|
||||||
${PROJECT_NAME}
|
target_include_directories(
|
||||||
INTERFACE
|
${PROJECT_NAME}
|
||||||
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${ERFALIB_INCLUDE_DIRS};${FITPACK_INCLUDE_DIR};>
|
INTERFACE
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${ERFALIB_INCLUDE_DIRS};>
|
# $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${ERFALIB_INCLUDE_DIRS};${FITPACK_INCLUDE_DIR};>
|
||||||
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${ERFALIB_INCLUDE_DIRS};>
|
||||||
)
|
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
|
||||||
if (USE_BSPLINE_PCM)
|
)
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE USE_BSPLINE_PCM)
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} INTERFACE fitpack)
|
target_include_directories(
|
||||||
# target_include_directories(
|
${PROJECT_NAME}
|
||||||
# ${PROJECT_NAME}
|
INTERFACE
|
||||||
# INTERFACE
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};>
|
||||||
# $<BUILD_INTERFACE:${FITPACK_INCLUDE_DIR};>)
|
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# get_target_property(ZZ ${PROJECT_NAME} INTERFACE_INCLUDE_DIRECTORIES)
|
if(USE_BSPLINE_PCM)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} INTERFACE USE_BSPLINE_PCM)
|
||||||
|
target_link_libraries(${PROJECT_NAME} INTERFACE fitpack)
|
||||||
|
endif()
|
||||||
|
|
||||||
# message(STATUS "INT: ${ZZ}")
|
if(USE_ASIO)
|
||||||
|
target_link_libraries(${PROJECT_NAME} INTERFACE PkgConfig::ASIOLIB)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(USE_SPDLOG)
|
||||||
|
target_link_libraries(${PROJECT_NAME} INTERFACE spdlog::spdlog)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_TESTS)
|
||||||
# add_executable(exe EXCLUDE_FROM_ALL main.cpp)
|
|
||||||
# target_link_libraries(exe PUBLIC ${PROJECT_NAME})
|
|
||||||
|
|
||||||
# get_target_property(ZZ exe INCLUDE_DIRECTORIES)
|
|
||||||
|
|
||||||
# message(STATUS "INT: ${ZZ_STRING}")
|
|
||||||
|
|
||||||
|
|
||||||
if (BUILD_TESTS)
|
|
||||||
add_executable(mcc_telemetry_test tests/mcc_telemetry_test.cpp)
|
add_executable(mcc_telemetry_test tests/mcc_telemetry_test.cpp)
|
||||||
target_link_libraries(mcc_telemetry_test PRIVATE ${PROJECT_NAME})
|
target_link_libraries(mcc_telemetry_test PRIVATE ${PROJECT_NAME})
|
||||||
|
|
||||||
@@ -185,40 +266,57 @@ if (BUILD_TESTS)
|
|||||||
|
|
||||||
add_executable(mcc_pzone_test tests/mcc_pzone_test.cpp)
|
add_executable(mcc_pzone_test tests/mcc_pzone_test.cpp)
|
||||||
target_link_libraries(mcc_pzone_test PRIVATE ${PROJECT_NAME})
|
target_link_libraries(mcc_pzone_test PRIVATE ${PROJECT_NAME})
|
||||||
|
|
||||||
|
add_executable(mcc_netmsg_test tests/mcc_netmsg_test.cpp)
|
||||||
|
target_link_libraries(mcc_netmsg_test PRIVATE ${PROJECT_NAME})
|
||||||
else()
|
else()
|
||||||
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
# This is just a stub to allow access to the path and library settings for the ${PROJECT_NAME} target during development
|
||||||
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
add_executable(just_stub EXCLUDE_FROM_ALL main.cpp)
|
||||||
target_link_libraries(just_stub PUBLIC ${PROJECT_NAME})
|
target_link_libraries(just_stub PUBLIC ${PROJECT_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
|
write_basic_package_version_file(
|
||||||
VERSION ${PROJECT_VERSION}
|
"${PROJECT_NAME}ConfigVersion.cmake"
|
||||||
COMPATIBILITY SameMajorVersion)
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY SameMajorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
set(MCC_CONFIG_INSTALLDIR
|
||||||
|
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||||
|
CACHE PATH
|
||||||
|
"install path for generated library config files"
|
||||||
|
)
|
||||||
|
set(MCC_HEADERS_INSTALLDIR
|
||||||
|
${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
CACHE PATH
|
||||||
|
"install path for headers"
|
||||||
|
)
|
||||||
|
|
||||||
set(MCC_CONFIG_INSTALLDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} CACHE PATH "install path for generated library config files")
|
configure_package_config_file(
|
||||||
set(MCC_HEADERS_INSTALLDIR ${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "install path for headers")
|
"${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in"
|
||||||
|
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||||
configure_package_config_file("${PROJECT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in"
|
INSTALL_DESTINATION ${MCC_CONFIG_INSTALLDIR}
|
||||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
PATH_VARS MCC_HEADERS_INSTALLDIR
|
||||||
INSTALL_DESTINATION
|
)
|
||||||
${MCC_CONFIG_INSTALLDIR}
|
|
||||||
PATH_VARS MCC_HEADERS_INSTALLDIR)
|
|
||||||
|
|
||||||
#install(EXPORT ${PROJECT_NAME}_Targets FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME_NAMESPACE}:: DESTINATION ${MCC_CONFIG_INSTALLDIR})
|
#install(EXPORT ${PROJECT_NAME}_Targets FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME_NAMESPACE}:: DESTINATION ${MCC_CONFIG_INSTALLDIR})
|
||||||
#install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION ${MCC_CONFIG_INSTALLDIR})
|
#install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION ${MCC_CONFIG_INSTALLDIR})
|
||||||
#install(FILES ${MCC_SRC} DESTINATION include/${PROJECT_NAME})
|
#install(FILES ${MCC_SRC} DESTINATION include/${PROJECT_NAME})
|
||||||
|
|
||||||
|
|
||||||
# uninstall target
|
# uninstall target
|
||||||
if(NOT TARGET uninstall)
|
if(NOT TARGET uninstall)
|
||||||
configure_file(
|
configure_file(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
IMMEDIATE @ONLY)
|
IMMEDIATE
|
||||||
|
@ONLY
|
||||||
|
)
|
||||||
|
|
||||||
add_custom_target(uninstall
|
add_custom_target(
|
||||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
uninstall
|
||||||
|
COMMAND
|
||||||
|
${CMAKE_COMMAND} -P
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
28
mcc_angle.h
28
mcc_angle.h
@@ -715,21 +715,21 @@ static constexpr MccCoordPairKind MccCoordStrToPairKind(R&& spair)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum class MccCoordinatePairRep : int {
|
// enum class MccCoordinatePairRep : int {
|
||||||
MCC_COORDPAIR_REP_DEGREES, // both angles are in decimal degrees
|
// MCC_COORDPAIR_REP_DEGREES, // both angles are in decimal degrees
|
||||||
MCC_COORDPAIR_REP_SXGM_HOURDEG, // X is in hour and Y is in degree sexagesimal representation
|
// MCC_COORDPAIR_REP_SXGM_HOURDEG, // X is in hour and Y is in degree sexagesimal representation
|
||||||
MCC_COORDPAIR_REP_SXGM_DEGDEG // both angles are in sexagesimal degrees
|
// MCC_COORDPAIR_REP_SXGM_DEGDEG // both angles are in sexagesimal degrees
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
|
||||||
// default wide-acceptable sexagesimal representation
|
// // default wide-acceptable sexagesimal representation
|
||||||
static constexpr MccCoordinatePairRep MccCoordinatePairToSxgmRep(MccCoordPairKind kind)
|
// static constexpr MccCoordinatePairRep MccCoordinatePairToSxgmRep(MccCoordPairKind kind)
|
||||||
{
|
// {
|
||||||
return kind == MccCoordPairKind::COORDS_KIND_AZALT || kind == MccCoordPairKind::COORDS_KIND_AZZD ||
|
// return kind == MccCoordPairKind::COORDS_KIND_AZALT || kind == MccCoordPairKind::COORDS_KIND_AZZD ||
|
||||||
kind == MccCoordPairKind::COORDS_KIND_XY || kind == MccCoordPairKind::COORDS_KIND_LONLAT ||
|
// kind == MccCoordPairKind::COORDS_KIND_XY || kind == MccCoordPairKind::COORDS_KIND_LONLAT ||
|
||||||
kind == MccCoordPairKind::COORDS_KIND_GENERIC
|
// kind == MccCoordPairKind::COORDS_KIND_GENERIC
|
||||||
? MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_DEGDEG
|
// ? MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_DEGDEG
|
||||||
: MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG; // RA-DEC or HA-DEC
|
// : MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG; // RA-DEC or HA-DEC
|
||||||
}
|
// }
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
@@ -280,15 +280,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// latitude and longitude
|
// longitude and latitude
|
||||||
template <mcc_angle_c LAT_T, mcc_angle_c LON_T>
|
template <mcc_angle_c LON_T, mcc_angle_c LAT_T>
|
||||||
void geoPosition(std::pair<LAT_T, LON_T>* coords) const
|
void geoPosition(std::pair<LON_T, LAT_T>* coords) const
|
||||||
{
|
{
|
||||||
std::lock_guard lock{*_stateMutex};
|
std::lock_guard lock{*_stateMutex};
|
||||||
|
|
||||||
if (coords) {
|
if (coords) {
|
||||||
coords->first = _currentState.lat;
|
coords->first = _currentState.lon;
|
||||||
coords->second = _currentState.lon;
|
coords->second = _currentState.lat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,23 @@ concept mcc_error_c = std::default_initializable<T> && (std::convertible_to<T, b
|
|||||||
|
|
||||||
|
|
||||||
template <mcc_error_c ErrT, mcc_error_c DefErrT>
|
template <mcc_error_c ErrT, mcc_error_c DefErrT>
|
||||||
DefErrT mcc_deduced_err(ErrT const& err, DefErrT const& default_err)
|
auto mcc_deduced_err(ErrT const& err, DefErrT const& default_err)
|
||||||
|
// DefErrT mcc_deduced_err(ErrT const& err, DefErrT const& default_err)
|
||||||
{
|
{
|
||||||
if constexpr (std::same_as<ErrT, DefErrT>) {
|
if constexpr (std::same_as<ErrT, DefErrT>) {
|
||||||
return err;
|
return err;
|
||||||
|
} else if constexpr (std::is_error_code_enum_v<DefErrT>) {
|
||||||
|
if constexpr (std::same_as<ErrT, std::error_code>) {
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
return default_err;
|
||||||
|
}
|
||||||
|
} else if constexpr (std::is_error_condition_enum_v<DefErrT>) {
|
||||||
|
if constexpr (std::same_as<ErrT, std::error_condition>) {
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
return default_err;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return default_err;
|
return default_err;
|
||||||
}
|
}
|
||||||
@@ -147,6 +160,11 @@ concept mcc_fp_type_like_c =
|
|||||||
|
|
||||||
/* GEOMETRICAL ANGLE REPRESENTATION CLASS CONCEPT */
|
/* GEOMETRICAL ANGLE REPRESENTATION CLASS CONCEPT */
|
||||||
|
|
||||||
|
/* REQUIREMENT: in the MCC-library it is assumed that an arithmetic representation of angles are measured in the
|
||||||
|
radians!!! This means that possible conversion operator 'SOME_USER_ANGLE_CLASS::operator double()'
|
||||||
|
must return an angle in radians!
|
||||||
|
*/
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_angle_c = mcc_fp_type_like_c<T> && requires(T v, double vd) {
|
concept mcc_angle_c = mcc_fp_type_like_c<T> && requires(T v, double vd) {
|
||||||
// mandatory arithmetic operations
|
// mandatory arithmetic operations
|
||||||
@@ -468,11 +486,11 @@ struct mcc_skypoint_interface_t {
|
|||||||
return std::forward<SelfT>(self).refractInverseCorrection(dZ);
|
return std::forward<SelfT>(self).refractInverseCorrection(dZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns apparent sideral time (Greenwich) for the epoch of the celestial point
|
// returns apparent sideral time (Greenwich or local) for the epoch of the celestial point
|
||||||
template <std::derived_from<mcc_skypoint_interface_t> SelfT>
|
template <std::derived_from<mcc_skypoint_interface_t> SelfT>
|
||||||
auto appSideralTime(this SelfT&& self, mcc_angle_c auto* st)
|
auto appSideralTime(this SelfT&& self, mcc_angle_c auto* st, bool is_local)
|
||||||
{
|
{
|
||||||
return std::forward<SelfT>(self).appSideralTime(st);
|
return std::forward<SelfT>(self).appSideralTime(st, is_local);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns equation of origins for the epoch of the celestial point
|
// returns equation of origins for the epoch of the celestial point
|
||||||
@@ -566,7 +584,7 @@ concept mcc_pcm_c = std::derived_from<T, mcc_pcm_interface_t<typename T::error_t
|
|||||||
// static constexpr uint16_t HW_MOVE_ERROR = 555;
|
// static constexpr uint16_t HW_MOVE_ERROR = 555;
|
||||||
// }
|
// }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_hardware_movement_state_c = requires {
|
concept mcc_hardware_movement_state_c = std::formattable<T, char> && requires {
|
||||||
[]() {
|
[]() {
|
||||||
// // mount axes were stopped
|
// // mount axes were stopped
|
||||||
// [[maybe_unused]] static constexpr auto v0 = T::HW_MOVE_STOPPED;
|
// [[maybe_unused]] static constexpr auto v0 = T::HW_MOVE_STOPPED;
|
||||||
@@ -616,7 +634,6 @@ concept mcc_hardware_movement_state_c = requires {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_hardware_state_c = requires(T state) {
|
concept mcc_hardware_state_c = requires(T state) {
|
||||||
// encoder co-longitude and co-latiitude positions, as well as its measurement time point
|
// encoder co-longitude and co-latiitude positions, as well as its measurement time point
|
||||||
// the given constrains on coordinate pair kind can be used to deduce mount type
|
|
||||||
requires mcc_coord_pair_c<decltype(state.XY)> &&
|
requires mcc_coord_pair_c<decltype(state.XY)> &&
|
||||||
(decltype(state.XY)::pairKind == impl::MccCoordPairKind::COORDS_KIND_GENERIC ||
|
(decltype(state.XY)::pairKind == impl::MccCoordPairKind::COORDS_KIND_GENERIC ||
|
||||||
decltype(state.XY)::pairKind == impl::MccCoordPairKind::COORDS_KIND_XY);
|
decltype(state.XY)::pairKind == impl::MccCoordPairKind::COORDS_KIND_XY);
|
||||||
@@ -783,6 +800,13 @@ struct mcc_telemetry_interface_t {
|
|||||||
{
|
{
|
||||||
return std::forward<SelfT>(self).setTarget(pt);
|
return std::forward<SelfT>(self).setTarget(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get entered target position
|
||||||
|
template <std::derived_from<mcc_telemetry_interface_t> SelfT>
|
||||||
|
RetT setTarget(this SelfT&& self, mcc_skypoint_c auto* pt)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self).getTarget(pt);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -944,10 +968,11 @@ concept mcc_movement_controls_c = requires(T t) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
concept mcc_mount_status_c = requires {
|
concept mcc_mount_status_c = requires {
|
||||||
[]() {
|
[]() {
|
||||||
[[maybe_unused]] static constexpr std::array arr = {
|
[[maybe_unused]]
|
||||||
T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE, T::MOUNT_STATUS_INITIALIZATION,
|
static constexpr std::array arr = {T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_IDLE,
|
||||||
T::MOUNT_STATUS_ERROR, T::MOUNT_STATUS_STOPPED, T::MOUNT_STATUS_SLEWING,
|
T::MOUNT_STATUS_INITIALIZATION, T::MOUNT_STATUS_STOPPED,
|
||||||
T::MOUNT_STATUS_ADJUSTING, T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING};
|
T::MOUNT_STATUS_SLEWING, T::MOUNT_STATUS_ADJUSTING,
|
||||||
|
T::MOUNT_STATUS_GUIDING, T::MOUNT_STATUS_TRACKING};
|
||||||
}; // to ensure mount status is compile-time constants
|
}; // to ensure mount status is compile-time constants
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,17 @@
|
|||||||
namespace mcc
|
namespace mcc
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr double MCC_HALF_PI = std::numbers::pi / 2.0;
|
static constexpr double MCC_DEGRESS_TO_RADS = std::numbers::pi / 180.0;
|
||||||
constexpr double MCC_TWO_PI = std::numbers::pi * 2.0;
|
static constexpr double MCC_RADS_TO_DEGRESS = 1.0 / MCC_DEGRESS_TO_RADS;
|
||||||
|
|
||||||
|
static constexpr double MCC_HALF_PI = std::numbers::pi / 2.0;
|
||||||
|
static constexpr double MCC_TWO_PI = std::numbers::pi * 2.0;
|
||||||
|
|
||||||
static constexpr double MCC_SIDERAL_TO_UT1_RATIO = 1.002737909350795; // sideral/UT1
|
static constexpr double MCC_SIDERAL_TO_UT1_RATIO = 1.002737909350795; // sideral/UT1
|
||||||
|
|
||||||
|
static constexpr double MCC_J2000_MJD = 51544.5;
|
||||||
|
static constexpr double MCC_MJD_ZERO = 2400000.5;
|
||||||
|
|
||||||
|
|
||||||
// a value to represent of infinite time duration according to type of duration representation
|
// a value to represent of infinite time duration according to type of duration representation
|
||||||
template <traits::mcc_time_duration_c DT>
|
template <traits::mcc_time_duration_c DT>
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ public:
|
|||||||
std::pair<double, double> pos;
|
std::pair<double, double> pos;
|
||||||
cctEngine.geoPosition(&pos);
|
cctEngine.geoPosition(&pos);
|
||||||
|
|
||||||
return MccGeoLONLAT(pos.second, pos.first);
|
return MccGeoLONLAT(pos.first, pos.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -581,14 +581,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error_t appSideralTime(mcc_angle_c auto* st) const
|
error_t appSideralTime(mcc_angle_c auto* st, bool is_local = false) const
|
||||||
{
|
{
|
||||||
// return Greenwich apparent sideral time since epoch is UTC
|
return cctEngine.apparentSideralTime(_epoch, st, is_local);
|
||||||
return cctEngine.apparentSideralTime(_epoch, st, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
error_t EO(mcc_angle_c auto* eo)
|
error_t EO(mcc_angle_c auto* eo) const
|
||||||
{
|
{
|
||||||
return cctEngine.equationOrigins(_epoch, eo);
|
return cctEngine.equationOrigins(_epoch, eo);
|
||||||
}
|
}
|
||||||
@@ -659,30 +658,30 @@ protected:
|
|||||||
// HA, DEC to AZ, ALT (AZ from the South through the West)
|
// HA, DEC to AZ, ALT (AZ from the South through the West)
|
||||||
void hadec2azalt(double ha, double dec, double phi, double& az, double& alt) const
|
void hadec2azalt(double ha, double dec, double phi, double& az, double& alt) const
|
||||||
{
|
{
|
||||||
eraHd2ae(ha, dec, phi, &az, &alt);
|
// eraHd2ae(ha, dec, phi, &az, &alt);
|
||||||
// from ERFA "from N" to "from S"
|
// // from ERFA "from N" to "from S"
|
||||||
if (az > std::numbers::pi) {
|
// if (az > std::numbers::pi) {
|
||||||
az -= std::numbers::pi;
|
// az -= std::numbers::pi;
|
||||||
} else {
|
// } else {
|
||||||
az += std::numbers::pi;
|
// az += std::numbers::pi;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
const auto cos_phi = std::cos(phi), sin_phi = std::sin(phi);
|
const auto cos_phi = std::cos(phi), sin_phi = std::sin(phi);
|
||||||
const auto cos_dec = std::cos(dec), sin_dec = std::sin(dec);
|
const auto cos_dec = std::cos(dec), sin_dec = std::sin(dec);
|
||||||
const auto cos_ha = std::cos(ha), sin_ha = std::sin(ha);
|
const auto cos_ha = std::cos(ha), sin_ha = std::sin(ha);
|
||||||
|
|
||||||
auto x = sin_phi * cos_dec * cos_ha - cos_phi * sin_dec;
|
auto x = sin_phi * cos_dec * cos_ha - cos_phi * sin_dec;
|
||||||
auto y = -cos_dec * sin_ha;
|
auto y = cos_dec * sin_ha;
|
||||||
auto z = cos_phi * cos_dec * cos_ha + sin_phi * sin_dec;
|
auto z = cos_phi * cos_dec * cos_ha + sin_phi * sin_dec;
|
||||||
|
|
||||||
auto xx = x * x, yy = y * y;
|
auto xx = x * x, yy = y * y;
|
||||||
decltype(x) r;
|
decltype(x) r;
|
||||||
if (xx < yy) {
|
if (xx < yy) {
|
||||||
r = yy * sqrt(1.0 + xx / yy);
|
r = std::abs(y) * sqrt(1.0 + xx / yy);
|
||||||
} else {
|
} else {
|
||||||
r = xx * sqrt(1.0 + yy / xx);
|
r = std::abs(x) * sqrt(1.0 + yy / xx);
|
||||||
}
|
}
|
||||||
|
|
||||||
az = utils::isEqual(r, 0.0) ? 0.0 : std::atan2(y, x);
|
az = utils::isEqual(r, 0.0) ? 0.0 : std::atan2(y, x);
|
||||||
@@ -697,10 +696,10 @@ protected:
|
|||||||
// AZ, ALT to HA, DEC (AZ from the South through the West)
|
// AZ, ALT to HA, DEC (AZ from the South through the West)
|
||||||
void azalt2hadec(double az, double alt, double phi, double& ha, double& dec) const
|
void azalt2hadec(double az, double alt, double phi, double& ha, double& dec) const
|
||||||
{
|
{
|
||||||
az += std::numbers::pi;
|
// az += std::numbers::pi;
|
||||||
eraAe2hd(az, alt, phi, &ha, &dec);
|
// eraAe2hd(az, alt, phi, &ha, &dec);
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
const auto cos_phi = std::cos(phi), sin_phi = std::sin(phi);
|
const auto cos_phi = std::cos(phi), sin_phi = std::sin(phi);
|
||||||
const auto cos_az = std::cos(az), sin_az = std::sin(az);
|
const auto cos_az = std::cos(az), sin_az = std::sin(az);
|
||||||
@@ -713,9 +712,9 @@ protected:
|
|||||||
auto xx = x * x, yy = y * y;
|
auto xx = x * x, yy = y * y;
|
||||||
decltype(x) r;
|
decltype(x) r;
|
||||||
if (xx < yy) {
|
if (xx < yy) {
|
||||||
r = yy * sqrt(1.0 + xx / yy);
|
r = std::abs(y) * sqrt(1.0 + xx / yy);
|
||||||
} else {
|
} else {
|
||||||
r = xx * sqrt(1.0 + yy / xx);
|
r = std::abs(x) * sqrt(1.0 + yy / xx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ha = utils::isEqual(r, 0.0) ? 0.0 : std::atan2(y, x);
|
ha = utils::isEqual(r, 0.0) ? 0.0 : std::atan2(y, x);
|
||||||
@@ -735,6 +734,16 @@ protected:
|
|||||||
static_assert(PT::pairKind != MccCoordPairKind::COORDS_KIND_UNKNOWN, "UNSUPPORTED SKY POINT TRANSFORMATION!");
|
static_assert(PT::pairKind != MccCoordPairKind::COORDS_KIND_UNKNOWN, "UNSUPPORTED SKY POINT TRANSFORMATION!");
|
||||||
|
|
||||||
|
|
||||||
|
if constexpr (PT::pairKind == MccCoordPairKind::COORDS_KIND_LONLAT) { // returns geographic site coordinates
|
||||||
|
std::pair<double, double> pos;
|
||||||
|
cctEngine.geoPosition(&pos);
|
||||||
|
|
||||||
|
cpair.setX(pos.first);
|
||||||
|
cpair.setY(pos.second);
|
||||||
|
|
||||||
|
return error_t{};
|
||||||
|
}
|
||||||
|
|
||||||
if (_pairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS &&
|
if (_pairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS &&
|
||||||
PT::pairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS to ICRS - just copy and exit
|
PT::pairKind == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) { // from ICRS to ICRS - just copy and exit
|
||||||
cpair = PT(typename PT::x_t(_x), typename PT::y_t(_y));
|
cpair = PT(typename PT::x_t(_x), typename PT::y_t(_y));
|
||||||
|
|||||||
@@ -1,23 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************************
|
|
||||||
* *
|
|
||||||
* MOUNT CONTROL COMPONENTS LIBRARY *
|
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* IMPLEMENTATION OF DESERIALIZER CLASSES *
|
|
||||||
* *
|
|
||||||
****************************************************************************************/
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
#include "mcc_concepts.h"
|
|
||||||
#include "mcc_coordinate.h"
|
#include "mcc_coordinate.h"
|
||||||
#include "mcc_epoch.h"
|
#include "mcc_epoch.h"
|
||||||
#include "mcc_error.h"
|
#include "mcc_serialization_common.h"
|
||||||
|
|
||||||
namespace mcc::impl
|
namespace mcc::impl
|
||||||
{
|
{
|
||||||
@@ -89,34 +76,11 @@ inline std::error_code make_error_code(MccDeserializerErrorCode ec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <mcc_error_c RetT>
|
|
||||||
struct mcc_deserializer_interface_t {
|
|
||||||
virtual ~mcc_deserializer_interface_t() = default;
|
|
||||||
|
|
||||||
typedef RetT error_t;
|
/* BASE DESERIALIZER CLASS (FOR IMPLEMENTATIONS BELOW) */
|
||||||
|
|
||||||
template <std::derived_from<mcc_deserializer_interface_t> SelfT,
|
struct MccDeserializerBase : mcc_deserializer_interface_t<MccError> {
|
||||||
traits::mcc_input_char_range R,
|
using typename mcc_deserializer_interface_t<MccError>::error_t;
|
||||||
typename ValueT,
|
|
||||||
typename... DeserParamsT>
|
|
||||||
RetT operator()(this SelfT&& self, R const& input, ValueT& value, DeserParamsT&&... params)
|
|
||||||
{
|
|
||||||
return std::forward<SelfT>(self)(input, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
mcc_deserializer_interface_t() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept mcc_deserializer_c = std::derived_from<T, mcc_deserializer_interface_t<typename T::error_t>>;
|
|
||||||
|
|
||||||
|
|
||||||
namespace details
|
|
||||||
{
|
|
||||||
|
|
||||||
struct MccDeserializerBase : mcc_deserializer_interface_t<impl::MccError>, utils::mcc_elem_sequence_with_delim_t {
|
|
||||||
using typename mcc_deserializer_interface_t<impl::MccError>::error_t;
|
|
||||||
|
|
||||||
virtual ~MccDeserializerBase() = default;
|
virtual ~MccDeserializerBase() = default;
|
||||||
|
|
||||||
@@ -127,14 +91,18 @@ protected:
|
|||||||
//
|
//
|
||||||
// empty == true, if the 'input' is empty or if all elements consist of only spaces
|
// empty == true, if the 'input' is empty or if all elements consist of only spaces
|
||||||
//
|
//
|
||||||
std::vector<std::string_view> splitAggregateValue(traits::mcc_input_char_range auto const& input, bool& empty) const
|
static std::vector<std::string_view> splitValueIntoElements(traits::mcc_input_char_range auto const& input,
|
||||||
|
mcc_serialization_params_c auto const& params,
|
||||||
|
bool& empty)
|
||||||
{
|
{
|
||||||
|
static_assert(std::ranges::contiguous_range<decltype(input)>, "NOT IMPLEMENTED FOR NON-CONTIGUIUS RANGES!!!");
|
||||||
|
|
||||||
std::vector<std::string_view> res;
|
std::vector<std::string_view> res;
|
||||||
|
|
||||||
if (std::ranges::size(input)) {
|
if (std::ranges::size(input)) {
|
||||||
empty = true;
|
empty = true;
|
||||||
|
|
||||||
std::ranges::for_each(std::views::split(input, this->_elementDelimiter), [&res, &empty](auto const& el) {
|
std::ranges::for_each(std::views::split(input, params.elem_delim), [&res, &empty](auto const& el) {
|
||||||
std::back_inserter(res) = utils::trimSpaces(std::string_view{el.begin(), el.end()});
|
std::back_inserter(res) = utils::trimSpaces(std::string_view{el.begin(), el.end()});
|
||||||
if (empty && res.back().size()) {
|
if (empty && res.back().size()) {
|
||||||
empty = false;
|
empty = false;
|
||||||
@@ -148,17 +116,17 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename VT, std::ranges::output_range<VT> R, typename... DeserParamsT>
|
template <typename VT, std::ranges::output_range<VT> R, typename... DeserParamsT>
|
||||||
error_t deserializingRange(mcc_deserializer_c auto& dsr,
|
static error_t deserializingRange(mcc_deserializer_c auto& dsr,
|
||||||
traits::mcc_input_char_range auto const& input,
|
traits::mcc_input_char_range auto const& input,
|
||||||
R& r,
|
R& r,
|
||||||
DeserParamsT&&... params) const
|
mcc_serialization_params_c auto const& params)
|
||||||
{
|
{
|
||||||
if (std::ranges::size(input) == 0) { // ignore an empty input, just return empty range?!!
|
if (std::ranges::size(input) == 0) { // ignore an empty input, just return empty range?!!
|
||||||
r = R{};
|
r = R{};
|
||||||
return MccDeserializerErrorCode::ERROR_OK;
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r_str = std::views::split(input, _seqDelimiter);
|
auto r_str = std::views::split(input, params.seq_delim);
|
||||||
VT val;
|
VT val;
|
||||||
|
|
||||||
auto it = r.begin();
|
auto it = r.begin();
|
||||||
@@ -181,24 +149,24 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace details
|
|
||||||
|
|
||||||
|
/* MAIN (FALLBACK) TEMPLATED IMPLEMENTATION */
|
||||||
|
|
||||||
/* fallback template: basic deserializer */
|
|
||||||
|
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
class MccDeserializer : public details::MccDeserializerBase
|
struct MccDeserializer : MccDeserializerBase {
|
||||||
{
|
static constexpr std::string_view deserializerName{"MCC-FALLBACK-DESERIALIZER"};
|
||||||
public:
|
|
||||||
using typename details::MccDeserializerBase::error_t;
|
|
||||||
|
|
||||||
virtual ~MccDeserializer() = default;
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
|
||||||
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
VT& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
{
|
{
|
||||||
if constexpr (std::is_arithmetic_v<VT>) {
|
if constexpr (std::is_arithmetic_v<VT>) {
|
||||||
auto v = mcc::utils::numFromStr<VT>(trimSpaces(input));
|
auto v = mcc::utils::numFromStr<VT>(utils::trimSpaces(input));
|
||||||
if (!v.has_value()) {
|
if (!v.has_value()) {
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
}
|
}
|
||||||
@@ -229,16 +197,16 @@ public:
|
|||||||
static_assert(std::ranges::output_range<VT, el_t>, "INVALID RANGE TYPE!!!");
|
static_assert(std::ranges::output_range<VT, el_t>, "INVALID RANGE TYPE!!!");
|
||||||
|
|
||||||
// no reference or constants allowed
|
// no reference or constants allowed
|
||||||
static_assert(std::is_reference_v<el_t> || std::is_const_v<el_t>, "INVALID RANGE ELEMENT TYPE!!!");
|
static_assert(!(std::is_reference_v<el_t> || std::is_const_v<el_t>), "INVALID RANGE ELEMENT TYPE!!!");
|
||||||
|
|
||||||
MccDeserializer<el_t> dsr;
|
MccDeserializer<el_t> dsr;
|
||||||
return deserializingRange<el_t>(dsr, input, value);
|
return deserializingRange<el_t>(dsr, input, value, params);
|
||||||
} else if constexpr (traits::mcc_time_duration_c<VT>) {
|
} else if constexpr (traits::mcc_time_duration_c<VT>) {
|
||||||
typename VT::rep vd;
|
typename VT::rep vd;
|
||||||
|
|
||||||
MccDeserializer<typename VT::rep> dsr;
|
MccDeserializer<typename VT::rep> dsr;
|
||||||
|
|
||||||
auto err = dsr(trimSpaces(input), vd);
|
auto err = dsr(utils::trimSpaces(input), vd, params);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
}
|
}
|
||||||
@@ -254,72 +222,147 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
||||||
|
|
||||||
|
template <mcc_coord_epoch_c VT>
|
||||||
|
struct MccDeserializer<VT> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-COORD-EPOCH-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
VT& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
bool ok = value.fromCharRange(input);
|
||||||
|
if (!ok) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename VT>
|
template <typename VT>
|
||||||
requires(mcc_coord_epoch_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
requires(!std::is_arithmetic_v<VT> && mcc_angle_c<VT>)
|
||||||
mcc_coord_epoch_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
struct MccDeserializer<VT> : MccDeserializerBase {
|
||||||
class MccDeserializer<VT> : public details::MccDeserializerBase
|
static constexpr std::string_view deserializerName{"MCC-ANGLE-DESERIALIZER"};
|
||||||
{
|
|
||||||
public:
|
|
||||||
using typename details::MccDeserializerBase::error_t;
|
|
||||||
|
|
||||||
virtual ~MccDeserializer() = default;
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
VT& value,
|
||||||
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
{
|
{
|
||||||
if constexpr (mcc_coord_epoch_c<VT>) { // scalar
|
bool hms = params.angle_format == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS;
|
||||||
bool ok = value.fromCharRange(input);
|
|
||||||
|
auto res = utils::parsAngleString(input, hms);
|
||||||
|
if (res) { // returned angle is in degrees!!!
|
||||||
|
value = res.value() * MCC_DEGRESS_TO_RADS;
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_skypoint_c VT>
|
||||||
|
struct MccDeserializer<VT> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-SKYPOINT-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input,
|
||||||
|
VT& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
auto pars = params;
|
||||||
|
|
||||||
|
// valid format: X<elem-delim>Y[<elem-delim>TIME-POINT<elem-delim>PAIR-KIND]
|
||||||
|
// X<elem-delim>Y (assumed RADEC_ICRS and J2000.0 epoch)
|
||||||
|
|
||||||
|
bool empty;
|
||||||
|
|
||||||
|
auto elems = MccDeserializerBase::splitValueIntoElements(input, params, empty);
|
||||||
|
|
||||||
|
if (empty || (elems.size() < 2) || (elems.size() == 3)) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccCoordPairKind pair_kind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||||
|
MccCelestialCoordEpoch epoch; // J2000.0
|
||||||
|
|
||||||
|
MccAngle x, y;
|
||||||
|
MccDeserializer<MccAngle> dsr_ang;
|
||||||
|
|
||||||
|
typename MccDeserializer<MccAngle>::error_t dsr_err;
|
||||||
|
|
||||||
|
if (elems.size() > 3) { // full format
|
||||||
|
// deserialize pair kind string
|
||||||
|
pair_kind = MccCoordStrToPairKind(elems[3]);
|
||||||
|
if (pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoch
|
||||||
|
bool ok = epoch.fromCharRange(elems[2]);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
}
|
}
|
||||||
} else { // range
|
|
||||||
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
|
||||||
MccDeserializer<value_t> dsr;
|
|
||||||
|
|
||||||
return deserializingRange(dsr, input, value);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename VT>
|
// deserialize X and Y
|
||||||
requires(!std::is_arithmetic_v<VT> &&
|
if (params.coordpair_format == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG) {
|
||||||
(mcc_angle_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS;
|
||||||
mcc_angle_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>)))
|
} else {
|
||||||
class MccDeserializer<VT> : public details::MccDeserializerBase
|
pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS;
|
||||||
{
|
}
|
||||||
public:
|
|
||||||
using typename details::MccDeserializerBase::error_t;
|
|
||||||
|
|
||||||
virtual ~MccDeserializer() = default;
|
dsr_err = dsr_ang(elems[0], x, pars);
|
||||||
|
if (dsr_err) {
|
||||||
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
// if hms == true and the input sequence is a sexagesimal string then it interpretates angle as hours:mins:secs
|
pars.angle_format = MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS;
|
||||||
// otherwise the input sequence is interpretated as decimal or sexagesimal degrees
|
dsr_err = dsr_ang(elems[1], y, pars);
|
||||||
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value, bool hms = false)
|
if (dsr_err) {
|
||||||
{
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
if constexpr (mcc_angle_c<VT>) { // scalar
|
}
|
||||||
auto res = utils::parsAngleString(input, hms);
|
|
||||||
if (res) {
|
switch (pair_kind) {
|
||||||
value = res.value();
|
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||||
} else {
|
value.from(MccSkyRADEC_ICRS{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_OBS:
|
||||||
|
value.from(MccSkyRADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||||
|
value.from(MccSkyRADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_OBS:
|
||||||
|
value.from(MccSkyHADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||||
|
value.from(MccSkyHADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZZD:
|
||||||
|
value.from(MccSkyAZZD{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZALT:
|
||||||
|
value.from(MccSkyAZALT{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_XY:
|
||||||
|
value.from(MccGenXY{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_GENERIC:
|
||||||
|
value.from(MccCoordPair{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_LONLAT:
|
||||||
|
value.from(MccGeoLONLAT{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
}
|
|
||||||
|
|
||||||
} else { // range
|
|
||||||
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
|
||||||
MccDeserializer<value_t> dsr;
|
|
||||||
|
|
||||||
if constexpr (std::invocable<MccDeserializer<value_t>, decltype(input), VT&, bool>) {
|
|
||||||
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
|
||||||
// (that is, it can interpret the third argument as a flag "false/true = only
|
|
||||||
// degrees/hour-like")
|
|
||||||
return deserializingRange<value_t>(dsr, input, value, hms);
|
|
||||||
} else {
|
|
||||||
return deserializingRange<value_t>(dsr, input, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MccDeserializerErrorCode::ERROR_OK;
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
@@ -327,119 +370,82 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename VT>
|
template <>
|
||||||
requires(mcc_skypoint_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
struct MccDeserializer<MccCoordPairKind> : MccDeserializerBase {
|
||||||
mcc_skypoint_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
static constexpr std::string_view deserializerName{"MCC-COORDPAIR-DESERIALIZER"};
|
||||||
class MccDeserializer<VT> : public details::MccDeserializerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using typename details::MccDeserializerBase::error_t;
|
|
||||||
|
|
||||||
virtual ~MccDeserializer() = default;
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator ()(
|
||||||
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
traits::mcc_input_char_range auto const& input,
|
||||||
|
MccCoordPairKind& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
{
|
{
|
||||||
if constexpr (mcc_skypoint_c<VT>) { // scalar: X[elem-delim]Y{[elem-delim]TIME-POINT[elem-delim]PAIR-KIND}
|
value = MccCoordStrToPairKind(input);
|
||||||
bool empty; // exactly 2 or >3 elements
|
|
||||||
auto elems = splitAggregateValue(input, empty);
|
|
||||||
|
|
||||||
if (empty || (elems.size() < 2) || (elems.size() == 3)) {
|
if (value == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
}
|
|
||||||
|
|
||||||
MccCoordPairKind pair_kind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
|
||||||
MccCelestialCoordEpoch epoch; // J2000.0
|
|
||||||
|
|
||||||
MccAngle x, y;
|
|
||||||
MccDeserializer<MccAngle> dsr_ang;
|
|
||||||
|
|
||||||
typename MccDeserializer<MccAngle>::error_t dsr_err;
|
|
||||||
|
|
||||||
if (elems.size() >= 4) { // X, Y, TIME-POINT, PAIR-KIND
|
|
||||||
// first, get pair-kind
|
|
||||||
pair_kind = MccCoordStrToPairKind(elems[3]);
|
|
||||||
if (pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// epoch
|
|
||||||
bool ok = epoch.fromCharRange(elems[2]);
|
|
||||||
if (!ok) {
|
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elems.size() >= 2) { // if == 2: just X and Y (if so it is interpretated as RADEC_ICRS)
|
|
||||||
if (MccCoordinatePairToSxgmRep(pair_kind) == MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG) {
|
|
||||||
// if input X-angle is in sexagesimal from then interpretate it in hours::mins::secs format
|
|
||||||
if constexpr (std::invocable<MccDeserializer<MccAngle>, decltype(elems[0]), MccAngle&, bool>) {
|
|
||||||
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
|
||||||
// (that is, it can interpret the third argument as a flag "false/true = only
|
|
||||||
// degrees/hour-like")
|
|
||||||
dsr_err = dsr_ang(elems[0], x, true);
|
|
||||||
} else {
|
|
||||||
dsr_err = dsr_ang(elems[0], x);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dsr_err = dsr_ang(elems[0], x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dsr_err) {
|
|
||||||
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
|
||||||
}
|
|
||||||
|
|
||||||
dsr_err = dsr_ang(elems[1], y);
|
|
||||||
|
|
||||||
if (dsr_err) {
|
|
||||||
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (pair_kind) {
|
|
||||||
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
|
||||||
value.from(MccSkyRADEC_ICRS{(double)x, (double)y});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_RADEC_OBS:
|
|
||||||
value.from(MccSkyRADEC_OBS{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
|
||||||
value.from(MccSkyRADEC_APP{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_HADEC_OBS:
|
|
||||||
value.from(MccSkyHADEC_OBS{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
|
||||||
value.from(MccSkyHADEC_APP{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_AZZD:
|
|
||||||
value.from(MccSkyAZZD{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_AZALT:
|
|
||||||
value.from(MccSkyAZALT{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_XY:
|
|
||||||
value.from(MccGenXY{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_GENERIC:
|
|
||||||
value.from(MccCoordPair{(double)x, (double)y, epoch});
|
|
||||||
break;
|
|
||||||
case MccCoordPairKind::COORDS_KIND_LONLAT:
|
|
||||||
value.from(MccGeoLONLAT{(double)x, (double)y});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else { // range
|
|
||||||
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
|
||||||
MccDeserializer<value_t> dsr;
|
|
||||||
|
|
||||||
return deserializingRange<value_t>(dsr, input, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MccDeserializerErrorCode::ERROR_OK;
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccDeserializer<MccSerializedAngleFormatPrec> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-ANGLE-FORMAT-PREC-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator ()(
|
||||||
|
traits::mcc_input_char_range auto const& input,
|
||||||
|
MccSerializedAngleFormatPrec& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
// valid format: hour_prec[<params.elem_delim>deg_prec<params.elem_delim>decimals]
|
||||||
|
|
||||||
|
std::vector<uint8_t> v;
|
||||||
|
|
||||||
|
auto err = MccDeserializer<decltype(v)>{}(input, v);
|
||||||
|
if (err) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 0) {
|
||||||
|
value.hour_prec = v[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 1) {
|
||||||
|
value.deg_prec = v[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.size() > 2) {
|
||||||
|
value.decimals = v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct MccDeserializer<MccSerializedCoordPairFormat> : MccDeserializerBase {
|
||||||
|
static constexpr std::string_view deserializerName{"MCC-COORDPAIR-FORMAT-DESERIALIZER"};
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT = mcc_serialization_params_t>
|
||||||
|
error_t operator ()(
|
||||||
|
traits::mcc_input_char_range auto const& input,
|
||||||
|
MccSerializedCoordPairFormat& value,
|
||||||
|
ParamsT const& params = mcc_serialization_params_t{})
|
||||||
|
{
|
||||||
|
value = MccSerializedCoordPairFormatStrToValue(input);
|
||||||
|
|
||||||
|
if (value != MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace mcc::impl
|
} // namespace mcc::impl
|
||||||
|
|||||||
445
mcc_deserializer.h.old
Normal file
445
mcc_deserializer.h.old
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* MOUNT CONTROL COMPONENTS LIBRARY *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
|
* IMPLEMENTATION OF DESERIALIZER CLASSES *
|
||||||
|
* *
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "mcc_concepts.h"
|
||||||
|
#include "mcc_coordinate.h"
|
||||||
|
#include "mcc_epoch.h"
|
||||||
|
#include "mcc_error.h"
|
||||||
|
|
||||||
|
namespace mcc::impl
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class MccDeserializerErrorCode : int {
|
||||||
|
ERROR_OK,
|
||||||
|
ERROR_UNDERLYING_DESERIALIZER,
|
||||||
|
ERROR_INVALID_SERIALIZED_VALUE,
|
||||||
|
ERROR_COORD_TRANSFORM
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mcc::impl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class is_error_code_enum<mcc::impl::MccDeserializerErrorCode> : public true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
|
namespace mcc::impl
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// error category
|
||||||
|
struct MccDeserializerCategory : public std::error_category {
|
||||||
|
MccDeserializerCategory() : std::error_category() {}
|
||||||
|
|
||||||
|
const char* name() const noexcept
|
||||||
|
{
|
||||||
|
return "MCC-DESERIALIZER-ERR-CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message(int ec) const
|
||||||
|
{
|
||||||
|
MccDeserializerErrorCode err = static_cast<MccDeserializerErrorCode>(ec);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case MccDeserializerErrorCode::ERROR_OK:
|
||||||
|
return "OK";
|
||||||
|
case MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER:
|
||||||
|
return "error returned by underlying deserializer";
|
||||||
|
case MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE:
|
||||||
|
return "invalid serialized value";
|
||||||
|
case MccDeserializerErrorCode::ERROR_COORD_TRANSFORM:
|
||||||
|
return "coordinates transformation error";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MccDeserializerCategory& get()
|
||||||
|
{
|
||||||
|
static const MccDeserializerCategory constInst;
|
||||||
|
return constInst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline std::error_code make_error_code(MccDeserializerErrorCode ec)
|
||||||
|
{
|
||||||
|
return std::error_code(static_cast<int>(ec), MccDeserializerCategory::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_error_c RetT>
|
||||||
|
struct mcc_deserializer_interface_t {
|
||||||
|
virtual ~mcc_deserializer_interface_t() = default;
|
||||||
|
|
||||||
|
typedef RetT error_t;
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_deserializer_interface_t> SelfT,
|
||||||
|
traits::mcc_input_char_range R,
|
||||||
|
typename ValueT,
|
||||||
|
typename... DeserParamsT>
|
||||||
|
RetT operator()(this SelfT&& self, R const& input, ValueT& value, DeserParamsT&&... params)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(input, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mcc_deserializer_interface_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_deserializer_c = std::derived_from<T, mcc_deserializer_interface_t<typename T::error_t>>;
|
||||||
|
|
||||||
|
|
||||||
|
namespace details
|
||||||
|
{
|
||||||
|
|
||||||
|
struct MccDeserializerBase : mcc_deserializer_interface_t<impl::MccError>, utils::mcc_elem_sequence_with_delim_t {
|
||||||
|
using typename mcc_deserializer_interface_t<impl::MccError>::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializerBase() = default;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MccDeserializerBase() = default;
|
||||||
|
|
||||||
|
//
|
||||||
|
// empty == true, if the 'input' is empty or if all elements consist of only spaces
|
||||||
|
//
|
||||||
|
std::vector<std::string_view> splitAggregateValue(traits::mcc_input_char_range auto const& input, bool& empty) const
|
||||||
|
{
|
||||||
|
std::vector<std::string_view> res;
|
||||||
|
|
||||||
|
if (std::ranges::size(input)) {
|
||||||
|
empty = true;
|
||||||
|
|
||||||
|
std::ranges::for_each(std::views::split(input, this->_elementDelimiter), [&res, &empty](auto const& el) {
|
||||||
|
std::back_inserter(res) = utils::trimSpaces(std::string_view{el.begin(), el.end()});
|
||||||
|
if (empty && res.back().size()) {
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VT, std::ranges::output_range<VT> R, typename... DeserParamsT>
|
||||||
|
error_t deserializingRange(mcc_deserializer_c auto& dsr,
|
||||||
|
traits::mcc_input_char_range auto const& input,
|
||||||
|
R& r,
|
||||||
|
DeserParamsT&&... params) const
|
||||||
|
{
|
||||||
|
if (std::ranges::size(input) == 0) { // ignore an empty input, just return empty range?!!
|
||||||
|
r = R{};
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto r_str = std::views::split(input, _seqDelimiter);
|
||||||
|
VT val;
|
||||||
|
|
||||||
|
auto it = r.begin();
|
||||||
|
for (auto const& el : r_str) {
|
||||||
|
auto err = dsr(el, val, std::forward<DeserParamsT>(params)...);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == r.end()) {
|
||||||
|
std::back_inserter(r) = val;
|
||||||
|
it = r.end();
|
||||||
|
} else {
|
||||||
|
*it = val;
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
|
||||||
|
|
||||||
|
/* fallback template: basic deserializer */
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
class MccDeserializer : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_arithmetic_v<VT>) {
|
||||||
|
auto v = mcc::utils::numFromStr<VT>(utils::trimSpaces(input));
|
||||||
|
if (!v.has_value()) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = v.value();
|
||||||
|
} else if constexpr (mcc::traits::mcc_output_char_range<VT>) {
|
||||||
|
VT r;
|
||||||
|
if constexpr (traits::mcc_array_c<VT>) {
|
||||||
|
size_t N =
|
||||||
|
std::ranges::size(r) <= std::ranges::size(input) ? std::ranges::size(r) : std::ranges::size(input);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
r[i] = input[i];
|
||||||
|
}
|
||||||
|
if (std::ranges::size(r) > N) {
|
||||||
|
for (size_t i = N; i < std::ranges::size(r); ++i) {
|
||||||
|
r[i] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::ranges::copy(input, std::back_inserter(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
value = r;
|
||||||
|
} else if constexpr (std::ranges::range<VT>) {
|
||||||
|
using el_t = std::ranges::range_value_t<VT>;
|
||||||
|
|
||||||
|
static_assert(std::ranges::output_range<VT, el_t>, "INVALID RANGE TYPE!!!");
|
||||||
|
|
||||||
|
// no reference or constants allowed
|
||||||
|
static_assert(std::is_reference_v<el_t> || std::is_const_v<el_t>, "INVALID RANGE ELEMENT TYPE!!!");
|
||||||
|
|
||||||
|
MccDeserializer<el_t> dsr;
|
||||||
|
return deserializingRange<el_t>(dsr, input, value);
|
||||||
|
} else if constexpr (traits::mcc_time_duration_c<VT>) {
|
||||||
|
typename VT::rep vd;
|
||||||
|
|
||||||
|
MccDeserializer<typename VT::rep> dsr;
|
||||||
|
|
||||||
|
auto err = dsr(trimSpaces(input), vd);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = VT{vd};
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNSUPPORTED VALUE TYPE!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_coord_epoch_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_coord_epoch_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_coord_epoch_c<VT>) { // scalar
|
||||||
|
bool ok = value.fromCharRange(input);
|
||||||
|
if (!ok) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
return deserializingRange(dsr, input, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(!std::is_arithmetic_v<VT> &&
|
||||||
|
(mcc_angle_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_angle_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>)))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
// if hms == true and the input sequence is a sexagesimal string then it interpretates angle as hours:mins:secs
|
||||||
|
// otherwise the input sequence is interpretated as decimal or sexagesimal degrees
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value, bool hms = false)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_angle_c<VT>) { // scalar
|
||||||
|
auto res = utils::parsAngleString(input, hms);
|
||||||
|
if (res) { // returned angle is in degrees!!!
|
||||||
|
value = res.value() * MCC_DEGRESS_TO_RADS;
|
||||||
|
} else {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
if constexpr (std::invocable<MccDeserializer<value_t>, decltype(input), VT&, bool>) {
|
||||||
|
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
||||||
|
// (that is, it can interpret the third argument as a flag "false/true = only
|
||||||
|
// degrees/hour-like")
|
||||||
|
return deserializingRange<value_t>(dsr, input, value, hms);
|
||||||
|
} else {
|
||||||
|
return deserializingRange<value_t>(dsr, input, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_skypoint_c<VT> || (std::ranges::output_range<VT, std::ranges::range_value_t<VT>> &&
|
||||||
|
mcc_skypoint_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccDeserializer<VT> : public details::MccDeserializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using typename details::MccDeserializerBase::error_t;
|
||||||
|
|
||||||
|
virtual ~MccDeserializer() = default;
|
||||||
|
|
||||||
|
error_t operator()(traits::mcc_input_char_range auto const& input, VT& value)
|
||||||
|
{
|
||||||
|
if constexpr (mcc_skypoint_c<VT>) { // scalar: X[elem-delim]Y{[elem-delim]TIME-POINT[elem-delim]PAIR-KIND}
|
||||||
|
bool empty; // exactly 2 or >3 elements
|
||||||
|
auto elems = splitAggregateValue(input, empty);
|
||||||
|
|
||||||
|
if (empty || (elems.size() < 2) || (elems.size() == 3)) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MccCoordPairKind pair_kind{MccCoordPairKind::COORDS_KIND_RADEC_ICRS};
|
||||||
|
MccCelestialCoordEpoch epoch; // J2000.0
|
||||||
|
|
||||||
|
MccAngle x, y;
|
||||||
|
MccDeserializer<MccAngle> dsr_ang;
|
||||||
|
|
||||||
|
typename MccDeserializer<MccAngle>::error_t dsr_err;
|
||||||
|
|
||||||
|
if (elems.size() >= 4) { // X, Y, TIME-POINT, PAIR-KIND
|
||||||
|
// first, get pair-kind
|
||||||
|
pair_kind = MccCoordStrToPairKind(elems[3]);
|
||||||
|
if (pair_kind == MccCoordPairKind::COORDS_KIND_UNKNOWN) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// epoch
|
||||||
|
bool ok = epoch.fromCharRange(elems[2]);
|
||||||
|
if (!ok) {
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elems.size() >= 2) { // if == 2: just X and Y (if so it is interpretated as RADEC_ICRS)
|
||||||
|
if (MccCoordinatePairToSxgmRep(pair_kind) == MccCoordinatePairRep::MCC_COORDPAIR_REP_SXGM_HOURDEG) {
|
||||||
|
// if input X-angle is in sexagesimal from then interpretate it in hours::mins::secs format
|
||||||
|
if constexpr (std::invocable<MccDeserializer<MccAngle>, decltype(elems[0]), MccAngle&, bool>) {
|
||||||
|
// it is assumed here, the angle deserializer has the same behavior as the one implemented above
|
||||||
|
// (that is, it can interpret the third argument as a flag "false/true = only
|
||||||
|
// degrees/hour-like")
|
||||||
|
dsr_err = dsr_ang(elems[0], x, true);
|
||||||
|
} else {
|
||||||
|
dsr_err = dsr_ang(elems[0], x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dsr_err = dsr_ang(elems[0], x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dsr_err) {
|
||||||
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
dsr_err = dsr_ang(elems[1], y);
|
||||||
|
|
||||||
|
if (dsr_err) {
|
||||||
|
return mcc_deduced_err(dsr_err, MccDeserializerErrorCode::ERROR_UNDERLYING_DESERIALIZER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (pair_kind) {
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||||
|
value.from(MccSkyRADEC_ICRS{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_OBS:
|
||||||
|
value.from(MccSkyRADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||||
|
value.from(MccSkyRADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_OBS:
|
||||||
|
value.from(MccSkyHADEC_OBS{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||||
|
value.from(MccSkyHADEC_APP{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZZD:
|
||||||
|
value.from(MccSkyAZZD{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZALT:
|
||||||
|
value.from(MccSkyAZALT{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_XY:
|
||||||
|
value.from(MccGenXY{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_GENERIC:
|
||||||
|
value.from(MccCoordPair{(double)x, (double)y, epoch});
|
||||||
|
break;
|
||||||
|
case MccCoordPairKind::COORDS_KIND_LONLAT:
|
||||||
|
value.from(MccGeoLONLAT{(double)x, (double)y});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return MccDeserializerErrorCode::ERROR_INVALID_SERIALIZED_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // range
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccDeserializer<value_t> dsr;
|
||||||
|
|
||||||
|
return deserializingRange<value_t>(dsr, input, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccDeserializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mcc::impl
|
||||||
1262
mcc_netserver.h
Normal file
1262
mcc_netserver.h
Normal file
File diff suppressed because it is too large
Load Diff
512
mcc_netserver_endpoint.h
Normal file
512
mcc_netserver_endpoint.h
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* NETWORK SERVER ENDPOINT CLASS IMPLEMENTATION */
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <charconv>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <ranges>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
|
namespace mcc::network
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
|
||||||
|
static constexpr bool mcc_char_range_compare(const traits::mcc_char_view auto& what,
|
||||||
|
const traits::mcc_char_view auto& where,
|
||||||
|
bool case_insensitive = false)
|
||||||
|
{
|
||||||
|
if (std::ranges::size(what) == std::ranges::size(where)) {
|
||||||
|
if (case_insensitive) {
|
||||||
|
auto f = std::ranges::search(where,
|
||||||
|
std::views::transform(what, [](const char& ch) { return std::tolower(ch); }));
|
||||||
|
return !f.empty();
|
||||||
|
} else {
|
||||||
|
auto f = std::ranges::search(where, what);
|
||||||
|
return !f.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Very simple various protocols endpoint parser and holder class
|
||||||
|
*
|
||||||
|
* endpoint: proto_mark://host_name:port_num/path
|
||||||
|
* where "path" is optional for all non-local protocol kinds;
|
||||||
|
*
|
||||||
|
* for local kind of protocols the endpoint must be given as:
|
||||||
|
* local://stream/PATH
|
||||||
|
* local://seqpacket/PATH
|
||||||
|
* local://serial/PATH
|
||||||
|
* where 'stream' and 'seqpacket' "host_name"-field marks the
|
||||||
|
* stream-type and seqpacket-type UNIX domain sockets protocols;
|
||||||
|
* 'serial' marks a serial (RS232/485) protocol.
|
||||||
|
* here, possible "port_num" field is allowed but ignored.
|
||||||
|
*
|
||||||
|
* NOTE: "proto_mark" and "host_name" (for local kind) fields are parsed in case-insensitive manner!
|
||||||
|
*
|
||||||
|
* EXAMPLES: tcp://192.168.70.130:3131
|
||||||
|
* local://serial/dev/ttyS1
|
||||||
|
* local://seqpacket/tmp/BM70_SERVER_SOCK
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class MccNetServerEndpoint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr std::string_view protoHostDelim = "://";
|
||||||
|
static constexpr std::string_view hostPortDelim = ":";
|
||||||
|
static constexpr std::string_view portPathDelim = "/";
|
||||||
|
|
||||||
|
enum proto_id_t : uint8_t {
|
||||||
|
PROTO_ID_LOCAL,
|
||||||
|
PROTO_ID_SEQLOCAL,
|
||||||
|
PROTO_ID_SERLOCAL,
|
||||||
|
PROTO_ID_TCP,
|
||||||
|
PROTO_ID_TLS,
|
||||||
|
PROTO_ID_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::string_view protoMarkLocal{"local"}; // UNIX domain
|
||||||
|
static constexpr std::string_view protoMarkTCP{"tcp"}; // TCP
|
||||||
|
static constexpr std::string_view protoMarkTLS{"tls"}; // TLS
|
||||||
|
|
||||||
|
static constexpr std::array validProtoMarks{protoMarkLocal, protoMarkTCP, protoMarkTLS};
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view localProtoTypeStream{"stream"}; // UNIX domain stream
|
||||||
|
static constexpr std::string_view localProtoTypeSeqpacket{"seqpacket"}; // UNIX domain seqpacket
|
||||||
|
static constexpr std::string_view localProtoTypeSerial{"serial"}; // serial (RS232/485)
|
||||||
|
|
||||||
|
static constexpr std::array validLocalProtoTypes{localProtoTypeStream, localProtoTypeSeqpacket,
|
||||||
|
localProtoTypeSerial};
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
MccNetServerEndpoint(const R& ept)
|
||||||
|
{
|
||||||
|
fromRange(ept);
|
||||||
|
}
|
||||||
|
|
||||||
|
MccNetServerEndpoint(const MccNetServerEndpoint& other)
|
||||||
|
{
|
||||||
|
copyInst(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
MccNetServerEndpoint(MccNetServerEndpoint&& other)
|
||||||
|
{
|
||||||
|
moveInst(std::move(other));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~MccNetServerEndpoint() = default;
|
||||||
|
|
||||||
|
|
||||||
|
MccNetServerEndpoint& operator=(const MccNetServerEndpoint& other)
|
||||||
|
{
|
||||||
|
copyInst(other);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MccNetServerEndpoint& operator=(MccNetServerEndpoint&& other)
|
||||||
|
{
|
||||||
|
moveInst(std::move(other));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
requires std::ranges::contiguous_range<R>
|
||||||
|
bool fromRange(const R& ept)
|
||||||
|
{
|
||||||
|
_isValid = false;
|
||||||
|
|
||||||
|
// at least 'ws://a' (proto, proto-host delimiter and at least a single character of hostname)
|
||||||
|
if (std::ranges::size(ept) < 6) {
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::is_array_v<std::remove_cvref_t<R>>) {
|
||||||
|
_endpoint = ept;
|
||||||
|
} else {
|
||||||
|
_endpoint.clear();
|
||||||
|
std::ranges::copy(ept, std::back_inserter(_endpoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto found = std::ranges::search(_endpoint, protoHostDelim);
|
||||||
|
if (found.empty()) {
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t idx;
|
||||||
|
if ((idx = checkProtoMark(std::string_view{_endpoint.begin(), found.begin()})) < 0) {
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
_proto = validProtoMarks[idx];
|
||||||
|
|
||||||
|
_host = std::string_view{found.end(), _endpoint.end()};
|
||||||
|
|
||||||
|
auto f1 = std::ranges::search(_host, portPathDelim);
|
||||||
|
// std::string_view port_sv;
|
||||||
|
if (f1.empty() && isLocal()) { // no path, but it is mandatory for 'local'!
|
||||||
|
return _isValid;
|
||||||
|
} else {
|
||||||
|
_host = std::string_view(_host.begin(), f1.begin());
|
||||||
|
|
||||||
|
_path = std::string_view(f1.end(), &*_endpoint.end());
|
||||||
|
|
||||||
|
f1 = std::ranges::search(_host, hostPortDelim);
|
||||||
|
if (f1.empty() && !isLocal()) { // no port, but it is mandatory for non-local!
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
_portView = std::string_view(f1.end(), _host.end());
|
||||||
|
if (_portView.size()) {
|
||||||
|
_host = std::string_view(_host.begin(), f1.begin());
|
||||||
|
|
||||||
|
if (!isLocal()) {
|
||||||
|
// convert port string to int
|
||||||
|
auto end_ptr = _portView.data() + _portView.size();
|
||||||
|
|
||||||
|
auto [ptr, ec] = std::from_chars(_portView.data(), end_ptr, _port);
|
||||||
|
if (ec != std::errc() || ptr != end_ptr) {
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
} else { // ignore for local
|
||||||
|
_port = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_port = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocal()) { // check for special values
|
||||||
|
idx = 0;
|
||||||
|
if (std::ranges::any_of(validLocalProtoTypes, [&idx, this](const auto& el) {
|
||||||
|
bool ok = utils::mcc_char_range_compare(_host, el, true);
|
||||||
|
if (!ok) {
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
})) {
|
||||||
|
_host = validLocalProtoTypes[idx];
|
||||||
|
} else {
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_isValid = true;
|
||||||
|
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{
|
||||||
|
return _isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto endpoint() const
|
||||||
|
{
|
||||||
|
return _endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R proto() const
|
||||||
|
{
|
||||||
|
return part<R>(PROTO_PART);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view proto() const
|
||||||
|
{
|
||||||
|
return proto<std::string_view>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R host() const
|
||||||
|
{
|
||||||
|
return part<R>(HOST_PART);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view host() const
|
||||||
|
{
|
||||||
|
return host<std::string_view>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int port() const
|
||||||
|
{
|
||||||
|
return _port;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R portView() const
|
||||||
|
{
|
||||||
|
return part<R>(PORT_PART);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view portView() const
|
||||||
|
{
|
||||||
|
return portView<std::string_view>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_output_char_range R, traits::mcc_input_char_range RR = std::string_view>
|
||||||
|
R path(RR&& root_path) const
|
||||||
|
{
|
||||||
|
if (_path.empty()) {
|
||||||
|
if constexpr (traits::mcc_output_char_range<R>) {
|
||||||
|
R res;
|
||||||
|
std::ranges::copy(std::forward<RR>(root_path), std::back_inserter(res));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} else { // can't add root path!!!
|
||||||
|
return part<R>(PATH_PART);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto N = std::ranges::distance(root_path.begin(), root_path.end());
|
||||||
|
|
||||||
|
if (N) {
|
||||||
|
R res;
|
||||||
|
std::filesystem::path pt(root_path.begin(), root_path.end());
|
||||||
|
|
||||||
|
if (isLocal() && _path[0] == '\0') {
|
||||||
|
std::ranges::copy(std::string_view(" "), std::back_inserter(res));
|
||||||
|
pt /= _path.substr(1);
|
||||||
|
std::ranges::copy(pt.string(), std::back_inserter(res));
|
||||||
|
*res.begin() = '\0';
|
||||||
|
} else {
|
||||||
|
pt /= _path;
|
||||||
|
std::ranges::copy(pt.string(), std::back_inserter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return part<R>(PATH_PART);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range RR = std::string_view>
|
||||||
|
std::string path(RR&& root_path) const
|
||||||
|
{
|
||||||
|
return path<std::string, RR>(std::forward<RR>(root_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R path() const
|
||||||
|
{
|
||||||
|
return part<R>(PATH_PART);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view path() const
|
||||||
|
{
|
||||||
|
return path<std::string_view>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isLocal() const
|
||||||
|
{
|
||||||
|
return proto() == protoMarkLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLocalStream() const
|
||||||
|
{
|
||||||
|
return host() == localProtoTypeStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLocalSerial() const
|
||||||
|
{
|
||||||
|
return host() == localProtoTypeSerial;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isLocalSeqpacket() const
|
||||||
|
{
|
||||||
|
return host() == localProtoTypeSeqpacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool isTCP() const
|
||||||
|
{
|
||||||
|
return proto() == protoMarkTCP;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isTLS() const
|
||||||
|
{
|
||||||
|
return proto() == protoMarkTLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// add '\0' char (or replace special-meaning char/char-sequence) to construct UNIX abstract namespace
|
||||||
|
// endpoint path
|
||||||
|
template <typename T = std::nullptr_t>
|
||||||
|
MccNetServerEndpoint& makeAbstract(const T& mark = nullptr)
|
||||||
|
requires(traits::mcc_input_char_range<T> || std::same_as<std::remove_cv_t<T>, char> ||
|
||||||
|
std::is_null_pointer_v<std::remove_cv_t<T>>)
|
||||||
|
{
|
||||||
|
if (!(isLocalStream() || isLocalSeqpacket())) { // only local proto is valid!
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::is_null_pointer_v<T>) { // just insert '\0'
|
||||||
|
auto it = _endpoint.insert(std::string::const_iterator(_path.begin()), '\0');
|
||||||
|
_path = std::string_view(it, _endpoint.end());
|
||||||
|
} else if constexpr (std::same_as<std::remove_cv_t<T>, char>) { // replace a character (mark)
|
||||||
|
auto pos = std::distance(_endpoint.cbegin(), std::string::const_iterator(_path.begin()));
|
||||||
|
if (_endpoint[pos] == mark) {
|
||||||
|
_endpoint[pos] = '\0';
|
||||||
|
}
|
||||||
|
} else { // replace a character range (mark)
|
||||||
|
if (std::ranges::equal(_path | std::views::take(std::ranges::size(mark), mark))) {
|
||||||
|
auto pos = std::distance(_endpoint.cbegin(), std::string::const_iterator(_path.begin()));
|
||||||
|
_endpoint.replace(pos, std::ranges::size(mark), 1, '\0');
|
||||||
|
_path = std::string_view(_endpoint.begin() + pos, _endpoint.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string _endpoint;
|
||||||
|
std::string_view _proto, _host, _path, _portView;
|
||||||
|
int _port;
|
||||||
|
bool _isValid;
|
||||||
|
|
||||||
|
|
||||||
|
virtual ssize_t checkProtoMark(std::string_view proto_mark)
|
||||||
|
{
|
||||||
|
ssize_t idx = 0;
|
||||||
|
|
||||||
|
// case-insensitive look-up
|
||||||
|
bool found = std::ranges::any_of(MccNetServerEndpoint::validProtoMarks, [&idx, &proto_mark](const auto& el) {
|
||||||
|
bool ok = utils::mcc_char_range_compare(proto_mark, el, true);
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
++idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
});
|
||||||
|
|
||||||
|
return found ? idx : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EndpointPart { PROTO_PART, HOST_PART, PATH_PART, PORT_PART };
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R part(EndpointPart what) const
|
||||||
|
{
|
||||||
|
R res;
|
||||||
|
|
||||||
|
// if (!_isValid) {
|
||||||
|
// return res;
|
||||||
|
// }
|
||||||
|
|
||||||
|
auto part = _proto;
|
||||||
|
|
||||||
|
switch (what) {
|
||||||
|
case PROTO_PART:
|
||||||
|
part = _proto;
|
||||||
|
break;
|
||||||
|
case HOST_PART:
|
||||||
|
part = _host;
|
||||||
|
break;
|
||||||
|
case PATH_PART:
|
||||||
|
part = _path;
|
||||||
|
break;
|
||||||
|
case PORT_PART:
|
||||||
|
part = _portView;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::ranges::view<R>) {
|
||||||
|
return {part.begin(), part.end()};
|
||||||
|
} else {
|
||||||
|
std::ranges::copy(part, std::back_inserter(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyInst(const MccNetServerEndpoint& other)
|
||||||
|
{
|
||||||
|
if (&other != this) {
|
||||||
|
if (other._isValid) {
|
||||||
|
_isValid = other._isValid;
|
||||||
|
_endpoint = other._endpoint;
|
||||||
|
_proto = other._proto;
|
||||||
|
|
||||||
|
std::iterator_traits<const char*>::difference_type idx;
|
||||||
|
if (other.isLocal()) { // for 'local' host is one of static class constants
|
||||||
|
_host = other._host;
|
||||||
|
} else {
|
||||||
|
idx = std::distance(other._endpoint.c_str(), other._host.data());
|
||||||
|
_host = std::string_view(_endpoint.c_str() + idx, other._host.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = std::distance(other._endpoint.c_str(), other._path.data());
|
||||||
|
_path = std::string_view(_endpoint.c_str() + idx, other._path.size());
|
||||||
|
|
||||||
|
idx = std::distance(other._endpoint.c_str(), other._portView.data());
|
||||||
|
_portView = std::string_view(_endpoint.c_str() + idx, other._portView.size());
|
||||||
|
|
||||||
|
_port = other._port;
|
||||||
|
} else {
|
||||||
|
_isValid = false;
|
||||||
|
_endpoint = std::string();
|
||||||
|
_proto = std::string_view();
|
||||||
|
_host = std::string_view();
|
||||||
|
_path = std::string_view();
|
||||||
|
_portView = std::string_view();
|
||||||
|
_port = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void moveInst(MccNetServerEndpoint&& other)
|
||||||
|
{
|
||||||
|
if (&other != this) {
|
||||||
|
if (other._isValid) {
|
||||||
|
_isValid = std::move(other._isValid);
|
||||||
|
_endpoint = std::move(other._endpoint);
|
||||||
|
_proto = other._proto;
|
||||||
|
_host = std::move(other._host);
|
||||||
|
_path = std::move(other._path);
|
||||||
|
_port = std::move(other._port);
|
||||||
|
_portView = std::move(other._portView);
|
||||||
|
} else {
|
||||||
|
_isValid = false;
|
||||||
|
_endpoint = std::string();
|
||||||
|
_proto = std::string_view();
|
||||||
|
_host = std::string_view();
|
||||||
|
_path = std::string_view();
|
||||||
|
_portView = std::string_view();
|
||||||
|
_port = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mcc::network
|
||||||
601
mcc_netserver_proto.h
Normal file
601
mcc_netserver_proto.h
Normal file
@@ -0,0 +1,601 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* MOUNT CONTROL COMPONENTS LIBRARY */
|
||||||
|
|
||||||
|
/* BASIC NETWORK PROTOCOL DEFINITIONS */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
|
||||||
|
#include "mcc_deserializer.h"
|
||||||
|
#include "mcc_serializer.h"
|
||||||
|
#include "mcc_utils.h"
|
||||||
|
|
||||||
|
namespace mcc::network
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The network protocol is the ASCII-based, case-sensitive textual protocol.
|
||||||
|
* The "client-server" communication is performed through messages.
|
||||||
|
* The message is a minimal unit of this communication.
|
||||||
|
* The model of network communication is a simple "client-server" one, i.e.,
|
||||||
|
* client asks - server responds.
|
||||||
|
*
|
||||||
|
* network communication message format:
|
||||||
|
* <keyword>[[<key-param-delim>]<param1>[<param-param-delim>][<param2>]...]<stop-seq>
|
||||||
|
*
|
||||||
|
* where
|
||||||
|
* <keyword> - mandatory message keyword (one or more ASCII symbols)
|
||||||
|
* <key-param-delim>
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* "TARGET 12:23:45.56 00:32:21.978\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* low-level network message format definitions */
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_STOP_SEQ = "\n";
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_SEQ = " ";
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ = ";";
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ = ",";
|
||||||
|
|
||||||
|
|
||||||
|
/* server special keywords */
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR = "ACK"; // ACK
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR = "ERROR"; // mount operational error
|
||||||
|
// pre-defined errors
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVKEY_STR = "INVKEY"; // invalid keyword
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVPAR_STR = "INVPAR"; // invalid parameter
|
||||||
|
|
||||||
|
|
||||||
|
/* server control keywords */
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_RESTART_SERVER_STR = "RESTART"; // restart server
|
||||||
|
|
||||||
|
|
||||||
|
/* BELOW IS ONE OF THE PROTOCOL OPTIONS CORRESPONDING MCC_GENERIC_MOUNT_C CONCEPT */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* keywords */
|
||||||
|
|
||||||
|
// NOTE: THE COORDINATES AND TIME-RELATED QUANTITIES CAN BE EXPRESSED IN THE TWO FORMATS:
|
||||||
|
// 1) fixed-point real number, e.g. 123.43987537359 or -0.09775
|
||||||
|
// 2) sexagesimal number, e.g. 10:43:43.12 or -123:54:12.435
|
||||||
|
//
|
||||||
|
// IN THE FIRST CASE ALL NUMBERS MUST BE INTERPRETATED AS DEGREES,
|
||||||
|
// IN THE SECOND CASE NUMBERS MUST BE INTERPRETATED ACCORDING TO ITS TYPE:
|
||||||
|
// ALL TIME-RELATED QUANTITIES AND RA/HA COORDINATES MUST BE EXPRESSED
|
||||||
|
// IN FORMAT 'HOURS:MINUTES:SECONDS', WHILE DEC/ALT/AZ/ZD COORDINATES MUST
|
||||||
|
// BE EXPRESSED AS '+/-DEGREES:ARCMINUTES:ARCSECONDS'
|
||||||
|
//
|
||||||
|
// USER-ENTERED (FROM NETWORK CLIENTS) COORDINATE PAIR CAN BE PROVIDED IN A MIXED FORM, I.E.,
|
||||||
|
// 12.34436658678 10:32:11.432 or
|
||||||
|
// 10:32:11.432 12.34436658678
|
||||||
|
//
|
||||||
|
// SERVER-RESPONDED COORDINATES ARE ALWAYS IN THE SAME FORMAT, SEXAGESIMAL OR FIXED-POINT
|
||||||
|
//
|
||||||
|
|
||||||
|
// format of output coordinates:
|
||||||
|
// "COORDFMT FMT-type\n"
|
||||||
|
// e.g.:
|
||||||
|
// "COORDFMT SGM\n"
|
||||||
|
// "COORDFMT\n"
|
||||||
|
//
|
||||||
|
// server must return "ACK" or "ERROR INVPAR" in the case of 'set'-operation and
|
||||||
|
// "ACK COORDFMT FMT-type" in the case of 'get'-operation
|
||||||
|
// e.g.:
|
||||||
|
// "COORDFMT FIX\n" -> "ACK\n"
|
||||||
|
// "COORDFMT SXT\n" -> "ERROR INVPAR\n" (invalid parameter of format type)
|
||||||
|
// "COORDFMT\n" -> "ACK COORDFMT FIX\n"
|
||||||
|
//
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_STR = "COORDFMT";
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR = "SGM"; // sexagesimal
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FIX"; // fixed point
|
||||||
|
|
||||||
|
|
||||||
|
// precision (number of decimal places) of returned coordinates:
|
||||||
|
// "COORDPREC seconds-prec arcseconds-prec\n"
|
||||||
|
// seconds-prec - precision of hour-based coordinates (RA and HA) or time-related quantities
|
||||||
|
// arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT)
|
||||||
|
// precision must be given as non-negative integer number
|
||||||
|
// e.g.
|
||||||
|
// "COORDPREC 2,1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
|
||||||
|
//
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
|
||||||
|
|
||||||
|
|
||||||
|
// set/get target coordinates
|
||||||
|
// "TARGET X-coord Y-coord XY-kind\n", if 'XY-kind' is omitted then one should assume RADEC_ICRS
|
||||||
|
// e.g.:
|
||||||
|
// "TARGET 12.7683487 10:23:09.75 AZZD\n"
|
||||||
|
// "TARGET HADEC\n"
|
||||||
|
// "TARGET\n"
|
||||||
|
//
|
||||||
|
// server must return "ACK" or "ERROR INVPAR" in the case of 'set'-operation and
|
||||||
|
// "ACK TARGET X-coord Y-coord XY-kind" in the case of 'get'-operation
|
||||||
|
// e.g.:
|
||||||
|
// "TARGET 12.7683487 10:23:09.75 AZZD\n" -> "ACK\n"
|
||||||
|
// "TARGET 12.7683487 10:23:09.75 AZZE\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
|
||||||
|
//
|
||||||
|
// "TARGET HADEC\n" -> "ACK TARGET 20:21:56.32 -01:32:34.2 HADEC\n"
|
||||||
|
// "TARGET\n" -> "ACK TARGET 20:21:56.32 -01:32:34.2 RADEC_ICRS\n"
|
||||||
|
//
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TARGET_STR = "TARGET";
|
||||||
|
|
||||||
|
// get mount coordinates:
|
||||||
|
// "MOUNT coord-kind", if 'coord-kind' is omitted then coordinates are according to mount type,
|
||||||
|
// i.e., HADEC for equathorial-type mount and AZZD for alt-azimuthal one
|
||||||
|
// e.g.:
|
||||||
|
// "MOUNT RADEC\n" (get current apparent RA and DEC mount coordinates)
|
||||||
|
//
|
||||||
|
// server must return "ACK MOUNT X-coord Y-coord XY-kind" or "ERROR INVPAR"
|
||||||
|
// e.g.
|
||||||
|
// "MOUNT AZALT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZALT\n"
|
||||||
|
// "MOUNT AZAL\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
|
||||||
|
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZZD\n" for alt-azimuthal mount
|
||||||
|
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 HADEC\n" for equathorial mount
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_MOUNT_STR = "MOUNT";
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TELEMETRY_STR = "TELEMETRY";
|
||||||
|
|
||||||
|
// init mount
|
||||||
|
// "INIT\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_INIT_STR = "INIT";
|
||||||
|
|
||||||
|
// stop any movements
|
||||||
|
// "STOP\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_STOP_STR = "STOP";
|
||||||
|
|
||||||
|
// slew mount and track target:
|
||||||
|
// "SLEW\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SLEW_STR = "SLEW";
|
||||||
|
|
||||||
|
// slew mount and stop:
|
||||||
|
// "MOVE\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_MOVE_STR = "MOVE";
|
||||||
|
|
||||||
|
// track target
|
||||||
|
// "TRACK\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TRACK_STR = "TRACK";
|
||||||
|
|
||||||
|
// get mount status
|
||||||
|
// "STATUS\n"
|
||||||
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_STATUS_STR = "STATUS";
|
||||||
|
|
||||||
|
// valid keywords
|
||||||
|
static constexpr std::array MCC_COMMPROTO_VALID_KEYS = {
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, MCC_COMMPROTO_KEYWORD_COORDFMT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_COORDPREC_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_TELEMETRY_STR, MCC_COMMPROTO_KEYWORD_INIT_STR, MCC_COMMPROTO_KEYWORD_STOP_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_SLEW_STR, MCC_COMMPROTO_KEYWORD_MOVE_STR, MCC_COMMPROTO_KEYWORD_TRACK_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_STATUS_STR};
|
||||||
|
|
||||||
|
|
||||||
|
// hashes of valid keywords
|
||||||
|
static constexpr std::array MCC_COMMPROTO_VALID_KEYS_HASH = []<size_t... Is>(std::index_sequence<Is...>) {
|
||||||
|
return std::array{mcc::utils::FNV1aHash(MCC_COMMPROTO_VALID_KEYS[Is])...};
|
||||||
|
}(std::make_index_sequence<MCC_COMMPROTO_VALID_KEYS.size()>());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_netmsg_valid_keys_c = requires(T t) {
|
||||||
|
// std::array of valid message keywords
|
||||||
|
[]<size_t N>(std::array<std::string_view, N>) {
|
||||||
|
// to ensure T::NETMSG_VALID_KEYWORDS can be used as compile-time constant
|
||||||
|
static constexpr auto v0 = T::NETMSG_VALID_KEYWORDS[0];
|
||||||
|
return v0;
|
||||||
|
}(T::NETMSG_VALID_KEYWORDS);
|
||||||
|
|
||||||
|
// std::array of valid message keywords hashes
|
||||||
|
[]<size_t N>(std::array<size_t, N>) {
|
||||||
|
// to ensure T::NETMSG_VALID_KEYWORD_HASHES can be used as compile-time constant
|
||||||
|
static constexpr auto v0 = T::NETMSG_VALID_KEYWORD_HASHES[0];
|
||||||
|
return v0;
|
||||||
|
}(T::NETMSG_VALID_KEYWORD_HASHES);
|
||||||
|
|
||||||
|
requires T::NETMSG_VALID_KEYWORDS.size() == T::NETMSG_VALID_KEYWORD_HASHES.size();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct MccNetMessageValidKeywords {
|
||||||
|
static constexpr std::array NETMSG_VALID_KEYWORDS = {
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_COORDFMT_STR, MCC_COMMPROTO_KEYWORD_COORDPREC_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_TARGET_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_TELEMETRY_STR, MCC_COMMPROTO_KEYWORD_INIT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_STOP_STR, MCC_COMMPROTO_KEYWORD_SLEW_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_MOVE_STR, MCC_COMMPROTO_KEYWORD_TRACK_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_STATUS_STR};
|
||||||
|
|
||||||
|
|
||||||
|
// hashes of valid keywords
|
||||||
|
static constexpr std::array NETMSG_VALID_KEYWORD_HASHES = []<size_t... Is>(std::index_sequence<Is...>) {
|
||||||
|
return std::array{mcc::utils::FNV1aHash(NETMSG_VALID_KEYWORDS[Is])...};
|
||||||
|
}(std::make_index_sequence<NETMSG_VALID_KEYWORDS.size()>());
|
||||||
|
|
||||||
|
constexpr static const size_t* isKeywordValid(std::string_view key)
|
||||||
|
{
|
||||||
|
const auto hash = mcc::utils::FNV1aHash(key);
|
||||||
|
|
||||||
|
for (auto const& h : NETMSG_VALID_KEYWORD_HASHES) {
|
||||||
|
if (h == hash) {
|
||||||
|
return &h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(mcc_netmsg_valid_keys_c<MccNetMessageValidKeywords>, "");
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_netmessage_c = requires(T t) { T(); };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc::traits::mcc_char_range BYTEREPR_T = std::string_view,
|
||||||
|
mcc_netmsg_valid_keys_c BASE_T = MccNetMessageValidKeywords>
|
||||||
|
class MccNetMessage
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// just a wrapper class to hold MccSerializer<T> specializations
|
||||||
|
struct DefaultSerializer {
|
||||||
|
template <traits::mcc_output_char_range OR, typename T>
|
||||||
|
auto operator()(OR& bytes, const T& value, mcc_serialization_params_c auto const& pars) const
|
||||||
|
{
|
||||||
|
return impl::MccSerializer<T>{}(bytes, value, pars);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef BASE_T valid_keys_t;
|
||||||
|
typedef BYTEREPR_T byte_repr_t;
|
||||||
|
|
||||||
|
enum MccNetMessageError { ERROR_OK, ERROR_EMPTY_MESSAGE, ERROR_INVALID_KEYWORD, ERROR_EMPTY_KEYWORD };
|
||||||
|
|
||||||
|
MccNetMessage() = default;
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range KT, typename... PTs>
|
||||||
|
MccNetMessage(KT&& key, PTs&&... params)
|
||||||
|
requires traits::mcc_output_char_range<BYTEREPR_T>
|
||||||
|
{
|
||||||
|
construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
constexpr MccNetMessage(const R& msg)
|
||||||
|
requires traits::mcc_input_char_range<BYTEREPR_T>
|
||||||
|
{
|
||||||
|
fromCharRange(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// constexpr MccNetMessage(const BYTEREPR_T& msg)
|
||||||
|
// requires traits::mcc_input_char_range<BYTEREPR_T>
|
||||||
|
// {
|
||||||
|
// fromCharRange(msg);
|
||||||
|
// }
|
||||||
|
|
||||||
|
virtual ~MccNetMessage() = default;
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range KT>
|
||||||
|
constexpr bool withKey(const KT& key) const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_pointer_v<std::decay_t<KT>>) {
|
||||||
|
return withKey(std::string_view{key});
|
||||||
|
}
|
||||||
|
|
||||||
|
return mcc::utils::FNV1aHash(key) == _keywordHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R keyword() const
|
||||||
|
{
|
||||||
|
if constexpr (traits::mcc_char_view<R>) {
|
||||||
|
return R{_keyword.begin(), _keyword.end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(_keyword, std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view keyword() const
|
||||||
|
{
|
||||||
|
return _keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t paramSize() const
|
||||||
|
{
|
||||||
|
return _params.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::ranges::range R>
|
||||||
|
R params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max()) const
|
||||||
|
requires(traits::mcc_view_or_output_char_range<R> || traits::mcc_range_of_char_range<R>)
|
||||||
|
{
|
||||||
|
if (start_idx >= _params.size()) {
|
||||||
|
return R{};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto stop_idx = start_idx + Nelemes - 1;
|
||||||
|
if (stop_idx >= _params.size()) {
|
||||||
|
stop_idx = _params.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (traits::mcc_range_of_char_range<R>) { // returm parameters as array
|
||||||
|
using el_t = std::ranges::range_value_t<R>;
|
||||||
|
|
||||||
|
R r;
|
||||||
|
if constexpr (traits::mcc_char_view<el_t> || traits::mcc_output_char_range<el_t>) {
|
||||||
|
for (size_t i = start_idx; i <= stop_idx; ++i) {
|
||||||
|
auto& el = _params[i];
|
||||||
|
std::back_inserter(r) = el_t{el.begin(), el.end()};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNSUPPORTED RANGE TYPE!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
if constexpr (traits::mcc_char_view<R>) { // return joined parameters as a single char-range
|
||||||
|
return R{_params[start_idx].begin(), _params[stop_idx].end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(std::string_view{_params[start_idx].begin(), _params[stop_idx].end()},
|
||||||
|
std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view params(size_t start_idx = 0, size_t Nelemes = std::numeric_limits<size_t>::max()) const
|
||||||
|
{
|
||||||
|
return params<std::string_view>(start_idx, Nelemes);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R param(size_t idx) const
|
||||||
|
{
|
||||||
|
if (idx >= _params.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (traits::mcc_char_view<R>) {
|
||||||
|
return R{_params[idx].begin(), _params[idx].end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(_params[idx], std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view param(size_t idx) const
|
||||||
|
{
|
||||||
|
if (idx >= _params.size()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return _params[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, typename DeserFuncT>
|
||||||
|
std::expected<T, std::error_code> paramValue(size_t idx, DeserFuncT&& deser_func) const
|
||||||
|
{
|
||||||
|
static_assert(std::invocable<DeserFuncT, typename decltype(_params)::value_type const&, T&,
|
||||||
|
impl::mcc_serialization_params_t const&>,
|
||||||
|
"INVALID DESERIALIZATION FUNCTION!");
|
||||||
|
static_assert(std::same_as<std::invoke_result_t<DeserFuncT, typename decltype(_params)::value_type const&, T&,
|
||||||
|
impl::mcc_serialization_params_t const&>,
|
||||||
|
std::error_code>,
|
||||||
|
"INVALID DESERIALIZATION FUNCTION!");
|
||||||
|
|
||||||
|
if (idx >= _params.size()) {
|
||||||
|
return std::unexpected{std::make_error_code(std::errc::value_too_large)};
|
||||||
|
}
|
||||||
|
|
||||||
|
T val;
|
||||||
|
|
||||||
|
auto ec = std::forward<DeserFuncT>(deser_func)(_params[idx], val, _serializationParams);
|
||||||
|
if (ec) {
|
||||||
|
return std::unexpected(ec);
|
||||||
|
} else {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::expected<T, std::error_code> paramValue(size_t idx) const
|
||||||
|
{
|
||||||
|
return paramValue<T>(
|
||||||
|
idx, impl::MccDeserializer<T>{}); // use one of specialization of MccDeserializer templated class
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <traits::mcc_view_or_output_char_range R>
|
||||||
|
R byteRepr() const
|
||||||
|
{
|
||||||
|
if constexpr (traits::mcc_char_view<R>) {
|
||||||
|
return R{_msgBuffer.begin(), _msgBuffer.end()};
|
||||||
|
} else {
|
||||||
|
R r;
|
||||||
|
std::ranges::copy(_msgBuffer, std::back_inserter(r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view byteRepr() const
|
||||||
|
{
|
||||||
|
return byteRepr<std::string_view>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range KT, typename... PTs>
|
||||||
|
std::error_code construct(KT&& key, PTs&&... params)
|
||||||
|
requires traits::mcc_output_char_range<BYTEREPR_T>
|
||||||
|
{
|
||||||
|
return construct(_defaultSerializer, std::forward<KT>(key), std::forward<PTs>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// serializing function SerFuncT - a callable with the signature:
|
||||||
|
// template<typename T, mcc_output_char_range R>
|
||||||
|
// void ser_func(R&& buffer, const T& val, mcc_serialization_params_t const& pars)
|
||||||
|
//
|
||||||
|
template <typename SerFuncT, traits::mcc_input_char_range KT, typename... PTs>
|
||||||
|
std::error_code construct(SerFuncT&& ser_func, KT&& key, PTs&&... params)
|
||||||
|
requires(traits::mcc_output_char_range<BYTEREPR_T> &&
|
||||||
|
!traits::mcc_input_char_range<std::remove_cvref_t<SerFuncT>>)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_pointer_v<std::decay_t<KT>>) {
|
||||||
|
return construct(std::forward<SerFuncT>(ser_func), std::string_view(key), std::forward<PTs>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!std::ranges::size(key)) {
|
||||||
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto r = valid_keys_t::isKeywordValid(key);
|
||||||
|
if (!r) {
|
||||||
|
return std::make_error_code(std::errc::not_supported);
|
||||||
|
}
|
||||||
|
|
||||||
|
_keywordHash = *r;
|
||||||
|
|
||||||
|
_msgBuffer = BYTEREPR_T{};
|
||||||
|
|
||||||
|
std::ranges::copy(std::forward<KT>(key), std::back_inserter(_msgBuffer));
|
||||||
|
// _keyword = {_msgBuffer.begin(), _msgBuffer.end()};
|
||||||
|
size_t key_idx = std::distance(_msgBuffer.begin(), _msgBuffer.end());
|
||||||
|
std::vector<size_t> par_idx;
|
||||||
|
|
||||||
|
_params.clear();
|
||||||
|
|
||||||
|
if constexpr (sizeof...(PTs)) {
|
||||||
|
std::ranges::copy(MCC_COMMPROTO_KEYPARAM_DELIM_SEQ, std::back_inserter(_msgBuffer));
|
||||||
|
|
||||||
|
convertFunc(std::forward<SerFuncT>(ser_func), par_idx, std::forward<PTs>(params)...);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < par_idx.size(); i += 2) {
|
||||||
|
_params.emplace_back(_msgBuffer.begin() + par_idx[i], _msgBuffer.begin() + par_idx[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_keyword = std::string_view{_msgBuffer.begin(), _msgBuffer.begin() + key_idx};
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
constexpr MccNetMessageError fromCharRange(const R& r)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_pointer_v<std::decay_t<R>>) {
|
||||||
|
return fromCharRange(std::string_view(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (std::ranges::size(r) == 0) {
|
||||||
|
return ERROR_EMPTY_MESSAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view key;
|
||||||
|
|
||||||
|
// auto prev_msg_buff = _msgBuffer;
|
||||||
|
|
||||||
|
if constexpr (traits::mcc_output_char_range<BYTEREPR_T>) {
|
||||||
|
_msgBuffer = BYTEREPR_T{};
|
||||||
|
std::ranges::copy(r, std::back_inserter(_msgBuffer));
|
||||||
|
} else {
|
||||||
|
_msgBuffer = {std::begin(r), std::end(r)};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto found = std::ranges::search(_msgBuffer, MCC_COMMPROTO_KEYPARAM_DELIM_SEQ);
|
||||||
|
|
||||||
|
if (found.empty()) { // only keyword
|
||||||
|
key = mcc::utils::trimSpaces(std::string_view{_msgBuffer.begin(), _msgBuffer.end()});
|
||||||
|
} else {
|
||||||
|
key = mcc::utils::trimSpaces(std::string_view{_msgBuffer.begin(), found.begin()});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto kv = valid_keys_t::isKeywordValid(key);
|
||||||
|
if (!kv) {
|
||||||
|
// _msgBuffer = prev_msg_buff; // restore previous netmessage state
|
||||||
|
return ERROR_INVALID_KEYWORD;
|
||||||
|
}
|
||||||
|
|
||||||
|
_keywordHash = *kv;
|
||||||
|
_keyword = key;
|
||||||
|
|
||||||
|
if (!found.empty()) { // params ...
|
||||||
|
_params.clear();
|
||||||
|
auto pr =
|
||||||
|
std::views::split(std::string_view{found.end(), _msgBuffer.end()}, MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ);
|
||||||
|
for (auto const& p : pr) {
|
||||||
|
_params.emplace_back(p.begin(), p.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t _keywordHash{};
|
||||||
|
std::string_view _keyword{};
|
||||||
|
std::vector<std::string_view> _params{};
|
||||||
|
|
||||||
|
BYTEREPR_T _msgBuffer{};
|
||||||
|
|
||||||
|
DefaultSerializer _defaultSerializer{};
|
||||||
|
|
||||||
|
impl::mcc_serialization_params_t _serializationParams{.seq_delim{MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ},
|
||||||
|
.elem_delim{MCC_COMMPROTO_RANGEPARAM_DELIM_SEQ}};
|
||||||
|
|
||||||
|
template <typename SerFuncT, typename T, typename... Ts>
|
||||||
|
void convertFunc(SerFuncT&& ser_func, std::vector<size_t>& idx, const T& par, const Ts&... pars)
|
||||||
|
{
|
||||||
|
if constexpr (std::same_as<T, MccSerializedCoordPairFormat>) {
|
||||||
|
_serializationParams.coordpair_format = par;
|
||||||
|
} else if constexpr (std::same_as<T, MccSerializedAngleFormatPrec>) {
|
||||||
|
_serializationParams.angle_prec = par;
|
||||||
|
} else {
|
||||||
|
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||||
|
|
||||||
|
std::forward<SerFuncT>(ser_func)(_msgBuffer, par, _serializationParams);
|
||||||
|
|
||||||
|
idx.emplace_back(std::distance(_msgBuffer.begin(), _msgBuffer.end()));
|
||||||
|
|
||||||
|
if constexpr (sizeof...(Ts)) {
|
||||||
|
std::ranges::copy(_serializationParams.seq_delim, std::back_inserter(_msgBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (sizeof...(Ts)) {
|
||||||
|
convertFunc(std::forward<SerFuncT>(ser_func), idx, pars...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(MccNetMessage<std::string, MccNetMessageValidKeywords>{"ACK"}.withKey("ACK"));
|
||||||
|
static_assert(MccNetMessage{"ACK"}.withKey("ACK"));
|
||||||
|
|
||||||
|
} // namespace mcc::network
|
||||||
@@ -115,7 +115,7 @@ public:
|
|||||||
{
|
{
|
||||||
auto sptr = std::make_shared<decltype(zone)>(std::move(zone));
|
auto sptr = std::make_shared<decltype(zone)>(std::move(zone));
|
||||||
|
|
||||||
_inZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, bool* res) {
|
_inZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, bool* res) -> error_t {
|
||||||
auto err = sptr->inPZone(pt, res);
|
auto err = sptr->inPZone(pt, res);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_INZONE_FUNC);
|
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_INZONE_FUNC);
|
||||||
@@ -125,7 +125,7 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
_timeToZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) {
|
_timeToZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) -> error_t {
|
||||||
auto err = sptr->timeToPZone(pt, res);
|
auto err = sptr->timeToPZone(pt, res);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC);
|
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMETO_FUNC);
|
||||||
@@ -135,7 +135,7 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
_timeFromZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) {
|
_timeFromZoneFunc.emplace_back([sptr](MccSkyPoint const& pt, duration_t* res) -> error_t {
|
||||||
auto err = sptr->timeFromPZone(pt, res);
|
auto err = sptr->timeFromPZone(pt, res);
|
||||||
if (err) {
|
if (err) {
|
||||||
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC);
|
return mcc_deduced_err(err, MccPZoneContainerErrorCode::ERROR_TIMEFROM_FUNC);
|
||||||
|
|||||||
390
mcc_serialization_common.h
Normal file
390
mcc_serialization_common.h
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* MOUNT CONTROL COMPONENTS LIBRARY *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
|
* COMMON DEFINITIONS FOR DATA SERIALIZATION/DESERIALIZATION *
|
||||||
|
* *
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include "mcc_concepts.h"
|
||||||
|
#include "mcc_error.h"
|
||||||
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
|
namespace mcc
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/* celestial angle serialization */
|
||||||
|
|
||||||
|
enum class MccSerializedAngleFormat {
|
||||||
|
MCC_SERIALIZED_FORMAT_DEGREES, // degrees as floating-point number
|
||||||
|
MCC_SERIALIZED_FORMAT_SXGM_HOURS, // sexagesimal representation: hours:mins:secs
|
||||||
|
MCC_SERIALIZED_FORMAT_SXGM_DEGS, // sexagesimal representation: degs:arcmins:arcsecs
|
||||||
|
MCC_SERIALIZED_FORMAT_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR = "SRANG-FORMAT-DEGREES";
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR = "SRANG-FORMAT-SXGM_HOURDEG";
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR = "SRANG-FORMAT-SXGM_DEGDEG";
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view MccSerializedAngleFormatToStr(MccSerializedAngleFormat fmt)
|
||||||
|
{
|
||||||
|
return fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES ? MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR
|
||||||
|
: fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS
|
||||||
|
? MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR
|
||||||
|
: fmt == MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS ? MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR
|
||||||
|
: MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
static constexpr MccSerializedAngleFormat MccSerializedAngleFormatStrToValue(R&& str)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
return MccSerializedAngleFormatStrToValue(std::string_view{str});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hash = mcc::utils::FNV1aHash(std::forward<R>(str));
|
||||||
|
|
||||||
|
return hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_DEGREES_STR)
|
||||||
|
? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_SXGM_HOURS_STR)
|
||||||
|
? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURS
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_ANG_FORMAT_SXGM_DEGS_STR)
|
||||||
|
? MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGS
|
||||||
|
: MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* coordinates pair serialization */
|
||||||
|
|
||||||
|
enum class MccSerializedCoordPairFormat {
|
||||||
|
MCC_SERIALIZED_FORMAT_DEGREES, // both angles are in degrees as floating-point number
|
||||||
|
MCC_SERIALIZED_FORMAT_SXGM_HOURDEG, // X is in hour (if RA or HA) and Y is in degree sexagesimal representation
|
||||||
|
MCC_SERIALIZED_FORMAT_SXGM_DEGDEG, // both angles are in sexagesimal degrees
|
||||||
|
MCC_SERIALIZED_FORMAT_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_DEGREES_STR = "SRCP-FORMAT-DEGREES";
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR = "SRCP-FORMAT-SXGM_HOURDEG";
|
||||||
|
static constexpr std::string_view MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR = "SRCP-FORMAT-SXGM_DEGDEG";
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view MccSerializedCoordPairFormatToStr(MccSerializedCoordPairFormat fmt)
|
||||||
|
{
|
||||||
|
return fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES ? MCC_SERIALIZED_CP_FORMAT_DEGREES_STR
|
||||||
|
: fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG
|
||||||
|
? MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR
|
||||||
|
: fmt == MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGDEG
|
||||||
|
? MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR
|
||||||
|
: MCC_SERIALIZED_CP_FORMAT_DEGREES_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
static constexpr MccSerializedCoordPairFormat MccSerializedCoordPairFormatStrToValue(R&& str)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
return MccSerializedCoordPairFormatStrToValue(std::string_view{str});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hash = mcc::utils::FNV1aHash(std::forward<R>(str));
|
||||||
|
|
||||||
|
return hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_DEGREES_STR)
|
||||||
|
? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_SXGM_HOURDEG_STR)
|
||||||
|
? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_SERIALIZED_CP_FORMAT_SXGM_DEGDEG_STR)
|
||||||
|
? MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_DEGDEG
|
||||||
|
: MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* precision of representation of serialized celestial angle/coordinates pair */
|
||||||
|
|
||||||
|
struct MccSerializedAngleFormatPrec {
|
||||||
|
uint8_t hour_prec = 2; // number of decimal places in hour seconds (sexagesimal format)
|
||||||
|
uint8_t deg_prec = 1; // number of decimal places in arcseconds (sexagesimal format)
|
||||||
|
// slightly better than 0.1 arcsecond precision
|
||||||
|
uint8_t decimals = 6; // number of decimal places in degrees (floating-point number format)
|
||||||
|
// if 0, then number of decimal places is according to formating rules of 'double' type
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MccTimePointFormat {
|
||||||
|
MCC_TIMEPOINT_FORMAT_DATE, // UTC date
|
||||||
|
MCC_TIMEPOINT_FORMAT_MJD, // MJD
|
||||||
|
MCC_TIMEPOINT_FORMAT_JD, // JD
|
||||||
|
MCC_TIMEPOINT_FORMAT_JEPOCH, // Julian epoch
|
||||||
|
MCC_TIMEPOINT_FORMAT_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr std::string_view MCC_TIMEPOINT_FORMAT_DATE_STR = "TP-FORMAT-DATE";
|
||||||
|
static constexpr std::string_view MCC_TIMEPOINT_FORMAT_MJD_STR = "TP-FORMAT-MJD";
|
||||||
|
static constexpr std::string_view MCC_TIMEPOINT_FORMAT_JD_STR = "TP-FORMAT-JD";
|
||||||
|
static constexpr std::string_view MCC_TIMEPOINT_FORMAT_JEPOCH_STR = "TP-FORMAT-JEPOCH";
|
||||||
|
|
||||||
|
static constexpr std::string_view MccTimePointFormatToStr(MccTimePointFormat fmt)
|
||||||
|
{
|
||||||
|
return fmt == MccTimePointFormat::MCC_TIMEPOINT_FORMAT_DATE ? MCC_TIMEPOINT_FORMAT_DATE_STR
|
||||||
|
: fmt == MccTimePointFormat::MCC_TIMEPOINT_FORMAT_MJD ? MCC_TIMEPOINT_FORMAT_MJD_STR
|
||||||
|
: fmt == MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JD ? MCC_TIMEPOINT_FORMAT_JD_STR
|
||||||
|
: fmt == MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JEPOCH ? MCC_TIMEPOINT_FORMAT_JEPOCH_STR
|
||||||
|
: MCC_TIMEPOINT_FORMAT_MJD_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range R>
|
||||||
|
static constexpr MccTimePointFormat MccTimePointFormatStrToValue(R&& str)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
return MccTimePointFormatStrToValue(std::string_view{str});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hash = mcc::utils::FNV1aHash(std::forward<R>(str));
|
||||||
|
|
||||||
|
return hash == mcc::utils::FNV1aHash(MCC_TIMEPOINT_FORMAT_DATE_STR) ? MccTimePointFormat::MCC_TIMEPOINT_FORMAT_DATE
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_TIMEPOINT_FORMAT_MJD_STR) ? MccTimePointFormat::MCC_TIMEPOINT_FORMAT_MJD
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_TIMEPOINT_FORMAT_JD_STR) ? MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JD
|
||||||
|
: hash == mcc::utils::FNV1aHash(MCC_TIMEPOINT_FORMAT_JEPOCH_STR)
|
||||||
|
? MccTimePointFormat::MCC_TIMEPOINT_FORMAT_JEPOCH
|
||||||
|
: MccTimePointFormat::MCC_TIMEPOINT_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SERIALIZATION/DESERIALIZATION PROCESS TUNING PARAMETERS */
|
||||||
|
|
||||||
|
// delimiter between items of serializing values sequence
|
||||||
|
static constexpr std::string_view MCC_SERIALIZING_DEFAULT_SEQ_DELIMITER{";"};
|
||||||
|
|
||||||
|
// delimiter between items of aggregative (multi-element) serializing value
|
||||||
|
static constexpr std::string_view MCC_SERIALIZING_DEFAULT_ELEM_DELIMITER{","};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_serialization_params_c = std::copyable<T> && requires(T t) {
|
||||||
|
requires traits::mcc_output_char_range<decltype(t.seq_delim)>;
|
||||||
|
requires traits::mcc_output_char_range<decltype(t.elem_delim)>;
|
||||||
|
|
||||||
|
requires std::same_as<decltype(t.angle_format), MccSerializedAngleFormat>;
|
||||||
|
requires std::same_as<decltype(t.angle_prec), MccSerializedAngleFormatPrec>;
|
||||||
|
requires std::same_as<decltype(t.coordpair_format), MccSerializedCoordPairFormat>;
|
||||||
|
requires std::same_as<decltype(t.timepoint_format), MccTimePointFormat>;
|
||||||
|
|
||||||
|
// a format string for mcc_systime_c types (std;:chrono::sys_time)
|
||||||
|
requires std::same_as<decltype(t.systime_format), std::string_view>;
|
||||||
|
|
||||||
|
// if true - normalize angle in sexagesimal format (to control rounding)
|
||||||
|
// (to avoid something like "24:00:00.0" for sexagesimal 'hours:minutes:seconds' format)
|
||||||
|
requires std::convertible_to<decltype(t.norm_sxgm), bool>;
|
||||||
|
|
||||||
|
// if true - interpretate serialized angle in sexagesimal format as 'hours:minutes:seconds'
|
||||||
|
// otherwise as 'degrees:arcmins:arcsecs'
|
||||||
|
requires std::convertible_to<decltype(t.sxgm_hms), bool>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* SERIALIZER/DESERIALIZER CONCEPTS */
|
||||||
|
|
||||||
|
template <mcc_error_c RetT>
|
||||||
|
struct mcc_serializer_interface_t {
|
||||||
|
virtual ~mcc_serializer_interface_t() = default;
|
||||||
|
|
||||||
|
typedef RetT error_t;
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_serializer_interface_t> SelfT, traits::mcc_output_char_range R, typename ValueT>
|
||||||
|
RetT operator()(this SelfT&& self, R& output, ValueT const& value)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(output, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_serializer_interface_t> SelfT, traits::mcc_output_char_range R, typename ValueT>
|
||||||
|
RetT operator()(this SelfT&& self, R& output, ValueT const& value, mcc_serialization_params_c auto const& params)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(output, value, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mcc_serializer_interface_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_serializer_c =
|
||||||
|
std::derived_from<T, mcc_serializer_interface_t<typename T::error_t>> && requires(T t, const T t_const) {
|
||||||
|
// static const variable with name of the serializer
|
||||||
|
requires std::formattable<decltype(T::serializerName), char> && std::is_const_v<decltype(T::serializerName)>;
|
||||||
|
|
||||||
|
// // must define a type "params_t"
|
||||||
|
// requires mcc_serialization_params_c<typename T::params_t>;
|
||||||
|
|
||||||
|
// { t.setParams(std::declval<typename T::params_t const&>()) };
|
||||||
|
|
||||||
|
// { t_const.getParams() } -> std::same_as<typename T::params_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_error_c RetT>
|
||||||
|
struct mcc_deserializer_interface_t {
|
||||||
|
virtual ~mcc_deserializer_interface_t() = default;
|
||||||
|
|
||||||
|
typedef RetT error_t;
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_deserializer_interface_t> SelfT, traits::mcc_input_char_range R, typename ValueT>
|
||||||
|
RetT operator()(this SelfT&& self, R const& input, ValueT& value)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(input, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_deserializer_interface_t> SelfT, traits::mcc_input_char_range R, typename ValueT>
|
||||||
|
RetT operator()(this SelfT&& self, R const& input, ValueT& value, mcc_serialization_params_c auto& params)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(input, value, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mcc_deserializer_interface_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_deserializer_c =
|
||||||
|
std::derived_from<T, mcc_deserializer_interface_t<typename T::error_t>> && requires(T t, const T t_const) {
|
||||||
|
// static const variable with name of the deserializer
|
||||||
|
requires std::formattable<decltype(T::deserializerName), char> &&
|
||||||
|
std::is_const_v<decltype(T::deserializerName)>;
|
||||||
|
|
||||||
|
// // must define a type "params_t"
|
||||||
|
// requires mcc_serialization_params_c<typename T::params_t>;
|
||||||
|
|
||||||
|
// { t.setParams(std::declval<typename T::params_t const&>()) };
|
||||||
|
|
||||||
|
// { t_const.getParams() } -> std::same_as<typename T::params_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* BASE CLASS IMPLEMENTATION FOR SERIALIZER/DESERIALIZER */
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
|
||||||
|
// default definition of serialization/deserialization process parameters structure
|
||||||
|
struct mcc_serialization_params_t {
|
||||||
|
std::string seq_delim{MCC_SERIALIZING_DEFAULT_SEQ_DELIMITER};
|
||||||
|
std::string elem_delim{MCC_SERIALIZING_DEFAULT_ELEM_DELIMITER};
|
||||||
|
|
||||||
|
MccSerializedAngleFormat angle_format{MccSerializedAngleFormat::MCC_SERIALIZED_FORMAT_DEGREES};
|
||||||
|
|
||||||
|
MccSerializedAngleFormatPrec angle_prec{MccSerializedAngleFormatPrec{.hour_prec = 2, .deg_prec = 1, .decimals = 6}};
|
||||||
|
|
||||||
|
MccSerializedCoordPairFormat coordpair_format{MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG};
|
||||||
|
|
||||||
|
MccTimePointFormat timepoint_format{MccTimePointFormat::MCC_TIMEPOINT_FORMAT_DATE};
|
||||||
|
|
||||||
|
std::string_view systime_format{"{:%FT%T}"};
|
||||||
|
|
||||||
|
bool norm_sxgm{false};
|
||||||
|
|
||||||
|
bool sxgm_hms{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static_assert(mcc_serialization_params_c<mcc_serialization_params_t>, "!!!");
|
||||||
|
|
||||||
|
namespace details
|
||||||
|
{
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c ParamsT>
|
||||||
|
struct _params_manipulator_t {
|
||||||
|
virtual ~_params_manipulator_t() = default;
|
||||||
|
|
||||||
|
typedef ParamsT params_t;
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c p_t>
|
||||||
|
void setParams(p_t const& pars)
|
||||||
|
{
|
||||||
|
if constexpr (std::same_as<p_t, params_t>) {
|
||||||
|
_params = pars;
|
||||||
|
} else {
|
||||||
|
_params.seq_delim = pars.seq_delim;
|
||||||
|
_params.elem_delim = pars.elem_delim;
|
||||||
|
_params.coordpair_format = pars.coordpair_format;
|
||||||
|
_params.angle_prec = pars.angle_prec;
|
||||||
|
_params.timepoint_format = pars.timepoint_format;
|
||||||
|
_params.norm_sxgm = pars.norm_sxgm;
|
||||||
|
_params.sxgm_hms = pars.sxgm_hms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <mcc_serialization_params_c p_t>
|
||||||
|
requires(!std::same_as<p_t, params_t>)
|
||||||
|
p_t getParams() const
|
||||||
|
{
|
||||||
|
p_t pars;
|
||||||
|
|
||||||
|
pars.seq_delim = _params.seq_delim;
|
||||||
|
pars.elem_delim = _params.elem_delim;
|
||||||
|
pars.coordpair_format = _params.coordpair_format;
|
||||||
|
pars.angle_prec = _params.angle_prec;
|
||||||
|
pars.timepoint_format = _params.timepoint_format;
|
||||||
|
pars.norm_sxgm = _params.norm_sxgm;
|
||||||
|
pars.sxgm_hms = _params.sxgm_hms;
|
||||||
|
|
||||||
|
return pars;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
params_t getParams() const
|
||||||
|
{
|
||||||
|
return _params;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
_params_manipulator_t() = default;
|
||||||
|
|
||||||
|
params_t _params;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// struct MccDeserializerBase : mcc_deserializer_interface_t<MccError> {
|
||||||
|
// virtual ~MccDeserializerBase() = default;
|
||||||
|
|
||||||
|
// using typename mcc_deserializer_interface_t<MccError>::error_t;
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// MccDeserializerBase() = default;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template <mcc_serialization_params_c ParamsT>
|
||||||
|
// struct MccSerializerBase : mcc_serializer_interface_t<MccError>, details::_params_manipulator_t<ParamsT> {
|
||||||
|
// virtual ~MccSerializerBase() = default;
|
||||||
|
|
||||||
|
// using typename mcc_serializer_interface_t<MccError>::error_t;
|
||||||
|
|
||||||
|
// using typename details::_params_manipulator_t<ParamsT>::params_t;
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// MccSerializerBase() = default;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template <mcc_serialization_params_c ParamsT>
|
||||||
|
// struct MccDeserializerBase : mcc_deserializer_interface_t<MccError>, details::_params_manipulator_t<ParamsT> {
|
||||||
|
// virtual ~MccDeserializerBase() = default;
|
||||||
|
|
||||||
|
// using typename mcc_deserializer_interface_t<MccError>::error_t;
|
||||||
|
|
||||||
|
// using typename details::_params_manipulator_t<ParamsT>::params_t;
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// MccDeserializerBase() = default;
|
||||||
|
// };
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
} // namespace mcc
|
||||||
1333
mcc_serializer.h
1333
mcc_serializer.h
File diff suppressed because it is too large
Load Diff
910
mcc_serializer.h.old
Normal file
910
mcc_serializer.h.old
Normal file
@@ -0,0 +1,910 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
* *
|
||||||
|
* MOUNT CONTROL COMPONENTS LIBRARY *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
|
* IMPLEMENTATION OF SERIALIZER CLASSES *
|
||||||
|
* *
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
#include "mcc_concepts.h"
|
||||||
|
#include "mcc_constants.h"
|
||||||
|
#include "mcc_coordinate.h"
|
||||||
|
#include "mcc_epoch.h"
|
||||||
|
#include "mcc_error.h"
|
||||||
|
#include "mcc_traits.h"
|
||||||
|
#include "mcc_utils.h"
|
||||||
|
|
||||||
|
namespace mcc::impl
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class MccSerializerErrorCode : int {
|
||||||
|
ERROR_OK,
|
||||||
|
ERROR_UNDERLYING_SERIALIZER,
|
||||||
|
ERROR_INVALID_EPOCH,
|
||||||
|
ERROR_COORD_TRANSFORM
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mcc::impl
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class is_error_code_enum<mcc::impl::MccSerializerErrorCode> : public true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
|
||||||
|
namespace mcc::impl
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// error category
|
||||||
|
struct MccSerializerCategory : public std::error_category {
|
||||||
|
MccSerializerCategory() : std::error_category() {}
|
||||||
|
|
||||||
|
const char* name() const noexcept
|
||||||
|
{
|
||||||
|
return "MCC-SERIALIZER-ERR-CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message(int ec) const
|
||||||
|
{
|
||||||
|
MccSerializerErrorCode err = static_cast<MccSerializerErrorCode>(ec);
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case MccSerializerErrorCode::ERROR_OK:
|
||||||
|
return "OK";
|
||||||
|
case MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER:
|
||||||
|
return "error returned by underlying serializer";
|
||||||
|
case MccSerializerErrorCode::ERROR_INVALID_EPOCH:
|
||||||
|
return "invalid coordinate epoch";
|
||||||
|
case MccSerializerErrorCode::ERROR_COORD_TRANSFORM:
|
||||||
|
return "coordinates transformation error";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MccSerializerCategory& get()
|
||||||
|
{
|
||||||
|
static const MccSerializerCategory constInst;
|
||||||
|
return constInst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline std::error_code make_error_code(MccSerializerErrorCode ec)
|
||||||
|
{
|
||||||
|
return std::error_code(static_cast<int>(ec), MccSerializerCategory::get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <mcc_error_c RetT>
|
||||||
|
struct mcc_serializer_interface_t {
|
||||||
|
virtual ~mcc_serializer_interface_t() = default;
|
||||||
|
|
||||||
|
typedef RetT error_t;
|
||||||
|
|
||||||
|
template <std::derived_from<mcc_serializer_interface_t> SelfT,
|
||||||
|
traits::mcc_output_char_range R,
|
||||||
|
typename ValueT,
|
||||||
|
typename FmtT>
|
||||||
|
requires(std::same_as<std::format_string<ValueT>, FmtT> || std::same_as<std::string_view, FmtT>)
|
||||||
|
RetT operator()(this SelfT&& self, R& output, ValueT const& value, FmtT fmt)
|
||||||
|
{
|
||||||
|
return std::forward<SelfT>(self)(output, value, std::move(fmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mcc_serializer_interface_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept mcc_serializer_c = std::derived_from<T, mcc_serializer_interface_t<typename T::error_t>>;
|
||||||
|
|
||||||
|
|
||||||
|
namespace details
|
||||||
|
{
|
||||||
|
|
||||||
|
struct MccSerializerBase : mcc_serializer_interface_t<impl::MccError>, utils::mcc_elem_sequence_with_delim_t {
|
||||||
|
using typename mcc_serializer_interface_t<impl::MccError>::error_t;
|
||||||
|
|
||||||
|
virtual ~MccSerializerBase() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MccSerializerBase() = default;
|
||||||
|
|
||||||
|
template <typename VT, typename R>
|
||||||
|
requires(std::ranges::input_range<R> && std::same_as<VT, std::ranges::range_value_t<R>>)
|
||||||
|
error_t serializingRange(mcc_serializer_c auto& sr,
|
||||||
|
R const& r,
|
||||||
|
traits::mcc_output_char_range auto& output,
|
||||||
|
auto fmt) const
|
||||||
|
{
|
||||||
|
size_t i = 0, N = std::ranges::size(r);
|
||||||
|
|
||||||
|
for (auto const& el : r) {
|
||||||
|
auto err = sr(output, el, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
if (++i < N) {
|
||||||
|
std::format_to(std::back_inserter(output), "{}", _seqDelimiter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace details
|
||||||
|
|
||||||
|
|
||||||
|
/* fallback template */
|
||||||
|
template <typename VT>
|
||||||
|
class MccSerializer : public details::MccSerializerBase
|
||||||
|
// class MccSerializer : public mcc_serializer_interface_t<impl::MccError>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// default delimiter
|
||||||
|
static constexpr std::string_view defaultRangeDelimiter{","};
|
||||||
|
|
||||||
|
// typedef impl::MccError error_t;
|
||||||
|
|
||||||
|
MccSerializer() = default;
|
||||||
|
|
||||||
|
~MccSerializer() = default;
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::formattable<VT, char>) {
|
||||||
|
if constexpr (std::is_null_pointer_v<FmtT>) {
|
||||||
|
std::format_to(std::back_inserter(output), "{}", value);
|
||||||
|
} else if constexpr (traits::mcc_input_char_range<FmtT>) {
|
||||||
|
std::string_view sfmt{fmt.begin(), fmt.end()};
|
||||||
|
std::vformat_to(std::back_inserter(output), sfmt, std::make_format_args(value));
|
||||||
|
} else if constexpr (std::same_as<std::format_string<VT>, FmtT>) {
|
||||||
|
std::format_to(std::back_inserter(output), std::move(fmt), value);
|
||||||
|
} else {
|
||||||
|
static_assert(false, "INVALID FORMAT STRING TYPE!!!");
|
||||||
|
}
|
||||||
|
} else if constexpr (std::convertible_to<VT, std::string>) {
|
||||||
|
auto err = MccSerializer<std::string>{}(output, static_cast<std::string>(value), std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if constexpr (std::ranges::range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
|
||||||
|
// special range (character sequence)
|
||||||
|
if constexpr (std::same_as<value_t, char>) {
|
||||||
|
std::string str;
|
||||||
|
std::ranges::copy(value, std::back_inserter(str));
|
||||||
|
|
||||||
|
auto err = MccSerializer<std::string>{}(output, str, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static_assert(false, "UNSUPPORTED TYPE!!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* SPECIALIZATION FOR THE SOME CONCEPTS */
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(traits::mcc_systime_c<VT> ||
|
||||||
|
(std::ranges::input_range<VT> && traits::mcc_systime_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccSerializer<VT> : public details::MccSerializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::input_range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
} else { // scalar
|
||||||
|
if constexpr (std::is_null_pointer_v<FmtT>) {
|
||||||
|
std::format_to(std::back_inserter(output), "{:%FT%T}", value);
|
||||||
|
} else if constexpr (traits::mcc_input_char_range<FmtT>) {
|
||||||
|
std::string_view sfmt{fmt.begin(), fmt.end()};
|
||||||
|
if (sfmt == "{}") {
|
||||||
|
sfmt = "{:%FT%T}";
|
||||||
|
}
|
||||||
|
std::vformat_to(std::back_inserter(output), sfmt, std::make_format_args(value));
|
||||||
|
} else if constexpr (std::same_as<std::format_string<VT>, FmtT>) {
|
||||||
|
std::string_view sfmt{fmt.get().begin(), fmt.get().end()};
|
||||||
|
if (sfmt == "{}") {
|
||||||
|
std::format_to(std::back_inserter(output), "{:%FT%T}", value);
|
||||||
|
} else {
|
||||||
|
std::format_to(std::back_inserter(output), std::move(fmt), value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
static_assert(false, "INVALID FORMAT STRING TYPE!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(!std::is_arithmetic_v<VT> &&
|
||||||
|
(mcc_angle_c<VT> ||
|
||||||
|
(std::ranges::input_range<VT> && mcc_angle_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>)))
|
||||||
|
class MccSerializer<VT> : public virtual details::MccSerializerBase
|
||||||
|
// class MccSerializer<VT> : public mcc_serializer_interface_t<impl::MccError>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum SerializedCoordFormat {
|
||||||
|
CFMT_DEGREES, // floating-point representation in degrees
|
||||||
|
CFMT_SGM_HOURS, // sexagesimal representation: HH:MM:SS.SSSSSS (hours:minutes:seconds)
|
||||||
|
CFMT_SGM_DEGS // sexagesimal representation: DD:MM:SS.SSSSS (degrees:arcmins::arcsecs)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SexagesimalCoordPrec {
|
||||||
|
uint8_t hour_prec = 2; // number of decimal places in hour seconds
|
||||||
|
uint8_t deg_prec = 1; // number of decimal places in arcseconds
|
||||||
|
};
|
||||||
|
|
||||||
|
// typedef impl::MccError error_t;
|
||||||
|
|
||||||
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
void setCoordFormat(SerializedCoordFormat format)
|
||||||
|
{
|
||||||
|
_coordFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedCoordFormat getCoordFormat() const
|
||||||
|
{
|
||||||
|
return _coordFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setCoordPrec(SexagesimalCoordPrec prec)
|
||||||
|
{
|
||||||
|
_coordPrec = std::move(prec);
|
||||||
|
}
|
||||||
|
|
||||||
|
SexagesimalCoordPrec getCoordPrec() const
|
||||||
|
{
|
||||||
|
return _coordPrec;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::input_range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
sr.setCoordFormat(_coordFormat);
|
||||||
|
sr.setCoordPrec(_coordPrec);
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
} else { // scalar
|
||||||
|
double v = (double)value; // radians
|
||||||
|
std::string sgm;
|
||||||
|
|
||||||
|
switch (_coordFormat) {
|
||||||
|
case MccSerializer::CFMT_DEGREES:
|
||||||
|
v *= 180.0 / std::numbers::pi;
|
||||||
|
return MccSerializer<double>{}(output, v, std::move(fmt));
|
||||||
|
case MccSerializer::CFMT_SGM_HOURS:
|
||||||
|
sgm = utils::rad2sxg(v, true, _coordPrec.load().hour_prec);
|
||||||
|
break;
|
||||||
|
case MccSerializer::CFMT_SGM_DEGS:
|
||||||
|
sgm = utils::rad2sxg(v, false, _coordPrec.load().deg_prec);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto err = MccSerializer<std::string>{}(output, sgm, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// std::atomic<SerializedCoordFormat> _coordFormat{MccSerializer::CFMT_DEGREES};
|
||||||
|
std::atomic<SerializedCoordFormat> _coordFormat{MccSerializer::CFMT_SGM_DEGS};
|
||||||
|
std::atomic<SexagesimalCoordPrec> _coordPrec{SexagesimalCoordPrec{.hour_prec = 2, .deg_prec = 1}};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_coord_epoch_c<VT> ||
|
||||||
|
(std::ranges::input_range<VT> && mcc_coord_epoch_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccSerializer<VT> : public virtual details::MccSerializerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum TimePointFormat { TP_FORMAT_DATE, TP_FORMAT_MJD, TP_FORMAT_JEPOCH };
|
||||||
|
|
||||||
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
void setTimePointFormat(TimePointFormat format)
|
||||||
|
{
|
||||||
|
_tpFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimePointFormat getTimePointFormat() const
|
||||||
|
{
|
||||||
|
return _tpFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::input_range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
sr.setTimePointFormat(_tpFormat);
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
} else {
|
||||||
|
switch (_tpFormat) {
|
||||||
|
case TP_FORMAT_DATE: {
|
||||||
|
auto utc = value.UTC();
|
||||||
|
auto err = MccSerializer<std::remove_cvref_t<decltype(utc)>>{}(output, utc, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case TP_FORMAT_MJD: {
|
||||||
|
double mjd = value.MJD();
|
||||||
|
auto err = MccSerializer<double>{}(output, mjd, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case TP_FORMAT_JEPOCH: {
|
||||||
|
auto jepoch = value.JEpoch();
|
||||||
|
auto err = MccSerializer<std::remove_cvref_t<decltype(jepoch)>>{}(output, jepoch, std::move(fmt));
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::atomic<TimePointFormat> _tpFormat{TP_FORMAT_DATE};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_coord_pair_c<VT> ||
|
||||||
|
(std::ranges::input_range<VT> && mcc_coord_pair_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccSerializer<VT> : public std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccCelestialCoordEpoch>>,
|
||||||
|
MccSerializer<MccCelestialCoordEpoch>>,
|
||||||
|
public std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccAngle>>,
|
||||||
|
MccSerializer<MccAngle>>
|
||||||
|
// class MccSerializer<VT> : public mcc_serializer_interface_t<MccError>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccCelestialCoordEpoch>>,
|
||||||
|
MccSerializer<MccCelestialCoordEpoch>>
|
||||||
|
base_ser_epoch_t;
|
||||||
|
|
||||||
|
typedef std::
|
||||||
|
conditional_t<std::ranges::input_range<VT>, MccSerializer<std::vector<MccAngle>>, MccSerializer<MccAngle>>
|
||||||
|
base_ser_angle_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using typename details::MccSerializerBase::error_t;
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::input_range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
|
||||||
|
sr.setTimePointFormat(this->_tpFormat);
|
||||||
|
sr.setCoordFormat(this->_coordFormat);
|
||||||
|
sr.setCoordPrec(this->_coordPrec);
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
} else { // scalar: format X[elem-delimiter]Y[elem-delimiter]epoch[elem-delimiter]pair-kind
|
||||||
|
|
||||||
|
// WARNING: still ignore format string!!!
|
||||||
|
|
||||||
|
error_t err;
|
||||||
|
|
||||||
|
// format to sexagesimal form according to celestial coordinate type (general XY-type is skipped)
|
||||||
|
if (this->_coordFormat != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
auto prev_format = this->_coordFormat.load();
|
||||||
|
|
||||||
|
if constexpr (VT::pairKind == MccCoordPairKind::COORDS_KIND_AZZD ||
|
||||||
|
VT::pairKind == MccCoordPairKind::COORDS_KIND_AZALT) { // azimuth is in degrees
|
||||||
|
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
err = base_ser_angle_t::operator()(output, MccAngle{(double)value.x()});
|
||||||
|
} else { // RA or HA are in hours
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
err = base_ser_angle_t::operator()(output, MccAngle{(double)value.x()});
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setCoordFormat(prev_format); // restore previous value
|
||||||
|
} else { // here all angles in deciamal degrees
|
||||||
|
err = base_ser_angle_t::operator()(output, MccAngle{(double)value.x()});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
// format to sexagesimal form according to celestial coordinate type (general XY-type is skipped)
|
||||||
|
// Y-coordinate of the celestial point is always in degrees
|
||||||
|
if (this->_coordFormat != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
auto prev_format = this->_coordFormat.load();
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
|
||||||
|
err = base_ser_angle_t::operator()(output, MccAngle{(double)value.y()});
|
||||||
|
|
||||||
|
this->setCoordFormat(prev_format); // restore previous value
|
||||||
|
} else { // here all angles in deciamal degrees
|
||||||
|
err = base_ser_angle_t::operator()(output, MccAngle{(double)value.y()});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
auto ep = value.epoch();
|
||||||
|
if constexpr (std::convertible_to<decltype(ep), MccCelestialCoordEpoch>) {
|
||||||
|
auto err_e = base_ser_epoch_t::operator()(output, MccCelestialCoordEpoch{ep});
|
||||||
|
if (err_e) {
|
||||||
|
return err_e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MccCelestialCoordEpoch ep1;
|
||||||
|
bool ok = ep1.fromMJD(ep.MJD());
|
||||||
|
if (!ok) {
|
||||||
|
return MccSerializerErrorCode::ERROR_INVALID_EPOCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_e = (*this)(output, ep1);
|
||||||
|
if (err_e) {
|
||||||
|
return err_e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
auto err_s = MccSerializer<std::string_view>{}(output, MccCoordPairKindToStr(VT::pairKind));
|
||||||
|
if (err_s) {
|
||||||
|
return mcc_deduced_err(err_s, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
requires(mcc_skypoint_c<VT> ||
|
||||||
|
(std::ranges::input_range<VT> && mcc_skypoint_c<std::remove_cv_t<std::ranges::range_value_t<VT>>>))
|
||||||
|
class MccSerializer<VT> : public std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccCelestialCoordEpoch>>,
|
||||||
|
MccSerializer<MccCelestialCoordEpoch>>,
|
||||||
|
public std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccAngle>>,
|
||||||
|
MccSerializer<MccAngle>>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
typedef std::conditional_t<std::ranges::input_range<VT>,
|
||||||
|
MccSerializer<std::vector<MccCelestialCoordEpoch>>,
|
||||||
|
MccSerializer<MccCelestialCoordEpoch>>
|
||||||
|
base_ser_epoch_t;
|
||||||
|
|
||||||
|
typedef std::
|
||||||
|
conditional_t<std::ranges::input_range<VT>, MccSerializer<std::vector<MccAngle>>, MccSerializer<MccAngle>>
|
||||||
|
base_ser_angle_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using typename details::MccSerializerBase::error_t;
|
||||||
|
|
||||||
|
enum SkyPointFormat {
|
||||||
|
SKYPOINT_FORMAT_FULL, // return RA_ICRS, DEC_ICRS, RA_APP, DEC_APP, RA_OBS, DEC_OBS, AZ, ZD, HA_APP,
|
||||||
|
// TIME-POINT
|
||||||
|
SKYPOINT_FORMAT_OBS, // return observed coordinates: RA_OBS, DEC_OBS, AZ, ZD, HA_OBS, TIME-POINT
|
||||||
|
SKYPOINT_FORMAT_APP, // return apparent (in vacuo) coordinates: RA_APP, DEC_APP, HA_APP, TIME-POINT
|
||||||
|
SKYPOINT_FORMAT_PAIR // return current stored coordinate pair: X, Y, TIME-POINT, PAIR-KIND
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~MccSerializer() = default;
|
||||||
|
|
||||||
|
void setSkyPointFormat(SkyPointFormat format)
|
||||||
|
{
|
||||||
|
_skptFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkyPointFormat getSkyPointFormat() const
|
||||||
|
{
|
||||||
|
return _skptFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FmtT = std::nullptr_t>
|
||||||
|
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, FmtT fmt = nullptr)
|
||||||
|
{
|
||||||
|
if constexpr (std::ranges::input_range<VT>) {
|
||||||
|
using value_t = std::remove_cv_t<std::ranges::range_value_t<VT>>;
|
||||||
|
MccSerializer<value_t> sr;
|
||||||
|
|
||||||
|
sr.setTimePointFormat(this->_tpFormat);
|
||||||
|
sr.setCoordFormat(this->_coordFormat);
|
||||||
|
sr.setCoordPrec(this->_coordPrec);
|
||||||
|
|
||||||
|
return serializingRange<value_t>(sr, value, output, std::move(fmt));
|
||||||
|
} else { // scalar
|
||||||
|
|
||||||
|
auto serialize_pair_func = [&output, this]<typename PT>(PT const& pt) -> error_t {
|
||||||
|
MccSerializer<PT> pt_sr;
|
||||||
|
|
||||||
|
pt_sr.setTimePointFormat(this->_tpFormat);
|
||||||
|
pt_sr.setCoordFormat(this->_coordFormat);
|
||||||
|
pt_sr.setCoordPrec(this->_coordPrec);
|
||||||
|
|
||||||
|
auto err = pt_sr(output, pt);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
// WARNING: still ignore format string!!!
|
||||||
|
|
||||||
|
auto skpt_fmt = _skptFormat.load();
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_PAIR) {
|
||||||
|
switch (value.pairKind()) {
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_ICRS:
|
||||||
|
return serialize_pair_func(value.operator MccSkyRADEC_ICRS());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_APP:
|
||||||
|
return serialize_pair_func(value.operator MccSkyRADEC_APP());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_RADEC_OBS:
|
||||||
|
return serialize_pair_func(value.operator MccSkyRADEC_OBS());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_APP:
|
||||||
|
return serialize_pair_func(value.operator MccSkyHADEC_APP());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_HADEC_OBS:
|
||||||
|
return serialize_pair_func(value.operator MccSkyHADEC_OBS());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZZD:
|
||||||
|
return serialize_pair_func(value.operator MccSkyAZZD());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_AZALT:
|
||||||
|
return serialize_pair_func(value.operator MccSkyAZALT());
|
||||||
|
case MccCoordPairKind::COORDS_KIND_XY:
|
||||||
|
return serialize_pair_func(value.operator MccGenXY());
|
||||||
|
default:
|
||||||
|
return serialize_pair_func(value.operator MccGenXY()); // ???????!!!!!!!!!!!
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MccSkyRADEC_ICRS radec_icrs;
|
||||||
|
MccSkyRADEC_OBS radec_obs;
|
||||||
|
MccSkyHADEC_OBS hadec_obs;
|
||||||
|
MccSkyRADEC_APP radec_app;
|
||||||
|
MccSkyHADEC_APP hadec_app;
|
||||||
|
MccSkyAZZD azzd;
|
||||||
|
// MccGenXY xy;
|
||||||
|
|
||||||
|
if (value.pairKind() == MccCoordPairKind::COORDS_KIND_RADEC_ICRS) {
|
||||||
|
auto ep_now = MccCelestialCoordEpoch::now();
|
||||||
|
radec_obs.setEpoch(ep_now);
|
||||||
|
radec_app.setEpoch(ep_now);
|
||||||
|
hadec_obs.setEpoch(ep_now);
|
||||||
|
hadec_app.setEpoch(ep_now);
|
||||||
|
azzd.setEpoch(ep_now);
|
||||||
|
} else {
|
||||||
|
auto ep = value.epoch();
|
||||||
|
radec_obs.setEpoch(ep);
|
||||||
|
radec_app.setEpoch(ep);
|
||||||
|
hadec_obs.setEpoch(ep);
|
||||||
|
hadec_app.setEpoch(ep);
|
||||||
|
azzd.setEpoch(ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prev_format = this->_coordFormat.load();
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_FULL) { // RA_ICRS, DEC_ICRS, RA_APP, DEC_APP
|
||||||
|
auto err = value.to(radec_icrs, radec_app);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RA_ICRS is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_icrs.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
|
||||||
|
// DEC_ICRS is in sexagesimal degrees
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_icrs.y()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
// RA_APP is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_app.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
|
||||||
|
// DEC_APP is in sexagesimal degrees
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_app.y()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_OBS || skpt_fmt == SKYPOINT_FORMAT_FULL) { // RA_OBS, DEC_OBS, AZ, ZD
|
||||||
|
auto err = value.to(radec_obs, azzd);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RA_OBS is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_obs.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
|
||||||
|
// DEC_OBS, AZ and ZD are in sexagesimal degrees
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_obs.y()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)azzd.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)azzd.y()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_FULL) { // HA_APP
|
||||||
|
auto err = value.to(hadec_app);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HA_APP is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)hadec_app.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_OBS) { // HA_OBS
|
||||||
|
auto err = value.to(hadec_obs);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HA_OBS is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)hadec_obs.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (skpt_fmt == SKYPOINT_FORMAT_APP) { // RA_APP, DEC_APP, HA_APP
|
||||||
|
auto err = value.to(radec_app, hadec_app);
|
||||||
|
if (err) {
|
||||||
|
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RA_APP is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_app.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
|
||||||
|
// DEC_APP is in sexagesimal degrees
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_DEGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)radec_app.y()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
|
||||||
|
// HA_APP is in sexagesimal hours
|
||||||
|
if (prev_format != base_ser_angle_t::CFMT_DEGREES) {
|
||||||
|
this->setCoordFormat(base_ser_angle_t::CFMT_SGM_HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_ang = base_ser_angle_t::operator()(output, MccAngle{(double)hadec_app.x()});
|
||||||
|
if (err_ang) {
|
||||||
|
return mcc_deduced_err(err_ang, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::format_to(std::back_inserter(output), "{}", this->_elementDelimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setCoordFormat(prev_format); // restore previous value
|
||||||
|
|
||||||
|
|
||||||
|
// epoch of app/obs coordinates
|
||||||
|
auto ep = value.epoch();
|
||||||
|
if constexpr (std::convertible_to<decltype(ep), MccCelestialCoordEpoch>) {
|
||||||
|
auto err_e = base_ser_epoch_t::operator()(output, MccCelestialCoordEpoch{ep});
|
||||||
|
if (err_e) {
|
||||||
|
return err_e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MccCelestialCoordEpoch ep1;
|
||||||
|
bool ok = ep1.fromMJD(ep.MJD());
|
||||||
|
if (!ok) {
|
||||||
|
return MccSerializerErrorCode::ERROR_INVALID_EPOCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto err_e = (*this)(output, ep1);
|
||||||
|
if (err_e) {
|
||||||
|
return err_e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MccSerializerErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::atomic<SkyPointFormat> _skptFormat{SKYPOINT_FORMAT_FULL};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static_assert(mcc_serializer_c<MccSerializer<float>>, "!!!");
|
||||||
|
|
||||||
|
static_assert(mcc_serializer_c<MccSerializer<impl::MccAngle>>, "!!!");
|
||||||
|
|
||||||
|
static_assert(std::atomic<MccSerializer<impl::MccAngle>::SerializedCoordFormat>::is_always_lock_free, "!!!");
|
||||||
|
static_assert(std::atomic<MccSerializer<impl::MccAngle>::SexagesimalCoordPrec>::is_always_lock_free, "!!!");
|
||||||
|
|
||||||
|
static_assert(std::formattable<impl::MccAngle, char>, "!!!");
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
MccSerializer<impl::MccAngle> s;
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
s(str, impl::MccAngleALT{1.1});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mcc::impl
|
||||||
@@ -286,6 +286,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
error_t getTarget(mcc_skypoint_c auto* sp)
|
||||||
|
{
|
||||||
|
sp = _enteredTargetPos;
|
||||||
|
|
||||||
|
return MccTelemetryErrorCode::ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// blocks the current thread until telemetry data is received.
|
// blocks the current thread until telemetry data is received.
|
||||||
// the maximum blocking time is equal to the set timeout (see setTelemetryDataTimeout method)
|
// the maximum blocking time is equal to the set timeout (see setTelemetryDataTimeout method)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// #include <mcc_ccte_erfa.h>
|
// #include <mcc_ccte_erfa.h>
|
||||||
#include <mcc_coordinate.h>
|
// #include <mcc_coordinate.h>
|
||||||
|
#include <mcc_deserializer.h>
|
||||||
#include <mcc_serializer.h>
|
#include <mcc_serializer.h>
|
||||||
|
|
||||||
using namespace mcc::impl;
|
using namespace mcc::impl;
|
||||||
@@ -25,15 +26,31 @@ void serialize(VT const& value)
|
|||||||
{
|
{
|
||||||
MccSerializer<VT> ser;
|
MccSerializer<VT> ser;
|
||||||
std::string s;
|
std::string s;
|
||||||
|
mcc_serialization_params_t pars{};
|
||||||
|
pars.norm_sxgm = true;
|
||||||
|
pars.coordpair_format = mcc::MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG;
|
||||||
|
|
||||||
auto err = ser(s, value);
|
auto err = ser(s, value, pars);
|
||||||
if (err) {
|
if (err) {
|
||||||
std::cout << "SERIALIZing ERR: " << err << "\n";
|
std::cout << "SERIALIZING ERR: " << err.message() << "\n";
|
||||||
} else {
|
} else {
|
||||||
std::cout << "SERIALIZED: " << s << "\n";
|
std::cout << "SERIALIZED: " << s << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
void deserialize(mcc::traits::mcc_input_char_range auto const& s, VT& value)
|
||||||
|
{
|
||||||
|
MccDeserializer<VT> deser;
|
||||||
|
|
||||||
|
auto err = deser(s, value);
|
||||||
|
if (err) {
|
||||||
|
std::cout << "DESERIALIZING ERR: " << err << "\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "DESERIALIZION IS OK\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
skypt_t::cctEngine.setStateERFA(saoras);
|
skypt_t::cctEngine.setStateERFA(saoras);
|
||||||
@@ -122,6 +139,9 @@ int main()
|
|||||||
std::cout << "\tfor 'double' type: ";
|
std::cout << "\tfor 'double' type: ";
|
||||||
serialize(v);
|
serialize(v);
|
||||||
|
|
||||||
|
std::cout << "\tfor 'coord pair' type: ";
|
||||||
|
serialize(icrs);
|
||||||
|
|
||||||
std::cout << "\tfor 'coord pair' type: ";
|
std::cout << "\tfor 'coord pair' type: ";
|
||||||
serialize(radec_obs);
|
serialize(radec_obs);
|
||||||
|
|
||||||
@@ -141,5 +161,22 @@ int main()
|
|||||||
std::cout << "\tfor 'sky point' type: ";
|
std::cout << "\tfor 'sky point' type: ";
|
||||||
serialize(pt);
|
serialize(pt);
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "\n\nDESERIALIZATION TEST:\n";
|
||||||
|
v = 0.0;
|
||||||
|
|
||||||
|
std::string s = "123.7687";
|
||||||
|
|
||||||
|
deserialize(s, v);
|
||||||
|
std::cout << "\tfor 'double' type: v = " << v << "\n";
|
||||||
|
|
||||||
|
s = " 11:22:33.453, -32.19820931,65632.87987987,RADEC-OBS ";
|
||||||
|
deserialize(s, pt);
|
||||||
|
pt.toAtSameEpoch(radec_obs);
|
||||||
|
std::cout << "\tfor 'sky point' type: x = " << radec_obs.x().sexagesimal(true)
|
||||||
|
<< ", y = " << radec_obs.y().degrees() << ", epoch = " << pt.epoch().MJD()
|
||||||
|
<< ", kind = " << MccCoordPairKindToStr(pt.pairKind()) << "\n";
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
77
tests/mcc_netmsg_test.cpp
Normal file
77
tests/mcc_netmsg_test.cpp
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#include <list>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
#include <mcc_netserver_proto.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using msg1_t = mcc::network::MccNetMessage<std::string_view>;
|
||||||
|
using msg2_t = mcc::network::MccNetMessage<std::string>;
|
||||||
|
|
||||||
|
mcc::network::MccNetMessage msg3("ACK");
|
||||||
|
|
||||||
|
std::string_view sv{"TARGET 11:22:33.212; -0.23876984; RADEC "};
|
||||||
|
std::vector<char> arr{sv.begin(), sv.end()};
|
||||||
|
|
||||||
|
msg1_t msg1;
|
||||||
|
|
||||||
|
msg1.fromCharRange(arr);
|
||||||
|
|
||||||
|
std::println("msg.key = <{}>", msg1.keyword());
|
||||||
|
std::println("msg.par[1] = <{}>", msg1.param(1));
|
||||||
|
|
||||||
|
std::vector<double> vd{1.1, 2.2, 3.3};
|
||||||
|
msg2_t msg2("ACK", 12.43298042, "EEE", std::chrono::seconds(10), vd);
|
||||||
|
// msg2_t msg2("ACK");
|
||||||
|
|
||||||
|
std::println("msg.bytes = <{}>", msg2.byteRepr());
|
||||||
|
std::println("msg.key = <{}>", msg2.keyword());
|
||||||
|
std::println("msg.par[1] = <{}>", msg2.param(1));
|
||||||
|
std::println("msg.par[2] = <{}>", msg2.param(2));
|
||||||
|
|
||||||
|
|
||||||
|
auto p2 = msg2.paramValue<std::chrono::seconds>(2);
|
||||||
|
std::println("msg.parvalue[2] = <{}>", p2.value_or(std::chrono::seconds{}));
|
||||||
|
|
||||||
|
|
||||||
|
std::print("msg.parvalue[3] = <");
|
||||||
|
auto p3 = msg2.paramValue<decltype(vd)>(3);
|
||||||
|
if (p3.has_value()) {
|
||||||
|
for (auto const& el : p3.value()) {
|
||||||
|
std::print("{} ", el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::println(">");
|
||||||
|
|
||||||
|
|
||||||
|
std::println("msg.par[1-2] joined = <{}>", msg2.params(1, 2));
|
||||||
|
|
||||||
|
auto vv = msg2.params<std::list<std::string_view>>(1, 3);
|
||||||
|
std::print("msg.par[1-3] array = <");
|
||||||
|
for (auto const& el : vv) {
|
||||||
|
std::print("{} ", el);
|
||||||
|
}
|
||||||
|
std::println(">");
|
||||||
|
|
||||||
|
|
||||||
|
std::println("\n\n");
|
||||||
|
|
||||||
|
mcc::impl::MccSkyPoint spt(mcc::impl::MccSkyRADEC_APP{"10:00:00.0"_hms, 12.098687_degs});
|
||||||
|
|
||||||
|
msg2.construct("ACK", "MOUNT", mcc::MccSerializedAngleFormatPrec{3, 2}, spt);
|
||||||
|
std::println("msg2.bytes = <{}>", msg2.byteRepr());
|
||||||
|
|
||||||
|
auto spt_d = msg2.paramValue<mcc::impl::MccSkyPoint>(1);
|
||||||
|
|
||||||
|
if (spt_d) {
|
||||||
|
std::println("msg2.parvalue(1).pairKind() = {}", MccCoordPairKindToStr(spt_d->pairKind()));
|
||||||
|
std::println("msg2.parvalue(1).epoch() = {}", spt_d->epoch().MJD() + mcc::MCC_MJD_ZERO);
|
||||||
|
} else {
|
||||||
|
std::println("cannot deserialize MccSkyPoint value!");
|
||||||
|
}
|
||||||
|
|
||||||
|
msg2.construct("ACK", "MOUNT", mcc::MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_DEGREES, spt);
|
||||||
|
std::println("msg2.bytes = <{}>", msg2.byteRepr());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include <mcc_pcm.h>
|
#include <mcc_pcm.h>
|
||||||
|
#include <mcc_serializer.h>
|
||||||
#include <mcc_telemetry.h>
|
#include <mcc_telemetry.h>
|
||||||
|
|
||||||
|
|
||||||
static std::random_device rd;
|
static std::random_device rd;
|
||||||
static std::mt19937 gen(rd());
|
static std::mt19937 gen(rd());
|
||||||
static std::uniform_int_distribution<long> tm_distrib(100, 700);
|
static std::uniform_int_distribution<long> tm_distrib(100, 700);
|
||||||
@@ -61,6 +61,32 @@ struct hw_t {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct std::formatter<hw_t::hardware_movement_state_t, char> : std::formatter<std::string_view> {
|
||||||
|
auto format(hw_t::hardware_movement_state_t e, auto& ctx) const
|
||||||
|
{
|
||||||
|
return formatter<std::string_view>::format(e == hw_t::hardware_movement_state_t::HW_MOVE_ERROR ? "ERROR"
|
||||||
|
: e == hw_t::hardware_movement_state_t::HW_MOVE_STOPPED ? "STOPPED"
|
||||||
|
: e == hw_t::hardware_movement_state_t::HW_MOVE_STOPPING ? "STOPPING"
|
||||||
|
: e == hw_t::hardware_movement_state_t::HW_MOVE_SLEWING ? "SLEWING"
|
||||||
|
: e == hw_t::hardware_movement_state_t::HW_MOVE_TRACKING ? "TRACKING"
|
||||||
|
: "UNKNOWN",
|
||||||
|
ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// template <>
|
||||||
|
// struct std::formatter<hw_t::hardware_movement_state_t, char>
|
||||||
|
// : std::formatter<std::underlying_type_t<hw_t::hardware_movement_state_t>, char> {
|
||||||
|
// auto format(hw_t::hardware_movement_state_t e, auto& ctx) const
|
||||||
|
// {
|
||||||
|
// return formatter<std::underlying_type_t<hw_t::hardware_movement_state_t>>::format(
|
||||||
|
// std::underlying_type_t<hw_t::hardware_movement_state_t>(e), ctx);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static_assert(mcc::mcc_hardware_c<hw_t>, "!!!!!");
|
static_assert(mcc::mcc_hardware_c<hw_t>, "!!!!!");
|
||||||
|
|
||||||
@@ -86,5 +112,18 @@ int main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mcc::impl::MccSerializer<typename t_t::telemetry_data_t> ser;
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
auto err = ser(str, tdata);
|
||||||
|
if (err) {
|
||||||
|
std::cout << "ERR: " << err.message() << "\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "\n\n";
|
||||||
|
std::cout << str << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user